Handle duplicates in playlist

This commit is contained in:
Sumner Evans
2020-04-23 14:59:54 -06:00
parent bb26068ac6
commit 678fde3b24
5 changed files with 32 additions and 15 deletions

View File

@@ -56,7 +56,7 @@ setup(
},
install_requires=[
'bottle',
'dataclasses-json @ git+https://github.com/sumnerevans/dataclasses-json@cc2eaeb#egg=dataclasses-json',
'dataclasses-json @ git+https://github.com/sumnerevans/dataclasses-json@cc2eaeb#egg=dataclasses-json', # noqa: E501
'deepdiff',
'Deprecated',
'fuzzywuzzy',

View File

@@ -199,6 +199,9 @@ class Adapter(abc.ABC):
"""
return False
# TODO some way of specifying what types of schemas can be provided (for
# example, http, https, file)
# Data Retrieval Methods
# These properties determine if what things the adapter can be used to do
# at the current moment.

View File

@@ -138,7 +138,7 @@ class SortedManyToManyField(ManyToManyField):
database = self.model._meta.database
schema = self.model._meta.schema
table_name = '{}_{}_through'.format(*tables)
indexes = (((lhs._meta.name, rhs._meta.name), True), )
indexes = (((lhs._meta.name, rhs._meta.name, 'position'), True), )
params = {'on_delete': self._on_delete, 'on_update': self._on_update}
attrs = {

View File

@@ -28,11 +28,12 @@ except Exception:
glib_notify_exists = False
from .adapters import AdapterManager
from .adapters.api_objects import Playlist
from .cache_manager import CacheManager
from .config import AppConfiguration, ReplayGainType
from .dbus_manager import dbus_propagate, DBusManager
from .players import ChromecastPlayer, MPVPlayer, PlayerEvent
from .server.api_objects import Child, Directory, Playlist
from .server.api_objects import Child, Directory
from .ui.configure_servers import ConfigureServersDialog
from .ui.main import MainWindow
from .ui.settings import SettingsDialog
@@ -288,7 +289,7 @@ class SublimeMusicApp(Gtk.Application):
if not self.dbus_manager:
return
if len(track_ids):
if len(track_ids) == 0:
# We are lucky, just return an empty list.
return GLib.Variant('(aa{sv})', ([], ))
@@ -302,8 +303,10 @@ class SublimeMusicApp(Gtk.Application):
]
# Get rid of all of the tracks that were not requested.
metadatas = filter(
lambda m: m['mpris:trackid'] in track_ids, metadatas)
metadatas = list(
filter(lambda m: m['mpris:trackid'] in track_ids, metadatas))
assert len(metadatas) == len(track_ids)
# Sort them so they get returned in the same order as they were
# requested.
@@ -322,17 +325,18 @@ class SublimeMusicApp(Gtk.Application):
def activate_playlist(playlist_id: str):
playlist_id = playlist_id.split('/')[-1]
playlist = CacheManager.get_playlist(playlist_id).result()
playlist = AdapterManager.get_playlist_details(
playlist_id).result()
# Calculate the song id to play.
song_idx = 0
if self.app_config.state.shuffle_on:
song_idx = random.randint(0, len(playlist.entry) - 1)
song_idx = random.randint(0, len(playlist.songs) - 1)
self.on_song_clicked(
None,
song_idx,
[s.id for s in playlist.entry],
[s.id for s in playlist.songs],
{'active_playlist_id': playlist_id},
)
@@ -342,13 +346,13 @@ class SublimeMusicApp(Gtk.Application):
order: str,
reverse_order: bool,
) -> GLib.Variant:
playlists_result = CacheManager.get_playlists()
if playlists_result.is_future:
playlists_result = AdapterManager.get_playlists()
if not playlists_result.data_is_available:
# We don't want to wait for the response in this case, so just
# return an empty array.
return GLib.Variant('(a(oss))', ([], ))
playlists = playlists_result.result()
playlists = list(playlists_result.result())
sorters = {
'Alphabetical': lambda p: p.name,
@@ -362,7 +366,7 @@ class SublimeMusicApp(Gtk.Application):
def make_playlist_tuple(p: Playlist) -> GLib.Variant:
cover_art_filename = CacheManager.get_cover_art_filename(
p.coverArt,
p.cover_art,
allow_download=False,
).result()
return (f'/playlist/{p.id}', p.name, cover_art_filename or '')
@@ -400,6 +404,7 @@ class SublimeMusicApp(Gtk.Application):
'org.mpris.MediaPlayer2.TrackList': {
'GoTo': set_pos_fn,
'GetTracksMetadata': get_tracks_metadata,
# 'RemoveTrack': remove_track,
},
'org.mpris.MediaPlayer2.Playlists': {
'ActivatePlaylist': activate_playlist,

View File

@@ -140,6 +140,15 @@ def test_caching_get_playlist_details(cache_adapter: FilesystemAdapter):
duration=timedelta(seconds=21.8),
path='/foo/song1.mp3',
),
SubsonicAPI.Song(
'1',
'Song 1',
parent='foo',
album='foo',
artist='foo',
duration=timedelta(seconds=21.8),
path='/foo/song1.mp3',
),
]
cache_adapter.ingest_new_data(
FilesystemAdapter.FunctionNames.GET_PLAYLIST_DETAILS,
@@ -150,8 +159,8 @@ def test_caching_get_playlist_details(cache_adapter: FilesystemAdapter):
playlist = cache_adapter.get_playlist_details('1')
assert playlist.id == '1'
assert playlist.name == 'foo'
assert playlist.song_count == 2
assert playlist.duration == timedelta(seconds=32)
assert playlist.song_count == 3
assert playlist.duration == timedelta(seconds=53.8)
for actual, song in zip(playlist.songs, songs):
for k, v in asdict(song).items():
assert getattr(actual, k, None) == v