Plex Connect: refactor and fixes plugin#3510
Open
anatosun wants to merge 8 commits intomusic-assistant:devfrom
Open
Plex Connect: refactor and fixes plugin#3510anatosun wants to merge 8 commits intomusic-assistant:devfrom
anatosun wants to merge 8 commits intomusic-assistant:devfrom
Conversation
handle_refresh_play_queue was missing the _updating_from_plex guard that all other command handlers use. Without it, any queue refresh from Plex would modify the MA queue, triggering _handle_queue_items_updated, which would recreate the Plex PlayQueue, causing another refreshPlayQueue — an infinite loop. The stale PlayQueue 404 errors were also a symptom of this.
Addresses style fixes and better segregation of functionalities to make the plugin easier to maintain and for others to contribute to. The monolithic player_remote.py is split into focused modules: - server.py — core HTTP server, routing, lifecycle - timeline.py — timeline XML building and broadcasting - playback.py — playback control command handlers - queue_commands.py — play queue HTTP command handlers - queue_sync.py — background queue loading and MA↔Plex sync logic Also promotes the plugin stage from alpha to beta, and fixes several bugs discovered during the refactor: a missing _updating_from_plex guard in handle_create_play_queue, a race condition in background queue loading, and shuffle changes not being synced back to the Plex play queue.
Replace direct PlayQueue.get() calls with a _fetch_full_play_queue helper that paginates past the Plex server's per-request cap (~200 items). The helper claims ownership of the queue (own=True) on the first fetch, then uses center + includeBefore=False to walk forward page by page until playQueueTotalCount items have been collected.
Remove the unconditional set_shuffle(False) in handle_refresh_play_queue (it was a workaround for the old infinite-loop bug, now fixed) and replace it with a sync of playqueue.playQueueShuffled after the queue is loaded. _play_from_plex_queue also now uses playqueue.playQueueShuffled as the authoritative shuffle state, falling back to the request parameter.
When a Plex play queue is flagged as shuffled, fetch the original source collection via playQueueSourceURI, load it into MA in its natural order, then apply MA's own shuffle and propagate the resulting order back to Plex via a new PlayQueue. This avoids double-shuffling an already-shuffled list. Also ensure MA shuffle is always explicitly synced to the Plex queue's shuffle state on playMedia, so a leftover enabled shuffle cannot silently reorder a non-shuffled queue.
Contributor
🔒 Dependency Security Report✅ No dependency changes detected in this PR. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors the Plex Connect plugin by splitting the former monolithic player_remote.py into smaller modules, while also addressing play-queue sync issues (pagination, ownership, shuffle propagation, and refresh-loop protection).
Changes:
- Split remote-control server responsibilities into focused modules (
server,timeline,playback,queue_commands,queue_sync) and removedplayer_remote.py. - Improved Plex PlayQueue handling (pagination past server window caps,
own=Trueinitial fetch, shuffle/source handling). - Updated plugin stage to
betaand adjusted imports to use the new module layout.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| music_assistant/providers/plex_connect/timeline.py | Builds/broadcasts Plex timeline XML and posts timeline updates to controllers/server. |
| music_assistant/providers/plex_connect/server.py | New per-player HTTP server wiring/routes and MA event subscriptions. |
| music_assistant/providers/plex_connect/queue_sync.py | MA↔Plex queue synchronization and MA event handlers. |
| music_assistant/providers/plex_connect/queue_commands.py | Implements Plex play queue HTTP commands and full-queue fetching/pagination. |
| music_assistant/providers/plex_connect/playback.py | Implements playback control endpoints (play/pause/seek/skip/etc.). |
| music_assistant/providers/plex_connect/init.py | Switches provider import to the new server.PlayerRemoteInstance. |
| music_assistant/providers/plex_connect/manifest.json | Moves plugin stage from alpha to beta. |
| music_assistant/providers/plex_connect/player_remote.py | Removed (functionality replaced by the new split modules). |
15 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR refactors the Plex Connect plugin and fixes several issues encountered during
testing.
Refactor
The monolithic player_remote.py has been split into focused modules for better
readability and easier contributions:
refreshPlayQueue)
The plugin stage has also been updated from alpha to beta.
Bug fixes
_updating_from_plex guard, causing a loop when features like Guest DJ were used.
fetching play queues. The fetch now paginates through the full queue using
playQueueTotalCount.
takes full control of the queue.
_create_plex_playqueue_from_ma call to sync the new order back.
original source is now fetched via playQueueSourceURI and loaded into MA in its
natural order. MA then applies its own shuffle and propagates the result back to
Plex, avoiding double-shuffling an already-shuffled list.
explicitly synced from Plex on every playMedia command, preventing a previously
enabled MA shuffle from silently reordering a non-shuffled queue.