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.
23 #include "JackNetInterface.h"
24 #include "JackAudioAdapterInterface.h"
33 #define MASTER_NAME_SIZE 256
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
63 jack_nframes_t buffer_size
;
64 jack_nframes_t sample_rate
;
65 char master_name
[MASTER_NAME_SIZE
];
73 typedef struct _jack_net_slave jack_net_slave_t
;
75 typedef int (* JackNetSlaveProcessCallback
) (jack_nframes_t buffer_size
,
77 float** audio_input_buffer
,
79 void** midi_input_buffer
,
81 float** audio_output_buffer
,
83 void** midi_output_buffer
,
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
, ...);
148 struct JackNetExtMaster
: public JackNetMasterInterface
{
150 jack_master_t fRequest
;
152 JackRingBuffer
** fRingBuffer
;
154 JackNetExtMaster(const char* ip
,
156 jack_master_t
* request
)
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
;
171 virtual ~JackNetExtMaster()
174 for (int i
= 0; i
< fParams
.fReturnAudioChannels
; i
++) {
175 delete fRingBuffer
[i
];
177 delete [] fRingBuffer
;
181 int Open(jack_slave_t
* result
)
184 if (fRequest
.buffer_size
== 0) {
185 jack_error("Incorrect buffer_size...");
189 if (fRequest
.sample_rate
== 0) {
190 jack_error("Incorrect sample_rate...");
194 // Init socket API (win32)
195 if (SocketAPIInit() < 0) {
196 jack_error("Can't init Socket API, exiting...");
201 if (fSocket
.NewSocket() == SOCKET_ERROR
) {
202 jack_error("Can't create the network manager input socket : %s", StrError(NET_ERROR_CODE
));
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
));
213 // Join multicast group
214 if (fSocket
.JoinMCastGroup(fMulticastIP
) == SOCKET_ERROR
) {
215 jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE
));
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
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" );
247 if (rx_bytes
== sizeof(session_params_t
)) {
248 switch (GetPacketType(&fParams
)) {
250 case SLAVE_AVAILABLE
:
251 if (InitMaster(result
) == 0) {
252 SessionParamsDisplay(&fParams
);
255 jack_error("Can't init new net master...");
258 jack_info("Waiting for a slave...");
269 while (fRunning
&& (--try_count
> 0));
271 if (try_count
== 0) {
272 jack_error("Time out error in connect");
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);
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
);
307 fSocket
.GetName(fParams
.fMasterNetName
);
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...");
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
);
328 if (fRequest
.audio_output
== -1) {
329 if (fParams
.fReturnAudioChannels
== -1) {
330 jack_error("Error : master and slave use -1 for wanted outputs...");
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
);
344 // Close request socket
348 if (!JackNetMasterInterface::Init()) {
352 // Set global parameters
366 void UseRingBuffer(int audio_input
, float** audio_input_buffer
, int write
, int read
)
368 // Possibly use ringbuffer...
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
)
381 // frames = -1 means : entire buffer
382 if (frames
< 0) frames
= fParams
.fPeriodSize
;
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();
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
);
411 case SYNC_PACKET_ERROR
:
412 // since sync packet is incorrect, don't decode it and continue with data
417 DecodeSyncPacket(read_frames
);
421 int res2
= DataRecv();
422 UseRingBuffer(audio_input
, audio_input_buffer
, read_frames
, frames
);
425 } catch (JackNetException
& e
) {
426 jack_error(e
.what());
431 int Write(int audio_output
, float** audio_output_buffer
, int midi_output
, void** midi_output_buffer
, int frames
)
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
);
453 if (SyncSend() == SOCKET_ERROR
) {
458 if (DataSend() == SOCKET_ERROR
) {
463 } catch (JackNetException
& e
) {
464 jack_error(e
.what());
470 void EncodeTransportData()
473 void DecodeTransportData()
478 struct JackNetExtSlave
: public JackNetSlaveInterface
, public JackRunnableInterface
{
481 float** fAudioCaptureBuffer
;
482 float** fAudioPlaybackBuffer
;
484 JackMidiBuffer
** fMidiCaptureBuffer
;
485 JackMidiBuffer
** fMidiPlaybackBuffer
;
489 JackNetSlaveProcessCallback fProcessCallback
;
492 JackNetSlaveShutdownCallback fShutdownCallback
;
495 JackNetSlaveRestartCallback fRestartCallback
;
498 JackNetSlaveErrorCallback fErrorCallback
;
501 JackNetSlaveBufferSizeCallback fBufferSizeCallback
;
502 void* fBufferSizeArg
;
504 JackNetSlaveSampleRateCallback fSampleRateCallback
;
505 void* fSampleRateArg
;
510 JackNetExtSlave(const char* ip
,
513 jack_slave_t
* request
)
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()
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
]);
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...");
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
);
649 // Check CELT encoder parameters
650 if ((fParams
.fSampleEncoder
== JackCeltEncoder
) && (fParams
.fKBps
== 0)) {
651 jack_error("CELT encoder with 0 for kps...");
655 if ((fParams
.fSampleEncoder
== JackOpusEncoder
) && (fParams
.fKBps
== 0)) {
656 jack_error("Opus encoder with 0 for kps...");
661 if (fParams
.fNetworkLatency
> NETWORK_MAX_LATENCY
) {
662 jack_error("Network latency is limited to %d", NETWORK_MAX_LATENCY
);
666 // Init network connection
667 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut
)) {
668 jack_error("Initing network fails...");
672 // Finish connection...
673 if (!JackNetSlaveInterface::InitRendering()) {
674 jack_error("Starting network fails...");
678 // Then set global parameters
680 jack_error("SetParams error...");
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
);
706 // Do it until client possibly decides to stop trying to connect...
709 // If restart cb is set, then call it
710 if (fRestartCallback
) {
711 if (fRestartCallback(fRestartArg
) != 0) {
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...");
728 if (!JackNetSlaveInterface::InitRendering()) {
729 jack_error("Starting network fails...");
733 // Then set global parameters
735 jack_error("SetParams error...");
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
);
747 if (fSampleRateCallback
) {
748 if (fSampleRateCallback(fParams
.fSampleRate
, fSampleRateArg
) != 0) {
749 jack_error("New sample rate = %d cannot be used...", fParams
.fSampleRate
);
766 void EncodeTransportData()
769 void DecodeTransportData()
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
785 return (fThread
.GetStatus() == JackThread::kRunning
);
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.
797 // keep running even in case of error
798 while (fThread
.GetStatus() == JackThread::kRunning
) {
799 if (Process() == SOCKET_ERROR
) {
804 } catch (JackNetException
& e
) {
805 // otherwise just restart...
807 jack_info("NetSlave is restarted");
808 fThread
.DropRealTime();
809 fThread
.SetStatus(JackThread::kIniting
);
811 if (Restart() == 0 && Init()) {
812 fThread
.SetStatus(JackThread::kRunning
);
822 // receive sync (launch the cycle)
823 switch (SyncRecv()) {
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
);
837 DecodeSyncPacket(fFrames
);
841 int res
= DataRecv();
842 if (res
== DATA_PACKET_ERROR
&& fErrorCallback
) {
843 fErrorCallback(DATA_PACKET_ERROR
, fErrorArg
);
850 EncodeSyncPacket(fFrames
);
852 if (SyncSend() == SOCKET_ERROR
) {
861 // First cycle with INT_MAX time out
862 SetPacketTimeOut(INT_MAX
);
867 // Then use PACKET_TIMEOUT * fParams.fNetworkLatency for next cycles
868 SetPacketTimeOut(std::max(int(PACKET_TIMEOUT
), int(PACKET_TIMEOUT
* fParams
.fNetworkLatency
)));
873 // Read data from the network, throw JackNetException in case of network error...
874 if (Read() == SOCKET_ERROR
) {
878 if (fFrames
< 0) fFrames
= fParams
.fPeriodSize
;
880 fProcessCallback(fFrames
,
881 fParams
.fSendAudioChannels
,
883 fParams
.fSendMidiChannels
,
884 (void**)fMidiCaptureBuffer
,
885 fParams
.fReturnAudioChannels
,
886 fAudioPlaybackBuffer
,
887 fParams
.fReturnMidiChannels
,
888 (void**)fMidiPlaybackBuffer
,
891 // Then write data to network, throw JackNetException in case of network error...
892 if (Write() == SOCKET_ERROR
) {
901 return (fProcessCallback
== 0) ? -1 : fThread
.StartSync();
906 return (fProcessCallback
== 0) ? -1 : fThread
.Kill();
910 int SetProcessCallback(JackNetSlaveProcessCallback net_callback
, void *arg
)
912 if (fThread
.GetStatus() == JackThread::kRunning
) {
915 fProcessCallback
= net_callback
;
921 int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback
, void *arg
)
923 if (fThread
.GetStatus() == JackThread::kRunning
) {
926 fShutdownCallback
= shutdown_callback
;
932 int SetRestartCallback(JackNetSlaveRestartCallback restart_callback
, void *arg
)
934 if (fThread
.GetStatus() == JackThread::kRunning
) {
937 fRestartCallback
= restart_callback
;
943 int SetErrorCallback(JackNetSlaveErrorCallback error_callback
, void *arg
)
945 if (fThread
.GetStatus() == JackThread::kRunning
) {
948 fErrorCallback
= error_callback
;
954 int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback
, void *arg
)
956 if (fThread
.GetStatus() == JackThread::kRunning
) {
959 fBufferSizeCallback
= bufsize_callback
;
960 fBufferSizeArg
= arg
;
965 int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback
, void *arg
)
967 if (fThread
.GetStatus() == JackThread::kRunning
) {
970 fSampleRateCallback
= samplerate_callback
;
971 fSampleRateArg
= arg
;
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
;
996 if (fCaptureChannels
> 0) {
997 fCaptureRingBuffer
= new JackResampler
*[fCaptureChannels
];
999 if (fPlaybackChannels
> 0) {
1000 fPlaybackRingBuffer
= new JackResampler
*[fPlaybackChannels
];
1004 AdaptRingBufferSize();
1005 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize
);
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()
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
;
1063 LIB_EXPORT
int jack_net_slave_close(jack_net_slave_t
* net
)
1065 JackNetExtSlave
* slave
= (JackNetExtSlave
*)net
;
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
);
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
;
1138 LIB_EXPORT
int jack_net_master_close(jack_net_master_t
* net
)
1140 JackNetExtMaster
* master
= (JackNetExtMaster
*)net
;
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
);
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
)
1179 return (jack_adapter_t
*)new JackNetAdapter(input
, output
, host_buffer_size
, host_sample_rate
, adapted_buffer_size
, adapted_sample_rate
);
1185 LIB_EXPORT
int jack_destroy_adapter(jack_adapter_t
* adapter
)
1187 delete((JackNetAdapter
*)adapter
);
1191 LIB_EXPORT
void jack_flush_adapter(jack_adapter_t
* adapter
)
1193 JackNetAdapter
* slave
= (JackNetAdapter
*)adapter
;
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
) {
1218 if (prefix
!= NULL
) {
1219 len
= strlen(prefix
);
1220 memcpy(buffer
, prefix
, len
);
1225 vsnprintf(buffer
+ len
, sizeof(buffer
) - len
, fmt
, ap
);
1226 printf("%s", buffer
);
1231 LIB_EXPORT
void jack_error(const char *fmt
, ...)
1235 jack_format_and_log(LOG_LEVEL_INFO
, "Jack: ", fmt
, ap
);
1239 LIB_EXPORT
void jack_info(const char *fmt
, ...)
1243 jack_format_and_log(LOG_LEVEL_INFO
, "Jack: ", fmt
, ap
);
1247 LIB_EXPORT
void jack_log(const char *fmt
, ...)
1251 jack_format_and_log(LOG_LEVEL_INFO
, "Jack: ", fmt
, ap
);