Jack2
1.9.10
|
00001 /* 00002 Copyright (C) 2008-2011 Romain Moret at Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 Global parameter setting : we can't call JackNetSlaveInterface constructor with some parameters before, 00035 because we don't have full parametering right now, parameters will be parsed from the param list, 00036 and then JackNetSlaveInterface will be filled with proper values. 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 // Desactivated for now... 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 // Possibly use env variable 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 //options parsing 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 // Set the socket parameters 00133 fSocket.SetPort(udp_port); 00134 fSocket.SetAddress(fMulticastIP, udp_port); 00135 00136 // If not set, takes default 00137 fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; 00138 00139 // If not set, takes default 00140 fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio; 00141 00142 // Set the audio adapter interface channel values 00143 SetInputs(fParams.fSendAudioChannels); 00144 SetOutputs(fParams.fReturnAudioChannels); 00145 00146 // Soft buffers will be allocated later (once network initialization done) 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 //open/close-------------------------------------------------------------------------- 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 //thread------------------------------------------------------------------------------ 00208 // TODO : if failure, thread exist... need to restart ? 00209 00210 bool JackNetAdapter::Init() 00211 { 00212 jack_log("JackNetAdapter::Init"); 00213 00214 //init network connection 00215 if (!JackNetSlaveInterface::Init()) { 00216 jack_error("JackNetSlaveInterface::Init() error..."); 00217 return false; 00218 } 00219 00220 //then set global parameters 00221 if (!SetParams()) { 00222 jack_error("SetParams error..."); 00223 return false; 00224 } 00225 00226 //set buffers 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 //set audio adapter parameters 00244 SetAdaptedBufferSize(fParams.fPeriodSize); 00245 SetAdaptedSampleRate(fParams.fSampleRate); 00246 00247 // Will do "something" on OSX only... 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 //init done, display parameters 00257 SessionParamsDisplay(&fParams); 00258 return true; 00259 } 00260 00261 bool JackNetAdapter::Execute() 00262 { 00263 try { 00264 // Keep running even in case of error 00265 while (fThread.GetStatus() == JackThread::kRunning) { 00266 if (Process() == SOCKET_ERROR) { 00267 return false; 00268 } 00269 } 00270 return false; 00271 } catch (JackNetException& e) { 00272 // Otherwise just restart... 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 //transport--------------------------------------------------------------------------- 00288 void JackNetAdapter::DecodeTransportData() 00289 { 00290 //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) 00291 00292 //is there a new transport state ? 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 // TODO, we need to : 00309 // - find a way to call TransportEngine->SetNetworkSync() 00310 // - turn the transport state to JackTransportRolling 00311 jack_info("NetMaster : transport rolls"); 00312 break; 00313 } 00314 } 00315 } 00316 00317 void JackNetAdapter::EncodeTransportData() 00318 { 00319 //is there a timebase master change ? 00320 int refnum = -1; 00321 bool conditional = 0; 00322 //TODO : get the actual timebase master 00323 if (refnum != fLastTimebaseMaster) { 00324 //timebase master has released its function 00325 if (refnum == -1) { 00326 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; 00327 jack_info("Sending a timebase master release request."); 00328 } else { 00329 //there is a new timebase master 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 //update transport state and position 00339 fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition); 00340 00341 //is it a new state (that the master need to know...) ? 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 //read/write operations--------------------------------------------------------------- 00351 int JackNetAdapter::Read() 00352 { 00353 switch (SyncRecv()) { 00354 00355 case SOCKET_ERROR: 00356 return SOCKET_ERROR; 00357 00358 case SYNC_PACKET_ERROR: 00359 // Since sync packet is incorrect, don't decode it and continue with data 00360 break; 00361 00362 default: 00363 //decode sync 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 //process----------------------------------------------------------------------------- 00384 int JackNetAdapter::Process() 00385 { 00386 //read data from the network 00387 //in case of fatal network error, stop the process 00388 if (Read() == SOCKET_ERROR) { 00389 return SOCKET_ERROR; 00390 } 00391 00392 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize); 00393 00394 //then write data to network 00395 //in case of failure, stop process 00396 if (Write() == SOCKET_ERROR) { 00397 return SOCKET_ERROR; 00398 } 00399 00400 return 0; 00401 } 00402 00403 } // namespace Jack 00404 00405 //loader------------------------------------------------------------------------------ 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