Correct netjack2 components help.
[jack2.git] / common / JackNetAPI.cpp
blobcf670d7a88b346d470bd4074f619a9ae00b12a7e
1 /*
2 Copyright (C) 2009-2011 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 JackMaxEncoder = 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];
67 } jack_master_t;
69 // NetJack slave API
71 typedef struct _jack_net_slave jack_net_slave_t;
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);
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);
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);
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);
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);
99 // NetJack master API
101 typedef struct _jack_net_master jack_net_master_t;
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);
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);
109 // NetJack adapter API
111 typedef struct _jack_adapter jack_adapter_t;
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);
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);
124 #define LOG_LEVEL_INFO 1
125 #define LOG_LEVEL_ERROR 2
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, ...);
131 #ifdef __cplusplus
133 #endif
135 namespace Jack
138 struct JackNetExtMaster : public JackNetMasterInterface {
140 // Data buffers
141 float** fAudioCaptureBuffer;
142 float** fAudioPlaybackBuffer;
144 JackMidiBuffer** fMidiCaptureBuffer;
145 JackMidiBuffer** fMidiPlaybackBuffer;
147 jack_master_t fRequest;
149 JackNetExtMaster(const char* ip,
150 int port,
151 const char* name,
152 jack_master_t* request)
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;
168 virtual ~JackNetExtMaster()
171 int Open(jack_slave_t* result)
173 // Init socket API (win32)
174 if (SocketAPIInit() < 0) {
175 jack_error("Can't init Socket API, exiting...");
176 return -1;
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;
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;
192 // Join multicast group
193 if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
194 jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
197 // Local loop
198 if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
199 jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
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));
207 // Main loop, wait for data, deal with it and wait again
208 int attempt = 0;
209 int rx_bytes = 0;
213 session_params_t net_params;
214 rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
215 SessionParamsNToH(&net_params, &fParams);
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;
225 if (rx_bytes == sizeof(session_params_t )) {
226 switch (GetPacketType(&fParams)) {
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;
236 jack_info("Waiting for a slave...");
237 break;
239 case KILL_MASTER:
240 break;
242 default:
243 break;
247 while (fRunning);
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;
258 error:
259 fSocket.Close();
260 return -1;
263 int InitMaster(jack_slave_t* result)
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;
271 // Settings
272 fSocket.GetName(fParams.fMasterNetName);
273 fParams.fID = 1;
274 fParams.fPeriodSize = fRequest.buffer_size;
275 fParams.fSampleRate = fRequest.sample_rate;
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);
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;
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);
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;
309 // Close request socket
310 fSocket.Close();
312 /// Network init
313 if (!JackNetMasterInterface::Init()) {
314 return -1;
317 // Set global parameters
318 if (!SetParams()) {
319 return -1;
322 AllocPorts();
323 return 0;
326 int Close()
328 fSocket.Close();
329 FreePorts();
330 return 0;
333 void AllocPorts()
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]);
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]);
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]);
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]);
369 void FreePorts()
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;
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;
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;
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;
400 int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer)
403 try {
405 assert(audio_input == fParams.fReturnAudioChannels);
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]);
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]);
415 //receive sync
416 int res = SyncRecv();
417 if ((res == 0) || (res == SOCKET_ERROR)) {
418 return res;
421 DecodeSyncPacket();
422 return DataRecv();
424 } catch (JackNetException& e) {
425 jack_error("Connection lost.");
426 return -1;
430 int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer)
432 try {
434 assert(audio_output == fParams.fSendAudioChannels);
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]);
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]);
445 if (IsSynched()) { // only send if connection is "synched"
447 EncodeSyncPacket();
449 if (SyncSend() == SOCKET_ERROR) {
450 return SOCKET_ERROR;
453 //send data
454 if (DataSend() == SOCKET_ERROR) {
455 return SOCKET_ERROR;
458 } else {
459 jack_info("Connection is not synched, skip cycle...");
462 return 0;
464 } catch (JackNetException& e) {
465 jack_error("Connection lost.");
466 return -1;
470 // Transport
471 void EncodeTransportData()
474 void DecodeTransportData()
479 struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterface {
481 JackThread fThread;
483 JackNetSlaveProcessCallback fProcessCallback;
484 void* fProcessArg;
486 JackNetSlaveShutdownCallback fShutdownCallback;
487 void* fShutdownArg;
489 JackNetSlaveBufferSizeCallback fBufferSizeCallback;
490 void* fBufferSizeArg;
492 JackNetSlaveSampleRateCallback fSampleRateCallback;
493 void* fSampleRateArg;
495 //sample buffers
496 float** fAudioCaptureBuffer;
497 float** fAudioPlaybackBuffer;
499 JackMidiBuffer** fMidiCaptureBuffer;
500 JackMidiBuffer** fMidiPlaybackBuffer;
502 int fConnectTimeOut;
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)
516 char host_name[JACK_CLIENT_NAME_SIZE];
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;
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);
538 // Set the socket parameters
539 fSocket.SetPort(port);
540 fSocket.SetAddress(fMulticastIP, port);
543 virtual ~JackNetExtSlave()
546 int Open(jack_master_t* result)
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;
554 // Check latency
555 if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
556 jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY);
557 return -1;
560 // Init network connection
561 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
562 jack_error("Initing network fails...");
563 return -1;
566 // Finish connection...
567 if (!JackNetSlaveInterface::InitRendering()) {
568 jack_error("Starting network fails...");
569 return -1;
572 // Then set global parameters
573 if (!SetParams()) {
574 jack_error("SetParams error...");
575 return -1;
578 // Set result
579 if (result != NULL) {
580 result->buffer_size = fParams.fPeriodSize;
581 result->sample_rate = fParams.fSampleRate;
582 result->audio_input = fParams.fSendAudioChannels;
583 result->audio_output = fParams.fReturnAudioChannels;
584 result->midi_input = fParams.fSendMidiChannels;
585 result->midi_output = fParams.fReturnMidiChannels;
586 strcpy(result->master_name, fParams.fMasterNetName);
589 AllocPorts();
590 return 0;
593 int Restart()
595 // If shutdown cb is set, then call it
596 if (fShutdownCallback) {
597 fShutdownCallback(fShutdownArg);
600 // Init network connection
601 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
602 jack_error("Initing network fails...");
603 return -1;
606 // Finish connection
607 if (!JackNetSlaveInterface::InitRendering()) {
608 jack_error("Starting network fails...");
609 return -1;
612 // Then set global parameters
613 if (!SetParams()) {
614 jack_error("SetParams error...");
615 return -1;
618 // We need to notify possibly new buffer size and sample rate (see Execute)
619 if (fBufferSizeCallback) {
620 fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg);
623 if (fSampleRateCallback) {
624 fSampleRateCallback(fParams.fSampleRate, fSampleRateArg);
627 AllocPorts();
628 return 0;
631 int Close()
633 fSocket.Close();
634 FreePorts();
635 return 0;
638 void AllocPorts()
640 // Set buffers
641 fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels];
642 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
643 fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize];
644 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]);
647 fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels];
648 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
649 fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
650 fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]);
653 fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels];
654 for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
655 fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize];
656 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]);
659 fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels];
660 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
661 fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
662 fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]);
666 void FreePorts()
668 if (fAudioCaptureBuffer) {
669 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
670 delete[] fAudioCaptureBuffer[audio_port_index];
672 delete[] fAudioCaptureBuffer;
673 fAudioCaptureBuffer = NULL;
676 if (fMidiCaptureBuffer) {
677 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
678 delete[] (fMidiCaptureBuffer[midi_port_index]);
680 delete[] fMidiCaptureBuffer;
681 fMidiCaptureBuffer = NULL;
684 if (fAudioPlaybackBuffer) {
685 for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
686 delete[] fAudioPlaybackBuffer[audio_port_index];
688 delete[] fAudioPlaybackBuffer;
689 fAudioPlaybackBuffer = NULL;
692 if (fMidiPlaybackBuffer) {
693 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
694 delete[] fMidiPlaybackBuffer[midi_port_index];
696 delete[] fMidiPlaybackBuffer;
697 fMidiPlaybackBuffer = NULL;
701 // Transport
702 void EncodeTransportData()
705 void DecodeTransportData()
708 bool Init()
710 // Will do "something" on OSX only...
711 UInt64 period, constraint;
712 period = constraint = UInt64(1000000000.f * (float(fParams.fPeriodSize) / float(fParams.fSampleRate)));
713 UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize) * 1000;
714 fThread.SetParams(period, computation, constraint);
716 return (fThread.AcquireSelfRealTime(80) == 0); // TODO: get a value from the server
719 bool Execute()
721 try {
722 // Keep running even in case of error
723 while (fThread.GetStatus() == JackThread::kRunning) {
724 if (Process() == SOCKET_ERROR) {
725 return false;
728 return false;
729 } catch (JackNetException& e) {
730 // Otherwise just restart...
731 e.PrintMessage();
732 jack_info("NetSlave is restarted");
733 fThread.DropRealTime();
734 fThread.SetStatus(JackThread::kIniting);
735 FreePorts();
736 if (Restart() == 0 && Init()) {
737 fThread.SetStatus(JackThread::kRunning);
738 return true;
739 } else {
740 return false;
745 int Read()
747 //receive sync (launch the cycle)
748 if (SyncRecv() == SOCKET_ERROR) {
749 return SOCKET_ERROR;
752 DecodeSyncPacket();
753 return DataRecv();
756 int Write()
758 EncodeSyncPacket();
760 if (SyncSend() == SOCKET_ERROR) {
761 return SOCKET_ERROR;
764 return DataSend();
767 int Process()
769 // Read data from the network, throw JackNetException in case of network error...
770 if (Read() == SOCKET_ERROR) {
771 return SOCKET_ERROR;
774 fProcessCallback(fParams.fPeriodSize,
775 fParams.fSendAudioChannels,
776 fAudioCaptureBuffer,
777 fParams.fSendMidiChannels,
778 (void**)fMidiCaptureBuffer,
779 fParams.fReturnAudioChannels,
780 fAudioPlaybackBuffer,
781 fParams.fReturnMidiChannels,
782 (void**)fMidiPlaybackBuffer,
783 fProcessArg);
785 // Then write data to network, throw JackNetException in case of network error...
786 if (Write() == SOCKET_ERROR) {
787 return SOCKET_ERROR;
790 return 0;
793 int Start()
795 return (fProcessCallback == 0) ? -1 : fThread.StartSync();
798 int Stop()
800 return (fProcessCallback == 0) ? -1 : fThread.Kill();
803 // Callback
804 int SetProcessCallback(JackNetSlaveProcessCallback net_callback, void *arg)
806 if (fThread.GetStatus() == JackThread::kRunning) {
807 return -1;
808 } else {
809 fProcessCallback = net_callback;
810 fProcessArg = arg;
811 return 0;
815 int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback, void *arg)
817 if (fThread.GetStatus() == JackThread::kRunning) {
818 return -1;
819 } else {
820 fShutdownCallback = shutdown_callback;
821 fShutdownArg = arg;
822 return 0;
826 int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
828 if (fThread.GetStatus() == JackThread::kRunning) {
829 return -1;
830 } else {
831 fBufferSizeCallback = bufsize_callback;
832 fBufferSizeArg = arg;
833 return 0;
837 int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
839 if (fThread.GetStatus() == JackThread::kRunning) {
840 return -1;
841 } else {
842 fSampleRateCallback = samplerate_callback;
843 fSampleRateArg = arg;
844 return 0;
850 struct JackNetAdapter : public JackAudioAdapterInterface {
852 JackNetAdapter(int input, int output,
853 jack_nframes_t host_buffer_size,
854 jack_nframes_t host_sample_rate,
855 jack_nframes_t adapted_buffer_size,
856 jack_nframes_t adapted_sample_rate)
857 :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate)
859 fCaptureChannels = input;
860 fPlaybackChannels = output;
861 Create();
864 void Create()
866 //ringbuffers
868 if (fCaptureChannels > 0) {
869 fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
871 if (fPlaybackChannels > 0) {
872 fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
875 if (fAdaptative) {
876 AdaptRingBufferSize();
877 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
878 } else {
879 if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
880 fRingbufferCurSize = DEFAULT_RB_SIZE;
882 jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
885 for (int i = 0; i < fCaptureChannels; i++ ) {
886 fCaptureRingBuffer[i] = new JackResampler();
887 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
889 for (int i = 0; i < fPlaybackChannels; i++ ) {
890 fPlaybackRingBuffer[i] = new JackResampler();
891 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
894 if (fCaptureChannels > 0) {
895 jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
897 if (fPlaybackChannels > 0) {
898 jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
902 virtual ~JackNetAdapter()
904 Destroy();
907 void Flush()
909 for (int i = 0; i < fCaptureChannels; i++ ) {
910 fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
912 for (int i = 0; i < fPlaybackChannels; i++ ) {
913 fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
920 } // end of namespace
922 using namespace Jack;
924 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)
926 JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request);
927 if (slave->Open(result) == 0) {
928 return (jack_net_slave_t*)slave;
929 } else {
930 delete slave;
931 return NULL;
935 LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net)
937 JackNetExtSlave* slave = (JackNetExtSlave*)net;
938 slave->Close();
939 delete slave;
940 return 0;
943 LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg)
945 JackNetExtSlave* slave = (JackNetExtSlave*)net;
946 return slave->SetProcessCallback(net_callback, arg);
949 LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net)
951 JackNetExtSlave* slave = (JackNetExtSlave*)net;
952 return slave->Start();
955 LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net)
957 JackNetExtSlave* slave = (JackNetExtSlave*)net;
958 return slave->Stop();
961 LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
963 JackNetExtSlave* slave = (JackNetExtSlave*)net;
964 return slave->SetBufferSizeCallback(bufsize_callback, arg);
967 LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
969 JackNetExtSlave* slave = (JackNetExtSlave*)net;
970 return slave->SetSampleRateCallback(samplerate_callback, arg);
973 LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg)
975 JackNetExtSlave* slave = (JackNetExtSlave*)net;
976 return slave->SetShutdownCallback(shutdown_callback, arg);
979 // Master API
981 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)
983 JackNetExtMaster* master = new JackNetExtMaster(ip, port, name, request);
984 if (master->Open(result) == 0) {
985 return (jack_net_master_t*)master;
986 } else {
987 delete master;
988 return NULL;
992 LIB_EXPORT int jack_net_master_close(jack_net_master_t* net)
994 JackNetExtMaster* master = (JackNetExtMaster*)net;
995 master->Close();
996 delete master;
997 return 0;
1000 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)
1002 JackNetExtMaster* master = (JackNetExtMaster*)net;
1003 return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer);
1006 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)
1008 JackNetExtMaster* master = (JackNetExtMaster*)net;
1009 return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer);
1012 // Adapter API
1014 LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
1015 jack_nframes_t host_buffer_size,
1016 jack_nframes_t host_sample_rate,
1017 jack_nframes_t adapted_buffer_size,
1018 jack_nframes_t adapted_sample_rate)
1020 try {
1021 return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate);
1022 } catch (...) {
1023 return NULL;
1027 LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter)
1029 delete((JackNetAdapter*)adapter);
1030 return 0;
1033 LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter)
1035 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1036 slave->Flush();
1039 LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1041 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1042 return slave->PushAndPull(input, output, frames);
1045 LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
1047 JackNetAdapter* slave = (JackNetAdapter*)adapter;
1048 return slave->PullAndPush(input, output, frames);
1051 static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap)
1053 static const char* netjack_log = getenv("JACK_NETJACK_LOG");
1054 static bool is_netjack_log = (netjack_log) ? atoi(netjack_log) : 0;
1056 if (is_netjack_log) {
1057 char buffer[300];
1058 size_t len;
1060 if (prefix != NULL) {
1061 len = strlen(prefix);
1062 memcpy(buffer, prefix, len);
1063 } else {
1064 len = 0;
1067 vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap);
1068 printf("%s", buffer);
1069 printf("\n");
1073 LIB_EXPORT void jack_error(const char *fmt, ...)
1075 va_list ap;
1076 va_start(ap, fmt);
1077 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1078 va_end(ap);
1081 LIB_EXPORT void jack_info(const char *fmt, ...)
1083 va_list ap;
1084 va_start(ap, fmt);
1085 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1086 va_end(ap);
1089 LIB_EXPORT void jack_log(const char *fmt, ...)
1091 va_list ap;
1092 va_start(ap, fmt);
1093 jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
1094 va_end(ap);