Merge pull request #476 from m45t3r/playerctl
Spotify module refactoring
This commit is contained in:
commit
1041f5d0c8
@ -24,7 +24,7 @@ MOCK_MODULES = [
|
|||||||
"netifaces", "psutil",
|
"netifaces", "psutil",
|
||||||
"lxml.html", "lxml.cssselect", "lxml",
|
"lxml.html", "lxml.cssselect", "lxml",
|
||||||
"praw",
|
"praw",
|
||||||
"gi.repository", "dbus.mainloop.glib", "dbus",
|
"gi", "gi.repository", "dbus.mainloop.glib", "dbus",
|
||||||
"pywapi", "basiciw",
|
"pywapi", "basiciw",
|
||||||
"i3pystatus.pulseaudio.pulse",
|
"i3pystatus.pulseaudio.pulse",
|
||||||
"notmuch",
|
"notmuch",
|
||||||
|
@ -11,7 +11,7 @@ Module reference
|
|||||||
:Audio: `alsa`_ - `pulseaudio`_
|
:Audio: `alsa`_ - `pulseaudio`_
|
||||||
:Hardware: `backlight`_ - `battery`_ - `temp`_
|
:Hardware: `backlight`_ - `battery`_ - `temp`_
|
||||||
:Network: `net_speed`_ - `network`_ - `online`_ - `openstack_vms`_ - `openvpn`_
|
: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`_ -
|
:Websites: `bitcoin`_ - `dota2wins`_ - `github`_ - `modsde`_ - `parcel`_ - `reddit`_ - `weather`_ -
|
||||||
`whosonlocation`_
|
`whosonlocation`_
|
||||||
:Other: `anybar`_ - `mail`_ - `pomodoro`_ - `pyload`_ - `text`_ - `updates`_
|
:Other: `anybar`_ - `mail`_ - `pomodoro`_ - `pyload`_ - `text`_ - `updates`_
|
||||||
|
104
i3pystatus/playerctl.py
Normal file
104
i3pystatus/playerctl.py
Normal file
@ -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()
|
@ -1,111 +1,8 @@
|
|||||||
import math
|
from i3pystatus.playerctl import Playerctl
|
||||||
from i3pystatus import formatp
|
|
||||||
from i3pystatus import IntervalModule
|
|
||||||
from gi.repository import Playerctl
|
|
||||||
|
|
||||||
|
|
||||||
class Spotify(IntervalModule):
|
class Spotify(Playerctl):
|
||||||
"""
|
"""
|
||||||
Gets Spotify info using playerctl
|
Get Spotify info using playerctl. Based on `Playerctl`_ module.
|
||||||
|
|
||||||
.. rubric:: Available formatters
|
|
||||||
|
|
||||||
* `{status}` — current status icon (paused/playing)
|
|
||||||
* `{length}` — total song duration (mm:ss format)
|
|
||||||
* `{artist}` — artist
|
|
||||||
* `{title}` — title
|
|
||||||
* `{album}` — album
|
|
||||||
"""
|
"""
|
||||||
|
player_name = "spotify"
|
||||||
settings = (
|
|
||||||
('format', 'formatp string'),
|
|
||||||
('format_not_running', 'Text to show if cmus is not running'),
|
|
||||||
('color', 'The color of the text'),
|
|
||||||
('color_not_running', 'The color of the text, when cmus is not running'),
|
|
||||||
('status', 'Dictionary mapping status to output'),
|
|
||||||
)
|
|
||||||
|
|
||||||
# default settings
|
|
||||||
color = '#ffffff'
|
|
||||||
color_not_running = '#ffffff'
|
|
||||||
format = '{status} {length} {artist} - {title}'
|
|
||||||
format_not_running = 'Not running'
|
|
||||||
interval = 1
|
|
||||||
status = {
|
|
||||||
'paused': '▷',
|
|
||||||
'playing': '▶',
|
|
||||||
}
|
|
||||||
|
|
||||||
on_leftclick = 'playpause'
|
|
||||||
on_rightclick = 'next_song'
|
|
||||||
on_upscroll = 'next_song'
|
|
||||||
on_downscroll = 'previous_song'
|
|
||||||
|
|
||||||
def get_info(self, player):
|
|
||||||
"""gets spotify track info from playerctl"""
|
|
||||||
|
|
||||||
artist = player.get_artist()
|
|
||||||
title = player.get_title()
|
|
||||||
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
|
|
||||||
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:
|
|
||||||
length = ""
|
|
||||||
|
|
||||||
# returns a dictionary of all spotify data
|
|
||||||
return {"artist": artist, "title": title, "album": album, "status": status, "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
|
|
||||||
self.output = {"full_text": formatp(self.format, **fdict),
|
|
||||||
"color": self.color}
|
|
||||||
|
|
||||||
# outputs the not running string if spotify is closed
|
|
||||||
except:
|
|
||||||
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"""
|
|
||||||
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()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user