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