Refactoring.
[laditools.git] / ladi-player
blobfcbd34b11dd4a564ffdb7fab1d56c303ec510219
1 #!/usr/bin/python
2 # LADITools - Linux Audio Desktop Integration Tools
3 # laditray - System tray integration for LADI
4 # Copyright (C) 2012 Alessio Treglia <quadrispro@ubuntu.com>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import os
20 import sys
21 import time
22 import signal
23 import gettext
24 import argparse
26 from laditools import _gettext_domain
27 gettext.install(_gettext_domain)
29 from laditools import get_version_string
30 from laditools import LadiConfiguration
31 from laditools import LadiApp
33 from gi.repository import Gtk
34 from gi.repository import GObject
35 from laditools import LadiManager
36 from laditools.gtk import LadiManagerGtk
37 from laditools.gtk import find_data_file
39 timeout_add = GObject.timeout_add
41 class LadiPlayer(LadiManagerGtk, LadiApp):
43 _appname = 'ladi-player'
44 _appname_long = _("LADI Player")
45 _appid = 'org.linuxaudio.ladi.player'
47 # Default configuration
48 _default_config = {
49 'autostart' : False,
52 def on_about(self, *args):
53 LadiManagerGtk.on_about(self, parent=self.window_main, version=get_version_string())
55 def quit(self, *args, **kwargs):
56 self.global_config.set_config_section (self.appname,
57 self.config_dict)
58 self.global_config.save()
59 Gtk.main_quit()
61 def _run_select_studio_dialog(self, title, *args):
62 studio_list = self.get_ladish_controller().studio_list()
63 if not studio_list:
64 dlg = Gtk.MessageDialog(None,Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
65 Gtk.MessageType.INFO,
66 Gtk.ButtonsType.CLOSE,
67 _('No studio is available.'))
68 dlg.set_transient_for(self.window_main)
69 dlg.set_title(title)
70 dlg.run()
71 dlg.destroy()
72 return None
74 dlg = Gtk.Dialog()
75 treeview = Gtk.TreeView()
76 model = Gtk.ListStore(GObject.TYPE_STRING)
77 renderer = Gtk.CellRendererText()
78 column = Gtk.TreeViewColumn('Available studios', renderer, text=0)
80 treeview.set_model(model)
81 treeview.append_column(column)
82 treeview.set_cursor(Gtk.TreePath(path=0),
83 focus_column=column,
84 start_editing=False)
86 for studio in studio_list:
87 model.append((studio,))
89 dlg.set_transient_for(self.window_main)
90 dlg.set_modal(True)
91 dlg.set_destroy_with_parent(True)
92 dlg.set_title(title)
93 dlg.get_content_area().pack_start(child=treeview,
94 expand=True,
95 fill=True,
96 padding=10)
97 dlg.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK)
98 dlg.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
99 dlg.show_all()
101 response = dlg.run()
102 ret = None
103 if response == Gtk.ResponseType.OK:
104 path, column = treeview.get_cursor()
105 ret = model[path][0]
106 dlg.hide()
107 return ret
109 def _toolbuttons_set_active(self, group, **kwargs):
110 buttons = getattr(self, "%s_status_buttons" % group)
111 if 'all' in kwargs:
112 status = kwargs['all']
113 for button in buttons:
114 buttons[button].set_sensitive(status)
115 else:
116 for button in kwargs:
117 buttons[button].set_sensitive(kwargs[button])
119 def jack_is_started(self, *args, **kwargs):
120 while True:
121 try:
122 return LadiManagerGtk.jack_is_started(self, *args, **kwargs)
123 except:
124 time.sleep(0.5)
125 continue
127 def ladish_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('ladish', **kwargs)
128 def jack_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('jack', **kwargs)
129 def a2j_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('a2j', **kwargs)
131 def ladish_status_buttons_update(self):
132 buttons = self.ladish_status_buttons
134 # Setup ladish controls
135 if self.ladish_is_available():
136 # Buttons "rename" and "unload"
137 if self.studio_is_loaded():
138 self.ladish_toolbuttons_set_active(unload=True, rename=True)
139 # Buttons "start" and "stop"
140 if self.studio_is_started():
141 self.ladish_toolbuttons_set_active(start=False, stop=True, save=True)
142 else:
143 self.ladish_toolbuttons_set_active(start=True, stop=False, save=False)
144 else:
145 self.ladish_toolbuttons_set_active(start=True,
146 stop=False,
147 save=False,
148 unload=False,
149 rename=False)
150 else:
151 self.ladish_toolbuttons_set_active(all=False)
153 def jack_status_buttons_update(self):
154 if not self.jack_is_available():
155 return
157 buttons = self.jack_status_buttons
158 ladish_available = self.ladish_is_available()
159 jack_started = self.jack_is_started()
161 if jack_started:
162 self.jack_toolbuttons_set_active(jack_start=False,
163 jack_stop=(not ladish_available),
164 jack_reset_xruns=True,
165 jack_reactivate=True)
166 else:
167 self.jack_toolbuttons_set_active(jack_start=True,
168 jack_stop=False,
169 jack_reset_xruns=False,
170 jack_reactivate=True)
173 def a2j_status_buttons_update(self):
174 if not self.a2j_is_available():
175 self.a2j_toolbuttons_set_active(all=False)
176 return
178 buttons = self.a2j_status_buttons
179 ladish_available = self.ladish_is_available()
180 a2j_started = self.a2j_is_started()
182 if not ladish_available:
183 if a2j_started:
184 self.a2j_toolbuttons_set_active(a2j_start=False,
185 a2j_stop=True,
186 a2j_reactivate=True)
187 else:
188 self.a2j_toolbuttons_set_active(a2j_start=True,
189 a2j_stop=False,
190 a2j_reactivate=True)
191 else:
192 self.a2j_toolbuttons_set_active(a2j_start=False,
193 a2j_stop=False,
194 a2j_reactivate=True)
196 def update_status_buttons(self):
198 # Update widgets
199 self.ladish_status_buttons_update()
200 self.jack_status_buttons_update()
201 self.a2j_status_buttons_update()
203 # Update status label and window icon
204 if self.jack_is_started():
205 self.window_main.set_icon_name("ladi-started")
206 if self.jack_is_realtime():
207 status_text = "RT | "
208 else:
209 status_text = ""
210 # Get DSP Load
211 status_text += str (round (float (self.jack_get_load()),1)) + "% | "
212 # Get Xruns
213 status_text += str (self.jack_get_xruns())
214 # Set a started status
215 self.status_label.set_label (status_text)
216 else:
217 self.window_main.set_icon_name("ladi-stopped")
218 self.status_label.set_label(_('<i>Stopped</i>'))
220 def update(self, *args, **kwargs):
221 self.update_status_buttons()
222 LadiManagerGtk.update(self, *args, **kwargs)
223 return True
225 def _set_starting_status(self):
226 self.window_main.set_icon_name("ladi-starting")
228 def action_ladish_new(self, action, *args):
229 self.studio_new()
231 def action_ladish_start(self, action, *args):
232 if self.studio_is_loaded():
233 if not self.studio_is_started():
234 self._set_starting_status()
235 self.studio_start()
236 self.update_status_buttons()
237 else:
238 self._set_starting_status()
239 self.jack_start()
240 self.update_status_buttons()
242 def action_ladish_save(self, action, *args):
243 self.studio_save()
245 def action_ladish_stop(self, action, *args):
246 if self.jack_is_started() and self.studio_is_started():
247 self.studio_stop()
248 self.update_status_buttons()
250 def action_ladish_rename(self, action, *args):
251 self.studio_rename()
252 self.update_status_buttons()
254 def action_ladish_load(self, action, *args):
255 selection = self._run_select_studio_dialog(_('Load studio'))
256 if selection:
257 self.studio_load(studio=selection)
258 return selection
260 def action_ladish_delete(self, action, *args):
261 selection = self._run_select_studio_dialog(_('Delete studio'))
262 if selection:
263 LadiManager.studio_delete(self, studio=selection)
264 return selection
266 def action_ladish_unload(self, action, *args):
267 while True:
268 try:
269 if self.studio_is_loaded():
270 self.studio_unload()
271 self.update_status_buttons()
272 break
273 except:
274 time.sleep(0.5)
275 continue
277 def action_ladish_reactivate(self, action, *args):
278 self.ladish_reactivate()
280 def action_jack_start(self, action, *args):
281 self._set_starting_status()
282 self.jack_start()
283 def action_jack_stop(self, action, *args):
284 self.jack_stop()
285 def action_jack_reset_xruns(self, action, *args):
286 self.jack_reset_xruns()
287 def action_jack_reactivate(self, action, *args):
288 self.jack_reactivate()
290 def action_a2j_start(self, action, *args):
291 self.a2j_start()
292 def action_a2j_stop(self, action, *args):
293 self.a2j_stop()
294 def action_a2j_reactivate(self, action, *args):
295 self.a2j_reactivate()
297 def action_launcher_launch(self, action, *args):
298 self.launcher_exec(command=self._launcher_which(action.get_name()))
300 def __init__(self):
301 # Initialize app
302 LadiApp.__init__(self)
303 # Handle the configuration
304 self.global_config = LadiConfiguration(self.appname, self._default_config)
305 self.config_dict = self.global_config.get_config_section (self.appname)
306 autostart = bool(eval(self.config_dict['autostart']))
308 LadiManagerGtk.__init__(self, autostart)
310 # Handle signals
311 signal.signal(signal.SIGTERM, self.quit)
312 signal.signal(signal.SIGINT, self.quit)
314 # Build the UI
315 builder = Gtk.Builder()
316 ui_path = find_data_file("ladi-player.ui")
317 builder.add_from_file(ui_path)
318 sys.stderr.write( _("Loading interface from %s\n") % ui_path)
319 sys.stderr.flush()
321 # Retrieve objects
322 self.window_main = builder.get_object("window_main")
323 actiongroup_ladish = builder.get_object("actiongroup_ladish")
324 actiongroup_jack = builder.get_object("actiongroup_jack")
325 actiongroup_a2j = builder.get_object("actiongroup_a2j")
326 actiongroup_launcher = builder.get_object("actiongroup_launcher")
327 self.status_label = builder.get_object('toolbutton_label_status')
329 # Setup status buttons
330 self.ladish_status_buttons = ladish_status_buttons = {}
331 self.jack_status_buttons = jack_status_buttons = {}
332 self.a2j_status_buttons = a2j_status_buttons = {}
333 self.launcher_status_buttons = launcher_status_buttons = {}
335 for action in actiongroup_ladish.list_actions():
336 ladish_status_buttons[action.get_name()] = action
337 for action in actiongroup_jack.list_actions():
338 jack_status_buttons[action.get_name()] = action
339 for action in actiongroup_a2j.list_actions():
340 a2j_status_buttons[action.get_name()] = action
341 for action in actiongroup_launcher.list_actions():
342 launcher_status_buttons[action.get_name()] = action
344 # Remove launchers for unavailable commands
345 for command in launcher_status_buttons:
346 if not self._launcher_which(command):
347 launcher_status_buttons[command].set_active(False)
349 # Accelerators
350 # accelgroup = builder.get_object("accelgroup1")
351 # action = actiongroup_launcher.get_action("gladish")
352 # action.set_accel_group(accelgroup)
353 # action.set_accel_path("menu_studio")
355 # Get the initial status
356 self.update ()
357 # Add the auto update callback
358 self.auto_updater = timeout_add (250, self.update, None)
360 builder.connect_signals(self)
362 def run(self):
363 self.window_main.show_all()
365 if __name__ == "__main__":
366 parser = argparse.ArgumentParser(description=_('graphical front-end that allows users to start, stop and'
367 'monitor JACK, as well as start some JACK related applications'),
368 epilog=_('This program is part of the LADITools suite.'))
369 parser.add_argument('--version', action='version', version="%(prog)s " + get_version_string())
370 parser.parse_args()
372 GObject.threads_init()
373 Gtk.init(None)
375 LadiPlayer().run()
376 Gtk.main()
378 sys.exit(0)