@@ -106,91 +106,110 @@ init(Parent, CueServer, MIDIServer, LinkServer) ->
106
106
107
107
loop (State ) ->
108
108
receive
109
+ {timeout , Timer , {call , Server , Msg , Tracker }} ->
110
+ Server ! Msg ,
111
+ tau_server_tracker :forget (Timer , Tracker ),
112
+ ? MODULE :loop (State );
113
+
109
114
{udp , APISocket , Ip , Port , Bin } ->
110
115
debug (3 , " api server got UDP on ~p :~p~n " , [Ip , Port ]),
111
- try osc :decode (Bin ) of
112
- {bundle , Time , X } ->
113
- debug (" got bundle for time ~f~n " , [Time ]),
114
- NewState = do_bundle (Time , X , State ),
115
- ? MODULE :loop (NewState );
116
+ case osc :decode (Bin ) of
116
117
{cmd , [" /ping" ]} ->
117
118
debug (" sending! /pong to ~p ~p ~n " , [Ip , Port ]),
118
119
PongBin = osc :encode ([" /pong" ]),
119
120
ok = gen_udp :send (APISocket , Ip , Port , PongBin ),
120
121
? MODULE :loop (State );
121
- {cmd , [" /midi" , OSC ]= Cmd } ->
122
- debug_cmd (Cmd ),
123
- MIDIServer = maps :get (midi_server , State ),
124
- MIDIServer ! {send , OSC },
125
- ? MODULE :loop (State );
126
- {cmd , [" /midi-flush" ]= Cmd } ->
127
- debug_cmd (Cmd ),
128
- MIDIServer = maps :get (midi_server , State ),
129
- MIDIServer ! {flush },
130
- ? MODULE :loop (State );
131
- {cmd , [" /flush" , Tag ]= Cmd } ->
132
- debug_cmd (Cmd ),
133
- {Tracker , NewState } = tracker_pid (Tag , State ),
134
- tau_server_tracker :flush (all , Tracker ),
135
- ? MODULE :loop (NewState );
136
- {cmd , [" /internal-cue-port" , Flag ]= Cmd } ->
137
- debug_cmd (Cmd ),
138
- send_to_cue ({internal , Flag =:= 1 }, State ),
139
- ? MODULE :loop (State );
140
- {cmd , [" /stop-start-cue-server" , Flag ]= Cmd } ->
141
- debug_cmd (Cmd ),
142
- send_to_cue ({enabled , Flag =:= 1 }, State ),
143
- ? MODULE :loop (State );
144
- {cmd , [" /stop-start-midi-cues" , Flag ]= Cmd } ->
145
- debug_cmd (Cmd ),
146
- send_to_cue ({midi_enabled , Flag =:= 1 }, State ),
147
- ? MODULE :loop (State );
148
- {cmd , [" /api-rpc" , UUID , " /link-get-current-time" ]= Cmd } ->
149
- debug_cmd (Cmd ),
150
- send_to_link ({link_rpc , UUID , get_current_time }, State ),
151
- ? MODULE :loop (State );
152
-
153
- {cmd , [" /api-rpc" , UUID , " /link-get-beat-at-time" , Time , Quantum ]= Cmd } ->
154
- debug_cmd (Cmd ),
155
- send_to_link ({link_rpc , UUID , get_beat_at_time , Time , Quantum }, State ),
156
- ? MODULE :loop (State );
157
-
158
- {cmd , [" /api-rpc" , UUID , " /link-get-time-at-beat" , Beat , Quantum ]= Cmd } ->
159
- debug_cmd (Cmd ),
160
- send_to_link ({link_rpc , UUID , get_time_at_beat , Beat , Quantum }, State ),
161
- ? MODULE :loop (State );
162
-
163
- {cmd , [" /api-rpc" , UUID , " /link-get-tempo" ]= Cmd } ->
164
- debug_cmd (Cmd ),
165
- send_to_link ({link_rpc , UUID , get_tempo }, State ),
166
- ? MODULE :loop (State );
167
-
168
- {cmd , [" /api-rpc" , UUID , " /link-get-num-peers" ]= Cmd } ->
169
- debug_cmd (Cmd ),
170
- send_to_link ({link_rpc , UUID , get_num_peers }, State ),
171
- ? MODULE :loop (State );
172
-
173
-
174
- {cmd , [" /link-disable" ]= Cmd } ->
175
- debug_cmd (Cmd ),
176
- send_to_link ({link_disable }, State ),
177
- ? MODULE :loop (State );
178
-
179
- {cmd , [" /link-enable" ]= Cmd } ->
180
- debug_cmd (Cmd ),
181
- send_to_link ({link_enable }, State ),
182
- ? MODULE :loop (State );
183
-
122
+ Any -> self () ! Any
123
+ end ,
124
+ ? MODULE :loop (State );
125
+
126
+ {bundle , Time , X } ->
127
+ debug (" got bundle for time ~f~n " , [Time ]),
128
+ NewState = do_bundle (Time , X , State ),
129
+ ? MODULE :loop (NewState );
130
+
131
+ {cmd , [" /midi" , OSC ]= Cmd } ->
132
+ debug_cmd (Cmd ),
133
+ MIDIServer = maps :get (midi_server , State ),
134
+ MIDIServer ! {send , OSC },
135
+ ? MODULE :loop (State );
136
+
137
+ {cmd , [" /midi-flush" ]= Cmd } ->
138
+ debug_cmd (Cmd ),
139
+ MIDIServer = maps :get (midi_server , State ),
140
+ MIDIServer ! {flush },
141
+ ? MODULE :loop (State );
142
+
143
+ {cmd , [" /flush" , Tag ]= Cmd } ->
144
+ debug_cmd (Cmd ),
145
+ {Tracker , NewState } = tracker_pid (Tag , State ),
146
+ tau_server_tracker :flush (all , Tracker ),
147
+ ? MODULE :loop (NewState );
148
+
149
+ {cmd , [" /internal-cue-port" , Flag ]= Cmd } ->
150
+ debug_cmd (Cmd ),
151
+ send_to_cue ({internal , Flag =:= 1 }, State ),
152
+ ? MODULE :loop (State );
153
+
154
+ {cmd , [" /stop-start-cue-server" , Flag ]= Cmd } ->
155
+ debug_cmd (Cmd ),
156
+ send_to_cue ({enabled , Flag =:= 1 }, State ),
157
+ ? MODULE :loop (State );
158
+
159
+ {cmd , [" /stop-start-midi-cues" , Flag ]= Cmd } ->
160
+ debug_cmd (Cmd ),
161
+ send_to_cue ({midi_enabled , Flag =:= 1 }, State ),
162
+ ? MODULE :loop (State );
163
+
164
+ {cmd , [" /api-rpc" , UUID , " /link-get-current-time" ]= Cmd } ->
165
+ debug_cmd (Cmd ),
166
+ send_to_link ({link_rpc , UUID , get_current_time }, State ),
167
+ ? MODULE :loop (State );
168
+
169
+ {cmd , [" /api-rpc" , UUID , " /link-get-beat-at-time" , Time , Quantum ]= Cmd } ->
170
+ debug_cmd (Cmd ),
171
+ send_to_link ({link_rpc , UUID , get_beat_at_time , Time , Quantum }, State ),
172
+ ? MODULE :loop (State );
173
+
174
+ {cmd , [" /api-rpc" , UUID , " /link-get-time-at-beat" , Beat , Quantum ]= Cmd } ->
175
+ debug_cmd (Cmd ),
176
+ send_to_link ({link_rpc , UUID , get_time_at_beat , Beat , Quantum }, State ),
177
+ ? MODULE :loop (State );
178
+
179
+ {cmd , [" /api-rpc" , UUID , " /link-get-tempo" ]= Cmd } ->
180
+ debug_cmd (Cmd ),
181
+ send_to_link ({link_rpc , UUID , get_tempo }, State ),
182
+ ? MODULE :loop (State );
183
+
184
+ {cmd , [" /api-rpc" , UUID , " /link-get-num-peers" ]= Cmd } ->
185
+ debug_cmd (Cmd ),
186
+ send_to_link ({link_rpc , UUID , get_num_peers }, State ),
187
+ ? MODULE :loop (State );
188
+
189
+ {cmd , [" /api-rpc" , UUID , " /link-is-enabled" ]= Cmd } ->
190
+ debug_cmd (Cmd ),
191
+ send_to_link ({link_rpc , UUID , is_enabled }, State ),
192
+ ? MODULE :loop (State );
193
+
194
+ {cmd , [" /link-reset" ]= Cmd } ->
195
+ debug_cmd (Cmd ),
196
+ send_to_link ({link_reset }, State ),
197
+ ? MODULE :loop (State );
198
+
199
+ {cmd , [" /link-disable" ]= Cmd } ->
200
+ debug_cmd (Cmd ),
201
+ send_to_link ({link_disable }, State ),
202
+ ? MODULE :loop (State );
203
+
204
+ {cmd , [" /link-enable" ]= Cmd } ->
205
+ debug_cmd (Cmd ),
206
+ send_to_link ({link_enable }, State ),
207
+ ? MODULE :loop (State );
208
+
209
+ {cmd , Cmd } ->
210
+ log (" Unknown OSC command:: ~p~n " , [Cmd ]),
211
+ ? MODULE :loop (State );
184
212
185
- {cmd , Cmd } ->
186
- log (" Unknown command:: ~p~n " , [Cmd ]),
187
- ? MODULE :loop (State )
188
- catch
189
- Class :Term :Trace ->
190
- log (" Error decoding OSC: ~p~n~p :~p~n~p~n " ,
191
- [Bin , Class , Term , Trace ]),
192
- ? MODULE :loop (State )
193
- end ;
194
213
{system , From , Request } ->
195
214
% % handling system messages (like a gen_server does)
196
215
sys :handle_system_msg (Request , From ,
@@ -218,14 +237,18 @@ debug_cmd([Cmd|Args]) ->
218
237
do_bundle (Time , [{_ ,Bin }|T ], State ) ->
219
238
NewState =
220
239
try osc :decode (Bin ) of
221
- {cmd , [" /send-after" , Host , Port , OSC ]} ->
222
- schedule_cmd (" default" , Time , Host , Port , OSC , State );
240
+ {cmd , [" /send-after" , Host , Port , OSC ]} ->
241
+ schedule_cmd (Time , " default" , State , { send_osc , Host , Port , OSC } );
223
242
{cmd , [" /send-after-tagged" , Tag , Host , Port , OSC ]} ->
224
- schedule_cmd (Tag , Time , Host , Port , OSC , State );
225
- {cmd , [" /midi-at" , Cmd ]} ->
226
- schedule_midi (" default" , Time , Cmd , State );
227
- {cmd , [" /midi-at-tagged" , Tag , Cmd ]} ->
228
- schedule_midi (Tag , Time , Cmd , State );
243
+ schedule_cmd (Time , Tag , State , {send_osc , Host , Port , OSC });
244
+ {cmd , [" /midi-at" , MIDI ]} ->
245
+ schedule_midi (Time , " default" , State , {send_midi , MIDI });
246
+ {cmd , [" /midi-at-tagged" , Tag , MIDI ]} ->
247
+ schedule_midi (Time , Tag , State , {send_midi , MIDI });
248
+ {cmd , [" /link-set-tempo" , Tempo ]} ->
249
+ schedule_link (Time , " default" , State , {link_set_tempo , Tempo });
250
+ {cmd , [" /link-set-tempo-tagged" , Tag , Tempo ]} ->
251
+ schedule_link (Time , Tag , State , {link_set_tempo , Tempo });
229
252
Other ->
230
253
log (" Unexpected bundle content:~p~n " , [Other ]),
231
254
State
@@ -239,46 +262,37 @@ do_bundle(Time, [{_,Bin}|T], State) ->
239
262
do_bundle (_Time , [], State ) ->
240
263
State .
241
264
242
- schedule_midi (Tag , Time , Data , State ) ->
243
- {Tracker , NewState } = tracker_pid (Tag , State ),
265
+ schedule_internal_call (Time , Tag , State , Server , Msg ) ->
244
266
Delay = Time - osc :now (),
245
267
MsDelay = trunc (Delay * 1000 + 0.5 ), % % nearest
246
- MIDIServer = maps : get ( midi_server , State ),
268
+ { Tracker , NewState } = tracker_pid ( Tag , State ),
247
269
if MsDelay > ? NODELAY_LIMIT ->
248
- Msg = { send , Time , Data , Tracker },
270
+
249
271
% % Note: lookup of the registered server name will happen
250
272
% % when the timer triggers, and if no such process exists
251
273
% % at that time, the message will be quietly dropped
252
- Timer = erlang :start_timer (MsDelay , MIDIServer , Msg ),
274
+ SchedMsg = {call , Server , Msg , Tracker },
275
+ Timer = erlang :start_timer (MsDelay , self (), SchedMsg ),
253
276
debug (2 , " start (MIDI) timer of ~w ms for time ~f~n " , [MsDelay , Time ]),
254
277
tau_server_tracker :track (Timer , Time , Tracker );
255
278
true ->
256
- MIDIServer ! { send , Time , Data } ,
257
- debug (2 , " directly forward (MIDI) message for delay ~f~ n" , [Delay ])
279
+ Server ! Msg ,
280
+ debug (2 , " Directly sent scheduled call ~ n" , [])
258
281
end ,
259
282
NewState .
260
283
261
284
262
- % % Schedules a command for forwarding (or forwards immediately)
263
- schedule_cmd (Tag , Time , Host , Port , OSC , State ) ->
264
- {Tracker , NewState } = tracker_pid (Tag , State ),
265
- Data = {Host , Port , OSC },
266
- Delay = Time - osc :now (),
267
- MsDelay = trunc (Delay * 1000 + 0.5 ), % % nearest
268
- if MsDelay > ? NODELAY_LIMIT ->
269
- Msg = {forward , Time , Data , Tracker },
270
- % % Note: lookup of the registered server name will happen
271
- % % when the timer triggers, and if no such process exists
272
- % % at that time, the message will be quietly dropped
273
- CueServer = maps :get (cue_server , State ),
274
- Timer = erlang :start_timer (MsDelay , CueServer , Msg ),
275
- debug (2 , " start timer of ~w ms for time ~f~n " , [MsDelay , Time ]),
276
- tau_server_tracker :track (Timer , Time , Tracker );
277
- true ->
278
- send_to_cue ({forward , Time , Data }, NewState ),
279
- debug (2 , " directly forward message for delay ~f~n " , [Delay ])
280
- end ,
281
- NewState .
285
+ schedule_link (Time , Tag , State , Msg ) ->
286
+ LinkServer = maps :get (link_server , State ),
287
+ schedule_internal_call (Time , Tag , State , LinkServer , Msg ).
288
+
289
+ schedule_midi (Time , Tag , State , Msg ) ->
290
+ MIDIServer = maps :get (midi_server , State ),
291
+ schedule_internal_call (Time , Tag , State , MIDIServer , Msg ).
292
+
293
+ schedule_cmd (Time , Tag , State , Msg ) ->
294
+ CueServer = maps :get (cue_server , State ),
295
+ schedule_internal_call (Time , Tag , State , CueServer , Msg ).
282
296
283
297
% % Get the pid for the tag group tracker, creating it if needed
284
298
tracker_pid (Tag , State ) ->
0 commit comments