00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "JackNetAdapter.h"
00020 #include "JackException.h"
00021 #include "JackServerGlobals.h"
00022 #include "JackEngineControl.h"
00023 #include "JackArgParser.h"
00024 #include <assert.h>
00025
00026 namespace Jack
00027 {
00028 JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
00029 : JackAudioAdapterInterface(buffer_size, sample_rate), JackNetSlaveInterface(), fThread(this)
00030 {
00031 jack_log("JackNetAdapter::JackNetAdapter");
00032
00033
00034
00035
00036
00037
00038 char multicast_ip[32];
00039 uint udp_port;
00040 GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
00041 fSocket.GetName(fParams.fSlaveNetName);
00042 fParams.fMtu = DEFAULT_MTU;
00043
00044 fParams.fTransportSync = 0;
00045 int send_audio = -1;
00046 int return_audio = -1;
00047 fParams.fSendMidiChannels = 0;
00048 fParams.fReturnMidiChannels = 0;
00049 fParams.fSampleRate = sample_rate;
00050 fParams.fPeriodSize = buffer_size;
00051 fParams.fSlaveSyncMode = 1;
00052 fParams.fNetworkLatency = NETWORK_DEFAULT_LATENCY;
00053 fParams.fSampleEncoder = JackFloatEncoder;
00054 fClient = jack_client;
00055
00056
00057 const char* default_udp_port = getenv("JACK_NETJACK_PORT");
00058 udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
00059
00060 const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
00061 if (default_multicast_ip) {
00062 strcpy(multicast_ip, default_multicast_ip);
00063 } else {
00064 strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
00065 }
00066
00067
00068 const JSList* node;
00069 const jack_driver_param_t* param;
00070 for (node = params; node; node = jack_slist_next(node))
00071 {
00072 param = (const jack_driver_param_t*) node->data;
00073
00074 switch (param->character) {
00075 case 'a' :
00076 assert(strlen(param->value.str) < 32);
00077 strcpy(multicast_ip, param->value.str);
00078 break;
00079 case 'p' :
00080 udp_port = param->value.ui;
00081 break;
00082 case 'M' :
00083 fParams.fMtu = param->value.i;
00084 break;
00085 case 'C' :
00086 send_audio = param->value.i;
00087 break;
00088 case 'P' :
00089 return_audio = param->value.i;
00090 break;
00091 case 'n' :
00092 strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE);
00093 break;
00094 case 't' :
00095 fParams.fTransportSync = param->value.ui;
00096 break;
00097 #if HAVE_CELT
00098 case 'c':
00099 if (param->value.i > 0) {
00100 fParams.fSampleEncoder = JackCeltEncoder;
00101 fParams.fKBps = param->value.i;
00102 }
00103 break;
00104 #endif
00105 #if HAVE_OPUS
00106 case 'O':
00107 if (param->value.i > 0) {
00108 fParams.fSampleEncoder = JackOpusEncoder;
00109 fParams.fKBps = param->value.i;
00110 }
00111 break;
00112 #endif
00113 case 'l' :
00114 fParams.fNetworkLatency = param->value.i;
00115 if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
00116 jack_error("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
00117 throw std::bad_alloc();
00118 }
00119 break;
00120 case 'q':
00121 fQuality = param->value.ui;
00122 break;
00123 case 'g':
00124 fRingbufferCurSize = param->value.ui;
00125 fAdaptative = false;
00126 break;
00127 }
00128 }
00129
00130 strcpy(fMulticastIP, multicast_ip);
00131
00132
00133 fSocket.SetPort(udp_port);
00134 fSocket.SetAddress(fMulticastIP, udp_port);
00135
00136
00137 fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
00138
00139
00140 fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
00141
00142
00143 SetInputs(fParams.fSendAudioChannels);
00144 SetOutputs(fParams.fReturnAudioChannels);
00145
00146
00147 fSoftCaptureBuffer = NULL;
00148 fSoftPlaybackBuffer = NULL;
00149 }
00150
00151 JackNetAdapter::~JackNetAdapter()
00152 {
00153 jack_log("JackNetAdapter::~JackNetAdapter");
00154
00155 if (fSoftCaptureBuffer) {
00156 for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
00157 delete[] fSoftCaptureBuffer[port_index];
00158 }
00159 delete[] fSoftCaptureBuffer;
00160 }
00161 if (fSoftPlaybackBuffer) {
00162 for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
00163 delete[] fSoftPlaybackBuffer[port_index];
00164 }
00165 delete[] fSoftPlaybackBuffer;
00166 }
00167 }
00168
00169
00170 int JackNetAdapter::Open()
00171 {
00172 jack_info("NetAdapter started in %s mode %s Master's transport sync.",
00173 (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
00174
00175 if (fThread.StartSync() < 0) {
00176 jack_error("Cannot start netadapter thread");
00177 return -1;
00178 }
00179
00180 return 0;
00181 }
00182
00183 int JackNetAdapter::Close()
00184 {
00185 int res = 0;
00186 jack_log("JackNetAdapter::Close");
00187
00188 #ifdef JACK_MONITOR
00189 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
00190 #endif
00191
00192 if (fThread.Kill() < 0) {
00193 jack_error("Cannot kill thread");
00194 res = -1;
00195 }
00196
00197 fSocket.Close();
00198 return res;
00199 }
00200
00201 int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
00202 {
00203 JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
00204 return 0;
00205 }
00206
00207
00208
00209
00210 bool JackNetAdapter::Init()
00211 {
00212 jack_log("JackNetAdapter::Init");
00213
00214
00215 if (!JackNetSlaveInterface::Init()) {
00216 jack_error("JackNetSlaveInterface::Init() error...");
00217 return false;
00218 }
00219
00220
00221 if (!SetParams()) {
00222 jack_error("SetParams error...");
00223 return false;
00224 }
00225
00226
00227 if (fCaptureChannels > 0) {
00228 fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
00229 for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
00230 fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
00231 fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
00232 }
00233 }
00234
00235 if (fPlaybackChannels > 0) {
00236 fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
00237 for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
00238 fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
00239 fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
00240 }
00241 }
00242
00243
00244 SetAdaptedBufferSize(fParams.fPeriodSize);
00245 SetAdaptedSampleRate(fParams.fSampleRate);
00246
00247
00248 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00249
00250 if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
00251 jack_error("AcquireSelfRealTime error");
00252 } else {
00253 set_threaded_log_function();
00254 }
00255
00256
00257 SessionParamsDisplay(&fParams);
00258 return true;
00259 }
00260
00261 bool JackNetAdapter::Execute()
00262 {
00263 try {
00264
00265 while (fThread.GetStatus() == JackThread::kRunning) {
00266 if (Process() == SOCKET_ERROR) {
00267 return false;
00268 }
00269 }
00270 return false;
00271 } catch (JackNetException& e) {
00272
00273 e.PrintMessage();
00274 jack_info("NetAdapter is restarted");
00275 Reset();
00276 fThread.DropSelfRealTime();
00277 fThread.SetStatus(JackThread::kIniting);
00278 if (Init()) {
00279 fThread.SetStatus(JackThread::kRunning);
00280 return true;
00281 } else {
00282 return false;
00283 }
00284 }
00285 }
00286
00287
00288 void JackNetAdapter::DecodeTransportData()
00289 {
00290
00291
00292
00293 if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fClient, NULL))) {
00294 switch (fSendTransportData.fState)
00295 {
00296 case JackTransportStopped :
00297 jack_transport_stop(fClient);
00298 jack_info("NetMaster : transport stops");
00299 break;
00300
00301 case JackTransportStarting :
00302 jack_transport_reposition(fClient, &fSendTransportData.fPosition);
00303 jack_transport_start(fClient);
00304 jack_info("NetMaster : transport starts");
00305 break;
00306
00307 case JackTransportRolling :
00308
00309
00310
00311 jack_info("NetMaster : transport rolls");
00312 break;
00313 }
00314 }
00315 }
00316
00317 void JackNetAdapter::EncodeTransportData()
00318 {
00319
00320 int refnum = -1;
00321 bool conditional = 0;
00322
00323 if (refnum != fLastTimebaseMaster) {
00324
00325 if (refnum == -1) {
00326 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00327 jack_info("Sending a timebase master release request.");
00328 } else {
00329
00330 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
00331 jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
00332 }
00333 fLastTimebaseMaster = refnum;
00334 } else {
00335 fReturnTransportData.fTimebaseMaster = NO_CHANGE;
00336 }
00337
00338
00339 fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition);
00340
00341
00342 fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
00343 (fReturnTransportData.fState != fSendTransportData.fState));
00344 if (fReturnTransportData.fNewState) {
00345 jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
00346 }
00347 fLastTransportState = fReturnTransportData.fState;
00348 }
00349
00350
00351 int JackNetAdapter::Read()
00352 {
00353 switch (SyncRecv()) {
00354
00355 case SOCKET_ERROR:
00356 return SOCKET_ERROR;
00357
00358 case SYNC_PACKET_ERROR:
00359
00360 break;
00361
00362 default:
00363
00364 int unused_frames;
00365 DecodeSyncPacket(unused_frames);
00366 break;
00367 }
00368
00369 return DataRecv();
00370 }
00371
00372 int JackNetAdapter::Write()
00373 {
00374 EncodeSyncPacket();
00375
00376 if (SyncSend() == SOCKET_ERROR) {
00377 return SOCKET_ERROR;
00378 }
00379
00380 return DataSend();
00381 }
00382
00383
00384 int JackNetAdapter::Process()
00385 {
00386
00387
00388 if (Read() == SOCKET_ERROR) {
00389 return SOCKET_ERROR;
00390 }
00391
00392 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
00393
00394
00395
00396 if (Write() == SOCKET_ERROR) {
00397 return SOCKET_ERROR;
00398 }
00399
00400 return 0;
00401 }
00402
00403 }
00404
00405
00406 #ifdef __cplusplus
00407 extern "C"
00408 {
00409 #endif
00410
00411 #include "driver_interface.h"
00412 #include "JackAudioAdapter.h"
00413
00414 using namespace Jack;
00415
00416 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00417 {
00418 jack_driver_desc_t * desc;
00419 jack_driver_desc_filler_t filler;
00420 jack_driver_param_value_t value;
00421
00422 desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler);
00423
00424 strcpy(value.str, DEFAULT_MULTICAST_IP);
00425 jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL);
00426
00427 value.i = DEFAULT_PORT;
00428 jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
00429
00430 value.i = DEFAULT_MTU;
00431 jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
00432
00433 value.i = 2;
00434 jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL);
00435 jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'P', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL);
00436
00437 #if HAVE_CELT
00438 value.i = -1;
00439 jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
00440 #endif
00441
00442 #if HAVE_OPUS
00443 value.i = -1;
00444 jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'O', JackDriverParamInt, &value, NULL, "Set Opus encoding and number of kBits per channel", NULL);
00445 #endif
00446
00447 strcpy(value.str, "'hostname'");
00448 jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
00449
00450 value.ui = 0U;
00451 jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
00452
00453 value.ui = 5U;
00454 jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);
00455
00456 value.i = 0;
00457 jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
00458
00459 value.i = 32768;
00460 jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
00461
00462 value.i = false;
00463 jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netadapter to system ports", NULL);
00464
00465 return desc;
00466 }
00467
00468 SERVER_EXPORT int jack_internal_initialize(jack_client_t* client, const JSList* params)
00469 {
00470 jack_log("Loading netadapter");
00471
00472 Jack::JackAudioAdapter* adapter;
00473 jack_nframes_t buffer_size = jack_get_buffer_size(client);
00474 jack_nframes_t sample_rate = jack_get_sample_rate(client);
00475
00476 try {
00477
00478 adapter = new Jack::JackAudioAdapter(client, new Jack::JackNetAdapter(client, buffer_size, sample_rate, params), params);
00479 assert(adapter);
00480
00481 if (adapter->Open() == 0) {
00482 return 0;
00483 } else {
00484 delete adapter;
00485 return 1;
00486 }
00487
00488 } catch (...) {
00489 jack_info("netadapter allocation error");
00490 return 1;
00491 }
00492 }
00493
00494 SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
00495 {
00496 JSList* params = NULL;
00497 bool parse_params = true;
00498 int res = 1;
00499 jack_driver_desc_t* desc = jack_get_descriptor();
00500
00501 Jack::JackArgParser parser(load_init);
00502 if (parser.GetArgc() > 0) {
00503 parse_params = parser.ParseParams(desc, ¶ms);
00504 }
00505
00506 if (parse_params) {
00507 res = jack_internal_initialize(jack_client, params);
00508 parser.FreeParams(params);
00509 }
00510 return res;
00511 }
00512
00513 SERVER_EXPORT void jack_finish(void* arg)
00514 {
00515 Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*>(arg);
00516
00517 if (adapter) {
00518 jack_log("Unloading netadapter");
00519 adapter->Close();
00520 delete adapter;
00521 }
00522 }
00523
00524 #ifdef __cplusplus
00525 }
00526 #endif