1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
local al = require 'abletonlink'
local termio = require 'posix.termio'
local poll = require 'posix.poll'
function print_help()
print([[
< L I N K H U T >
usage:
enable / disable Link: a
start / stop: space
decrease / increase tempo: w / e
decrease / increase quantum: r / t
enable / disable start stop sync: s
quit: q]])
end
function set_buffered_input(enable)
local t = termio.tcgetattr(0)
if enable then
t.lflag = t.lflag | termio.ICANON
else
t.lflag = t.lflag & (~termio.ICANON)
end
termio.tcsetattr(0, termio.TCSANOW, t)
end
function wait_for_input()
return poll.rpoll(0, 50) > 0
end
function clear_line()
io.stdout:write(' \r')
io.stdout:flush()
end
function print_state_header()
print("\nenabled | num peers | quantum | start stop sync | tempo | beats | metro")
end
function print_state()
link:capture_app_session_state(session_state)
local time = link:clock_micros()
local enabled = link:is_enabled() and "yes" or "no"
local num_peers = link:num_peers()
local start_stop = link:is_start_stop_sync_enabled() and "yes" or " no"
local tempo = session_state:tempo()
local playing = session_state:is_playing() and "[playing]" or "[stopped]"
local beats = session_state:beat_at_time(time, quantum)
local phase = session_state:phase_at_time(time, quantum)
local bts = ''
for i = 0, math.ceil(quantum)-1 do
bts = bts .. (i < phase and 'X' or 'O')
end
io.stdout:write(string.format(
"%7s | %9d | %7.f | %3s %11s | %7.2f | %7.2f | %s",
enabled, num_peers, quantum, start_stop, playing, tempo, beats, bts
))
end
function input()
char = io.read(1)
local time = link:clock_micros()
local enabled = link:is_enabled()
local start_stop = link:is_start_stop_sync_enabled()
local tempo = session_state:tempo()
link:capture_app_session_state(session_state)
if char == 'q' then
running = false
clear_line()
elseif char == 'a' then
link:enable(not enabled)
elseif char == 'w' then
session_state:set_tempo(tempo - 1, time)
elseif char == 'e' then
session_state:set_tempo(tempo + 1, time)
elseif char == 'r' then
quantum = quantum - 1
elseif char == 't' then
quantum = quantum + 1
elseif char == 's' then
link:enable_start_stop_sync(not start_stop)
elseif char == ' ' then
if session_state:is_playing() then
session_state:set_is_playing(false, time)
else
session_state:set_is_playing_and_request_beat_at_time(true, time, 0, quantum)
end
end
link:commit_app_session_state(session_state)
end
link = al.create(120)
session_state = al.create_session_state()
running = true
quantum = 4
link:set_num_peers_callback(function (np)
print("\nevent:", "num peers", np)
end)
link:set_tempo_callback(function (t)
print("\nevent:", "tempo", t)
end)
link:set_start_stop_callback(function (p)
print("\nevent:", "start_stop", p)
end)
print_help()
print_state_header()
set_buffered_input(false)
while running do
clear_line()
if wait_for_input() then
input()
else
print_state()
end
link:pump_events()
end
set_buffered_input(true)
|