class systemdBus(object): def __init__(self, user=False): self.bus = SessionBus() if user else SystemBus() systemd = self.bus.get_object(SYSTEMD_BUSNAME, SYSTEMD_PATH) self.manager = Interface(systemd, dbus_interface=SYSTEMD_MANAGER_INTERFACE) def get_unit_active_state(self, unit): unit = self.manager.LoadUnit(unit) unit_object = self.bus.get_object(SYSTEMD_BUSNAME, unit) unit_properties = Interface(unit_object, DBUS_INTERFACE) return unit_properties.Get(SYSTEMD_UNIT_INTERFACE, 'ActiveState') def get_unit_load_state(self, unit): unit = self.manager.LoadUnit(unit) unit_object = self.bus.get_object(SYSTEMD_BUSNAME, unit) unit_properties = Interface(unit_object, DBUS_INTERFACE) return unit_properties.Get(SYSTEMD_UNIT_INTERFACE, 'LoadState') def get_unit_uptime(self, unit): unit = self.manager.LoadUnit(unit) unit_object = self.bus.get_object(SYSTEMD_BUSNAME, unit) unit_properties = Interface(unit_object, DBUS_INTERFACE) return unit_properties.Get(SYSTEMD_UNIT_INTERFACE, 'ActiveEnterTimestamp') def start_unit(self, unit): try: self.manager.StartUnit(unit, 'replace') return True except exceptions.DBusException: return False def stop_unit(self, unit): try: self.manager.StopUnit(unit, 'replace') return True except exceptions.DBusException: return False def restart_unit(self, unit): try: self.manager.RestartUnit(unit, 'replace') return True except exceptions.DBusException: return False def reload_unit(self, unit): try: self.manager.ReloadUnit(unit, 'replace') return True except exceptions.DBusException: return False def reload_or_restart_unit(self, unit): try: self.manager.ReloadOrRestartUnit(unit, 'replace') return True except exceptions.DBusException: return False
class _OSDManager(object): """ Manages OSD notifications via DBus. """ def __init__(self): self._last_id = 0 if IS_INIT: self.bus = SessionBus() self.notifcations = self.bus.get_object( "org.freedesktop.Notifications", "/org/freedesktop/Notifications") self.notify_interface = Interface(self.notifcations, "org.freedesktop.Notifications") def notify(self, track): """ Create new or update existing notification. """ if IS_INIT: thread = Thread(target=self._notify, args=(track, )) thread.daemon = True thread.start() def _notify(self, track): artist_art_filename = track.get_artist_art_filename() self._last_id = self.notify_interface.Notify( meta.APP_NAME, self._last_id, artist_art_filename if artist_art_filename is not None else 'audio-headphones', track.title, u'by {}\nfrom {}'.format(track.artist, track.album_name), [], dict(), 5000)
def nh_side_command_process(): """ Execute command (clear screen or exit) on NH. :return: [no return value] """ bus = SessionBus() obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject") purple = Interface(obj, "im.pidgin.purple.PurpleInterface") account = purple.PurpleAccountsGetAllActive()[0] while True: if nh_side_command.empty(): sleep(0.001) continue cmd = nh_side_command.get() if cmd.startswith("TFC|N|%s|U|CLEAR|" % int_version): contact = cmd.split('|')[5] new_conv = purple.PurpleConversationNew(1, account, contact) purple.PurpleConversationClearMessageHistory(new_conv) system("clear")
class DBusMediaKeyListener(object): '''Listen on DBus for media-key events.''' def __init__(self, callback=None): self._subscribers = [] self.app = APP_NAME self.bus = SessionBus() self.bus_object = self.bus.get_object( 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys') self.bus_object.GrabMediaPlayerKeys( self.app, 0, dbus_interface='org.gnome.SettingsDaemon.MediaKeys') self.bus_object.connect_to_signal( 'MediaPlayerKeyPressed', self._notify) if callback: self.subscribe(callback) def _notify(self, application, *mmkeys): for subscriber in self._subscribers: subscriber(mmkeys) def subscribe(self, callback): self._subscribers.append(callback) def unsubscribe(self, callback): self._subscribers.remove(callback)
def main(): print( "starting to monitor your spotify tracks, make sure you start the spotify client before you run this program" ) while True: try: session_bus = SessionBus() bus_data = ("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2") spotify_bus = session_bus.get_object(*bus_data) interface = Interface(spotify_bus, "org.freedesktop.DBus.Properties") metadata = interface.Get("org.mpris.MediaPlayer2.Player", "Metadata") status = str( interface.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus")) is_playing = False if status == "Playing": is_playing = True data = {"artist": None, "song": None, "album": None} artist_data = metadata.get("xesam:albumArtist") artist = str(next(iter(artist_data))) song_name = str(metadata.get("xesam:title")) album = str(metadata.get("xesam:album")) thread = Thread(target=handle_track, args=( song_name, album, artist, is_playing, prev_track, )) thread.start() # if is_playing: # print('{} - {}'.format(song_name, artist)) sleep(1) except Exception as e: print("exception occurred") print(e) sleep(1) print('exiting? wtf?')
class Vibra_Plugin(Plugin): def __init__(self): DBusGMainLoop(set_as_default=True) self.bus = SystemBus() self.sessionbus = SessionBus() try: self.mce = self.bus.get_object("com.nokia.mce", "/com/nokia/mce") except DBusException: warning("Nokia MCE not found. Vibra is disabled\n") return self.profiled = self.sessionbus.get_object("com.nokia.profiled", "/com/nokia/profiled") self.sessionbus.add_signal_receiver( self.profile_changed_handler, "profile_changed", "com.nokia.profiled", "com.nokia.profiled", "/com/nokia/profiled", ) profile = self.profiled.get_profile(dbus_interface="com.nokia.profiled") self.get_vibra_enabled(profile) self.register_plugin(PLUGIN_TYPE_VIBRA) def ready(self): self.notification = get_plugin_by_type(PLUGIN_TYPE_NOTIFICATION) sendfile = get_plugin_by_type(PLUGIN_TYPE_SEND_FILE) sendfile.receive_cb.append(self.file_receive) def get_vibra_enabled(self, profile): self.enabled = ( self.profiled.get_value(profile, "vibrating.alert.enabled", dbus_interface="com.nokia.profiled") == "On" ) debug("Vibra enabled: %s\n" % self.enabled) def profile_changed_handler(self, foo, bar, profile, *args): self.get_vibra_enabled(profile) def vibrate(self): if self.enabled: self.mce.req_vibrator_pattern_activate("PatternChatAndEmail", dbus_interface="com.nokia.mce.request") def file_receive(self, cb, user, fname): self.vibrate() def user_appears(self, user): if user.get("friend"): self.vibrate()
def setup(): global HOME, arch, db_conn, browser_bus HOME = getenv('HOME', '/home/pi') arch = machine() signal(SIGUSR1, sigusr1) load_settings() db_conn = db.conn(settings['database']) load_browser() bus = SessionBus() browser_bus = bus.get_object('screenly.webview', '/Screenly')
class Audiobox(): """Audiobox class""" def __init__(self): self.bus = SessionBus() self.init() def init(self): self.proxy_obj = self.bus.get_object(vim.eval('g:audiobox_dbus_dest'), vim.eval('g:audiobox_dbus_path')) self.player = Interface(self.proxy_obj, vim.eval('g:audiobox_dbus_interface')) self.properties = Interface(self.proxy_obj, vim.eval('g:audiobox_dbus_properties_interface')) def Play(self): """Play current song""" if self.player: self.player.Play() def Pause(self): """Pause current song""" if self.player: self.player.Pause() def Next(self): """Play the next song""" if self.player: self.player.Next() def Prev(self): """Play the previous song""" if self.player: self.player.Previous() def PlayPause(self): """Play / Pause the current song""" if self.player: self.player.PlayPause() def Stop(self): """Stop the current song""" if self.player: self.player.Stop() def GetCurrentSong(self): """Get the title of the current song""" if self.properties: metadata = self.properties.Get(vim.eval('g:audiobox_dbus_interface'), 'Metadata') if len(metadata) > 0: vim.command("echohl String | echom \"" + ("Song: %s, Artist: %s, Album: %s" % (str(metadata['xesam:title']), str(metadata['xesam:artist'][0]), str(metadata['xesam:album']))) + "\" | echohl None")
def run_client(self): bus = SessionBus() obj = bus.get_object(CROSS_TEST_BUS_NAME, CROSS_TEST_PATH) self.obj = obj self.run_synchronous_tests(obj) # Signal tests logger.info("Binding signal handler for Triggered") # FIXME: doesn't seem to work when going via the Interface method # FIXME: should be possible to ask the proxy object for its # bus name bus.add_signal_receiver(self.triggered_cb, 'Triggered', INTERFACE_SIGNAL_TESTS, CROSS_TEST_BUS_NAME, path_keyword='sender_path') logger.info("method/signal: Triggering signal") self.expected.add('%s.Trigger' % INTERFACE_TESTS) Interface(obj, INTERFACE_TESTS).Trigger(u'/Where/Ever', dbus.UInt64(42), reply_handler=self.trigger_returned_cb, error_handler=self.trigger_error_handler)
def header_printer_process(): """ Print NH.py headers. :return: [no return value] """ try: bus = SessionBus() obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject") purple = Interface(obj, "im.pidgin.purple.PurpleInterface") active = purple.PurpleAccountsGetAllActive()[0] acco_u = purple.PurpleAccountGetUsername(active)[:-1] print("TFC-NaCl %s | NH.py\n" % str_version) print("Active account: %s\n" % acco_u) except DBusException: raise CriticalError("header_printer_process", "DBusException. Ensure " "Pidgin is running.")
class _OSDManager(object): """ Manages OSD notifications via DBus. """ def __init__(self): self._last_id = 0 if IS_INIT: self.bus = SessionBus() self.notifcations = self.bus.get_object( "org.freedesktop.Notifications", "/org/freedesktop/Notifications") self.notify_interface = Interface(self.notifcations, "org.freedesktop.Notifications") def notify(self, title, message): """ Create new or update existing notification. """ if IS_INIT: self._last_id = self.notify_interface.Notify( meta.APP_NAME, self._last_id, 'audio-headphones', title, message, [], dict(), 5000)
def queue_to_pidgin_process(): """ Send message from queue to Pidgin. :return: [no return value] """ bus = SessionBus() obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject") purple = Interface(obj, "im.pidgin.purple.PurpleInterface") account = purple.PurpleAccountsGetAllActive()[0] while True: if message_to_pidgin.empty(): sleep(0.001) continue message = message_to_pidgin.get() if message.startswith("TFC|N|%s|M|" % int_version): tfc, model, ver, pt, ct, key_id, recipient = message.split('|') to_pidgin = '|'.join(message.split('|')[:6]) if output_pidgin: new_conv = purple.PurpleConversationNew(1, account, recipient) sel_conv = purple.PurpleConvIm(new_conv) purple.PurpleConvImSend(sel_conv, to_pidgin) if message.startswith("TFC|N|%s|P|" % int_version): tfc, model, ver, pt, pub_key, recipient = message.split('|') to_pidgin = '|'.join(message.split('|')[:5]) if output_pidgin: new_conv = purple.PurpleConversationNew(1, account, recipient) sel_conv = purple.PurpleConvIm(new_conv) purple.PurpleConvImSend(sel_conv, to_pidgin)
class DBusMediaKeyListener(object): '''Listen on DBus for media-key events.''' def __init__(self, callback=None): self._subscribers = [] self.app = APP_NAME self.bus = SessionBus() self.bus_object = self.bus.get_object( 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys') self.bus_object.GrabMediaPlayerKeys( self.app, 0, dbus_interface='org.gnome.SettingsDaemon.MediaKeys') self.bus_object.connect_to_signal('MediaPlayerKeyPressed', self._notify) if callback: self.subscribe(callback) def _notify(self, application, *mmkeys): for subscriber in self._subscribers: subscriber(mmkeys) def subscribe(self, callback): self._subscribers.append(callback) def unsubscribe(self, callback): self._subscribers.remove(callback)
def run_client(self): bus = SessionBus() obj = bus.get_object(CROSS_TEST_BUS_NAME, CROSS_TEST_PATH) self.obj = obj self.run_synchronous_tests(obj) # Signal tests logger.info("Binding signal handler for Triggered") # FIXME: doesn't seem to work when going via the Interface method # FIXME: should be possible to ask the proxy object for its # bus name bus.add_signal_receiver(self.triggered_cb, 'Triggered', INTERFACE_SIGNAL_TESTS, CROSS_TEST_BUS_NAME, path_keyword='sender_path') logger.info("method/signal: Triggering signal") self.expected.add('%s.Trigger' % INTERFACE_TESTS) Interface(obj, INTERFACE_TESTS).Trigger( '/Where/Ever', dbus.UInt64(42), reply_handler=self.trigger_returned_cb, error_handler=self.trigger_error_handler)
class SystemTrayApp(QApplication): def __init__(self, args, read_pipe): QApplication.__init__(self, args) self.menu = None self.read_pipe = read_pipe self.fmt = "80s80sI32sI80sf" self.fmt_size = struct.calcsize(self.fmt) self.timer_active = False self.active_icon = False self.user_settings = UserSettings() self.user_settings.load() self.user_settings.debug() self.tray_icon = QSystemTrayIcon() pm = load_pixmap("hp_logo", "32x32") self.prop_icon = QIcon(pm) a = load_pixmap('active', '16x16') painter = QPainter(pm) painter.drawPixmap(32, 0, a) painter.end() self.prop_active_icon = QIcon(pm) self.tray_icon.setIcon(self.prop_icon) self.session_bus = SessionBus() self.service = None for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.tray_icon.setToolTip(self.__tr("HPLIP Status Service")) # QObject.tray_icon.messageClicked.connect(self.messageClicked) self.tray_icon.messageClicked.connect(self.messageClicked) notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read) # QObject.notifier.activated[int].connect(self.notifierActivated) notifier.activated[int].connect(self.notifierActivated) # QObject.tray_icon.activated[QSystemTrayIcon::ActivationReason].connect(self.trayActivated) self.tray_icon.activated["QSystemTrayIcon::ActivationReason"].connect(self.trayActivated) signal.signal(signal.SIGINT, signal.SIG_DFL) self.tray_icon.show() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: self.tray_icon.setVisible(True) else: QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) # show icon for awhile @ startup self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True if "--ignore-update-firsttime" not in args: self.handle_hplip_updation() QTimer.singleShot(SET_MENU_DELAY, self.initDone) self.update_timer = QTimer() # self.update_timer.connect(self.update_timer,SIGNAL("timeout()"),self.handle_hplip_updation) self.update_timer.timeout.connect(self.handle_hplip_updation) self.update_timer.start(UPGRADE_CHECK_DELAY) # Cleans the /var/log/hp/tmp directory #self.handle_hplip_clean() #self.clean_timer = QTimer() #self.clean_timer.connect(self.clean_timer,SIGNAL("timeout()"),self.handle_hplip_clean) #self.clean_timer.start(CLEAN_EXEC_DELAY) def initDone(self): self.tray_icon.setIcon(self.prop_icon) self.active_icon = False self.setMenu() def resetDevice(self): devices.clear() def addDevice(self, device_uri): try: devices[device_uri] except KeyError: devices[device_uri] = HistoryDevice(device_uri) else: devices[device_uri].needs_update = True def handle_hplip_clean(self): log.debug("handle_hplip_clean ") home_dir = sys_conf.get('dirs', 'home') cmd = 'sh %s/hplip_clean.sh'%home_dir os.system(cmd) def handle_hplip_updation(self): log.debug("handle_hplip_updation upgrade_notify =%d"%(self.user_settings.upgrade_notify)) path = utils.which('hp-upgrade') if self.user_settings.upgrade_notify is False: log.debug("upgrade notification is disabled in systray ") if path: path = os.path.join(path, 'hp-upgrade') log.debug("Running hp-upgrade: %s " % (path)) # this just updates the available version in conf file. But won't notify os.spawnlp(os.P_NOWAIT, path, 'hp-upgrade', '--check') time.sleep(5) try: os.waitpid(0, os.WNOHANG) except OSError: pass return current_time = time.time() if int(current_time) > self.user_settings.upgrade_pending_update_time: path = utils.which('hp-upgrade') if path: path = os.path.join(path, 'hp-upgrade') log.debug("Running hp-upgrade: %s " % (path)) os.spawnlp(os.P_NOWAIT, path, 'hp-upgrade', '--notify') time.sleep(5) else: log.error("Unable to find hp-upgrade --notify on PATH.") else: log.debug("upgrade schedule time is not yet completed. schedule time =%d current time =%d " %(self.user_settings.upgrade_pending_update_time, current_time)) try: os.waitpid(0, os.WNOHANG) except OSError: pass def setMenu(self): self.menu = QMenu() title = QAction(self.menu) #title.setDisabled(True) title.setText(self.__tr("HPLIP Status Service")) title.setIcon(self.prop_icon) title.setIconVisibleInMenu(True) self.menu.insertAction(None, title) if devices: if self.service is None: t = 0 while t < 3: try: self.service = self.session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") except dbus.DBusException: log.warn("Unable to connect to StatusService. Retrying...") t += 1 time.sleep(0.5) if self.service is not None: self.menu.addSeparator() for d in devices: devices[d].getHistory(self.service) menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index) self.menu.addMenu(menu) menu.update() self.menu.addSeparator() self.menu.addAction(self.__tr("HP Device Manager..."), self.toolboxTriggered) self.menu.addSeparator() self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')), self.__tr("Settings..."), self.settingsTriggered) self.menu.addSeparator() self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), "Quit", self.quitTriggered) self.tray_icon.setContextMenu(self.menu) def settingsTriggered(self): if self.menu is None: return self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING) # sys_conf cur_vers = sys_conf.get('hplip', 'version') self.user_settings.load() installed_time =time.strftime("%d-%m-%Y", time.localtime(self.user_settings.upgrade_last_update_time)) if utils.Is_HPLIP_older_version(cur_vers, self.user_settings.latest_available_version): if int(time.time()) < self.user_settings.upgrade_pending_update_time : postponed_time =time.strftime("%d-%m-%Y", time.localtime(self.user_settings.upgrade_pending_update_time)) upgrade_msg ="HPLIP-%s version was installed on %s.\n\nNew version of HPLIP-%s is available for upgrade. HPLIP upgrade is scheduled on %s." %(cur_vers,installed_time , self.user_settings.latest_available_version, postponed_time) elif self.user_settings.upgrade_last_update_time: upgrade_msg ="HPLIP-%s version was installed on %s.\n\nNew version of HPLIP-%s is available for upgrade." %(cur_vers,installed_time , self.user_settings.latest_available_version) else: upgrade_msg ="HPLIP-%s version was installed.\n\nNew version of HPLIP-%s is available for upgrade." %(cur_vers, self.user_settings.latest_available_version) elif self.user_settings.upgrade_last_update_time: upgrade_msg ="HPLIP-%s version was installed on %s."%(cur_vers, installed_time) else: upgrade_msg ="HPLIP-%s version was installed."%(cur_vers) try: dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible, self.user_settings.polling, self.user_settings.polling_interval, self.user_settings.systray_messages, self.user_settings.polling_device_list, self.user_settings.upgrade_notify, self.user_settings.upgrade_pending_update_time, self.user_settings.upgrade_last_update_time, upgrade_msg) if dlg.exec_() == QDialog.Accepted: self.user_settings.systray_visible = dlg.systray_visible self.user_settings.systray_messages = dlg.systray_messages self.user_settings.upgrade_notify = dlg.upgrade_notify log.debug("HPLIP update notification = %d"%(self.user_settings.upgrade_notify)) self.user_settings.save() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: log.debug("Showing...") self.tray_icon.setVisible(True) else: log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED) finally: self.sendMessage('', '', EVENT_DEVICE_START_POLLING) def timeoutHideWhenInactive(self): log.debug("Hiding...") if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): self.tray_icon.setVisible(False) log.debug("Hidden") def updateMenu(self): if self.menu is None: return for a in self.menu.actions(): try: a.menu().update() except AttributeError: continue def trayActivated(self, reason): if reason == QSystemTrayIcon.Context: self.updateMenu() elif reason == QSystemTrayIcon.DoubleClick: #print "double click" self.toolboxTriggered() pass elif reason == QSystemTrayIcon.Trigger: #print "single click" self.updateMenu() if not self.menu is None: self.menu.popup(QCursor.pos()) pass elif reason == QSystemTrayIcon.MiddleClick: #print "middle click" pass def messageClicked(self): #print "\nPARENT: message clicked" pass def quitTriggered(self): log.debug("Exiting") self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT) self.quit() del self.tray_icon def toolboxTriggered(self): try: os.waitpid(-1, os.WNOHANG) except OSError: pass # See if it is already running... ok, lock_file = utils.lock_app('hp-toolbox', True) if ok: # able to lock, not running... utils.unlock(lock_file) path = utils.which('hp-toolbox') if path: path = os.path.join(path, 'hp-toolbox') else: self.tray_icon.showMessage(self.__tr("HPLIP Status Service"), self.__tr("Unable to locate hp-toolbox on system PATH."), QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY) log.error("Unable to find hp-toolbox on PATH.") return #log.debug(path) log.debug("Running hp-toolbox: hp-toolbox") os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox') else: # ...already running, raise it self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface='com.hplip.Toolbox') def sendMessage(self, device_uri, printer_name, event_code, username=prop.username, job_id=0, title='', pipe_name='', interface='com.hplip.StatusService'): #device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(SessionBus(), interface) device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface) def notifierActivated(self, s): m = '' while True: try: r, w, e = select.select([self.read_pipe], [], [self.read_pipe], 1.0) except select.error: log.debug("Error in select()") break if e: log.error("Pipe error: %s" % e) break if r: #m = ''.join([m, os.read(self.read_pipe, self.fmt_size)]) m = os.read(self.read_pipe, self.fmt_size) while len(m) >= self.fmt_size: event = device.Event(*[x.rstrip(b'\x00').decode('utf-8') if isinstance(x, bytes) else x for x in struct.unpack(self.fmt, m[:self.fmt_size])]) m = m[self.fmt_size:] if event.event_code == EVENT_CUPS_QUEUES_REMOVED or event.event_code == EVENT_CUPS_QUEUES_ADDED: self.resetDevice() for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.setMenu() if event.event_code == EVENT_USER_CONFIGURATION_CHANGED: log.debug("Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)") self.user_settings.load() self.user_settings.debug() elif event.event_code == EVENT_SYSTEMTRAY_EXIT: self.quit() return if self.user_settings.systray_visible in \ (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE): log.debug("Showing...") self.tray_icon.setVisible(True) if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True continue elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE: if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False continue elif event.event_code == EVENT_DEVICE_UPDATE_BLIP: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(BLIP_DELAY, self.blipTimeout) continue if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) if event.event_code <= EVENT_MAX_USER_EVENT or \ event.event_code == EVENT_CUPS_QUEUES_REMOVED or event.event_code == EVENT_CUPS_QUEUES_ADDED: if event.event_code != EVENT_CUPS_QUEUES_REMOVED: self.addDevice(event.device_uri) self.setMenu() if self.tray_icon.supportsMessages(): log.debug("Tray icon message:") event.debug() error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR) desc = device.queryString(event.event_code) show_message = False if self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ALL: # OK, Busy show_message = True elif self.user_settings.systray_messages in (SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS, SYSTRAY_MESSAGES_SHOW_ERRORS_ONLY): if error_state == ERROR_STATE_ERROR: show_message = True elif self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS and \ error_state in (ERROR_STATE_WARNING, ERROR_STATE_LOW_SUPPLIES, ERROR_STATE_LOW_PAPER): show_message = True if event.printer_name: d = event.printer_name else: back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ device.parseDeviceURI(event.device_uri) if bus == 'usb': idd = serial elif bus == 'net': idd = host elif bus == 'par': idd = dev_file else: idd = 'unknown' self.model = models.normalizeModelUIName(model) if back_end == 'hp': d = self.__tr("%s Printer (%s)"%(model,idd)) elif back_end == 'hpaio': d = self.__tr("%s Scanner (%s)"%(model,idd)) elif back_end == 'hpfax': d = self.__tr("%s Fax (%s)"%(model,idd)) else: d = self.__tr("%s (%s)"%(model,idd)) if show_message: if have_pynotify and pynotify.init("hplip"): # Use libnotify/pynotify icon, urgency = ERROR_STATE_TO_ICON_AND_URGENCY_PYNOTIFY.get(error_state, (getPynotifyIcon('info'), pynotify.URGENCY_NORMAL)) if event.job_id and event.title: msg = "%s\n%s: %s\n(%s/%s)" % (to_unicode(d), desc, event.title, event.username, event.job_id) log.debug("Notify: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) else: msg = "%s\n%s (%s)" % (to_unicode(d), desc, event.event_code) log.debug("Notify: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) n = pynotify.Notification("HPLIP Device Status", msg, icon) # CRID: 11833 Debian Traceback error notification exceeded n.set_hint('transient', True) n.set_urgency(urgency) if error_state == ERROR_STATE_ERROR: n.set_timeout(pynotify.EXPIRES_NEVER) else: n.set_timeout(TRAY_MESSAGE_DELAY) n.show() else: # Use "standard" message bubbles icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information) if event.job_id and event.title: log.debug("Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), "%s\n%s: %s\n(%s/%s)"%(d,desc, event.title,event.username,event.job_id), icon, TRAY_MESSAGE_DELAY) else: log.debug("Bubble: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), "%s\n%s (%s)"%(d,desc,event.event_code), icon, TRAY_MESSAGE_DELAY) else: break # return def blipTimeout(self): if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False def __tr(self, s, c=None): return QApplication.translate("SystemTray", s, c)
volume_type = 'Master' # Interpreting how to affect the volume and by what percentage vol_action = argv[1] if vol_action in ['increase', 'decrease']: vol_percent_change = int(argv[2]) elif vol_action in ['mute']: vol_percent_change = 0 else: print("ERROR: command not one of 'decrease', 'increase' or 'mute': {}". format(vol_action)) exit(1) # Getting the dbus interface to communicate with gnome's OSD session_bus = SessionBus() proxy = session_bus.get_object('org.gnome.Shell', '/org/gnome/Shell') interface = Interface(proxy, 'org.gnome.Shell') # Get the current state. output = check_output(base_cmd + ['sget', volume_type]).decode('utf-8') # Mute status. try: on = search(r'\[(on)?(off)?\]', output).group(1) except IndexError: print("ERROR: no volume information found, try changing base_cmd") exit(1) # Calculate the new level based on an average for all levels. vol_percentage = [int(x) for x in findall(r'\[(\d{1,3})\%\]', output)] vol_percentage = int(sum(vol_percentage) / len(vol_percentage) + 0.5)
class SystemTrayApp(QApplication): def __init__(self, args, read_pipe): QApplication.__init__(self, args) self.menu = None self.read_pipe = read_pipe self.fmt = "80s80sI32sI80sf" self.fmt_size = struct.calcsize(self.fmt) self.timer_active = False self.active_icon = False self.user_settings = UserSettings() self.user_settings.load() self.user_settings.debug() self.tray_icon = QSystemTrayIcon() pm = load_pixmap("hp_logo", "32x32") self.prop_icon = QIcon(pm) a = load_pixmap('active', '16x16') painter = QPainter(pm) painter.drawPixmap(32, 0, a) painter.end() self.prop_active_icon = QIcon(pm) self.tray_icon.setIcon(self.prop_icon) self.session_bus = SessionBus() self.service = None for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.tray_icon.setToolTip(self.__tr("HPLIP Status Service")) QObject.connect(self.tray_icon, SIGNAL("messageClicked()"), self.messageClicked) notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read) QObject.connect(notifier, SIGNAL("activated(int)"), self.notifierActivated) QObject.connect(self.tray_icon, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.trayActivated) self.tray_icon.show() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: self.tray_icon.setVisible(True) else: QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) # show icon for awhile @ startup self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(SET_MENU_DELAY, self.initDone) def initDone(self): self.tray_icon.setIcon(self.prop_icon) self.active_icon = False self.setMenu() def addDevice(self, device_uri): try: devices[device_uri] except KeyError: devices[device_uri] = HistoryDevice(device_uri) else: devices[device_uri].needs_update = True def setMenu(self): self.menu = QMenu() title = QAction(self.menu) #title.setDisabled(True) title.setText(self.__tr("HPLIP Status Service")) title.setIcon(self.prop_icon) title.setIconVisibleInMenu(True) self.menu.insertAction(None, title) if devices: if self.service is None: t = 0 while t < 3: try: self.service = self.session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") except DBusException: log.warn("Unable to connect to StatusService. Retrying...") t += 1 time.sleep(0.5) if self.service is not None: self.menu.addSeparator() for d in devices: devices[d].getHistory(self.service) menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index) self.menu.addMenu(menu) menu.update() self.menu.addSeparator() self.menu.addAction(self.__tr("HP Device Manager..."), self.toolboxTriggered) self.menu.addSeparator() self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')), self.__tr("Settings..."), self.settingsTriggered) self.menu.addSeparator() self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), "Quit", self.quitTriggered) self.tray_icon.setContextMenu(self.menu) def settingsTriggered(self): if self.menu is None: return self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING) try: dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible, self.user_settings.polling, self.user_settings.polling_interval, self.user_settings.systray_messages, self.user_settings.polling_device_list) if dlg.exec_() == QDialog.Accepted: self.user_settings.systray_visible = dlg.systray_visible self.user_settings.systray_messages = dlg.systray_messages self.user_settings.save() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: log.debug("Showing...") self.tray_icon.setVisible(True) else: log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED) finally: self.sendMessage('', '', EVENT_DEVICE_START_POLLING) def timeoutHideWhenInactive(self): log.debug("Hiding...") if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): self.tray_icon.setVisible(False) log.debug("Hidden") def updateMenu(self): if self.menu is None: return for a in self.menu.actions(): try: a.menu().update() except AttributeError: continue def trayActivated(self, reason): if reason == QSystemTrayIcon.Context: self.updateMenu() elif reason == QSystemTrayIcon.DoubleClick: #print "double click" self.toolboxTriggered() pass elif reason == QSystemTrayIcon.Trigger: #print "single click" self.updateMenu() if not self.menu is None: self.menu.popup(QCursor.pos()) pass elif reason == QSystemTrayIcon.MiddleClick: #print "middle click" pass def messageClicked(self): #print "\nPARENT: message clicked" pass def quitTriggered(self): log.debug("Exiting") self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT) self.quit() del self.tray_icon def toolboxTriggered(self): try: os.waitpid(-1, os.WNOHANG) except OSError: pass # See if it is already running... ok, lock_file = utils.lock_app('hp-toolbox', True) if ok: # able to lock, not running... utils.unlock(lock_file) path = utils.which('hp-toolbox') if path: path = os.path.join(path, 'hp-toolbox') else: self.tray_icon.showMessage(self.__tr("HPLIP Status Service"), self.__tr("Unable to locate hp-toolbox on system PATH."), QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY) log.error("Unable to find hp-toolbox on PATH.") return #log.debug(path) log.debug("Running hp-toolbox: hp-toolbox") os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox') else: # ...already running, raise it self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface='com.hplip.Toolbox') def sendMessage(self, device_uri, printer_name, event_code, username=prop.username, job_id=0, title='', pipe_name='', interface='com.hplip.StatusService'): #device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(SessionBus(), interface) device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface) def notifierActivated(self, s): m = '' while True: try: r, w, e = select.select([self.read_pipe], [], [self.read_pipe], 1.0) except select.error: log.debug("Error in select()") break if e: log.error("Pipe error: %s" % e) break if r: m = ''.join([m, os.read(self.read_pipe, self.fmt_size)]) while len(m) >= self.fmt_size: event = device.Event(*struct.unpack(self.fmt, m[:self.fmt_size])) m = m[self.fmt_size:] if event.event_code == EVENT_USER_CONFIGURATION_CHANGED: log.debug("Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)") self.user_settings.load() self.user_settings.debug() elif event.event_code == EVENT_SYSTEMTRAY_EXIT: self.quit() return if self.user_settings.systray_visible in \ (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE): log.debug("Showing...") self.tray_icon.setVisible(True) if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True continue elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE: if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False continue elif event.event_code == EVENT_DEVICE_UPDATE_BLIP: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(BLIP_DELAY, self.blipTimeout) continue if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) if event.event_code <= EVENT_MAX_USER_EVENT: self.addDevice(event.device_uri) self.setMenu() if self.tray_icon.supportsMessages(): log.debug("Tray icon message:") event.debug() error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR) desc = device.queryString(event.event_code) show_message = False if self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ALL: # OK, Busy show_message = True elif self.user_settings.systray_messages in (SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS, SYSTRAY_MESSAGES_SHOW_ERRORS_ONLY): if error_state == ERROR_STATE_ERROR: show_message = True elif self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS and \ error_state in (ERROR_STATE_WARNING, ERROR_STATE_LOW_SUPPLIES, ERROR_STATE_LOW_PAPER): show_message = True if event.printer_name: d = QString(event.printer_name) else: back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ device.parseDeviceURI(event.device_uri) if bus == 'usb': idd = serial elif bus == 'net': idd = host elif bus == 'par': idd = dev_file else: idd = 'unknown' self.model = models.normalizeModelUIName(model) if back_end == 'hp': d = self.__tr("%1 Printer (%2)").arg(model).arg(idd) elif back_end == 'hpaio': d = self.__tr("%1 Scanner (%2)").arg(model).arg(idd) elif back_end == 'hpfax': d = self.__tr("%1 Fax (%2)").arg(model).arg(idd) else: d = self.__tr("%1 (%2)").arg(model).arg(idd) if show_message: if have_pynotify and pynotify.init("hplip"): # Use libnotify/pynotify icon, urgency = ERROR_STATE_TO_ICON_AND_URGENCY_PYNOTIFY.get(error_state, (getPynotifyIcon('info'), pynotify.URGENCY_NORMAL)) if event.job_id and event.title: msg = "%s\n%s: %s\n(%s/%s)" % (unicode(d), desc, event.title, event.username, event.job_id) log.debug("Notify: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) else: msg = "%s\n%s (%s)" % (unicode(d), desc, event.event_code) log.debug("Notify: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) n = pynotify.Notification("HPLIP Device Status", msg, icon) n.set_urgency(urgency) if error_state == ERROR_STATE_ERROR: n.set_timeout(pynotify.EXPIRES_NEVER) else: n.set_timeout(TRAY_MESSAGE_DELAY) n.show() else: # Use "standard" message bubbles icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information) if event.job_id and event.title: log.debug("Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), QString("%1\n%2: %3\n(%4/%5)").\ arg(d).\ arg(desc).arg(event.title).\ arg(event.username).arg(event.job_id), icon, TRAY_MESSAGE_DELAY) else: log.debug("Bubble: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), QString("%1\n%2 (%3)").arg(d).\ arg(desc).arg(event.event_code), icon, TRAY_MESSAGE_DELAY) else: break def blipTimeout(self): if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False def __tr(self, s, c=None): return QApplication.translate("SystemTray", s, c, QApplication.UnicodeUTF8)
class SystemTrayApp(QApplication): def __init__(self, args, read_pipe): QApplication.__init__(self, args) self.menu = None self.read_pipe = read_pipe self.fmt = "80s80sI32sI80sf" self.fmt_size = struct.calcsize(self.fmt) self.timer_active = False self.active_icon = False self.user_settings = UserSettings() self.user_settings.load() self.user_settings.debug() self.tray_icon = QSystemTrayIcon() pm = load_pixmap("hp_logo", "32x32") self.prop_icon = QIcon(pm) a = load_pixmap('active', '16x16') painter = QPainter(pm) painter.drawPixmap(32, 0, a) painter.end() self.prop_active_icon = QIcon(pm) self.tray_icon.setIcon(self.prop_icon) self.session_bus = SessionBus() self.service = None for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.tray_icon.setToolTip(self.__tr("HPLIP Status Service")) QObject.connect(self.tray_icon, SIGNAL("messageClicked()"), self.messageClicked) notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read) QObject.connect(notifier, SIGNAL("activated(int)"), self.notifierActivated) QObject.connect(self.tray_icon, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.trayActivated) self.tray_icon.show() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: self.tray_icon.setVisible(True) else: QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) # show icon for awhile @ startup self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(SET_MENU_DELAY, self.initDone) def initDone(self): self.tray_icon.setIcon(self.prop_icon) self.active_icon = False self.setMenu() def addDevice(self, device_uri): try: devices[device_uri] except KeyError: devices[device_uri] = HistoryDevice(device_uri) else: devices[device_uri].needs_update = True def setMenu(self): self.menu = QMenu() title = QWidgetAction(self.menu) #title.setDisabled(True) hbox = QFrame(self.menu) layout = QHBoxLayout(hbox) layout.setMargin(3) layout.setSpacing(5) pix_label = QLabel(hbox) layout.insertWidget(-1, pix_label, 0) icon_size = self.menu.style().pixelMetric(QStyle.PM_SmallIconSize) pix_label.setPixmap(self.prop_icon.pixmap(icon_size)) label = QLabel(hbox) layout.insertWidget(-1, label, 20) title.setDefaultWidget(hbox) label.setText(self.__tr("HPLIP Status Service")) f = label.font() f.setBold(True) label.setFont(f) self.menu.insertAction(None, title) if devices: if self.service is None: t = 0 while t < 3: try: self.service = self.session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") except DBusException: log.warn("Unable to connect to StatusService. Retrying...") t += 1 time.sleep(0.5) if self.service is not None: self.menu.addSeparator() for d in devices: devices[d].getHistory(self.service) menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index) self.menu.addMenu(menu) menu.update() self.menu.addSeparator() self.menu.addAction(self.__tr("HP Device Manager..."), self.toolboxTriggered) self.menu.addSeparator() self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')), self.__tr("Settings..."), self.settingsTriggered) self.menu.addSeparator() self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), "Quit", self.quitTriggered) self.tray_icon.setContextMenu(self.menu) def settingsTriggered(self): if self.menu is None: return self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING) try: dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible, self.user_settings.polling, self.user_settings.polling_interval, self.user_settings.systray_messages, self.user_settings.polling_device_list) if dlg.exec_() == QDialog.Accepted: self.user_settings.systray_visible = dlg.systray_visible self.user_settings.systray_messages = dlg.systray_messages self.user_settings.save() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: log.debug("Showing...") self.tray_icon.setVisible(True) else: log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED) finally: self.sendMessage('', '', EVENT_DEVICE_START_POLLING) def timeoutHideWhenInactive(self): log.debug("Hiding...") if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): self.tray_icon.setVisible(False) log.debug("Hidden") def updateMenu(self): if self.menu is None: return for a in self.menu.actions(): try: a.menu().update() except AttributeError: continue def trayActivated(self, reason): if reason == QSystemTrayIcon.Context: self.updateMenu() elif reason == QSystemTrayIcon.DoubleClick: #print "double click" self.toolboxTriggered() pass elif reason == QSystemTrayIcon.Trigger: #print "single click" pass elif reason == QSystemTrayIcon.MiddleClick: #print "middle click" pass def messageClicked(self): #print "\nPARENT: message clicked" pass def quitTriggered(self): log.debug("Exiting") self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT) self.quit() del self.tray_icon def toolboxTriggered(self): try: os.waitpid(-1, os.WNOHANG) except OSError: pass # See if it is already running... ok, lock_file = utils.lock_app('hp-toolbox', True) if ok: # able to lock, not running... utils.unlock(lock_file) path = utils.which('hp-toolbox') if path: path = os.path.join(path, 'hp-toolbox') else: self.tray_icon.showMessage(self.__tr("HPLIP Status Service"), self.__tr("Unable to locate hp-toolbox on system PATH."), QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY) log.error("Unable to find hp-toolbox on PATH.") return #log.debug(path) log.debug("Running hp-toolbox: hp-toolbox") os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox') else: # ...already running, raise it self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface='com.hplip.Toolbox') def sendMessage(self, device_uri, printer_name, event_code, username=prop.username, job_id=0, title='', pipe_name='', interface='com.hplip.StatusService'): #device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(SessionBus(), interface) device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface) def notifierActivated(self, s): m = '' while True: try: r, w, e = select.select([self.read_pipe], [], [self.read_pipe], 1.0) except select.error: log.debug("Error in select()") break if e: log.error("Pipe error: %s" % e) break if r: m = ''.join([m, os.read(self.read_pipe, self.fmt_size)]) while len(m) >= self.fmt_size: event = device.Event(*struct.unpack(self.fmt, m[:self.fmt_size])) m = m[self.fmt_size:] if event.event_code == EVENT_USER_CONFIGURATION_CHANGED: log.debug("Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)") self.user_settings.load() self.user_settings.debug() elif event.event_code == EVENT_SYSTEMTRAY_EXIT: self.quit() return if self.user_settings.systray_visible in \ (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE): log.debug("Showing...") self.tray_icon.setVisible(True) if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True continue elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE: if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False continue elif event.event_code == EVENT_DEVICE_UPDATE_BLIP: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(BLIP_DELAY, self.blipTimeout) continue if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) if event.event_code <= EVENT_MAX_USER_EVENT: self.addDevice(event.device_uri) self.setMenu() if self.tray_icon.supportsMessages(): log.debug("Tray icon message:") event.debug() error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR) desc = device.queryString(event.event_code) show_message = False if self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ALL: # OK, Busy show_message = True elif self.user_settings.systray_messages in (SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS, SYSTRAY_MESSAGES_SHOW_ERRORS_ONLY): if error_state == ERROR_STATE_ERROR: show_message = True elif self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS and \ error_state in (ERROR_STATE_WARNING, ERROR_STATE_LOW_SUPPLIES, ERROR_STATE_LOW_PAPER): show_message = True if event.printer_name: d = QString(event.printer_name) else: back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ device.parseDeviceURI(event.device_uri) if bus == 'usb': idd = serial elif bus == 'net': idd = host elif bus == 'par': idd = dev_file else: idd = 'unknown' self.model = models.normalizeModelUIName(model) if back_end == 'hp': d = self.__tr("%1 Printer (%2)").arg(model).arg(idd) elif back_end == 'hpaio': d = self.__tr("%1 Scanner (%2)").arg(model).arg(idd) elif back_end == 'hpfax': d = self.__tr("%1 Fax (%2)").arg(model).arg(idd) else: d = self.__tr("%1 (%2)").arg(model).arg(idd) if show_message: if have_pynotify and pynotify.init("hplip"): # Use libnotify/pynotify icon, urgency = ERROR_STATE_TO_ICON_AND_URGENCY_PYNOTIFY.get(error_state, (getPynotifyIcon('info'), pynotify.URGENCY_NORMAL)) if event.job_id and event.title: msg = "%s\n%s: %s\n(%s/%s)" % (unicode(d), desc, event.title, event.username, event.job_id) log.debug("Notify: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) else: msg = "%s\n%s (%s)" % (unicode(d), desc, event.event_code) log.debug("Notify: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) n = pynotify.Notification("HPLIP Device Status", msg, icon) n.set_urgency(urgency) if error_state == ERROR_STATE_ERROR: n.set_timeout(pynotify.EXPIRES_NEVER) else: n.set_timeout(TRAY_MESSAGE_DELAY) n.show() else: # Use "standard" message bubbles icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information) if event.job_id and event.title: log.debug("Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), QString("%1\n%2: %3\n(%4/%5)").\ arg(d).\ arg(desc).arg(event.title).\ arg(event.username).arg(event.job_id), icon, TRAY_MESSAGE_DELAY) else: log.debug("Bubble: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), QString("%1\n%2 (%3)").arg(d).\ arg(desc).arg(event.event_code), icon, TRAY_MESSAGE_DELAY) else: break def blipTimeout(self): if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False def __tr(self, s, c=None): return QApplication.translate("SystemTray", s, c, QApplication.UnicodeUTF8)
def notify(self, title, body, notify_type, **kwargs): """ Perform DBus Notification """ if not self._enabled or MAINLOOP_MAP[self.schema] is None: self.logger.warning( "{} notifications could not be loaded.".format(self.schema)) return False # Acquire our session session = SessionBus(mainloop=MAINLOOP_MAP[self.schema]) # acquire our dbus object dbus_obj = session.get_object( NOTIFY_DBUS_INTERFACE, NOTIFY_DBUS_SETTING_LOCATION, ) # Acquire our dbus interface dbus_iface = Interface( dbus_obj, dbus_interface=NOTIFY_DBUS_INTERFACE, ) # image path icon_path = self.image_path(notify_type, extension='.ico') # Our meta payload meta_payload = { "urgency": Byte(self.urgency) } if not (self.x_axis is None and self.y_axis is None): # Set x/y access if these were set meta_payload['x'] = self.x_axis meta_payload['y'] = self.y_axis if NOTIFY_DBUS_IMAGE_SUPPORT is True: try: # Use Pixbuf to create the proper image type image = GdkPixbuf.Pixbuf.new_from_file(icon_path) # Associate our image to our notification meta_payload['icon_data'] = ( image.get_width(), image.get_height(), image.get_rowstride(), image.get_has_alpha(), image.get_bits_per_sample(), image.get_n_channels(), ByteArray(image.get_pixels()) ) except Exception as e: self.logger.warning( "Could not load Gnome notification icon ({}): {}" .format(icon_path, e)) # Limit results to just the first 10 line otherwise # there is just to much content to display body = re.split('[\r\n]+', body) if title: # Place title on first line if it exists body.insert(0, title) body = '\r\n'.join(body[0:10]) try: dbus_iface.Notify( # Application Identifier self.app_id, # Message ID (0 = New Message) 0, # Icon (str) - not used '', # Title str(title), # Body str(body), # Actions list(), # Meta meta_payload, # Message Timeout self.message_timeout_ms, ) self.logger.info('Sent DBus notification.') except Exception as e: self.logger.warning('Failed to send DBus notification.') self.logger.exception('DBus Exception') return False return True
class AutoPlayer: def __init__(self): # Diccionario para evitar los dobles escaneos producto de la emisión # de señales repetidas. Pasa porque Rhythmbox vuelve a escanear todos # los dispositivos cuando levanta por primera vez. self._already_scanned = {} # Se obtiene una conexión al bus de sistema self._system_bus = SystemBus() # Se obtiene una conexión al bus de sesión self._session_bus = SessionBus() # Conectar a las señales que emite de UDisks self._connect_to_udisks() def _connect_to_udisks(self): # Información de D-Bus para UDisks udisks_bus_name = 'org.freedesktop.UDisks' udisks_object_path = '/org/freedesktop/UDisks' udisks_dbus_interface = 'org.freedesktop.UDisks' # Se conecta la señal 'DeviceChanged' exportada por el objeto remoto # al manejador local de señales '_onDeviceChanged'. self._system_bus.add_signal_receiver( self._onDeviceChanged, signal_name='DeviceChanged', dbus_interface=udisks_dbus_interface, bus_name=udisks_bus_name, path=udisks_object_path) # Se conecta la señal 'DeviceRemoved' exportada por el objeto remoto # al manejador local de señales '_onDeviceRemoved'. self._system_bus.add_signal_receiver( self._onDeviceRemoved, signal_name='DeviceRemoved', dbus_interface=udisks_dbus_interface, bus_name=udisks_bus_name, path=udisks_object_path) def _onDeviceChanged(self, device_object_path): " La señal 'DeviceChanged' es emitida cuando se cambia el estado de un" " dispositivo (por ejemplo, cuando se monta o desmonta). UDisks envía " " el camino del objeto remoto del dispositivo que cambió de estado. " print u'Un dispositivo cambió: %s' % device_object_path mount_path = self._get_device_mount_path(device_object_path) # Si no está montado o ya fue escaneado, no hacer nada y retornar if not mount_path: return playlist = self._get_playlist(mount_path) # Si no hay música en el dispositivo, no hacer nada y retornar if not playlist: return self._play(playlist) def _onDeviceRemoved(self, device_object_path): " La señal 'DeviceRemoved' es emitida cuando un dispositivo es " " desconectado por hardware de la PC. UDisks envía el camino del " " objeto remoto del dispositivo." print u'Un dispositivo fue desconectado: %s' % device_object_path if device_object_path in self._already_scanned: del self._already_scanned[device_object_path] def _get_device_mount_path(self, device_object_path): # Información necesaria para procesar los dispositivos de UDisks udisks_bus_name = 'org.freedesktop.UDisks' device_dbus_interface = 'org.freedesktop.UDisks.Device' # Se obtiene el objeto remoto del dispositivo insertado a través # de la conexión al bus de sistema del demonio UDisks. device_object = self._system_bus.get_object(udisks_bus_name, device_object_path) # Para acceder a las propiedades de un objeto FreeDesktop.org # establece una interfaz estándar: 'org.freedesktop.DBus.Properties' device = Interface(device_object, 'org.freedesktop.DBus.Properties') # Con el método 'Get' de la interfaz 'org.freedesktop.DBus.Properties' # se obtiene el valor de una propiedad en una interfaz determinada. # La propiedad 'DeviceFile' devuelve el archivo de dispositivo en /dev # En nuestro caso no lo necesitamos, se pone a modo de enseñanza. dev_file = device.Get(device_dbus_interface, 'DeviceFile') # La propiedad 'DeviceIsMounted' devuelve si está montado is_mounted = device.Get(device_dbus_interface, 'DeviceIsMounted') print u'¿Está montado %s? : %s' % (dev_file, str(bool(is_mounted))) # Si el dispositivo ya fue escaneado y no está montado, significa que # recién se desmontó, hay que olvidarlo. mount_path = None if device_object_path in self._already_scanned: if not is_mounted: del self._already_scanned[device_object_path] # Si no ha sido escaneado y está montado, significa que recién se # ha montado y hay que escanearlo y recordarlo, se devuelve el punto # de montaje. En otros casos, no se hace nada y no se devuelve nada. elif is_mounted: self._already_scanned[device_object_path] = True # La propiedad 'DeviceMountPaths' devuelve todos los directorios # del sistema de archivos donde se ha montado este dispositivo. mount_paths = device.Get(device_dbus_interface, 'DeviceMountPaths') mount_path = mount_paths[0] return mount_path def _get_playlist(self, directory_path): print u'Buscando música en el directorio %s' % directory_path playlist = [] filenames = listdir(directory_path) for filename in filenames: path = join(directory_path, filename) if isfile(path): # Se obtiene el tipo MIME, ejemplo "audio/mpeg" mime_type = guess_type(path)[0] # Lo que interesa es la primera parte del tipo MIME category = mime_type.split('/')[0] if category == 'audio': # El Playlist Manager de Rhythmbox espera URIs, por tanto.. uri = urljoin('file:', pathname2url(path)) playlist.append(uri) return playlist def _get_rhythmbox_playlist_manager(self): # Para modificar la lista de reproducción no hay MPRIS que valga :-( # Información de D-Bus para el Playlist Manager de Rhythmbox rhythmbox_bus_name = 'org.gnome.Rhythmbox3' playlist_mgr_object_path = '/org/gnome/Rhythmbox3/PlaylistManager' playlist_mgr_dbus_interface = 'org.gnome.Rhythmbox3.PlaylistManager' # Se obtiene el objeto remoto de Rhythmbox desde el bus de sesión playlist_mgr_obj = self._session_bus.get_object( rhythmbox_bus_name, playlist_mgr_object_path) # Esperar a que levante Rhythmbox... sí, ok, ya sé que esto es una # mala práctica. Lo correcto sería conectar a alguna señal remota que # avise de que está listo el reproductor, pero mejor no complicarse :-P sleep(5) playlist_manager = Interface(playlist_mgr_obj, playlist_mgr_dbus_interface) return playlist_manager def _get_rhythmbox_player(self): # Para controlar el reproductor, usaremos la interfaz estándar que # define FreeDestkop.org, es decir MPRIS # Información de D-Bus para Rhythmbox usando interfaz estándar MPRIS rhythmbox_bus_name = 'org.mpris.MediaPlayer2.rhythmbox' rhythmbox_object_path = '/org/mpris/MediaPlayer2' rhythmbox_dbus_interface_player = 'org.mpris.MediaPlayer2.Player' rhythmbox_dbus_interface_playlists = 'org.mpris.MediaPlayer2.Playlists' # Se obtiene el objeto remoto de Rhythmbox desde el bus de sesión rhythmbox_object = self._session_bus.get_object( rhythmbox_bus_name, rhythmbox_object_path) # Se obtiene la interfaz Player del objeto remoto del reproductor rhythmbox_player = Interface(rhythmbox_object, rhythmbox_dbus_interface_player) # Se obtiene la interfaz Playerlists del objeto remoto del reproductor rhythmbox_playlists = Interface(rhythmbox_object, rhythmbox_dbus_interface_playlists) # Se necesita obtener la cantidad de listas de reproducción contenidas # en el reproductor. Eso lo devuelve la propiedad "PlaylistCount" playlists_properties = Interface(rhythmbox_object, 'org.freedesktop.DBus.Properties') pl_count = playlists_properties.Get(rhythmbox_dbus_interface_playlists, 'PlaylistCount') return rhythmbox_player, rhythmbox_playlists, pl_count def _play(self, playlist): # Obtener el Playlist Manager de Rhythmbox playlist_manager = self._get_rhythmbox_playlist_manager() # Nombre estático para la lista de reproducción, # se llamará siempre "Autoplayer" playlist_name = 'Autoplayer' try: # Borrar la lista de reproducción si ya existe playlist_manager.DeletePlaylist(playlist_name) except: # Si no existe levanta excepción, la ignoramos pass # Crear una lista de reproducción nueva playlist_manager.CreatePlaylist(playlist_name) # Se adiciona cada archivo de música obtenido del dispositvo # de almacenamiento a la nueva lista de reproducción for uri in playlist: playlist_manager.AddToPlaylist(playlist_name, uri) # Obtenemos el reproductor y sus listas desde la interfaz MPRIS (rhythmbox_player, playlists_interface, playlists_count) = self._get_rhythmbox_player() # En un mundo ideal, Rhythmbox sería buenito y ordenaría las listas de # reproducción por fecha de creación en orden reverso como indica el # API de MPRIS, pero desgraciadamente no soporta esta funcionalidad, # así que hay que buscar a lo bestia... :-P :-( playlists = playlists_interface.GetPlaylists(0, playlists_count, 'CreationDate', True) # Buscando nuestra lista de reproducción a lo bestia... :-P i = 0 while i < playlists_count and playlists[i][1] != playlist_name: i += 1 if i < playlists_count: playlist_id = playlists[i][0] else: print >> stderr, u'Rhythmbox no cargó la lista correctamente.' return # Si se llega aquí, es que se encontró nuestra lista de reproducción # Detenemos cualquier reproducción previa para evitar mareadera :-P rhythmbox_player.Stop() # Activar la lista de reproducción como lista de reproducción actual playlists_interface.ActivatePlaylist(playlist_id) # Reproducir... :-) rhythmbox_player.Play()
# -*- coding: utf-8 -*- from os import environ from os.path import join, expanduser from dbus import SessionBus, Interface, glib from xdg.BaseDirectory import xdg_config_home, xdg_data_home SCRIBES_DBUS_SERVICE = "net.sourceforge.Scribes" SCRIBES_DBUS_PATH = "/net/sourceforge/Scribes" SCRIBES_SAVE_PROCESS_DBUS_SERVICE = "net.sourceforge.ScribesSaveProcess" SCRIBES_SAVE_PROCESS_DBUS_PATH = "/net/sourceforge/ScribesSaveProcess" session_bus = SessionBus() dbus_proxy_obj = session_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') dbus_iface = Interface(dbus_proxy_obj, 'org.freedesktop.DBus') home_folder = expanduser("~") from tempfile import gettempdir tmp_folder = gettempdir() folder_ = join(home_folder, "Desktop") from os.path import exists desktop_folder = folder_ if exists(folder_) else home_folder metadata_folder = config_folder = join(xdg_config_home, "scribes") print_settings_filename = join(metadata_folder, "ScribesPrintSettings.txt") home_plugin_folder = home_generic_plugin_folder = join(config_folder, "GenericPlugins") home_language_plugin_folder = join(config_folder, "LanguagePlugins") scribes_theme_folder = join(config_folder, "styles") storage_folder = join(config_folder, ".config") default_home_theme_folder = join(xdg_data_home, "gtksourceview-2.0", "styles") name = "scribes" prefix = "/usr" executable_path = join(prefix, "bin") data_path = "/usr/share"
class SystemdBus(object): def __init__(self, user=False): self.bus = SessionBus() if user else SystemBus() systemd = self.bus.get_object(SYSTEMD_BUSNAME, SYSTEMD_PATH) self.manager = Interface(systemd, dbus_interface=SYSTEMD_MANAGER_INTERFACE) def get_unit_active_state(self, unit): unit = self.manager.LoadUnit(unit) unit_object = self.bus.get_object(SYSTEMD_BUSNAME, unit) unit_properties = Interface(unit_object, DBUS_INTERFACE) return unit_properties.Get(SYSTEMD_UNIT_INTERFACE, 'ActiveState') def get_unit_field_state(self, unit, field): unit = self.manager.LoadUnit(unit) unit_object = self.bus.get_object(SYSTEMD_BUSNAME, unit) unit_properties = Interface(unit_object, DBUS_INTERFACE) return unit_properties.Get(SYSTEMD_UNIT_INTERFACE, field) def get_unit_load_state(self, unit): unit = self.manager.LoadUnit(unit) unit_object = self.bus.get_object(SYSTEMD_BUSNAME, unit) unit_properties = Interface(unit_object, DBUS_INTERFACE) return unit_properties.Get(SYSTEMD_UNIT_INTERFACE, 'LoadState') def reload(self): self.manager.Reload() # In [31]: manager.DisableUnitFiles(["zabbix-agent.service"], False) # Out[31]: dbus.Array([dbus.Struct((dbus.String(u'unlink'), dbus.String(u'/etc/systemd/system/multi-user. # target.wants/zabbix-agent.service'), dbus.String(u'')), signature=None)], signature=dbus.Signature('(sss)')) # In [33]: manager.EnableUnitFiles(["zabbix-agent.service"], False, True) # Out[33]: # (dbus.Boolean(True), # dbus.Array([dbus.Struct((dbus.String(u'symlink'), dbus.String(u'/etc/systemd/system/multi-user.target. # wants/zabbix-agent.service'), dbus.String(u'/usr/lib/systemd/system/zabbix-agent.service')), signature=None)], # signature=dbus.Signature('(sss)'))) def start_unit(self, unit): try: self.manager.StartUnit(unit, 'replace') return True except exceptions.DBusException: return False def stop_unit(self, unit): try: self.manager.StopUnit(unit, 'replace') return True except exceptions.DBusException: return False def restart_unit(self, unit): try: self.manager.RestartUnit(unit, 'replace') return True except exceptions.DBusException: return False def reload_unit(self, unit): try: self.manager.ReloadUnit(unit, 'replace') return True except exceptions.DBusException: return False def reload_or_restart_unit(self, unit): try: self.manager.ReloadOrRestartUnit(unit, 'replace') return True except exceptions.DBusException: return False
# -*- coding: utf-8 -*- from os import environ from os.path import join, expanduser from dbus import SessionBus, Interface, glib from xdg.BaseDirectory import xdg_config_home, xdg_data_home SCRIBES_DBUS_SERVICE = "net.sourceforge.Scribes" SCRIBES_DBUS_PATH = "/net/sourceforge/Scribes" SCRIBES_SAVE_PROCESS_DBUS_SERVICE = "net.sourceforge.ScribesSaveProcess" SCRIBES_SAVE_PROCESS_DBUS_PATH = "/net/sourceforge/ScribesSaveProcess" session_bus = SessionBus() dbus_proxy_obj = session_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') dbus_iface = Interface(dbus_proxy_obj, 'org.freedesktop.DBus') home_folder = expanduser("~") from tempfile import gettempdir tmp_folder = gettempdir() folder_ = join(home_folder, "Desktop") from os.path import exists desktop_folder = folder_ if exists(folder_) else home_folder metadata_folder = config_folder = join(xdg_config_home, "scribes") print_settings_filename = join(metadata_folder, "ScribesPrintSettings.txt") home_plugin_folder = home_generic_plugin_folder = join(config_folder, "GenericPlugins") home_language_plugin_folder = join(config_folder, "LanguagePlugins") scribes_theme_folder = join(config_folder, "styles") storage_folder = join(config_folder, ".config") default_home_theme_folder = join(xdg_data_home, "gtksourceview-2.0", "styles") name = "scribes" prefix = "/usr" executable_path = join(prefix, "bin") data_path = "/usr/share" library_path = "/usr/lib" sysconfdir = "/usr/etc"
#!/usr/bin/env python3 from argparse import ArgumentParser from dbus import Interface, SessionBus parser = ArgumentParser(description='wrapper DBus pour Spotify') parser.add_argument('action', nargs=1, choices=['play', 'pause', 'playpause', 'next', 'previous']) action = parser.parse_args().action[0] bus = SessionBus() proxy = bus.get_object('org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2') interface = Interface(proxy, dbus_interface='org.mpris.MediaPlayer2.Player') if action in ['pause', 'play']: # Workaround spotify’s bad implementation of Play… interface.Pause() if action in ['playpause', 'play']: interface.PlayPause() elif action == 'next': interface.Next() elif action == 'previous': interface.Previous()
def send(self, body, title='', notify_type=NotifyType.INFO, **kwargs): """ Perform DBus Notification """ if not self._enabled or MAINLOOP_MAP[self.schema] is None: self.logger.warning("{} notifications could not be loaded.".format( self.schema)) return False # Acquire our session session = SessionBus(mainloop=MAINLOOP_MAP[self.schema]) # acquire our dbus object dbus_obj = session.get_object( NOTIFY_DBUS_INTERFACE, NOTIFY_DBUS_SETTING_LOCATION, ) # Acquire our dbus interface dbus_iface = Interface( dbus_obj, dbus_interface=NOTIFY_DBUS_INTERFACE, ) # image path icon_path = None if not self.include_image \ else self.image_path(notify_type, extension='.ico') # Our meta payload meta_payload = {"urgency": Byte(self.urgency)} if not (self.x_axis is None and self.y_axis is None): # Set x/y access if these were set meta_payload['x'] = self.x_axis meta_payload['y'] = self.y_axis if NOTIFY_DBUS_IMAGE_SUPPORT and icon_path: try: # Use Pixbuf to create the proper image type image = GdkPixbuf.Pixbuf.new_from_file(icon_path) # Associate our image to our notification meta_payload['icon_data'] = (image.get_width(), image.get_height(), image.get_rowstride(), image.get_has_alpha(), image.get_bits_per_sample(), image.get_n_channels(), ByteArray(image.get_pixels())) except Exception as e: self.logger.warning( "Could not load Gnome notification icon ({}): {}".format( icon_path, e)) try: # Always call throttle() before any remote execution is made self.throttle() dbus_iface.Notify( # Application Identifier self.app_id, # Message ID (0 = New Message) 0, # Icon (str) - not used '', # Title str(title), # Body str(body), # Actions list(), # Meta meta_payload, # Message Timeout self.message_timeout_ms, ) self.logger.info('Sent DBus notification.') except Exception: self.logger.warning('Failed to send DBus notification.') self.logger.exception('DBus Exception') return False return True
class Client(GObject): (STATE_INITIALIZED, STATE_STATIONS_LOADED, STATE_CHANNELS_LOADED) = range(3) __gtype_name__ = 'WebRadioClient' __gsignals__ = { 'station-added': (SIGNAL_RUN_LAST, TYPE_NONE, (object,)), 'channel-added': (SIGNAL_RUN_LAST, TYPE_NONE, (object,)), 'state-changed': (SIGNAL_RUN_LAST, TYPE_NONE, ()), 'stream-tags-changed': (SIGNAL_RUN_LAST, TYPE_NONE, ()), } @staticmethod def decode_stream(uri, title, length): return Stream(uri, title, length) @classmethod def decode_channel(cls, station, uri, tags, streams): streams = [cls.decode_stream(*s) for s in streams] return Channel(station, uri, tags, streams) def __init__(self): super(Client, self).__init__() self.__stations = dict() self.__channels = dict() self.__stream_tags = dict() self.__current_channel = None self.__is_playing = False def register_channel(station, channel): if station: station.channels.append(channel) for stream in channel.streams: self.__channels[stream.uri] = channel self.__channels[channel.uri] = channel def station_added_cb(station): id, title, uri, channels = station station = Station(id, title, uri) for channel in channels: channel = self.decode_channel(station, *channel) register_channel(station, channel) self.__stations[station.id] = station self.emit('station-added', station) def channel_added_cb(station_id, channel): station = self.find_station(station_id) channel = self.decode_channel(station, *channel) register_channel(station, channel) self.emit('channel-added', channel) def state_changed_cb(playing, stream_uri): self.__stream_tags = self.__service.GetStreamTags() self.__current_channel = self.__channels.get(stream_uri) self.__is_playing = playing self.emit('state-changed') def stream_tags_changed_cb(tags): self.__stream_tags.update(tags) self.emit('stream-tags-changed') def name_owner_cb(new_owner): if not new_owner: # FIXME from gtk import main_quit main_quit() self.__bus = SessionBus() proxy = self.__bus.get_object(Service.name, '/') self.__bus.watch_name_owner(Service.name, name_owner_cb) self.__service = Interface(proxy, Service.interface) self.__service.connect_to_signal('StationAdded', station_added_cb) self.__service.connect_to_signal('ChannelAdded', channel_added_cb) self.__service.connect_to_signal('StateChanged', state_changed_cb) self.__service.connect_to_signal('StreamTagsChanged', stream_tags_changed_cb) for station in self.__service.GetStations(): station_added_cb(station) state_changed_cb(*self.__service.GetState()) def wait(self, stage=STATE_CHANNELS_LOADED): loop = MainLoop(None, True) def data_ready_cb(new_stage): if new_stage >= stage: loop.quit() self.__service.connect_to_signal('DataReady', data_ready_cb) if self.__service.GetDataStage() >= stage: loop.quit() progress_id = 0 if loop.is_running(): if sys.stdout.isatty(): progress = ['-\r', '\\\r', '|\r', '/\r'] def progress_cb(): c = progress.pop(0) sys.stdout.write(c) sys.stdout.flush() progress.append(c) return True progress_id = timeout_add(250, progress_cb) sys.stdout.write(' loading...\r') loop.run() if progress_id: source_remove(progress_id) sys.stdout.write('\r\033[K') sys.stdout.flush() def find_channels(self, query=[]): result = list() for station_id, channel in self.__service.Find(query): station = self.__stations.get(station_id) channel = self.decode_channel(station, *channel) result.append(channel) return result def find_station(self, id): return self.__stations.get(id) def get_stations(self): return self.__stations.values() def get_tags(self): return self.__service.GetTags() def play(self, channel): self.__service.Play(channel.streams[0].uri) def pause(self): self.__service.Pause() def resume(self): self.__service.Resume() def quit(self): self.__service.Quit() def get_equalizer_profiles(self): return self.__service.ListEqualizerProfiles() def __get_equalizer_profile(self): return self.__service.GetEqualizerProfile() def __set_equalizer_profile(self, value): self.__service.SetEqualizerProfile(value) is_playing = property(fget=lambda self: self.__is_playing) current_channel = property(fget=lambda self: self.__current_channel) stream_tags = property(fget=lambda self: self.__stream_tags) equalizer_profile = property(fget=__get_equalizer_profile, fset=__set_equalizer_profile)
class Client(GObject): (STATE_INITIALIZED, STATE_STATIONS_LOADED, STATE_CHANNELS_LOADED) = range(3) __gtype_name__ = 'WebRadioClient' __gsignals__ = { 'station-added': (SIGNAL_RUN_LAST, TYPE_NONE, (object, )), 'channel-added': (SIGNAL_RUN_LAST, TYPE_NONE, (object, )), 'state-changed': (SIGNAL_RUN_LAST, TYPE_NONE, ()), 'stream-tags-changed': (SIGNAL_RUN_LAST, TYPE_NONE, ()), } @staticmethod def decode_stream(uri, title, length): return Stream(uri, title, length) @classmethod def decode_channel(cls, station, uri, tags, streams): streams = [cls.decode_stream(*s) for s in streams] return Channel(station, uri, tags, streams) def __init__(self): super(Client, self).__init__() self.__stations = dict() self.__channels = dict() self.__stream_tags = dict() self.__current_channel = None self.__is_playing = False def register_channel(station, channel): if station: station.channels.append(channel) for stream in channel.streams: self.__channels[stream.uri] = channel self.__channels[channel.uri] = channel def station_added_cb(station): id, title, uri, channels = station station = Station(id, title, uri) for channel in channels: channel = self.decode_channel(station, *channel) register_channel(station, channel) self.__stations[station.id] = station self.emit('station-added', station) def channel_added_cb(station_id, channel): station = self.find_station(station_id) channel = self.decode_channel(station, *channel) register_channel(station, channel) self.emit('channel-added', channel) def state_changed_cb(playing, stream_uri): self.__stream_tags = self.__service.GetStreamTags() self.__current_channel = self.__channels.get(stream_uri) self.__is_playing = playing self.emit('state-changed') def stream_tags_changed_cb(tags): self.__stream_tags.update(tags) self.emit('stream-tags-changed') def name_owner_cb(new_owner): if not new_owner: # FIXME from gtk import main_quit main_quit() self.__bus = SessionBus() proxy = self.__bus.get_object(Service.name, '/') self.__bus.watch_name_owner(Service.name, name_owner_cb) self.__service = Interface(proxy, Service.interface) self.__service.connect_to_signal('StationAdded', station_added_cb) self.__service.connect_to_signal('ChannelAdded', channel_added_cb) self.__service.connect_to_signal('StateChanged', state_changed_cb) self.__service.connect_to_signal('StreamTagsChanged', stream_tags_changed_cb) for station in self.__service.GetStations(): station_added_cb(station) state_changed_cb(*self.__service.GetState()) def wait(self, stage=STATE_CHANNELS_LOADED): loop = MainLoop(None, True) def data_ready_cb(new_stage): if new_stage >= stage: loop.quit() self.__service.connect_to_signal('DataReady', data_ready_cb) if self.__service.GetDataStage() >= stage: loop.quit() progress_id = 0 if loop.is_running(): if sys.stdout.isatty(): progress = ['-\r', '\\\r', '|\r', '/\r'] def progress_cb(): c = progress.pop(0) sys.stdout.write(c) sys.stdout.flush() progress.append(c) return True progress_id = timeout_add(250, progress_cb) sys.stdout.write(' loading...\r') loop.run() if progress_id: source_remove(progress_id) sys.stdout.write('\r\033[K') sys.stdout.flush() def find_channels(self, query=[]): result = list() for station_id, channel in self.__service.Find(query): station = self.__stations.get(station_id) channel = self.decode_channel(station, *channel) result.append(channel) return result def find_station(self, id): return self.__stations.get(id) def get_stations(self): return self.__stations.values() def get_tags(self): return self.__service.GetTags() def play(self, channel): self.__service.Play(channel.streams[0].uri) def pause(self): self.__service.Pause() def resume(self): self.__service.Resume() def quit(self): self.__service.Quit() def get_equalizer_profiles(self): return self.__service.ListEqualizerProfiles() def __get_equalizer_profile(self): return self.__service.GetEqualizerProfile() def __set_equalizer_profile(self, value): self.__service.SetEqualizerProfile(value) is_playing = property(fget=lambda self: self.__is_playing) current_channel = property(fget=lambda self: self.__current_channel) stream_tags = property(fget=lambda self: self.__stream_tags) equalizer_profile = property(fget=__get_equalizer_profile, fset=__set_equalizer_profile)
class _ISkypeAPI(_ISkypeAPIBase): def __init__(self, handler, opts): _ISkypeAPIBase.__init__(self, opts) self.RegisterHandler(handler) self.skype_in = self.skype_out = self.dbus_name_owner_watch = None self.bus = opts.pop('Bus', None) try: mainloop = opts.pop('MainLoop') if self.bus is not None: raise TypeError( 'Bus and MainLoop cannot be used at the same time!') except KeyError: if self.bus is None: import dbus.mainloop.glib import gobject gobject.threads_init() dbus.mainloop.glib.threads_init() mainloop = dbus.mainloop.glib.DBusGMainLoop() self.mainloop = gobject.MainLoop() if self.bus is None: from dbus import SessionBus self.bus = SessionBus(private=True, mainloop=mainloop) if opts: raise TypeError('Unexpected parameter(s): %s' % ', '.join(opts.keys())) def run(self): self.DebugPrint('thread started') if hasattr(self, 'mainloop'): self.mainloop.run() self.DebugPrint('thread finished') def Close(self): if hasattr(self, 'mainloop'): self.mainloop.quit() self.skype_in = self.skype_out = None if self.dbus_name_owner_watch is not None: self.bus.remove_signal_receiver(self.dbus_name_owner_watch) self.dbus_name_owner_watch = None self.DebugPrint('closed') def SetFriendlyName(self, FriendlyName): self.FriendlyName = FriendlyName if self.skype_out: self.SendCommand(ICommand(-1, 'NAME %s' % FriendlyName)) def StartWatcher(self): self.dbus_name_owner_watch = self.bus.add_signal_receiver( self.dbus_name_owner_changed, 'NameOwnerChanged', 'org.freedesktop.DBus', 'org.freedesktop.DBus', '/org/freedesktop/DBus', arg0='com.Skype.API') def __Attach_ftimeout(self): self.wait = False def Attach(self, Timeout=30000, Wait=True): try: if not self.isAlive(): self.StartWatcher() self.start() except AssertionError: pass try: self.wait = True t = threading.Timer(Timeout / 1000.0, self.__Attach_ftimeout) if Wait: t.start() while self.wait: if not Wait: self.wait = False try: if not self.skype_out: self.skype_out = self.bus.get_object( 'com.Skype.API', '/com/Skype') if not self.skype_in: self.skype_in = _SkypeNotifyCallback( self.bus, self.notify) except dbus.DBusException: if not Wait: break time.sleep(1.0) else: break else: raise ISkypeAPIError('Skype attach timeout') finally: t.cancel() c = ICommand(-1, 'NAME %s' % self.FriendlyName, '', True, Timeout) if self.skype_out: self.SendCommand(c) if c.Reply != 'OK': self.skype_out = None self.SetAttachmentStatus(apiAttachRefused) return self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol)) self.SetAttachmentStatus(apiAttachSuccess) def IsRunning(self): try: self.bus.get_object('com.Skype.API', '/com/Skype') return True except dbus.DBusException: return False def Start(self, Minimized=False, Nosplash=False): # options are not supported as of Skype 1.4 Beta for Linux if not self.IsRunning(): import os if os.fork() == 0: # we're child os.setsid() os.execlp('skype') def Shutdown(self): import os from signal import SIGINT fh = os.popen('ps -o %p --no-heading -C skype') pid = fh.readline().strip() fh.close() if pid: os.kill(int(pid), SIGINT) self.skype_in = self.skype_out = None def SendCommand(self, Command): if not self.skype_out: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) self.DebugPrint('->', repr(com)) if Command.Blocking: Command._event = event = threading.Event() else: Command._timer = timer = threading.Timer(Command.Timeout / 1000.0, self.CommandsStackPop, (Command.Id, )) try: result = self.skype_out.Invoke(com) except dbus.DBusException, err: raise ISkypeAPIError(str(err)) if result.startswith(u'#%d ' % Command.Id): self.notify(result) if Command.Blocking: event.wait(Command.Timeout / 1000.0) if not event.isSet(): raise ISkypeAPIError('Skype command timeout') else: timer.start()
def __init__(self): session_bus = SessionBus() self.player_engine = session_bus.get_object(self.BANSHEE_OBJECT, self.PLAYER_ENGINE_NODE)
class _ISkypeAPI(_ISkypeAPIBase): def __init__(self, handler, opts): _ISkypeAPIBase.__init__(self, opts) self.RegisterHandler(handler) self.skype_in = self.skype_out = self.dbus_name_owner_watch = None self.bus = opts.pop('Bus', None) try: mainloop = opts.pop('MainLoop') if self.bus is not None: raise TypeError('Bus and MainLoop cannot be used at the same time!') except KeyError: if self.bus is None: import dbus.mainloop.glib import gobject gobject.threads_init() dbus.mainloop.glib.threads_init() mainloop = dbus.mainloop.glib.DBusGMainLoop() self.mainloop = gobject.MainLoop() if self.bus is None: from dbus import SessionBus self.bus = SessionBus(private=True, mainloop=mainloop) if opts: raise TypeError('Unexpected parameter(s): %s' % ', '.join(opts.keys())) def run(self): self.DebugPrint('thread started') if hasattr(self, 'mainloop'): self.mainloop.run() self.DebugPrint('thread finished') def Close(self): if hasattr(self, 'mainloop'): self.mainloop.quit() self.skype_in = self.skype_out = None if self.dbus_name_owner_watch is not None: self.bus.remove_signal_receiver(self.dbus_name_owner_watch) self.dbus_name_owner_watch = None self.DebugPrint('closed') def SetFriendlyName(self, FriendlyName): self.FriendlyName = FriendlyName if self.skype_out: self.SendCommand(ICommand(-1, 'NAME %s' % FriendlyName)) def StartWatcher(self): self.dbus_name_owner_watch = self.bus.add_signal_receiver(self.dbus_name_owner_changed, 'NameOwnerChanged', 'org.freedesktop.DBus', 'org.freedesktop.DBus', '/org/freedesktop/DBus', arg0='com.Skype.API') def __Attach_ftimeout(self): self.wait = False def Attach(self, Timeout=30000, Wait=True): try: if not self.isAlive(): self.StartWatcher() self.start() except AssertionError: pass try: self.wait = True t = threading.Timer(Timeout / 1000.0, self.__Attach_ftimeout) if Wait: t.start() while self.wait: if not Wait: self.wait = False try: if not self.skype_out: self.skype_out = self.bus.get_object('com.Skype.API', '/com/Skype') if not self.skype_in: self.skype_in = _SkypeNotifyCallback(self.bus, self.notify) except dbus.DBusException: if not Wait: break time.sleep(1.0) else: break else: raise ISkypeAPIError('Skype attach timeout') finally: t.cancel() c = ICommand(-1, 'NAME %s' % self.FriendlyName, '', True, Timeout) if self.skype_out: self.SendCommand(c) if c.Reply != 'OK': self.skype_out = None self.SetAttachmentStatus(apiAttachRefused) return self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol)) self.SetAttachmentStatus(apiAttachSuccess) def IsRunning(self): try: self.bus.get_object('com.Skype.API', '/com/Skype') return True except dbus.DBusException: return False def Start(self, Minimized=False, Nosplash=False): # options are not supported as of Skype 1.4 Beta for Linux if not self.IsRunning(): import os if os.fork() == 0: # we're child os.setsid() os.execlp('skype') def Shutdown(self): import os from signal import SIGINT fh = os.popen('ps -o %p --no-heading -C skype') pid = fh.readline().strip() fh.close() if pid: os.kill(int(pid), SIGINT) self.skype_in = self.skype_out = None def SendCommand(self, Command): if not self.skype_out: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) self.DebugPrint('->', repr(com)) if Command.Blocking: Command._event = event = threading.Event() else: Command._timer = timer = threading.Timer(Command.Timeout / 1000.0, self.CommandsStackPop, (Command.Id,)) try: result = self.skype_out.Invoke(com) except dbus.DBusException, err: raise ISkypeAPIError(str(err)) if result.startswith(u'#%d ' % Command.Id): self.notify(result) if Command.Blocking: event.wait(Command.Timeout / 1000.0) if not event.isSet(): raise ISkypeAPIError('Skype command timeout') else: timer.start()
class SystemTrayApp(QApplication): def __init__(self, args, read_pipe): QApplication.__init__(self, args) self.menu = None self.read_pipe = read_pipe self.fmt = "80s80sI32sI80sf" self.fmt_size = struct.calcsize(self.fmt) self.timer_active = False self.active_icon = False self.user_settings = UserSettings() self.user_settings.load() self.user_settings.debug() self.tray_icon = QSystemTrayIcon() pm = load_pixmap("hp_logo", "32x32") self.prop_icon = QIcon(pm) a = load_pixmap('active', '16x16') painter = QPainter(pm) painter.drawPixmap(32, 0, a) painter.end() self.prop_active_icon = QIcon(pm) self.tray_icon.setIcon(self.prop_icon) self.session_bus = SessionBus() self.service = None for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.tray_icon.setToolTip(self.__tr("HPLIP Status Service")) QObject.connect(self.tray_icon, SIGNAL("messageClicked()"), self.messageClicked) notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read) QObject.connect(notifier, SIGNAL("activated(int)"), self.notifierActivated) QObject.connect(self.tray_icon, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.trayActivated) signal.signal(signal.SIGINT, signal.SIG_DFL) self.tray_icon.show() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: self.tray_icon.setVisible(True) else: QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) # show icon for awhile @ startup self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True if "--ignore-update-firsttime" not in args: self.handle_hplip_updation() QTimer.singleShot(SET_MENU_DELAY, self.initDone) self.update_timer = QTimer() self.update_timer.connect(self.update_timer,SIGNAL("timeout()"),self.handle_hplip_updation) self.update_timer.start(UPGRADE_CHECK_DELAY) # Cleans the /var/log/hp/tmp directory #self.handle_hplip_clean() #self.clean_timer = QTimer() #self.clean_timer.connect(self.clean_timer,SIGNAL("timeout()"),self.handle_hplip_clean) #self.clean_timer.start(CLEAN_EXEC_DELAY) def initDone(self): self.tray_icon.setIcon(self.prop_icon) self.active_icon = False self.setMenu() def resetDevice(self): devices.clear() def addDevice(self, device_uri): try: devices[device_uri] except KeyError: devices[device_uri] = HistoryDevice(device_uri) else: devices[device_uri].needs_update = True def handle_hplip_clean(self): log.debug("handle_hplip_clean ") home_dir = sys_conf.get('dirs', 'home') cmd = 'sh %s/hplip_clean.sh'%home_dir os.system(cmd) def handle_hplip_updation(self): log.debug("handle_hplip_updation upgrade_notify =%d"%(self.user_settings.upgrade_notify)) path = utils.which('hp-upgrade') if self.user_settings.upgrade_notify is False: log.debug("upgrade notification is disabled in systray ") if path: path = os.path.join(path, 'hp-upgrade') log.debug("Running hp-upgrade: %s " % (path)) # this just updates the available version in conf file. But won't notify os.spawnlp(os.P_NOWAIT, path, 'hp-upgrade', '--check') time.sleep(5) try: os.waitpid(0, os.WNOHANG) except OSError: pass return current_time = time.time() if int(current_time) > self.user_settings.upgrade_pending_update_time: path = utils.which('hp-upgrade') if path: path = os.path.join(path, 'hp-upgrade') log.debug("Running hp-upgrade: %s " % (path)) os.spawnlp(os.P_NOWAIT, path, 'hp-upgrade', '--notify') time.sleep(5) else: log.error("Unable to find hp-upgrade --notify on PATH.") else: log.debug("upgrade schedule time is not yet completed. schedule time =%d current time =%d " %(self.user_settings.upgrade_pending_update_time, current_time)) try: os.waitpid(0, os.WNOHANG) except OSError: pass def setMenu(self): self.menu = QMenu() title = QWidgetAction(self.menu) #title.setDisabled(True) hbox = QFrame(self.menu) layout = QHBoxLayout(hbox) layout.setMargin(3) layout.setSpacing(5) pix_label = QLabel(hbox) layout.insertWidget(-1, pix_label, 0) icon_size = self.menu.style().pixelMetric(QStyle.PM_SmallIconSize) pix_label.setPixmap(self.prop_icon.pixmap(icon_size)) label = QLabel(hbox) layout.insertWidget(-1, label, 20) title.setDefaultWidget(hbox) label.setText(self.__tr("HPLIP Status Service")) f = label.font() f.setBold(True) label.setFont(f) self.menu.insertAction(None, title) if devices: if self.service is None: t = 0 while t < 3: try: self.service = self.session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") except dbus.DBusException: log.warn("Unable to connect to StatusService. Retrying...") t += 1 time.sleep(0.5) if self.service is not None: self.menu.addSeparator() for d in devices: devices[d].getHistory(self.service) menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index) self.menu.addMenu(menu) menu.update() self.menu.addSeparator() self.menu.addAction(self.__tr("HP Device Manager..."), self.toolboxTriggered) self.menu.addSeparator() self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')), self.__tr("Settings..."), self.settingsTriggered) self.menu.addSeparator() self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), "Quit", self.quitTriggered) self.tray_icon.setContextMenu(self.menu) def settingsTriggered(self): if self.menu is None: return self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING) # sys_conf cur_vers = sys_conf.get('hplip', 'version') self.user_settings.load() installed_time =time.strftime("%d-%m-%Y", time.localtime(self.user_settings.upgrade_last_update_time)) if utils.Is_HPLIP_older_version(cur_vers, self.user_settings.latest_available_version): if int(time.time()) < self.user_settings.upgrade_pending_update_time : postponed_time =time.strftime("%d-%m-%Y", time.localtime(self.user_settings.upgrade_pending_update_time)) upgrade_msg ="HPLIP-%s version was installed on %s.\n\nNew version of HPLIP-%s is available for upgrade. HPLIP upgrade is scheduled on %s." %(cur_vers,installed_time , self.user_settings.latest_available_version, postponed_time) elif self.user_settings.upgrade_last_update_time: upgrade_msg ="HPLIP-%s version was installed on %s.\n\nNew version of HPLIP-%s is available for upgrade." %(cur_vers,installed_time , self.user_settings.latest_available_version) else: upgrade_msg ="HPLIP-%s version was installed.\n\nNew version of HPLIP-%s is available for upgrade." %(cur_vers, self.user_settings.latest_available_version) elif self.user_settings.upgrade_last_update_time: upgrade_msg ="HPLIP-%s version was installed on %s."%(cur_vers, installed_time) else: upgrade_msg ="HPLIP-%s version was installed."%(cur_vers) try: dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible, self.user_settings.polling, self.user_settings.polling_interval, self.user_settings.systray_messages, self.user_settings.polling_device_list, self.user_settings.upgrade_notify, self.user_settings.upgrade_pending_update_time, self.user_settings.upgrade_last_update_time, upgrade_msg) if dlg.exec_() == QDialog.Accepted: self.user_settings.systray_visible = dlg.systray_visible self.user_settings.systray_messages = dlg.systray_messages self.user_settings.upgrade_notify = dlg.upgrade_notify log.debug("HPLIP update notification = %d"%(self.user_settings.upgrade_notify)) self.user_settings.save() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: log.debug("Showing...") self.tray_icon.setVisible(True) else: log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED) finally: self.sendMessage('', '', EVENT_DEVICE_START_POLLING) def timeoutHideWhenInactive(self): log.debug("Hiding...") if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): self.tray_icon.setVisible(False) log.debug("Hidden") def updateMenu(self): if self.menu is None: return for a in self.menu.actions(): try: a.menu().update() except AttributeError: continue def trayActivated(self, reason): if reason == QSystemTrayIcon.Context: self.updateMenu() elif reason == QSystemTrayIcon.DoubleClick: #print "double click" self.toolboxTriggered() pass elif reason == QSystemTrayIcon.Trigger: #print "single click" pass elif reason == QSystemTrayIcon.MiddleClick: #print "middle click" pass def messageClicked(self): #print "\nPARENT: message clicked" pass def quitTriggered(self): log.debug("Exiting") self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT) self.quit() del self.tray_icon def toolboxTriggered(self): try: os.waitpid(-1, os.WNOHANG) except OSError: pass # See if it is already running... ok, lock_file = utils.lock_app('hp-toolbox', True) if ok: # able to lock, not running... utils.unlock(lock_file) path = utils.which('hp-toolbox') if path: path = os.path.join(path, 'hp-toolbox') else: self.tray_icon.showMessage(self.__tr("HPLIP Status Service"), self.__tr("Unable to locate hp-toolbox on system PATH."), QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY) log.error("Unable to find hp-toolbox on PATH.") return #log.debug(path) log.debug("Running hp-toolbox: hp-toolbox") os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox') else: # ...already running, raise it self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface='com.hplip.Toolbox') def sendMessage(self, device_uri, printer_name, event_code, username=prop.username, job_id=0, title='', pipe_name='', interface='com.hplip.StatusService'): #device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(SessionBus(), interface) device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface) def notifierActivated(self, s): m = '' while True: try: r, w, e = select.select([self.read_pipe], [], [self.read_pipe], 1.0) except select.error: log.debug("Error in select()") break if e: log.error("Pipe error: %s" % e) break if r: #m = ''.join([m, os.read(self.read_pipe, self.fmt_size)]) m = os.read(self.read_pipe, self.fmt_size) while len(m) >= self.fmt_size: event = device.Event(*[x.rstrip(b'\x00').decode('utf-8') if isinstance(x, bytes) else x for x in struct.unpack(self.fmt, m[:self.fmt_size])]) m = m[self.fmt_size:] if event.event_code == EVENT_CUPS_QUEUES_REMOVED or event.event_code == EVENT_CUPS_QUEUES_ADDED: self.resetDevice() for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.setMenu() if event.event_code == EVENT_USER_CONFIGURATION_CHANGED: log.debug("Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)") self.user_settings.load() self.user_settings.debug() elif event.event_code == EVENT_SYSTEMTRAY_EXIT: self.quit() return if self.user_settings.systray_visible in \ (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE): log.debug("Showing...") self.tray_icon.setVisible(True) if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True continue elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE: if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False continue elif event.event_code == EVENT_DEVICE_UPDATE_BLIP: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(BLIP_DELAY, self.blipTimeout) continue if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) if event.event_code <= EVENT_MAX_USER_EVENT or \ event.event_code == EVENT_CUPS_QUEUES_REMOVED or event.event_code == EVENT_CUPS_QUEUES_ADDED: if event.event_code != EVENT_CUPS_QUEUES_REMOVED: self.addDevice(event.device_uri) self.setMenu() if self.tray_icon.supportsMessages(): log.debug("Tray icon message:") event.debug() error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR) desc = device.queryString(event.event_code) show_message = False if self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ALL: # OK, Busy show_message = True elif self.user_settings.systray_messages in (SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS, SYSTRAY_MESSAGES_SHOW_ERRORS_ONLY): if error_state == ERROR_STATE_ERROR: show_message = True elif self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS and \ error_state in (ERROR_STATE_WARNING, ERROR_STATE_LOW_SUPPLIES, ERROR_STATE_LOW_PAPER): show_message = True if event.printer_name: d = QString(event.printer_name) else: back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ device.parseDeviceURI(event.device_uri) if bus == 'usb': idd = serial elif bus == 'net': idd = host elif bus == 'par': idd = dev_file else: idd = 'unknown' self.model = models.normalizeModelUIName(model) if back_end == 'hp': d = self.__tr("%s Printer (%s)"%(model,idd)) elif back_end == 'hpaio': d = self.__tr("%s Scanner (%s)"%(model,idd)) elif back_end == 'hpfax': d = self.__tr("%s Fax (%s)"%(model,idd)) else: d = self.__tr("%s (%s)"%(model,idd)) if show_message: if have_pynotify and pynotify.init("hplip"): # Use libnotify/pynotify icon, urgency = ERROR_STATE_TO_ICON_AND_URGENCY_PYNOTIFY.get(error_state, (getPynotifyIcon('info'), pynotify.URGENCY_NORMAL)) if event.job_id and event.title: msg = "%s\n%s: %s\n(%s/%s)" % (to_unicode(d), desc, event.title, event.username, event.job_id) log.debug("Notify: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) else: msg = "%s\n%s (%s)" % (to_unicode(d), desc, event.event_code) log.debug("Notify: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) n = pynotify.Notification("HPLIP Device Status", msg, icon) # CRID: 11833 Debian Traceback error notification exceeded n.set_hint('transient', True) n.set_urgency(urgency) if error_state == ERROR_STATE_ERROR: n.set_timeout(pynotify.EXPIRES_NEVER) else: n.set_timeout(TRAY_MESSAGE_DELAY) n.show() else: # Use "standard" message bubbles icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information) if event.job_id and event.title: log.debug("Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), QString("%s\n%s: %s\n(%s/%s)"%(d,desc, event.title,event.username,event.job_id)), icon, TRAY_MESSAGE_DELAY) else: log.debug("Bubble: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), QString("%s\n%s (%s)"%(d,desc,event.event_code)), icon, TRAY_MESSAGE_DELAY) else: break def blipTimeout(self): if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False def __tr(self, s, c=None): return QApplication.translate("SystemTray", s, c, QApplication.UnicodeUTF8)
#!/usr/bin/env python from dbus import SessionBus, Interface bus = SessionBus() mpris_obj = bus.get_object('org.gnome.Rhythmbox3', '/org/mpris/MediaPlayer2') rb_plm_obj = bus.get_object('org.gnome.Rhythmbox3', '/org/gnome/Rhythmbox3/PlaylistManager') mpris_introspectable = Interface(mpris_obj, 'org.freedesktop.DBus.Introspectable') rb_plm_introspectable = Interface(rb_plm_obj, 'org.freedesktop.DBus.Introspectable') with open('org.mpris.MediaPlayer2.rhythmbox.xml', 'w') as mpris_xml: print >> mpris_xml, mpris_introspectable.Introspect() with open('org.gnome.Rhythmbox3.PlaylistManager.xml', 'w') as rb_plm_xml: print >> rb_plm_xml, rb_plm_introspectable.Introspect()