fix: keep editor playback active on playhead changes
This commit is contained in:
@@ -4508,6 +4508,9 @@ class AudioEditorDialog(QDialog):
|
|||||||
if not checked:
|
if not checked:
|
||||||
self._stop_play()
|
self._stop_play()
|
||||||
return
|
return
|
||||||
|
self._play_from_playhead()
|
||||||
|
|
||||||
|
def _play_from_playhead(self) -> None:
|
||||||
play_t = self._playhead_secs()
|
play_t = self._playhead_secs()
|
||||||
se = self._selection_secs()
|
se = self._selection_secs()
|
||||||
if se is not None and se[0] <= play_t <= se[1]:
|
if se is not None and se[0] <= play_t <= se[1]:
|
||||||
@@ -4539,7 +4542,7 @@ class AudioEditorDialog(QDialog):
|
|||||||
end: float | None = None,
|
end: float | None = None,
|
||||||
loop: bool = False) -> None:
|
loop: bool = False) -> None:
|
||||||
from PyQt6.QtCore import QProcess
|
from PyQt6.QtCore import QProcess
|
||||||
self._stop_play()
|
self._stop_play(reset_button=False)
|
||||||
self._play_proc = QProcess(self)
|
self._play_proc = QProcess(self)
|
||||||
self._play_proc.finished.connect(self._on_play_finished)
|
self._play_proc.finished.connect(self._on_play_finished)
|
||||||
self._play_proc.errorOccurred.connect(self._on_play_error)
|
self._play_proc.errorOccurred.connect(self._on_play_error)
|
||||||
@@ -4570,7 +4573,7 @@ class AudioEditorDialog(QDialog):
|
|||||||
|
|
||||||
def _on_wave_playhead_changed(self, t: float) -> None:
|
def _on_wave_playhead_changed(self, t: float) -> None:
|
||||||
if self._play_proc is not None:
|
if self._play_proc is not None:
|
||||||
self._stop_play()
|
self._play_from_playhead()
|
||||||
|
|
||||||
def _playhead_secs(self) -> float:
|
def _playhead_secs(self) -> float:
|
||||||
t = self._wave.playhead()
|
t = self._wave.playhead()
|
||||||
@@ -4623,7 +4626,7 @@ class AudioEditorDialog(QDialog):
|
|||||||
self._btn_play.setChecked(False)
|
self._btn_play.setChecked(False)
|
||||||
self._btn_play.blockSignals(False)
|
self._btn_play.blockSignals(False)
|
||||||
|
|
||||||
def _stop_play(self) -> None:
|
def _stop_play(self, reset_button: bool = True) -> None:
|
||||||
proc = self._play_proc
|
proc = self._play_proc
|
||||||
self._play_proc = None
|
self._play_proc = None
|
||||||
self._playhead_timer.stop()
|
self._playhead_timer.stop()
|
||||||
@@ -4636,8 +4639,9 @@ class AudioEditorDialog(QDialog):
|
|||||||
proc.kill()
|
proc.kill()
|
||||||
proc.waitForFinished(100)
|
proc.waitForFinished(100)
|
||||||
proc.deleteLater()
|
proc.deleteLater()
|
||||||
self._btn_play.setText("▶ Play")
|
if reset_button:
|
||||||
if self._btn_play.isChecked():
|
self._btn_play.setText("▶ Play")
|
||||||
|
if reset_button and self._btn_play.isChecked():
|
||||||
self._btn_play.blockSignals(True)
|
self._btn_play.blockSignals(True)
|
||||||
self._btn_play.setChecked(False)
|
self._btn_play.setChecked(False)
|
||||||
self._btn_play.blockSignals(False)
|
self._btn_play.blockSignals(False)
|
||||||
|
|||||||
@@ -1076,6 +1076,51 @@ def test_editor_play_button_loops_selection_when_playhead_inside(win, tmp_path,
|
|||||||
assert seen == {"start": 1.25, "end": 2.75, "loop": True}
|
assert seen == {"start": 1.25, "end": 2.75, "loop": True}
|
||||||
|
|
||||||
|
|
||||||
|
def test_editor_playhead_change_keeps_playback_running(win, tmp_path, monkeypatch):
|
||||||
|
import main as m
|
||||||
|
src = tmp_path / "v0.wav"; src.write_bytes(b"")
|
||||||
|
dlg = m.AudioEditorDialog(str(src), parent=win)
|
||||||
|
dlg._clip_dur = 5.0
|
||||||
|
dlg._wave.set_view(0.0, 5.0)
|
||||||
|
dlg._wave.set_selection(1.25, 2.75)
|
||||||
|
dlg._wave.set_playhead(4.0)
|
||||||
|
dlg._play_proc = object()
|
||||||
|
dlg._btn_play.setChecked(True)
|
||||||
|
seen = {}
|
||||||
|
stopped = {"n": 0}
|
||||||
|
monkeypatch.setattr(
|
||||||
|
dlg, "_play_current",
|
||||||
|
lambda start=None, end=None, loop=False:
|
||||||
|
seen.update(start=start, end=end, loop=loop))
|
||||||
|
monkeypatch.setattr(dlg, "_stop_play", lambda: stopped.__setitem__("n", stopped["n"] + 1))
|
||||||
|
dlg._on_wave_playhead_changed(4.0)
|
||||||
|
assert seen == {"start": 4.0, "end": 5.0, "loop": False}
|
||||||
|
assert stopped["n"] == 0
|
||||||
|
assert dlg._btn_play.isChecked()
|
||||||
|
|
||||||
|
|
||||||
|
def test_editor_playhead_change_keeps_looping_when_inside_selection(win, tmp_path, monkeypatch):
|
||||||
|
import main as m
|
||||||
|
src = tmp_path / "v0.wav"; src.write_bytes(b"")
|
||||||
|
dlg = m.AudioEditorDialog(str(src), parent=win)
|
||||||
|
dlg._clip_dur = 5.0
|
||||||
|
dlg._wave.set_view(0.0, 5.0)
|
||||||
|
dlg._wave.set_selection(1.25, 2.75)
|
||||||
|
dlg._wave.set_playhead(2.0)
|
||||||
|
dlg._play_proc = object()
|
||||||
|
dlg._btn_play.setChecked(True)
|
||||||
|
seen = {}
|
||||||
|
stopped = {"n": 0}
|
||||||
|
monkeypatch.setattr(
|
||||||
|
dlg, "_play_current",
|
||||||
|
lambda start=None, end=None, loop=False:
|
||||||
|
seen.update(start=start, end=end, loop=loop))
|
||||||
|
monkeypatch.setattr(dlg, "_stop_play", lambda: stopped.__setitem__("n", stopped["n"] + 1))
|
||||||
|
dlg._on_wave_playhead_changed(2.0)
|
||||||
|
assert seen == {"start": 1.25, "end": 2.75, "loop": True}
|
||||||
|
assert stopped["n"] == 0
|
||||||
|
|
||||||
|
|
||||||
def test_editor_has_local_speed_controls(win, tmp_path):
|
def test_editor_has_local_speed_controls(win, tmp_path):
|
||||||
import main as m
|
import main as m
|
||||||
from PyQt6.QtWidgets import QPushButton
|
from PyQt6.QtWidgets import QPushButton
|
||||||
|
|||||||
Reference in New Issue
Block a user