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 = 2;
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 case 'l' :
00106 fParams.fNetworkLatency = param->value.i;
00107 if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
00108 jack_error("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
00109 throw std::bad_alloc();
00110 }
00111 break;
00112 case 'q':
00113 fQuality = param->value.ui;
00114 break;
00115 case 'g':
00116 fRingbufferCurSize = param->value.ui;
00117 fAdaptative = false;
00118 break;
00119 }
00120 }
00121
00122 strcpy(fMulticastIP, multicast_ip);
00123
00124
00125 fSocket.SetPort(udp_port);
00126 fSocket.SetAddress(fMulticastIP, udp_port);
00127
00128
00129 fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
00130
00131
00132 fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
00133
00134
00135 SetInputs(fParams.fSendAudioChannels);
00136 SetOutputs(fParams.fReturnAudioChannels);
00137
00138
00139 fSoftCaptureBuffer = NULL;
00140 fSoftPlaybackBuffer = NULL;
00141 }
00142
00143 JackNetAdapter::~JackNetAdapter()
00144 {
00145 jack_log("JackNetAdapter::~JackNetAdapter");
00146
00147 if (fSoftCaptureBuffer) {
00148 for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
00149 delete[] fSoftCaptureBuffer[port_index];
00150 }
00151 delete[] fSoftCaptureBuffer;
00152 }
00153 if (fSoftPlaybackBuffer) {
00154 for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
00155 delete[] fSoftPlaybackBuffer[port_index];
00156 }
00157 delete[] fSoftPlaybackBuffer;
00158 }
00159 }
00160
00161
00162 int JackNetAdapter::Open()
00163 {
00164 jack_info("NetAdapter started in %s mode %s Master's transport sync.",
00165 (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
00166
00167 if (fThread.StartSync() < 0) {
00168 jack_error("Cannot start netadapter thread");
00169 return -1;
00170 }
00171
00172 return 0;
00173 }
00174
00175 int JackNetAdapter::Close()
00176 {
00177 int res = 0;
00178 jack_log("JackNetAdapter::Close");
00179
00180 #ifdef JACK_MONITOR
00181 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
00182 #endif
00183
00184 if (fThread.Kill() < 0) {
00185 jack_error("Cannot kill thread");
00186 res = -1;
00187 }
00188
00189 fSocket.Close();
00190 return res;
00191 }
00192
00193 int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
00194 {
00195 JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
00196 return 0;
00197 }
00198
00199
00200
00201
00202 bool JackNetAdapter::Init()
00203 {
00204 jack_log("JackNetAdapter::Init");
00205
00206
00207 if (!JackNetSlaveInterface::Init()) {
00208 jack_error("JackNetSlaveInterface::Init() error...");
00209 return false;
00210 }
00211
00212
00213 if (!SetParams()) {
00214 jack_error("SetParams error...");
00215 return false;
00216 }
00217
00218
00219 if (fCaptureChannels > 0) {
00220 fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
00221 for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
00222 fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
00223 fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
00224 }
00225 }
00226
00227 if (fPlaybackChannels > 0) {
00228 fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
00229 for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
00230 fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
00231 fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
00232 }
00233 }
00234
00235
00236 SetAdaptedBufferSize(fParams.fPeriodSize);
00237 SetAdaptedSampleRate(fParams.fSampleRate);
00238
00239
00240 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00241
00242 if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
00243 jack_error("AcquireSelfRealTime error");
00244 } else {
00245 set_threaded_log_function();
00246 }
00247
00248
00249 SessionParamsDisplay(&fParams);
00250 return true;
00251 }
00252
00253 bool JackNetAdapter::Execute()
00254 {
00255 try {
00256
00257 while (fThread.GetStatus() == JackThread::kRunning)
00258 if (Process() == SOCKET_ERROR) {
00259 return false;
00260 }
00261 return false;
00262 } catch (JackNetException& e) {
00263 e.PrintMessage();
00264 jack_info("NetAdapter is restarted");
00265 Reset();
00266 fThread.DropSelfRealTime();
00267 fThread.SetStatus(JackThread::kIniting);
00268 if (Init()) {
00269 fThread.SetStatus(JackThread::kRunning);
00270 return true;
00271 } else {
00272 return false;
00273 }
00274 }
00275 }
00276
00277
00278 void JackNetAdapter::DecodeTransportData()
00279 {
00280
00281
00282
00283 if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fClient, NULL))) {
00284 switch (fSendTransportData.fState)
00285 {
00286 case JackTransportStopped :
00287 jack_transport_stop(fClient);
00288 jack_info("NetMaster : transport stops");
00289 break;
00290
00291 case JackTransportStarting :
00292 jack_transport_reposition(fClient, &fSendTransportData.fPosition);
00293 jack_transport_start(fClient);
00294 jack_info("NetMaster : transport starts");
00295 break;
00296
00297 case JackTransportRolling :
00298
00299
00300
00301 jack_info("NetMaster : transport rolls");
00302 break;
00303 }
00304 }
00305 }
00306
00307 void JackNetAdapter::EncodeTransportData()
00308 {
00309
00310 int refnum = -1;
00311 bool conditional = 0;
00312
00313 if (refnum != fLastTimebaseMaster) {
00314
00315 if (refnum == -1) {
00316 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00317 jack_info("Sending a timebase master release request.");
00318 } else {
00319
00320 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
00321 jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
00322 }
00323 fLastTimebaseMaster = refnum;
00324 } else {
00325 fReturnTransportData.fTimebaseMaster = NO_CHANGE;
00326 }
00327
00328
00329 fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition);
00330
00331
00332 fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
00333 (fReturnTransportData.fState != fSendTransportData.fState));
00334 if (fReturnTransportData.fNewState) {
00335 jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
00336 }
00337 fLastTransportState = fReturnTransportData.fState;
00338 }
00339
00340
00341 int JackNetAdapter::Read()
00342 {
00343
00344
00345 if (SyncRecv() == SOCKET_ERROR) {
00346 return 0;
00347 }
00348
00349 DecodeSyncPacket();
00350 return DataRecv();
00351 }
00352
00353 int JackNetAdapter::Write()
00354 {
00355 EncodeSyncPacket();
00356
00357 if (SyncSend() == SOCKET_ERROR) {
00358 return SOCKET_ERROR;
00359 }
00360
00361 return DataSend();
00362 }
00363
00364
00365 int JackNetAdapter::Process()
00366 {
00367
00368
00369 if (Read() == SOCKET_ERROR) {
00370 return SOCKET_ERROR;
00371 }
00372
00373 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
00374
00375
00376
00377 if (Write() == SOCKET_ERROR) {
00378 return SOCKET_ERROR;
00379 }
00380
00381 return 0;
00382 }
00383
00384 }
00385
00386
00387 #ifdef __cplusplus
00388 extern "C"
00389 {
00390 #endif
00391
00392 #include "driver_interface.h"
00393 #include "JackAudioAdapter.h"
00394
00395 using namespace Jack;
00396
00397 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00398 {
00399 jack_driver_desc_t * desc;
00400 jack_driver_desc_filler_t filler;
00401 jack_driver_param_value_t value;
00402
00403 desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler);
00404
00405 strcpy(value.str, DEFAULT_MULTICAST_IP);
00406 jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
00407
00408 value.i = DEFAULT_PORT;
00409 jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
00410
00411 value.i = DEFAULT_MTU;
00412 jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
00413
00414 value.i = 2;
00415 jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL);
00416 jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL);
00417
00418 #if HAVE_CELT
00419 value.i = -1;
00420 jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
00421 #endif
00422
00423 strcpy(value.str, "'hostname'");
00424 jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
00425
00426 value.ui = 0U;
00427 jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
00428
00429 value.ui = 5U;
00430 jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);
00431
00432 value.i = 0;
00433 jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
00434
00435 value.i = 32768;
00436 jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
00437
00438 value.i = false;
00439 jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", "");
00440
00441 return desc;
00442 }
00443
00444 SERVER_EXPORT int jack_internal_initialize(jack_client_t* client, const JSList* params)
00445 {
00446 jack_log("Loading netadapter");
00447
00448 Jack::JackAudioAdapter* adapter;
00449 jack_nframes_t buffer_size = jack_get_buffer_size(client);
00450 jack_nframes_t sample_rate = jack_get_sample_rate(client);
00451
00452 try {
00453
00454 adapter = new Jack::JackAudioAdapter(client, new Jack::JackNetAdapter(client, buffer_size, sample_rate, params), params);
00455 assert(adapter);
00456
00457 if (adapter->Open() == 0) {
00458 return 0;
00459 } else {
00460 delete adapter;
00461 return 1;
00462 }
00463
00464 } catch (...) {
00465 jack_info("NetAdapter allocation error");
00466 return 1;
00467 }
00468 }
00469
00470 SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
00471 {
00472 JSList* params = NULL;
00473 bool parse_params = true;
00474 int res = 1;
00475 jack_driver_desc_t* desc = jack_get_descriptor();
00476
00477 Jack::JackArgParser parser(load_init);
00478 if (parser.GetArgc() > 0) {
00479 parse_params = parser.ParseParams(desc, ¶ms);
00480 }
00481
00482 if (parse_params) {
00483 res = jack_internal_initialize(jack_client, params);
00484 parser.FreeParams(params);
00485 }
00486 return res;
00487 }
00488
00489 SERVER_EXPORT void jack_finish(void* arg)
00490 {
00491 Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*>(arg);
00492
00493 if (adapter) {
00494 jack_log("Unloading netadapter");
00495 adapter->Close();
00496 delete adapter;
00497 }
00498 }
00499
00500 #ifdef __cplusplus
00501 }
00502 #endif