Skip to content

Commit ca3469b

Browse files
committed
AbletonLinkClock: Start/stop sync support
1 parent 99c33d6 commit ca3469b

1 file changed

Lines changed: 33 additions & 30 deletions

File tree

isobar/timelines/clock_link.py

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ def __init__(self,
2929
def start_stop_callback(is_starting):
3030
logger.debug("Link: Start/Stop callback: is_starting=%s" % is_starting)
3131
if is_starting:
32-
self.running = True
33-
32+
self.clock_target.start()
3433
else:
35-
self.running = False
34+
self.clock_target.stop()
35+
self.clock_target.reset()
3636

3737
if start_stop_sync_enabled:
3838
self.link_client.setStartStopCallback(start_stop_callback)
3939
self.running = self.link_client.captureSessionState().isPlaying()
40-
print("Start/Stop sync enabled, running: %s" % self.running)
40+
logger.debug("Start/Stop sync enabled, is_running: %s" % self.running)
4141
else:
42-
print("Start/Stop sync disabled, running")
42+
logger.debug("Start/Stop sync disabled, running")
4343
self.running = True
4444

4545
def tempo_changed_callback(tempo):
@@ -50,37 +50,40 @@ def tempo_changed_callback(tempo):
5050
def run(self):
5151
ticks_previous = None
5252
got_sync = False
53+
self.running = True
5354

54-
while True:
55-
if self.running:
56-
link_state = self.link_client.captureSessionState()
57-
link_time = self.link_client.clock().micros()
58-
beats = link_state.beatAtTime(link_time, 4)
55+
while self.running:
56+
link_state = self.link_client.captureSessionState()
57+
link_time = self.link_client.clock().micros()
58+
beats = link_state.beatAtTime(link_time, 4)
5959

60-
ticks_current = int(beats * self.ticks_per_beat)
61-
if not got_sync:
60+
ticks_current = int(beats * self.ticks_per_beat)
61+
if not got_sync:
62+
#--------------------------------------------------------------------------------
63+
# Start clock at next 4-beat boundary (next bar, assuming 4/4)
64+
#--------------------------------------------------------------------------------
65+
if ticks_current % (self.ticks_per_beat * 4) == 0:
66+
got_sync = True
67+
if ticks_previous is None or ticks_current > ticks_previous:
68+
if ticks_previous is None:
69+
delta_ticks = 1
70+
else:
6271
#--------------------------------------------------------------------------------
63-
# Start clock at next 4-beat boundary (next bar, assuming 4/4)
72+
# Under system load, multiple ticks may have passed since our last timestamp was
73+
# received. In this case, send multiple ticks to the timeline to compensate.
6474
#--------------------------------------------------------------------------------
65-
if ticks_current % (self.ticks_per_beat * 4) == 0:
66-
got_sync = True
67-
if ticks_previous is None or ticks_current > ticks_previous:
68-
if ticks_previous is None:
69-
delta_ticks = 1
70-
else:
71-
#--------------------------------------------------------------------------------
72-
# Under system load, multiple ticks may have passed since our last timestamp was
73-
# received. In this case, send multiple ticks to the timeline to compensate.
74-
#--------------------------------------------------------------------------------
75-
delta_ticks = ticks_current - ticks_previous
76-
ticks_previous = ticks_current
77-
78-
if not got_sync:
79-
continue
80-
for n in range(delta_ticks):
81-
self.clock_target.tick()
75+
delta_ticks = ticks_current - ticks_previous
76+
ticks_previous = ticks_current
77+
78+
if not got_sync:
79+
continue
80+
for n in range(delta_ticks):
81+
self.clock_target.tick()
8282
time.sleep(0.0001)
8383

84+
def stop(self):
85+
self.running = False
86+
8487
def get_tempo(self):
8588
link_state = self.link_client.captureSessionState()
8689
return link_state.tempo()

0 commit comments

Comments
 (0)