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