113 lines
4.3 KiB
Python
113 lines
4.3 KiB
Python
#!/usr/bin/python3
|
|
|
|
from threading import Thread
|
|
from jeepney import DBusAddress
|
|
from jeepney.bus_messages import message_bus
|
|
from jeepney.io.blocking import DBusConnection, open_dbus_connection
|
|
|
|
from .utils import *
|
|
from .dbus_properties import DBusProperties
|
|
from .dbus_introspectable import DBUSIntrospectable
|
|
from .mpris_root import MPRISRoot
|
|
from .mpris_player import MPRISPlayer
|
|
|
|
|
|
class MPRISServer:
|
|
def __init__(self, app):
|
|
self.app = app
|
|
|
|
self.properties_interface = DBusProperties(self, PROPERTIES_INTERFACE)
|
|
self.introspection_interface = DBUSIntrospectable(self, INTROSPECTION_INTERFACE)
|
|
self.root_interface = MPRISRoot(self, MPRIS_ROOT_INTERFACE)
|
|
self.player_interface = MPRISPlayer(self, MPRIS_PLAYER_INTERFACE)
|
|
|
|
self.bus_address = DBusAddress(OBJECT_PATH, SERVICE_NAME, PROPERTIES_INTERFACE)
|
|
self.bus: DBusConnection = None
|
|
|
|
def start(self):
|
|
self.bus = open_dbus_connection()
|
|
|
|
reply = self.bus.send_and_get_reply(message_bus.RequestName(SERVICE_NAME))
|
|
if reply.body[0] == 1:
|
|
print("MPRIS Server connected to DBus: ", SERVICE_NAME)
|
|
|
|
Thread(target=self.run_event_loop, daemon=True).start()
|
|
|
|
def run_event_loop(self):
|
|
while True:
|
|
msg = self.bus.receive()
|
|
self.app.gui.window.mpris_signal.emit(msg) # queue message in the PyQt event loop
|
|
|
|
def handle_event(self, event): # called by app.gui.window.mpris_signal
|
|
self.handle_message(event)
|
|
|
|
def handle_message(self, msg: Message):
|
|
object_path = msg.header.fields[HeaderFields.path]
|
|
|
|
if not object_path == OBJECT_PATH: # only accept messages for "/org/mpris/MediaPlayer2"
|
|
self.bus.send_message(new_error(msg, *DBusErrors.unknownObject(object_path)))
|
|
return
|
|
|
|
interface = msg.header.fields[HeaderFields.interface]
|
|
|
|
# let the corresponding interface handle the message
|
|
if interface == PROPERTIES_INTERFACE:
|
|
self.properties_interface.handle_message(msg)
|
|
|
|
elif interface == INTROSPECTION_INTERFACE:
|
|
self.introspection_interface.handle_message(msg)
|
|
|
|
elif interface == MPRIS_ROOT_INTERFACE:
|
|
self.root_interface.handle_message(msg)
|
|
|
|
elif interface == MPRIS_PLAYER_INTERFACE:
|
|
self.player_interface.handle_message(msg)
|
|
|
|
def on_playstate_update(self):
|
|
player = self.app.player
|
|
current_playlist = player.current_playlist
|
|
|
|
if current_playlist is not None and current_playlist.current_track is not None:
|
|
current_track = current_playlist.current_track
|
|
metadata = current_track.metadata
|
|
|
|
art_path = self.app.utils.tmp_path + "/cover_cache/" + current_track.metadata.path.split("/")[-1][:-4]
|
|
|
|
# metadata milli to microseconds --↓
|
|
self.player_interface.metadata["mpris:length"] = ("x", current_track.duration * 1000)
|
|
self.player_interface.metadata["mpris:artUrl"] = ("s", "file://" + art_path)
|
|
self.player_interface.metadata["xesam:title"] = ("s", metadata.title)
|
|
|
|
if metadata.artist is None:
|
|
self.player_interface.metadata["xesam:artist"] = ("as", ["Unknown Artist"])
|
|
|
|
else:
|
|
self.player_interface.metadata["xesam:artist"] = ("as", [metadata.artist])
|
|
|
|
if metadata.album is None:
|
|
self.player_interface.metadata["xesam:album"] = ("s", metadata.title + " (single)")
|
|
|
|
else:
|
|
self.player_interface.metadata["xesam:album"] = ("s", current_track.metadata.album)
|
|
|
|
if metadata.genre is None:
|
|
self.player_interface.metadata["xesam:genre"] = ("as", ["Unknown Genre"])
|
|
|
|
else:
|
|
self.player_interface.metadata["xesam:genre"] = ("as", [metadata.genre])
|
|
|
|
self.properties_interface.properties_changed(MPRIS_PLAYER_INTERFACE, "Metadata")
|
|
|
|
if player.playing:
|
|
if player.paused:
|
|
playback_status = "Paused"
|
|
|
|
else:
|
|
playback_status = "Playing"
|
|
|
|
else:
|
|
playback_status = "Stopped"
|
|
|
|
self.player_interface.playback_status = playback_status
|
|
|
|
self.properties_interface.properties_changed(MPRIS_PLAYER_INTERFACE, "PlaybackStatus")
|