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
|
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) 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
print_help()
print_state_header()
set_buffered_input(false)
while running do
clear_line()
if wait_for_input() then
input()
else
print_state()
end
end
set_buffered_input(true)
|