keep MPRIS always alive

This commit is contained in:
Martin Wagner 2020-09-25 17:13:39 +02:00
parent 76e149b04b
commit 375fe48fa0

View File

@ -64,6 +64,9 @@ class MPRISInterface(dbus.service.Object): # TODO emit Seeked if needed
self._metadata={} self._metadata={}
self._bus=dbus.SessionBus() self._bus=dbus.SessionBus()
# start
self._bus_name=dbus.service.BusName(self._name, bus=self._bus, allow_replacement=True, replace_existing=True) # TODO
# connect # connect
self._client.emitter.connect("state", self._on_state_changed) self._client.emitter.connect("state", self._on_state_changed)
self._client.emitter.connect("current_song_changed", self._on_song_changed) self._client.emitter.connect("current_song_changed", self._on_song_changed)
@ -71,7 +74,7 @@ class MPRISInterface(dbus.service.Object): # TODO emit Seeked if needed
self._client.emitter.connect("repeat", self._on_loop_changed) self._client.emitter.connect("repeat", self._on_loop_changed)
self._client.emitter.connect("single", self._on_loop_changed) self._client.emitter.connect("single", self._on_loop_changed)
self._client.emitter.connect("random", self._on_random_changed) self._client.emitter.connect("random", self._on_random_changed)
self._client.emitter.connect("disconnected", self._on_disconnected) self._client.emitter.connect("connection_error", self._on_connection_error)
self._client.emitter.connect("reconnected", self._on_reconnected) self._client.emitter.connect("reconnected", self._on_reconnected)
# Interfaces # Interfaces
@ -88,72 +91,82 @@ class MPRISInterface(dbus.service.Object): # TODO emit Seeked if needed
} }
def __get_playback_status(self): def __get_playback_status(self):
status=self._client.wrapped_call("status") if self._client.connected():
return {"play": "Playing", "pause": "Paused", "stop": "Stopped"}[status["state"]] status=self._client.wrapped_call("status")
return {"play": "Playing", "pause": "Paused", "stop": "Stopped"}[status["state"]]
return "Stopped"
def __set_loop_status(self, value): def __set_loop_status(self, value):
if value == "Playlist": if self._client.connected():
self._client.wrapped_call("repeat", 1) if value == "Playlist":
self._client.wrapped_call("single", 0) self._client.wrapped_call("repeat", 1)
elif value == "Track": self._client.wrapped_call("single", 0)
self._client.wrapped_call("repeat", 1) elif value == "Track":
self._client.wrapped_call("single", 1) self._client.wrapped_call("repeat", 1)
elif value == "None": self._client.wrapped_call("single", 1)
self._client.wrapped_call("repeat", 0) elif value == "None":
self._client.wrapped_call("single", 0) self._client.wrapped_call("repeat", 0)
else: self._client.wrapped_call("single", 0)
raise dbus.exceptions.DBusException("Loop mode '{}' not supported".format(value)) else:
raise dbus.exceptions.DBusException("Loop mode '{}' not supported".format(value))
return return
def __get_loop_status(self): def __get_loop_status(self):
status=self._client.wrapped_call("status") if self._client.connected():
if int(status["repeat"]) == 1: status=self._client.wrapped_call("status")
if int(status.get("single", 0)) == 1: if int(status["repeat"]) == 1:
return "Track" if int(status.get("single", 0)) == 1:
return "Track"
else:
return "Playlist"
else: else:
return "Playlist" return "None"
else: return "None"
return "None"
def __set_shuffle(self, value): def __set_shuffle(self, value):
self._client.wrapped_call("random", value) if self._client.connected():
self._client.wrapped_call("random", value)
return return
def __get_shuffle(self): def __get_shuffle(self):
if int(self._client.wrapped_call("status")["random"]) == 1: if self._client.connected():
return True if int(self._client.wrapped_call("status")["random"]) == 1:
else: return True
return False else:
return False
return False
def __get_metadata(self): def __get_metadata(self):
return dbus.Dictionary(self._metadata, signature="sv") return dbus.Dictionary(self._metadata, signature="sv")
def __get_volume(self): def __get_volume(self):
vol=float(self._client.wrapped_call("status").get("volume", 0)) if self._client.connected():
if vol > 0: return float(self._client.wrapped_call("status").get("volume", 0))/100
return vol / 100.0 return 0.0
else:
return 0.0
def __set_volume(self, value): def __set_volume(self, value):
if value >= 0 and value <= 1: if self._client.connected():
self._client.wrapped_call("setvol", int(value * 100)) if value >= 0 and value <= 1:
self._client.wrapped_call("setvol", int(value * 100))
return return
def __get_position(self): def __get_position(self):
status=self._client.wrapped_call("status") if self._client.connected():
if "time" in status: status=self._client.wrapped_call("status")
current, end=status["time"].split(":") return dbus.Int64(float(status.get("elapsed", 0))*1000000)
return dbus.Int64((int(current) * 1000000)) return dbus.Int64(0)
else:
return dbus.Int64(0)
def __get_can_next_prev(self): def __get_can_next_prev(self):
status=self._client.wrapped_call("status") if self._client.connected():
if status["state"] == "stop": status=self._client.wrapped_call("status")
return False if status["state"] == "stop":
else: return False
return True else:
return True
return False
def __get_can_play_pause_seek(self):
return self._client.connected()
__player_interface="org.mpris.MediaPlayer2.Player" __player_interface="org.mpris.MediaPlayer2.Player"
__player_props={ __player_props={
@ -168,9 +181,9 @@ class MPRISInterface(dbus.service.Object): # TODO emit Seeked if needed
"MaximumRate": (1.0, None), "MaximumRate": (1.0, None),
"CanGoNext": (__get_can_next_prev, None), "CanGoNext": (__get_can_next_prev, None),
"CanGoPrevious": (__get_can_next_prev, None), "CanGoPrevious": (__get_can_next_prev, None),
"CanPlay": (True, None), "CanPlay": (__get_can_play_pause_seek, None),
"CanPause": (True, None), "CanPause": (__get_can_play_pause_seek, None),
"CanSeek": (True, None), "CanSeek": (__get_can_play_pause_seek, None),
"CanControl": (True, None), "CanControl": (True, None),
} }
__prop_mapping={ __prop_mapping={
@ -357,12 +370,15 @@ class MPRISInterface(dbus.service.Object): # TODO emit Seeked if needed
self._update_property("org.mpris.MediaPlayer2.Player", "Shuffle") self._update_property("org.mpris.MediaPlayer2.Player", "Shuffle")
def _on_reconnected(self, *args): def _on_reconnected(self, *args):
self._bus_name=dbus.service.BusName(self._name, bus=self._bus, allow_replacement=True, replace_existing=True) # TODO properties=("CanPlay","CanPause","CanSeek")
for p in properties:
self._update_property("org.mpris.MediaPlayer2.Player", p)
def _on_disconnected(self, *args): def _on_connection_error(self, *args):
if hasattr(self, "_bus_name"):
del self._bus_name
self._metadata={} self._metadata={}
properties=("PlaybackStatus","CanGoNext","CanGoPrevious","Metadata","Volume","LoopStatus","Shuffle","CanPlay","CanPause","CanSeek")
for p in properties:
self._update_property("org.mpris.MediaPlayer2.Player", p)
###################### ######################
# MPD client wrapper # # MPD client wrapper #