- PlayerPanel now leaves an 8px bottom margin so the transport row
isn't flush against the tab's edge.
- Frame-step buttons read '⏮ Frame' / 'Frame ⏭' instead of
'⏮ Frame (,)' / 'Frame ⏭ (.)' -- the shortcuts still work, just not
spelled out on the buttons.
- Detect Next Clap is now a button in the Sync markers panel next to
Detect All Claps (still also in the Tools menu), kept in sync with
its menu action's enabled state the same way Detect All Claps was.
Extracts a new PlayerPanel widget (video + its own seek slider/marker
strip + its own centered frame-step/play/mute transport row) into
player_panel.py. Both Source and Preview tabs now use one, so
switching tabs switches a complete, independent monitor -- its own
scrubber, its own play state, its own frame-stepping -- not just the
video frame with a single shared play button underneath.
main.py's global keyboard shortcuts (,/./space/left/right) now
dispatch to whichever panel is active via a small _active_panel()
helper, so they follow the same 'whichever monitor you're looking at'
rule as the on-screen controls.
MarkerStrip (clap detection) and the Mark Audio/Video/offset/export
row stay outside the tabs, at the MainWindow level -- marking and
exporting are inherently about the source file, not the preview clip,
so only the timeline+transport moved, not the whole marking workflow.
Updated every existing smoke test for the new win.source_panel.* /
win.preview_panel.* structure (previously flat win.player,
win.seek_slider, etc.), and added a new check to
smoke_test_preview.py confirming the Preview tab's slider is a
genuinely separate, functional widget -- dragging it seeks the preview
player without moving the source player, which is the actual thing
this change was for.
Verified the full suite on the virtual Xvfb display, plus a live
click-through (mark both events, build preview, confirm the Preview
tab shows its own populated timeline/transport, not the source's).