#!/usr/bin/python # LADITools - Linux Audio Desktop Integration Tools # ladi-system-tray - System tray integration for LADI # Copyright (C) 2011-2012 Alessio Treglia # Copyright (C) 2007-2010, Marc-Olivier Barre # Copyright (C) 2007-2009, Nedko Arnaudov # # 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 . import os import sys 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 LadiManager from laditools import LadiApp from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject try: from gi.repository import AppIndicator3 except: AppIndicator3 = None from laditools.gtk import LadiMenu from laditools.gtk import find_data_file timeout_add = GObject.timeout_add class LadiStatusIcon (LadiMenu, LadiApp): _appname = 'ladi-system-tray' _appname_long = _("LADI System Tray") _appid = 'org.linuxaudio.ladi.systemtray' # Default configuration _default_config = { 'autostart' : False, } def on_about(self, *args): LadiMenu.on_about(self, version=get_version_string()) def quit(self, *args, **kwargs): # Some default config might need to be injected in the config file, # we handle all that before we quit. self.global_config.set_config_section (self.appname, self.config_dict) self.global_config.save () Gtk.main_quit() def set_tooltip_text(self, text): pass def __init__ (self, config_filename = None): # Handle the configuration self.icon_state = "" self.last_status_text = "" self.diagnose_text = None self.status_icons = {'started' : 'ladi-started', 'stopped' : 'ladi-stopped', 'starting' : 'ladi-starting'} self.global_config = LadiConfiguration(self.appname, self._default_config, config_filename) self.config_dict = self.global_config.get_config_section (self.appname) autostart = bool(eval(self.config_dict['autostart'])) # Build the UI LadiMenu.__init__(self, autostart, quit = self.quit) LadiApp.__init__(self) self.connect_signals_quit() def menu_activate(self, status_icon, button, activate_time, user_data=None): menu = self.create_menu() menu.popup (parent_menu_shell=None, parent_menu_item=None, func=self.position_menu, data=self, button=button, activate_time=activate_time) menu.reposition () def set_starting_status (self): self.set_tooltip_safe ("JACK is starting") self.set_icon ("starting") def set_tooltip_safe (self, text): if text != self.last_status_text: self.set_tooltip_text (text) self.last_status_text = text def run(self): Gtk.main () class LadiStatusTray(Gtk.StatusIcon, LadiStatusIcon): def __init__(self): LadiStatusIcon.__init__(self) GObject.GObject.__init__ (self) self.set_icon ("stopped") # Get the initial status self.update () # Add the auto update callback self.auto_updater = timeout_add (250, self.update, None) # Make the menu popup when the icon is right clicked self.connect ("popup-menu", self.menu_activate) self.set_title(self.appname_long) def do_button_press_event(self, event): if event.type != Gdk.EventType._2BUTTON_PRESS: return False self.on_menu_launch_handler(None, "gladish") return True def update (self, user_data = None): try: if self.jack_is_started(): # Get Realtime status 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.set_tooltip_safe (status_text) self.set_icon ("started") else: self.set_tooltip_safe ("JACK is stopped") self.set_icon ("stopped") self.clear_diagnose_text() except Exception as e: self.set_tooltip_safe ("JACK is sick") self.set_diagnose_text(repr(e)) self.set_icon ("stopped") self.clear_jack_proxies() finally: LadiManager.update(self) return True def set_icon (self, newstate): if self.icon_state == newstate: return self.icon_state = newstate self.set_from_icon_name(self.status_icons[newstate]) class LadiStatusIndicator(LadiStatusIcon): def update (self, user_data = None): try: if self.jack_is_started(): # Get Realtime status 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.set_tooltip_safe (status_text) self.set_icon ("started") else: self.set_tooltip_safe ("JACK is stopped") self.set_icon ("stopped") self.clear_diagnose_text() except (Exception, e): self.set_tooltip_safe ("JACK is sick") self.set_diagnose_text(repr(e)) self.set_icon ("stopped") self.clear_jack_proxies() finally: LadiManager.update(self) return True def set_icon (self, newstate): if self.icon_state == newstate: return self.icon_state = newstate self.indicator.set_icon(self.status_icons[newstate]) def create_menu(self): menu_items = [] ladish_available = self.ladish_is_available() menu_items.append((Gtk.ImageMenuItem(_("LADI Player")), self.on_menu_launch_handler, "ladi-player")) if ladish_available: menu_items.append((Gtk.ImageMenuItem(_("Session editor")), self.on_menu_launch_handler, "gladish")) menu_items.append((Gtk.SeparatorMenuItem.new(),)) menu_items.append((Gtk.ImageMenuItem(_("Settings")), self.on_menu_launch_handler, "ladi-control-center")) menu_items.append((Gtk.ImageMenuItem(_("Log Viewer")), self.on_menu_launch_handler, "ladi-system-log")) menu_items.append((Gtk.SeparatorMenuItem.new(),)) if hasattr(self, 'on_about'): menu_items.append((Gtk.ImageMenuItem(_("About")), self.on_about, None)) menu_items.append((Gtk.ImageMenuItem(_("Quit")), self.on_menu_command, self.quit)) menu = Gtk.Menu() for menu_tuple in menu_items: item = menu_tuple[0] if len(menu_tuple) > 1: callback = menu_tuple[1] exec_path = menu_tuple[2] menu.append(item) if type(item) is not Gtk.SeparatorMenuItem: if callback in (self.studio_list_fill, self.configure_list_fill): item.set_submenu(Gtk.Menu()) item.connect("activate", callback, exec_path) menu.show_all() return menu def __init__(self): LadiStatusIcon.__init__(self) self.indicator = indicator = AppIndicator3.Indicator.new('ladi-indicator', find_data_file('scalable/apps/laditools.svg'), AppIndicator3.IndicatorCategory.APPLICATION_STATUS) self.menu = menu = self.create_menu() indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE) indicator.set_menu(menu) menu.show() # Get the initial status self.update () # Add the auto update callback self.auto_updater = timeout_add (250, self.update, None) if __name__ == "__main__": parser = argparse.ArgumentParser(description=_('system tray icon 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('--no-appindicator', action='store_true', help=_('Force fallback to system tray.')) parser.add_argument('--version', action='version', version="%(prog)s " + get_version_string()) args = parser.parse_args() Gtk.init(None) if (not args.no_appindicator) and AppIndicator3: LadiStatusIndicator().run() else: LadiStatusTray().run() sys.exit(0)