ffmpeg's reconnect gave up on the first HTTP-error response, so a PMS
answering 503 (startup maintenance) after an idle-pause disconnect
surfaced as a clean mid-file EOF instead of riding through the outage.
The old bool meant "attempt was current and handled", so callers could
not distinguish a real pre-open failure (old stream still loaded) from
success — the distinction the #1520 recovery needs.
close#1514
A query submitted from the companion remote now behaves like a submit
instead of focus-to-type: TvKeyboardController closes an already-open
OSK and lands focus on the input without reopening it, then the shared
handleSearchSubmit path runs the search and focuses the first result.
Also guard DebouncedMediaSearch against selection-only controller
notifications re-arming the debounce into a duplicate fetch.
Co-authored-by: l3gitpanda <12003346+l3gitpanda@users.noreply.github.com>
A paused-but-alive player keeps its MediaCodec decoders and tunneled
passthrough AudioTrack while Plezy sits in the background, which can
degrade playback in every other app on shared-pipeline TV SoCs until
force-stop. After a 30s grace on Android TV the player is stopped
(retaining session state); returning reloads in place, or re-tunes the
channel for live TV.
When the display/system sleeps with a video paused, the window server
stops completing CAMetalLayer presents and mpv's MoltenVK swapchain wedges,
pinning one core at 100% until the app exits. occlusionState does not
reliably change on display sleep, so observe NSWorkspace screensDidSleep/
Wake to hide the metal layer (and drop the playback activity) while dark,
restoring on wake with a forced redraw when paused to avoid a stale frame.
Pairs with MPVKit v1.0.10, which gates libmpv presentation on the layer's
hidden state (check_visible) so presents actually stop while hidden.
The non-mixing playback session was activated in didFinishLaunching,
so merely opening the app stopped other apps' audio. Keep the category
configuration; playback start activates the session.
close#1496
Bumps os_media_controls so the audio session is only activated on
playing-state pushes; paused/metadata pushes no longer re-interrupt
other apps' audio (which caused the 1-2 Hz play/pause loop).
Pulls edde746/media_controls@71b96f8: iOS/macOS guard async artwork
downloads against track changes (slow art no longer lands on the next
track) and clear stale artwork when a track has none.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
TrackRow compared bare ids (server-scoped rating keys), so a track on
another server with the same id lit up as currently playing. Compare
globalKey (serverId:id) like the rest of the queue engine.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All timed presets shared one 'timed' bool, so arming any of 15/30/60
minutes checkmarked all three. The service now retains the armed
duration (sleepTimerDuration) and the menu marks the matching preset.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A queue edit can un-arm the next entry in the same instant mpv rolls
into it; the resulting transition was dropped as unexpected, leaving the
UI and progress reporting on the finished track for the entire next
file. Remember the cleared arm (generation-gated) so the transition is
still adopted, and handle the armed track no longer being in the queue:
advance to the queue's real next, or park when nothing follows. Also
fixes the latent fallthrough that left the cursor on the finished track
when the armed track vanished from the queue.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The platforms advertise stop, skip forward/backward, and playback-rate
commands by default, but both the music and video handlers silently
dropped them (Android Auto/Bluetooth stop and FF/rewind did nothing;
iOS/macOS showed a dead rate control). setControlsEnabled now manages
those controls: music handles Stop and in-track skips and stops
advertising a speed control; video handles Stop (exit, matching the
companion remote), skips via a shared relative-seek helper, and rate
changes through player.setRate. Skip commands stay off on iOS/macOS
where they would displace the next/previous lock-screen buttons.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
setNext() appended raw content:// URIs that mpv cannot open, stalling
playback at the SD-card-download track boundary. Convert to fdclose://
like open(), track the armed fd, and reclaim it via a new closeContentFd
method when the entry is dropped unplayed (close only when provably
unconsumed — playlist-pos 0 before and after the remove; leak on doubt).
The playlist-pos pre-check also keeps the clear path from removing the
playing entry when mpv rolls into the armed track mid-clear.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Shared TabChipStrip replaces the plain Rows in libraries/downloads/live
TV app bars (and live TV's hand-rolled scroll wrapper); chips center
themselves on focus so d-pad reaches off-screen tabs.
Queue sheet/panel now renders the whole playback order — dimmed played
tracks above the current one — instead of only up-next. Opens scrolled
to the current track and follows advancement while parked on it.
Wide layouts put the circular portrait beside a left-aligned
name/genre/bio/actions block (mirroring the album header) instead of
a centered mobile column floating over the left-hugging albums grid.
mpv's http-header-fields string-list parser splits on commas inside
header values, so X-Plex-Device on Apple hardware (model ids like
Mac17,9) produced a colon-less garbage header line that Plex rejects
with 400 'Error parsing HTTP request' — first hit by music direct play
on macOS, latent in the mpv video path too. Deliver headers via
change-list append items (open) and per-entry -clr/-append loadfile
options (gapless arming), each item verbatim and %len%-quoted against
the outer option-list split.
Bumps os_media_controls to 4f4b28f3: MediaStyle foreground service with
a JUnit-tested promote/demote/stop policy, artwork URL download (also
fixes video lock-screen art), and task-removal teardown that can't leak
orphan notifications. The music service opts into background mode per
session and requests POST_NOTIFICATIONS before first playback.
Album/artist downloads expand to tracks with pinned parent metadata,
aggregate progress, container deletes with reference-counted album
covers, and a Music tab on the downloads screen with fully offline
album playback. Home rows include music libraries (fixes plex hub
items being filtered to video types) and audio playlists join
download/sync rules.
Audio-only mpv core on every platform (dedicated
com.plezy/mpv_audio_player channels): parameterized android/windows/
linux mpv plugins and a new apple MpvAudioPlayerCore, all skipping
video/window paths (vid=no, audio-display=no, gapless-audio=weak).
MusicPlaybackService drives an in-memory queue with shuffle/repeat,
file-loaded-event gapless arming (property edges coalesce and the
android bridge drops them), per-track progress reporting, OS media
controls, audio focus, sleep timer, and error auto-skip.
PlaybackCoordinator enforces one live native player: starting video
disposes the audio core first.
Un-gates music libraries; adds CardShape.square plumbing (circular
artists), artists/albums/tracks browse groupings with per-grouping
sorts, audio playlists tab, artist + album detail screens with dpad
track rows, music context-menu actions, and a stub MusicPlaybackService
seam for the upcoming engine.