From 985c46772be8169c835e8e03ed204b65f4cfec17 Mon Sep 17 00:00:00 2001 From: Gavan Fantom Date: Thu, 17 Sep 2026 18:04:37 +0100 Subject: [PATCH] Add functionality to set a marker when playback is replaced. --- events.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/events.py b/events.py index 7488faf..bae41e7 100644 --- a/events.py +++ b/events.py @@ -110,6 +110,7 @@ class Playback(Event): self._nextdata = None self._nextfs = None self._delay = False + self._setmark = None self._stream = sounddevice.OutputStream( samplerate=self._fs, device=self._device, channels=self._channels, @@ -136,6 +137,9 @@ class Playback(Event): raise sounddevice.CallbackStop() self._current_frame += frames frames = 0 + if self._setmark is not None: + self._eventrunner.activate(self._setmark) + self._setmark = None def callback_fillchunk(self, outdata, offset, frames): chunksize = min(len(self._data) - self._current_frame, frames) @@ -171,19 +175,20 @@ class Playback(Event): self._stream.close(True) self._stream = None - def replace(self, media, delay=False, loop=False): + def replace(self, media, delay=False, loop=False, setmark=None): self._nextdata, self._nextfs = soundfile.read(media) self._delay = delay self._nextloop = loop + self._setmark = setmark # We really should check that the media is the sampe shape as the # existing playback. But for now, let's trust the user. *cough* - def notify(self, message, fadetime=10, db=30, media=None, delay=False, *args, **kwargs): + def notify(self, message, fadetime=10, db=30, media=None, delay=False, setmark=None, *args, **kwargs): if message == 'fadeout': self._fadecurve = np.logspace(0, -db/10, fadetime * self._fs) self._fadeframe = 0 elif message == 'replaceplayback': - self.replace(media, delay) + self.replace(media, delay, setmark=setmark) elif message == 'endloop': self._loop = False @@ -215,18 +220,23 @@ class EndLoop(Event): class PlaybackNext(Event): - def __init__(self, media, delay=False, loop=False, *args, **kwargs): + def __init__(self, media, delay=False, loop=False, setmark=None, *args, **kwargs): super().__init__(*args, **kwargs) self._media = media self._delay = delay self._loop = loop + self._setmark = setmark def __repr__(self): - return '{}(at={}, media={}, delay={}, loop={})'.format(type(self).__name__, self._at, self._media, self._delay, self._loop) + return '{}(at={}, media={}, delay={}, loop={}, setmark={})'.format(type(self).__name__, self._at, self._media, self._delay, self._loop, self._setmark) + + def prepare(self): + if self._setmark is not None: + self._at._timings.register_mark(self._setmark, None) def start(self): print("Replacing playback") - self._eventrunner.notify('replaceplayback', media=self._media, delay=self._delay, loop=self._loop) + self._eventrunner.notify('replaceplayback', media=self._media, delay=self._delay, loop=self._loop, setmark=self._setmark) self._eventrunner.finished(self) class SetTempo(Event):