def post_config_hook(self): if self.user: bus = SessionBus() else: bus = SystemBus() systemd = bus.get("org.freedesktop.systemd1") self.systemd_unit = bus.get(".systemd1", systemd.LoadUnit(self.unit))
def _init_dbus(self): """ Get the device id """ _bus = SessionBus() if self.device_id is None: self.device_id = self._get_device_id(_bus) if self.device_id is None: return False try: self._dev = _bus.get(SERVICE_BUS, DEVICE_PATH + f"/{self.device_id}") try: self._bat = _bus.get( SERVICE_BUS, DEVICE_PATH + f"/{self.device_id}" + BATTERY_SUBPATH) self._not = _bus.get( SERVICE_BUS, DEVICE_PATH + f"/{self.device_id}" + NOTIFICATIONS_SUBPATH, ) except Exception: # Fallback to the old version self._bat = None self._not = None except Exception: return False return True
def main(args): bus = SessionBus() loop = GLib.MainLoop() def new_wallpaper(): wg.NewWallpaper(args.type, args.subreddit, args.directory, args.output, args.generate_only) if args.dbus: bus.publish('de.thm.mni.mhpp11.WallGen', WallGenDBUSService(loop)) run(loop) else: try: wg = bus.get('de.thm.mni.mhpp11.WallGen') except GLib.Error: wg = WallGenDBUSService(None) if type(wg) != WallGenDBUSService: if args.monitor: dc = bus.get('org.gnome.Mutter.DisplayConfig') with wg.Closed.connect(loop.quit): with dc.MonitorsChanged.connect(new_wallpaper): run(loop) elif args.quit: wg.Close() if not args.monitor: new_wallpaper() elif type(wg) == WallGenDBUSService: raise Exception("Monitoring is not possible without DBus service!")
class SystemdSession(object): def __init__(self): self.session_bus = SessionBus() self.systemd = self.session_bus.get('org.freedesktop.systemd1') def get_unit(self, name): unit_object = self.systemd.LoadUnit(name) return SystemdUnit(name, self.session_bus.get('.systemd1', unit_object), self.systemd)
def main(): LOG_FOLDER = sys.argv[1] try: DBUS_INTERFACE = sys.argv[2] except IndexError: DBUS_INTERFACE = 'org.gnome.ScreenSaver' STARTUP_TIME = datetime.now() logging.getLogger().setLevel(logging.INFO) loop = GLib.MainLoop() bus = SessionBus() try: dev = bus.get(DBUS_INTERFACE) except ValueError: logging.error( "Failed opening D-Bus interface '{}'\nexiting ...".format( DBUS_INTERFACE)) sys.exit(1) handler = create_event_handler(LOG_FOLDER, STARTUP_TIME) try: with dev.ActiveChanged.connect(handler) as bus_ses: logging.info("Succesfully registered handler for D-Bus event '{}' " "on interface '{}'".format('ActiveChanged', DBUS_INTERFACE)) loop.run() except AttributeError as e: logging.error("Failed registering handler for D-Bus event '{}' " "on interface '{}' ({})\nexiting ...".format( 'ActiveChanged', DBUS_INTERFACE, e)) sys.exit(1)
def __init__(self): super(GUI, self).__init__(application_id=APPLICATION_ID, flags=Gio.ApplicationFlags.FLAGS_NONE) self.builder = Gtk.Builder() self.builder.set_application(self) self.builder.add_from_file(GUI_GLADE_PATH) signals = { "on_volume_changed": self.on_volume_changed, "on_streaming_activate": self.on_streaming_activate, "on_streaming_refresh": self.on_streaming_refresh, "on_web_page_activate": self.on_web_page_activate, "on_web_page_refresh": self.on_web_page_refresh, "on_blur_radius_changed": self.on_blur_radius_changed } self.builder.connect_signals(signals) self.window = None self.local_video_icon_view = None self.local_video_list = None self.is_autostart = os.path.isfile(AUTOSTART_DESKTOP_PATH) bus = SessionBus() try: self.server = bus.get(DBUS_NAME) except GLib.Error: dialog = Gtk.MessageDialog( text="Oops!", message_type=Gtk.MessageType.ERROR, secondary_text="Couldn't connect to server", buttons=Gtk.ButtonsType.OK) dialog.run() dialog.destroy() print("Error: Couldn't connect to server")
def notify(message): try: bus = SessionBus() notifier = bus.get(".Notifications") notifier.Notify("home.py", 0, "", "My backup", message, "", "", 10000) except GLib.Error: pass
def NewWallpaper(self, type, subreddit, directory, output, generate_only): print("Create a new Wallpaper...") bus = SessionBus() dc = bus.get('org.gnome.Mutter.DisplayConfig') if type == 'reddit': generator = reddit_generator option = subreddit else: generator = local_generator option = directory active_monitors = [] for monitor in dc.GetResources()[1]: if monitor[6] > -1: active_monitors.append(monitor) (max_width, max_height) = get_maximum_resolution(active_monitors) with Image(width=max_width, height=max_height) as wallpaper: for monitor in active_monitors: image = generator.get_image(option, width=monitor[4], height=monitor[5]) wallpaper.composite(image, left=monitor[2], top=monitor[3]) with wallpaper.convert('png') as converted: save(converted, output, generate_only)
def spotibus_connect(): """ The DBUS INTERFACE with the Spotify Desktop client. You can browse it also by command line tool: $ mdbus2 org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 (bool) """ global spotibus spotibus = None tries = 3 while tries: try: # SessionBus will work if D-Bus has an available X11 $DISPLAY bus = SessionBus() spotibus = bus.get( 'org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2' ) logging.info(f'spotibus OK') return True except Exception as e: logging.info(f'spotibus FAILED: {e}') tries -= 1 sleep(.1) return False
class DbusHooks(hooks_base_class): def __init__(self): super().__init__() self._bus = SessionBus() self._bot = None self._log = PladderLogProxy(self._bus) def on_trigger(self, timestamp, network, channel, sender, text): retry = True while True: try: if self._bot is None: self._bot = self._bus.get("se.raek.PladderBot") return self._bot.RunCommand(timestamp, network, channel, sender.nick, text) except GLib.Error as e: if "org.freedesktop.DBus.Error.ServiceUnknown" in str(e): if retry: retry = False self._bot = None continue else: self._bot = None return "Internal error: could not reach pladder-bot. Please check the log: \"journalctl --user-unit pladder-bot.service -e\"" else: logger.error(str(e)) return "Internal error: " + str(e) def on_privmsg(self, timestamp, network, channel, sender, text): self._log.AddLine(timestamp, network, channel, sender.nick, text) def on_send_privmsg(self, timestamp, network, channel, nick, text): self._log.AddLine(timestamp, network, channel, nick, text)
def send_desktop_notification(title="Hello World", msg="pydbus works!"): """Send a notification to the desktop environment to display""" bus = SessionBus() notifications = bus.get('.Notifications') notifications.Notify('test', 0, 'dialog-information', title, msg, [], {}, 5000)
def main(): parser = argparse.ArgumentParser() parser.add_argument( "--dbus", action="store_true", help= "Connect to existing pladder-bot service instead of running command directly." ) parser.add_argument("--state-dir", help="Directory where bot keeps its state") parser.add_argument( "-c", "--command", help="Run this command instead of reading commands from stdin.") args = parser.parse_args() if args.dbus: from pydbus import SessionBus # type: ignore bus = SessionBus() bot = bus.get("se.raek.PladderBot") run_commands(bot, args.command) else: from pladder.bot import PladderBot, load_standard_plugins state_dir = args.state_dir or default_state_dir() with PladderBot(state_dir, None) as bot: load_standard_plugins(bot) run_commands(bot, args.command)
def start(): args = parse_arguments() config = Config() if not config.is_supported_desktop(): raise Exception('Desktop environment not supported.') bus = SessionBus() loop = GLib.MainLoop() if args.dbus: bus.publish('de.thm.mni.mhpp11.WallGen', WallGenDBUSService(loop)) run(loop) else: try: wg = bus.get('de.thm.mni.mhpp11.WallGen') except GLib.Error: wg = WallGenDBUSService(None) if type(wg) != WallGenDBUSService: if args.monitor: dc = None if config.is_gnome(): dc = bus.get('org.gnome.Mutter.DisplayConfig') elif config.is_kde(): dc = bus.get('org.kde.KScreen', object_path='/backend') with wg.Closed.connect(loop.quit): if config.is_gnome(): with dc.MonitorsChanged.connect(wg.NewWallpaper): run(loop) elif config.is_kde(): class KDENewWallpaper: first_call = True def call(self, _): if (self.first_call): wg.NewWallpaper() self.first_call = not self.first_call with dc.configChanged.connect(KDENewWallpaper().call): run(loop) elif args.quit: wg.Close() elif type(wg) == WallGenDBUSService and args.monitor: raise Exception("Monitoring is not possible without DBus service!") if not args.monitor and not args.quit: wg.NewWallpaper()
def _get_spotify_proxy(): bus = SessionBus() try: proxy = bus.get('org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2') return proxy except Exception: return None
def trigger(self) -> None: """ Sends a system notification """ bus = SessionBus() notifications = bus.get('.Notifications') notifications.Notify('cwp', 0, 'dialog-information', self.title, self.text, [], {}, self.mstime)
def __init__(self): session_bus = SessionBus() self.player = session_bus.get( self.PLAYERCTLD_BUS, self.MEDIA_PLAYER_PATH, ) self.was_playing = self.player.PlaybackStatus
def _get_session_bus(self): bus = SessionBus() try: proxy = bus.get('org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2') return proxy except Exception as e: log.info('Failed to load session bus: %s', str(e)) raise SpotifyError('Spotify is not running')
def __init__(self, bus_instance=None): if DBusNightLightManager._instance is None: DBusNightLightManager._instance = self if self.dbus_color_service is None: if bus_instance is None: bus_instance = SessionBus() self.dbus_color_service = bus_instance.get( 'org.gnome.SettingsDaemon.Color', '/org/gnome/SettingsDaemon/Color') self.dbus_color_service.onPropertiesChanged = self.processNightLightInvocation
def disable(settings, **kwargs): try: bus = SessionBus() systemd = bus.get(".systemd1") if systemd.DisableUnitFiles(["rammon.service"], False): print("Disabled rammon, it will no longer auto-start") sys.exit(0) except GError: pass print("Rammon is already disabled") sys.exit(1)
def __wait_dbus_object(self): bus = SessionBus() while True: try: os.waitpid(self.__pid, os.P_NOWAIT) except OSError: raise RuntimeError('KTimeTracker process stopped unexpectedly') try: return bus.get('org.kde.ktimetracker', '/KTimeTracker') except GLib.Error: time.sleep(0.5)
def info(self): tod_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(start_time)) message_string = ("Wheel circumference: {} meters\n" "Start time: {}\n" "GPIO Channel Number: {}".format( wheel_circumference, tod_time, channel)) bus_1 = SessionBus() notifications = bus_1.get('.Notifications') notifications.Notify('test', 0, 'dialog-information', "Pydbus Server Information", message_string, [], {}, 5000)
def notify(self, *args, **kwargs) -> None: """ :return: """ from pydbus import SessionBus Logger.debug(f'Application: notify({args} {kwargs})') bus = SessionBus() notifications = bus.get('.Notifications') notifications.Notify(NOTIFICATION_APP, self.msg_id, self.icon, self.summary, self.msg, [], {}, 5000)
def main(): """ Entry point for this script. """ # Get mpris2 bus = SessionBus() mpris = bus.get("org.mpris.MediaPlayer2.clementine", "/org/mpris/MediaPlayer2") if mpris is None or mpris.Metadata is None: sys.exit(1) # Get metadata md = mpris.Metadata status = mpris.PlaybackStatus.strip().lower() if status is None or mpris.Position is None: sys.exit(0) # Parse metadata statusIcons = {'paused': u'\uf04c', 'playing': u'\uf04b', 'stopped': u'\uf04d'} status = statusIcons[status] if status in statusIcons else '?' artist = md.get("xesam:artist") album = md.get("xesam:album") track = md.get("xesam:title") bitrate = md.get("bitrate") if artist is None: artist = "Unknown Artist" elif isinstance(artist, list) and artist: artist = artist[0] album = album if album is not None else "Unknown Album" track = track if track is not None else "Unknown Track" # Build result string icons = f'\uf025 {status} ' result = f'{artist} - {album} - {track}' if bitrate is not None: result = f'{result} @ {bitrate} kbps' # Apply scroll effect based on the time and print result pos = mpris.Position posSeconds = (float(pos) / 1000000.0) strPos = int(posSeconds * ScrollFactor) % len(result) result = result[strPos:] + " " + result[0:strPos] print(icons + result[:MaxCharacters]) return 0
def main(args): bus = SessionBus() gmusic = bus.get('org.gmusicbrowser') pos = gmusic.GetPosition() if pos < 10: gmusic.RunCommand("PrevSong") else: gmusic.RunCommand("Rewind(20)") return 0
def main(): parser = argparse.ArgumentParser() parser.add_argument('param', type=int, help="Size in bytes to send to server") args = parser.parse_args() bus = SessionBus() server_proxy = bus.get('com.nstack.DbusTest') print("Sending ping - {}".format(args.param)) output = server_proxy.Ping(bytes(args.param)) print("Received pong - {}".format(output)) return 0
def execute_commands(command_list): """Executes the commands in the command list. **DANGER** This is VERY unsafe, as it passing the strings directly to `exec`""" from pydbus import SessionBus bus = SessionBus() Layout = bus.get(bus_name="org.way-cooler", object_path="/org/way_cooler/Layout") for command in command_list: print("Executing command: \"{}\"".format(command)) sleep(1) exec(command)
def info(self): tod_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(start_time)) message_string = ("Wheel circumference: {} meters\n" "Start time: {}\n" "GPIO Channel Number: {}" .format(wheel_circumference, tod_time, channel)) bus_1 = SessionBus() notifications = bus_1.get('.Notifications') notifications.Notify('test', 0, 'dialog-information', "Pydbus Server Information", message_string, [], {}, 5000)
def test_user_facing_interface(self): from pydbus import SessionBus import os import sys import time ppath = os.path.abspath( os.path.dirname(os.path.abspath(sys.modules[__name__].__file__)) + "/..") os.system('export PYTHONPATH="' + ppath + '";cd ' + ppath + ";" + sys.executable + " -m tests.unittest_server&") #print(ppath) sb = SessionBus() tick = time.time() + 30 test_server = None while time.time() < tick: try: test_server = sb.get('pydbus.unittest', timeout=10) break except: time.sleep(1) pass self.assertIsNotNone(test_server) r = test_server.NoArgsStringReply() self.assertEqual(r, 0, "Translation Inactive") r = test_server.AddTwo(2) self.assertEqual(r, 4, "Translation Inactive") test_server = sb.get('pydbus.unittest', translation_spec=True, timeout=10) r = test_server.NoArgsStringReply() self.assertEqual(r, "first string", "Translation Active") r = test_server.AddTwo(2) self.assertEqual(r, 4, "Translation Active") test_server.Quit()
def set_up_dbus(hooks_base_class): from gi.repository import GLib from pydbus import SessionBus bus = SessionBus() bot = bus.get("se.raek.PladderBot") class DbusHooks(hooks_base_class): def on_trigger(self, sender, text): try: return bot.RunCommand(text) except GLib.Error as e: logger.error(str(e)) return "Oops! Error logged." return DbusHooks
def hibernate(): try: bus = SessionBus() power = bus.get('org.gnome.PowerManager', '/org/gnome/PowerManager') if power.CanHibernate(): answer = input("Do you want to hibernate? [Y/n]:") if answer.lower() == "y": power.Hibernate() else: print("Cannot hibernate") except Exception as ex: print("Could not get PowerManager from DBUS") print(str(ex))
def enable(**kwargs): os.umask(0o077) rammon_path = shutil.which("rammon") if rammon_path is None: print( "Could not find rammon in $PATH, this likely means it is installed in a virtualenv.\n" "Try leaving the virtualenv and installing with:\n" " pip3 install --user rammon") sys.exit(1) if shutil.which("systemctl") is None: print( "Your system doesn't appear to be using systemd and is not currently supported.\n" "If you are interested in support for other init systems, please open an issue " "on Github.") sys.exit(1) rammon_unit_path = os.path.expanduser( "~/.local/share/systemd/user/rammon.service") os.makedirs(os.path.dirname(rammon_unit_path), exist_ok=True) if not os.path.exists(rammon_unit_path): print("Creating systemd unit at:\n" " ~/.local/share/systemd/user/rammon.service") with open(rammon_unit_path, "w") as f: f.write(f"""[Unit] Description=Memory usage monitor and notification daemon [Service] Type=simple TimeoutStartSec=0 TimeoutStopSec=1 ExecStart={rammon_path} -d Environment=LAUNCHED_FROM_SYSTEMD=1 Restart=on-failure RestartSec=20 [Install] WantedBy=default.target """) bus = SessionBus() systemd = bus.get(".systemd1") if systemd.GetUnitFileState("rammon.service") == "enabled": print("Rammon auto-start is already enabled") sys.exit(1) if systemd.EnableUnitFiles(["rammon.service"], False, False)[0]: print("Rammon enable and will now start on login!") else: print("Rammon failed to be enabled and I don't know why...\n" "Try enabling it manually with:\n" " systemctl enable --user rammon")
def _init_dbus(self): """ Get the device id """ _bus = SessionBus() if self.device_id is None: self.device_id = self._get_device_id(_bus) if self.device_id is None: return False try: self._dev = _bus.get(SERVICE_BUS, DEVICE_PATH + "/%s" % self.device_id) except Exception: return False return True
done += 1 if done == 2: loop.quit() return "M1" def Method2(self): global done done += 1 if done == 2: loop.quit() return "M2" bus = SessionBus() with bus.publish("net.lew21.pydbus.tests.expose_multiface", TestObject()): remote = bus.get("net.lew21.pydbus.tests.expose_multiface") def t1_func(): print(remote.Method1()) print(remote.Method2()) t1 = Thread(None, t1_func) t1.daemon = True def handle_timeout(): print("ERROR: Timeout.") sys.exit(1) GLib.timeout_add_seconds(2, handle_timeout) t1.start()
#!/usr/bin/python3 import os import sys import datetime import json import subprocess from time import sleep from pydbus import SessionBus from glob import glob BUS = SessionBus() LAYOUT = BUS.get(bus_name='org.way-cooler', object_path='/org/way_cooler/Layout') def main(): while True: layout = json.loads(LAYOUT.Debug()) workspaces = get_workspaces(layout) workspaces.sort() active_workspace = "" try: active_workspace = LAYOUT.ActiveWorkspace() except Exception: pass workspaces = " ".join(workspaces) workspaces = format_workspaces(layout, workspaces, active_workspace) funcs = [workspaces + "%{c}", lambda: get_time() + "%{r}", my_get_temp,
def __init__(self, bucket, loop, *args, **kargs): self.bucket = bucket self.loop = loop self.running = True self._stop = threading.Event() self.queue = Queue.Queue(10) # NOTE: enumerate req to iterate through tuple and find GVariant @trace def player_cb(*args, **kwargs): if SCARLETT_DEBUG: logger.debug("player_cb PrettyPrinter: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(args) for i, v in enumerate(args): if SCARLETT_DEBUG: logger.debug("Type v: {}".format(type(v))) logger.debug("Type i: {}".format(type(i))) if type(v) is gi.overrides.GLib.Variant: if SCARLETT_DEBUG: logger.debug( "THIS SHOULD BE A Tuple now: {}".format(v)) msg, scarlett_sound = v logger.warning(" msg: {}".format(msg)) logger.warning( " scarlett_sound: {}".format(scarlett_sound)) # NOTE: Create something like test_gdbus_player.ScarlettPlayer('pi-listening') # NOTE: test_gdbus_player.ScarlettPlayer # NOTE: self.bucket.put() # NOTE: ADD self.queue.put(v) # NOTE: enumerate req to iterate through tuple and find GVariant @trace def command_cb(*args, **kwargs): if SCARLETT_DEBUG: logger.debug("player_cb PrettyPrinter: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(args) for i, v in enumerate(args): if SCARLETT_DEBUG: logger.debug("Type v: {}".format(type(v))) logger.debug("Type i: {}".format(type(i))) if type(v) is gi.overrides.GLib.Variant: if SCARLETT_DEBUG: logger.debug( "THIS SHOULD BE A Tuple now: {}".format(v)) msg, scarlett_sound, command = v logger.warning(" msg: {}".format(msg)) logger.warning( " scarlett_sound: {}".format(scarlett_sound)) logger.warning(" command: {}".format(command)) # NOTE: Create something like test_gdbus_player.ScarlettPlayer('pi-listening') # NOTE: test_gdbus_player.ScarlettPlayer # NOTE: self.bucket.put() # NOTE: ADD self.queue.put(v) # with SessionBus() as bus: bus = SessionBus() ss = bus.get("org.scarlett", object_path='/org/scarlett/Listener') # SttFailedSignal / player_cb ss_failed_signal = bus.con.signal_subscribe(None, "org.scarlett.Listener", "SttFailedSignal", '/org/scarlett/Listener', None, 0, player_cb) # ListenerReadySignal / player_cb ss_rdy_signal = bus.con.signal_subscribe(None, "org.scarlett.Listener", "ListenerReadySignal", '/org/scarlett/Listener', None, 0, player_cb) # KeywordRecognizedSignal / player_cb ss_kw_rec_signal = bus.con.signal_subscribe(None, "org.scarlett.Listener", "KeywordRecognizedSignal", '/org/scarlett/Listener', None, 0, player_cb) # CommandRecognizedSignal /command_cb ss_cmd_rec_signal = bus.con.signal_subscribe(None, "org.scarlett.Listener", "CommandRecognizedSignal", '/org/scarlett/Listener', None, 0, command_cb) # ListenerCancelSignal / player_cb ss_cancel_signal = bus.con.signal_subscribe(None, "org.scarlett.Listener", "ListenerCancelSignal", '/org/scarlett/Listener', None, 0, player_cb) # NOTE: print dir(ss) # NOTE: # Quit mainloop # NOTE: self.quit = ss.quit() # NOTE: # let listener know when we connect to it # NOTE: self._tasker_connected = ss.emitConnectedToListener("{}".format( # NOTE: # self._tasker_connected(ScarlettTasker().__class__.__name__))) logger.debug("ss PrettyPrinter: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(ss)
def __init__(self, id): self.id = id def HelloWorld(self, a, b): res = self.id + ": " + a + str(b) global done done += 1 if done == 2: loop.quit() print(res) return res bus = SessionBus() with bus.publish("net.lew21.pydbus.Test", TestObject("Main"), ("Lol", TestObject("Lol"))): remoteMain = bus.get("net.lew21.pydbus.Test") remoteLol = bus.get("net.lew21.pydbus.Test", "Lol") def t1_func(): print(remoteMain.HelloWorld("t", 1)) def t2_func(): print(remoteLol.HelloWorld("t", 2)) t1 = Thread(None, t1_func) t2 = Thread(None, t2_func) t1.daemon = True t2.daemon = True def handle_timeout(): print("ERROR: Timeout.")
<property name="Bar" type="s" access="write"/> <method name='Quit'/> </interface> </node> ''' def __init__(self): self.Foo = "foo" self.Foobar = "foobar" def Quit(self): loop.quit() bus = SessionBus() with bus.publish("net.lew21.pydbus.tests.publish_properties", TestObject()): remote = bus.get("net.lew21.pydbus.tests.publish_properties") remote_iface = remote['net.lew21.pydbus.tests.publish_properties'] def t1_func(): for obj in [remote, remote_iface]: assert(obj.Foo == "foo") assert(obj.Foobar == "foobar") obj.Foobar = "barfoo" assert(obj.Foobar == "barfoo") obj.Foobar = "foobar" assert(obj.Foobar == "foobar") obj.Bar = "rab" remote.Foobar = "barfoo" try:
def __init__(self, *args): _IdleObject.__init__(self) context = GObject.MainContext.default() self.bucket = bucket = Queue.Queue() # NOQA self.hello = None # with SessionBus() as bus: bus = SessionBus() ss = bus.get("org.scarlett", object_path='/org/scarlett/Listener') # NOQA time.sleep(1) ss_failed_signal = bus.subscribe(sender=None, iface="org.scarlett.Listener", signal="SttFailedSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=player_cb) ss_rdy_signal = bus.subscribe(sender=None, iface="org.scarlett.Listener", signal="ListenerReadySignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=player_cb) ss_kw_rec_signal = bus.subscribe(sender=None, iface="org.scarlett.Listener", signal="KeywordRecognizedSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=player_cb) ss_cmd_rec_signal = bus.subscribe(sender=None, iface="org.scarlett.Listener", signal="CommandRecognizedSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=command_cb) ss_cancel_signal = bus.subscribe(sender=None, iface="org.scarlett.Listener", signal="ListenerCancelSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=player_cb) pp.pprint((ss_failed_signal, ss_rdy_signal, ss_kw_rec_signal, ss_cmd_rec_signal, ss_cancel_signal)) logger.debug("ss_failed_signal: {}".format(ss_failed_signal)) logger.debug("ss_rdy_signal: {}".format(ss_rdy_signal)) logger.debug("ss_kw_rec_signal: {}".format(ss_kw_rec_signal)) logger.debug("ss_cmd_rec_signal: {}".format(ss_cmd_rec_signal)) logger.debug("ss_cancel_signal: {}".format(ss_cancel_signal)) ss.emitConnectedToListener('ScarlettTasker') loop.run() # THE ACTUAL THREAD BIT # self.manager = FooThreadManager(3) try: print("ScarlettTasker Thread Started") except Exception: ss_failed_signal.disconnect() ss_rdy_signal.disconnect() ss_kw_rec_signal.disconnect() ss_cmd_rec_signal.disconnect() ss_cancel_signal.disconnect() loop.quit() self.bucket.put(sys.exc_info()) raise
from pydbus import SessionBus # TODO I'm not happy with the naming of this module. -> Find a better name # TODO check for privileges to suspend bus = SessionBus() power = bus.get('org.freedesktop.UPower', '/org/freedesktop/UPower') def suspend(): power.Suspend() def hibernate(): power.Hibernate() if __name__ == '__main__': suspend()
"""https://github.com/LEW21/pydbus""" import sys sys.path += ['pydbus/'] from pydbus import SessionBus bus = SessionBus() notifications = bus.get('.Notifications') notifications.Notify('test', 0, 'dialog-information', "Hello World!", "pydbus works :)", [], {}, 5000)
class KDEConnectNotify(): """ """ # available configuration parameters device_id = None debug = None terminal = None libnotify = None ignore = None _bus = None _dev = None def __init__(self, use_terminal = True, use_libnotify = True, debug = False, device_id = None, device_name = None, ignore = None): """ Get the device id """ self.terminal = use_terminal self.libnotify = use_libnotify self.debug = debug if ignore: self.ignore = [app.lower() for app in ignore] if not self.terminal: self._debug('hide terminal messages') if not self.libnotify: self._debug('hide notifications') if use_libnotify: Notify.init('KDEConnect Notify') if ignore: apps = ignore[0] for app in ignore[1:]: apps += ', ' + app self._debug('ignore ' + apps) self._bus = SessionBus() if device_id is None: self.device_id = self._get_device_id(device_id, device_name) if self.device_id is None: self._debug('No device id found') return else: self.device_id = device_id self._debug('Device id is %s' % self.device_id) try: self._dev = self._bus.get(SERVICE_BUS, DEVICE_PATH + '/%s' % self.device_id) except Exception: self.device_id = None return def _get_device_id(self, device_id, device_name): """ Find the device id """ _dbus = self._bus.get(SERVICE_BUS, PATH) devices = _dbus.devices() if device_name is None and device_id is None and len(devices) == 1: return devices[0] self._debug('Search device name \'%s\'' % device_name) for id in devices: self._dev = self._bus.get(SERVICE_BUS, DEVICE_PATH + '/%s' % id) if device_name == self._dev.name: return id return None def _debug(self, text): if self.debug: print(text) def _print(self, text): if self.terminal: print(text) def _merge(self, notifies): merged = [] for notif in notifies: found = None sep = notif['text'].find('‐') title = notif['app_name'] body = { 'text': notif['text'][:sep-1], 'desc': '<i>' + notif['text'][sep+2:] + '</i>' } for entry in merged: if entry['title'] == title: found = entry break if found: found['body'].append(body) else: merged.append({ 'title': title, 'body': [body] }) return merged def _notify(self, summary, body, category = 'dialog-information'): if self.libnotify: notify = Notify.Notification.new(summary, body, category) notify.show() def _get_device(self): """ Get the device """ try: device = { 'name': self._dev.name, 'isReachable': self._dev.isReachable, 'isTrusted': self._dev.isTrusted, } except Exception: return None return device def _get_notification_ids(self): """ Get notification ids """ try: return self._dev.activeNotifications() except Exception: return None def _get_notification(self, id): """ Get the notification text """ try: _path = DEVICE_PATH + '/' + self.device_id + '/notifications/' + id _notify = self._bus.get(SERVICE_BUS, _path) notification = { 'app_name': _notify.appName, 'text': _notify.ticker } return notification except Exception: return None def show_notifications(self): """ Get the current metadatas """ if self.device_id is None: self._print('No device found') self._notify('KDEConnect Notify', 'No device found') return False device = self._get_device() if device is None: summary = 'KDEConnect Notify' else: summary = device['name'] if device is None or not device['isReachable'] or not device['isTrusted']: self._print('Device is disconnected') self._notify(summary, 'Device is disconnected') return False ids = self._get_notification_ids() notifies = [] for id in ids: notif = self._get_notification(id) if notif is None: self._print(' Couldn\'t read any notification') self._notify(summary, 'Couldn\'t read any notification') return False if not self.ignore or notif['app_name'].lower() not in self.ignore: notifies.append(notif) size = len(notifies) self._debug('%s notifications available' % size) self._print(summary + ':') if size == 0: self._print(' No notifications available') self._notify(summary, 'No notifications available') return True for notif in notifies: prefix = id + ' ' if self.debug else '' self._print(' ' + prefix + notif['app_name'] + ': ' + notif['text']) if not self.libnotify: return True notifies = self._merge(notifies) for notif in notifies: if len(notif['body']) == 1: body = notif['body'][0] text = body['text'] + '\n' + body['desc'] else: text = "" for body in notif['body']: text += body['text'] + ' - ' + body['desc'] + '\n' self._notify(notif['title'], text) return True
class ScarlettListenerI(threading.Thread, _IdleObject): """ Attempt to take out all Gstreamer logic and put it in a class ouside the dbus server. Cancellable thread which uses gobject signals to return information to the GUI. """ __gsignals__ = SCARLETT_LISTENER_I_SIGNALS device = PS_DEVICE hmm = HMM_PATH lm = LM_PATH dic = DICT_PATH # __dr = None __instance = None MAX_FAILURES = 10 def __init__(self, name, config_manager, *args): threading.Thread.__init__(self) _IdleObject.__init__(self) self.running = False self.finished = False self.ready_sem = threading.Semaphore(SEMAPHORE_NUM) self.queue = queue.Queue(QUEUE_SIZE) # Load in config object, and set default device information self._config_manager = config_manager self._graphviz_debug_dir = self._config_manager.cfg["graphviz_debug_dir"] self._device = self._config_manager.cfg["pocketsphinx"]["device"] self._hmm = self._config_manager.cfg["pocketsphinx"]["hmm"] self._lm = self._config_manager.cfg["pocketsphinx"]["lm"] self._dic = self._config_manager.cfg["pocketsphinx"]["dict"] self._fwdflat = bool(self._config_manager.cfg["pocketsphinx"]["fwdflat"]) self._bestpath = bool(self._config_manager.cfg["pocketsphinx"]["bestpath"]) self._dsratio = int(self._config_manager.cfg["pocketsphinx"]["dsratio"]) self._maxhmmpf = int(self._config_manager.cfg["pocketsphinx"]["maxhmmpf"]) self._bestpath = bool(self._config_manager.cfg["pocketsphinx"]["bestpath"]) self._silprob = float(self._config_manager.cfg["pocketsphinx"]["silprob"]) self._wip = float(self._config_manager.cfg["pocketsphinx"]["wip"]) # dotfile setup self._dotfile_listener = os.path.join( self._graphviz_debug_dir, "generator-listener.dot" ) self._pngfile_listener = os.path.join( self._graphviz_debug_dir, "generator-listener-pipeline.png" ) # self._handler = DbusSignalHandler() # Get a dbus proxy and check if theres a service registered called 'org.scarlett.Listener' # if not, then we can skip all further processing. (The scarlett-os-mpris-dbus seems not to be running) # self.__dr = DBusRunner.get_instance() logger.info("Initializing ScarlettListenerI") # This wil get filled with an exception if opening fails. self.read_exc = None self.dot_exc = None self.cancelled = False self.name = name self.setName("{}".format(self.name)) self.pipelines_stack = [] self.elements_stack = [] self.gst_bus_stack = [] self._message = "This is the ScarlettListenerI" # TODO: When we're ready to unit test, config this back in!!!!! # self.config = scarlett_config.Config() self.config = None self.override_parse = "" self.failed = 0 self.kw_found = 0 self.debug = False self.create_dot = True self.terminate = False self.capsfilter_queue_overrun_handler_id = None self._cancel_signal_callback = None # source: https://github.com/ljmljz/xpra/blob/b32f748e0c29cdbfab836b3901c1e318ea142b33/src/xpra/sound/sound_pipeline.py # NOQA self.bus = None self.bus_message_element_handler_id = None self.bus_message_error_handler_id = None self.bus_message_eos_handler_id = None self.bus_message_state_changed_handler_id = None self.pipeline = None self.start_time = 0 self.state = "stopped" self.buffer_count = 0 self.byte_count = 0 self._status_ready = " ScarlettListener is ready" self._status_kw_match = " ScarlettListener caught a keyword match" self._status_cmd_match = " ScarlettListener caught a command match" self._status_stt_failed = " ScarlettListener hit Max STT failures" self._status_cmd_start = " ScarlettListener emitting start command" self._status_cmd_fin = " ScarlettListener Emitting Command run finish" self._status_cmd_cancel = " ScarlettListener cancel speech Recognition" if self.debug: # NOTE: For testing puposes, mainly when in public # so you dont have to keep yelling scarlett in front of strangers self.kw_to_find = ["yo", "hello", "man", "children"] else: # NOTE: Before we start worrying about the config class, lets hardcode what we care about # ADD ME BACK IN WHEN WE REALLY START UNIT TESTING # self.kw_to_find = self.config.get('scarlett', 'keywords') self.kw_to_find = ["scarlett", "SCARLETT"] if self.read_exc: # An error occurred before the stream became ready. self.close(True) raise self.read_exc # pylint: disable=raising-bad-type def scarlett_reset_listen(self): self.failed = 0 self.kw_found = 0 def on_cancel_listening(self, *args, **kwargs): logger.debug("Inside cancel_listening function") self.scarlett_reset_listen() logger.debug("self.failed = {}".format(self.failed)) logger.debug("self.keyword_identified = {}".format(self.kw_found)) def play(self): p = self.pipelines_stack[0] self.state = "active" self.running = True # GST_STATE_PAUSED is the state in which an element is ready to accept and handle data. # For most elements this state is the same as PLAYING. The only exception to this rule are sink elements. # Sink elements only accept one single buffer of data and then block. # At this point the pipeline is 'prerolled' and ready to render data immediately. p.set_state(Gst.State.PAUSED) # GST_STATE_PLAYING is the highest state that an element can be in. # For most elements this state is exactly the same as PAUSED, # they accept and process events and buffers with data. # Only sink elements need to differentiate between PAUSED and PLAYING state. # In PLAYING state, sink elements actually render incoming data, # e.g. output audio to a sound card or render video pictures to an image sink. ret = p.set_state(Gst.State.PLAYING) if ret == Gst.StateChangeReturn.FAILURE: logger.error("ERROR: Unable to set the pipeline to the playing state") # 8/8/2018 (Only enable this if we turn on debug mode) if os.environ.get("SCARLETT_DEBUG_MODE"): self.on_debug_activate() logger.debug("BEFORE: self.ready_sem.acquire()") self.ready_sem.acquire() logger.debug("AFTER: self.ready_sem.acquire()") logger.info("Press Ctrl+C to quit ...") def stop(self): p = self.pipelines_stack[0] self.state = "stopped" self.running = False # GST_STATE_NULL is the default state of an element. # In this state, it has not allocated any runtime resources, # it has not loaded any runtime libraries and it can obviously not handle data. p.set_state(Gst.State.NULL) def get_pocketsphinx_definition(self, override=False): r""" GST_DEBUG=2,pocketsphinx*:5 gst-launch-1.0 alsasrc device=plughw:CARD=Device,DEV=0 ! \ queue name=capsfilter_queue \ leaky=2 \ max-size-buffers=0 \ max-size-time=0 \ max-size-bytes=0 ! \ capsfilter caps='audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved' ! \ audioconvert ! \ audioresample ! \ pocketsphinx \ name=asr \ lm=~/dev/bossjones-github/scarlett_os/static/speech/lm/1473.lm \ dict=~/dev/bossjones-github/scarlett_os/static/speech/dict/1473.dic \ hmm=~/.virtualenvs/scarlett_os/share/pocketsphinx/model/en-us/en-us bestpath=true ! \ tee name=tee ! \ queue name=appsink_queue \ leaky=2 \ max-size-buffers=0 \ max-size-time=0 \ max-size-bytes=0 ! \ appsink caps='audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved' \ drop=false max-buffers=10 sync=false \ emit-signals=true tee. queue name=fakesink_queue \ leaky=2 \ max-size-buffers=0 \ max-size-time=0 \ max-size-bytes=0 ! \ fakesink sync=false """ logger.debug("Inside get_pocketsphinx_definition") if override: _gst_launch = override else: # TODO: Add audio levels, see the following # SOURCE: http://stackoverflow.com/questions/5686424/detecting-blowing-on-a-microphone-with-gstreamer-or-another-library _gst_launch = [ "alsasrc device=" + self.device, # source: https://github.com/walterbender/story/blob/master/grecord.py # without a buffer here, gstreamer struggles at the start of the # recording and then the A/V sync is bad for the whole video # (possibly a gstreamer/ALSA bug -- even if it gets caught up, it # should be able to resync without problem) # 'progressreport name=progressreport update-freq=1', # NOTE: comment this in when you want performance information "queue name=capsfilter_queue silent=false leaky=2 max-size-buffers=0 max-size-time=0 max-size-bytes=0", "capsfilter name=capsfilter caps=audio/x-raw,format=S16LE,channels=1,layout=interleaved", "audioconvert name=audioconvert", "audioresample name=audioresample", "identity name=ident", "pocketsphinx name=asr", "tee name=tee", "queue name=appsink_queue silent=false leaky=2 max-size-buffers=0 max-size-time=0 max-size-bytes=0", # caps=audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved # NOQA "appsink name=appsink drop=false max-buffers=10 sync=false emit-signals=true tee.", "queue leaky=2 name=fakesink_queue", "fakesink", ] return _gst_launch def cancel(self): """ Threads in python are not cancellable, so we implement our own cancellation logic """ self.cancelled = True @abort_on_exception def run(self, event=None): # TODO: WE NEED TO USE A THREADING EVENT OR A RLOCK HERE TO WAIT TILL DBUS SERVICE IS RUNNING TO CONNECT # TODO: SIGNALS TO THE DBUS PROXY METHODS WE WANT TO USE # TODO: lock.acquire() / event / condition # TODO: self.connect_to_dbus() # TODO: self.setup_dbus_callbacks_handlers() self._connect_to_dbus() self.init_gst() print("Running {}".format(str(self))) self.play() self.emit("playback-status-changed") self.emit("playing-changed") # FIXME: is this needed? # self.mainloop.run() def _connect_to_dbus(self): self.bus = SessionBus() self.dbus_proxy = self.bus.get( "org.scarlett", object_path="/org/scarlett/Listener" ) # NOQA self.dbus_proxy.emitConnectedToListener("ScarlettListener") time.sleep(2) logger.info("_connect_to_dbus") # TODO: Add a ss_cancel_signal.disconnect() function later ss_cancel_signal = self.bus.subscribe( sender=None, iface="org.scarlett.Listener", signal="ListenerCancelSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=self.on_cancel_listening, ) # NOTE: This function generates the dot file, checks that graphviz in installed and # then finally generates a png file, which it then displays def on_debug_activate(self): # FIXME: This needs to use dynamic paths, it's possible that we're having issues because of order of operations # FIXME: STATIC PATH 7/3/2018 # dotfile = ( # "/home/pi/dev/bossjones-github/scarlett_os/_debug/generator-listener.dot" # ) # pngfile = "/home/pi/dev/bossjones-github/scarlett_os/_debug/generator-listener-pipeline.png" # NOQA dotfile = self._dotfile_listener pngfile = self._pngfile_listener if os.access(dotfile, os.F_OK): os.remove(dotfile) if os.access(pngfile, os.F_OK): os.remove(pngfile) Gst.debug_bin_to_dot_file( self.pipelines_stack[0], Gst.DebugGraphDetails.ALL, "generator-listener" ) cmd = "/usr/bin/dot -Tpng -o {pngfile} {dotfile}".format( pngfile=pngfile, dotfile=dotfile ) os.system(cmd) def result(self, final_hyp): """Forward result signals on the bus to the main thread.""" logger.debug("Inside result function") logger.debug("final_hyp: {}".format(final_hyp)) pp.pprint(final_hyp) logger.debug("kw_to_find: {}".format(self.kw_to_find)) if final_hyp in self.kw_to_find and final_hyp != "": logger.debug("HYP-IS-SOMETHING: {}\n\n\n".format(final_hyp)) self.failed = 0 self.kw_found = 1 self.dbus_proxy.emitKeywordRecognizedSignal() # CHANGEME else: failed_temp = self.failed + 1 self.failed = failed_temp logger.debug("self.failed = {}".format(int(self.failed))) # failed > 10 if self.failed > 4: # reset pipline self.dbus_proxy.emitSttFailedSignal() # CHANGEME self.scarlett_reset_listen() def run_cmd(self, final_hyp): logger.debug("Inside run_cmd function") logger.debug("KEYWORD IDENTIFIED BABY") logger.debug("self.kw_found = {}".format(int(self.kw_found))) if final_hyp == "CANCEL": self.dbus_proxy.emitListenerCancelSignal() # CHANGEME self.on_cancel_listening() else: current_kw_identified = self.kw_found self.kw_found = current_kw_identified self.dbus_proxy.emitCommandRecognizedSignal(final_hyp) # CHANGEME logger.info("Command = {}".format(final_hyp)) logger.debug("AFTER run_cmd, self.kw_found = {}".format(int(self.kw_found))) def init_gst(self): logger.debug("Inside init_gst") self.start_time = time.time() pipeline = Gst.parse_launch(" ! ".join(self.get_pocketsphinx_definition())) logger.debug("After get_pocketsphinx_definition") # Add pipeline obj to stack we can pull from later self.pipelines_stack.append(pipeline) gst_bus = pipeline.get_bus() # gst_bus = pipeline.get_gst_bus() gst_bus.add_signal_watch() self.bus_message_element_handler_id = gst_bus.connect( "message::element", self._on_message ) self.bus_message_eos_handler_id = gst_bus.connect( "message::eos", self._on_message ) self.bus_message_error_handler_id = gst_bus.connect( "message::error", self._on_message ) self.bus_message_state_changed_handler_id = gst_bus.connect( "message::state-changed", self._on_state_changed ) # Add bus obj to stack we can pull from later self.gst_bus_stack.append(gst_bus) appsink = pipeline.get_by_name("appsink") appsink.set_property( "caps", Gst.Caps.from_string( "audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved" ), ) appsink.set_property("drop", False) appsink.set_property("max-buffers", BUFFER_SIZE) appsink.set_property("sync", False) # The callback to receive decoded data. appsink.set_property("emit-signals", True) appsink.connect("new-sample", self._new_sample) self.caps_handler = appsink.get_static_pad("sink").connect( "notify::caps", self._notify_caps ) self.elements_stack.append(appsink) # ************************************************************ # get gst pipeline element pocketsphinx and set properties - BEGIN # ************************************************************ pocketsphinx = pipeline.get_by_name("asr") # from scarlett_os.internal.debugger import dump # print("debug-2018-pocketsphinx - BEGIN") # dump(pocketsphinx.get_property('decoder')) # print("debug-2018-pocketsphinx - END") # print(pocketsphinx.list_properties()) if self._hmm: pocketsphinx.set_property("hmm", self._hmm) if self._lm: pocketsphinx.set_property("lm", self._lm) if self._dic: pocketsphinx.set_property("dict", self._dic) if self._fwdflat: pocketsphinx.set_property("fwdflat", self._fwdflat) if self._bestpath: pocketsphinx.set_property("bestpath", self._bestpath) if self._dsratio: pocketsphinx.set_property("dsratio", self._dsratio) if self._maxhmmpf: pocketsphinx.set_property("maxhmmpf", self._maxhmmpf) if self._bestpath: pocketsphinx.set_property("bestpath", self._bestpath) # if self._silprob: # pocketsphinx.set_property("silprob", self._silprob) # if self._wip: # pocketsphinx.set_property("wip", self._wip) # ************************************************************ # get gst pipeline element pocketsphinx and set properties - END # ************************************************************ # NOTE: Old way of setting pocketsphinx properties. 8/5/2018 # pocketsphinx.set_property( # "fwdflat", True # ) # Enable Flat Lexicon Search | Default: true # pocketsphinx.set_property( # "bestpath", True # ) # Enable Graph Search | Boolean. Default: true # pocketsphinx.set_property( # "dsratio", 1 # ) # Evaluate acoustic model every N frames | Integer. Range: 1 - 10 Default: 1 # pocketsphinx.set_property( # "maxhmmpf", 3000 # ) # Maximum number of HMMs searched per frame | Integer. Range: 1 - 100000 Default: 30000 # pocketsphinx.set_property( # "bestpath", True # ) # Enable Graph Search | Boolean. Default: true # pocketsphinx.set_property('maxwpf', -1) # # pocketsphinx.set_property('maxwpf', 20) # Maximum number of words # searched per frame | Range: 1 - 100000 Default: -1 self.elements_stack.append(pocketsphinx) capsfilter_queue = pipeline.get_by_name("capsfilter_queue") capsfilter_queue.set_property("leaky", True) # prefer fresh data capsfilter_queue.set_property("silent", False) capsfilter_queue.set_property("max-size-time", 0) # 0 seconds capsfilter_queue.set_property("max-size-buffers", 0) capsfilter_queue.set_property("max-size-bytes", 0) self.capsfilter_queue_overrun_handler_id = capsfilter_queue.connect( "overrun", self._log_queue_overrun ) # capsfilter_queue.connect('overrun', self._on_overrun) # capsfilter_queue.connect('underrun', self._on_underrun) # capsfilter_queue.connect('pushing', self._on_pushing) # capsfilter_queue.connect('running', self._on_running) self.elements_stack.append(capsfilter_queue) ident = pipeline.get_by_name("ident") # ident.connect('handoff', self._on_handoff) self.elements_stack.append(ident) logger.debug("After all self.elements_stack.append() calls") # Set up the queue for data and run the main thread. self.queue = queue.Queue(QUEUE_SIZE) self.thread = get_loop_thread() # NOTE: Disabled since we aren't connecting to handoff # def _on_handoff(self, element, buf): # logger.debug('buf:') # pp.pprint(buf) # pp.pprint(dir(buf)) # logger.debug("on_handoff - %d bytes".format(len(buf)) # if self.signed is None: # # only ever one caps struct on our buffers # struct = buf.get_caps().get_structure(0) # # I think these are always set too, but catch just in case # try: # self.signed = struct["signed"] # self.depth = struct["depth"] # self.rate = struct["rate"] # self.channels = struct["channels"] # except Exception: # logger.debug('on_handoff: missing caps') # pass # raw = str(buf) # # # print 'len(raw) =', len(raw) # # sm = 0 # for i in range(0, len(raw)): # sm += ord(raw[i]) # # print sm # FIXEME: Add somthing like analyse.py # SOURCE: https://github.com/jcupitt/huebert/blob/master/huebert/audio.py def _on_state_changed(self, bus, msg): states = msg.parse_state_changed() # To state is PLAYING if msg.src.get_name() == "pipeline0" and states[1] == 4: logger.info("Inside pipeline0 on _on_state_changed") logger.info("State: {}".format(states[1])) self.ready_sem.release() return False else: # logger.error('NOTHING RETURNED in _on_state_changed') logger.info("State: {}".format(states[1])) def _on_overrun(self, element): logging.debug("on_overrun") def _on_underrun(self, element): logging.debug("on_underrun") def _on_running(self, element): logging.debug("on_running") def _on_pushing(self, element): logging.debug("on_pushing") def _notify_caps(self, pad, args): """The callback for the sinkpad's "notify::caps" signal. """ # The sink has started to receive data, so the stream is ready. # This also is our opportunity to read information about the # stream. self.got_caps = True # Allow constructor to complete. self.ready_sem.release() _got_a_pad = False def _log_queue_overrun(self, queue): cbuffers = queue.get_property("current-level-buffers") cbytes = queue.get_property("current-level-bytes") ctime = queue.get_property("current-level-time") def _new_sample(self, sink): """The callback for appsink's "new-sample" signal. """ if self.running: # New data is available from the pipeline! Dump it into our # queue (or possibly block if we're full). buf = sink.emit("pull-sample").get_buffer() # IMPORTANT!!!!! # NOTE: I think this is causing a deadlock self.queue.put(buf.extract_dup(0, buf.get_size())) # "OK = 0. Data passing was ok."" return Gst.FlowReturn.OK def _on_message(self, bus, message): """The callback for GstBus's "message" signal (for two kinds of messages). """ # logger.debug("[_on_message](%s, %s)", bus, message) if not self.finished: struct = message.get_structure() if message.type == Gst.MessageType.EOS: # The file is done. Tell the consumer thread. self.queue.put(SENTINEL) if not self.got_caps: logger.error( "If the stream ends before _notify_caps was called, this is an invalid stream." ) # If the stream ends before _notify_caps was called, this # is an invalid file. self.read_exc = NoStreamError() self.ready_sem.release() elif struct and struct.get_name() == "pocketsphinx": # "final", G_TYPE_BOOLEAN, final, # SOURCE: https://github.com/cmusphinx/pocketsphinx/blob/1fdc9ccb637836d45d40956e745477a2bd3b470a/src/gst-plugin/gstpocketsphinx.c if struct["final"]: logger.info("confidence: {}".format(struct["confidence"])) logger.info("hypothesis: {}".format(struct["hypothesis"])) if self.kw_found == 1: # If keyword is set AND qualifier # then perform action self.run_cmd(struct["hypothesis"]) else: # If it's the main keyword, # set values wait for qualifier self.result(struct["hypothesis"]) elif message.type == Gst.MessageType.ERROR: gerror, debug = message.parse_error() pp.pprint(("gerror,debug:", gerror, debug)) if "not-linked" in debug: logger.error("not-linked") self.read_exc = NoStreamError() elif "No such device" in debug: logger.error("No such device") self.read_exc = NoStreamError() else: logger.info("FileReadError") pp.pprint( ("SOME FileReadError", bus, message, struct, struct.get_name()) ) self.read_exc = FileReadError(debug) self.ready_sem.release() # Cleanup. def close(self, force=False): """Close the file and clean up associated resources. Calling `close()` a second time has no effect. """ if self.running or force: self.running = False self.finished = True try: gst_bus = self.gst_bus_stack[0] except Exception: logger.error("Failed to get gst_bus from gst_bus_stack[0]") if gst_bus: gst_bus.remove_signal_watch() if self.bus_message_element_handler_id: gst_bus.disconnect(self.bus_message_element_handler_id) if self.bus_message_error_handler_id: gst_bus.disconnect(self.bus_message_error_handler_id) if self.bus_message_eos_handler_id: gst_bus.disconnect(self.bus_message_eos_handler_id) if self.bus_message_state_changed_handler_id: gst_bus.disconnect(self.bus_message_state_changed_handler_id) self.bus = None self.pipeline = None self.codec = None self.bitrate = -1 self.state = None # Unregister for signals, which we registered for above with # `add_signal_watch`. (Without this, GStreamer leaks file # descriptors.) logger.debug("BEFORE p = self.pipelines_stack[0]") p = self.pipelines_stack[0] p.get_bus().remove_signal_watch() logger.debug("AFTER p.get_bus().remove_signal_watch()") # Block spurious signals. appsink = self.elements_stack[0] appsink.get_static_pad("sink").disconnect(self.caps_handler) # Make space in the output queue to let the decoder thread # finish. (Otherwise, the thread blocks on its enqueue and # the interpreter hangs.) try: self.queue.get_nowait() except queue.Empty: pass # Halt the pipeline (closing file). self.stop() # Delete the pipeline object. This seems to be necessary on Python # 2, but not Python 3 for some reason: on 3.5, at least, the # pipeline gets dereferenced automatically. del p def __del__(self): self.close() def __exit__(self, exc_type, exc_val, exc_tb): self.close() return False
def __init__(self, *args): _IdleObject.__init__(self) self.bucket = bucket = Queue.Queue() # NOQA self.loop = GLib.MainLoop() self.hello = None # with SessionBus() as bus: bus = SessionBus() ss = bus.get("org.scarlett", object_path='/org/scarlett/Listener') # NOQA # # SttFailedSignal / player_cb # ss_failed_signal = bus.con.signal_subscribe(None, # NOQA # "org.scarlett.Listener", # "SttFailedSignal", # '/org/scarlett/Listener', # None, # 0, # player_cb) ss_failed_signal = ss.SttFailedSignal.connect(player_cb) # # ListenerReadySignal / player_cb # ss_rdy_signal = bus.con.signal_subscribe(None, # NOQA # "org.scarlett.Listener", # "ListenerReadySignal", # '/org/scarlett/Listener', # None, # 0, # player_cb) ss_rdy_signal = ss.ListenerReadySignal.connect(player_cb) # # KeywordRecognizedSignal / player_cb # ss_kw_rec_signal = bus.con.signal_subscribe(None, # NOQA # "org.scarlett.Listener", # "KeywordRecognizedSignal", # '/org/scarlett/Listener', # None, # 0, # player_cb) ss_kw_rec_signal = ss.KeywordRecognizedSignal.connect(player_cb) # # CommandRecognizedSignal /command_cb # ss_cmd_rec_signal = bus.con.signal_subscribe(None, # NOQA # "org.scarlett.Listener", # "CommandRecognizedSignal", # '/org/scarlett/Listener', # None, # 0, # command_cb) ss_cmd_rec_signal = ss.CommandRecognizedSignal.connect(command_cb) # # ListenerCancelSignal / player_cb # # signal_subscribe (sender, interface_name, member, object_path, arg0, flags, callback, *user_data) # ss_cancel_signal = bus.con.signal_subscribe(None, # NOQA # "org.scarlett.Listener", # "ListenerCancelSignal", # '/org/scarlett/Listener', # None, # 0, # player_cb) ss_cancel_signal = ss.ListenerCancelSignal.connect(player_cb) ss.emitConnectedToListener('ScarlettTasker') # THE ACTUAL THREAD BIT self.manager = FooThreadManager(3) try: print "ScarlettTasker Thread Started", self self.loop.run() except Exception: ss_failed_signal.disconnect() ss_rdy_signal.disconnect() ss_kw_rec_signal.disconnect() ss_cmd_rec_signal.disconnect() ss_cancel_signal.disconnect() self.bucket.put(sys.exc_info()) raise
class Py3status: """ """ # available configuration parameters button_stop = None button_toggle = 1 button_next = 4 button_previous = 5 format = "{previous}{toggle}{next} {state} [{artist} - ][{title}]" format_none = "no player running" icon_pause = u"▮" icon_play = u"▶" icon_stop = u"◾" icon_next = u"»" icon_previous = u"«" state_pause = u"▮" state_play = u"▶" state_stop = u"◾" player_priority = [] def __init__(self): self._dbus = None self._data = {} self._kill = False self._mpris_players = {} self._mpris_names = {} self._mpris_name_index = {} self._player = None self._player_details = {} self._tries = 0 def post_config_hook(self): self._dbus = SessionBus() self._start_listener() def _init_data(self): self._data = { "album": None, "artist": None, "error_occurred": False, "length": None, "player": None, "state": STOPPED, "title": None, } if self._player is None: return try: self._data["player"] = self._player.Identity playback_status = self._player.PlaybackStatus self._data["state"] = self._get_state(playback_status) metadata = self._player.Metadata self._update_metadata(metadata) except Exception: self._data["error_occurred"] = True def _get_button_state(self, control_state): try: # Workaround: The last parameter returns True for the Stop button. clickable = getattr(self._player, control_state["clickable"], True) except Exception: clickable = False state = self._data.get("state") if control_state["action"] == "Play" and state == PLAYING: clickable = False elif control_state["action"] == "Pause" and state in [STOPPED, PAUSED]: clickable = False elif control_state["action"] == "Stop" and state == STOPPED: clickable = False return clickable def _get_state(self, playback_status): if playback_status == "Playing": return PLAYING elif playback_status == "Paused": return PAUSED else: return STOPPED def _get_text(self): """ Get the current metadata """ if self._data.get("state") == PLAYING: color = self.py3.COLOR_PLAYING or self.py3.COLOR_GOOD state_symbol = self.state_play elif self._data.get("state") == PAUSED: color = self.py3.COLOR_PAUSED or self.py3.COLOR_DEGRADED state_symbol = self.state_pause else: color = self.py3.COLOR_STOPPED or self.py3.COLOR_BAD state_symbol = self.state_stop if self._data.get("error_occurred"): color = self.py3.COLOR_BAD try: ptime_ms = self._player.Position ptime = _get_time_str(ptime_ms) except Exception: ptime = None if "{time}" in self.format and self._data.get("state") == PLAYING: # Don't get trapped in aliasing errors! update = time() + 0.5 else: update = self.py3.CACHE_FOREVER placeholders = { "player": self._data.get("player"), "state": state_symbol, "album": self._data.get("album"), "artist": self._data.get("artist"), "length": self._data.get("length"), "time": ptime, "title": self._data.get("title") or "No Track", "full_name": self._player_details.get("full_name"), # for debugging ;p } return (placeholders, color, update) def _get_control_states(self): control_states = { "pause": {"action": "Pause", "clickable": "CanPause", "icon": self.icon_pause}, "play": {"action": "Play", "clickable": "CanPlay", "icon": self.icon_play}, "stop": { "action": "Stop", # Workaround: The MPRIS API has no CanStop function. "clickable": "True", "icon": self.icon_stop, }, "next": {"action": "Next", "clickable": "CanGoNext", "icon": self.icon_next}, "previous": {"action": "Previous", "clickable": "CanGoPrevious", "icon": self.icon_previous}, } state = "pause" if self._data.get("state") == PLAYING else "play" control_states["toggle"] = control_states[state] return control_states def _get_response_buttons(self): response = {} for button in self._control_states.keys(): control_state = self._control_states[button] if self._get_button_state(control_state): color = self.py3.COLOR_CONTROL_ACTIVE or self.py3.COLOR_GOOD else: color = self.py3.COLOR_CONTROL_INACTIVE or self.py3.COLOR_BAD response[button] = { "color": color, "full_text": control_state["icon"], "index": button, "min_width": 20, "align": "center", } return response def _start_loop(self): self._loop = GObject.MainLoop() GObject.timeout_add(1000, self._timeout) try: self._loop.run() except KeyboardInterrupt: # This branch is only needed for the test mode self._kill = True def _name_owner_changed(self, *args): player_add = args[5][2] player_remove = args[5][1] if player_add: self._add_player(player_add) if player_remove: self._remove_player(player_remove) self._set_player() def _set_player(self): """ Sort the current players into priority order and set self._player Players are ordered by working state then prefernce supplied by user and finally by instance if a player has more than one running. """ players = [] for name, p in self._mpris_players.items(): # we set the priority here as we need to establish the player name # which might not be immediately available. if "_priority" not in p: if self.player_priority: try: priority = self.player_priority.index(p["name"]) except ValueError: try: priority = self.player_priority.index("*") except ValueError: priority = None else: priority = 0 if priority is not None: p["_priority"] = priority if p.get("_priority") is not None: players.append((p["_state_priority"], p["_priority"], p["index"], name)) if players: top_player = self._mpris_players.get(sorted(players)[0][3]) else: top_player = {} self._player = top_player.get("_dbus_player") self._player_details = top_player self.py3.update() def _player_monitor(self, player_id): def player_on_change(*args): """ Monitor a player and update its status. """ data = args[1] status = data.get("PlaybackStatus") if status: player = self._mpris_players[player_id] player["status"] = status player["_state_priority"] = WORKING_STATES.index(status) self._set_player() return player_on_change def _add_player(self, player_id): """ Add player to mpris_players """ try: player = self._dbus.get(player_id, SERVICE_BUS_URL) if player_id.startswith(SERVICE_BUS): if player.Identity not in self._mpris_names: self._mpris_names[player.Identity] = player_id.split(".")[-1] for p in self._mpris_players.values(): if not p["name"] and p["identity"] in self._mpris_names: p["name"] = self._mpris_names[p["identity"]] p["full_name"] = u"{} {}".format(p["name"], p["index"]) return status = player.PlaybackStatus state_priority = WORKING_STATES.index(status) identity = player.Identity if identity not in self._mpris_name_index: self._mpris_name_index[identity] = 0 index = self._mpris_name_index[identity] self._mpris_name_index[identity] += 1 name = self._mpris_names.get(identity) subscription = player.PropertiesChanged.connect(self._player_monitor(player_id)) except: return self._mpris_players[player_id] = { "_dbus_player": player, "_id": player_id, "_state_priority": state_priority, "index": index, "identity": identity, "name": name, "full_name": u"{} {}".format(name, index), "status": status, "subscription": subscription, } return True def _remove_player(self, player_id): """ Remove player from mpris_players """ player = self._mpris_players.get(player_id) if player: if player.get("subscription"): player["subscription"].disconnect() del self._mpris_players[player_id] def _get_players(self): bus = self._dbus.get("org.freedesktop.DBus") for player in bus.ListNames(): if player.startswith(":") or player.startswith(SERVICE_BUS): if not self._add_player(player): continue self._set_player() def _start_listener(self): self._dbus.con.signal_subscribe( None, "org.freedesktop.DBus", "NameOwnerChanged", None, None, 0, self._name_owner_changed ) self._get_players() t = Thread(target=self._start_loop) t.daemon = True t.start() def _timeout(self): if self._kill: self._loop.quit() sys.exit(0) def _update_metadata(self, metadata): is_stream = False try: if len(metadata) > 0: url = metadata.get("xesam:url") is_stream = url is not None and "file://" not in url self._data["title"] = metadata.get("xesam:title") self._data["album"] = metadata.get("xesam:album") if metadata.get("xesam:artist") is not None: self._data["artist"] = metadata.get("xesam:artist")[0] else: # we assume here that we playing a video and these types of # media we handle just like streams is_stream = True length_ms = metadata.get("mpris:length") if length_ms is not None: self._data["length"] = _get_time_str(length_ms) else: # use stream format if no metadata is available is_stream = True except Exception: self._data["error_occurred"] = True if is_stream and self._data.get("title"): # delete the file extension self._data["title"] = re.sub(r"\....$", "", self._data.get("title")) def kill(self): self._kill = True def mpris(self): """ Get the current output format and return it. """ current_player_id = self._player_details.get("id") cached_until = self.py3.CACHE_FOREVER if self._player is None: text = self.format_none color = self.py3.COLOR_BAD composite = [{"full_text": text, "color": color}] self._data = {} else: self._init_data() (text, color, cached_until) = self._get_text() self._control_states = self._get_control_states() buttons = self._get_response_buttons() composite = self.py3.build_composite(self.format, text, buttons) if self._data.get("error_occurred") or current_player_id != self._player_details.get("id"): # Something went wrong or the player changed during our processing # This is usually due to something like a player being killed # whilst we are checking its details # Retry but limit the number of attempts self._tries += 1 if self._tries < 3: return self.mpris() # Max retries hit we need to output something composite = [{"full_text": "Something went wrong", "color": self.py3.COLOR_BAD}] cached_until = self.py3.time_in(1) response = {"cached_until": cached_until, "color": color, "composite": composite} # we are outputing so reset tries self._tries = 0 return response def on_click(self, event): """ Handles click events """ index = event["index"] button = event["button"] if index not in self._control_states.keys(): if button == self.button_toggle: index = "toggle" elif button == self.button_stop: index = "stop" elif button == self.button_next: index = "next" elif button == self.button_previous: index = "previous" else: return elif button != 1: return control_state = self._control_states[index] if self._player and self._get_button_state(control_state): getattr(self._player, self._control_states[index]["action"])()
class Py3status: """ """ # available configuration parameters button_next = 4 button_previous = 5 button_stop = None button_toggle = 1 format = '{previous}{toggle}{next} {state} [{artist} - ][{title}]' format_none = 'no player running' icon_next = u'»' icon_pause = u'▮' icon_play = u'▶' icon_previous = u'«' icon_stop = u'◾' player_priority = [] state_pause = u'▮' state_play = u'▶' state_stop = u'◾' def __init__(self): self._dbus = None self._data = {} self._kill = False self._mpris_players = {} self._mpris_names = {} self._mpris_name_index = {} self._player = None self._player_details = {} self._tries = 0 def post_config_hook(self): self._dbus = SessionBus() self._start_listener() def _init_data(self): self._data = { 'album': None, 'artist': None, 'error_occurred': False, 'length': None, 'player': None, 'state': STOPPED, 'title': None } if self._player is None: return try: self._data['player'] = self._player.Identity playback_status = self._player.PlaybackStatus self._data['state'] = self._get_state(playback_status) metadata = self._player.Metadata self._update_metadata(metadata) except Exception: self._data['error_occurred'] = True def _get_button_state(self, control_state): try: # Workaround: The last parameter returns True for the Stop button. clickable = getattr(self._player, control_state['clickable'], True) except Exception: clickable = False state = self._data.get('state') if control_state['action'] == 'Play' and state == PLAYING: clickable = False elif control_state['action'] == 'Pause' and state in [STOPPED, PAUSED]: clickable = False elif control_state['action'] == 'Stop' and state == STOPPED: clickable = False return clickable def _get_state(self, playback_status): if playback_status == 'Playing': return PLAYING elif playback_status == 'Paused': return PAUSED else: return STOPPED def _get_text(self): """ Get the current metadata """ if self._data.get('state') == PLAYING: color = self.py3.COLOR_PLAYING or self.py3.COLOR_GOOD state_symbol = self.state_play elif self._data.get('state') == PAUSED: color = self.py3.COLOR_PAUSED or self.py3.COLOR_DEGRADED state_symbol = self.state_pause else: color = self.py3.COLOR_STOPPED or self.py3.COLOR_BAD state_symbol = self.state_stop if self._data.get('error_occurred'): color = self.py3.COLOR_BAD try: ptime_ms = self._player.Position ptime = _get_time_str(ptime_ms) except Exception: ptime = None if '{time}' in self.format and self._data.get('state') == PLAYING: # Don't get trapped in aliasing errors! update = time() + 0.5 else: update = self.py3.CACHE_FOREVER placeholders = { 'player': self._data.get('player'), 'state': state_symbol, 'album': self._data.get('album'), 'artist': self._data.get('artist'), 'length': self._data.get('length'), 'time': ptime, 'title': self._data.get('title') or 'No Track', 'full_name': self._player_details.get('full_name'), # for debugging ;p } return (placeholders, color, update) def _get_control_states(self): control_states = { 'pause': {'action': 'Pause', 'clickable': 'CanPause', 'icon': self.icon_pause}, 'play': {'action': 'Play', 'clickable': 'CanPlay', 'icon': self.icon_play}, 'stop': {'action': 'Stop', # Workaround: The MPRIS API has no CanStop function. 'clickable': 'True', 'icon': self.icon_stop}, 'next': {'action': 'Next', 'clickable': 'CanGoNext', 'icon': self.icon_next}, 'previous': {'action': 'Previous', 'clickable': 'CanGoPrevious', 'icon': self.icon_previous} } state = 'pause' if self._data.get('state') == PLAYING else 'play' control_states['toggle'] = control_states[state] return control_states def _get_response_buttons(self): response = {} for button in self._control_states.keys(): control_state = self._control_states[button] if self._get_button_state(control_state): color = self.py3.COLOR_CONTROL_ACTIVE or self.py3.COLOR_GOOD else: color = self.py3.COLOR_CONTROL_INACTIVE or self.py3.COLOR_BAD response[button] = { 'color': color, 'full_text': control_state['icon'], 'index': button, 'min_width': 20, 'align': 'center' } return response def _start_loop(self): self._loop = GObject.MainLoop() GObject.timeout_add(1000, self._timeout) try: self._loop.run() except KeyboardInterrupt: # This branch is only needed for the test mode self._kill = True def _name_owner_changed(self, *args): player_add = args[5][2] player_remove = args[5][1] if player_add: self._add_player(player_add) if player_remove: self._remove_player(player_remove) self._set_player() def _set_player(self): """ Sort the current players into priority order and set self._player Players are ordered by working state then prefernce supplied by user and finally by instance if a player has more than one running. """ players = [] for name, p in self._mpris_players.items(): # we set the priority here as we need to establish the player name # which might not be immediately available. if '_priority' not in p: if self.player_priority: try: priority = self.player_priority.index(p['name']) except ValueError: try: priority = self.player_priority.index('*') except ValueError: priority = None else: priority = 0 if priority is not None: p['_priority'] = priority if p.get('_priority') is not None: players.append( (p['_state_priority'], p['_priority'], p['index'], name) ) if players: top_player = self._mpris_players.get(sorted(players)[0][3]) else: top_player = {} self._player = top_player.get('_dbus_player') self._player_details = top_player self.py3.update() def _player_monitor(self, player_id): def player_on_change(*args): """ Monitor a player and update its status. """ data = args[1] status = data.get('PlaybackStatus') if status: player = self._mpris_players[player_id] player['status'] = status player['_state_priority'] = WORKING_STATES.index(status) self._set_player() return player_on_change def _add_player(self, player_id): """ Add player to mpris_players """ try: player = self._dbus.get(player_id, SERVICE_BUS_URL) if player_id.startswith(SERVICE_BUS): if player.Identity not in self._mpris_names: self._mpris_names[player.Identity] = player_id.split('.')[-1] for p in self._mpris_players.values(): if not p['name'] and p['identity'] in self._mpris_names: p['name'] = self._mpris_names[p['identity']] p['full_name'] = u'{} {}'.format(p['name'], p['index']) return status = player.PlaybackStatus state_priority = WORKING_STATES.index(status) identity = player.Identity if identity not in self._mpris_name_index: self._mpris_name_index[identity] = 0 index = self._mpris_name_index[identity] self._mpris_name_index[identity] += 1 name = self._mpris_names.get(identity) subscription = player.PropertiesChanged.connect( self._player_monitor(player_id) ) except: return self._mpris_players[player_id] = { '_dbus_player': player, '_id': player_id, '_state_priority': state_priority, 'index': index, 'identity': identity, 'name': name, 'full_name': u'{} {}'.format(name, index), 'status': status, 'subscription': subscription, } return True def _remove_player(self, player_id): """ Remove player from mpris_players """ player = self._mpris_players.get(player_id) if player: if player.get('subscription'): player['subscription'].disconnect() del self._mpris_players[player_id] def _get_players(self): bus = self._dbus.get('org.freedesktop.DBus') for player in bus.ListNames(): if player.startswith(':') or player.startswith(SERVICE_BUS): if not self._add_player(player): continue self._set_player() def _start_listener(self): self._dbus.con.signal_subscribe( None, 'org.freedesktop.DBus', 'NameOwnerChanged', None, None, 0, self._name_owner_changed, ) self._get_players() t = Thread(target=self._start_loop) t.daemon = True t.start() def _timeout(self): if self._kill: self._loop.quit() sys.exit(0) def _update_metadata(self, metadata): is_stream = False try: if len(metadata) > 0: url = metadata.get('xesam:url') is_stream = url is not None and 'file://' not in url self._data['title'] = metadata.get('xesam:title') self._data['album'] = metadata.get('xesam:album') if metadata.get('xesam:artist') is not None: self._data['artist'] = metadata.get('xesam:artist')[0] else: # we assume here that we playing a video and these types of # media we handle just like streams is_stream = True length_ms = metadata.get('mpris:length') if length_ms is not None: self._data['length'] = _get_time_str(length_ms) else: # use stream format if no metadata is available is_stream = True except Exception: self._data['error_occurred'] = True if is_stream and self._data.get('title'): # delete the file extension self._data['title'] = re.sub(r'\....$', '', self._data.get('title')) def kill(self): self._kill = True def mpris(self): """ Get the current output format and return it. """ current_player_id = self._player_details.get('id') cached_until = self.py3.CACHE_FOREVER if self._player is None: text = self.format_none color = self.py3.COLOR_BAD composite = [{ 'full_text': text, 'color': color, }] self._data = {} else: self._init_data() (text, color, cached_until) = self._get_text() self._control_states = self._get_control_states() buttons = self._get_response_buttons() composite = self.py3.build_composite(self.format, text, buttons) if (self._data.get('error_occurred') or current_player_id != self._player_details.get('id')): # Something went wrong or the player changed during our processing # This is usually due to something like a player being killed # whilst we are checking its details # Retry but limit the number of attempts self._tries += 1 if self._tries < 3: return self.mpris() # Max retries hit we need to output something composite = [{ 'full_text': 'Something went wrong', 'color': self.py3.COLOR_BAD, }] cached_until = self.py3.time_in(1) response = { 'cached_until': cached_until, 'color': color, 'composite': composite } # we are outputing so reset tries self._tries = 0 return response def on_click(self, event): """ Handles click events """ index = event['index'] button = event['button'] if not index: return if index not in self._control_states.keys(): if button == self.button_toggle: index = 'toggle' elif button == self.button_stop: index = 'stop' elif button == self.button_next: index = 'next' elif button == self.button_previous: index = 'previous' else: return elif button != 1: return control_state = self._control_states[index] if self._player and self._get_button_state(control_state): getattr(self._player, self._control_states[index]['action'])()
#!/usr/bin/env python # -*- coding: utf-8 -*- from flask import Flask from flask import request app = Flask(__name__) from pydbus import SessionBus bus = SessionBus() try: player = bus.get("github.zhangn1985.dbplay") except: from playthread import Mpvplayer player = Mpvplayer() player.start() import json import types from ykdl.common import url_to_module @app.route('/play', methods=['POST', 'GET']) def play(): if request.method == 'POST': url = request.form['url'] try: islist = request.form['list'] islist = islist == "True" except: islist = False m,u = url_to_module(url)
def command_cb(*args, **kwargs): if SCARLETT_DEBUG: logger.debug("command_cb PrettyPrinter: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(args) # MAR 13 2016 logger.debug("command_cb kwargs") print_keyword_args(**kwargs) # (con=<DBusConnection object at 0x7f3fba21f0f0 (GDBusConnection at 0x2ede000)>, # sender=':1.0', # object='/org/scarlett/Listener', # iface='org.scarlett.Listener', # signal='CommandRecognizedSignal', # params=GLib.Variant('(sss)', (' ScarlettListener caugh...ommand match', 'pi-response', 'what time is it'))) # NOTE: THIS IS WHAT FIXED THE GENERATOR NONSENSE # source: https://www.python.org/dev/peps/pep-0343/ def player_generator_func(): for path in wavefile: path = os.path.abspath(os.path.expanduser(path)) yield True print("for path in wavefile") p = generator_player.ScarlettPlayer(path, False) while True: try: yield p.next() finally: time.sleep(p.duration) p.close(force=True) yield False def run_player(function): gen = function() GObject.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_HIGH) def speaker_generator_func(): for scarlett_text in tts_list: yield True print("scarlett_text in tts_list") _wavepath = "/home/pi/dev/bossjones-github/scarlett-dbus-poc/espeak_tmp.wav" s = generator_speaker.ScarlettSpeaker(text_to_speak=scarlett_text, wavpath=_wavepath, skip_player=True) p = generator_player.ScarlettPlayer(_wavepath, False) logger.error("Duration: p.duration: {}".format(p.duration)) while True: try: yield p.next() finally: time.sleep(p.duration) p.close(force=True) s.close(force=True) yield False def run_speaker(function): gen = function() GObject.idle_add(lambda: next(gen, False), priority=GLib.PRIORITY_HIGH) for i, v in enumerate(args): if SCARLETT_DEBUG: logger.debug("Type v: {}".format(type(v))) logger.debug("Type i: {}".format(type(i))) if isinstance(v, tuple): if SCARLETT_DEBUG: logger.debug( "THIS SHOULD BE A Tuple now: {}".format(v)) msg, scarlett_sound, command = v logger.warning(" msg: {}".format(msg)) logger.warning( " scarlett_sound: {}".format(scarlett_sound)) logger.warning(" command: {}".format(command)) # 1. play sound first wavefile = SoundType.get_path(scarlett_sound) run_player_result = run_player(player_generator_func) # 2. Perform command command_run_results = generator_commands.Command.check_cmd(command_tuple=v) # 3. Verify it is not a command NO_OP if command_run_results == '__SCARLETT_NO_OP__': logger.error("__SCARLETT_NO_OP__") return False # 4. Scarlett Speaks tts_list = SpeakerType.speaker_to_array(command_run_results) run_speaker_result = run_speaker(speaker_generator_func) # 5. Emit signal to reset keyword match ( need to implement this ) bus = SessionBus() ss = bus.get("org.scarlett", object_path='/org/scarlett/Listener') # NOQA time.sleep(1) ss.emitListenerCancelSignal() # 6. Finished call back else: logger.debug("THIS IS NOT A GLib.Variant: {} - TYPE {}".format(v, type(v)))
class ScarlettListenerI(threading.Thread, _IdleObject): """ Attempt to take out all Gstreamer logic and put it in a class ouside the dbus server. Cancellable thread which uses gobject signals to return information to the GUI. """ __gsignals__ = SCARLETT_LISTENER_I_SIGNALS device = PS_DEVICE hmm = HMM_PATH lm = LM_PATH dic = DICT_PATH # SCARLETT_LISTENER_I_SIGNALS = { # "completed": ( # GObject.SignalFlags.RUN_LAST, None, []), # "progress": ( # GObject.SignalFlags.RUN_LAST, None, [ # GObject.TYPE_FLOAT]), # percent complete # "eos": (GObject.SignalFlags.RUN_LAST, None, ()), # "error": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "died": (GObject.SignalFlags.RUN_LAST, None, ()), # "async-done": (GObject.SignalFlags.RUN_LAST, None, ()), # "state-change": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_INT, GObject.TYPE_INT)), # # FIXME: AUDIT THE RETURN TYPES # "keyword-recgonized": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "command-recgonized": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "stt-failed": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "listener-cancel": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "listener-ready": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "connected-to-server": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # "listener-message": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING, GObject.TYPE_STRING)), # 'finished': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,)), # 'aborted': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,)) # } def __init__(self, *args): threading.Thread.__init__(self) _IdleObject.__init__(self) # Gst.init(None) self.running = False self.finished = False self.ready_sem = threading.Semaphore(0) self.queue = queue.Queue(QUEUE_SIZE) # This wil get filled with an exception if opening fails. self.read_exc = None self.dot_exc = None self.cancelled = False self.name = args[0] self.setName("%s" % self.name) self.pipelines_stack = [] self.elements_stack = [] self.gst_bus_stack = [] self._message = 'This is the ScarlettListenerI' self.config = scarlett_config.Config() self.override_parse = '' self.failed = 0 self.kw_found = 0 self.debug = False self.create_dot = True self.terminate = False self.capsfilter_queue_overrun_handler = None # source: https://github.com/ljmljz/xpra/blob/b32f748e0c29cdbfab836b3901c1e318ea142b33/src/xpra/sound/sound_pipeline.py # NOQA self.bus = None self.bus_message_element_handler_id = None self.bus_message_error_handler_id = None self.bus_message_eos_handler_id = None self.bus_message_state_changed_handler_id = None self.pipeline = None self.start_time = 0 self.state = "stopped" self.buffer_count = 0 self.byte_count = 0 # # Thread manager, maximum of 1 since it'll be long running # self.manager = FooThreadManager(1) self._status_ready = " ScarlettListener is ready" self._status_kw_match = " ScarlettListener caught a keyword match" self._status_cmd_match = " ScarlettListener caught a command match" self._status_stt_failed = " ScarlettListener hit Max STT failures" self._status_cmd_start = " ScarlettListener emitting start command" self._status_cmd_fin = " ScarlettListener Emitting Command run finish" self._status_cmd_cancel = " ScarlettListener cancel speech Recognition" if self.debug: # NOTE: For testing puposes, mainly when in public # so you dont have to keep yelling scarlett in front of strangers self.kw_to_find = ['yo', 'hello', 'man', 'children'] else: self.kw_to_find = self.config.get('scarlett', 'keywords') if self.read_exc: # An error occurred before the stream became ready. self.close(True) raise self.read_exc def connect_to_dbus(self): # self.dbus_stack.append(bus) # self.dbus_stack.append(path) # logger.debug("Inside self.dbus_stack") # pp.pprint(self.dbus_stack) pass def scarlett_reset_listen(self): self.failed = 0 self.kw_found = 0 def cancel_listening(self, *args, **kwargs): logger.debug("Inside cancel_listening function") self.scarlett_reset_listen() logger.debug("self.failed = %i" % (self.failed)) logger.debug( "self.keyword_identified = %i" % (self.kw_found)) def play(self): p = self.pipelines_stack[0] self.state = "active" self.running = True # GST_STATE_PAUSED is the state in which an element is ready to accept and handle data. # For most elements this state is the same as PLAYING. The only exception to this rule are sink elements. # Sink elements only accept one single buffer of data and then block. # At this point the pipeline is 'prerolled' and ready to render data immediately. p.set_state(Gst.State.PAUSED) # GST_STATE_PLAYING is the highest state that an element can be in. # For most elements this state is exactly the same as PAUSED, # they accept and process events and buffers with data. # Only sink elements need to differentiate between PAUSED and PLAYING state. # In PLAYING state, sink elements actually render incoming data, # e.g. output audio to a sound card or render video pictures to an image sink. ret = p.set_state(Gst.State.PLAYING) if ret == Gst.StateChangeReturn.FAILURE: logger.error("ERROR: Unable to set the pipeline to the playing state") self.on_debug_activate() logger.debug("BEFORE: self.ready_sem.acquire()") self.ready_sem.acquire() logger.debug("AFTER: self.ready_sem.acquire()") logger.info("Press Ctrl+C to quit ...") # @trace def stop(self): p = self.pipelines_stack[0] self.state = "stopped" self.running = False # GST_STATE_NULL is the default state of an element. # In this state, it has not allocated any runtime resources, # it has not loaded any runtime libraries and it can obviously not handle data. p.set_state(Gst.State.NULL) def get_pocketsphinx_definition(self, override=False): """ GST_DEBUG=2,pocketsphinx*:5 gst-launch-1.0 alsasrc device=plughw:CARD=Device,DEV=0 ! \ queue name=capsfilter_queue \ leaky=2 \ max-size-buffers=0 \ max-size-time=0 \ max-size-bytes=0 ! \ capsfilter caps='audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved' ! \ audioconvert ! \ audioresample ! \ pocketsphinx \ name=asr \ lm=~/dev/bossjones-github/scarlett-dbus-poc/tests/fixtures/lm/1473.lm \ dict=~/dev/bossjones-github/scarlett-dbus-poc/tests/fixtures/dict/1473.dic \ hmm=~/.virtualenvs/scarlett-dbus-poc/share/pocketsphinx/model/en-us/en-us bestpath=true ! \ tee name=tee ! \ queue name=appsink_queue \ leaky=2 \ max-size-buffers=0 \ max-size-time=0 \ max-size-bytes=0 ! \ appsink caps='audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved' \ drop=false max-buffers=10 sync=false \ emit-signals=true tee. queue name=fakesink_queue \ leaky=2 \ max-size-buffers=0 \ max-size-time=0 \ max-size-bytes=0 ! \ fakesink sync=false """ logger.debug("Inside get_pocketsphinx_definition") if override: _gst_launch = override else: _gst_launch = ['alsasrc device=' + ScarlettListenerI.device, # source: https://github.com/walterbender/story/blob/master/grecord.py # without a buffer here, gstreamer struggles at the start of the # recording and then the A/V sync is bad for the whole video # (possibly a gstreamer/ALSA bug -- even if it gets caught up, it # should be able to resync without problem) 'queue name=capsfilter_queue silent=false leaky=2 max-size-buffers=0 max-size-time=0 max-size-bytes=0', 'capsfilter name=capsfilter caps=audio/x-raw,format=S16LE,channels=1,layout=interleaved', 'audioconvert name=audioconvert', 'audioresample name=audioresample', 'identity name=ident', 'pocketsphinx name=asr', 'tee name=tee', 'queue name=appsink_queue silent=false leaky=2 max-size-buffers=0 max-size-time=0 max-size-bytes=0', # caps=audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved # NOQA 'appsink name=appsink drop=false max-buffers=10 sync=false emit-signals=true tee.', 'queue leaky=2 name=fakesink_queue', 'fakesink'] return _gst_launch # @trace def cancel(self): """ Threads in python are not cancellable, so we implement our own cancellation logic """ self.cancelled = True @abort_on_exception def run(self, event=None): # TODO: WE NEED TO USE A THREADING EVENT OR A RLOCK HERE TO WAIT TILL DBUS SERVICE IS RUNNING TO CONNECT # TODO: SIGNALS TO THE DBUS PROXY METHODS WE WANT TO USE # TODO: lock.acquire() / event / condition # TODO: self.connect_to_dbus() # TODO: self.setup_dbus_callbacks_handlers() self._connect_to_dbus() self.init_gst() print "Running %s" % str(self) self.play() self.emit('playback-status-changed') self.emit('playing-changed') # FIXME: is this needed? # self.mainloop.run() def _connect_to_dbus(self): self.bus = SessionBus() self.dbus_proxy = self.bus.get("org.scarlett", object_path='/org/scarlett/Listener') # NOQA self.dbus_proxy.emitConnectedToListener('ScarlettListener') sleep(2) logger.info('_connect_to_dbus') ss_cancel_signal = self.bus.subscribe(sender=None, iface="org.scarlett.Listener", signal="ListenerCancelSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=self.cancel_listening) # NOTE: This function generates the dot file, checks that graphviz in installed and # then finally generates a png file, which it then displays def on_debug_activate(self): dotfile = "/home/pi/dev/bossjones-github/scarlett-dbus-poc/_debug/generator-listener.dot" pngfile = "/home/pi/dev/bossjones-github/scarlett-dbus-poc/_debug/generator-listener-pipeline.png" # NOQA if os.access(dotfile, os.F_OK): os.remove(dotfile) if os.access(pngfile, os.F_OK): os.remove(pngfile) Gst.debug_bin_to_dot_file(self.pipelines_stack[0], Gst.DebugGraphDetails.ALL, "generator-listener") os.system('/usr/bin/dot' + " -Tpng -o " + pngfile + " " + dotfile) def result(self, final_hyp): """Forward result signals on the bus to the main thread.""" logger.debug("Inside result function") logger.debug("final_hyp: {}".format(final_hyp)) pp.pprint(final_hyp) logger.debug("kw_to_find: {}".format(self.kw_to_find)) if final_hyp in self.kw_to_find and final_hyp != '': logger.debug( "HYP-IS-SOMETHING: " + final_hyp + "\n\n\n") self.failed = 0 self.kw_found = 1 self.dbus_proxy.emitKeywordRecognizedSignal() # CHANGEME else: failed_temp = self.failed + 1 self.failed = failed_temp logger.debug( "self.failed = %i" % (self.failed)) if self.failed > 4: # reset pipline self.dbus_proxy.emitSttFailedSignal() # CHANGEME self.scarlett_reset_listen() def run_cmd(self, final_hyp): logger.debug("Inside run_cmd function") logger.debug("KEYWORD IDENTIFIED BABY") logger.debug( "self.kw_found = %i" % (self.kw_found)) if final_hyp == 'CANCEL': self.dbus_proxy.emitListenerCancelSignal() # CHANGEME self.cancel_listening() else: current_kw_identified = self.kw_found self.kw_found = current_kw_identified self.dbus_proxy.emitCommandRecognizedSignal(final_hyp) # CHANGEME logger.info( " Command = {}".format(final_hyp)) logger.debug( "AFTER run_cmd, self.kw_found = %i" % (self.kw_found)) def init_gst(self): logger.debug("Inside init_gst") self.start_time = time.time() pipeline = Gst.parse_launch(' ! '.join(self.get_pocketsphinx_definition())) logger.debug("After get_pocketsphinx_definition") # Add pipeline obj to stack we can pull from later self.pipelines_stack.append(pipeline) gst_bus = pipeline.get_bus() # gst_bus = pipeline.get_gst_bus() gst_bus.add_signal_watch() self.bus_message_element_handler_id = gst_bus.connect("message::element", self._on_message) self.bus_message_eos_handler_id = gst_bus.connect("message::eos", self._on_message) self.bus_message_error_handler_id = gst_bus.connect("message::error", self._on_message) self.bus_message_state_changed_handler_id = gst_bus.connect("message::state-changed", self._on_state_changed) # Add bus obj to stack we can pull from later self.gst_bus_stack.append(gst_bus) appsink = pipeline.get_by_name('appsink') appsink.set_property( 'caps', Gst.Caps.from_string('audio/x-raw,format=(string)S16LE,rate=(int)16000,channels=(int)1,layout=(string)interleaved'), ) appsink.set_property('drop', False) appsink.set_property('max-buffers', BUFFER_SIZE) appsink.set_property('sync', False) # The callback to receive decoded data. appsink.set_property('emit-signals', True) appsink.connect("new-sample", self._new_sample) self.caps_handler = appsink.get_static_pad("sink").connect( "notify::caps", self._notify_caps ) self.elements_stack.append(appsink) # get gst pipeline element pocketsphinx and set properties pocketsphinx = pipeline.get_by_name('asr') if ScarlettListenerI.hmm: pocketsphinx.set_property('hmm', ScarlettListenerI.hmm) if ScarlettListenerI.lm: pocketsphinx.set_property('lm', ScarlettListenerI.lm) if ScarlettListenerI.dic: pocketsphinx.set_property('dict', ScarlettListenerI.dic) pocketsphinx.set_property('fwdflat', True) # Enable Flat Lexicon Search | Default: true pocketsphinx.set_property('bestpath', True) # Enable Graph Search | Boolean. Default: true pocketsphinx.set_property('dsratio', 1) # Evaluate acoustic model every N frames | Integer. Range: 1 - 10 Default: 1 pocketsphinx.set_property('maxhmmpf', 3000) # Maximum number of HMMs searched per frame | Integer. Range: 1 - 100000 Default: 30000 pocketsphinx.set_property('bestpath', True) # Enable Graph Search | Boolean. Default: true # pocketsphinx.set_property('maxwpf', -1) # pocketsphinx.set_property('maxwpf', 20) # Maximum number of words searched per frame | Range: 1 - 100000 Default: -1 self.elements_stack.append(pocketsphinx) capsfilter_queue = pipeline.get_by_name('capsfilter_queue') capsfilter_queue.set_property('leaky', True) # prefer fresh data capsfilter_queue.set_property('silent', False) capsfilter_queue.set_property('max-size-time', 0) # 0 seconds capsfilter_queue.set_property('max-size-buffers', 0) capsfilter_queue.set_property('max-size-bytes', 0) self.capsfilter_queue_overrun_handler = capsfilter_queue.connect('overrun', self._log_queue_overrun) # capsfilter_queue.connect('overrun', self._on_overrun) # capsfilter_queue.connect('underrun', self._on_underrun) # capsfilter_queue.connect('pushing', self._on_pushing) # capsfilter_queue.connect('running', self._on_running) self.elements_stack.append(capsfilter_queue) ident = pipeline.get_by_name('ident') # ident.connect('handoff', self._on_handoff) self.elements_stack.append(ident) logger.debug("After all self.elements_stack.append() calls") # Set up the queue for data and run the main thread. self.queue = queue.Queue(QUEUE_SIZE) self.thread = get_loop_thread() def _on_handoff(self, element, buf): logger.debug('buf:') pp.pprint(buf) pp.pprint(dir(buf)) logger.debug('on_handoff - %d bytes' % len(buf)) # print 'buf =', buf # print 'dir(buf) =', dir(buf) if self.signed is None: # only ever one caps struct on our buffers struct = buf.get_caps().get_structure(0) # I think these are always set too, but catch just in case try: self.signed = struct["signed"] self.depth = struct["depth"] self.rate = struct["rate"] self.channels = struct["channels"] except: logger.debug('on_handoff: missing caps') pass # raw = str(buf) # # # print 'len(raw) =', len(raw) # # sm = 0 # for i in range(0, len(raw)): # sm += ord(raw[i]) # # print sm # FIXEME: Add somthing like analyse.py # SOURCE: https://github.com/jcupitt/huebert/blob/master/huebert/audio.py def _on_state_changed(self, bus, msg): states = msg.parse_state_changed() # To state is PLAYING if msg.src.get_name() == "pipeline0" and states[1] == 4: logger.info('Inside pipeline0 on _on_state_changed') logger.info("State: {}".format(states[1])) self.ready_sem.release() return False else: # logger.error('NOTHING RETURNED in _on_state_changed') logger.info("State: {}".format(states[1])) def _on_overrun(self, element): logging.debug('on_overrun') def _on_underrun(self, element): logging.debug('on_underrun') def _on_running(self, element): logging.debug('on_running') def _on_pushing(self, element): logging.debug('on_pushing') def _notify_caps(self, pad, args): """The callback for the sinkpad's "notify::caps" signal. """ # The sink has started to receive data, so the stream is ready. # This also is our opportunity to read information about the # stream. self.got_caps = True # Allow constructor to complete. self.ready_sem.release() _got_a_pad = False def _log_queue_overrun(self, queue): cbuffers = queue.get_property('current-level-buffers') cbytes = queue.get_property('current-level-bytes') ctime = queue.get_property('current-level-time') def _new_sample(self, sink): """The callback for appsink's "new-sample" signal. """ if self.running: # New data is available from the pipeline! Dump it into our # queue (or possibly block if we're full). buf = sink.emit('pull-sample').get_buffer() self.queue.put(buf.extract_dup(0, buf.get_size())) return Gst.FlowReturn.OK def _on_message(self, bus, message): """The callback for GstBus's "message" signal (for two kinds of messages). """ # logger.debug("[_on_message](%s, %s)", bus, message) if not self.finished: struct = message.get_structure() if message.type == Gst.MessageType.EOS: # The file is done. Tell the consumer thread. self.queue.put(SENTINEL) if not self.got_caps: logger.error( "If the stream ends before _notify_caps was called, this is an invalid stream.") # If the stream ends before _notify_caps was called, this # is an invalid file. self.read_exc = generator_utils.NoStreamError() self.ready_sem.release() elif struct and struct.get_name() == 'pocketsphinx': if struct['final']: logger.info(struct['hypothesis']) if self.kw_found == 1: # If keyword is set AND qualifier # then perform action self.run_cmd(struct['hypothesis']) else: # If it's the main keyword, # set values wait for qualifier self.result(struct['hypothesis']) elif message.type == Gst.MessageType.ERROR: gerror, debug = message.parse_error() pp.pprint(("gerror,debug:", gerror, debug)) if 'not-linked' in debug: logger.error('not-linked') self.read_exc = generator_utils.NoStreamError() elif 'No such device' in debug: logger.error('No such device') self.read_exc = generator_utils.NoStreamError() else: logger.info("FileReadError") pp.pprint(("SOME FileReadError", bus, message, struct, struct.get_name())) self.read_exc = generator_utils.FileReadError(debug) self.ready_sem.release() # Cleanup. def close(self, force=False): """Close the file and clean up associated resources. Calling `close()` a second time has no effect. """ if self.running or force: self.running = False self.finished = True try: gst_bus = self.gst_bus_stack[0] except: logger.error("Failed to get gst_bus from gst_bus_stack[0]") pass if gst_bus: gst_bus.remove_signal_watch() if self.bus_message_element_handler_id: gst_bus.disconnect(self.bus_message_element_handler_id) if self.bus_message_error_handler_id: gst_bus.disconnect(self.bus_message_error_handler_id) if self.bus_message_eos_handler_id: gst_bus.disconnect(self.bus_message_eos_handler_id) if self.bus_message_state_changed_handler_id: gst_bus.disconnect(self.bus_message_state_changed_handler_id) self.bus = None self.pipeline = None self.codec = None self.bitrate = -1 self.state = None # Unregister for signals, which we registered for above with # `add_signal_watch`. (Without this, GStreamer leaks file # descriptors.) logger.debug('BEFORE p = self.pipelines_stack[0]') p = self.pipelines_stack[0] p.get_bus().remove_signal_watch() logger.debug('AFTER p.get_bus().remove_signal_watch()') # Block spurious signals. appsink = self.elements_stack[0] appsink.get_static_pad("sink").disconnect(self.caps_handler) # Make space in the output queue to let the decoder thread # finish. (Otherwise, the thread blocks on its enqueue and # the interpreter hangs.) try: self.queue.get_nowait() except queue.Empty: pass # Halt the pipeline (closing file). self.stop() # Delete the pipeline object. This seems to be necessary on Python # 2, but not Python 3 for some reason: on 3.5, at least, the # pipeline gets dereferenced automatically. del p def __del__(self): self.close() def __exit__(self, exc_type, exc_val, exc_tb): self.close() return False
from scarlett_os.internal.debugger import init_debugger from scarlett_os.internal.debugger import set_gst_grapviz_tracing init_debugger() set_gst_grapviz_tracing() # Example of how to use it loop = GLib.MainLoop() recieved_signals = [] from pydbus import SessionBus bus = SessionBus() ss = bus.get("org.scarlett", object_path="/org/scarlett/Listener") time.sleep(0.5) # taken from tasker ss_failed_signal = bus.subscribe( sender=None, iface="org.scarlett.Listener", signal="SttFailedSignal", object="/org/scarlett/Listener", arg0=None, flags=0, signal_fired=catchall_handler, ) ss_rdy_signal = bus.subscribe( sender=None,
#!/usr/bin/env python # Based on http://stackoverflow.com/questions/22390064/use-dbus-to-just-send-a-message-in-python # Python script to call the methods of the DBUS Test Server from pydbus import SessionBus #get the session bus bus = SessionBus() #get the object the_object = bus.get("net.lew21.pydbus.ClientServerExample") #call the methods and print the results reply = the_object.Hello() print(reply) reply = the_object.EchoString("test 123") print(reply) the_object.Quit()
#!/usr/bin/python from pydbus import SessionBus session_bus = SessionBus() bkd_obj = session_bus.get('org.geekpur.vishal.BKD', '/org/geekpur/vishal/BKD') print bkd_obj.GetBackspaceCount()
def __init__(self): Gtk.Window.__init__(self, title=TITLE) #self.set_default_size(150, 100) grid_main = Gtk.Grid() self.add(grid_main) # Modify the overall font name and size, for use with video projection. if PROJECTOR: pangoFont = Pango.FontDescription(PROJECTOR_FONT) self.modify_font(pangoFont) # Get the session dbus bus = SessionBus() # Get the object try: self.server_1_object = bus.get(BUS) except GLib.Error as e: print("GLib.Error: {}.\nIs the server running?".format(BUS)) #print(e) sys.exit("Exiting...") except GDBus.Error as e: # Doesn't seem to have GDBus.Error as an error. # TODO: Remove is never detected print("Error 2") print(e) # TODO: Check if it can hang here. If bus not registered / available? # Create Frames to group different data in. frame_1 = Gtk.Frame(label=FRAME_1, margin=10) grid_main.attach(frame_1, 0, 0, 1, 1) frame_2 = Gtk.Frame(label=FRAME_2, margin=10) grid_main.attach(frame_2, 1, 0, 1, 1) frame_3 = Gtk.Frame(label=FRAME_3, margin=10) grid_main.attach(frame_3, 0, 1, 1, 2) frame_4 = Gtk.Frame(label=FRAME_4, margin=10) grid_main.attach(frame_4, 1, 1, 1, 1) frame_5 = Gtk.Frame(label=FRAME_4, margin=10) grid_main.attach(frame_5, 1, 2, 1, 1) # Frame_1 Grid for widgets grid_frame_1 = Gtk.Grid() frame_1.add(grid_frame_1) # Frame_1 Static labels. xalign float from 0 = left to 1 = right f1_label_1 = Gtk.Label(F1_LABEL_1, margin=10, xalign=1) f1_label_2 = Gtk.Label(F1_LABEL_2, margin=10, xalign=1) f1_label_3 = Gtk.Label(F1_LABEL_3, margin=10, xalign=1) f1_label_4 = Gtk.Label(F1_LABEL_4, margin=10, xalign=1) f1_label_5 = Gtk.Label(F1_LABEL_5, margin=10, xalign=1) # Frame_1 Attach to grid grid_frame_1.attach(f1_label_1, 0, 0, 1, 1,) grid_frame_1.attach(f1_label_2, 0, 1, 1, 1,) grid_frame_1.attach(f1_label_3, 0, 2, 1, 1,) grid_frame_1.attach(f1_label_4, 0, 3, 1, 1,) grid_frame_1.attach(f1_label_5, 0, 4, 1, 1,) # Frame_1 Dynamic labels. Provide self. # So they can be updated by any method. self.f1_label_1a = Gtk.Label("0", margin=10, xalign=1) self.f1_label_2a = Gtk.Label("0", margin=10, xalign=1) self.f1_label_3a = Gtk.Label("0", margin=10, xalign=1) self.f1_label_4a = Gtk.Label("0", margin=10, xalign=1) self.f1_label_5a = Gtk.Label("0", margin=10, xalign=1) # Frame_1 Attach to grid grid_frame_1.attach(self.f1_label_1a, 1, 0, 1, 1,) grid_frame_1.attach(self.f1_label_2a, 1, 1, 1, 1,) grid_frame_1.attach(self.f1_label_3a, 1, 2, 1, 1,) grid_frame_1.attach(self.f1_label_4a, 1, 3, 1, 1,) grid_frame_1.attach(self.f1_label_5a, 1, 4, 1, 1,) # Frame_1 Progress bar self.f1_progressbar_1 = Gtk.ProgressBar() grid_frame_1.attach(self.f1_progressbar_1, 2, 0, 1, 1,) self.f1_progressbar_1.set_fraction(0) # Frame_2 Grid for widgets grid_frame_2 = Gtk.Grid() frame_2.add(grid_frame_2) # Frame_2 Static labels. f2_label_1 = Gtk.Label(F2_LABEL_1, margin=10, xalign=1) f2_label_2 = Gtk.Label(F2_LABEL_2, margin=10, xalign=1) f2_label_3 = Gtk.Label(F2_LABEL_3, margin=10, xalign=1) f2_label_4 = Gtk.Label(F2_LABEL_4, margin=10, xalign=1) f2_label_5 = Gtk.Label(F2_LABEL_5, margin=10, xalign=1) f2_label_6 = Gtk.Label(F2_LABEL_6, margin=10, xalign=1) # Frame_2 Attach to grid grid_frame_2.attach(f2_label_1, 0, 0, 1, 1,) grid_frame_2.attach(f2_label_2, 0, 1, 1, 1,) grid_frame_2.attach(f2_label_3, 0, 2, 1, 1,) grid_frame_2.attach(f2_label_4, 0, 3, 1, 1,) grid_frame_2.attach(f2_label_5, 0, 4, 1, 1,) grid_frame_2.attach(f2_label_6, 0, 5, 1, 1,) # Frame_2 Dynamic labels. self.f2_label_1a = Gtk.Label("0", margin=10, xalign=1) self.f2_label_2a = Gtk.Label("0", margin=10, xalign=1) self.f2_label_3a = Gtk.Label("0", margin=10, xalign=1) self.f2_label_4a = Gtk.Label("0", margin=10, xalign=1) self.f2_label_5a = Gtk.Label("0", margin=10, xalign=1) self.f2_label_6a = Gtk.Label("0", margin=10, xalign=1) # Frame_2 Attach to grid grid_frame_2.attach(self.f2_label_1a, 1, 0, 1, 1,) grid_frame_2.attach(self.f2_label_2a, 1, 1, 1, 1,) grid_frame_2.attach(self.f2_label_3a, 1, 2, 1, 1,) grid_frame_2.attach(self.f2_label_4a, 1, 3, 1, 1,) grid_frame_2.attach(self.f2_label_5a, 1, 4, 1, 1,) grid_frame_2.attach(self.f2_label_6a, 1, 5, 1, 1,) # Frame_3 Grid for widgets grid_frame_3 = Gtk.Grid() frame_3.add(grid_frame_3) # Frame_3 Static labels. f3_label_1 = Gtk.Label(F3_LABEL_1, margin=10, xalign=1) f3_label_2 = Gtk.Label(F3_LABEL_2, margin=10, xalign=1) f3_label_3 = Gtk.Label(F3_LABEL_3, margin=10, xalign=1) f3_label_4 = Gtk.Label(F3_LABEL_4, margin=10, xalign=1) # Frame_3 Attach to grid grid_frame_3.attach(f3_label_1, 0, 0, 1, 1,) grid_frame_3.attach(f3_label_2, 0, 1, 1, 1,) grid_frame_3.attach(f3_label_3, 0, 2, 1, 1,) grid_frame_3.attach(f3_label_4, 0, 3, 1, 1,) # Frame_3 Dynamic labels. self.f3_label_1a = Gtk.Label("0", margin=10, xalign=1) self.f3_label_2a = Gtk.Label("0", margin=10, xalign=1) self.f3_label_3a = Gtk.Label("0", margin=10, xalign=1) self.f3_label_4a = Gtk.Label("0", margin=10, xalign=1) # Frame_3 Attach to grid grid_frame_3.attach(self.f3_label_1a, 1, 0, 1, 1,) grid_frame_3.attach(self.f3_label_2a, 1, 1, 1, 1,) grid_frame_3.attach(self.f3_label_3a, 1, 2, 1, 1,) grid_frame_3.attach(self.f3_label_4a, 1, 3, 1, 1,) # Frame_3 Progress bar. self.f3_progressbar_1 = Gtk.ProgressBar() grid_frame_3.attach(self.f3_progressbar_1, 2, 0, 1, 1,) self.f3_progressbar_1.set_fraction(0) # Frame_4 Grid for widgets grid_frame_4 = Gtk.Grid() frame_4.add(grid_frame_4) # Frame_4 Buttons. Start/Stop/Reset buttons. self.f4_button_1 = Gtk.Button(label=F4_BUTTON_1, margin=10) self.f4_button_2 = Gtk.Button(label=F4_BUTTON_2, margin=10) self.f4_button_2.set_sensitive(False) self.f4_button_3 = Gtk.Button(label=F4_BUTTON_3, margin=10) self.f4_button_4 = Gtk.Button(label=F4_BUTTON_4, margin=10) # Frame_4 Button call-back signals self.f4_button_1.connect("clicked", self.cb_f4_button_1, self.f4_button_2) self.f4_button_2.connect("clicked", self.cb_f4_button_2, self.f4_button_1) self.f4_button_3.connect("clicked", self.cb_f4_button_3) self.f4_button_4.connect("clicked", self.cb_f4_button_4) # Frame_4 Attach to grid grid_frame_4.attach(self.f4_button_1, 0, 0, 1, 1, ) grid_frame_4.attach(self.f4_button_2, 1, 0, 1, 1, ) grid_frame_4.attach(self.f4_button_3, 2, 0, 1, 1, ) grid_frame_4.attach(self.f4_button_4, 3, 0, 1, 1, ) # Frame_5 Grid for widgets grid_frame_5 = Gtk.Grid() frame_5.add(grid_frame_5) # Frame_5 Buttons. Start/Stop/Reset buttons. self.f5_button_1 = Gtk.Button(label=F5_BUTTON_1, margin=10) self.f5_button_2 = Gtk.Button(label=F5_BUTTON_2, margin=10) self.f5_button_3 = Gtk.Button(label=F5_BUTTON_3, margin=10) self.f5_button_4 = Gtk.Button(label=F5_BUTTON_4, margin=10) # Frame_5 Button call-back signals self.f5_button_1.connect("clicked", self.cb_f5_button_1) self.f5_button_2.connect("clicked", self.cb_f5_button_2) self.f5_button_3.connect("clicked", self.cb_f5_button_3) self.f5_button_4.connect("clicked", self.cb_f5_button_4) # Frame_5 Attach to grid grid_frame_5.attach(self.f5_button_1, 0, 0, 1, 1, ) grid_frame_5.attach(self.f5_button_2, 1, 0, 1, 1, ) grid_frame_5.attach(self.f5_button_3, 2, 0, 1, 1, ) grid_frame_5.attach(self.f5_button_4, 3, 0, 1, 1, ) # Launch with client started... self.cb_f4_button_1(self.f4_button_1, self.f4_button_2)
from __future__ import print_function from pydbus import SessionBus from gi.repository import GLib import subprocess from time import sleep loop = GLib.MainLoop() subprocess.Popen("gnome-music") sleep(5) print("Waiting for GNOME Music to start...") b = SessionBus() m = b.get("org.mpris.MediaPlayer2.GnomeMusic", "/org/mpris/MediaPlayer2") m.PropertiesChanged.connect(print) m.ActivatePlaylist(m.GetPlaylists(0, 5, "Alphabetical", 0)[0][0]) m.Play() sleep(1) assert(m.PlaybackStatus == "Playing") m.Pause() assert(m.PlaybackStatus == "Paused") m.Play() assert(m.PlaybackStatus == "Playing") t = m.Metadata["xesam:title"]
return if conv in chat: send_me = nick + "--" if len(reason) > 0: send_me += " (" + reason + ")" for target_conv in iter(set(chat)-set([conv])): purple.PurpleConvChatSend(purple.PurpleConversationGetChatData(target_conv), send_me) debug_print(target_conv, send_me) # start main proc bus = SessionBus() purple = bus.get("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject") print ">>> Rainbow 🌈 Bridge for Libpurple/Finch/Pidgin <<<" for conv in purple.PurpleGetConversations(): name = purple.PurpleConversationGetName(conv) if name in bridge_me: chat[conv] = { "nick": purple.PurpleConvChatGetNick(purple.PurpleConversationGetChatData(conv)), "protocol": purple.PurpleAccountGetProtocolName(purple.PurpleConversationGetAccount(conv)), "announce": name not in dont_announce, } for conv in chat.keys(): print "<->", chat[conv]["nick"], "on", purple.PurpleConversationGetName(conv), "(" + str(conv) + ")", "using", chat[conv]["protocol"]