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 
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 
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 
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 
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::JackMachThread
Darwin threads. Real-time threads are actually "time constraint" threads.
Definition: JackMachThread.h:92
jack_log
LIB_EXPORT void jack_log(const char *fmt,...)
Definition: JackNetAPI.cpp:1247
Jack::JackNetAdapter
Net adapter.
Definition: JackNetAdapter.h:33
Jack::JackNetSlaveInterface
Definition: JackNetInterface.h:199
Jack::JackNetMasterInterface
Definition: JackNetInterface.h:143
jack_error
LIB_EXPORT void jack_error(const char *fmt,...)
Definition: JackNetAPI.cpp:1231
Jack::JackNetExtSlave::Init
bool Init()
Definition: JackNetAPI.cpp:772
Jack::JackNetException
Exception possibly thrown by Net slaves.
Definition: JackException.h:103
Jack::JackAudioAdapterInterface
Base class for audio adapters.
Definition: JackAudioAdapterInterface.h:65
Jack::_session_params
This structure containes master/slave connection parameters, it's used to setup the whole system.
Definition: JackNetTool.h:91
jack_slave_t
Definition: JackNetAPI.cpp:43
jack_master_t
Definition: JackNetAPI.cpp:57
Jack::JackResampler
Base class for Resampler.
Definition: JackResampler.h:79
Jack::JackNetExtSlave
Definition: JackNetAPI.cpp:478
Jack::JackMidiBuffer
Definition: JackMidiPort.h:75
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::JackNetExtMaster
Definition: JackNetAPI.cpp:148
Jack::JackRingBuffer
Base class for RingBuffer in frames.
Definition: JackResampler.h:41
Jack::JackNetExtMaster::InitMaster
int InitMaster(jack_slave_t *result)
Definition: JackNetAPI.cpp:298
jack_info
LIB_EXPORT void jack_info(const char *fmt,...)
Definition: JackNetAPI.cpp:1239