TrackList.TrackListReplaced signal
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
import math
|
||||
import random
|
||||
|
||||
@@ -264,6 +265,7 @@ class LibremsonicApp(Gtk.Application):
|
||||
invocation,
|
||||
):
|
||||
second_microsecond_conversion = 1000000
|
||||
track_id_re = re.compile(r'/song/(.*)')
|
||||
|
||||
def seek_fn(offset):
|
||||
offset_seconds = offset / second_microsecond_conversion
|
||||
@@ -276,14 +278,14 @@ class LibremsonicApp(Gtk.Application):
|
||||
self.on_play_pause()
|
||||
pos_seconds = position / second_microsecond_conversion
|
||||
self.state.song_progress = pos_seconds
|
||||
self.play_song(track_id[1:])
|
||||
self.play_song(track_id_re.match(track_id).group(1))
|
||||
|
||||
def get_track_metadata(track_ids):
|
||||
metadatas = []
|
||||
|
||||
song_details_futures = [
|
||||
CacheManager.get_song_details(track_id)
|
||||
for track_id in (tid[1:] for tid in track_ids)
|
||||
CacheManager.get_song_details(track_id) for track_id in (
|
||||
track_id_re.match(tid).group(1) for tid in track_ids)
|
||||
]
|
||||
for f in concurrent.futures.wait(song_details_futures).done:
|
||||
metadata = self.dbus_manager.get_mpris_metadata(f.result())
|
||||
@@ -293,7 +295,7 @@ class LibremsonicApp(Gtk.Application):
|
||||
for k, v in metadata.items()
|
||||
})
|
||||
|
||||
return GLib.Variant('(aa{sv})', (metadatas,))
|
||||
return GLib.Variant('(aa{sv})', (metadatas, ))
|
||||
|
||||
method_call_map = {
|
||||
'org.mpris.MediaPlayer2': {
|
||||
@@ -334,17 +336,19 @@ class LibremsonicApp(Gtk.Application):
|
||||
new_loop_status.get_string())
|
||||
self.update_window()
|
||||
|
||||
def do_shuffle(new_val):
|
||||
def set_shuffle(new_val):
|
||||
if new_val.get_boolean() != self.state.shuffle_on:
|
||||
self.on_shuffle_press(None, None)
|
||||
|
||||
def set_volume(new_val):
|
||||
self.on_volume_change(None, value.get_double() * 100)
|
||||
|
||||
setter_map = {
|
||||
'org.mpris.MediaPlayer2.Player': {
|
||||
'LoopStatus': change_loop,
|
||||
'Rate': lambda _: None,
|
||||
'Shuffle': do_shuffle,
|
||||
'Volume':
|
||||
lambda v: self.on_volume_change(None, v.get_double() * 100),
|
||||
'Shuffle': set_shuffle,
|
||||
'Volume': set_volume,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -210,9 +210,16 @@ class DBusManager:
|
||||
True,
|
||||
},
|
||||
'org.mpris.MediaPlayer2.TrackList': {
|
||||
'Tracks': ['/' + i for i in state.play_queue],
|
||||
'Tracks': ['/song/' + i for i in state.play_queue],
|
||||
'CanEditTracks': False,
|
||||
},
|
||||
'org.mpris.MediaPlayer2.Playlists': {
|
||||
# TODO this may do a network request. This really is a case for
|
||||
# doing the whole thing with caching some data beforehand.
|
||||
'PlaylistCount': len(CacheManager.get_playlists().result()),
|
||||
'Orderings': ['Alphabetical'],
|
||||
'ActivePlaylist': None,
|
||||
},
|
||||
}
|
||||
|
||||
def get_mpris_metadata(self, song: Child):
|
||||
@@ -221,7 +228,7 @@ class DBusManager:
|
||||
(song.duration or 0) * self.second_microsecond_conversion,
|
||||
)
|
||||
return {
|
||||
'mpris:trackid': song.id,
|
||||
'mpris:trackid': '/song/' + song.id,
|
||||
'mpris:length': duration,
|
||||
'mpris:artUrl': CacheManager.get_cover_art_url(song.id, 1000),
|
||||
'xesam:album': song.album,
|
||||
@@ -252,16 +259,47 @@ class DBusManager:
|
||||
changed_props['Metadata'] = new_property_dict[interface][
|
||||
'Metadata']
|
||||
|
||||
if 'Position' in changed_props.keys():
|
||||
# Special handling for when the position changes (a seek).
|
||||
# Technically, I'm sending this signal too often, but I don't think
|
||||
# it really matters.
|
||||
if (interface == 'org.mpris.MediaPlayer2.Player'
|
||||
and 'Position' in changed_props):
|
||||
self.connection.emit_signal(
|
||||
None,
|
||||
'/org/mpris/MediaPlayer2',
|
||||
'org.mpris.MediaPlayer2.Player',
|
||||
interface,
|
||||
'Seeked',
|
||||
GLib.Variant('(x)', (changed_props['Position'][1], )),
|
||||
)
|
||||
|
||||
# Do not emit the property change.
|
||||
del changed_props['Position']
|
||||
|
||||
# Special handling for when the track list changes.
|
||||
# Technically, I'm supposed to use `TrackAdded` and `TrackRemoved`
|
||||
# signals when minor changes occur, but the docs also say that:
|
||||
#
|
||||
# > It is left up to the implementation to decide when a change to
|
||||
# > the track list is invasive enough that this signal should be
|
||||
# > emitted instead of a series of TrackAdded and TrackRemoved
|
||||
# > signals.
|
||||
#
|
||||
# So I think that any change is invasive enough that I should use
|
||||
# this signal.
|
||||
if (interface == 'org.mpris.MediaPlayer2.TrackList'
|
||||
and 'Tracks' in changed_props):
|
||||
track_list = changed_props['Tracks']
|
||||
current_track = (
|
||||
new_property_dict['org.mpris.MediaPlayer2.Player']
|
||||
['Metadata']['mpris:trackid'])
|
||||
self.connection.emit_signal(
|
||||
None,
|
||||
'/org/mpris/MediaPlayer2',
|
||||
interface,
|
||||
'TrackListReplaced',
|
||||
GLib.Variant('(aoo)', (track_list, current_track)),
|
||||
)
|
||||
|
||||
self.connection.emit_signal(
|
||||
None,
|
||||
'/org/mpris/MediaPlayer2',
|
||||
|
Reference in New Issue
Block a user