Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2008 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 //global parametering 00034 //we can't call JackNetSlaveInterface constructor with some parameters before 00035 //because we don't have full parametering right now 00036 //parameters will be parsed from the param list, and then JackNetSlaveInterface will be filled with proper values 00037 strcpy ( fMulticastIP, DEFAULT_MULTICAST_IP ); 00038 uint port = DEFAULT_PORT; 00039 GetHostName ( fParams.fName, JACK_CLIENT_NAME_SIZE ); 00040 fSocket.GetName ( fParams.fSlaveNetName ); 00041 fParams.fMtu = DEFAULT_MTU; 00042 fParams.fTransportSync = 0; 00043 fParams.fSendAudioChannels = 2; 00044 fParams.fReturnAudioChannels = 2; 00045 fParams.fSendMidiChannels = 0; 00046 fParams.fReturnMidiChannels = 0; 00047 fParams.fSampleRate = sample_rate; 00048 fParams.fPeriodSize = buffer_size; 00049 fParams.fSlaveSyncMode = 1; 00050 fParams.fNetworkMode = 's'; 00051 fJackClient = jack_client; 00052 00053 //options parsing 00054 const JSList* node; 00055 const jack_driver_param_t* param; 00056 for ( node = params; node; node = jack_slist_next ( node ) ) 00057 { 00058 param = ( const jack_driver_param_t* ) node->data; 00059 switch ( param->character ) 00060 { 00061 case 'a' : 00062 if (strlen (param->value.str) < 32) 00063 strcpy(fMulticastIP, param->value.str); 00064 else 00065 jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); 00066 break; 00067 case 'p' : 00068 fSocket.SetPort ( param->value.ui ); 00069 break; 00070 case 'M' : 00071 fParams.fMtu = param->value.i; 00072 break; 00073 case 'C' : 00074 fParams.fSendAudioChannels = param->value.i; 00075 break; 00076 case 'P' : 00077 fParams.fReturnAudioChannels = param->value.i; 00078 break; 00079 case 'n' : 00080 strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE ); 00081 break; 00082 case 't' : 00083 //fParams.fTransportSync = param->value.ui; 00084 break; 00085 case 'm' : 00086 if ( strcmp ( param->value.str, "normal" ) == 0 ) 00087 fParams.fNetworkMode = 'n'; 00088 else if ( strcmp ( param->value.str, "slow" ) == 0 ) 00089 fParams.fNetworkMode = 's'; 00090 else if ( strcmp ( param->value.str, "fast" ) == 0 ) 00091 fParams.fNetworkMode = 'f'; 00092 else 00093 jack_error ( "Unknown network mode, using 'normal' mode." ); 00094 break; 00095 case 'q': 00096 fQuality = param->value.ui; 00097 break; 00098 case 'g': 00099 fRingbufferCurSize = param->value.ui; 00100 fAdaptative = false; 00101 break; 00102 } 00103 } 00104 00105 //set the socket parameters 00106 fSocket.SetPort ( port ); 00107 fSocket.SetAddress ( fMulticastIP, port ); 00108 00109 //set the audio adapter interface channel values 00110 SetInputs ( fParams.fSendAudioChannels ); 00111 SetOutputs ( fParams.fReturnAudioChannels ); 00112 00113 //soft buffers will be allocated later (once network initialization done) 00114 fSoftCaptureBuffer = NULL; 00115 fSoftPlaybackBuffer = NULL; 00116 } 00117 00118 JackNetAdapter::~JackNetAdapter() 00119 { 00120 jack_log ( "JackNetAdapter::~JackNetAdapter" ); 00121 00122 int port_index; 00123 if ( fSoftCaptureBuffer ) 00124 { 00125 for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) 00126 delete[] fSoftCaptureBuffer[port_index]; 00127 delete[] fSoftCaptureBuffer; 00128 } 00129 if ( fSoftPlaybackBuffer ) 00130 { 00131 for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) 00132 delete[] fSoftPlaybackBuffer[port_index]; 00133 delete[] fSoftPlaybackBuffer; 00134 } 00135 } 00136 00137 //open/close-------------------------------------------------------------------------- 00138 int JackNetAdapter::Open() 00139 { 00140 jack_log ( "JackNetAdapter::Open" ); 00141 00142 jack_info ( "NetAdapter started in %s mode %s Master's transport sync.", 00143 ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" ); 00144 00145 if ( fThread.StartSync() < 0 ) 00146 { 00147 jack_error ( "Cannot start netadapter thread" ); 00148 return -1; 00149 } 00150 00151 return 0; 00152 } 00153 00154 int JackNetAdapter::Close() 00155 { 00156 jack_log ( "JackNetAdapter::Close" ); 00157 00158 #ifdef JACK_MONITOR 00159 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); 00160 #endif 00161 00162 switch ( fThread.GetStatus() ) 00163 { 00164 // Kill the thread in Init phase 00165 case JackThread::kStarting: 00166 case JackThread::kIniting: 00167 if ( fThread.Kill() < 0 ) 00168 { 00169 jack_error ( "Cannot kill thread" ); 00170 return -1; 00171 } 00172 break; 00173 // Stop when the thread cycle is finished 00174 00175 case JackThread::kRunning: 00176 if ( fThread.Stop() < 0 ) 00177 { 00178 jack_error ( "Cannot stop thread" ); 00179 return -1; 00180 } 00181 break; 00182 00183 default: 00184 break; 00185 } 00186 fSocket.Close(); 00187 return 0; 00188 } 00189 00190 int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size ) 00191 { 00192 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); 00193 return 0; 00194 } 00195 00196 //thread------------------------------------------------------------------------------ 00197 bool JackNetAdapter::Init() 00198 { 00199 jack_log ( "JackNetAdapter::Init" ); 00200 00201 int port_index; 00202 00203 //init network connection 00204 if ( !JackNetSlaveInterface::Init() ) 00205 return false; 00206 00207 //then set global parameters 00208 SetParams(); 00209 00210 //set buffers 00211 fSoftCaptureBuffer = new sample_t*[fCaptureChannels]; 00212 for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) 00213 { 00214 fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize]; 00215 fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] ); 00216 } 00217 fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels]; 00218 for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) 00219 { 00220 fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize]; 00221 fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] ); 00222 } 00223 00224 //set audio adapter parameters 00225 SetAdaptedBufferSize ( fParams.fPeriodSize ); 00226 SetAdaptedSampleRate ( fParams.fSampleRate ); 00227 00228 // Will do "something" on OSX only... 00229 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); 00230 00231 if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) { 00232 jack_error("AcquireSelfRealTime error"); 00233 } else { 00234 set_threaded_log_function(); 00235 } 00236 00237 //init done, display parameters 00238 SessionParamsDisplay ( &fParams ); 00239 return true; 00240 } 00241 00242 bool JackNetAdapter::Execute() 00243 { 00244 try { 00245 // Keep running even in case of error 00246 while (fThread.GetStatus() == JackThread::kRunning) 00247 if (Process() == SOCKET_ERROR) 00248 return false; 00249 return false; 00250 } catch (JackNetException& e) { 00251 e.PrintMessage(); 00252 jack_info("NetAdapter is restarted."); 00253 Reset(); 00254 fThread.DropSelfRealTime(); 00255 fThread.SetStatus(JackThread::kIniting); 00256 if (Init()) { 00257 fThread.SetStatus(JackThread::kRunning); 00258 return true; 00259 } else { 00260 return false; 00261 } 00262 } 00263 } 00264 00265 //transport--------------------------------------------------------------------------- 00266 void JackNetAdapter::DecodeTransportData() 00267 { 00268 //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) 00269 00270 //is there a new transport state ? 00271 if ( fSendTransportData.fNewState && ( fSendTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) ) 00272 { 00273 switch ( fSendTransportData.fState ) 00274 { 00275 case JackTransportStopped : 00276 jack_transport_stop ( fJackClient ); 00277 jack_info ( "NetMaster : transport stops." ); 00278 break; 00279 00280 case JackTransportStarting : 00281 jack_transport_reposition ( fJackClient, &fSendTransportData.fPosition ); 00282 jack_transport_start ( fJackClient ); 00283 jack_info ( "NetMaster : transport starts." ); 00284 break; 00285 00286 case JackTransportRolling : 00287 //TODO , we need to : 00288 // - find a way to call TransportEngine->SetNetworkSync() 00289 // - turn the transport state to JackTransportRolling 00290 jack_info ( "NetMaster : transport rolls." ); 00291 break; 00292 } 00293 } 00294 } 00295 00296 void JackNetAdapter::EncodeTransportData() 00297 { 00298 //is there a timebase master change ? 00299 int refnum = -1; 00300 bool conditional = 0; 00301 //TODO : get the actual timebase master 00302 if ( refnum != fLastTimebaseMaster ) 00303 { 00304 //timebase master has released its function 00305 if ( refnum == -1 ) 00306 { 00307 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; 00308 jack_info ( "Sending a timebase master release request." ); 00309 } 00310 //there is a new timebase master 00311 else 00312 { 00313 fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER; 00314 jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" ); 00315 } 00316 fLastTimebaseMaster = refnum; 00317 } 00318 else 00319 fReturnTransportData.fTimebaseMaster = NO_CHANGE; 00320 00321 //update transport state and position 00322 fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition ); 00323 00324 //is it a new state (that the master need to know...) ? 00325 fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) && 00326 ( fReturnTransportData.fState != fSendTransportData.fState ) ); 00327 if ( fReturnTransportData.fNewState ) 00328 jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) ); 00329 fLastTransportState = fReturnTransportData.fState; 00330 } 00331 00332 //read/write operations--------------------------------------------------------------- 00333 int JackNetAdapter::Read() 00334 { 00335 //don't return -1 in case of sync recv failure 00336 //we need the process to continue for network error detection 00337 if ( SyncRecv() == SOCKET_ERROR ) 00338 return 0; 00339 00340 DecodeSyncPacket(); 00341 return DataRecv(); 00342 } 00343 00344 int JackNetAdapter::Write() 00345 { 00346 EncodeSyncPacket(); 00347 00348 if ( SyncSend() == SOCKET_ERROR ) 00349 return SOCKET_ERROR; 00350 00351 return DataSend(); 00352 } 00353 00354 //process----------------------------------------------------------------------------- 00355 int JackNetAdapter::Process() 00356 { 00357 //read data from the network 00358 //in case of fatal network error, stop the process 00359 if (Read() == SOCKET_ERROR) 00360 return SOCKET_ERROR; 00361 00362 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize); 00363 00364 //then write data to network 00365 //in case of failure, stop process 00366 if (Write() == SOCKET_ERROR) 00367 return SOCKET_ERROR; 00368 00369 return 0; 00370 } 00371 00372 } // namespace Jack 00373 00374 //loader------------------------------------------------------------------------------ 00375 #ifdef __cplusplus 00376 extern "C" 00377 { 00378 #endif 00379 00380 #include "driver_interface.h" 00381 #include "JackAudioAdapter.h" 00382 00383 using namespace Jack; 00384 00385 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00386 { 00387 jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); 00388 00389 strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 00390 strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 00391 00392 desc->nparams = 11; 00393 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); 00394 00395 int i = 0; 00396 strcpy ( desc->params[i].name, "multicast_ip" ); 00397 desc->params[i].character = 'a'; 00398 desc->params[i].type = JackDriverParamString; 00399 strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP ); 00400 strcpy ( desc->params[i].short_desc, "Multicast Address" ); 00401 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00402 00403 i++; 00404 strcpy ( desc->params[i].name, "udp_net_port" ); 00405 desc->params[i].character = 'p'; 00406 desc->params[i].type = JackDriverParamInt; 00407 desc->params[i].value.i = DEFAULT_PORT; 00408 strcpy ( desc->params[i].short_desc, "UDP port" ); 00409 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00410 00411 i++; 00412 strcpy ( desc->params[i].name, "mtu" ); 00413 desc->params[i].character = 'M'; 00414 desc->params[i].type = JackDriverParamInt; 00415 desc->params[i].value.i = DEFAULT_MTU; 00416 strcpy ( desc->params[i].short_desc, "MTU to the master" ); 00417 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00418 00419 i++; 00420 strcpy ( desc->params[i].name, "input-ports" ); 00421 desc->params[i].character = 'C'; 00422 desc->params[i].type = JackDriverParamInt; 00423 desc->params[i].value.i = 2; 00424 strcpy ( desc->params[i].short_desc, "Number of audio input ports" ); 00425 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00426 00427 i++; 00428 strcpy ( desc->params[i].name, "output-ports" ); 00429 desc->params[i].character = 'P'; 00430 desc->params[i].type = JackDriverParamInt; 00431 desc->params[i].value.i = 2; 00432 strcpy ( desc->params[i].short_desc, "Number of audio output ports" ); 00433 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00434 00435 i++; 00436 strcpy ( desc->params[i].name, "client-name" ); 00437 desc->params[i].character = 'n'; 00438 desc->params[i].type = JackDriverParamString; 00439 strcpy ( desc->params[i].value.str, "'hostname'" ); 00440 strcpy ( desc->params[i].short_desc, "Name of the jack client" ); 00441 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00442 00443 i++; 00444 strcpy ( desc->params[i].name, "transport-sync" ); 00445 desc->params[i].character = 't'; 00446 desc->params[i].type = JackDriverParamUInt; 00447 desc->params[i].value.ui = 1U; 00448 strcpy ( desc->params[i].short_desc, "Sync transport with master's" ); 00449 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00450 00451 i++; 00452 strcpy ( desc->params[i].name, "mode" ); 00453 desc->params[i].character = 'm'; 00454 desc->params[i].type = JackDriverParamString; 00455 strcpy ( desc->params[i].value.str, "slow" ); 00456 strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." ); 00457 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00458 00459 i++; 00460 strcpy(desc->params[i].name, "quality"); 00461 desc->params[i].character = 'q'; 00462 desc->params[i].type = JackDriverParamInt; 00463 desc->params[i].value.ui = 0; 00464 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); 00465 strcpy(desc->params[i].long_desc, desc->params[i].short_desc); 00466 00467 i++; 00468 strcpy(desc->params[i].name, "ring-buffer"); 00469 desc->params[i].character = 'g'; 00470 desc->params[i].type = JackDriverParamInt; 00471 desc->params[i].value.ui = 32768; 00472 strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); 00473 strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); 00474 00475 i++; 00476 strcpy ( desc->params[i].name, "auto-connect" ); 00477 desc->params[i].character = 'c'; 00478 desc->params[i].type = JackDriverParamBool; 00479 desc->params[i].value.i = false; 00480 strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" ); 00481 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00482 00483 return desc; 00484 } 00485 00486 SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params ) 00487 { 00488 jack_log ( "Loading netadapter" ); 00489 00490 Jack::JackAudioAdapter* adapter; 00491 jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client ); 00492 jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client ); 00493 00494 try { 00495 00496 adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false); 00497 assert ( adapter ); 00498 00499 if ( adapter->Open() == 0 ) 00500 return 0; 00501 else 00502 { 00503 delete adapter; 00504 return 1; 00505 } 00506 00507 } catch (...) { 00508 return 1; 00509 } 00510 } 00511 00512 SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init ) 00513 { 00514 JSList* params = NULL; 00515 bool parse_params = true; 00516 int res = 1; 00517 jack_driver_desc_t* desc = jack_get_descriptor(); 00518 00519 Jack::JackArgParser parser ( load_init ); 00520 if ( parser.GetArgc() > 0 ) 00521 parse_params = parser.ParseParams ( desc, ¶ms ); 00522 00523 if (parse_params) { 00524 res = jack_internal_initialize ( jack_client, params ); 00525 parser.FreeParams ( params ); 00526 } 00527 return res; 00528 } 00529 00530 SERVER_EXPORT void jack_finish ( void* arg ) 00531 { 00532 Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg ); 00533 00534 if (adapter) { 00535 jack_log ( "Unloading netadapter" ); 00536 adapter->Close(); 00537 delete adapter; 00538 } 00539 } 00540 00541 #ifdef __cplusplus 00542 } 00543 #endif