Jack2  1.9.9
JackNetAPI.cpp
1 /*
2 Copyright (C) 2009-2011 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 
67  } jack_master_t;
68 
69  // NetJack slave API
70 
71  typedef struct _jack_net_slave jack_net_slave_t;
72 
73  typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size,
74  int audio_input,
75  float** audio_input_buffer,
76  int midi_input,
77  void** midi_input_buffer,
78  int audio_output,
79  float** audio_output_buffer,
80  int midi_output,
81  void** midi_output_buffer,
82  void* data);
83 
84  typedef int (*JackNetSlaveBufferSizeCallback) (jack_nframes_t nframes, void *arg);
85  typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg);
86  typedef void (*JackNetSlaveShutdownCallback) (void* data);
87 
88  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);
89  LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net);
90 
91  LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net);
92  LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net);
93 
94  LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg);
95  LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t* net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg);
96  LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t* net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg);
97  LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t* net, JackNetSlaveShutdownCallback shutdown_callback, void *arg);
98 
99  // NetJack master API
100 
101  typedef struct _jack_net_master jack_net_master_t;
102 
103  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);
104  LIB_EXPORT int jack_net_master_close(jack_net_master_t* net);
105 
106  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);
107  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);
108 
109  // NetJack adapter API
110 
111  typedef struct _jack_adapter jack_adapter_t;
112 
113  LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
114  jack_nframes_t host_buffer_size,
115  jack_nframes_t host_sample_rate,
116  jack_nframes_t adapted_buffer_size,
117  jack_nframes_t adapted_sample_rate);
118  LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter);
119  LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter);
120 
121  LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
122  LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
123 
124  #define LOG_LEVEL_INFO 1
125  #define LOG_LEVEL_ERROR 2
126 
127  LIB_EXPORT void jack_error(const char *fmt, ...);
128  LIB_EXPORT void jack_info(const char *fmt, ...);
129  LIB_EXPORT void jack_log(const char *fmt, ...);
130 
131 #ifdef __cplusplus
132 }
133 #endif
134 
135 namespace Jack
136 {
137 
139 
140  // Data buffers
141  float** fAudioCaptureBuffer;
142  float** fAudioPlaybackBuffer;
143 
144  JackMidiBuffer** fMidiCaptureBuffer;
145  JackMidiBuffer** fMidiPlaybackBuffer;
146 
147  jack_master_t fRequest;
148 
149  JackNetExtMaster(const char* ip,
150  int port,
151  const char* name,
152  jack_master_t* request)
153  {
154  fRunning = true;
155  assert(strlen(ip) < 32);
156  strcpy(fMulticastIP, ip);
157  fSocket.SetPort(port);
158  fRequest.buffer_size = request->buffer_size;
159  fRequest.sample_rate = request->sample_rate;
160  fRequest.audio_input = request->audio_input;
161  fRequest.audio_output = request->audio_output;
162  fAudioCaptureBuffer = NULL;
163  fAudioPlaybackBuffer = NULL;
164  fMidiCaptureBuffer = NULL;
165  fMidiPlaybackBuffer = NULL;
166  }
167 
168  virtual ~JackNetExtMaster()
169  {}
170 
171  int Open(jack_slave_t* result)
172  {
173  // Init socket API (win32)
174  if (SocketAPIInit() < 0) {
175  jack_error("Can't init Socket API, exiting...");
176  return -1;
177  }
178 
179  // Request socket
180  if (fSocket.NewSocket() == SOCKET_ERROR) {
181  jack_error("Can't create the network management input socket : %s", StrError(NET_ERROR_CODE));
182  return -1;
183  }
184 
185  // Bind the socket to the local port
186  if (fSocket.Bind() == SOCKET_ERROR) {
187  jack_error("Can't bind the network manager socket : %s", StrError(NET_ERROR_CODE));
188  fSocket.Close();
189  return -1;
190  }
191 
192  // Join multicast group
193  if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
194  jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
195  }
196 
197  // Local loop
198  if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
199  jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
200  }
201 
202  // Set a timeout on the multicast receive (the thread can now be cancelled)
203  if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
204  jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
205  }
206 
207  // Main loop, wait for data, deal with it and wait again
208  int attempt = 0;
209  int rx_bytes = 0;
210 
211  do
212  {
213  session_params_t net_params;
214  rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
215  SessionParamsNToH(&net_params, &fParams);
216 
217  if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
218  jack_error("Error in receive : %s", StrError(NET_ERROR_CODE));
219  if (++attempt == 10) {
220  jack_error("Can't receive on the socket, exiting net manager" );
221  goto error;
222  }
223  }
224 
225  if (rx_bytes == sizeof(session_params_t )) {
226  switch (GetPacketType(&fParams)) {
227 
228  case SLAVE_AVAILABLE:
229  if (InitMaster(result) == 0) {
230  SessionParamsDisplay(&fParams);
231  fRunning = false;
232  } else {
233  jack_error("Can't init new net master...");
234  goto error;
235  }
236  jack_info("Waiting for a slave...");
237  break;
238 
239  case KILL_MASTER:
240  break;
241 
242  default:
243  break;
244  }
245  }
246  }
247  while (fRunning);
248 
249  // Set result parameters
250  result->audio_input = fParams.fSendAudioChannels;
251  result->audio_output = fParams.fReturnAudioChannels;
252  result->midi_input = fParams.fSendMidiChannels;
253  result->midi_output = fParams.fReturnMidiChannels;
254  result->mtu = fParams.fMtu;
255  result->latency = fParams.fNetworkLatency;
256  return 0;
257 
258  error:
259  fSocket.Close();
260  return -1;
261  }
262 
264  {
265  // Check MASTER <==> SLAVE network protocol coherency
266  if (fParams.fProtocolVersion != MASTER_PROTOCOL) {
267  jack_error("Error : slave is running with a different protocol %s", fParams.fName);
268  return -1;
269  }
270 
271  // Settings
272  fSocket.GetName(fParams.fMasterNetName);
273  fParams.fID = 1;
274  fParams.fPeriodSize = fRequest.buffer_size;
275  fParams.fSampleRate = fRequest.sample_rate;
276 
277  if (fRequest.audio_input == -1) {
278  if (fParams.fSendAudioChannels == -1) {
279  jack_error("Error : master and slave use -1 for wanted inputs...");
280  return -1;
281  } else {
282  result->audio_input = fParams.fSendAudioChannels;
283  jack_info("Takes slave %d inputs", fParams.fSendAudioChannels);
284  }
285  } else if (fParams.fSendAudioChannels == -1) {
286  fParams.fSendAudioChannels = fRequest.audio_input;
287  jack_info("Takes master %d inputs", fRequest.audio_input);
288  } else if (fParams.fSendAudioChannels != fRequest.audio_input) {
289  jack_error("Error : master wants %d inputs and slave wants %d inputs...", fRequest.audio_input, fParams.fSendAudioChannels);
290  return -1;
291  }
292 
293  if (fRequest.audio_output == -1) {
294  if (fParams.fReturnAudioChannels == -1) {
295  jack_error("Error : master and slave use -1 for wanted outputs...");
296  return -1;
297  } else {
298  result->audio_output = fParams.fReturnAudioChannels;
299  jack_info("Takes slave %d outputs", fParams.fReturnAudioChannels);
300  }
301  } else if (fParams.fReturnAudioChannels == -1) {
302  fParams.fReturnAudioChannels = fRequest.audio_output;
303  jack_info("Takes master %d outputs", fRequest.audio_output);
304  } else if (fParams.fReturnAudioChannels != fRequest.audio_output) {
305  jack_error("Error : master wants %d outputs and slave wants %d outputs...", fRequest.audio_output, fParams.fReturnAudioChannels);
306  return -1;
307  }
308 
309  // Close request socket
310  fSocket.Close();
311 
313  if (!JackNetMasterInterface::Init()) {
314  return -1;
315  }
316 
317  // Set global parameters
318  if (!SetParams()) {
319  return -1;
320  }
321 
322  AllocPorts();
323  return 0;
324  }
325 
326  int Close()
327  {
328  fSocket.Close();
329  FreePorts();
330  return 0;
331  }
332 
333  void AllocPorts()
334  {
335  // Set buffers
336  if (fParams.fSendAudioChannels > 0) {
337  fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels];
338  for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
339  fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize];
340  fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]);
341  }
342  }
343 
344  if (fParams.fSendMidiChannels > 0) {
345  fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels];
346  for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
347  fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
348  fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]);
349  }
350  }
351 
352  if (fParams.fReturnAudioChannels > 0) {
353  fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels];
354  for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
355  fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize];
356  fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]);
357  }
358  }
359 
360  if (fParams.fReturnMidiChannels > 0) {
361  fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels];
362  for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
363  fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
364  fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]);
365  }
366  }
367  }
368 
369  void FreePorts()
370  {
371  if (fAudioPlaybackBuffer) {
372  for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++)
373  delete[] fAudioPlaybackBuffer[audio_port_index];
374  delete[] fAudioPlaybackBuffer;
375  fAudioPlaybackBuffer = NULL;
376  }
377 
378  if (fMidiPlaybackBuffer) {
379  for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++)
380  delete[] (fMidiPlaybackBuffer[midi_port_index]);
381  delete[] fMidiPlaybackBuffer;
382  fMidiPlaybackBuffer = NULL;
383  }
384 
385  if (fAudioCaptureBuffer) {
386  for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++)
387  delete[] fAudioCaptureBuffer[audio_port_index];
388  delete[] fAudioCaptureBuffer;
389  fAudioCaptureBuffer = NULL;
390  }
391 
392  if (fMidiCaptureBuffer) {
393  for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++)
394  delete[] fMidiCaptureBuffer[midi_port_index];
395  delete[] fMidiCaptureBuffer;
396  fMidiCaptureBuffer = NULL;
397  }
398  }
399 
400  int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer)
401  {
402 
403  try {
404 
405  assert(audio_input == fParams.fReturnAudioChannels);
406 
407  for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) {
408  fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, audio_input_buffer[audio_port_index]);
409  }
410 
411  for (int midi_port_index = 0; midi_port_index < midi_input; midi_port_index++) {
412  fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]);
413  }
414 
415  //receive sync
416  int res = SyncRecv();
417  if ((res == 0) || (res == SOCKET_ERROR)) {
418  return res;
419  }
420 
421  DecodeSyncPacket();
422  return DataRecv();
423 
424  } catch (JackNetException& e) {
425  jack_error("Connection lost.");
426  return -1;
427  }
428  }
429 
430  int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer)
431  {
432  try {
433 
434  assert(audio_output == fParams.fSendAudioChannels);
435 
436  for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) {
437  fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]);
438  }
439 
440  for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) {
441  fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]);
442  }
443 
444 
445  if (IsSynched()) { // only send if connection is "synched"
446 
447  EncodeSyncPacket();
448 
449  if (SyncSend() == SOCKET_ERROR) {
450  return SOCKET_ERROR;
451  }
452 
453  //send data
454  if (DataSend() == SOCKET_ERROR) {
455  return SOCKET_ERROR;
456  }
457 
458  } else {
459  jack_info("Connection is not synched, skip cycle...");
460  }
461 
462  return 0;
463 
464  } catch (JackNetException& e) {
465  jack_error("Connection lost.");
466  return -1;
467  }
468  }
469 
470  // Transport
471  void EncodeTransportData()
472  {}
473 
474  void DecodeTransportData()
475  {}
476 
477 };
478 
480 
481  JackThread fThread;
482 
483  JackNetSlaveProcessCallback fProcessCallback;
484  void* fProcessArg;
485 
486  JackNetSlaveShutdownCallback fShutdownCallback;
487  void* fShutdownArg;
488 
489  JackNetSlaveBufferSizeCallback fBufferSizeCallback;
490  void* fBufferSizeArg;
491 
492  JackNetSlaveSampleRateCallback fSampleRateCallback;
493  void* fSampleRateArg;
494 
495  //sample buffers
496  float** fAudioCaptureBuffer;
497  float** fAudioPlaybackBuffer;
498 
499  JackMidiBuffer** fMidiCaptureBuffer;
500  JackMidiBuffer** fMidiPlaybackBuffer;
501 
502  int fConnectTimeOut;
503 
504  JackNetExtSlave(const char* ip,
505  int port,
506  const char* name,
507  jack_slave_t* request)
508  :fThread(this),
509  fProcessCallback(NULL),fProcessArg(NULL),
510  fShutdownCallback(NULL), fShutdownArg(NULL),
511  fBufferSizeCallback(NULL), fBufferSizeArg(NULL),
512  fSampleRateCallback(NULL), fSampleRateArg(NULL),
513  fAudioCaptureBuffer(NULL), fAudioPlaybackBuffer(NULL),
514  fMidiCaptureBuffer(NULL), fMidiPlaybackBuffer(NULL)
515  {
516  char host_name[JACK_CLIENT_NAME_SIZE];
517 
518  // Request parameters
519  assert(strlen(ip) < 32);
520  strcpy(fMulticastIP, ip);
521  fParams.fMtu = request->mtu;
522  fParams.fTransportSync = 0;
523  fParams.fSendAudioChannels = request->audio_input;
524  fParams.fReturnAudioChannels = request->audio_output;
525  fParams.fSendMidiChannels = request->midi_input;
526  fParams.fReturnMidiChannels = request->midi_output;
527  fParams.fNetworkLatency = request->latency;
528  fParams.fSampleEncoder = request->encoder;
529  fParams.fKBps = request->kbps;
530  fParams.fSlaveSyncMode = 1;
531  fConnectTimeOut = request->time_out;
532 
533  // Create name with hostname and client name
534  GetHostName(host_name, JACK_CLIENT_NAME_SIZE);
535  snprintf(fParams.fName, JACK_CLIENT_NAME_SIZE, "%s_%s", host_name, name);
536  fSocket.GetName(fParams.fSlaveNetName);
537 
538  // Set the socket parameters
539  fSocket.SetPort(port);
540  fSocket.SetAddress(fMulticastIP, port);
541  }
542 
543  virtual ~JackNetExtSlave()
544  {}
545 
546  int Open(jack_master_t* result)
547  {
548  // Check CELT encoder parameters
549  if ((fParams.fSampleEncoder == JackCeltEncoder) && (fParams.fKBps == 0)) {
550  jack_error("CELT encoder with 0 for kps...");
551  return -1;
552  }
553 
554  if ((fParams.fSampleEncoder == JackOpusEncoder) && (fParams.fKBps == 0)) {
555  jack_error("Opus encoder with 0 for kps...");
556  return -1;
557  }
558 
559  // Check latency
560  if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
561  jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY);
562  return -1;
563  }
564 
565  // Init network connection
566  if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
567  jack_error("Initing network fails...");
568  return -1;
569  }
570 
571  // Finish connection...
572  if (!JackNetSlaveInterface::InitRendering()) {
573  jack_error("Starting network fails...");
574  return -1;
575  }
576 
577  // Then set global parameters
578  if (!SetParams()) {
579  jack_error("SetParams error...");
580  return -1;
581  }
582 
583  // Set result
584  if (result != NULL) {
585  result->buffer_size = fParams.fPeriodSize;
586  result->sample_rate = fParams.fSampleRate;
587  result->audio_input = fParams.fSendAudioChannels;
588  result->audio_output = fParams.fReturnAudioChannels;
589  result->midi_input = fParams.fSendMidiChannels;
590  result->midi_output = fParams.fReturnMidiChannels;
591  strcpy(result->master_name, fParams.fMasterNetName);
592  }
593 
594  AllocPorts();
595  return 0;
596  }
597 
598  int Restart()
599  {
600  // If shutdown cb is set, then call it
601  if (fShutdownCallback) {
602  fShutdownCallback(fShutdownArg);
603  }
604 
605  // Init network connection
606  if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
607  jack_error("Initing network fails...");
608  return -1;
609  }
610 
611  // Finish connection
612  if (!JackNetSlaveInterface::InitRendering()) {
613  jack_error("Starting network fails...");
614  return -1;
615  }
616 
617  // Then set global parameters
618  if (!SetParams()) {
619  jack_error("SetParams error...");
620  return -1;
621  }
622 
623  // We need to notify possibly new buffer size and sample rate (see Execute)
624  if (fBufferSizeCallback) {
625  fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg);
626  }
627 
628  if (fSampleRateCallback) {
629  fSampleRateCallback(fParams.fSampleRate, fSampleRateArg);
630  }
631 
632  AllocPorts();
633  return 0;
634  }
635 
636  int Close()
637  {
638  fSocket.Close();
639  FreePorts();
640  return 0;
641  }
642 
643  void AllocPorts()
644  {
645  // Set buffers
646  fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels];
647  for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
648  fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize];
649  fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]);
650  }
651 
652  fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels];
653  for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
654  fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
655  fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]);
656  }
657 
658  fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels];
659  for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
660  fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize];
661  fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]);
662  }
663 
664  fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels];
665  for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
666  fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
667  fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]);
668  }
669  }
670 
671  void FreePorts()
672  {
673  if (fAudioCaptureBuffer) {
674  for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
675  delete[] fAudioCaptureBuffer[audio_port_index];
676  }
677  delete[] fAudioCaptureBuffer;
678  fAudioCaptureBuffer = NULL;
679  }
680 
681  if (fMidiCaptureBuffer) {
682  for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
683  delete[] (fMidiCaptureBuffer[midi_port_index]);
684  }
685  delete[] fMidiCaptureBuffer;
686  fMidiCaptureBuffer = NULL;
687  }
688 
689  if (fAudioPlaybackBuffer) {
690  for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
691  delete[] fAudioPlaybackBuffer[audio_port_index];
692  }
693  delete[] fAudioPlaybackBuffer;
694  fAudioPlaybackBuffer = NULL;
695  }
696 
697  if (fMidiPlaybackBuffer) {
698  for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
699  delete[] fMidiPlaybackBuffer[midi_port_index];
700  }
701  delete[] fMidiPlaybackBuffer;
702  fMidiPlaybackBuffer = NULL;
703  }
704  }
705 
706  // Transport
707  void EncodeTransportData()
708  {}
709 
710  void DecodeTransportData()
711  {}
712 
713  bool Init()
714  {
715  // Will do "something" on OSX only...
716  UInt64 period, constraint;
717  period = constraint = UInt64(1000000000.f * (float(fParams.fPeriodSize) / float(fParams.fSampleRate)));
718  UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize) * 1000;
719  fThread.SetParams(period, computation, constraint);
720 
721  return (fThread.AcquireSelfRealTime(80) == 0); // TODO: get a value from the server
722  }
723 
724  bool Execute()
725  {
726  try {
727  // Keep running even in case of error
728  while (fThread.GetStatus() == JackThread::kRunning) {
729  if (Process() == SOCKET_ERROR) {
730  return false;
731  }
732  }
733  return false;
734  } catch (JackNetException& e) {
735  // Otherwise just restart...
736  e.PrintMessage();
737  jack_info("NetSlave is restarted");
738  fThread.DropRealTime();
739  fThread.SetStatus(JackThread::kIniting);
740  FreePorts();
741  if (Restart() == 0 && Init()) {
742  fThread.SetStatus(JackThread::kRunning);
743  return true;
744  } else {
745  return false;
746  }
747  }
748  }
749 
750  int Read()
751  {
752  //receive sync (launch the cycle)
753  if (SyncRecv() == SOCKET_ERROR) {
754  return SOCKET_ERROR;
755  }
756 
757  DecodeSyncPacket();
758  return DataRecv();
759  }
760 
761  int Write()
762  {
763  EncodeSyncPacket();
764 
765  if (SyncSend() == SOCKET_ERROR) {
766  return SOCKET_ERROR;
767  }
768 
769  return DataSend();
770  }
771 
772  int Process()
773  {
774  // Read data from the network, throw JackNetException in case of network error...
775  if (Read() == SOCKET_ERROR) {
776  return SOCKET_ERROR;
777  }
778 
779  fProcessCallback(fParams.fPeriodSize,
780  fParams.fSendAudioChannels,
781  fAudioCaptureBuffer,
782  fParams.fSendMidiChannels,
783  (void**)fMidiCaptureBuffer,
784  fParams.fReturnAudioChannels,
785  fAudioPlaybackBuffer,
786  fParams.fReturnMidiChannels,
787  (void**)fMidiPlaybackBuffer,
788  fProcessArg);
789 
790  // Then write data to network, throw JackNetException in case of network error...
791  if (Write() == SOCKET_ERROR) {
792  return SOCKET_ERROR;
793  }
794 
795  return 0;
796  }
797 
798  int Start()
799  {
800  return (fProcessCallback == 0) ? -1 : fThread.StartSync();
801  }
802 
803  int Stop()
804  {
805  return (fProcessCallback == 0) ? -1 : fThread.Kill();
806  }
807 
808  // Callback
809  int SetProcessCallback(JackNetSlaveProcessCallback net_callback, void *arg)
810  {
811  if (fThread.GetStatus() == JackThread::kRunning) {
812  return -1;
813  } else {
814  fProcessCallback = net_callback;
815  fProcessArg = arg;
816  return 0;
817  }
818  }
819 
820  int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback, void *arg)
821  {
822  if (fThread.GetStatus() == JackThread::kRunning) {
823  return -1;
824  } else {
825  fShutdownCallback = shutdown_callback;
826  fShutdownArg = arg;
827  return 0;
828  }
829  }
830 
831  int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
832  {
833  if (fThread.GetStatus() == JackThread::kRunning) {
834  return -1;
835  } else {
836  fBufferSizeCallback = bufsize_callback;
837  fBufferSizeArg = arg;
838  return 0;
839  }
840  }
841 
842  int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
843  {
844  if (fThread.GetStatus() == JackThread::kRunning) {
845  return -1;
846  } else {
847  fSampleRateCallback = samplerate_callback;
848  fSampleRateArg = arg;
849  return 0;
850  }
851  }
852 
853 };
854 
856 
857  JackNetAdapter(int input, int output,
858  jack_nframes_t host_buffer_size,
859  jack_nframes_t host_sample_rate,
860  jack_nframes_t adapted_buffer_size,
861  jack_nframes_t adapted_sample_rate)
862  :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate)
863  {
864  fCaptureChannels = input;
865  fPlaybackChannels = output;
866  Create();
867  }
868 
869  void Create()
870  {
871  //ringbuffers
872 
873  if (fCaptureChannels > 0) {
874  fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
875  }
876  if (fPlaybackChannels > 0) {
877  fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
878  }
879 
880  if (fAdaptative) {
881  AdaptRingBufferSize();
882  jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
883  } else {
884  if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
885  fRingbufferCurSize = DEFAULT_RB_SIZE;
886  }
887  jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
888  }
889 
890  for (int i = 0; i < fCaptureChannels; i++ ) {
891  fCaptureRingBuffer[i] = new JackResampler();
892  fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
893  }
894  for (int i = 0; i < fPlaybackChannels; i++ ) {
895  fPlaybackRingBuffer[i] = new JackResampler();
896  fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
897  }
898 
899  if (fCaptureChannels > 0) {
900  jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
901  }
902  if (fPlaybackChannels > 0) {
903  jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
904  }
905  }
906 
907  virtual ~JackNetAdapter()
908  {
909  Destroy();
910  }
911 
912  void Flush()
913  {
914  for (int i = 0; i < fCaptureChannels; i++ ) {
915  fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
916  }
917  for (int i = 0; i < fPlaybackChannels; i++ ) {
918  fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
919  }
920  }
921 
922 };
923 
924 
925 } // end of namespace
926 
927 using namespace Jack;
928 
929 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)
930 {
931  JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request);
932  if (slave->Open(result) == 0) {
933  return (jack_net_slave_t*)slave;
934  } else {
935  delete slave;
936  return NULL;
937  }
938 }
939 
940 LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net)
941 {
942  JackNetExtSlave* slave = (JackNetExtSlave*)net;
943  slave->Close();
944  delete slave;
945  return 0;
946 }
947 
948 LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg)
949 {
950  JackNetExtSlave* slave = (JackNetExtSlave*)net;
951  return slave->SetProcessCallback(net_callback, arg);
952 }
953 
954 LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net)
955 {
956  JackNetExtSlave* slave = (JackNetExtSlave*)net;
957  return slave->Start();
958 }
959 
960 LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net)
961 {
962  JackNetExtSlave* slave = (JackNetExtSlave*)net;
963  return slave->Stop();
964 }
965 
966 LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
967 {
968  JackNetExtSlave* slave = (JackNetExtSlave*)net;
969  return slave->SetBufferSizeCallback(bufsize_callback, arg);
970 }
971 
972 LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
973 {
974  JackNetExtSlave* slave = (JackNetExtSlave*)net;
975  return slave->SetSampleRateCallback(samplerate_callback, arg);
976 }
977 
978 LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg)
979 {
980  JackNetExtSlave* slave = (JackNetExtSlave*)net;
981  return slave->SetShutdownCallback(shutdown_callback, arg);
982 }
983 
984 // Master API
985 
986 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)
987 {
988  JackNetExtMaster* master = new JackNetExtMaster(ip, port, name, request);
989  if (master->Open(result) == 0) {
990  return (jack_net_master_t*)master;
991  } else {
992  delete master;
993  return NULL;
994  }
995 }
996 
997 LIB_EXPORT int jack_net_master_close(jack_net_master_t* net)
998 {
999  JackNetExtMaster* master = (JackNetExtMaster*)net;
1000  master->Close();
1001  delete master;
1002  return 0;
1003 }
1004 
1005 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)
1006 {
1007  JackNetExtMaster* master = (JackNetExtMaster*)net;
1008  return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer);
1009 }
1010 
1011 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)
1012 {
1013  JackNetExtMaster* master = (JackNetExtMaster*)net;
1014  return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer);
1015 }
1016 
1017 // Adapter API
1018 
1019 LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
1020  jack_nframes_t host_buffer_size,
1021  jack_nframes_t host_sample_rate,
1022  jack_nframes_t adapted_buffer_size,
1023  jack_nframes_t adapted_sample_rate)
1024 {
1025  try {
1026  return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate);
1027  } catch (...) {
1028  return NULL;
1029  }
1030 }
1031 
1032 LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter)
1033 {
1034  delete((JackNetAdapter*)adapter);
1035  return 0;
1036 }
1037 
1038 LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter)
1039 {
1040  JackNetAdapter* slave = (JackNetAdapter*)adapter;
1041  slave->Flush();
1042 }
1043 
1044 LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1045 {
1046  JackNetAdapter* slave = (JackNetAdapter*)adapter;
1047  return slave->PushAndPull(input, output, frames);
1048 }
1049 
1050 LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1051 {
1052  JackNetAdapter* slave = (JackNetAdapter*)adapter;
1053  return slave->PullAndPush(input, output, frames);
1054 }
1055 
1056 static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap)
1057 {
1058  static const char* netjack_log = getenv("JACK_NETJACK_LOG");
1059  static bool is_netjack_log = (netjack_log) ? atoi(netjack_log) : 0;
1060 
1061  if (is_netjack_log) {
1062  char buffer[300];
1063  size_t len;
1064 
1065  if (prefix != NULL) {
1066  len = strlen(prefix);
1067  memcpy(buffer, prefix, len);
1068  } else {
1069  len = 0;
1070  }
1071 
1072  vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap);
1073  printf("%s", buffer);
1074  printf("\n");
1075  }
1076 }
1077 
1078 LIB_EXPORT void jack_error(const char *fmt, ...)
1079 {
1080  va_list ap;
1081  va_start(ap, fmt);
1082  jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1083  va_end(ap);
1084 }
1085 
1086 LIB_EXPORT void jack_info(const char *fmt, ...)
1087 {
1088  va_list ap;
1089  va_start(ap, fmt);
1090  jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1091  va_end(ap);
1092 }
1093 
1094 LIB_EXPORT void jack_log(const char *fmt, ...)
1095 {
1096  va_list ap;
1097  va_start(ap, fmt);
1098  jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1099  va_end(ap);
1100 }
int InitMaster(jack_slave_t *result)
Definition: JackNetAPI.cpp:263
The base class for runnable objects, that have an Init and Execute method to be called in a threa...
Definition: JackThread.h:34
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
Base class for Resampler.
Definition: JackResampler.h:41
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:99
Base class for audio adapters.
Exception possibly thrown by Net slaves.
This structure containes master/slave connection parameters, it&#39;s used to setup the whole system...
Definition: JackNetTool.h:88
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107
Darwin threads. Real-time threads are actually &quot;time constraint&quot; threads.