From f68eeb323141546fcfa62f999e2fe2f9f290f4dc Mon Sep 17 00:00:00 2001 From: noah Date: Wed, 3 Aug 2022 15:01:09 -0500 Subject: [PATCH] Containing spotify module to reside soley within polybar config directory --- polybar/spotify/launchlistener.sh | 3 + polybar/spotify/py_spotify_listener.py | 124 +++++++++++++++++++++++++ polybar/spotify/spotify_status.py | 67 +++++++++++++ polybar/user_modules.ini | 2 +- 4 files changed, 195 insertions(+), 1 deletion(-) create mode 100755 polybar/spotify/launchlistener.sh create mode 100755 polybar/spotify/py_spotify_listener.py create mode 100755 polybar/spotify/spotify_status.py diff --git a/polybar/spotify/launchlistener.sh b/polybar/spotify/launchlistener.sh new file mode 100755 index 0000000..04889e8 --- /dev/null +++ b/polybar/spotify/launchlistener.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh + +/usr/bin/env python3 ~/.config/polybar/spotify/py_spotify_listener.py diff --git a/polybar/spotify/py_spotify_listener.py b/polybar/spotify/py_spotify_listener.py new file mode 100755 index 0000000..e960411 --- /dev/null +++ b/polybar/spotify/py_spotify_listener.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# Unwrap function: (C)2011-2015 Dennis Kaarsemaker +# License: GPL3+ +"""Receiver related functionality.""" +import dbus.service +import dbus.glib +from os import system +from gi.repository import GObject +import dbus + + +class Test(dbus.service.Object): + """Reciever test class.""" + + loop = None + + def __init__(self, bus_name, object_path, loop): + """Initialize the DBUS service object.""" + dbus.service.Object.__init__(self, bus_name, object_path) + self.loop = loop + + @dbus.service.method('tld.domain.sub.TestInterface') + def foo(self): + """Return a string.""" + return 'Foo' + + # Stop the main loop + @dbus.service.method('tld.domain.sub.TestInterface') + def stop(self): + """Stop the receiver.""" + self.loop.quit() + return 'Quit loop' + + # Pass an exception through dbus + @dbus.service.method('tld.domain.sub.TestInterface') + def fail(self): + """Trigger an exception.""" + raise Exception('FAIL!') + + +def catchall_handler(*args, **kwargs): + """Catch all handler. + Catch and print information about all singals. + """ + print('---- Caught signal ----') + print('%s:%s\n' % (kwargs['dbus_interface'], kwargs['member'])) + + print("\n") + +def quit_handler(): + """Signal handler for quitting the receiver.""" + print('Quitting....') + loop.quit() + +def event_handler(*args, **kwargs): + """event handler for the receiver.""" + """arg[1] contains metadata""" + """arg[1][1] contains PlaybackStatus""" + data = unwrap(args) + if 'spotify' in data[1]['Metadata']['mpris:trackid']: + if data[1]['PlaybackStatus'] == "Playing": + print("Music is playing") + system("polybar-msg hook playpause 2") + """ Send IPC hook 2 to all bars for module playpause """ + if data[1]['PlaybackStatus'] == "Paused": + print("Music is paused.") + """ Send IPC hook 3 to all bars module playpause """ + system("polybar-msg hook playpause 3") + """ Send IPC hook 2 to all bars for module spotify """ + system("polybar-msg hook spotify 2") + +def unwrap(val): + if isinstance(val, dbus.ByteArray): + return "".join([str(x) for x in val]) + if isinstance(val, (dbus.Array, list, tuple)): + return [unwrap(x) for x in val] + if isinstance(val, (dbus.Dictionary, dict)): + return dict([(unwrap(x), unwrap(y)) for x, y in val.items()]) + if isinstance(val, (dbus.Signature, dbus.String)): + return str(val) + if isinstance(val, dbus.Boolean): + return bool(val) + if isinstance(val, (dbus.Int16, dbus.UInt16, dbus.Int32, dbus.UInt32, dbus.Int64, dbus.UInt64)): + return int(val) + if isinstance(val, dbus.Byte): + return bytes([int(val)]) + return val + +loop = GObject.MainLoop() + +""" +First we get the bus to attach to. This may be either the session bus, of the +system bus. For system bus root permission is required. +We claim a bus name on the chosen bus. The name should be in form of a +domain name. +""" +bus = dbus.SessionBus() +# bus = dbus.SystemBus() +bus_name = dbus.service.BusName('sub.domain.tld', bus=bus) + +""" +We initialize our service object with our name and object path. Object +path should be in form of a reverse domain dame, delimited by / instead of . +and the Class name as last part. +The object path we set here is of importance for our invoker, since it will to +call it exactly as defined here. +""" +obj = Test(bus_name, '/tld/domain/sub/Test', loop) + + +""" +Attach signal handler. +Signal handlers may be attached in different ways, either by interface keyword +or DBUS interface and a signal name or member keyword. +You can easily gather all information by running the DBUS monitor. +""" +bus.add_signal_receiver(quit_handler, + dbus_interface='tld.domain.sub.event', + signal_name='quit_signal') +bus.add_signal_receiver(event_handler, + dbus_interface='org.freedesktop.DBus.Properties', + member_keyword='PropertiesChanged') + +loop.run() diff --git a/polybar/spotify/spotify_status.py b/polybar/spotify/spotify_status.py new file mode 100755 index 0000000..4476987 --- /dev/null +++ b/polybar/spotify/spotify_status.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +import sys +import dbus +import argparse + + +parser = argparse.ArgumentParser() +parser.add_argument( + '-t', + '--trunclen', + type=int, + metavar='trunclen' +) +parser.add_argument( + '-f', + '--format', + type=str, + metavar='custom format', + dest='custom_format' +) +args = parser.parse_args() + +# Default parameters +output = '{artist}: {song}' +trunclen = 25 + +# parameters can be overwritten by args +if args.trunclen is not None: + trunclen = args.trunclen +if args.custom_format is not None: + output = args.custom_format + +try: + session_bus = dbus.SessionBus() + spotify_bus = session_bus.get_object( + 'org.mpris.MediaPlayer2.spotify', + '/org/mpris/MediaPlayer2' + ) + + spotify_properties = dbus.Interface( + spotify_bus, + 'org.freedesktop.DBus.Properties' + ) + + metadata = spotify_properties.Get('org.mpris.MediaPlayer2.Player', 'Metadata') + + artist = metadata['xesam:artist'][0] + song = metadata['xesam:title'] + + if len(song) > trunclen: + song = song[0:trunclen] + song += '...' + if ('(' in song) and (')' not in song): + song += ')' + + # Python3 uses UTF-8 by default. + if sys.version_info.major == 3: + print(output.format(artist=artist, song=song)) + else: + print(output.format(artist=artist, song=song).encode('UTF-8')) +except Exception as e: + if isinstance(e, dbus.exceptions.DBusException): + print('') + else: + print(e) + diff --git a/polybar/user_modules.ini b/polybar/user_modules.ini index 05727d8..85a0761 100644 --- a/polybar/user_modules.ini +++ b/polybar/user_modules.ini @@ -277,7 +277,7 @@ click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org [module/spotify] type = custom/ipc hook-0 = echo "" -hook-1 = python3 ~/scripts/spotify/spotify_status.py +hook-1 = python3 ~/.config/polybar/spotify/spotify_status.py initial = 1 format-padding = 4 format-underline = #1db954