Skip to content

Commit

Permalink
Fix cast player playing duplicate songs (#923)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt authored Nov 12, 2023
1 parent 91ff687 commit 6f12531
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions music_assistant/server/providers/chromecast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class CastPlayer:
mz_controller: MultizoneController | None = None
next_url: str | None = None
active_group: str | None = None
current_queue_item_id: str | None = None


class ChromecastProvider(PlayerProvider):
Expand Down Expand Up @@ -425,6 +426,7 @@ def on_new_media_status(self, castplayer: CastPlayer, status: MediaStatus):
"""Handle updated MediaStatus."""
castplayer.logger.debug("Received media status update: %s", status.player_state)
# player state
prev_state = castplayer.player.state
if status.player_is_playing:
castplayer.player.state = PlayerState.PLAYING
elif status.player_is_paused:
Expand All @@ -443,15 +445,26 @@ def on_new_media_status(self, castplayer: CastPlayer, status: MediaStatus):
castplayer.player.current_url = status.content_id
self.mass.loop.call_soon_threadsafe(self.mass.players.update, castplayer.player_id)

# enqueue next item if needed
if (
# enqueue next item if player is almost at the end of the track
if ( # noqa: SIM114
castplayer.player.state == PlayerState.PLAYING
and castplayer.player.active_source == castplayer.player.player_id
and castplayer.next_url in (None, castplayer.player.current_url)
and (queue := self.mass.player_queues.get(castplayer.player_id))
and (current_item := queue.current_item)
and current_item.duration
and (current_item.duration - castplayer.player.elapsed_time) <= 10
):
asyncio.run_coroutine_threadsafe(self._enqueue_next_track(castplayer), self.mass.loop)
# failsafe enqueue next item if player stopped at the end of the track
elif (
castplayer.player.state == PlayerState.IDLE
and prev_state == PlayerState.PLAYING
and castplayer.player.active_source == castplayer.player.player_id
and castplayer.player.current_url == castplayer.next_url
):
asyncio.run_coroutine_threadsafe(self._enqueue_next_track(castplayer), self.mass.loop)
# handle end of MA queue - set current item to None
if (
elif (
castplayer.player.state == PlayerState.IDLE
and castplayer.player.current_url
and (queue := self.mass.player_queues.get(castplayer.player_id))
Expand Down Expand Up @@ -495,14 +508,15 @@ async def _enqueue_next_track(self, castplayer: CastPlayer) -> None:
"""Enqueue the next track of the MA queue on the CC queue."""
try:
next_url, next_item, _ = await self.mass.player_queues.preload_next_url(
castplayer.player_id
castplayer.player_id, castplayer.current_queue_item_id
)
except QueueEmpty:
return

if castplayer.next_url == next_url:
return # already set ?!
castplayer.next_url = next_url
castplayer.current_queue_item_id = next_item.queue_item_id

# in flow/direct url mode, we just send the url and the metadata is of no use
if not next_item:
Expand Down

0 comments on commit 6f12531

Please sign in to comment.