From 8b95c429d433dbb0bbc3e093d5366a920e031587 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 10:02:49 -0200 Subject: [PATCH 01/11] Refactor Spotify module Simplify logic and increase code robutness by using specific instead of generic Exceptions. --- i3pystatus/spotify.py | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index c12bc36..c5bf903 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -1,7 +1,10 @@ import math from i3pystatus import formatp from i3pystatus import IntervalModule -from gi.repository import Playerctl + +import gi +gi.require_version('Playerctl', '1.0') +from gi.repository import Playerctl, GLib class Spotify(IntervalModule): @@ -49,54 +52,40 @@ class Spotify(IntervalModule): album = player.get_album() status = player.props.status - # gets the length of spotify through the metadata command - length = "" - # stores the metadata and checks if it is valid metadata = player.props.metadata - if metadata is not None: - # math to convert the number stored in mpris:length to a human readable format + try: time = dict(metadata)["mpris:length"] / 60.0e6 minutes = math.floor(time) seconds = round(time % 1 * 60) if seconds < 10: seconds = "0" + str(seconds) length = "{}:{}".format(minutes, seconds) - - # sets length to an empty string if it does not exist for whatever reason. This should usually not happen - else: + except (KeyError, TypeError): length = "" # returns a dictionary of all spotify data - return {"artist": artist, "title": title, "album": album, "status": status, "length": length} + return { + "status": self.status[status.lower()] if status else None, + "title": title if title else "", + "album": album if album else "", + "artist": artist if artist else "", + "length": length, + } def run(self): """Main statement, executes all code every interval""" - # tries to create player object and get data from player try: self.player = Playerctl.Player(player_name="spotify") - response = self.get_info(self.player) - - # creates a dictionary of the spotify data captured - fdict = { - 'status': self.status[response['status'].lower()], - 'title': response["title"], - 'album': response.get('album', ''), - 'artist': response.get('artist', ''), - 'length': response.get('length', 0), - } - self.data = fdict + fdict = self.get_info(self.player) + self.output = {"full_text": formatp(self.format, **fdict), "color": self.color} - - # outputs the not running string if spotify is closed - except: + except GLib.Error: self.output = {"full_text": self.format_not_running, "color": self.color_not_running} - if hasattr(self, "data"): - del self.data def playpause(self): """Pauses and plays spotify""" From 76cdd5487f6bf7699caf4e9f4c2ac685db8180f1 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 10:09:36 -0200 Subject: [PATCH 02/11] Modify Spotify module to support any player --- i3pystatus/spotify.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index c5bf903..1692dfb 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -3,13 +3,13 @@ from i3pystatus import formatp from i3pystatus import IntervalModule import gi -gi.require_version('Playerctl', '1.0') +gi.require_version('Playerctl', '1.0') # nopep8 from gi.repository import Playerctl, GLib class Spotify(IntervalModule): """ - Gets Spotify info using playerctl + Gets Spotify (or any supported player) info using playerctl .. rubric:: Available formatters @@ -22,10 +22,12 @@ class Spotify(IntervalModule): settings = ( ('format', 'formatp string'), - ('format_not_running', 'Text to show if cmus is not running'), + ('format_not_running', 'Text to show if player is not running'), ('color', 'The color of the text'), - ('color_not_running', 'The color of the text, when cmus is not running'), + ('color_not_running', + 'The color of the text, when player is not running'), ('status', 'Dictionary mapping status to output'), + ('player_name', 'Name of music player. If None, tries to autodetect'), ) # default settings @@ -38,6 +40,7 @@ class Spotify(IntervalModule): 'paused': '▷', 'playing': '▶', } + player_name = None on_leftclick = 'playpause' on_rightclick = 'next_song' @@ -45,7 +48,7 @@ class Spotify(IntervalModule): on_downscroll = 'previous_song' def get_info(self, player): - """gets spotify track info from playerctl""" + """gets player track info from playerctl""" artist = player.get_artist() title = player.get_title() @@ -64,7 +67,7 @@ class Spotify(IntervalModule): except (KeyError, TypeError): length = "" - # returns a dictionary of all spotify data + # returns a dictionary of all player data return { "status": self.status[status.lower()] if status else None, "title": title if title else "", @@ -77,10 +80,10 @@ class Spotify(IntervalModule): """Main statement, executes all code every interval""" try: - self.player = Playerctl.Player(player_name="spotify") + self.player = Playerctl.Player(player_name=self.player_name) fdict = self.get_info(self.player) - + self.output = {"full_text": formatp(self.format, **fdict), "color": self.color} except GLib.Error: @@ -88,7 +91,7 @@ class Spotify(IntervalModule): "color": self.color_not_running} def playpause(self): - """Pauses and plays spotify""" + """Pauses and plays player""" self.player.play_pause() def next_song(self): From bdd23126d8dc35cd05ced90daad97a11bf6bff62 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 13:13:03 -0200 Subject: [PATCH 03/11] Fix tests --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index d1948e0..a202929 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,7 +24,7 @@ MOCK_MODULES = [ "netifaces", "psutil", "lxml.html", "lxml.cssselect", "lxml", "praw", - "gi.repository", "dbus.mainloop.glib", "dbus", + "gi", "gi.repository", "dbus.mainloop.glib", "dbus", "pywapi", "basiciw", "i3pystatus.pulseaudio.pulse", "notmuch", From cf8415d2286731af939cd0585db5582e2e5f6d00 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 13:34:57 -0200 Subject: [PATCH 04/11] Added 'stopped' to status And make sure that the status exist so we don't show an error to the user. --- i3pystatus/spotify.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index 1692dfb..ff6b5ee 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -13,7 +13,7 @@ class Spotify(IntervalModule): .. rubric:: Available formatters - * `{status}` — current status icon (paused/playing) + * `{status}` — current status icon (paused/playing/stopped) * `{length}` — total song duration (mm:ss format) * `{artist}` — artist * `{title}` — title @@ -39,6 +39,7 @@ class Spotify(IntervalModule): status = { 'paused': '▷', 'playing': '▶', + 'stopped': '■', } player_name = None @@ -69,7 +70,8 @@ class Spotify(IntervalModule): # returns a dictionary of all player data return { - "status": self.status[status.lower()] if status else None, + "status": self.status[status.lower()] + if status in self.status.keys() else "", "title": title if title else "", "album": album if album else "", "artist": artist if artist else "", From 217b60a3c8e68a90eba852d4ea79a636c01e7d65 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 13:45:23 -0200 Subject: [PATCH 05/11] Convert strings to lower case or it does not work --- i3pystatus/spotify.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index ff6b5ee..7947a1f 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -54,7 +54,7 @@ class Spotify(IntervalModule): artist = player.get_artist() title = player.get_title() album = player.get_album() - status = player.props.status + status = player.props.status.lower() # stores the metadata and checks if it is valid metadata = player.props.metadata @@ -70,7 +70,7 @@ class Spotify(IntervalModule): # returns a dictionary of all player data return { - "status": self.status[status.lower()] + "status": self.status[status] if status in self.status.keys() else "", "title": title if title else "", "album": album if album else "", From 70b56624c2e21433f9d1bfc37b5ff9997c3a50e1 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 13:58:04 -0200 Subject: [PATCH 06/11] Improve documentation --- i3pystatus/spotify.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index 7947a1f..fd5c1a3 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -27,7 +27,9 @@ class Spotify(IntervalModule): ('color_not_running', 'The color of the text, when player is not running'), ('status', 'Dictionary mapping status to output'), - ('player_name', 'Name of music player. If None, tries to autodetect'), + ('player_name', + 'Name of music player, use `playerctl -l` with player running' + 'to get. If None, tries to autodetect.'), ) # default settings From f4479b7c77d6d52d5c91ba65377eaecc5047e2bd Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 14:47:38 -0200 Subject: [PATCH 07/11] Refactored method get_info() --- i3pystatus/spotify.py | 46 ++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index fd5c1a3..a9f6e7d 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -50,16 +50,7 @@ class Spotify(IntervalModule): on_upscroll = 'next_song' on_downscroll = 'previous_song' - def get_info(self, player): - """gets player track info from playerctl""" - - artist = player.get_artist() - title = player.get_title() - album = player.get_album() - status = player.props.status.lower() - - # stores the metadata and checks if it is valid - metadata = player.props.metadata + def _get_length(self, metadata): try: time = dict(metadata)["mpris:length"] / 60.0e6 minutes = math.floor(time) @@ -67,28 +58,39 @@ class Spotify(IntervalModule): if seconds < 10: seconds = "0" + str(seconds) length = "{}:{}".format(minutes, seconds) - except (KeyError, TypeError): + except KeyError: length = "" - # returns a dictionary of all player data - return { - "status": self.status[status] - if status in self.status.keys() else "", - "title": title if title else "", - "album": album if album else "", - "artist": artist if artist else "", - "length": length, + return length + + def get_info(self, player): + """gets player track info from playerctl""" + + result = { + "status": "", + "artist": "", + "title": "", + "album": "", + "length": "", } + if player.props.status: + result["status"] = player.props.status.lower() + result["artist"] = player.get_artist() + result["title"] = player.get_title() + result["album"] = player.get_album() + result["length"] = self._get_length(player.props.metadata) + + return result + def run(self): """Main statement, executes all code every interval""" try: self.player = Playerctl.Player(player_name=self.player_name) + data = self.get_info(self.player) - fdict = self.get_info(self.player) - - self.output = {"full_text": formatp(self.format, **fdict), + self.output = {"full_text": formatp(self.format, **data), "color": self.color} except GLib.Error: self.output = {"full_text": self.format_not_running, From 962578cf615131965e2e1fb61757a42f01804ae1 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 14:51:33 -0200 Subject: [PATCH 08/11] Forget to get format from dict --- i3pystatus/spotify.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index a9f6e7d..842a411 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -74,8 +74,9 @@ class Spotify(IntervalModule): "length": "", } - if player.props.status: - result["status"] = player.props.status.lower() + status = player.props.status + if status: + result["status"] = self.status.get(status.lower(), None) result["artist"] = player.get_artist() result["title"] = player.get_title() result["album"] = player.get_album() From 42b09c883418e866844e9c751061e8321dcae525 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 16:09:49 -0200 Subject: [PATCH 09/11] Make format_not_running works again --- i3pystatus/spotify.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index 842a411..1d5e81b 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -4,7 +4,7 @@ from i3pystatus import IntervalModule import gi gi.require_version('Playerctl', '1.0') # nopep8 -from gi.repository import Playerctl, GLib +from gi.repository import Playerctl class Spotify(IntervalModule): @@ -51,8 +51,11 @@ class Spotify(IntervalModule): on_downscroll = 'previous_song' def _get_length(self, metadata): + if not metadata: + return "" + try: - time = dict(metadata)["mpris:length"] / 60.0e6 + time = metadata["mpris:length"] / 60.0e6 minutes = math.floor(time) seconds = round(time % 1 * 60) if seconds < 10: @@ -64,7 +67,7 @@ class Spotify(IntervalModule): return length def get_info(self, player): - """gets player track info from playerctl""" + """Get player track info from playerctl""" result = { "status": "", @@ -76,7 +79,7 @@ class Spotify(IntervalModule): status = player.props.status if status: - result["status"] = self.status.get(status.lower(), None) + result["status"] = self.status.get(status.lower(), "") result["artist"] = player.get_artist() result["title"] = player.get_title() result["album"] = player.get_album() @@ -87,13 +90,12 @@ class Spotify(IntervalModule): def run(self): """Main statement, executes all code every interval""" - try: - self.player = Playerctl.Player(player_name=self.player_name) - data = self.get_info(self.player) - + self.player = Playerctl.Player(player_name=self.player_name) + data = self.get_info(self.player) + if data.get("status", ""): self.output = {"full_text": formatp(self.format, **data), "color": self.color} - except GLib.Error: + else: self.output = {"full_text": self.format_not_running, "color": self.color_not_running} From aab7f35c7da219b284f2c65dc63939f03a9c975e Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 19 Oct 2016 22:03:33 -0200 Subject: [PATCH 10/11] Use TimeWrapper to format length, additional clean-ups --- i3pystatus/spotify.py | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index 1d5e81b..f5cfab3 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -1,6 +1,6 @@ -import math from i3pystatus import formatp from i3pystatus import IntervalModule +from i3pystatus.core.util import TimeWrapper import gi gi.require_version('Playerctl', '1.0') # nopep8 @@ -14,7 +14,7 @@ class Spotify(IntervalModule): .. rubric:: Available formatters * `{status}` — current status icon (paused/playing/stopped) - * `{length}` — total song duration (mm:ss format) + * `{length}` — total song duration, uses TimeWrapper formatting, default format is `%E%l:%M:%S` * `{artist}` — artist * `{title}` — title * `{album}` — album @@ -24,12 +24,10 @@ class Spotify(IntervalModule): ('format', 'formatp string'), ('format_not_running', 'Text to show if player is not running'), ('color', 'The color of the text'), - ('color_not_running', - 'The color of the text, when player is not running'), + ('color_not_running', 'The color of the text, when player is not running'), ('status', 'Dictionary mapping status to output'), ('player_name', - 'Name of music player, use `playerctl -l` with player running' - 'to get. If None, tries to autodetect.'), + 'Name of music player, use `playerctl -l` with player running to get. If None, tries to autodetect.'), ) # default settings @@ -37,7 +35,6 @@ class Spotify(IntervalModule): color_not_running = '#ffffff' format = '{status} {length} {artist} - {title}' format_not_running = 'Not running' - interval = 1 status = { 'paused': '▷', 'playing': '▶', @@ -50,23 +47,17 @@ class Spotify(IntervalModule): on_upscroll = 'next_song' on_downscroll = 'previous_song' - def _get_length(self, metadata): + def _get_length_in_secs(self, metadata): if not metadata: - return "" - + return 0 try: - time = metadata["mpris:length"] / 60.0e6 - minutes = math.floor(time) - seconds = round(time % 1 * 60) - if seconds < 10: - seconds = "0" + str(seconds) - length = "{}:{}".format(minutes, seconds) + time = metadata["mpris:length"] / 1.0e6 + seconds = round(time) + return seconds except KeyError: - length = "" + return 0 - return length - - def get_info(self, player): + def get_formatted_info(self, player): """Get player track info from playerctl""" result = { @@ -83,7 +74,8 @@ class Spotify(IntervalModule): result["artist"] = player.get_artist() result["title"] = player.get_title() result["album"] = player.get_album() - result["length"] = self._get_length(player.props.metadata) + length_in_secs = self._get_length_in_secs(player.props.metadata) + result["length"] = TimeWrapper(length_in_secs, "%E%l%M:%S") return result @@ -91,9 +83,9 @@ class Spotify(IntervalModule): """Main statement, executes all code every interval""" self.player = Playerctl.Player(player_name=self.player_name) - data = self.get_info(self.player) - if data.get("status", ""): - self.output = {"full_text": formatp(self.format, **data), + fdict = self.get_formatted_info(self.player) + if fdict.get("status", ""): + self.output = {"full_text": formatp(self.format, **fdict), "color": self.color} else: self.output = {"full_text": self.format_not_running, From dd1243a0630532cb0e2f0635ef2269cba874816c Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Thu, 20 Oct 2016 10:50:30 -0200 Subject: [PATCH 11/11] Rename Spotify module to Playerctl Provides a Spotify module, that is simply a wrapper of Playerctl module, for compatibility purposes. --- docs/i3pystatus.rst | 2 +- i3pystatus/playerctl.py | 104 ++++++++++++++++++++++++++++++++++++++++ i3pystatus/spotify.py | 104 ++-------------------------------------- 3 files changed, 109 insertions(+), 101 deletions(-) create mode 100644 i3pystatus/playerctl.py diff --git a/docs/i3pystatus.rst b/docs/i3pystatus.rst index a2bf7e2..882d801 100644 --- a/docs/i3pystatus.rst +++ b/docs/i3pystatus.rst @@ -11,7 +11,7 @@ Module reference :Audio: `alsa`_ - `pulseaudio`_ :Hardware: `backlight`_ - `battery`_ - `temp`_ :Network: `net_speed`_ - `network`_ - `online`_ - `openstack_vms`_ - `openvpn`_ -:Music: `cmus`_ - `moc`_ - `mpd`_ - `now_playing`_ - `pianobar`_ - `spotify`_ +:Music: `cmus`_ - `moc`_ - `mpd`_ - `now_playing`_ - `pianobar`_ - `playerctl`_ - `spotify`_ :Websites: `bitcoin`_ - `dota2wins`_ - `github`_ - `modsde`_ - `parcel`_ - `reddit`_ - `weather`_ - `whosonlocation`_ :Other: `anybar`_ - `mail`_ - `pomodoro`_ - `pyload`_ - `text`_ - `updates`_ diff --git a/i3pystatus/playerctl.py b/i3pystatus/playerctl.py new file mode 100644 index 0000000..d0afc41 --- /dev/null +++ b/i3pystatus/playerctl.py @@ -0,0 +1,104 @@ +from i3pystatus import formatp +from i3pystatus import IntervalModule +from i3pystatus.core.util import TimeWrapper + +import gi +gi.require_version('Playerctl', '1.0') # nopep8 +from gi.repository import Playerctl as pctl + + +class Playerctl(IntervalModule): + """ + Gets current music information from a playerctl supported player. + + .. rubric:: Available formatters + + * `{status}` — current status icon (paused/playing/stopped) + * `{length}` — total song duration, uses TimeWrapper formatting, default format is `%E%l:%M:%S` + * `{artist}` — artist + * `{title}` — title + * `{album}` — album + """ + + settings = ( + ('format', 'formatp string'), + ('format_not_running', 'Text to show if player is not running'), + ('color', 'The color of the text'), + ('color_not_running', 'The color of the text, when player is not running'), + ('status', 'Dictionary mapping status to output'), + ('player_name', + 'Name of music player, use `playerctl -l` with player running to get. If None, tries to autodetect.'), + ) + + # default settings + color = '#ffffff' + color_not_running = '#ffffff' + format = '{status} {length} {artist} - {title}' + format_not_running = 'Not running' + status = { + 'paused': '▷', + 'playing': '▶', + 'stopped': '■', + } + player_name = None + + on_leftclick = 'playpause' + on_rightclick = 'next_song' + on_upscroll = 'next_song' + on_downscroll = 'previous_song' + + def _get_length_in_secs(self, metadata): + if not metadata: + return 0 + try: + time = metadata["mpris:length"] / 1.0e6 + seconds = round(time) + return seconds + except KeyError: + return 0 + + def get_formatted_info(self, player): + """Get player track info from playerctl""" + + result = { + "status": "", + "artist": "", + "title": "", + "album": "", + "length": "", + } + + status = player.props.status + if status: + result["status"] = self.status.get(status.lower(), "") + result["artist"] = player.get_artist() + result["title"] = player.get_title() + result["album"] = player.get_album() + length_in_secs = self._get_length_in_secs(player.props.metadata) + result["length"] = TimeWrapper(length_in_secs, "%E%l%M:%S") + + return result + + def run(self): + """Main statement, executes all code every interval""" + + self.player = pctl.Player(player_name=self.player_name) + fdict = self.get_formatted_info(self.player) + if fdict.get("status", ""): + self.output = {"full_text": formatp(self.format, **fdict), + "color": self.color} + else: + self.output = {"full_text": self.format_not_running, + "color": self.color_not_running} + + def playpause(self): + """Pauses and plays player""" + self.player.play_pause() + + def next_song(self): + """skips to the next song""" + self.player.next() + + def previous_song(self): + """Plays the previous song""" + self.player.previous() diff --git a/i3pystatus/spotify.py b/i3pystatus/spotify.py index f5cfab3..bd608fe 100644 --- a/i3pystatus/spotify.py +++ b/i3pystatus/spotify.py @@ -1,104 +1,8 @@ -from i3pystatus import formatp -from i3pystatus import IntervalModule -from i3pystatus.core.util import TimeWrapper - -import gi -gi.require_version('Playerctl', '1.0') # nopep8 -from gi.repository import Playerctl +from i3pystatus.playerctl import Playerctl -class Spotify(IntervalModule): +class Spotify(Playerctl): """ - Gets Spotify (or any supported player) info using playerctl - - .. rubric:: Available formatters - - * `{status}` — current status icon (paused/playing/stopped) - * `{length}` — total song duration, uses TimeWrapper formatting, default format is `%E%l:%M:%S` - * `{artist}` — artist - * `{title}` — title - * `{album}` — album + Get Spotify info using playerctl. Based on `Playerctl`_ module. """ - - settings = ( - ('format', 'formatp string'), - ('format_not_running', 'Text to show if player is not running'), - ('color', 'The color of the text'), - ('color_not_running', 'The color of the text, when player is not running'), - ('status', 'Dictionary mapping status to output'), - ('player_name', - 'Name of music player, use `playerctl -l` with player running to get. If None, tries to autodetect.'), - ) - - # default settings - color = '#ffffff' - color_not_running = '#ffffff' - format = '{status} {length} {artist} - {title}' - format_not_running = 'Not running' - status = { - 'paused': '▷', - 'playing': '▶', - 'stopped': '■', - } - player_name = None - - on_leftclick = 'playpause' - on_rightclick = 'next_song' - on_upscroll = 'next_song' - on_downscroll = 'previous_song' - - def _get_length_in_secs(self, metadata): - if not metadata: - return 0 - try: - time = metadata["mpris:length"] / 1.0e6 - seconds = round(time) - return seconds - except KeyError: - return 0 - - def get_formatted_info(self, player): - """Get player track info from playerctl""" - - result = { - "status": "", - "artist": "", - "title": "", - "album": "", - "length": "", - } - - status = player.props.status - if status: - result["status"] = self.status.get(status.lower(), "") - result["artist"] = player.get_artist() - result["title"] = player.get_title() - result["album"] = player.get_album() - length_in_secs = self._get_length_in_secs(player.props.metadata) - result["length"] = TimeWrapper(length_in_secs, "%E%l%M:%S") - - return result - - def run(self): - """Main statement, executes all code every interval""" - - self.player = Playerctl.Player(player_name=self.player_name) - fdict = self.get_formatted_info(self.player) - if fdict.get("status", ""): - self.output = {"full_text": formatp(self.format, **fdict), - "color": self.color} - else: - self.output = {"full_text": self.format_not_running, - "color": self.color_not_running} - - def playpause(self): - """Pauses and plays player""" - self.player.play_pause() - - def next_song(self): - """skips to the next song""" - self.player.next() - - def previous_song(self): - """Plays the previous song""" - self.player.previous() + player_name = "spotify"