Skip to content

Instantly share code, notes, and snippets.

@kris7t
Created May 17, 2020 11:45
Show Gist options
  • Save kris7t/2ccab4565988ca072dd80b73e4698e92 to your computer and use it in GitHub Desktop.
Save kris7t/2ccab4565988ca072dd80b73e4698e92 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import html
import json
import gi
import sys
gi.require_version('Playerctl', '2.0')
from gi.repository import Playerctl, GLib # noqa: E402
ARTIST = 'xesam:artist'
TITLE = 'xesam:title'
ICONS = {
'spotify': '阮',
'ncspot': '阮',
'vlc': '嗢',
'firefox': '',
'default': '契',
'paused': ''
}
last_status = None
def find_active_player(manager, vanished_player):
for player in manager.props.players:
if player == vanished_player:
continue
if player.props.playback_status != Playerctl.PlaybackStatus.STOPPED:
return player
return None
def get_status(manager, vanished_player):
player = find_active_player(manager, vanished_player)
if player is None:
return '', '', 'stopped'
name = player.props.player_name
metadata = player.props.metadata
title = metadata[TITLE] if TITLE in metadata.keys() else None
artist = metadata[ARTIST][0] if ARTIST in metadata.keys() else None
if name == 'firefox' and title == 'Firefox' and artist == 'Mozilla':
title = None
artist = None
if player.props.playback_status == Playerctl.PlaybackStatus.PAUSED:
css_class = 'paused'
else:
css_class = 'playing'
if title is None and artist is None:
if css_class == 'paused':
icon = ICONS['paused']
else:
icon = ICONS['default']
app_icon = ICONS.get(name, None)
if app_icon is None:
label = icon
else:
label = f'{icon} {app_icon}'
return label, f'{name.title()}: {css_class.title()}', css_class
if css_class == 'paused':
icon = ICONS['paused']
else:
icon = ICONS.get(name, ICONS['default'])
if title is None or title == '':
song = artist or name.title()
elif artist is None or artist == '':
song = f'{title}'
else:
song = f'{artist} – {title}'
html_song = html.escape(song)
return f'{icon} {html_song}', f'{name.title()}: {song}', css_class
def print_status(manager, vanished_player=None):
text, tooltip, css_class = get_status(manager, vanished_player)
status = json.dumps({'text': text, 'tooltip': tooltip, 'class': css_class})
global last_status
if last_status != status:
print(status)
sys.stdout.flush()
last_status = status
def on_playback_status(player, status, manager):
manager.move_player_to_top(player)
print_status(manager)
def on_metadata(player, metadata, manager):
manager.move_player_to_top(player)
print_status(manager)
def init_player(manager, name):
player = Playerctl.Player.new_from_name(name)
player.connect('playback-status', on_playback_status, manager)
player.connect('metadata', on_metadata, manager)
manager.manage_player(player)
def on_name_appeared(manager, name, _):
init_player(manager, name)
print_status(manager)
def on_player_vanished(manager, player, _):
print_status(manager, player)
def init_manager():
manager = Playerctl.PlayerManager()
manager.connect('name-appeared', on_name_appeared, manager)
manager.connect('player-vanished', on_player_vanished, manager)
for name in manager.props.player_names:
init_player(manager, name)
print_status(manager)
if __name__ == '__main__':
init_manager()
main = GLib.MainLoop()
main.run()
{
"custom/playerctl": {
"exec": "/home/kris/.local/bin/media-player-status.py",
"return-type": "json",
"on-click": "playerctl play-pause",
"on-click-middle": "playerctl stop"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment