From: Marcel van der Veldt Date: Wed, 5 Feb 2025 13:37:00 +0000 (+0100) Subject: Fix: allow seek support in providers which support it X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=3640aeb9076ba14dc23e768ea65db170519112d9;p=music-assistant-server.git Fix: allow seek support in providers which support it --- diff --git a/music_assistant/providers/_template_music_provider/__init__.py b/music_assistant/providers/_template_music_provider/__init__.py index ce6b9b08..c305d7b8 100644 --- a/music_assistant/providers/_template_music_provider/__init__.py +++ b/music_assistant/providers/_template_music_provider/__init__.py @@ -392,6 +392,10 @@ class MyDemoMusicprovider(MusicProvider): stream_type=StreamType.HTTP, # explore the StreamDetails model and StreamType enum for more options # but the above should be the mandatory fields to set. + allow_seek=True, + # set allow_seek to True if the stream may be seeked + can_seek=True, + # set can_seek to True if the stream supports seeking ) async def get_audio_stream( diff --git a/music_assistant/providers/apple_music/__init__.py b/music_assistant/providers/apple_music/__init__.py index fdda7cc0..bfee2038 100644 --- a/music_assistant/providers/apple_music/__init__.py +++ b/music_assistant/providers/apple_music/__init__.py @@ -370,6 +370,7 @@ class AppleMusicProvider(MusicProvider): path=stream_url, decryption_key=await self._get_decryption_key(license_url, key_id, uri, item_id), can_seek=True, + allow_seek=True, ) def _parse_artist(self, artist_obj): diff --git a/music_assistant/providers/audible/audible_helper.py b/music_assistant/providers/audible/audible_helper.py index 37bcfcb9..f7d11086 100644 --- a/music_assistant/providers/audible/audible_helper.py +++ b/music_assistant/providers/audible/audible_helper.py @@ -16,12 +16,7 @@ from urllib.parse import parse_qs, urlparse import audible import audible.register from audible import AsyncClient -from music_assistant_models.enums import ( - ContentType, - ImageType, - MediaType, - StreamType, -) +from music_assistant_models.enums import ContentType, ImageType, MediaType, StreamType from music_assistant_models.errors import LoginFailed from music_assistant_models.media_items import ( Audiobook, @@ -169,6 +164,7 @@ class AudibleHelper: stream_type=StreamType.HTTP, path=m3u8_url, can_seek=True, + allow_seek=True, duration=duration, data={"acr": acr}, ) diff --git a/music_assistant/providers/audiobookshelf/__init__.py b/music_assistant/providers/audiobookshelf/__init__.py index fa8f454c..2c579148 100644 --- a/music_assistant/providers/audiobookshelf/__init__.py +++ b/music_assistant/providers/audiobookshelf/__init__.py @@ -445,6 +445,8 @@ class Audiobookshelf(MusicProvider): media_type=media_type, stream_type=StreamType.HLS, path=stream_url, + can_seek=True, + allow_seek=True, ) async def get_stream_details(self, item_id: str, media_type: MediaType) -> StreamDetails: @@ -490,6 +492,8 @@ class Audiobookshelf(MusicProvider): media_type=MediaType.AUDIOBOOK, stream_type=StreamType.HTTP, path=stream_url, + can_seek=True, + allow_seek=True, ) async def _get_stream_details_podcast_episode(self, podcast_id: str) -> StreamDetails: @@ -517,6 +521,8 @@ class Audiobookshelf(MusicProvider): media_type=MediaType.PODCAST_EPISODE, stream_type=StreamType.HTTP, path=full_url, + can_seek=True, + allow_seek=True, ) async def on_played( diff --git a/music_assistant/providers/builtin/__init__.py b/music_assistant/providers/builtin/__init__.py index 1f2170a8..f8b44288 100644 --- a/music_assistant/providers/builtin/__init__.py +++ b/music_assistant/providers/builtin/__init__.py @@ -558,6 +558,7 @@ class BuiltinProvider(MusicProvider): stream_type=StreamType.HTTP, path=item_id, can_seek=not is_radio, + allow_seek=not is_radio, ) async def _get_builtin_playlist_random_favorite_tracks(self) -> list[Track]: diff --git a/music_assistant/providers/deezer/__init__.py b/music_assistant/providers/deezer/__init__.py index d435063b..a7a5ae3e 100644 --- a/music_assistant/providers/deezer/__init__.py +++ b/music_assistant/providers/deezer/__init__.py @@ -444,6 +444,8 @@ class DeezerProvider(MusicProvider): # separately so we can use it later on. data={"url": url, "format": url_details["format"], "track_id": song_data["SNG_ID"]}, size=int(song_data[f"FILESIZE_{url_details['format']}"]), + can_seek=True, + allow_seek=True, ) async def get_audio_stream( diff --git a/music_assistant/providers/filesystem_local/__init__.py b/music_assistant/providers/filesystem_local/__init__.py index b9f52054..d27566e2 100644 --- a/music_assistant/providers/filesystem_local/__init__.py +++ b/music_assistant/providers/filesystem_local/__init__.py @@ -1550,6 +1550,7 @@ class LocalFileSystemProvider(MusicProvider): data=file_item, path=file_item.absolute_path, can_seek=True, + allow_seek=True, ) async def _get_stream_details_for_podcast_episode(self, item_id: str) -> StreamDetails: diff --git a/music_assistant/providers/ibroadcast/__init__.py b/music_assistant/providers/ibroadcast/__init__.py index 0e044092..2a3a11bc 100644 --- a/music_assistant/providers/ibroadcast/__init__.py +++ b/music_assistant/providers/ibroadcast/__init__.py @@ -246,6 +246,8 @@ class IBroadcastProvider(MusicProvider): ), stream_type=StreamType.HTTP, path=url, + can_seek=True, + allow_seek=True, ) async def _get_tracks(self, track_ids: list[int], is_playlist: bool = False) -> list[Track]: diff --git a/music_assistant/providers/jellyfin/__init__.py b/music_assistant/providers/jellyfin/__init__.py index a4309ca4..9e698dcf 100644 --- a/music_assistant/providers/jellyfin/__init__.py +++ b/music_assistant/providers/jellyfin/__init__.py @@ -450,6 +450,8 @@ class JellyfinProvider(MusicProvider): jellyfin_track[ITEM_KEY_RUNTIME_TICKS] / 10000000 ), # 10000000 ticks per millisecond) path=url, + can_seek=True, + allow_seek=True, ) async def get_similar_tracks(self, prov_track_id: str, limit: int = 25) -> list[Track]: diff --git a/music_assistant/providers/plex/__init__.py b/music_assistant/providers/plex/__init__.py index d2212195..d4aa15a0 100644 --- a/music_assistant/providers/plex/__init__.py +++ b/music_assistant/providers/plex/__init__.py @@ -915,6 +915,8 @@ class PlexProvider(MusicProvider): stream_type=StreamType.HTTP, duration=plex_track.duration, data=plex_track, + can_seek=True, + allow_seek=True, ) if content_type != ContentType.M4A: diff --git a/music_assistant/providers/podcastfeed/__init__.py b/music_assistant/providers/podcastfeed/__init__.py index 0314ecab..bf9148dd 100644 --- a/music_assistant/providers/podcastfeed/__init__.py +++ b/music_assistant/providers/podcastfeed/__init__.py @@ -179,6 +179,8 @@ class PodcastMusicprovider(MusicProvider): media_type=MediaType.PODCAST_EPISODE, stream_type=StreamType.HTTP, path=episode["enclosures"][0]["url"], + can_seek=True, + allow_seek=True, ) raise MediaNotFoundError("Stream not found") diff --git a/music_assistant/providers/qobuz/__init__.py b/music_assistant/providers/qobuz/__init__.py index df820fda..0549e454 100644 --- a/music_assistant/providers/qobuz/__init__.py +++ b/music_assistant/providers/qobuz/__init__.py @@ -440,6 +440,8 @@ class QobuzProvider(MusicProvider): duration=streamdata["duration"], data=streamdata, # we need these details for reporting playback path=streamdata["url"], + can_seek=True, + allow_seek=True, ) async def _report_playback_started(self, streamdata: dict) -> None: diff --git a/music_assistant/providers/radiobrowser/__init__.py b/music_assistant/providers/radiobrowser/__init__.py index 68a8a010..1b85736b 100644 --- a/music_assistant/providers/radiobrowser/__init__.py +++ b/music_assistant/providers/radiobrowser/__init__.py @@ -193,7 +193,10 @@ class RadioBrowserProvider(MusicProvider): if TYPE_CHECKING: stored_radios = cast(list[str], stored_radios) for item in stored_radios: - yield await self.get_radio(item) + try: + yield await self.get_radio(item) + except MediaNotFoundError as err: + self.logger.warning("Radio station %s not found: %s", item, err) async def library_add(self, item: MediaItemType) -> bool: """Add item to provider's library. Return true on success.""" @@ -364,4 +367,5 @@ class RadioBrowserProvider(MusicProvider): stream_type=StreamType.HTTP, path=stream.url_resolved, can_seek=False, + allow_seek=False, ) diff --git a/music_assistant/providers/siriusxm/__init__.py b/music_assistant/providers/siriusxm/__init__.py index 998d26f2..0649caba 100644 --- a/music_assistant/providers/siriusxm/__init__.py +++ b/music_assistant/providers/siriusxm/__init__.py @@ -238,6 +238,7 @@ class SiriusXMProvider(MusicProvider): media_type=MediaType.RADIO, path=hls_path, can_seek=False, + allow_seek=False, ) return self._current_stream_details diff --git a/music_assistant/providers/soundcloud/__init__.py b/music_assistant/providers/soundcloud/__init__.py index e4567654..e0363ed9 100644 --- a/music_assistant/providers/soundcloud/__init__.py +++ b/music_assistant/providers/soundcloud/__init__.py @@ -319,6 +319,8 @@ class SoundcloudMusicProvider(MusicProvider): if url.startswith("https://cf-hls-media.sndcdn.com") else StreamType.HTTP, path=url, + can_seek=True, + allow_seek=True, ) async def _parse_artist(self, artist_obj: dict[str, Any]) -> Artist: diff --git a/music_assistant/providers/test/__init__.py b/music_assistant/providers/test/__init__.py index f26d8f56..d645ad52 100644 --- a/music_assistant/providers/test/__init__.py +++ b/music_assistant/providers/test/__init__.py @@ -353,4 +353,5 @@ class TestProvider(MusicProvider): stream_type=StreamType.HTTP, path=SILENCE_FILE_LONG, can_seek=True, + allow_seek=True, ) diff --git a/music_assistant/providers/tidal/__init__.py b/music_assistant/providers/tidal/__init__.py index 5e27d37e..b9c3026f 100644 --- a/music_assistant/providers/tidal/__init__.py +++ b/music_assistant/providers/tidal/__init__.py @@ -611,6 +611,8 @@ class TidalProvider(MusicProvider): stream_type=StreamType.HTTP, duration=track.duration, path=url, + can_seek=True, + allow_seek=True, ) @throttle_with_retries diff --git a/music_assistant/providers/tunein/__init__.py b/music_assistant/providers/tunein/__init__.py index a0e3ea8b..c03a2ddf 100644 --- a/music_assistant/providers/tunein/__init__.py +++ b/music_assistant/providers/tunein/__init__.py @@ -251,6 +251,7 @@ class TuneInProvider(MusicProvider): media_type=MediaType.RADIO, stream_type=StreamType.HTTP, path=item_id, + allow_seek=False, can_seek=False, ) if "--" in item_id: @@ -269,6 +270,7 @@ class TuneInProvider(MusicProvider): media_type=MediaType.RADIO, stream_type=StreamType.HTTP, path=stream["url"], + allow_seek=False, can_seek=False, ) msg = f"Unable to retrieve stream details for {item_id}" diff --git a/music_assistant/providers/ytmusic/__init__.py b/music_assistant/providers/ytmusic/__init__.py index 3a2a06da..4e39a0cf 100644 --- a/music_assistant/providers/ytmusic/__init__.py +++ b/music_assistant/providers/ytmusic/__init__.py @@ -551,6 +551,8 @@ class YoutubeMusicProvider(MusicProvider): ), stream_type=StreamType.HTTP, path=stream_format["url"], + can_seek=True, + allow_seek=True, ) if ( stream_format.get("audio_channels")