From 9b2591018cf7b72159c1757e8ae1c3ac6c5161c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Mand=C3=A1k?= Date: Sun, 18 Jan 2015 18:24:35 +0100 Subject: [PATCH] Updated 'now_playing' module: - Added custom format and color, when no player is running. - Make a difference between DBus error and no players found. - Exdended try-cath for DBus errors. - Changed player method calls according to docs [1] since my player did not recognize them. [1] http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#interfaces-and-methods --- i3pystatus/now_playing.py | 109 +++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 44 deletions(-) diff --git a/i3pystatus/now_playing.py b/i3pystatus/now_playing.py index fbbccdf..a413130 100644 --- a/i3pystatus/now_playing.py +++ b/i3pystatus/now_playing.py @@ -8,39 +8,49 @@ from i3pystatus import IntervalModule, formatp from i3pystatus.core.util import TimeWrapper +class NoPlayerException(Exception): + pass + + class NowPlaying(IntervalModule): """ Shows currently playing track information, supports most media players + * Requires python-dbus available from every distros' package manager. + + Left click on the module play/pauses, right click goes to the next track. + Available formatters (uses :ref:`formatp`) * `{title}` — (the title of the current song) * `{album}` — (the album of the current song, can be an empty string (e.g. for online streams)) * `{artist}` — (can be empty, too) * `{filename}` — (file name with out extension and path; empty unless title is empty) - * `{song_elapsed}` — (Position in the currently playing song, uses :ref:`TimeWrapper`, default is `%m:%S`) - * `{song_length}` — (Length of the current song, same as song_elapsed) + * `{song_elapsed}` — (position in the currently playing song, uses :ref:`TimeWrapper`, default is `%m:%S`) + * `{song_length}` — (length of the current song, same as song_elapsed) * `{status}` — (play, pause, stop mapped through the `status` dictionary) - * `{volume}` — (Volume) - - Left click on the module play/pauses, right click goes to the next track. - - Requires python-dbus available from every distros' package manager. + * `{volume}` — (volume) """ interval = 1 settings = ( - ("player", "Player name"), + ("player", "Player name. If not set, compatible players will be \ + detected automatically."), ("status", "Dictionary mapping pause, play and stop to output text"), - ("color", "Text color"), ("format", "formatp string"), + ("color", "Text color"), + ("format_no_player", "Text to show if no player is detected"), + ("color_no_player", "Text color when no player is detected"), ("hide_no_player", "Hide output if no player is detected"), ) hide_no_player = True - player = None + format_no_player = "No Player" + color_no_player = "#ffffff" + format = "{title} {status}" + color = "#ffffff" status = { "pause": "▷", "play": "▶", @@ -51,18 +61,19 @@ class NowPlaying(IntervalModule): "Paused": "pause", "Stopped": "stop", } - color = "#FFFFFF" - old_player = None on_leftclick = "playpause" on_rightclick = "next_song" + player = None + old_player = None + def find_player(self): players = [a for a in dbus.SessionBus().get_object("org.freedesktop.DBus", "/org/freedesktop/DBus").ListNames() if a.startswith("org.mpris.MediaPlayer2.")] if self.old_player in players: return self.old_player if not players: - raise dbus.exceptions.DBusException() + raise NoPlayerException() self.old_player = players[0] return players[0] @@ -76,45 +87,55 @@ class NowPlaying(IntervalModule): def run(self): try: player = self.get_player() - except dbus.exceptions.DBusException: + properties = dbus.Interface(player, "org.freedesktop.DBus.Properties") + get_prop = functools.partial(properties.Get, "org.mpris.MediaPlayer2.Player") + currentsong = get_prop("Metadata") + + fdict = { + "status": self.status[self.statusmap[get_prop("PlaybackStatus")]], + "len": 0, # TODO: Use optional(!) TrackList interface for this to gain 100 % mpd<->now_playing compat + "pos": 0, + "volume": int(get_prop("Volume") * 100), + + "title": currentsong.get("xesam:title", ""), + "album": currentsong.get("xesam:album", ""), + "artist": ", ".join(currentsong.get("xesam:artist", "")), + "song_length": TimeWrapper((currentsong.get("mpris:length") or 0) / 1000 ** 2), + "song_elapsed": TimeWrapper((get_prop("Position") or 0) / 1000 ** 2), + "filename": "", + } + + if not fdict["title"]: + fdict["filename"] = '.'.join( + basename((currentsong.get("xesam:url") or "")).split('.')[:-1]) + + self.output = { + "full_text": formatp(self.format, **fdict).strip(), + "color": self.color, + } + + except NoPlayerException: if self.hide_no_player: self.output = None else: self.output = { - "full_text": "now_playing: d-bus error", + "full_text": self.format_no_player, + "color": self.color, + } + return + + except dbus.exceptions.DBusException as e: + if self.hide_no_player: + self.output = None + else: + self.output = { + "full_text": "DBus error: " + e.get_dbus_message(), "color": "#ff0000", } return - properties = dbus.Interface(player, "org.freedesktop.DBus.Properties") - get_prop = functools.partial(properties.Get, "org.mpris.MediaPlayer2.Player") - currentsong = get_prop("Metadata") - - fdict = { - "status": self.status[self.statusmap[get_prop("PlaybackStatus")]], - "len": 0, # TODO: Use optional(!) TrackList interface for this to gain 100 % mpd<->now_playing compat - "pos": 0, - "volume": int(get_prop("Volume") * 100), - - "title": currentsong.get("xesam:title", ""), - "album": currentsong.get("xesam:album", ""), - "artist": ", ".join(currentsong.get("xesam:artist", "")), - "song_length": TimeWrapper((currentsong.get("mpris:length") or 0) / 1000 ** 2), - "song_elapsed": TimeWrapper((get_prop("Position") or 0) / 1000 ** 2), - "filename": "", - } - - if not fdict["title"]: - fdict["filename"] = '.'.join( - basename((currentsong.get("xesam:url") or "")).split('.')[:-1]) - - self.output = { - "full_text": formatp(self.format, **fdict).strip(), - "color": self.color, - } - def playpause(self): - self.get_player().PlayPause() + dbus.Interface(self.get_player(), "org.mpris.MediaPlayer2.Player").PlayPause() def next_song(self): - self.get_player().Next() + dbus.Interface(self.get_player(), "org.mpris.MediaPlayer2.Player").Next()