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
This commit is contained in:
Lukáš Mandák 2015-01-18 18:24:35 +01:00
parent efcf8c8610
commit 9b2591018c

View File

@ -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()