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)