aboutsummaryrefslogtreecommitdiffstats
path: root/examples/linkhut.lua
blob: de3ba9e3cb31e879088fa04a58ec76fa428bdc19 (plain)
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)