19 #include "JackNetAdapter.h"
20 #include "JackException.h"
21 #include "JackServerGlobals.h"
22 #include "JackEngineControl.h"
23 #include "JackArgParser.h"
28 JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate,
const JSList* params)
31 jack_log(
"JackNetAdapter::JackNetAdapter");
38 char multicast_ip[32];
40 GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
41 fSocket.GetName(fParams.fSlaveNetName);
42 fParams.fMtu = DEFAULT_MTU;
44 fParams.fTransportSync = 0;
46 int return_audio = -1;
47 fParams.fSendMidiChannels = 0;
48 fParams.fReturnMidiChannels = 0;
49 fParams.fSampleRate = sample_rate;
50 fParams.fPeriodSize = buffer_size;
51 fParams.fSlaveSyncMode = 1;
52 fParams.fNetworkLatency = 2;
53 fParams.fSampleEncoder = JackFloatEncoder;
54 fClient = jack_client;
57 const char* default_udp_port = getenv(
"JACK_NETJACK_PORT");
58 udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
60 const char* default_multicast_ip = getenv(
"JACK_NETJACK_MULTICAST");
61 if (default_multicast_ip) {
62 strcpy(multicast_ip, default_multicast_ip);
64 strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
70 for (node = params; node; node = jack_slist_next(node))
74 switch (param->character) {
76 assert(strlen(param->value.str) < 32);
77 strcpy(multicast_ip, param->value.str);
80 udp_port = param->value.ui;
83 fParams.fMtu = param->value.i;
86 send_audio = param->value.i;
89 return_audio = param->value.i;
92 strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE);
95 fParams.fTransportSync = param->value.ui;
99 if (param->value.i > 0) {
100 fParams.fSampleEncoder = JackCeltEncoder;
101 fParams.fKBps = param->value.i;
107 if (param->value.i > 0) {
108 fParams.fSampleEncoder = JackOpusEncoder;
109 fParams.fKBps = param->value.i;
114 fParams.fNetworkLatency = param->value.i;
115 if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
116 jack_error(
"Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
117 throw std::bad_alloc();
121 fQuality = param->value.ui;
124 fRingbufferCurSize = param->value.ui;
130 strcpy(fMulticastIP, multicast_ip);
133 fSocket.SetPort(udp_port);
134 fSocket.SetAddress(fMulticastIP, udp_port);
137 fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
140 fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
143 SetInputs(fParams.fSendAudioChannels);
144 SetOutputs(fParams.fReturnAudioChannels);
147 fSoftCaptureBuffer = NULL;
148 fSoftPlaybackBuffer = NULL;
151 JackNetAdapter::~JackNetAdapter()
153 jack_log(
"JackNetAdapter::~JackNetAdapter");
155 if (fSoftCaptureBuffer) {
156 for (
int port_index = 0; port_index < fCaptureChannels; port_index++) {
157 delete[] fSoftCaptureBuffer[port_index];
159 delete[] fSoftCaptureBuffer;
161 if (fSoftPlaybackBuffer) {
162 for (
int port_index = 0; port_index < fPlaybackChannels; port_index++) {
163 delete[] fSoftPlaybackBuffer[port_index];
165 delete[] fSoftPlaybackBuffer;
170 int JackNetAdapter::Open()
172 jack_info(
"NetAdapter started in %s mode %s Master's transport sync.",
173 (fParams.fSlaveSyncMode) ?
"sync" :
"async", (fParams.fTransportSync) ?
"with" :
"without");
175 if (fThread.StartSync() < 0) {
183 int JackNetAdapter::Close()
189 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
192 if (fThread.Kill() < 0) {
201 int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
203 JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
215 if (!JackNetSlaveInterface::Init()) {
216 jack_error(
"JackNetSlaveInterface::Init() error...");
227 if (fCaptureChannels > 0) {
228 fSoftCaptureBuffer =
new sample_t*[fCaptureChannels];
229 for (
int port_index = 0; port_index < fCaptureChannels; port_index++) {
230 fSoftCaptureBuffer[port_index] =
new sample_t[fParams.fPeriodSize];
231 fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
235 if (fPlaybackChannels > 0) {
236 fSoftPlaybackBuffer =
new sample_t*[fPlaybackChannels];
237 for (
int port_index = 0; port_index < fPlaybackChannels; port_index++) {
238 fSoftPlaybackBuffer[port_index] =
new sample_t[fParams.fPeriodSize];
239 fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
244 SetAdaptedBufferSize(fParams.fPeriodSize);
245 SetAdaptedSampleRate(fParams.fSampleRate);
248 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
250 if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
253 set_threaded_log_function();
257 SessionParamsDisplay(&fParams);
261 bool JackNetAdapter::Execute()
265 while (fThread.GetStatus() == JackThread::kRunning)
266 if (Process() == SOCKET_ERROR) {
275 fThread.DropSelfRealTime();
276 fThread.SetStatus(JackThread::kIniting);
278 fThread.SetStatus(JackThread::kRunning);
287 void JackNetAdapter::DecodeTransportData()
292 if (fSendTransportData.fNewState &&(fSendTransportData.fState !=
jack_transport_query(fClient, NULL))) {
293 switch (fSendTransportData.fState)
295 case JackTransportStopped :
297 jack_info(
"NetMaster : transport stops");
300 case JackTransportStarting :
303 jack_info(
"NetMaster : transport starts");
306 case JackTransportRolling :
310 jack_info(
"NetMaster : transport rolls");
316 void JackNetAdapter::EncodeTransportData()
320 bool conditional = 0;
322 if (refnum != fLastTimebaseMaster) {
325 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
326 jack_info(
"Sending a timebase master release request.");
329 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
330 jack_info(
"Sending a %s timebase master request.", (conditional) ?
"conditional" :
"non-conditional");
332 fLastTimebaseMaster = refnum;
334 fReturnTransportData.fTimebaseMaster = NO_CHANGE;
341 fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
342 (fReturnTransportData.fState != fSendTransportData.fState));
343 if (fReturnTransportData.fNewState) {
344 jack_info(
"Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
346 fLastTransportState = fReturnTransportData.fState;
350 int JackNetAdapter::Read()
354 if (SyncRecv() == SOCKET_ERROR) {
362 int JackNetAdapter::Write()
366 if (SyncSend() == SOCKET_ERROR) {
374 int JackNetAdapter::Process()
378 if (Read() == SOCKET_ERROR) {
382 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
386 if (Write() == SOCKET_ERROR) {
401 #include "driver_interface.h"
402 #include "JackAudioAdapter.h"
404 using namespace Jack;
412 desc = jack_driver_descriptor_construct(
"netadapter", JackDriverNone,
"netjack net <==> audio backend adapter", &filler);
414 strcpy(value.str, DEFAULT_MULTICAST_IP);
415 jack_driver_descriptor_add_parameter(desc, &filler,
"multicast-ip",
'a', JackDriverParamString, &value, NULL,
"Multicast address, or explicit IP of the master", NULL);
417 value.i = DEFAULT_PORT;
418 jack_driver_descriptor_add_parameter(desc, &filler,
"udp-net-port",
'p', JackDriverParamInt, &value, NULL,
"UDP port", NULL);
420 value.i = DEFAULT_MTU;
421 jack_driver_descriptor_add_parameter(desc, &filler,
"mtu",
'M', JackDriverParamInt, &value, NULL,
"MTU to the master", NULL);
424 jack_driver_descriptor_add_parameter(desc, &filler,
"input-ports",
'C', JackDriverParamInt, &value, NULL,
"Number of audio input ports", NULL);
425 jack_driver_descriptor_add_parameter(desc, &filler,
"output-ports",
'P', JackDriverParamInt, &value, NULL,
"Number of audio output ports", NULL);
429 jack_driver_descriptor_add_parameter(desc, &filler,
"celt",
'c', JackDriverParamInt, &value, NULL,
"Set CELT encoding and number of kBits per channel", NULL);
434 jack_driver_descriptor_add_parameter(desc, &filler,
"opus",
'O', JackDriverParamInt, &value, NULL,
"Set Opus encoding and number of kBits per channel", NULL);
437 strcpy(value.str,
"'hostname'");
438 jack_driver_descriptor_add_parameter(desc, &filler,
"client-name",
'n', JackDriverParamString, &value, NULL,
"Name of the jack client", NULL);
441 jack_driver_descriptor_add_parameter(desc, &filler,
"transport-sync",
't', JackDriverParamUInt, &value, NULL,
"Sync transport with master's", NULL);
444 jack_driver_descriptor_add_parameter(desc, &filler,
"latency",
'l', JackDriverParamUInt, &value, NULL,
"Network latency", NULL);
447 jack_driver_descriptor_add_parameter(desc, &filler,
"quality",
'q', JackDriverParamInt, &value, NULL,
"Resample algorithm quality (0 - 4)", NULL);
450 jack_driver_descriptor_add_parameter(desc, &filler,
"ring-buffer",
'g', JackDriverParamInt, &value, NULL,
"Fixed ringbuffer size",
"Fixed ringbuffer size (if not set => automatic adaptative)");
453 jack_driver_descriptor_add_parameter(desc, &filler,
"auto-connect",
'c', JackDriverParamBool, &value, NULL,
"Auto connect netmaster to system ports",
"");
458 SERVER_EXPORT
int jack_internal_initialize(jack_client_t* client,
const JSList* params)
471 if (adapter->Open() == 0) {
479 jack_info(
"netadapter allocation error");
484 SERVER_EXPORT
int jack_initialize(jack_client_t* jack_client,
const char* load_init)
487 bool parse_params =
true;
492 if (parser.GetArgc() > 0) {
493 parse_params = parser.ParseParams(desc, ¶ms);
497 res = jack_internal_initialize(jack_client, params);
498 parser.FreeParams(params);
503 SERVER_EXPORT
void jack_finish(
void* arg)
LIB_EXPORT jack_transport_state_t jack_transport_query(const jack_client_t *client, jack_position_t *pos)
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
Base class for audio adapters.
LIB_EXPORT void jack_transport_start(jack_client_t *client)
Audio adapter : Jack client side.
LIB_EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *)
LIB_EXPORT void jack_transport_stop(jack_client_t *client)
LIB_EXPORT int jack_transport_reposition(jack_client_t *client, const jack_position_t *pos)
LIB_EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *)
Exception possibly thrown by Net slaves.
SERVER_EXPORT void jack_log(const char *fmt,...)