376 lines
14 KiB
Python
Executable File
376 lines
14 KiB
Python
Executable File
#!/usr/bin/python
|
|
# LADITools - Linux Audio Desktop Integration Tools
|
|
# laditray - System tray integration for LADI
|
|
# Copyright (C) 2012 Alessio Treglia <quadrispro@ubuntu.com>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
import gettext
|
|
import argparse
|
|
|
|
from laditools import _gettext_domain
|
|
gettext.install(_gettext_domain)
|
|
|
|
from laditools import get_version_string
|
|
from laditools import LadiConfiguration
|
|
from laditools import LadiApp
|
|
|
|
from gi.repository import Gtk
|
|
from gi.repository import GObject
|
|
from laditools import LadiManager
|
|
from laditools.gtk import LadiManagerGtk
|
|
from laditools.gtk import find_data_file
|
|
|
|
timeout_add = GObject.timeout_add
|
|
|
|
class LadiPlayer(LadiManagerGtk, LadiApp):
|
|
|
|
_appname = 'ladi-player'
|
|
_appname_long = _("LADI Player")
|
|
_appid = 'org.linuxaudio.ladi.player'
|
|
|
|
# Default configuration
|
|
_default_config = {
|
|
'autostart' : False,
|
|
}
|
|
|
|
def on_about(self, *args):
|
|
LadiManagerGtk.on_about(self, parent=self.window_main, version=get_version_string())
|
|
|
|
def quit(self, *args, **kwargs):
|
|
self.global_config.set_config_section (self.appname,
|
|
self.config_dict)
|
|
self.global_config.save()
|
|
Gtk.main_quit()
|
|
|
|
def _run_select_studio_dialog(self, title, *args):
|
|
studio_list = self.get_ladish_controller().studio_list()
|
|
if not studio_list:
|
|
dlg = Gtk.MessageDialog(None,Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
|
|
Gtk.MessageType.INFO,
|
|
Gtk.ButtonsType.CLOSE,
|
|
_('No studio is available.'))
|
|
dlg.set_transient_for(self.window_main)
|
|
dlg.set_title(title)
|
|
dlg.run()
|
|
dlg.destroy()
|
|
return None
|
|
|
|
dlg = Gtk.Dialog()
|
|
treeview = Gtk.TreeView()
|
|
model = Gtk.ListStore(GObject.TYPE_STRING)
|
|
renderer = Gtk.CellRendererText()
|
|
column = Gtk.TreeViewColumn('Available studios', renderer, text=0)
|
|
|
|
treeview.set_model(model)
|
|
treeview.append_column(column)
|
|
treeview.set_cursor(Gtk.TreePath(path=0),
|
|
focus_column=column,
|
|
start_editing=False)
|
|
|
|
for studio in studio_list:
|
|
model.append((studio,))
|
|
|
|
dlg.set_transient_for(self.window_main)
|
|
dlg.set_modal(True)
|
|
dlg.set_destroy_with_parent(True)
|
|
dlg.set_title(title)
|
|
dlg.get_content_area().pack_start(child=treeview,
|
|
expand=True,
|
|
fill=True,
|
|
padding=10)
|
|
dlg.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK)
|
|
dlg.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)
|
|
dlg.show_all()
|
|
|
|
response = dlg.run()
|
|
ret = None
|
|
if response == Gtk.ResponseType.OK:
|
|
path, column = treeview.get_cursor()
|
|
ret = model[path][0]
|
|
dlg.hide()
|
|
return ret
|
|
|
|
def _toolbuttons_set_active(self, group, **kwargs):
|
|
buttons = getattr(self, "%s_status_buttons" % group)
|
|
if 'all' in kwargs:
|
|
status = kwargs['all']
|
|
for button in buttons:
|
|
buttons[button].set_sensitive(status)
|
|
else:
|
|
for button in kwargs:
|
|
buttons[button].set_sensitive(kwargs[button])
|
|
|
|
def jack_is_started(self, *args, **kwargs):
|
|
while True:
|
|
try:
|
|
return LadiManagerGtk.jack_is_started(self, *args, **kwargs)
|
|
except:
|
|
time.sleep(0.5)
|
|
continue
|
|
|
|
def ladish_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('ladish', **kwargs)
|
|
def jack_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('jack', **kwargs)
|
|
def a2j_toolbuttons_set_active(self, **kwargs): self._toolbuttons_set_active('a2j', **kwargs)
|
|
|
|
def ladish_status_buttons_update(self):
|
|
buttons = self.ladish_status_buttons
|
|
|
|
# Setup ladish controls
|
|
if self.ladish_is_available():
|
|
# Buttons "rename" and "unload"
|
|
if self.studio_is_loaded():
|
|
self.ladish_toolbuttons_set_active(unload=True, rename=True)
|
|
# Buttons "start" and "stop"
|
|
if self.studio_is_started():
|
|
self.ladish_toolbuttons_set_active(start=False, stop=True, save=True)
|
|
else:
|
|
self.ladish_toolbuttons_set_active(start=True, stop=False, save=False)
|
|
else:
|
|
self.ladish_toolbuttons_set_active(start=True,
|
|
stop=False,
|
|
save=False,
|
|
unload=False,
|
|
rename=False)
|
|
else:
|
|
self.ladish_toolbuttons_set_active(all=False)
|
|
|
|
def jack_status_buttons_update(self):
|
|
if not self.jack_is_available():
|
|
return
|
|
|
|
buttons = self.jack_status_buttons
|
|
ladish_available = self.ladish_is_available()
|
|
jack_started = self.jack_is_started()
|
|
|
|
if jack_started:
|
|
self.jack_toolbuttons_set_active(jack_start=False,
|
|
jack_stop=(not ladish_available),
|
|
jack_reset_xruns=True,
|
|
jack_reactivate=True)
|
|
else:
|
|
self.jack_toolbuttons_set_active(jack_start=True,
|
|
jack_stop=False,
|
|
jack_reset_xruns=False,
|
|
jack_reactivate=True)
|
|
|
|
|
|
def a2j_status_buttons_update(self):
|
|
if not self.a2j_is_available():
|
|
self.a2j_toolbuttons_set_active(all=False)
|
|
return
|
|
|
|
buttons = self.a2j_status_buttons
|
|
ladish_available = self.ladish_is_available()
|
|
a2j_started = self.a2j_is_started()
|
|
|
|
if not ladish_available:
|
|
if a2j_started:
|
|
self.a2j_toolbuttons_set_active(a2j_start=False,
|
|
a2j_stop=True,
|
|
a2j_reactivate=True)
|
|
else:
|
|
self.a2j_toolbuttons_set_active(a2j_start=True,
|
|
a2j_stop=False,
|
|
a2j_reactivate=True)
|
|
else:
|
|
self.a2j_toolbuttons_set_active(a2j_start=False,
|
|
a2j_stop=False,
|
|
a2j_reactivate=True)
|
|
|
|
def update_status_buttons(self):
|
|
|
|
# Update widgets
|
|
self.ladish_status_buttons_update()
|
|
self.jack_status_buttons_update()
|
|
self.a2j_status_buttons_update()
|
|
|
|
# Update status label and window icon
|
|
if self.jack_is_started():
|
|
self.window_main.set_icon_name("ladi-started")
|
|
if self.jack_is_realtime():
|
|
status_text = "RT | "
|
|
else:
|
|
status_text = ""
|
|
# Get DSP Load
|
|
status_text += str (round (float (self.jack_get_load()),1)) + "% | "
|
|
# Get Xruns
|
|
status_text += str (self.jack_get_xruns())
|
|
# Set a started status
|
|
self.status_label.set_label (status_text)
|
|
else:
|
|
self.window_main.set_icon_name("ladi-stopped")
|
|
self.status_label.set_label(_('<i>Stopped</i>'))
|
|
|
|
def update(self, *args, **kwargs):
|
|
self.update_status_buttons()
|
|
LadiManagerGtk.update(self, *args, **kwargs)
|
|
return True
|
|
|
|
def _set_starting_status(self):
|
|
self.window_main.set_icon_name("ladi-starting")
|
|
|
|
def action_ladish_new(self, action, *args):
|
|
self.studio_new()
|
|
|
|
def action_ladish_start(self, action, *args):
|
|
if self.studio_is_loaded():
|
|
if not self.studio_is_started():
|
|
self._set_starting_status()
|
|
self.studio_start()
|
|
self.update_status_buttons()
|
|
else:
|
|
self._set_starting_status()
|
|
self.jack_start()
|
|
self.update_status_buttons()
|
|
|
|
def action_ladish_save(self, action, *args):
|
|
self.studio_save()
|
|
|
|
def action_ladish_stop(self, action, *args):
|
|
if self.jack_is_started() and self.studio_is_started():
|
|
self.studio_stop()
|
|
self.update_status_buttons()
|
|
|
|
def action_ladish_rename(self, action, *args):
|
|
self.studio_rename()
|
|
self.update_status_buttons()
|
|
|
|
def action_ladish_load(self, action, *args):
|
|
selection = self._run_select_studio_dialog(_('Load studio'))
|
|
if selection:
|
|
self.studio_load(studio=selection)
|
|
return selection
|
|
|
|
def action_ladish_delete(self, action, *args):
|
|
selection = self._run_select_studio_dialog(_('Delete studio'))
|
|
if selection:
|
|
LadiManager.studio_delete(self, studio=selection)
|
|
return selection
|
|
|
|
def action_ladish_unload(self, action, *args):
|
|
while True:
|
|
try:
|
|
if self.studio_is_loaded():
|
|
self.studio_unload()
|
|
self.update_status_buttons()
|
|
break
|
|
except:
|
|
time.sleep(0.5)
|
|
continue
|
|
|
|
def action_ladish_reactivate(self, action, *args):
|
|
self.ladish_reactivate()
|
|
|
|
def action_jack_start(self, action, *args):
|
|
self._set_starting_status()
|
|
self.jack_start()
|
|
def action_jack_stop(self, action, *args):
|
|
self.jack_stop()
|
|
def action_jack_reset_xruns(self, action, *args):
|
|
self.jack_reset_xruns()
|
|
def action_jack_reactivate(self, action, *args):
|
|
self.jack_reactivate()
|
|
|
|
def action_a2j_start(self, action, *args):
|
|
self.a2j_start()
|
|
def action_a2j_stop(self, action, *args):
|
|
self.a2j_stop()
|
|
def action_a2j_reactivate(self, action, *args):
|
|
self.a2j_reactivate()
|
|
|
|
def action_launcher_launch(self, action, *args):
|
|
self.launcher_exec(command=self._launcher_which(action.get_name()))
|
|
|
|
def __init__(self):
|
|
# Initialize app
|
|
LadiApp.__init__(self)
|
|
# Handle the configuration
|
|
self.global_config = LadiConfiguration(self.appname, self._default_config)
|
|
self.config_dict = self.global_config.get_config_section (self.appname)
|
|
autostart = bool(eval(self.config_dict['autostart']))
|
|
|
|
LadiManagerGtk.__init__(self, autostart)
|
|
|
|
# Handle signals
|
|
self.connect_signals_quit()
|
|
|
|
# Build the UI
|
|
builder = Gtk.Builder()
|
|
ui_path = find_data_file("ladi-player.ui")
|
|
builder.add_from_file(ui_path)
|
|
sys.stderr.write( _("Loading interface from %s\n") % ui_path)
|
|
sys.stderr.flush()
|
|
|
|
# Retrieve objects
|
|
self.window_main = builder.get_object("window_main")
|
|
actiongroup_ladish = builder.get_object("actiongroup_ladish")
|
|
actiongroup_jack = builder.get_object("actiongroup_jack")
|
|
actiongroup_a2j = builder.get_object("actiongroup_a2j")
|
|
actiongroup_launcher = builder.get_object("actiongroup_launcher")
|
|
self.status_label = builder.get_object('toolbutton_label_status')
|
|
|
|
# Setup status buttons
|
|
self.ladish_status_buttons = ladish_status_buttons = {}
|
|
self.jack_status_buttons = jack_status_buttons = {}
|
|
self.a2j_status_buttons = a2j_status_buttons = {}
|
|
self.launcher_status_buttons = launcher_status_buttons = {}
|
|
|
|
for action in actiongroup_ladish.list_actions():
|
|
ladish_status_buttons[action.get_name()] = action
|
|
for action in actiongroup_jack.list_actions():
|
|
jack_status_buttons[action.get_name()] = action
|
|
for action in actiongroup_a2j.list_actions():
|
|
a2j_status_buttons[action.get_name()] = action
|
|
for action in actiongroup_launcher.list_actions():
|
|
launcher_status_buttons[action.get_name()] = action
|
|
|
|
# Remove launchers for unavailable commands
|
|
for command in launcher_status_buttons:
|
|
if not self._launcher_which(command):
|
|
launcher_status_buttons[command].set_active(False)
|
|
|
|
# Accelerators
|
|
# accelgroup = builder.get_object("accelgroup1")
|
|
# action = actiongroup_launcher.get_action("gladish")
|
|
# action.set_accel_group(accelgroup)
|
|
# action.set_accel_path("menu_studio")
|
|
|
|
# Get the initial status
|
|
self.update ()
|
|
# Add the auto update callback
|
|
self.auto_updater = timeout_add (250, self.update, None)
|
|
|
|
builder.connect_signals(self)
|
|
|
|
def run(self):
|
|
self.window_main.show_all()
|
|
Gtk.main()
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description=_('graphical front-end that allows users to start, stop and '
|
|
'monitor JACK, as well as start some JACK related applications.'),
|
|
epilog=_('This program is part of the LADITools suite.'))
|
|
parser.add_argument('--version', action='version', version="%(prog)s " + get_version_string())
|
|
parser.parse_args()
|
|
|
|
Gtk.init(None)
|
|
|
|
LadiPlayer().run()
|
|
|
|
sys.exit(0)
|