Play held-title theme music while the title page is resumed #71
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fm/theme-music-title"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Activate theme music on held Wolfskin title pages without changing their UI or the Conductarr TV API. Target:
fm/tv-round2.Change
ThemeSongPlayerfrom aLifecycleResumeEffect, restricted to the current held title entry.AppPreference.PlayThemeMusic: Disabled stays silent and High remains the upstream 0.5 volume.Verification
33 touched JVM/native Robolectric cases passed, including seven new theme lifecycle cases. The native smoke opens the real episode title destination, observes one series-theme start, activates Play, and verifies theme stop before playback navigation with no restart while the outgoing title remains composed. Other cases cover held movies, metadata refresh/recreation, catalogue-only and disabled titles, pause/resume, disposal, identity ownership and navigation away/back.
The first run lacked the Android 16 Robolectric runtime for six existing Back cases; the repository cache task supplied it and the final run passed all 33. Shared Gradle lock respected; no full suite, APK build, TV-box access, ADB or Jellyfin mutation.
One deferred manual check
With operator approval, hand-place one
theme.m4asymlink in a single held title's layer folder, refresh that item in Jellyfin, then open the title page at High. Confirm audible theme playback, silence when starting video/leaving/backgrounding/switching person/signing out, and one theme when returning. This check was not performed in this lane.Risk
Audible end-to-end proof depends on Jellyfin indexing a real theme file; native tests use a fake theme player. The existing upstream streaming and volume implementation is unchanged.
Implementation and verification assisted by AI.
Review of the theme music title-page PR at head
2f3cdf233976e60745c9be10e7c920cad1d83674(basefm/tv-round2).Code verdict: APPROVE (
review/code-claude= success).Design verdict: PASS (
review/design-claude= success). No visual, focus or layout change: the diff adds one non-visual composable call.Held titles only.
movie:<tmdb>,tv:<tmdb>) don't parse as UUIDs, a missing series id stays silent, and person pages never play. The call also requires the Ready status.Preference.
playThemeSongssetting. Disabled never starts the effect, and switching to Disabled while playing stops it.Once, not twice.
LifecycleResumeEffectkeyed on item id, person-and-session owner, and volume.Stops on every required event.
play()stops the theme just beforenavigateTo(Playback), and the trailer path stops it too.Regression surface. Only the Hilt-injected constructor parameter and the two
stop()calls touch non-theme code. All 11 test constructor sites were updated. A merge-tree check against currentfm/tv-round2is clean. I could not test against the pending polish lanes.Non-blocking notes:
ThemeSongPlayer.playandstopeach run in their ownscope.launchon the IO scope. The mutex serializes them but does not preserve call order. A page swap (title to related title and Back, or a person switch) issues a stop and a play back to back, so an inversion would silence the returning page or leave a theme running on a page that is gone. The window is a few milliseconds and the old upstream screens had the same property. The fake player cannot observe it. If it shows on the box, the fix belongs in the upstream player (an ordered single-threaded dispatch). [INFERENCE]stop()is asynchronous, so there are a few milliseconds of audio before the video player starts. The stop is issued before navigation, so there is no sustained overlap.ThemeSongVolume.HIGHESTmaps to75fupstream; ExoPlayer clamps it. Pre-existing.Full report (review 9):
/root/.treehouse/firstmate-7bab20/2/firstmate/data/round2-review/report.md. Not run: Gradle/make, nothing on the box.