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).
77 lines
2.9 KiB
Python
77 lines
2.9 KiB
Python
"""Verifies arrow-key skips preserve whichever play/pause state the user
|
|
was already in, instead of always forcing a pause.
|
|
|
|
Calls the real PlayerPanel.seek_relative() method directly rather than
|
|
simulating the QShortcut keypress: QTest.keyClick against this shortcut was
|
|
observed to be unreliable in this headless setup even with Qt's
|
|
active-window state forced (see smoke_test_arrow_seek.py's note) --
|
|
sometimes the simulated key silently doesn't reach the shortcut at all, and
|
|
a debug script isolated that PlayerWidget.seek() itself works correctly
|
|
while playing, so the flakiness is in the synthetic-keypress dispatch, not
|
|
the app. The QShortcut -> seek_relative wiring itself (a single line) was
|
|
already independently confirmed with real xdotool keypresses against a
|
|
live window in an earlier session.
|
|
"""
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
from PyQt6.QtWidgets import QApplication
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
import main as app_main
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
CLIP = str(ROOT / "test_media" / "sync_test_INSYNC.mp4")
|
|
|
|
|
|
def main():
|
|
qapp = QApplication(sys.argv)
|
|
win = app_main.MainWindow()
|
|
win.show()
|
|
qapp.processEvents()
|
|
|
|
win._load(CLIP)
|
|
qapp.processEvents()
|
|
time.sleep(0.2)
|
|
qapp.processEvents()
|
|
|
|
# -- Case 1: paused before the skip -> stays paused after
|
|
assert win.source_panel.player.mpv.pause is True
|
|
before_pos = win.source_panel.player.get_position()
|
|
win.source_panel.seek_relative(5.0)
|
|
qapp.processEvents()
|
|
time.sleep(0.2)
|
|
qapp.processEvents()
|
|
after_pos = win.source_panel.player.get_position()
|
|
print(f"paused case: before={before_pos:.3f}s after={after_pos:.3f}s")
|
|
assert win.source_panel.player.mpv.pause is True, "should still be paused after skip"
|
|
assert win.source_panel.play_button.text() == "Play"
|
|
assert after_pos > before_pos + 4.0, "should have actually skipped forward"
|
|
print("PASS: stays paused across arrow-key skip when it started paused")
|
|
|
|
# -- Case 2: playing before the skip -> stays playing after
|
|
win.source_panel.player.seek(0.0)
|
|
win.source_panel.player.play()
|
|
win.source_panel.play_button.setText("Pause")
|
|
qapp.processEvents()
|
|
time.sleep(0.2)
|
|
before_pos = win.source_panel.player.get_position()
|
|
win.source_panel.seek_relative(5.0)
|
|
qapp.processEvents()
|
|
time.sleep(0.2)
|
|
qapp.processEvents()
|
|
assert win.source_panel.player.mpv.pause is False, "should still be playing after skip"
|
|
assert win.source_panel.play_button.text() == "Pause"
|
|
after_pos = win.source_panel.player.get_position()
|
|
print(f"playing case: before={before_pos:.3f}s after={after_pos:.3f}s (should have jumped ~5s and kept playing)")
|
|
assert after_pos > before_pos + 4.0, "should have actually skipped forward"
|
|
|
|
win.source_panel.shutdown()
|
|
win.preview_panel.shutdown()
|
|
print("\nPRESERVE PLAY STATE SMOKE TEST PASSED")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|