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.
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
];
71 typedef struct _jack_net_slave jack_net_slave_t
;
73 typedef int (* JackNetSlaveProcessCallback
) (jack_nframes_t buffer_size
,
75 float** audio_input_buffer
,
77 void** midi_input_buffer
,
79 float** audio_output_buffer
,
81 void** midi_output_buffer
,
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
);
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
, ...);
138 struct JackNetExtMaster
: public JackNetMasterInterface
{
141 float** fAudioCaptureBuffer
;
142 float** fAudioPlaybackBuffer
;
144 JackMidiBuffer
** fMidiCaptureBuffer
;
145 JackMidiBuffer
** fMidiPlaybackBuffer
;
147 jack_master_t fRequest
;
149 JackNetExtMaster(const char* ip
,
152 jack_master_t
* request
)
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...");
180 if (fSocket
.NewSocket() == SOCKET_ERROR
) {
181 jack_error("Can't create the network management input socket : %s", StrError(NET_ERROR_CODE
));
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
));
192 // Join multicast group
193 if (fSocket
.JoinMCastGroup(fMulticastIP
) == SOCKET_ERROR
) {
194 jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE
));
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
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" );
225 if (rx_bytes
== sizeof(session_params_t
)) {
226 switch (GetPacketType(&fParams
)) {
228 case SLAVE_AVAILABLE
:
229 if (InitMaster(result
) == 0) {
230 SessionParamsDisplay(&fParams
);
233 jack_error("Can't init new net master...");
236 jack_info("Waiting for a slave...");
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
;
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
);
272 fSocket
.GetName(fParams
.fMasterNetName
);
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...");
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
);
293 if (fRequest
.audio_output
== -1) {
294 if (fParams
.fReturnAudioChannels
== -1) {
295 jack_error("Error : master and slave use -1 for wanted outputs...");
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
);
309 // Close request socket
313 if (!JackNetMasterInterface::Init()) {
317 // Set global parameters
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
]);
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
)
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
]);
416 int res
= SyncRecv();
417 if ((res
== 0) || (res
== SOCKET_ERROR
)) {
424 } catch (JackNetException
& e
) {
425 jack_error("Connection lost.");
430 int Write(int audio_output
, float** audio_output_buffer
, int midi_output
, void** midi_output_buffer
)
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"
449 if (SyncSend() == SOCKET_ERROR
) {
454 if (DataSend() == SOCKET_ERROR
) {
459 jack_info("Connection is not synched, skip cycle...");
464 } catch (JackNetException
& e
) {
465 jack_error("Connection lost.");
471 void EncodeTransportData()
474 void DecodeTransportData()
479 struct JackNetExtSlave
: public JackNetSlaveInterface
, public JackRunnableInterface
{
483 JackNetSlaveProcessCallback fProcessCallback
;
486 JackNetSlaveShutdownCallback fShutdownCallback
;
489 JackNetSlaveBufferSizeCallback fBufferSizeCallback
;
490 void* fBufferSizeArg
;
492 JackNetSlaveSampleRateCallback fSampleRateCallback
;
493 void* fSampleRateArg
;
496 float** fAudioCaptureBuffer
;
497 float** fAudioPlaybackBuffer
;
499 JackMidiBuffer
** fMidiCaptureBuffer
;
500 JackMidiBuffer
** fMidiPlaybackBuffer
;
504 JackNetExtSlave(const char* ip
,
507 jack_slave_t
* request
)
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...");
555 if (fParams
.fNetworkLatency
> NETWORK_MAX_LATENCY
) {
556 jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY
);
560 // Init network connection
561 if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut
)) {
562 jack_error("Initing network fails...");
566 // Finish connection...
567 if (!JackNetSlaveInterface::InitRendering()) {
568 jack_error("Starting network fails...");
572 // Then set global parameters
574 jack_error("SetParams error...");
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
);
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...");
607 if (!JackNetSlaveInterface::InitRendering()) {
608 jack_error("Starting network fails...");
612 // Then set global parameters
614 jack_error("SetParams error...");
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
);
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
]);
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
;
702 void EncodeTransportData()
705 void DecodeTransportData()
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
722 // Keep running even in case of error
723 while (fThread
.GetStatus() == JackThread::kRunning
) {
724 if (Process() == SOCKET_ERROR
) {
729 } catch (JackNetException
& e
) {
730 // Otherwise just restart...
732 jack_info("NetSlave is restarted");
733 fThread
.DropRealTime();
734 fThread
.SetStatus(JackThread::kIniting
);
736 if (Restart() == 0 && Init()) {
737 fThread
.SetStatus(JackThread::kRunning
);
747 //receive sync (launch the cycle)
748 if (SyncRecv() == SOCKET_ERROR
) {
760 if (SyncSend() == SOCKET_ERROR
) {
769 // Read data from the network, throw JackNetException in case of network error...
770 if (Read() == SOCKET_ERROR
) {
774 fProcessCallback(fParams
.fPeriodSize
,
775 fParams
.fSendAudioChannels
,
777 fParams
.fSendMidiChannels
,
778 (void**)fMidiCaptureBuffer
,
779 fParams
.fReturnAudioChannels
,
780 fAudioPlaybackBuffer
,
781 fParams
.fReturnMidiChannels
,
782 (void**)fMidiPlaybackBuffer
,
785 // Then write data to network, throw JackNetException in case of network error...
786 if (Write() == SOCKET_ERROR
) {
795 return (fProcessCallback
== 0) ? -1 : fThread
.StartSync();
800 return (fProcessCallback
== 0) ? -1 : fThread
.Kill();
804 int SetProcessCallback(JackNetSlaveProcessCallback net_callback
, void *arg
)
806 if (fThread
.GetStatus() == JackThread::kRunning
) {
809 fProcessCallback
= net_callback
;
815 int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback
, void *arg
)
817 if (fThread
.GetStatus() == JackThread::kRunning
) {
820 fShutdownCallback
= shutdown_callback
;
826 int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback
, void *arg
)
828 if (fThread
.GetStatus() == JackThread::kRunning
) {
831 fBufferSizeCallback
= bufsize_callback
;
832 fBufferSizeArg
= arg
;
837 int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback
, void *arg
)
839 if (fThread
.GetStatus() == JackThread::kRunning
) {
842 fSampleRateCallback
= samplerate_callback
;
843 fSampleRateArg
= arg
;
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
;
868 if (fCaptureChannels
> 0) {
869 fCaptureRingBuffer
= new JackResampler
*[fCaptureChannels
];
871 if (fPlaybackChannels
> 0) {
872 fPlaybackRingBuffer
= new JackResampler
*[fPlaybackChannels
];
876 AdaptRingBufferSize();
877 jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize
);
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()
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
;
935 LIB_EXPORT
int jack_net_slave_close(jack_net_slave_t
* net
)
937 JackNetExtSlave
* slave
= (JackNetExtSlave
*)net
;
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
);
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
;
992 LIB_EXPORT
int jack_net_master_close(jack_net_master_t
* net
)
994 JackNetExtMaster
* master
= (JackNetExtMaster
*)net
;
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
);
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
)
1021 return (jack_adapter_t
*)new JackNetAdapter(input
, output
, host_buffer_size
, host_sample_rate
, adapted_buffer_size
, adapted_sample_rate
);
1027 LIB_EXPORT
int jack_destroy_adapter(jack_adapter_t
* adapter
)
1029 delete((JackNetAdapter
*)adapter
);
1033 LIB_EXPORT
void jack_flush_adapter(jack_adapter_t
* adapter
)
1035 JackNetAdapter
* slave
= (JackNetAdapter
*)adapter
;
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
) {
1060 if (prefix
!= NULL
) {
1061 len
= strlen(prefix
);
1062 memcpy(buffer
, prefix
, len
);
1067 vsnprintf(buffer
+ len
, sizeof(buffer
) - len
, fmt
, ap
);
1068 printf("%s", buffer
);
1073 LIB_EXPORT
void jack_error(const char *fmt
, ...)
1077 jack_format_and_log(LOG_LEVEL_INFO
, "Jack: ", fmt
, ap
);
1081 LIB_EXPORT
void jack_info(const char *fmt
, ...)
1085 jack_format_and_log(LOG_LEVEL_INFO
, "Jack: ", fmt
, ap
);
1089 LIB_EXPORT
void jack_log(const char *fmt
, ...)
1093 jack_format_and_log(LOG_LEVEL_INFO
, "Jack: ", fmt
, ap
);