Feat: Allow core logic to handle seeking for providers without native seek support
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 10 Jan 2025 22:27:17 +0000 (23:27 +0100)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 10 Jan 2025 22:27:17 +0000 (23:27 +0100)
music_assistant/controllers/streams.py
music_assistant/providers/opensubsonic/sonic_provider.py
music_assistant/providers/spotify/__init__.py

index 29a601dc7508c11c3a8ba4684157357e57d55d74..1596ba5f12d73a620862bb7106ec24775bebd206 100644 (file)
@@ -910,9 +910,6 @@ class StreamsController(CoreController):
         pcm_format: AudioFormat,
     ) -> AsyncGenerator[tuple[bool, bytes], None]:
         """Get the audio stream for the given streamdetails as raw pcm chunks."""
-        is_radio = streamdetails.media_type == MediaType.RADIO or not streamdetails.duration
-        if is_radio:
-            streamdetails.seek_position = 0
         # collect all arguments for ffmpeg
         filter_params = []
         extra_input_args = []
@@ -978,8 +975,11 @@ class StreamsController(CoreController):
         # handle seek support
         if (
             streamdetails.seek_position
-            and streamdetails.media_type != MediaType.RADIO
-            and streamdetails.stream_type != StreamType.CUSTOM
+            and streamdetails.duration
+            and streamdetails.allow_seek
+            # allow seeking for custom streams,
+            # but only for custom streams that can't seek theirselves
+            and (streamdetails.stream_type != StreamType.CUSTOM or not streamdetails.can_seek)
         ):
             extra_input_args += ["-ss", str(int(streamdetails.seek_position))]
 
index f86e240c626a17ee0b29a1a522823216a1c4fb7c..db1bc60090c631f9d56b1d38c4bdb230bb4dad49 100644 (file)
@@ -874,6 +874,7 @@ class OpenSonicProvider(MusicProvider):
         return StreamDetails(
             item_id=item.id,
             provider=self.instance_id,
+            allow_seek=True,
             can_seek=self._seek_support,
             media_type=media_type,
             audio_format=AudioFormat(content_type=ContentType.try_parse(mime_type)),
@@ -902,6 +903,10 @@ class OpenSonicProvider(MusicProvider):
     ) -> AsyncGenerator[bytes, None]:
         """Provide a generator for the stream data."""
         audio_buffer = asyncio.Queue(1)
+        # ignore seek position if the server does not support it
+        # in that case we let the core handle seeking
+        if not self._seek_support:
+            seek_position = 0
 
         self.logger.debug("Streaming %s", streamdetails.item_id)
 
index f855811d38b19c57977f3c1b61a83ac28a897c6b..268f4d63f25c6f7d3dc2e08adce572e0ed319858 100644 (file)
@@ -556,6 +556,8 @@ class SpotifyProvider(MusicProvider):
                 content_type=ContentType.OGG,
             ),
             stream_type=StreamType.CUSTOM,
+            allow_seek=True,
+            can_seek=True,
         )
 
     async def get_audio_stream(