Jack2: JackNetAPI.cpp Source File

Jack2 1.9.12

JackNetAPI.cpp
1 /*
2 Copyright (C) 2009-2013 Grame
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 */
19
20 #include <assert.h>
21 #include <stdarg.h>
22
23 #include "JackNetInterface.h"
24 #include "JackAudioAdapterInterface.h"
25
26 #ifdef __cplusplus
27 extern "C"
28 {
29 #endif
30
31 // NetJack common API
32
33 #define MASTER_NAME_SIZE 256
34
35 enum JackNetEncoder {
36
37 JackFloatEncoder = 0,
38 JackIntEncoder = 1,
39 JackCeltEncoder = 2,
40 JackOpusEncoder = 3
41 };
42
43 typedef struct {
44
45 int audio_input;
46 int audio_output;
47 int midi_input;
48 int midi_output;
49 int mtu;
50 int time_out; // in millisecond, -1 means in infinite
51 int encoder; // one of JackNetEncoder
52 int kbps; // KB per second for CELT encoder
53 int latency; // network cycles
54
55 } jack_slave_t;
56
57 typedef struct {
58
59 int audio_input;
60 int audio_output;
61 int midi_input;
62 int midi_output;
63 jack_nframes_t buffer_size;
64 jack_nframes_t sample_rate;
65 char master_name[MASTER_NAME_SIZE];
66 int time_out;
67 int partial_cycle;
68
69 } jack_master_t;
70
71 // NetJack slave API
72
73 typedef struct _jack_net_slave jack_net_slave_t;
74
75 typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size,
76 int audio_input,
77 float** audio_input_buffer,
78 int midi_input,
79 void** midi_input_buffer,
80 int audio_output,
81 float** audio_output_buffer,
82 int midi_output,
83 void** midi_output_buffer,
84 void* data);
85
86 typedef int (*JackNetSlaveBufferSizeCallback) (jack_nframes_t nframes, void *arg);
87 typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg);
88 typedef void (*JackNetSlaveShutdownCallback) (void* arg);
89 typedef int (*JackNetSlaveRestartCallback) (void* arg);
90 typedef void (*JackNetSlaveErrorCallback) (int error_code, void* arg);
91
92 LIB_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result);
93 LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net);
94
95 LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net);
96 LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net);
97 LIB_EXPORT int jack_net_slave_is_active(jack_net_slave_t* net);
98
99 LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg);
100 LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t* net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg);
101 LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t* net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg);
102 LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t* net, JackNetSlaveShutdownCallback shutdown_callback, void *arg);
103 LIB_EXPORT int jack_set_net_slave_restart_callback(jack_net_slave_t* net, JackNetSlaveRestartCallback restart_callback, void *arg);
104 LIB_EXPORT int jack_set_net_slave_error_callback(jack_net_slave_t* net, JackNetSlaveErrorCallback error_callback, void *arg);
105
106 // NetJack master API
107
108 typedef struct _jack_net_master jack_net_master_t;
109
110 LIB_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, jack_master_t* request, jack_slave_t* result);
111 LIB_EXPORT int jack_net_master_close(jack_net_master_t* net);
112
113 LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer);
114 LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer);
115
116 LIB_EXPORT int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames);
117 LIB_EXPORT int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames);
118
119 // NetJack adapter API
120
121 typedef struct _jack_adapter jack_adapter_t;
122
123 LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
124 jack_nframes_t host_buffer_size,
125 jack_nframes_t host_sample_rate,
126 jack_nframes_t adapted_buffer_size,
127 jack_nframes_t adapted_sample_rate);
128 LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter);
129 LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter);
130
131 LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
132 LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
133
134 #define LOG_LEVEL_INFO 1
135 #define LOG_LEVEL_ERROR 2
136
137 LIB_EXPORT void jack_error(const char *fmt, ...);
138 LIB_EXPORT void jack_info(const char *fmt, ...);
139 LIB_EXPORT void jack_log(const char *fmt, ...);
140
141 #ifdef __cplusplus
142 }
143 #endif
144
145 namespace Jack
146 {
147
148 struct JackNetExtMaster : public JackNetMasterInterface {
149
150 jack_master_t fRequest;
151
152 JackRingBuffer** fRingBuffer;
153
154 JackNetExtMaster(const char* ip,
155 int port,
156 jack_master_t* request)
157 {
158 fRunning = true;
159 assert(strlen(ip) < 32);
160 strcpy(fMulticastIP, ip);
161 fSocket.SetPort(port);
162 fRequest.buffer_size = request->buffer_size;
163 fRequest.sample_rate = request->sample_rate;
164 fRequest.audio_input = request->audio_input;
165 fRequest.audio_output = request->audio_output;
166 fRequest.time_out = request->time_out;
167 fRequest.partial_cycle = request->partial_cycle;
168 fRingBuffer = NULL;
169 }
170
171 virtual ~JackNetExtMaster()
172 {
173 if (fRingBuffer) {
174 for (int i = 0; i < fParams.fReturnAudioChannels; i++) {
175 delete fRingBuffer[i];
176 }
177 delete [] fRingBuffer;
178 }
179 }
180
181 int Open(jack_slave_t* result)
182 {
183 // Check buffer_size
184 if (fRequest.buffer_size == 0) {
185 jack_error("Incorrect buffer_size...");
186 return -1;
187 }
188 // Check sample_rate
189 if (fRequest.sample_rate == 0) {
190 jack_error("Incorrect sample_rate...");
191 return -1;
192 }
193
194 // Init socket API (win32)
195 if (SocketAPIInit() < 0) {
196 jack_error("Can't init Socket API, exiting...");
197 return -1;
198 }
199
200 // Request socket
201 if (fSocket.NewSocket() == SOCKET_ERROR) {
202 jack_error("Can't create the network manager input socket : %s", StrError(NET_ERROR_CODE));
203 return -1;
204 }
205
206 // Bind the socket to the local port
207 if (fSocket.Bind() == SOCKET_ERROR) {
208 jack_error("Can't bind the network manager socket : %s", StrError(NET_ERROR_CODE));
209 fSocket.Close();
210 return -1;
211 }
212
213 // Join multicast group
214 if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
215 jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
216 }
217
218 // Local loop
219 if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
220 jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
221 }
222
223 // Set a timeout on the multicast receive (the thread can now be cancelled)
224 if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
225 jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
226 }
227
228 // Main loop, wait for data, deal with it and wait again
229 int attempt = 0;
230 int rx_bytes = 0;
231 int try_count = (fRequest.time_out > 0) ? int((1000000.f * float(fRequest.time_out)) / float(MANAGER_INIT_TIMEOUT)) : INT_MAX;
232
233 do
234 {
235 session_params_t net_params;
236 rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
237 SessionParamsNToH(&net_params, &fParams);
238
239 if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
240 jack_error("Error in receive : %s", StrError(NET_ERROR_CODE));
241 if (++attempt == 10) {
242 jack_error("Can't receive on the socket, exiting net manager" );
243 goto error;
244 }
245 }
246
247 if (rx_bytes == sizeof(session_params_t)) {
248 switch (GetPacketType(&fParams)) {
249
250 case SLAVE_AVAILABLE:
251 if (InitMaster(result) == 0) {
252 SessionParamsDisplay(&fParams);
253 fRunning = false;
254 } else {
255 jack_error("Can't init new net master...");
256 goto error;
257 }
258 jack_info("Waiting for a slave...");
259 break;
260
261 case KILL_MASTER:
262 break;
263
264 default:
265 break;
266 }
267 }
268 }
269 while (fRunning && (--try_count > 0));
270
271 if (try_count == 0) {
272 jack_error("Time out error in connect");
273 return -1;
274 }
275
276 // Set result parameters
277 result->audio_input = fParams.fSendAudioChannels;
278 result->audio_output = fParams.fReturnAudioChannels;
279 result->midi_input = fParams.fSendMidiChannels;
280 result->midi_output = fParams.fReturnMidiChannels;
281 result->mtu = fParams.fMtu;
282 result->latency = fParams.fNetworkLatency;
283
284 // Use ringbuffer in case of partial cycle and latency > 0
285 if (fRequest.partial_cycle && result->latency > 0) {
286 fRingBuffer = new JackRingBuffer*[fParams.fReturnAudioChannels];
287 for (int i = 0; i < fParams.fReturnAudioChannels; i++) {
288 fRingBuffer[i] = new JackRingBuffer(fRequest.buffer_size * result->latency * 2);
289 }
290 }
291 return 0;
292
293 error:
294 fSocket.Close();
295 return -1;
296 }
297
298 int InitMaster(jack_slave_t* result)
299 {
300 // Check MASTER <==> SLAVE network protocol coherency
301 if (fParams.fProtocolVersion != NETWORK_PROTOCOL) {
302 jack_error("Error : slave '%s' is running with a different protocol %d != %d", fParams.fName, fParams.fProtocolVersion, NETWORK_PROTOCOL);
303 return -1;
304 }
305
306 // Settings
307 fSocket.GetName(fParams.fMasterNetName);
308 fParams.fID = 1;
309 fParams.fPeriodSize = fRequest.buffer_size;
310 fParams.fSampleRate = fRequest.sample_rate;
311
312 if (fRequest.audio_input == -1) {
313 if (fParams.fSendAudioChannels == -1) {
314 jack_error("Error : master and slave use -1 for wanted inputs...");
315 return -1;
316 } else {
317 result->audio_input = fParams.fSendAudioChannels;
318 jack_info("Takes slave %d inputs", fParams.fSendAudioChannels);
319 }
320 } else if (fParams.fSendAudioChannels == -1) {
321 fParams.fSendAudioChannels = fRequest.audio_input;
322 jack_info("Takes master %d inputs", fRequest.audio_input);
323 } else if (fParams.fSendAudioChannels != fRequest.audio_input) {
324 jack_error("Error : master wants %d inputs and slave wants %d inputs...", fRequest.audio_input, fParams.fSendAudioChannels);
325 return -1;
326 }
327
328 if (fRequest.audio_output == -1) {
329 if (fParams.fReturnAudioChannels == -1) {
330 jack_error("Error : master and slave use -1 for wanted outputs...");
331 return -1;
332 } else {
333 result->audio_output = fParams.fReturnAudioChannels;
334 jack_info("Takes slave %d outputs", fParams.fReturnAudioChannels);
335 }
336 } else if (fParams.fReturnAudioChannels == -1) {
337 fParams.fReturnAudioChannels = fRequest.audio_output;
338 jack_info("Takes master %d outputs", fRequest.audio_output);
339 } else if (fParams.fReturnAudioChannels != fRequest.audio_output) {
340 jack_error("Error : master wants %d outputs and slave wants %d outputs...", fRequest.audio_output, fParams.fReturnAudioChannels);
341 return -1;
342 }
343
344 // Close request socket
345 fSocket.Close();
346
348 if (!JackNetMasterInterface::Init()) {
349 return -1;
350 }
351
352 // Set global parameters
353 if (!SetParams()) {
354 return -1;
355 }
356
357 return 0;
358 }
359
360 int Close()
361 {
362 fSocket.Close();
363 return 0;
364 }
365
366 void UseRingBuffer(int audio_input, float** audio_input_buffer, int write, int read)
367 {
368 // Possibly use ringbuffer...
369 if (fRingBuffer) {
370 for (int i = 0; i < audio_input; i++) {
371 fRingBuffer[i]->Write(audio_input_buffer[i], write);
372 fRingBuffer[i]->Read(audio_input_buffer[i], read);
373 }
374 }
375 }
376
377 int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames)
378 {
379 try {
380
381 // frames = -1 means : entire buffer
382 if (frames < 0) frames = fParams.fPeriodSize;
383
384 int read_frames = 0;
385 assert(audio_input == fParams.fReturnAudioChannels);
386
387 for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) {
388 assert(audio_input_buffer[audio_port_index]);
389 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, audio_input_buffer[audio_port_index]);
390 }
391
392 for (int midi_port_index = 0; midi_port_index < midi_input; midi_port_index++) {
393 assert(((JackMidiBuffer**)midi_input_buffer)[midi_port_index]);
394 fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]);
395 }
396
397 int res1 = SyncRecv();
398 switch (res1) {
399
400 case NET_SYNCHING:
401 // Data will not be received, so cleanup buffers...
402 for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) {
403 memset(audio_input_buffer[audio_port_index], 0, sizeof(float) * fParams.fPeriodSize);
404 }
405 UseRingBuffer(audio_input, audio_input_buffer, fParams.fPeriodSize, frames);
406 return res1;
407
408 case SOCKET_ERROR:
409 return res1;
410
411 case SYNC_PACKET_ERROR:
412 // since sync packet is incorrect, don't decode it and continue with data
413 break;
414
415 default:
416 // decode sync
417 DecodeSyncPacket(read_frames);
418 break;
419 }
420
421 int res2 = DataRecv();
422 UseRingBuffer(audio_input, audio_input_buffer, read_frames, frames);
423 return res2;
424
425 } catch (JackNetException& e) {
426 jack_error(e.what());
427 return -1;
428 }
429 }
430
431 int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames)
432 {
433 try {
434
435 // frames = -1 means : entire buffer
436 if (frames < 0) frames = fParams.fPeriodSize;
437
438 assert(audio_output == fParams.fSendAudioChannels);
439
440 for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) {
441 assert(audio_output_buffer[audio_port_index]);
442 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]);
443 }
444
445 for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) {
446 assert(((JackMidiBuffer**)midi_output_buffer)[midi_port_index]);
447 fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]);
448 }
449
450 EncodeSyncPacket(frames);
451
452 // send sync
453 if (SyncSend() == SOCKET_ERROR) {
454 return SOCKET_ERROR;
455 }
456
457 // send data
458 if (DataSend() == SOCKET_ERROR) {
459 return SOCKET_ERROR;
460 }
461 return 0;
462
463 } catch (JackNetException& e) {
464 jack_error(e.what());
465 return -1;
466 }
467 }
468
469 // Transport
470 void EncodeTransportData()
471 {}
472
473 void DecodeTransportData()
474 {}
475
476 };
477
478 struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterface {
479
480 // Data buffers
481 float** fAudioCaptureBuffer;
482 float** fAudioPlaybackBuffer;
483
484 JackMidiBuffer** fMidiCaptureBuffer;
485 JackMidiBuffer** fMidiPlaybackBuffer;
486
487 JackThread fThread;
488
489 JackNetSlaveProcessCallback fProcessCallback;
490 void* fProcessArg;
491
492 JackNetSlaveShutdownCallback fShutdownCallback;
493 void* fShutdownArg;
494
495 JackNetSlaveRestartCallback fRestartCallback;
496 void* fRestartArg;
497
498 JackNetSlaveErrorCallback fErrorCallback;
499 void* fErrorArg;
500
501 JackNetSlaveBufferSizeCallback fBufferSizeCallback;
502 void* fBufferSizeArg;
503
504 JackNetSlaveSampleRateCallback fSampleRateCallback;
505 void* fSampleRateArg;
506
507 int fConnectTimeOut;
508 int fFrames;
509
510 JackNetExtSlave(const char* ip,
511 int port,
512 const char* name,
513 jack_slave_t* request)
514 :fThread(this),
515 fProcessCallback(NULL),fProcessArg(NULL),
516 fShutdownCallback(NULL), fShutdownArg(NULL),
517 fRestartCallback(NULL), fRestartArg(NULL),
518 fErrorCallback(NULL), fErrorArg(NULL),
519 fBufferSizeCallback(NULL), fBufferSizeArg(NULL),
520 fSampleRateCallback(NULL), fSampleRateArg(NULL)
521 {
522 char host_name[JACK_CLIENT_NAME_SIZE + 1];
523
524 // Request parameters
525 assert(strlen(ip) < 32);
526 strcpy(fMulticastIP, ip);
527 fParams.fMtu = request->mtu;
528 fParams.fTransportSync = 0;
529 fParams.fSendAudioChannels = request->audio_input;
530 fParams.fReturnAudioChannels = request->audio_output;
531 fParams.fSendMidiChannels = request->midi_input;
532 fParams.fReturnMidiChannels = request->midi_output;
533 fParams.fNetworkLatency = request->latency;
534 fParams.fSampleEncoder = request->encoder;
535 fParams.fKBps = request->kbps;
536 fParams.fSlaveSyncMode = 1;
537 fConnectTimeOut = request->time_out;
538
539 // Create name with hostname and client name
540 GetHostName(host_name, JACK_CLIENT_NAME_SIZE);
541 snprintf(fParams.fName, JACK_CLIENT_NAME_SIZE, "%s_%s", host_name, name);
542 fSocket.GetName(fParams.fSlaveNetName);
543
544 // Set the socket parameters
545 fSocket.SetPort(port);
546 fSocket.SetAddress(fMulticastIP, port);
547
548 fAudioCaptureBuffer = NULL;
549 fAudioPlaybackBuffer = NULL;
550 fMidiCaptureBuffer = NULL;
551 fMidiPlaybackBuffer = NULL;
552 }
553
554 virtual ~JackNetExtSlave()
555 {}
556
557 void AllocPorts()
558 {
559 // Set buffers
560 if (fParams.fSendAudioChannels > 0) {
561 fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels];
562 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
563 fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize];
564 memset(fAudioCaptureBuffer[audio_port_index], 0, sizeof(float) * fParams.fPeriodSize);
565 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]);
566 }
567 }
568
569 if (fParams.fSendMidiChannels > 0) {
570 fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels];
571 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
572 fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
573 memset(fMidiCaptureBuffer[midi_port_index], 0, sizeof(float) * fParams.fPeriodSize);
574 fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]);
575 }
576 }
577
578 if (fParams.fReturnAudioChannels > 0) {
579 fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels];
580 for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
581 fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize];
582 memset(fAudioPlaybackBuffer[audio_port_index], 0, sizeof(float) * fParams.fPeriodSize);
583 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]);
584 }
585 }
586
587 if (fParams.fReturnMidiChannels > 0) {
588 fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels];
589 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
590 fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
591 memset(fMidiPlaybackBuffer[midi_port_index], 0, sizeof(float) * fParams.fPeriodSize);
592 fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]);
593 }
594 }
595 }
596
597 void FreePorts()
598 {
599 if (fAudioCaptureBuffer) {
600 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
601 delete[] fAudioCaptureBuffer[audio_port_index];
602 }
603 delete[] fAudioCaptureBuffer;
604 fAudioCaptureBuffer = NULL;
605 }
606
607 if (fMidiCaptureBuffer) {
608 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
609 delete[] fMidiCaptureBuffer[midi_port_index];
610 }
611 delete[] fMidiCaptureBuffer;
612 fMidiCaptureBuffer = NULL;
613 }
614
615 if (fAudioPlaybackBuffer) {
616 for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
617 delete[] fAudioPlaybackBuffer[audio_port_index];
618 }
619 delete[] fAudioPlaybackBuffer;
620 fAudioPlaybackBuffer = NULL;
621 }
622
623 if (fMidiPlaybackBuffer) {
624 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
625 delete[] (fMidiPlaybackBuffer[midi_port_index]);
626 }
627 delete[] fMidiPlaybackBuffer;
628 fMidiPlaybackBuffer = NULL;
629 }
630 }
631
632 int Open(jack_master_t* result)
633 {
634 // Check audio/midi parameters
635 if (fParams.fSendAudioChannels == 0
636 && fParams.fReturnAudioChannels == 0
637 && fParams.fSendMidiChannels == 0
638 && fParams.fReturnMidiChannels == 0) {
639 jack_error("Incorrect audio/midi channels number...");
640 return -1;
641 }
642
643 // Check MTU parameters
644 if ((fParams.fMtu < DEFAULT_MTU) && (fParams.fMtu > MAX_MTU)) {
645 jack_error("MTU is not in the expected range [%d ... %d]", DEFAULT_MTU, MAX_MTU);
646 return -1;
647 }
648
649 // Check CELT encoder parameters
650 if ((fParams.fSampleEncoder == JackCeltEncoder) && (fParams.fKBps == 0)) {
651 jack_error("CELT encoder with 0 for kps...");
652 return -1;
653 }
654
655 if ((fParams.fSampleEncoder == JackOpusEncoder) && (fParams.fKBps == 0)) {
656 jack_error("Opus encoder with 0 for kps...");
657 return -1;
658 }
659
660 // Check latency
661 if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
662 jack_error("Network latency is limited to %d", NETWORK_MAX_LATENCY);
663 return -1;
664 }
665
666 // Init network connection
667 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
668 jack_error("Initing network fails...");
669 return -1;
670 }
671
672 // Finish connection...
673 if (!JackNetSlaveInterface::InitRendering()) {
674 jack_error("Starting network fails...");
675 return -1;
676 }
677
678 // Then set global parameters
679 if (!SetParams()) {
680 jack_error("SetParams error...");
681 return -1;
682 }
683
684 // Set result
685 if (result != NULL) {
686 result->buffer_size = fParams.fPeriodSize;
687 result->sample_rate = fParams.fSampleRate;
688 result->audio_input = fParams.fSendAudioChannels;
689 result->audio_output = fParams.fReturnAudioChannels;
690 result->midi_input = fParams.fSendMidiChannels;
691 result->midi_output = fParams.fReturnMidiChannels;
692 strcpy(result->master_name, fParams.fMasterNetName);
693 }
694
695 // By default fFrames is fPeriodSize
696 fFrames = fParams.fPeriodSize;
697
698 SessionParamsDisplay(&fParams);
699
700 AllocPorts();
701 return 0;
702 }
703
704 int Restart()
705 {
706 // Do it until client possibly decides to stop trying to connect...
707 while (true) {
708
709 // If restart cb is set, then call it
710 if (fRestartCallback) {
711 if (fRestartCallback(fRestartArg) != 0) {
712 return -1;
713 }
714 // Otherwise if shutdown cb is set, then call it
715 } else if (fShutdownCallback) {
716 fShutdownCallback(fShutdownArg);
717 }
718
719 // Init network connection
720 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
721 jack_error("Initing network fails after time_out, retry...");
722 } else {
723 break;
724 }
725 }
726
727 // Finish connection
728 if (!JackNetSlaveInterface::InitRendering()) {
729 jack_error("Starting network fails...");
730 return -1;
731 }
732
733 // Then set global parameters
734 if (!SetParams()) {
735 jack_error("SetParams error...");
736 return -1;
737 }
738
739 // We need to notify possibly new buffer size and sample rate (see Execute)
740 if (fBufferSizeCallback) {
741 if (fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg) != 0) {
742 jack_error("New buffer size = %d cannot be used...", fParams.fPeriodSize);
743 return -1;
744 }
745 }
746
747 if (fSampleRateCallback) {
748 if (fSampleRateCallback(fParams.fSampleRate, fSampleRateArg) != 0) {
749 jack_error("New sample rate = %d cannot be used...", fParams.fSampleRate);
750 return -1;
751 }
752 }
753
754 AllocPorts();
755 return 0;
756 }
757
758 int Close()
759 {
760 fSocket.Close();
761 FreePorts();
762 return 0;
763 }
764
765 // Transport
766 void EncodeTransportData()
767 {}
768
769 void DecodeTransportData()
770 {}
771
772 bool Init()
773 {
774 // Will do "something" on OSX only...
775 UInt64 period, constraint;
776 period = constraint = UInt64(1000000000.f * (float(fParams.fPeriodSize) / float(fParams.fSampleRate)));
777 UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize) * 1000;
778 fThread.SetParams(period, computation, constraint);
779
780 return (fThread.AcquireSelfRealTime(80) == 0); // TODO: get a value from the server
781 }
782
783 bool IsRunning()
784 {
785 return (fThread.GetStatus() == JackThread::kRunning);
786 }
787
788 bool Execute()
789 {
790 try {
791 /*
792 Fist cycle use an INT_MAX time out, so that connection
793 is considered established (with PACKET_TIMEOUT later on)
794 when the first cycle has been done.
795 */
796 DummyProcess();
797 // keep running even in case of error
798 while (fThread.GetStatus() == JackThread::kRunning) {
799 if (Process() == SOCKET_ERROR) {
800 return false;
801 }
802 }
803 return false;
804 } catch (JackNetException& e) {
805 // otherwise just restart...
806 e.PrintMessage();
807 jack_info("NetSlave is restarted");
808 fThread.DropRealTime();
809 fThread.SetStatus(JackThread::kIniting);
810 FreePorts();
811 if (Restart() == 0 && Init()) {
812 fThread.SetStatus(JackThread::kRunning);
813 return true;
814 } else {
815 return false;
816 }
817 }
818 }
819
820 int Read()
821 {
822 // receive sync (launch the cycle)
823 switch (SyncRecv()) {
824
825 case SOCKET_ERROR:
826 return SOCKET_ERROR;
827
828 case SYNC_PACKET_ERROR:
829 // since sync packet is incorrect, don't decode it and continue with data
830 if (fErrorCallback) {
831 fErrorCallback(SYNC_PACKET_ERROR, fErrorArg);
832 }
833 break;
834
835 default:
836 // decode sync
837 DecodeSyncPacket(fFrames);
838 break;
839 }
840
841 int res = DataRecv();
842 if (res == DATA_PACKET_ERROR && fErrorCallback) {
843 fErrorCallback(DATA_PACKET_ERROR, fErrorArg);
844 }
845 return res;
846 }
847
848 int Write()
849 {
850 EncodeSyncPacket(fFrames);
851
852 if (SyncSend() == SOCKET_ERROR) {
853 return SOCKET_ERROR;
854 }
855
856 return DataSend();
857 }
858
859 void DummyProcess()
860 {
861 // First cycle with INT_MAX time out
862 SetPacketTimeOut(INT_MAX);
863
864 // One cycle
865 Process();
866
867 // Then use PACKET_TIMEOUT * fParams.fNetworkLatency for next cycles
868 SetPacketTimeOut(std::max(int(PACKET_TIMEOUT), int(PACKET_TIMEOUT * fParams.fNetworkLatency)));
869 }
870
871 int Process()
872 {
873 // Read data from the network, throw JackNetException in case of network error...
874 if (Read() == SOCKET_ERROR) {
875 return SOCKET_ERROR;
876 }
877
878 if (fFrames < 0) fFrames = fParams.fPeriodSize;
879
880 fProcessCallback(fFrames,
881 fParams.fSendAudioChannels,
882 fAudioCaptureBuffer,
883 fParams.fSendMidiChannels,
884 (void**)fMidiCaptureBuffer,
885 fParams.fReturnAudioChannels,
886 fAudioPlaybackBuffer,
887 fParams.fReturnMidiChannels,
888 (void**)fMidiPlaybackBuffer,
889 fProcessArg);
890
891 // Then write data to network, throw JackNetException in case of network error...
892 if (Write() == SOCKET_ERROR) {
893 return SOCKET_ERROR;
894 }
895
896 return 0;
897 }
898
899 int Start()
900 {
901 return (fProcessCallback == 0) ? -1 : fThread.StartSync();
902 }
903
904 int Stop()
905 {
906 return (fProcessCallback == 0) ? -1 : fThread.Kill();
907 }
908
909 // Callback
910 int SetProcessCallback(JackNetSlaveProcessCallback net_callback, void *arg)
911 {
912 if (fThread.GetStatus() == JackThread::kRunning) {
913 return -1;
914 } else {
915 fProcessCallback = net_callback;
916 fProcessArg = arg;
917 return 0;
918 }
919 }
920
921 int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback, void *arg)
922 {
923 if (fThread.GetStatus() == JackThread::kRunning) {
924 return -1;
925 } else {
926 fShutdownCallback = shutdown_callback;
927 fShutdownArg = arg;
928 return 0;
929 }
930 }
931
932 int SetRestartCallback(JackNetSlaveRestartCallback restart_callback, void *arg)
933 {
934 if (fThread.GetStatus() == JackThread::kRunning) {
935 return -1;
936 } else {
937 fRestartCallback = restart_callback;
938 fRestartArg = arg;
939 return 0;
940 }
941 }
942
943 int SetErrorCallback(JackNetSlaveErrorCallback error_callback, void *arg)
944 {
945 if (fThread.GetStatus() == JackThread::kRunning) {
946 return -1;
947 } else {
948 fErrorCallback = error_callback;
949 fErrorArg = arg;
950 return 0;
951 }
952 }
953
954 int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
955 {
956 if (fThread.GetStatus() == JackThread::kRunning) {
957 return -1;
958 } else {
959 fBufferSizeCallback = bufsize_callback;
960 fBufferSizeArg = arg;
961 return 0;
962 }
963 }
964
965 int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
966 {
967 if (fThread.GetStatus() == JackThread::kRunning) {
968 return -1;
969 } else {
970 fSampleRateCallback = samplerate_callback;
971 fSampleRateArg = arg;
972 return 0;
973 }
974 }
975
976 };
977
978 struct JackNetAdapter : public JackAudioAdapterInterface {
979
980 JackNetAdapter(int input, int output,
981 jack_nframes_t host_buffer_size,
982 jack_nframes_t host_sample_rate,
983 jack_nframes_t adapted_buffer_size,
984 jack_nframes_t adapted_sample_rate)
985 :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate)
986 {
987 fCaptureChannels = input;
988 fPlaybackChannels = output;
989 Create();
990 }
991
992 void Create()
993 {
994 //ringbuffers
995
996 if (fCaptureChannels > 0) {
997 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
998 }
999 if (fPlaybackChannels > 0) {
1000 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
1001 }
1002
1003 if (fAdaptative) {
1004 AdaptRingBufferSize();
1005 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
1006 } else {
1007 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
1008 fRingbufferCurSize = DEFAULT_RB_SIZE;
1009 }
1010 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
1011 }
1012
1013 for (int i = 0; i < fCaptureChannels; i++ ) {
1014 fCaptureRingBuffer[i] = new JackResampler();
1015 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
1016 }
1017 for (int i = 0; i < fPlaybackChannels; i++ ) {
1018 fPlaybackRingBuffer[i] = new JackResampler();
1019 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
1020 }
1021
1022 if (fCaptureChannels > 0) {
1023 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
1024 }
1025 if (fPlaybackChannels > 0) {
1026 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
1027 }
1028 }
1029
1030 virtual ~JackNetAdapter()
1031 {
1032 Destroy();
1033 }
1034
1035 void Flush()
1036 {
1037 for (int i = 0; i < fCaptureChannels; i++ ) {
1038 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
1039 }
1040 for (int i = 0; i < fPlaybackChannels; i++ ) {
1041 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
1042 }
1043 }
1044
1045 };
1046
1047
1048 } // end of namespace
1049
1050 using namespace Jack;
1051
1052 LIB_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result)
1053 {
1054 JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request);
1055 if (slave->Open(result) == 0) {
1056 return (jack_net_slave_t*)slave;
1057 } else {
1058 delete slave;
1059 return NULL;
1060 }
1061 }
1062
1063 LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net)
1064 {
1065 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1066 slave->Close();
1067 delete slave;
1068 return 0;
1069 }
1070
1071 LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg)
1072 {
1073 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1074 return slave->SetProcessCallback(net_callback, arg);
1075 }
1076
1077 LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net)
1078 {
1079 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1080 return slave->Start();
1081 }
1082
1083 LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net)
1084 {
1085 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1086 return slave->Stop();
1087 }
1088
1089 LIB_EXPORT int jack_net_slave_is_active(jack_net_slave_t* net)
1090 {
1091 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1092 return slave->IsRunning();
1093 }
1094
1095 LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
1096 {
1097 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1098 return slave->SetBufferSizeCallback(bufsize_callback, arg);
1099 }
1100
1101 LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
1102 {
1103 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1104 return slave->SetSampleRateCallback(samplerate_callback, arg);
1105 }
1106
1107 LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg)
1108 {
1109 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1110 return slave->SetShutdownCallback(shutdown_callback, arg);
1111 }
1112
1113 LIB_EXPORT int jack_set_net_slave_restart_callback(jack_net_slave_t *net, JackNetSlaveRestartCallback restart_callback, void *arg)
1114 {
1115 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1116 return slave->SetRestartCallback(restart_callback, arg);
1117 }
1118
1119 LIB_EXPORT int jack_set_net_slave_error_callback(jack_net_slave_t *net, JackNetSlaveErrorCallback error_callback, void *arg)
1120 {
1121 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1122 return slave->SetErrorCallback(error_callback, arg);
1123 }
1124
1125 // Master API
1126
1127 LIB_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, jack_master_t* request, jack_slave_t* result)
1128 {
1129 JackNetExtMaster* master = new JackNetExtMaster(ip, port, request);
1130 if (master->Open(result) == 0) {
1131 return (jack_net_master_t*)master;
1132 } else {
1133 delete master;
1134 return NULL;
1135 }
1136 }
1137
1138 LIB_EXPORT int jack_net_master_close(jack_net_master_t* net)
1139 {
1140 JackNetExtMaster* master = (JackNetExtMaster*)net;
1141 master->Close();
1142 delete master;
1143 return 0;
1144 }
1145
1146 LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer)
1147 {
1148 JackNetExtMaster* master = (JackNetExtMaster*)net;
1149 return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer, -1);
1150 }
1151
1152 LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer)
1153 {
1154 JackNetExtMaster* master = (JackNetExtMaster*)net;
1155 return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer, -1);
1156 }
1157
1158 LIB_EXPORT int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames)
1159 {
1160 JackNetExtMaster* master = (JackNetExtMaster*)net;
1161 return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer, frames);
1162 }
1163
1164 LIB_EXPORT int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames)
1165 {
1166 JackNetExtMaster* master = (JackNetExtMaster*)net;
1167 return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer, frames);
1168 }
1169
1170 // Adapter API
1171
1172 LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
1173 jack_nframes_t host_buffer_size,
1174 jack_nframes_t host_sample_rate,
1175 jack_nframes_t adapted_buffer_size,
1176 jack_nframes_t adapted_sample_rate)
1177 {
1178 try {
1179 return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate);
1180 } catch (...) {
1181 return NULL;
1182 }
1183 }
1184
1185 LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter)
1186 {
1187 delete((JackNetAdapter*)adapter);
1188 return 0;
1189 }
1190
1191 LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter)
1192 {
1193 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1194 slave->Flush();
1195 }
1196
1197 LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1198 {
1199 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1200 return slave->PushAndPull(input, output, frames);
1201 }
1202
1203 LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1204 {
1205 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1206 return slave->PullAndPush(input, output, frames);
1207 }
1208
1209 static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap)
1210 {
1211 static const char* netjack_log = getenv("JACK_NETJACK_LOG");
1212 static bool is_netjack_log = (netjack_log) ? atoi(netjack_log) : 0;
1213
1214 if (is_netjack_log) {
1215 char buffer[300];
1216 size_t len;
1217
1218 if (prefix != NULL) {
1219 len = strlen(prefix);
1220 memcpy(buffer, prefix, len);
1221 } else {
1222 len = 0;
1223 }
1224
1225 vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap);
1226 printf("%s", buffer);
1227 printf("\n");
1228 }
1229 }
1230
1231 LIB_EXPORT void jack_error(const char *fmt, ...)
1232 {
1233 va_list ap;
1234 va_start(ap, fmt);
1235 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1236 va_end(ap);
1237 }
1238
1239 LIB_EXPORT void jack_info(const char *fmt, ...)
1240 {
1241 va_list ap;
1242 va_start(ap, fmt);
1243 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1244 va_end(ap);
1245 }
1246
1247 LIB_EXPORT void jack_log(const char *fmt, ...)
1248 {
1249 va_list ap;
1250 va_start(ap, fmt);
1251 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1252 va_end(ap);
1253 }
Jack::JackNetExtMaster::InitMaster
int InitMaster(jack_slave_t *result)
Definition: JackNetAPI.cpp:298
Jack::JackRingBuffer
Base class for RingBuffer in frames.
Definition: JackResampler.h:41
Jack::JackNetSlaveInterface
Definition: JackNetInterface.h:199
Jack::JackRunnableInterface
The base class for runnable objects, that have an Init and Execute method to be called in a threa...
Definition: JackThread.h:34
jack_master_t
Definition: JackNetAPI.cpp:57
jack_error
LIB_EXPORT void jack_error(const char *fmt,...)
Definition: JackNetAPI.cpp:1231
Jack::JackResampler
Base class for Resampler.
Definition: JackResampler.h:79
jack_info
LIB_EXPORT void jack_info(const char *fmt,...)
Definition: JackNetAPI.cpp:1239
Jack::JackAudioAdapterInterface
Base class for audio adapters.
Definition: JackAudioAdapterInterface.h:65
Jack::JackNetExtSlave::Init
bool Init()
Definition: JackNetAPI.cpp:772
jack_slave_t
Definition: JackNetAPI.cpp:43
Jack::JackNetExtMaster
Definition: JackNetAPI.cpp:148
Jack::JackNetExtSlave
Definition: JackNetAPI.cpp:478
Jack::JackNetAdapter
Net adapter.
Definition: JackNetAdapter.h:33
Jack::JackMidiBuffer
Definition: JackMidiPort.h:75
Jack::JackNetMasterInterface
Definition: JackNetInterface.h:143
Jack::JackNetException
Exception possibly thrown by Net slaves.
Definition: JackException.h:103
Jack::_session_params
This structure containes master/slave connection parameters, it's used to setup the whole system.
Definition: JackNetTool.h:91
jack_log
LIB_EXPORT void jack_log(const char *fmt,...)
Definition: JackNetAPI.cpp:1247
Jack::JackMachThread
Darwin threads. Real-time threads are actually "time constraint" threads.
Definition: JackMachThread.h:92