Merge pull request #441 from joshbarrass/master

Add support for nowplaying-tf in deadbeef module
This commit is contained in:
tobi-wan-kenobi 2019-09-23 19:44:35 +02:00 committed by GitHub
commit 00c1209f73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,22 +1,38 @@
# pylint: disable=C0111,R0903 # pylint: disable=C0111,R0903
"""Displays the current song being played in DeaDBeeF and """Displays the current song being played in DeaDBeeF and provides
provides some media control bindings. some media control bindings.
Left click toggles pause, scroll up skips the current song, Left click toggles pause, scroll up skips the current song, scroll
scroll down returns to the previous song. down returns to the previous song.
Requires the following library: Requires the following library:
* subprocess * subprocess
Parameters: Parameters:
* deadbeef.format: Format string (defaults to "{artist} - {title}") * deadbeef.format: Format string (defaults to "{artist} - {title}")
Available values are: {artist}, {title}, {album}, {length}, Available values are: {artist}, {title}, {album}, {length},
{trackno}, {year}, {comment}, {trackno}, {year}, {comment},
{copyright}, {time} {copyright}, {time}
* deadbeef.previous: Change binding for previous song (default is left click) This is deprecated, but much simpler.
* deadbeef.next: Change binding for next song (default is right click) * deadbeef.tf_format: A foobar2000 title formatting-style format string.
* deadbeef.pause: Change binding for toggling pause (default is middle click) These can be much more sophisticated than the standard
format strings. This is off by default, but specifying
any tf_format will enable it. If both deadbeef.format
and deadbeef.tf_format are specified, deadbeef.tf_format
takes priority.
* deadbeef.tf_format_if_stopped: Controls whether or not the tf_format format
string should be displayed even if no song is paused or
playing. This could be useful if you want to implement
your own stop strings with the built in logic. Any non-
null value will enable this (by default the module will
hide itself when the player is stopped).
* deadbeef.previous: Change binding for previous song (default is left click)
* deadbeef.next: Change binding for next song (default is right click)
* deadbeef.pause: Change binding for toggling pause (default is middle click)
Available options for deadbeef.previous, deadbeef.next and deadbeef.pause are: Available options for deadbeef.previous, deadbeef.next and deadbeef.pause are:
LEFT_CLICK, RIGHT_CLICK, MIDDLE_CLICK, SCROLL_UP, SCROLL_DOWN LEFT_CLICK, RIGHT_CLICK, MIDDLE_CLICK, SCROLL_UP, SCROLL_DOWN
""" """
import sys
import bumblebee.input import bumblebee.input
import bumblebee.output import bumblebee.output
@ -34,54 +50,94 @@ class Module(bumblebee.engine.Module):
super(Module, self).__init__(engine, config, super(Module, self).__init__(engine, config,
bumblebee.output.Widget(full_text=self.deadbeef) bumblebee.output.Widget(full_text=self.deadbeef)
) )
buttons = {"LEFT_CLICK":bumblebee.input.LEFT_MOUSE, buttons = {"LEFT_CLICK": bumblebee.input.LEFT_MOUSE,
"RIGHT_CLICK":bumblebee.input.RIGHT_MOUSE, "RIGHT_CLICK": bumblebee.input.RIGHT_MOUSE,
"MIDDLE_CLICK":bumblebee.input.MIDDLE_MOUSE, "MIDDLE_CLICK": bumblebee.input.MIDDLE_MOUSE,
"SCROLL_UP":bumblebee.input.WHEEL_UP, "SCROLL_UP": bumblebee.input.WHEEL_UP,
"SCROLL_DOWN":bumblebee.input.WHEEL_DOWN, "SCROLL_DOWN": bumblebee.input.WHEEL_DOWN,
} }
self._song = "" self._song = ""
self._format = self.parameter("format", "{artist} - {title}") self._format = self.parameter("format", "{artist} - {title}")
self._tf_format = self.parameter("tf_format", "")
self._show_tf_when_stopped = bool(self.parameter("tf_format_if_stopped", ""))
prev_button = self.parameter("previous", "LEFT_CLICK") prev_button = self.parameter("previous", "LEFT_CLICK")
next_button = self.parameter("next", "RIGHT_CLICK") next_button = self.parameter("next", "RIGHT_CLICK")
pause_button = self.parameter("pause", "MIDDLE_CLICK") pause_button = self.parameter("pause", "MIDDLE_CLICK")
self.now_playing = ["deadbeef","--nowplaying","%a;%t;%b;%l;%n;%y;%c;%r;%e"] self.now_playing = ["deadbeef", "--nowplaying", "%a;%t;%b;%l;%n;%y;%c;%r;%e"]
self.now_playing_tf = ["deadbeef", "--nowplaying-tf", ""]
cmd = "deadbeef " cmd = "deadbeef "
engine.input.register_callback(self, button=buttons[prev_button], engine.input.register_callback(self, button=buttons[prev_button],
cmd=cmd + "--prev") cmd=cmd + "--prev")
engine.input.register_callback(self, button=buttons[next_button], engine.input.register_callback(self, button=buttons[next_button],
cmd=cmd + "--next") cmd=cmd + "--next")
engine.input.register_callback(self, button=buttons[pause_button], engine.input.register_callback(self, button=buttons[pause_button],
cmd=cmd + "--play-pause") cmd=cmd + "--play-pause")
# modify the tf_format if we don't want it to show on stop
# this adds conditions to the query itself, rather than
# polling to see if deadbeef is running
# doing this reduces the number of calls we have to make
if self._tf_format and not self._show_tf_when_stopped:
self._tf_format = "$if($or(%isplaying%,%ispaused%),{query})".format(query=self._tf_format)
@scrollable @scrollable
def deadbeef(self, widget): def deadbeef(self, widget):
return str(self._song) return self.string_song
def hidden(self): def hidden(self):
return str(self._song) == "" return self.string_song == ""
def update(self, widgets): def update(self, widgets):
try: try:
deadbeef = subprocess.Popen(self.now_playing,stdin=subprocess.PIPE,stdout=subprocess.PIPE) if self._tf_format == "": # no tf format set, use the old style
data = deadbeef.communicate()[0] return self.update_standard(widgets)
if data == "nothing": return self.update_tf(widgets)
self._song = ""
else:
data = data.split(";")
self._song = self._format.format(artist=data[0],
title=data[1],
album=data[2],
length=data[3],
trackno=data[4],
year=data[5],
comment=data[6],
copyright=data[7],
time=data[8])
except Exception: except Exception:
self._song = "error"
def update_tf(self, widgets):
## ensure that deadbeef is actually running
## easiest way to do this is to check --nowplaying for
## the string "nothing"
if read_process(self.now_playing) == "nothing":
self._song = "" self._song = ""
return
## perform the actual query -- these can be much more sophisticated
self.now_playing_tf[-1] = self._tf_format
data = read_process(self.now_playing_tf)
self._song = data
def update_standard(self, widgets):
data = read_process(self.now_playing)
if data == "nothing":
self._song = ""
else:
data = data.split(";")
self._song = self._format.format(artist=data[0],
title=data[1],
album=data[2],
length=data[3],
trackno=data[4],
year=data[5],
comment=data[6],
copyright=data[7],
time=data[8])
@property
def string_song(self):
"""\
Returns the current song as a string, either as a unicode() (Python <
3) or a regular str() (Python >= 3)
"""
if sys.version_info.major < 3:
return unicode(self._song)
return str(self._song)
def read_process(command):
proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
return proc.stdout.read()
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4