Add keyboard shortcuts.
[laditools.git] / ladi-player
blob268a0b38243828be73626b59edbba9771c15dfe2
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 sig_handler = signal.getsignal(signal.SIGTERM)
27 signal.signal(signal.SIGINT, sig_handler)
29 from laditools import _gettext_domain
30 gettext.install(_gettext_domain)
32 from laditools import get_version_string
33 from laditools import LadiConfiguration
35 from gi.repository import Gtk
36 from gi.repository import GdkPixbuf
37 from gi.repository import GObject
38 from laditools import LadiManager
39 from laditools.gtk import LadiManagerGtk
40 from laditools.gtk import find_data_file
42 timeout_add = GObject.timeout_add
44 class LadiPlayer(LadiManagerGtk):
46 # Default configuration
47 _default_config = {
48 'autostart' : False,
51 def on_about(self, *args):
52 LadiManagerGtk.on_about(self, parent=self.window_main, version=get_version_string())
54 def on_quit(self, *args, **kwargs):
55 Gtk.main_quit()
57 def _run_select_studio_dialog(self, title, *args):
58 studio_list = self.get_ladish_controller().studio_list()
59 if not studio_list:
60 dlg = Gtk.MessageDialog(None,Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
61 Gtk.MessageType.INFO,
62 Gtk.ButtonsType.CLOSE,
63 _('No studio is available.'))
64 dlg.set_transient_for(self.window_main)
65 dlg.set_title(title)
66 dlg.run()
67 dlg.destroy()
68 return None
70 dlg = Gtk.Dialog()
71 treeview = Gtk.TreeView()
72 model = Gtk.ListStore(GObject.TYPE_STRING)
73 renderer = Gtk.CellRendererText()
74 column = Gtk.TreeViewColumn('Available studios', renderer, text=0)
76 treeview.set_model(model)
77 treeview.append_column(column)
78 treeview.set_cursor(Gtk.TreePath(path=0),
79 focus_column=column,
80 start_editing=False)
82 for studio in studio_list:
83 model.append((studio,))
85 dlg.set_transient_for(self.window_main)
86 dlg.set_modal(True)
87 dlg.set_destroy_with_parent(True)
88 dlg.set_title(title)
89 dlg.get_content_area().pack_start(child=treeview,
90 expand=True,
91 fill=True,
92 padding=10)
93 dlg.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK)
94 dlg.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
95 dlg.show_all()
97 response = dlg.run()
98 ret = None
99 if response == Gtk.ResponseType.OK:
100 path, column = treeview.get_cursor()
101 ret = model[path][0]
102 dlg.hide()
103 return ret
105 def _toolbuttons_set_active(self, group, **kwargs):
106 buttons = getattr(self, "%s_status_buttons" % group)
107 if 'all' in kwargs:
108 status = kwargs['all']
109 for button in buttons:
110 buttons[button].set_sensitive(status)
111 else:
112 for button in kwargs:
113 buttons[button].set_sensitive(kwargs[button])
115 def jack_is_started(self, *args, **kwargs):
116 while True:
117 try:
118 return LadiManagerGtk.jack_is_started(self, *args, **kwargs)
119 except:
120 time.sleep(0.5)
121 continue
123 def ladish_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('ladish', **kwargs)
124 def jack_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('jack', **kwargs)
125 def a2j_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('a2j', **kwargs)
127 def ladish_status_buttons_update(self):
128 buttons = self.ladish_status_buttons
130 # Setup ladish controls
131 if self.ladish_is_available():
132 # Buttons "rename" and "unload"
133 if self.studio_is_loaded():
134 self.ladish_toolbuttons_set_active(unload=True, rename=True)
135 # Buttons "start" and "stop"
136 if self.studio_is_started():
137 self.ladish_toolbuttons_set_active(start=False, stop=True, save=True)
138 else:
139 self.ladish_toolbuttons_set_active(start=True, stop=False, save=False)
140 else:
141 self.ladish_toolbuttons_set_active(start=True,
142 stop=False,
143 save=False,
144 unload=False,
145 rename=False)
146 else:
147 self.ladish_toolbuttons_set_active(all=False)
149 def jack_status_buttons_update(self):
150 if not self.jack_is_available():
151 return
153 buttons = self.jack_status_buttons
154 ladish_available = self.ladish_is_available()
155 jack_started = self.jack_is_started()
157 if jack_started:
158 self.jack_toolbuttons_set_active(jack_start=False,
159 jack_stop=(not ladish_available),
160 jack_reset_xruns=True,
161 jack_reactivate=True)
162 else:
163 self.jack_toolbuttons_set_active(jack_start=True,
164 jack_stop=False,
165 jack_reset_xruns=False,
166 jack_reactivate=True)
169 def a2j_status_buttons_update(self):
170 if not self.a2j_is_available():
171 self.a2j_toolbuttons_set_active(all=False)
172 return
174 buttons = self.a2j_status_buttons
175 ladish_available = self.ladish_is_available()
176 a2j_started = self.a2j_is_started()
178 if not ladish_available:
179 if a2j_started:
180 self.a2j_toolbuttons_set_active(a2j_start=False,
181 a2j_stop=True,
182 a2j_reactivate=True)
183 else:
184 self.a2j_toolbuttons_set_active(a2j_start=True,
185 a2j_stop=False,
186 a2j_reactivate=True)
187 else:
188 self.a2j_toolbuttons_set_active(a2j_start=False,
189 a2j_stop=False,
190 a2j_reactivate=True)
192 def update_status_buttons(self):
194 # Update widgets
195 self.ladish_status_buttons_update()
196 self.jack_status_buttons_update()
197 self.a2j_status_buttons_update()
199 # Update status label and window icon
200 if self.jack_is_started():
201 self.window_main.set_icon_from_file(find_data_file("started.svg"))
202 if self.jack_is_realtime():
203 status_text = "RT | "
204 else:
205 status_text = ""
206 # Get DSP Load
207 status_text += str (round (float (self.jack_get_load()),1)) + "% | "
208 # Get Xruns
209 status_text += str (self.jack_get_xruns())
210 # Set a started status
211 self.status_label.set_label (status_text)
212 else:
213 self.window_main.set_icon_from_file(find_data_file("stopped.svg"))
214 self.status_label.set_label(_('<i>Stopped</i>'))
216 def update(self, *args, **kwargs):
217 self.update_status_buttons()
218 LadiManagerGtk.update(self, *args, **kwargs)
219 return True
221 def _set_starting_status(self):
222 self.window_main.set_icon_from_file(find_data_file("starting.svg"))
224 def action_ladish_new(self, action, *args):
225 self.studio_new()
227 def action_ladish_start(self, action, *args):
228 if self.studio_is_loaded():
229 if not self.studio_is_started():
230 self._set_starting_status()
231 self.studio_start()
232 self.update_status_buttons()
233 else:
234 self._set_starting_status()
235 self.jack_start()
236 self.update_status_buttons()
238 def action_ladish_save(self, action, *args):
239 self.studio_save()
241 def action_ladish_stop(self, action, *args):
242 if self.jack_is_started() and self.studio_is_started():
243 self.studio_stop()
244 self.update_status_buttons()
246 def action_ladish_rename(self, action, *args):
247 self.studio_rename()
248 self.update_status_buttons()
250 def action_ladish_load(self, action, *args):
251 selection = self._run_select_studio_dialog(_('Load studio'))
252 if selection:
253 self.studio_load(studio=selection)
254 return selection
256 def action_ladish_delete(self, action, *args):
257 selection = self._run_select_studio_dialog(_('Delete studio'))
258 if selection:
259 LadiManager.studio_delete(self, studio=selection)
260 return selection
262 def action_ladish_unload(self, action, *args):
263 while True:
264 try:
265 if self.studio_is_loaded():
266 self.studio_unload()
267 self.update_status_buttons()
268 break
269 except:
270 time.sleep(0.5)
271 continue
273 def action_ladish_reactivate(self, action, *args):
274 self.ladish_reactivate()
276 def action_jack_start(self, action, *args):
277 self._set_starting_status()
278 self.jack_start()
279 def action_jack_stop(self, action, *args):
280 self.jack_stop()
281 def action_jack_reset_xruns(self, action, *args):
282 self.jack_reset_xruns()
283 def action_jack_reactivate(self, action, *args):
284 self.jack_reactivate()
286 def action_a2j_start(self, action, *args):
287 self.a2j_start()
288 def action_a2j_stop(self, action, *args):
289 self.a2j_stop()
290 def action_a2j_reactivate(self, action, *args):
291 self.a2j_reactivate()
293 def action_launcher_launch(self, action, *args):
294 self.launcher_exec(command=self._launcher_which(action.get_name()))
296 def __init__(self):
297 # Handle the configuration
298 self.global_config = LadiConfiguration(laditray = self._default_config)
299 self.ladiplayer_param_dict = self.global_config.get_config_section ('ladiplayer')
300 #autostart = bool(eval(self.ladiplayer_param_dict['autostart']))
302 #LadiManagerGtk.__init__(self, self.global_config.get_config_section ('ladiplayer'), False)
303 LadiManagerGtk.__init__(self, False)
305 # Build the UI
306 builder = Gtk.Builder()
307 ui_path = find_data_file("ladi-player.ui")
308 builder.add_from_file(ui_path)
309 sys.stderr.write( _("Loading interface from %s\n") % ui_path)
310 sys.stderr.flush()
312 # Retrieve objects
313 self.window_main = builder.get_object("window_main")
314 actiongroup_ladish = builder.get_object("actiongroup_ladish")
315 actiongroup_jack = builder.get_object("actiongroup_jack")
316 actiongroup_a2j = builder.get_object("actiongroup_a2j")
317 actiongroup_launcher = builder.get_object("actiongroup_launcher")
318 self.status_label = builder.get_object('toolbutton_label_status')
320 # Setup status buttons
321 self.ladish_status_buttons = ladish_status_buttons = {}
322 self.jack_status_buttons = jack_status_buttons = {}
323 self.a2j_status_buttons = a2j_status_buttons = {}
324 self.launcher_status_buttons = launcher_status_buttons = {}
326 for action in actiongroup_ladish.list_actions():
327 ladish_status_buttons[action.get_name()] = action
328 for action in actiongroup_jack.list_actions():
329 jack_status_buttons[action.get_name()] = action
330 for action in actiongroup_a2j.list_actions():
331 a2j_status_buttons[action.get_name()] = action
332 for action in actiongroup_launcher.list_actions():
333 launcher_status_buttons[action.get_name()] = action
335 # Remove launchers for unavailable commands
336 for command in launcher_status_buttons:
337 if not self._launcher_which(command):
338 launcher_status_buttons[command].set_active(False)
340 # Accelerators
341 # accelgroup = builder.get_object("accelgroup1")
342 # action = actiongroup_launcher.get_action("gladish")
343 # action.set_accel_group(accelgroup)
344 # action.set_accel_path("menu_studio")
346 # Get the initial status
347 self.update ()
348 # Add the auto update callback
349 self.auto_updater = timeout_add (250, self.update, None)
351 builder.connect_signals(self)
353 def run(self):
354 self.window_main.show_all()
356 if __name__ == "__main__":
357 parser = argparse.ArgumentParser(description=_('graphical front-end that allows users to start, stop and'
358 'monitor JACK, as well as start some JACK related applications'),
359 epilog=_('This program is part of the LADITools suite.'))
360 parser.add_argument('--version', action='version', version="%(prog)s " + get_version_string())
362 parser.parse_args()
363 GObject.threads_init()
365 LadiPlayer().run()
366 Gtk.main()
367 sys.exit(0)