Two bugs from a live career session.
1. CHANGING ARRANGEMENT REPLAYED THE ARRIVAL FLYOVER.
changeArrangement() reloads the song through the normal load path, so
highway.js re-emits `song:loaded` — same filename, new arrangement. The venue
could not tell that from a fresh arrival, so it reset the machine and flew the
camera in from the back of the room again, mid-set, every time the player
switched lead -> rhythm. The player is already on stage.
onSongLoaded now compares the filename. A repeat of the song already on stage
keeps the video pipeline running and only re-syncs the mood: the performance
restarts, so the loop follows the reset machine with a quiet crossfade, never
the intro. A genuinely different song still gets the full teardown + flyover.
2. THE VENUE SHOWED UP ON THE VIRTUOSO HIGHWAY.
The venue was gated purely on `isVenueViz()` — the selected visualization,
which is a GLOBAL preference and says nothing about what is on screen.
Virtuoso borrows the same highway_3d renderer for its practice charts, so with
Venue selected it inherited the backdrop: the crowd and the stage behind a
chromatic exercise.
Selecting Venue is a preference for the PLAYER; it is not a licence to paint
the venue over whatever else happens to be using the renderer. The venue is now
gated on viz AND screen (`shouldBeActive`), and follows `screen:changed` — it
tears down on leaving the player and rebuilds on return. Nothing else changes:
stop() already unbinds the videos from the renderer, so deactivating is enough
to clear the backdrop.
Tests: both decisions exposed as pure predicates and pinned — arrangement switch
vs new song (including the first load, and a malformed payload that must not
suppress the flyover forever), and the venue's screen scope. The existing syncViz
test encoded the OLD contract (activate regardless of screen), so it now states
the new one and additionally asserts the venue does NOT activate on virtuoso.
Includes a guard test: with Venue selected AND on the player, the venue IS
active — without it, every "not active" assertion could pass vacuously.
All 8 new/updated assertions fail against the pre-fix source. eslint clean;
JS 1199/1199; pytest 2597 passed.