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 
JackNetExtMasterJack::JackNetExtMaster154     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 
~JackNetExtMasterJack::JackNetExtMaster171     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 
OpenJack::JackNetExtMaster181     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 
InitMasterJack::JackNetExtMaster298     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 
347         /// Network init
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 
CloseJack::JackNetExtMaster360     int Close()
361     {
362         fSocket.Close();
363         return 0;
364     }
365 
UseRingBufferJack::JackNetExtMaster366     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 
ReadJack::JackNetExtMaster377     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 
WriteJack::JackNetExtMaster431     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
EncodeTransportDataJack::JackNetExtMaster470     void EncodeTransportData()
471     {}
472 
DecodeTransportDataJack::JackNetExtMaster473     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 
JackNetExtSlaveJack::JackNetExtSlave510     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 
~JackNetExtSlaveJack::JackNetExtSlave554     virtual ~JackNetExtSlave()
555     {}
556 
AllocPortsJack::JackNetExtSlave557     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 
FreePortsJack::JackNetExtSlave597     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 
OpenJack::JackNetExtSlave632     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 
RestartJack::JackNetExtSlave704     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 
CloseJack::JackNetExtSlave758     int Close()
759     {
760         fSocket.Close();
761         FreePorts();
762         return 0;
763     }
764 
765     // Transport
EncodeTransportDataJack::JackNetExtSlave766     void EncodeTransportData()
767     {}
768 
DecodeTransportDataJack::JackNetExtSlave769     void DecodeTransportData()
770     {}
771 
InitJack::JackNetExtSlave772     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 
IsRunningJack::JackNetExtSlave783     bool IsRunning()
784     {
785         return (fThread.GetStatus() == JackThread::kRunning);
786     }
787 
ExecuteJack::JackNetExtSlave788     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 
ReadJack::JackNetExtSlave820     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 
WriteJack::JackNetExtSlave848     int Write()
849     {
850         EncodeSyncPacket(fFrames);
851 
852         if (SyncSend() == SOCKET_ERROR) {
853             return SOCKET_ERROR;
854         }
855 
856         return DataSend();
857     }
858 
DummyProcessJack::JackNetExtSlave859     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 
ProcessJack::JackNetExtSlave871     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 
StartJack::JackNetExtSlave899     int Start()
900     {
901         return (fProcessCallback == 0) ? -1 : fThread.StartSync();
902     }
903 
StopJack::JackNetExtSlave904     int Stop()
905     {
906         return (fProcessCallback == 0) ? -1 : fThread.Kill();
907     }
908 
909     // Callback
SetProcessCallbackJack::JackNetExtSlave910     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 
SetShutdownCallbackJack::JackNetExtSlave921     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 
SetRestartCallbackJack::JackNetExtSlave932     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 
SetErrorCallbackJack::JackNetExtSlave943     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 
SetBufferSizeCallbackJack::JackNetExtSlave954     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 
SetSampleRateCallbackJack::JackNetExtSlave965     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 
JackNetAdapterJack::JackNetAdapter980     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 
CreateJack::JackNetAdapter992     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 
~JackNetAdapterJack::JackNetAdapter1030     virtual ~JackNetAdapter()
1031     {
1032         Destroy();
1033     }
1034 
FlushJack::JackNetAdapter1035     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 
jack_net_slave_open(const char * ip,int port,const char * name,jack_slave_t * request,jack_master_t * result)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 
jack_net_slave_close(jack_net_slave_t * net)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 
jack_set_net_slave_process_callback(jack_net_slave_t * net,JackNetSlaveProcessCallback net_callback,void * arg)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 
jack_net_slave_activate(jack_net_slave_t * net)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 
jack_net_slave_deactivate(jack_net_slave_t * net)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 
jack_net_slave_is_active(jack_net_slave_t * net)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 
jack_set_net_slave_buffer_size_callback(jack_net_slave_t * net,JackNetSlaveBufferSizeCallback bufsize_callback,void * arg)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 
jack_set_net_slave_sample_rate_callback(jack_net_slave_t * net,JackNetSlaveSampleRateCallback samplerate_callback,void * arg)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 
jack_set_net_slave_shutdown_callback(jack_net_slave_t * net,JackNetSlaveShutdownCallback shutdown_callback,void * arg)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 
jack_set_net_slave_restart_callback(jack_net_slave_t * net,JackNetSlaveRestartCallback restart_callback,void * arg)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 
jack_set_net_slave_error_callback(jack_net_slave_t * net,JackNetSlaveErrorCallback error_callback,void * arg)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 
jack_net_master_open(const char * ip,int port,jack_master_t * request,jack_slave_t * result)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 
jack_net_master_close(jack_net_master_t * net)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 
jack_net_master_recv(jack_net_master_t * net,int audio_input,float ** audio_input_buffer,int midi_input,void ** midi_input_buffer)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 
jack_net_master_send(jack_net_master_t * net,int audio_output,float ** audio_output_buffer,int midi_output,void ** midi_output_buffer)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 
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)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 
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)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 
jack_create_adapter(int input,int output,jack_nframes_t host_buffer_size,jack_nframes_t host_sample_rate,jack_nframes_t adapted_buffer_size,jack_nframes_t adapted_sample_rate)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 
jack_destroy_adapter(jack_adapter_t * adapter)1185 LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter)
1186 {
1187     delete((JackNetAdapter*)adapter);
1188     return 0;
1189 }
1190 
jack_flush_adapter(jack_adapter_t * adapter)1191 LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter)
1192 {
1193     JackNetAdapter* slave = (JackNetAdapter*)adapter;
1194     slave->Flush();
1195 }
1196 
jack_adapter_push_and_pull(jack_adapter_t * adapter,float ** input,float ** output,unsigned int frames)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 
jack_adapter_pull_and_push(jack_adapter_t * adapter,float ** input,float ** output,unsigned int frames)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 
jack_format_and_log(int level,const char * prefix,const char * fmt,va_list ap)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 
jack_error(const char * fmt,...)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 
jack_info(const char * fmt,...)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 
jack_log(const char * fmt,...)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 }
1254