From dc346f375844ee62443b02348648851d10b0941b Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Tue, 31 May 2022 11:45:13 +0200 Subject: [PATCH] Fix queue repeat issues (#349) * clear current item when playback stopped (and repeat off) * restart queue from beginning when repeat enabled --- music_assistant/models/player_queue.py | 44 +++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/music_assistant/models/player_queue.py b/music_assistant/models/player_queue.py index 24181b87..471837bf 100644 --- a/music_assistant/models/player_queue.py +++ b/music_assistant/models/player_queue.py @@ -351,9 +351,11 @@ class PlayerQueue: Returns None if queue is empty or no more items. """ - if next_index := self.get_next_index(self._current_index): + try: + next_index = self.get_next_index(self._current_index) return self._items[next_index] - return None + except IndexError: + return None def get_item(self, index: int) -> QueueItem | None: """Get queue item by index.""" @@ -660,10 +662,19 @@ class PlayerQueue: self._last_state = self.player.state # always signal update if playback state changed self.signal_update() - # handle case where stream stopped on purpose and we need to restart it - if self.player.state != PlayerState.PLAYING and self._signal_next: - self._signal_next = False - self.mass.create_task(self.resume()) + if self.player.state != PlayerState.PLAYING: + # handle end of queue + if self._current_index >= (len(self._items) - 1): + self._current_index += 1 + self._current_item_elapsed_time = 0 + # repeat enabled (of whole queue), play queue from beginning + if self.settings.repeat_mode == RepeatMode.ALL: + self.mass.create_task(self.play_index(0)) + + # handle case where stream stopped on purpose and we need to restart it + elif self._signal_next: + self._signal_next = False + self.mass.create_task(self.resume()) # start poll/updater task if playback starts on player async def updater() -> None: @@ -688,7 +699,6 @@ class PlayerQueue: new_index = self._current_index track_time = self._current_item_elapsed_time new_item_loaded = False - # if self.player.state == PlayerState.PLAYING: if self.player.state == PlayerState.PLAYING and self.player.elapsed_time > 0: new_index, track_time = self.__get_queue_stream_index() # process new index @@ -753,19 +763,15 @@ class PlayerQueue: self._next_start_index = self.get_next_index(self._next_start_index) return next_idx - def get_next_index(self, index: int) -> int | None: - """Return the next index or None if no more items.""" - if not self._items or index is None: - # queue is empty - return None + def get_next_index(self, cur_index: int) -> int: + """Return the next index for the queue, accounting for repeat settings.""" + if not self._items or cur_index is None: + raise IndexError("No (more) items in queue") if self.settings.repeat_mode == RepeatMode.ONE: - return index - if len(self._items) > (index + 1): - return index + 1 - if self.settings.repeat_mode == RepeatMode.ALL: - # repeat enabled, start queue at beginning - return 0 - return None + return cur_index + # simply return the next index. other logic is guarded to detect the index + # being higher than the number of items to detect end of queue and/or handle repeat. + return cur_index + 1 async def queue_stream_signal_next(self): """Indicate that queue stream needs to start next index once playback finished.""" -- 2.34.1