diff --git a/README.md b/README.md index 3570c33..5c8d501 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ Modules and commandline utilities are only required for modules, the core itself * redshift (for the module 'redshift') * xrandr (for the module 'xrandr') * sensors (for the module 'sensors') +* mpc (for the module 'mpd') # Examples Here are some screenshots for all themes that currently exist: diff --git a/bumblebee/modules/mpd.py b/bumblebee/modules/mpd.py new file mode 100644 index 0000000..783bd94 --- /dev/null +++ b/bumblebee/modules/mpd.py @@ -0,0 +1,105 @@ +# pylint: disable=C0111,R0903 +# -*- coding: utf-8 -*- + +"""Displays information about the current song in mpd. + +Requires the following executable: + * mpc + +Parameters: + * mpd.format: Format string for the song information. Tag values can be put in curly brackets (i.e. {artist}) +""" + +from collections import defaultdict + +import string + +import bumblebee.util +import bumblebee.input +import bumblebee.output +import bumblebee.engine + +from bumblebee.output import scrollable + +class Module(bumblebee.engine.Module): + def __init__(self, engine, config): + widgets = [ + bumblebee.output.Widget(name="mpd.prev"), + bumblebee.output.Widget(name="mpd.main", full_text=self.description), + bumblebee.output.Widget(name="mpd.next"), + bumblebee.output.Widget(name="mpd.shuffle"), + bumblebee.output.Widget(name="mpd.repeat"), + ] + super(Module, self).__init__(engine, config, widgets) + + engine.input.register_callback(widgets[0], button=bumblebee.input.LEFT_MOUSE, + cmd="mpc prev") + engine.input.register_callback(widgets[1], button=bumblebee.input.LEFT_MOUSE, + cmd="mpc toggle") + engine.input.register_callback(widgets[2], button=bumblebee.input.LEFT_MOUSE, + cmd="mpc next") + engine.input.register_callback(widgets[3], button=bumblebee.input.LEFT_MOUSE, + cmd="mpc random") + engine.input.register_callback(widgets[4], button=bumblebee.input.LEFT_MOUSE, + cmd="mpc repeat") + + self._fmt = self.parameter("format", "{artist} - {title} {position}/{duration}") + self._status = None + self._shuffle = False + self._repeat = False + self._tags = defaultdict(lambda: '') + + def description(self, widget): + return string.Formatter().vformat(self._fmt, (), self._tags) + + def update(self, widgets): + self._load_song() + + def state(self, widget): + if widget.name == "mpd.shuffle": + return "shuffle-on" if self._shuffle else "shuffle-off" + if widget.name == "mpd.repeat": + return "repeat-on" if self._repeat else "repeat-off" + if widget.name == "mpd.prev": + return "prev" + if widget.name == "mpd.next": + return "next" + return self._status + + def _load_song(self): + info = "" + try: + info = bumblebee.util.execute('mpc -f "tag artist %artist%\ntag title %title%"') + except RuntimeError: + pass + self._tags = defaultdict(lambda: '') + for line in info.split("\n"): + if line.startswith("[playing]"): + self._status = "playing" + elif line.startswith("[paused]"): + self._status = "paused" + + if line.startswith("["): + timer = line.split(" ")[1] + position = timer.split("/")[0] + dur = timer.split("/")[1] + duration = dur.split(" ")[0] + self._tags.update({'position': position}) + self._tags.update({'duration': duration}) + + if line.startswith("volume"): + value = line.split(" ", 2)[1:] + for option in value: + if option.startswith("repeat: on"): + self._repeat = True + elif option.startswith("repeat: off"): + self._repeat = False + elif option.startswith("random: on"): + self._shuffle = True + elif option.startswith("random: off"): + self._shuffle = False + if line.startswith("tag"): + key, value = line.split(" ", 2)[1:] + self._tags.update({ key: value }) + +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/screenshots/mpd.png b/screenshots/mpd.png new file mode 100644 index 0000000..a332b00 Binary files /dev/null and b/screenshots/mpd.png differ diff --git a/themes/icons/ascii.json b/themes/icons/ascii.json index 9b03a46..a104d6e 100644 --- a/themes/icons/ascii.json +++ b/themes/icons/ascii.json @@ -66,5 +66,16 @@ "traffic": { "rx": { "prefix": "down"}, "tx": { "prefix": "up"} + }, + "mpd": { + "playing": { "prefix": ">" }, + "paused": { "prefix": "||" }, + "stopped": { "prefix": "[]" }, + "prev": { "prefix": "|<" }, + "next": { "prefix": ">|" }, + "shuffle-on": { "prefix": "S" }, + "shuffle-off": { "prefix": "[s]" }, + "repeat-on": { "prefix": "R" }, + "repeat-off": { "prefix": "[r]" } } } diff --git a/themes/icons/awesome-fonts.json b/themes/icons/awesome-fonts.json index 4263a19..91ee4b8 100644 --- a/themes/icons/awesome-fonts.json +++ b/themes/icons/awesome-fonts.json @@ -82,5 +82,16 @@ "traffic":{ "rx": { "prefix": "" }, "tx": { "prefix": "" } - } + }, + "mpd": { + "playing": { "prefix": "" }, + "paused": { "prefix": "" }, + "stopped": { "prefix": "" }, + "prev": { "prefix": "" }, + "next": { "prefix": "" }, + "shuffle-on": { "prefix": "" }, + "shuffle-off": { "prefix": "" }, + "repeat-on": { "prefix": "" }, + "repeat-off": { "prefix": "" } + } }