Merge branch 'master' into develop
[jack2.git] / common / JackNetAPI.cpp
blob09962ca71619e1dfe159831daadd38c5a6a336b4
1 /*
2 Copyright (C) 2009-2013 Grame
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.
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.
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.
20 #include <assert.h>
21 #include <stdarg.h>
23 #include "JackNetInterface.h"
24 #include "JackAudioAdapterInterface.h"
26 #ifdef __cplusplus
27 extern "C"
29 #endif
31 // NetJack common API
33 #define MASTER_NAME_SIZE 256
35 enum JackNetEncoder {
37 JackFloatEncoder = 0,
38 JackIntEncoder = 1,
39 JackCeltEncoder = 2,
40 JackOpusEncoder = 3
43 typedef struct {
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
55 } jack_slave_t;
57 typedef struct {
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;
69 } jack_master_t;
71 // NetJack slave API
73 typedef struct _jack_net_slave jack_net_slave_t;
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);
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);
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);
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);
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);
106 // NetJack master API
108 typedef struct _jack_net_master jack_net_master_t;
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);
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);
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);
119 // NetJack adapter API
121 typedef struct _jack_adapter jack_adapter_t;
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);
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);
134 #define LOG_LEVEL_INFO 1
135 #define LOG_LEVEL_ERROR 2
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, ...);
141 #ifdef __cplusplus
143 #endif
145 namespace Jack
148 struct JackNetExtMaster : public JackNetMasterInterface {
150 jack_master_t fRequest;
152 JackRingBuffer** fRingBuffer;
154 JackNetExtMaster(const char* ip,
155 int port,
156 jack_master_t* request)
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;
171 virtual ~JackNetExtMaster()
173 if (fRingBuffer) {
174 for (int i = 0; i < fParams.fReturnAudioChannels; i++) {
175 delete fRingBuffer[i];
177 delete [] fRingBuffer;
181 int Open(jack_slave_t* result)
183 // Check buffer_size
184 if (fRequest.buffer_size == 0) {
185 jack_error("Incorrect buffer_size...");
186 return -1;
188 // Check sample_rate
189 if (fRequest.sample_rate == 0) {
190 jack_error("Incorrect sample_rate...");
191 return -1;
194 // Init socket API (win32)
195 if (SocketAPIInit() < 0) {
196 jack_error("Can't init Socket API, exiting...");
197 return -1;
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;
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;
213 // Join multicast group
214 if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
215 jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
218 // Local loop
219 if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
220 jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
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));
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;
235 session_params_t net_params;
236 rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
237 SessionParamsNToH(&net_params, &fParams);
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;
247 if (rx_bytes == sizeof(session_params_t)) {
248 switch (GetPacketType(&fParams)) {
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;
258 jack_info("Waiting for a slave...");
259 break;
261 case KILL_MASTER:
262 break;
264 default:
265 break;
269 while (fRunning && (--try_count > 0));
271 if (try_count == 0) {
272 jack_error("Time out error in connect");
273 return -1;
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;
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);
291 return 0;
293 error:
294 fSocket.Close();
295 return -1;
298 int InitMaster(jack_slave_t* result)
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;
306 // Settings
307 fSocket.GetName(fParams.fMasterNetName);
308 fParams.fID = 1;
309 fParams.fPeriodSize = fRequest.buffer_size;
310 fParams.fSampleRate = fRequest.sample_rate;
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);
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;
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);
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;
344 // Close request socket
345 fSocket.Close();
347 /// Network init
348 if (!JackNetMasterInterface::Init()) {
349 return -1;
352 // Set global parameters
353 if (!SetParams()) {
354 return -1;
357 return 0;
360 int Close()
362 fSocket.Close();
363 return 0;
366 void UseRingBuffer(int audio_input, float** audio_input_buffer, int write, int read)
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);
377 int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames)
379 try {
381 // frames = -1 means : entire buffer
382 if (frames < 0) frames = fParams.fPeriodSize;
384 int read_frames = 0;
385 assert(audio_input == fParams.fReturnAudioChannels);
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]);
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]);
397 int res1 = SyncRecv();
398 switch (res1) {
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);
405 UseRingBuffer(audio_input, audio_input_buffer, fParams.fPeriodSize, frames);
406 return res1;
408 case SOCKET_ERROR:
409 return res1;
411 case SYNC_PACKET_ERROR:
412 // since sync packet is incorrect, don't decode it and continue with data
413 break;
415 default:
416 // decode sync
417 DecodeSyncPacket(read_frames);
418 break;
421 int res2 = DataRecv();
422 UseRingBuffer(audio_input, audio_input_buffer, read_frames, frames);
423 return res2;
425 } catch (JackNetException& e) {
426 jack_error(e.what());
427 return -1;
431 int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames)
433 try {
435 // frames = -1 means : entire buffer
436 if (frames < 0) frames = fParams.fPeriodSize;
438 assert(audio_output == fParams.fSendAudioChannels);
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]);
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]);
450 EncodeSyncPacket(frames);
452 // send sync
453 if (SyncSend() == SOCKET_ERROR) {
454 return SOCKET_ERROR;
457 // send data
458 if (DataSend() == SOCKET_ERROR) {
459 return SOCKET_ERROR;
461 return 0;
463 } catch (JackNetException& e) {
464 jack_error(e.what());
465 return -1;
469 // Transport
470 void EncodeTransportData()
473 void DecodeTransportData()
478 struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterface {
480 // Data buffers
481 float** fAudioCaptureBuffer;
482 float** fAudioPlaybackBuffer;
484 JackMidiBuffer** fMidiCaptureBuffer;
485 JackMidiBuffer** fMidiPlaybackBuffer;
487 JackThread fThread;
489 JackNetSlaveProcessCallback fProcessCallback;
490 void* fProcessArg;
492 JackNetSlaveShutdownCallback fShutdownCallback;
493 void* fShutdownArg;
495 JackNetSlaveRestartCallback fRestartCallback;
496 void* fRestartArg;
498 JackNetSlaveErrorCallback fErrorCallback;
499 void* fErrorArg;
501 JackNetSlaveBufferSizeCallback fBufferSizeCallback;
502 void* fBufferSizeArg;
504 JackNetSlaveSampleRateCallback fSampleRateCallback;
505 void* fSampleRateArg;
507 int fConnectTimeOut;
508 int fFrames;
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)
522 char host_name[JACK_CLIENT_NAME_SIZE + 1];
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;
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);
544 // Set the socket parameters
545 fSocket.SetPort(port);
546 fSocket.SetAddress(fMulticastIP, port);
548 fAudioCaptureBuffer = NULL;
549 fAudioPlaybackBuffer = NULL;
550 fMidiCaptureBuffer = NULL;
551 fMidiPlaybackBuffer = NULL;
554 virtual ~JackNetExtSlave()
557 void AllocPorts()
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]);
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]);
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]);
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]);
597 void FreePorts()
599 if (fAudioCaptureBuffer) {
600 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
601 delete[] fAudioCaptureBuffer[audio_port_index];
603 delete[] fAudioCaptureBuffer;
604 fAudioCaptureBuffer = NULL;
607 if (fMidiCaptureBuffer) {
608 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
609 delete[] fMidiCaptureBuffer[midi_port_index];
611 delete[] fMidiCaptureBuffer;
612 fMidiCaptureBuffer = NULL;
615 if (fAudioPlaybackBuffer) {
616 for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
617 delete[] fAudioPlaybackBuffer[audio_port_index];
619 delete[] fAudioPlaybackBuffer;
620 fAudioPlaybackBuffer = NULL;
623 if (fMidiPlaybackBuffer) {
624 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
625 delete[] (fMidiPlaybackBuffer[midi_port_index]);
627 delete[] fMidiPlaybackBuffer;
628 fMidiPlaybackBuffer = NULL;
632 int Open(jack_master_t* result)
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;
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;
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;
655 if ((fParams.fSampleEncoder == JackOpusEncoder) && (fParams.fKBps == 0)) {
656 jack_error("Opus encoder with 0 for kps...");
657 return -1;
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;
666 // Init network connection
667 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
668 jack_error("Initing network fails...");
669 return -1;
672 // Finish connection...
673 if (!JackNetSlaveInterface::InitRendering()) {
674 jack_error("Starting network fails...");
675 return -1;
678 // Then set global parameters
679 if (!SetParams()) {
680 jack_error("SetParams error...");
681 return -1;
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);
695 // By default fFrames is fPeriodSize
696 fFrames = fParams.fPeriodSize;
698 SessionParamsDisplay(&fParams);
700 AllocPorts();
701 return 0;
704 int Restart()
706 // Do it until client possibly decides to stop trying to connect...
707 while (true) {
709 // If restart cb is set, then call it
710 if (fRestartCallback) {
711 if (fRestartCallback(fRestartArg) != 0) {
712 return -1;
714 // Otherwise if shutdown cb is set, then call it
715 } else if (fShutdownCallback) {
716 fShutdownCallback(fShutdownArg);
719 // Init network connection
720 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
721 jack_error("Initing network fails after time_out, retry...");
722 } else {
723 break;
727 // Finish connection
728 if (!JackNetSlaveInterface::InitRendering()) {
729 jack_error("Starting network fails...");
730 return -1;
733 // Then set global parameters
734 if (!SetParams()) {
735 jack_error("SetParams error...");
736 return -1;
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;
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;
754 AllocPorts();
755 return 0;
758 int Close()
760 fSocket.Close();
761 FreePorts();
762 return 0;
765 // Transport
766 void EncodeTransportData()
769 void DecodeTransportData()
772 bool Init()
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);
780 return (fThread.AcquireSelfRealTime(80) == 0); // TODO: get a value from the server
783 bool IsRunning()
785 return (fThread.GetStatus() == JackThread::kRunning);
788 bool Execute()
790 try {
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.
796 DummyProcess();
797 // keep running even in case of error
798 while (fThread.GetStatus() == JackThread::kRunning) {
799 if (Process() == SOCKET_ERROR) {
800 return false;
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;
820 int Read()
822 // receive sync (launch the cycle)
823 switch (SyncRecv()) {
825 case SOCKET_ERROR:
826 return SOCKET_ERROR;
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);
833 break;
835 default:
836 // decode sync
837 DecodeSyncPacket(fFrames);
838 break;
841 int res = DataRecv();
842 if (res == DATA_PACKET_ERROR && fErrorCallback) {
843 fErrorCallback(DATA_PACKET_ERROR, fErrorArg);
845 return res;
848 int Write()
850 EncodeSyncPacket(fFrames);
852 if (SyncSend() == SOCKET_ERROR) {
853 return SOCKET_ERROR;
856 return DataSend();
859 void DummyProcess()
861 // First cycle with INT_MAX time out
862 SetPacketTimeOut(INT_MAX);
864 // One cycle
865 Process();
867 // Then use PACKET_TIMEOUT * fParams.fNetworkLatency for next cycles
868 SetPacketTimeOut(std::max(int(PACKET_TIMEOUT), int(PACKET_TIMEOUT * fParams.fNetworkLatency)));
871 int Process()
873 // Read data from the network, throw JackNetException in case of network error...
874 if (Read() == SOCKET_ERROR) {
875 return SOCKET_ERROR;
878 if (fFrames < 0) fFrames = fParams.fPeriodSize;
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);
891 // Then write data to network, throw JackNetException in case of network error...
892 if (Write() == SOCKET_ERROR) {
893 return SOCKET_ERROR;
896 return 0;
899 int Start()
901 return (fProcessCallback == 0) ? -1 : fThread.StartSync();
904 int Stop()
906 return (fProcessCallback == 0) ? -1 : fThread.Kill();
909 // Callback
910 int SetProcessCallback(JackNetSlaveProcessCallback net_callback, void *arg)
912 if (fThread.GetStatus() == JackThread::kRunning) {
913 return -1;
914 } else {
915 fProcessCallback = net_callback;
916 fProcessArg = arg;
917 return 0;
921 int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback, void *arg)
923 if (fThread.GetStatus() == JackThread::kRunning) {
924 return -1;
925 } else {
926 fShutdownCallback = shutdown_callback;
927 fShutdownArg = arg;
928 return 0;
932 int SetRestartCallback(JackNetSlaveRestartCallback restart_callback, void *arg)
934 if (fThread.GetStatus() == JackThread::kRunning) {
935 return -1;
936 } else {
937 fRestartCallback = restart_callback;
938 fRestartArg = arg;
939 return 0;
943 int SetErrorCallback(JackNetSlaveErrorCallback error_callback, void *arg)
945 if (fThread.GetStatus() == JackThread::kRunning) {
946 return -1;
947 } else {
948 fErrorCallback = error_callback;
949 fErrorArg = arg;
950 return 0;
954 int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
956 if (fThread.GetStatus() == JackThread::kRunning) {
957 return -1;
958 } else {
959 fBufferSizeCallback = bufsize_callback;
960 fBufferSizeArg = arg;
961 return 0;
965 int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
967 if (fThread.GetStatus() == JackThread::kRunning) {
968 return -1;
969 } else {
970 fSampleRateCallback = samplerate_callback;
971 fSampleRateArg = arg;
972 return 0;
978 struct JackNetAdapter : public JackAudioAdapterInterface {
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)
987 fCaptureChannels = input;
988 fPlaybackChannels = output;
989 Create();
992 void Create()
994 //ringbuffers
996 if (fCaptureChannels > 0) {
997 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
999 if (fPlaybackChannels > 0) {
1000 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
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;
1010 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
1013 for (int i = 0; i < fCaptureChannels; i++ ) {
1014 fCaptureRingBuffer[i] = new JackResampler();
1015 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
1017 for (int i = 0; i < fPlaybackChannels; i++ ) {
1018 fPlaybackRingBuffer[i] = new JackResampler();
1019 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
1022 if (fCaptureChannels > 0) {
1023 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
1025 if (fPlaybackChannels > 0) {
1026 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
1030 virtual ~JackNetAdapter()
1032 Destroy();
1035 void Flush()
1037 for (int i = 0; i < fCaptureChannels; i++ ) {
1038 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
1040 for (int i = 0; i < fPlaybackChannels; i++ ) {
1041 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
1048 } // end of namespace
1050 using namespace Jack;
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)
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;
1063 LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net)
1065 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1066 slave->Close();
1067 delete slave;
1068 return 0;
1071 LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg)
1073 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1074 return slave->SetProcessCallback(net_callback, arg);
1077 LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net)
1079 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1080 return slave->Start();
1083 LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net)
1085 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1086 return slave->Stop();
1089 LIB_EXPORT int jack_net_slave_is_active(jack_net_slave_t* net)
1091 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1092 return slave->IsRunning();
1095 LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
1097 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1098 return slave->SetBufferSizeCallback(bufsize_callback, arg);
1101 LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
1103 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1104 return slave->SetSampleRateCallback(samplerate_callback, arg);
1107 LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg)
1109 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1110 return slave->SetShutdownCallback(shutdown_callback, arg);
1113 LIB_EXPORT int jack_set_net_slave_restart_callback(jack_net_slave_t *net, JackNetSlaveRestartCallback restart_callback, void *arg)
1115 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1116 return slave->SetRestartCallback(restart_callback, arg);
1119 LIB_EXPORT int jack_set_net_slave_error_callback(jack_net_slave_t *net, JackNetSlaveErrorCallback error_callback, void *arg)
1121 JackNetExtSlave* slave = (JackNetExtSlave*)net;
1122 return slave->SetErrorCallback(error_callback, arg);
1125 // Master API
1127 LIB_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, jack_master_t* request, jack_slave_t* result)
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;
1138 LIB_EXPORT int jack_net_master_close(jack_net_master_t* net)
1140 JackNetExtMaster* master = (JackNetExtMaster*)net;
1141 master->Close();
1142 delete master;
1143 return 0;
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)
1148 JackNetExtMaster* master = (JackNetExtMaster*)net;
1149 return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer, -1);
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)
1154 JackNetExtMaster* master = (JackNetExtMaster*)net;
1155 return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer, -1);
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)
1160 JackNetExtMaster* master = (JackNetExtMaster*)net;
1161 return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer, frames);
1164 LIB_EXPORT int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames)
1166 JackNetExtMaster* master = (JackNetExtMaster*)net;
1167 return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer, frames);
1170 // Adapter API
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)
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;
1185 LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter)
1187 delete((JackNetAdapter*)adapter);
1188 return 0;
1191 LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter)
1193 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1194 slave->Flush();
1197 LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1199 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1200 return slave->PushAndPull(input, output, frames);
1203 LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1205 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1206 return slave->PullAndPush(input, output, frames);
1209 static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap)
1211 static const char* netjack_log = getenv("JACK_NETJACK_LOG");
1212 static bool is_netjack_log = (netjack_log) ? atoi(netjack_log) : 0;
1214 if (is_netjack_log) {
1215 char buffer[300];
1216 size_t len;
1218 if (prefix != NULL) {
1219 len = strlen(prefix);
1220 memcpy(buffer, prefix, len);
1221 } else {
1222 len = 0;
1225 vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap);
1226 printf("%s", buffer);
1227 printf("\n");
1231 LIB_EXPORT void jack_error(const char *fmt, ...)
1233 va_list ap;
1234 va_start(ap, fmt);
1235 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1236 va_end(ap);
1239 LIB_EXPORT void jack_info(const char *fmt, ...)
1241 va_list ap;
1242 va_start(ap, fmt);
1243 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1244 va_end(ap);
1247 LIB_EXPORT void jack_log(const char *fmt, ...)
1249 va_list ap;
1250 va_start(ap, fmt);
1251 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1252 va_end(ap);