From: Marcel van der Veldt Date: Sun, 22 May 2022 19:44:16 +0000 (+0200) Subject: Fix: Stop playback at end of queue properly (#336) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=768c4ad922b1f42c1cb810f99937fc1e1fc13b05;p=music-assistant-server.git Fix: Stop playback at end of queue properly (#336) * Fix: Stop queue stream when no more tracks in queue (no repeat) * send stop when queue is empty * send silence to player at queue end --- diff --git a/music_assistant/controllers/stream.py b/music_assistant/controllers/stream.py index c956d7e6..1e35909c 100644 --- a/music_assistant/controllers/stream.py +++ b/music_assistant/controllers/stream.py @@ -11,6 +11,7 @@ from aiohttp import web from music_assistant.helpers.audio import ( check_audio_support, + create_wave_header, crossfade_pcm_parts, get_media_stream, get_preview_stream, @@ -26,7 +27,11 @@ from music_assistant.models.enums import ( MediaType, ProviderType, ) -from music_assistant.models.errors import MediaNotFoundError, MusicAssistantError +from music_assistant.models.errors import ( + MediaNotFoundError, + MusicAssistantError, + QueueEmpty, +) from music_assistant.models.event import MassEvent from music_assistant.models.player_queue import PlayerQueue, QueueItem @@ -137,12 +142,21 @@ class StreamController: return web.Response(status=404) # prepare request + try: + start_streamdetails = await queue.queue_stream_prepare() + except QueueEmpty: + # send stop here to prevent the player from retrying over and over + await queue.stop() + # send some silence to allow the player to process the stop request + result = create_wave_header(duration=10) + result += b"\0" * 1764000 + return web.Response(status=200, body=result, content_type="audio/wav") + resp = web.StreamResponse( status=200, reason="OK", headers={"Content-Type": f"audio/{fmt}"} ) await resp.prepare(request) - start_streamdetails = await queue.queue_stream_prepare() output_fmt = ContentType(fmt) # work out sample rate if queue.settings.crossfade_mode == CrossFadeMode.ALWAYS: @@ -162,7 +176,7 @@ class StreamController: output_format=output_fmt, ) # get the raw pcm bytes from the queue stream and on the fly encode to wanted format - # send the compressed/endoded stream to the client. + # send the compressed/encoded stream to the client. async with AsyncProcess(sox_args, True) as sox_proc: async def writer(): diff --git a/music_assistant/models/player_queue.py b/music_assistant/models/player_queue.py index 210f21ad..f524afc2 100644 --- a/music_assistant/models/player_queue.py +++ b/music_assistant/models/player_queue.py @@ -723,7 +723,7 @@ class PlayerQueue: async def queue_stream_prepare(self) -> StreamDetails: """Call when queue_streamer is about to start playing.""" - start_from_index = self._next_start_index or 0 + start_from_index = self._next_start_index try: next_item = self._items[start_from_index] except (IndexError, TypeError) as err: @@ -737,7 +737,7 @@ class PlayerQueue: async def queue_stream_start(self) -> int: """Call when queue_streamer starts playing the queue stream.""" - start_from_index = self._next_start_index or 0 + start_from_index = self._next_start_index self._current_item_elapsed_time = 0 self._current_index = start_from_index self._start_index = start_from_index @@ -754,12 +754,9 @@ class PlayerQueue: def get_next_index(self, index: int) -> int | None: """Return the next index or None if no more items.""" - if not self._items: + if not self._items or index is None: # queue is empty return None - if index is None: - # guard just in case - return 0 if self.settings.repeat_mode == RepeatMode.ONE: return index if len(self._items) > (index + 1):