Chore: Limit number of retries for failed track
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 30 Mar 2025 22:34:09 +0000 (00:34 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 30 Mar 2025 22:34:09 +0000 (00:34 +0200)
music_assistant/controllers/metadata.py
music_assistant/controllers/player_queues.py

index 16756306d5cb26228cce45d407409c5c3daa1e4f..b993532e56389e23841ae41c2aab126b0ce7b7ec 100644 (file)
@@ -347,10 +347,10 @@ class MetaDataController(CoreController):
         if not image.remotely_accessible or prefer_proxy or size:
             # return imageproxy url for images that need to be resolved
             # the original path is double encoded
-            encoded_url = urllib.parse.quote(urllib.parse.quote(image.path))
+            encoded_url = urllib.parse.quote_plus(urllib.parse.quote_plus(image.path))
             return (
-                f"{self.mass.streams.base_url}/imageproxy?path={encoded_url}"
-                f"&provider={image.provider}&size={size}&fmt={image_format}"
+                f"{self.mass.streams.base_url}/imageproxy?provider={image.provider}"
+                f"&size={size}&fmt={image_format}&path={encoded_url}"
             )
         return image.path
 
@@ -389,7 +389,7 @@ class MetaDataController(CoreController):
             return web.Response(status=404)
         if "%" in path:
             # assume (double) encoded url, decode it
-            path = urllib.parse.unquote(path)
+            path = urllib.parse.unquote_plus(path)
         with suppress(FileNotFoundError):
             image_data = await self.get_thumbnail(
                 path, size=size, provider=provider, image_format=image_format
index ed3051678a0ad26d97ca7469198a706e002f67df..26c01f396419a402f7b7e554f5491b91dc6ced47 100644 (file)
@@ -661,7 +661,8 @@ class PlayerQueuesController(CoreController):
             # TODO: forward to underlying player if not active
             return
         idx = self._queues[queue_id].current_index
-        while True:
+        attempts = 5
+        while attempts:
             try:
                 if (next_index := self._get_next_index(queue_id, idx, True)) is not None:
                     await self.play_index(queue_id, next_index, debounce=True)
@@ -672,6 +673,7 @@ class PlayerQueuesController(CoreController):
                     queue.display_name,
                 )
                 idx += 1
+                attempts -= 1
 
     @api_command("player_queues/previous")
     async def previous(self, queue_id: str) -> None:
@@ -979,6 +981,9 @@ class PlayerQueuesController(CoreController):
             queue_item = self.get_item(queue_id, next_index)
             if queue_item is None:
                 raise QueueEmpty("No more tracks left in the queue.")
+            if idx >= 10:
+                # we only allow 10 retries to prevent infinite loops
+                raise QueueEmpty("No more (playable) tracks left in the queue.")
             try:
                 await self._load_item(queue_item, next_index)
                 # we're all set, this is our next item
@@ -1131,9 +1136,9 @@ class PlayerQueuesController(CoreController):
         if (
             insert_at_index == (index_in_buffer + 1)
             and queue.state != PlayerState.IDLE
-            and (cur_item := self.get_item(queue_id, index_in_buffer))
+            and (next_item := self._get_next_item(queue_id, index_in_buffer))
         ):
-            self._enqueue_next_item(queue_id, cur_item.queue_item_id)
+            self._enqueue_next_item(queue_id, next_item)
 
     def update_items(self, queue_id: str, queue_items: list[QueueItem]) -> None:
         """Update the existing queue items, mostly caused by reordering."""