import os
from dbus.mainloop.glib import DBusGMainLoop
import dbus
import dbus.service
import requests
from gi.repository import GLib
OBJECT_PATH = '/org/mpris/MediaPlayer2'
MEDIAPLAYER_INTERFACE = 'org.mpris.MediaPlayer2'
MEDIAPLAYER_PLAYER_INTERFACE = 'org.mpris.MediaPlayer2.Player'
MPRIS_URL = 'org.mpris.MediaPlayer2.top2000'
def get_now_playing():
url = 'https://www.nporadio2.nl/api/miniplayer/info?channel=npo-radio-2'
response = requests.get(url)
data = response.json()
return data['data']['radioTrackPlays']['data'][0]
class MmprisApiPlayer(dbus.service.Object):
def __init__(self):
bus = dbus.service.BusName(MPRIS_URL, bus=dbus.SessionBus())
super().__init__(bus, OBJECT_PATH)
self.last_song = None
self._properties = dbus.Dictionary({
'DesktopEntry': 'top2000',
'Identity': 'top2000',
'CanQuit': False,
'CanRaise': False,
'HasTrackList': False,
'SupportedUriSchemes': [],
'SupportedMimeTypes': [],
}, signature='sv')
self._current_position = 0
self._player_properties = dbus.Dictionary({
'Metadata': dbus.Dictionary({
'mpris:length': dbus.Int64(0),
'mpris:artUrl': '',
'xesam:artist': ['None'],
'xesam:title': 'None',
'xesam:url': '',
'xesam:album': 'None'
}, signature='sv', variant_level=1),
'Rate': 1.0,
'MinimumRate': 1.0,
'MaximumRate': 1.0,
'CanGoNext': False,
'CanGoPrevious': False,
'CanControl': False,
'CanSeek': False,
'CanPause': False,
'CanPlay': True,
'Position': dbus.Int64(0),
'PlaybackStatus': 'Playing',
'Volume': 1.0,
}, signature='sv', variant_level=2)
@dbus.service.method(dbus.PROPERTIES_IFACE,
in_signature='ss', out_signature='v')
def Get(self, interface, prop):
return self.GetAll(interface)[prop]
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ssv')
def Set(self, interface, prop, value):
self._player_properties[prop] = value
if prop == 'Volume':
self._app.player.volume = int(100 * value)
@dbus.service.method(dbus.PROPERTIES_IFACE,
in_signature='s', out_signature='a{sv}')
def GetAll(self, interface):
if interface == MEDIAPLAYER_PLAYER_INTERFACE:
return self._player_properties
elif interface == MEDIAPLAYER_INTERFACE:
return self._properties
else:
raise dbus.exceptions.DBusException(
'com.example.UnknownInterface',
'The TOP2000 mpris object does not implement the %s interface'
% interface
)
@dbus.service.signal(dbus.PROPERTIES_IFACE,
signature='sa{sv}as')
def PropertiesChanged(self, interface, changed_properties,
invalidated_properties=[]):
pass
def _song_change(self, playing):
if playing == self.last_song:
return
self.last_song = playing
top2000_index = 0
if 'cmsChartEditionPositions' in playing and 'position' in playing['cmsChartEditionPositions']:
top2000_index = playing['cmsChartEditionPositions']['position']
title = playing['name'] if 'name' in playing else playing['song']
data = {
'xesam:artist': [playing['artist']],
'xesam:album': playing['album'] if 'album' in playing else '',
'xesam:title': f'#{top2000_index} {title}',
}
if 'radioTracks' in playing and 'coverUrl' in playing['radioTracks'] and playing['radioTracks']['coverUrl']:
data['mpris:artUrl'] = playing['radioTracks']['coverUrl']
print("Now playing", data)
props = dbus.Dictionary({
'Metadata': dbus.Dictionary(data, signature='sv'),
'Position': dbus.Int64(0),
}, signature='sv')
self._player_properties.update(props)
self.PropertiesChanged(MEDIAPLAYER_PLAYER_INTERFACE,
props, [])
self.PropertiesChanged(MEDIAPLAYER_PLAYER_INTERFACE,
{'PlaybackStatus': 'playing'}, [])
def update_song_info():
data = get_now_playing()
server._song_change(data)
return True
if __name__ == '__main__':
DBusGMainLoop(set_as_default=True)
mainloop = GLib.MainLoop()
GLib.timeout_add(10000, update_song_info)
server = MmprisApiPlayer()
update_song_info()
mainloop.run()