Jack2
1.9.8
|
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 = 2; 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 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 // Set the socket parameters 00125 fSocket.SetPort(udp_port); 00126 fSocket.SetAddress(fMulticastIP, udp_port); 00127 00128 // If not set, takes default 00129 fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; 00130 00131 // If not set, takes default 00132 fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio; 00133 00134 // Set the audio adapter interface channel values 00135 SetInputs(fParams.fSendAudioChannels); 00136 SetOutputs(fParams.fReturnAudioChannels); 00137 00138 // Soft buffers will be allocated later (once network initialization done) 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 //open/close-------------------------------------------------------------------------- 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 //thread------------------------------------------------------------------------------ 00200 // TODO : if failure, thread exist... need to restart ? 00201 00202 bool JackNetAdapter::Init() 00203 { 00204 jack_log("JackNetAdapter::Init"); 00205 00206 //init network connection 00207 if (!JackNetSlaveInterface::Init()) { 00208 jack_error("JackNetSlaveInterface::Init() error..."); 00209 return false; 00210 } 00211 00212 //then set global parameters 00213 if (!SetParams()) { 00214 jack_error("SetParams error..."); 00215 return false; 00216 } 00217 00218 //set buffers 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 //set audio adapter parameters 00236 SetAdaptedBufferSize(fParams.fPeriodSize); 00237 SetAdaptedSampleRate(fParams.fSampleRate); 00238 00239 // Will do "something" on OSX only... 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 //init done, display parameters 00249 SessionParamsDisplay(&fParams); 00250 return true; 00251 } 00252 00253 bool JackNetAdapter::Execute() 00254 { 00255 try { 00256 // Keep running even in case of error 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 //transport--------------------------------------------------------------------------- 00278 void JackNetAdapter::DecodeTransportData() 00279 { 00280 //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) 00281 00282 //is there a new transport state ? 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 // TODO, we need to : 00299 // - find a way to call TransportEngine->SetNetworkSync() 00300 // - turn the transport state to JackTransportRolling 00301 jack_info("NetMaster : transport rolls"); 00302 break; 00303 } 00304 } 00305 } 00306 00307 void JackNetAdapter::EncodeTransportData() 00308 { 00309 //is there a timebase master change ? 00310 int refnum = -1; 00311 bool conditional = 0; 00312 //TODO : get the actual timebase master 00313 if (refnum != fLastTimebaseMaster) { 00314 //timebase master has released its function 00315 if (refnum == -1) { 00316 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; 00317 jack_info("Sending a timebase master release request."); 00318 } else { 00319 //there is a new timebase master 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 //update transport state and position 00329 fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition); 00330 00331 //is it a new state (that the master need to know...) ? 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 //read/write operations--------------------------------------------------------------- 00341 int JackNetAdapter::Read() 00342 { 00343 //don't return -1 in case of sync recv failure 00344 //we need the process to continue for network error detection 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 //process----------------------------------------------------------------------------- 00365 int JackNetAdapter::Process() 00366 { 00367 //read data from the network 00368 //in case of fatal network error, stop the process 00369 if (Read() == SOCKET_ERROR) { 00370 return SOCKET_ERROR; 00371 } 00372 00373 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize); 00374 00375 //then write data to network 00376 //in case of failure, stop process 00377 if (Write() == SOCKET_ERROR) { 00378 return SOCKET_ERROR; 00379 } 00380 00381 return 0; 00382 } 00383 00384 } // namespace Jack 00385 00386 //loader------------------------------------------------------------------------------ 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