Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: support show/play a playlist model #861

Merged
merged 1 commit into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions feeluown/server/handlers/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
from difflib import SequenceMatcher
from typing import Any

from feeluown.library import resolve, reverse
from feeluown.library import (
resolve, reverse, BriefSongModel, BriefPlaylistModel,
SupportsPlaylistSongsReader,
)
from .base import AbstractHandler
from .excs import HandlerException


def score(src, tar):
Expand Down Expand Up @@ -47,12 +51,29 @@ def handle(self, cmd): # pylint: disable=inconsistent-return-statements
self.player.toggle()

def play(self, s): # pylint: disable=inconsistent-return-statements
# pylint: disable=no-else-return
# pylint: disable=no-else-return,too-many-branches
if s.startswith('fuo://'):
model = resolve(s)
if model is None:
return 'Invalid fuo uri.'
self._app.playlist.play_model(model)
elif isinstance(model, BriefSongModel):
self._app.playlist.play_model(model)
elif isinstance(model, BriefPlaylistModel):
provider = self._app.library.get(model.source)
if isinstance(provider, SupportsPlaylistSongsReader):
reader = provider.playlist_create_songs_rd(model)
songs = reader.readall()
self._app.playlist.set_models(songs, next_=True)
self._app.player.resume()
else:
raise HandlerException(
f"provider:{provider.identifier} does not support"
" SupportsPlaylistSongsReader"
)
else:
model_type = model.meta.model_type
raise HandlerException(f"can't play this model type: {model_type}")

return
elif s.startswith('http'):
return self.player.play(s, video=False)
Expand Down
12 changes: 7 additions & 5 deletions feeluown/server/handlers/playlist.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from feeluown.library import ModelType
from feeluown.library import ModelType, SupportsPlaylistSongsReader
from feeluown.library import resolve, reverse
from feeluown.utils.utils import to_readall_reader
from .base import AbstractHandler


Expand Down Expand Up @@ -32,9 +31,12 @@ def add(self, furi_list):
if obj_type == ModelType.song:
playlist.add(obj)
elif obj_type == ModelType.playlist:
songs = to_readall_reader(obj, "songs").readall()
for song in songs:
playlist.add(song)
provider = self.library.get(obj.source)
if isinstance(provider, SupportsPlaylistSongsReader):
reader = provider.playlist_create_songs_rd(obj)
for song in reader:
playlist.add(song)
# TODO: raise error if it does not support

def remove(self, song_uri):
# FIXME: a little bit tricky
Expand Down
20 changes: 14 additions & 6 deletions feeluown/server/handlers/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
from functools import wraps
from urllib.parse import urlparse

from feeluown.utils.utils import to_readall_reader
from feeluown.utils.router import Router, NotFound
from feeluown.library import ResourceNotFound
from feeluown.library import NS_TYPE_MAP
from feeluown.library import ModelType
from feeluown.library import (
ResourceNotFound, NS_TYPE_MAP, ModelType,
SupportsPlaylistSongsReader, SupportsArtistAlbumsReader,
)

from .base import AbstractHandler
from .excs import HandlerException
Expand Down Expand Up @@ -120,12 +120,20 @@ def lyric_(req, provider, sid):
@use_provider
def playlist_songs(req, provider, pid):
playlist = get_model_or_raise(req.ctx['library'], provider, ModelType.playlist, pid)
return to_readall_reader(playlist, 'songs').readall()
if isinstance(provider, SupportsPlaylistSongsReader):
reader = provider.playlist_create_songs_rd(playlist)
return reader.readall()
raise HandlerException(f"provider:{provider.identifier} does not support"
f" {SupportsPlaylistSongsReader}")


@route('/<provider>/artists/<aid>/albums')
@use_provider
def albums_of_artist(req, provider, aid):
"""show all albums of an artist identified by artist id"""
artist = get_model_or_raise(req.ctx['library'], provider, ModelType.artist, aid)
return to_readall_reader(artist, 'albums').readall()
if isinstance(provider, SupportsArtistAlbumsReader):
reader = provider.artist_create_albums_rd(artist)
return reader.readall()
raise HandlerException(f"provider:{provider.identifier} does not support"
f" {SupportsArtistAlbumsReader}")
31 changes: 0 additions & 31 deletions feeluown/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
from functools import wraps
from itertools import filterfalse

from feeluown.utils.reader import wrap as reader_wrap


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -90,34 +87,6 @@ def get_osx_theme():
return 1 if theme == 'Dark' else -1


def to_reader(model, field):
flag_attr = 'allow_create_{}_g'.format(field)
method_attr = 'create_{}_g'.format(field)

flag_g = getattr(model.meta, flag_attr)

if flag_g:
return reader_wrap(getattr(model, method_attr)())

value = getattr(model, field, None)
if value is None:
return reader_wrap([])
if isinstance(value, (list, tuple)):
return reader_wrap(value)
return reader_wrap(iter(value)) # TypeError if not iterable


def to_readall_reader(*args, **kwargs):
"""
hack: set SequentialReader reader's count to 1000 if it is None
so that we can call readall method.
"""
reader = to_reader(*args, **kwargs)
if reader.count is None:
reader.count = 1000
return reader


class DedupList(list):
"""List that doesn't contain duplicate items

Expand Down
Loading