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 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
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
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
00106 fSocket.SetPort ( port );
00107 fSocket.SetAddress ( fMulticastIP, port );
00108
00109
00110 SetInputs ( fParams.fSendAudioChannels );
00111 SetOutputs ( fParams.fReturnAudioChannels );
00112
00113
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
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
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
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
00197 bool JackNetAdapter::Init()
00198 {
00199 jack_log ( "JackNetAdapter::Init" );
00200
00201 int port_index;
00202
00203
00204 if ( !JackNetSlaveInterface::Init() )
00205 return false;
00206
00207
00208 SetParams();
00209
00210
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
00225 SetAdaptedBufferSize ( fParams.fPeriodSize );
00226 SetAdaptedSampleRate ( fParams.fSampleRate );
00227
00228
00229 fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00230
00231 if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) {
00232 jack_error("AcquireRealTime error");
00233 } else {
00234 set_threaded_log_function();
00235 }
00236
00237
00238 SessionParamsDisplay ( &fParams );
00239 return true;
00240 }
00241
00242 bool JackNetAdapter::Execute()
00243 {
00244 try {
00245
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.DropRealTime();
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
00266 void JackNetAdapter::DecodeTransportData()
00267 {
00268
00269
00270
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
00288
00289
00290 jack_info ( "NetMaster : transport rolls." );
00291 break;
00292 }
00293 }
00294 }
00295
00296 void JackNetAdapter::EncodeTransportData()
00297 {
00298
00299 int refnum = -1;
00300 bool conditional = 0;
00301
00302 if ( refnum != fLastTimebaseMaster )
00303 {
00304
00305 if ( refnum == -1 )
00306 {
00307 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00308 jack_info ( "Sending a timebase master release request." );
00309 }
00310
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
00322 fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition );
00323
00324
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
00333 int JackNetAdapter::Read()
00334 {
00335
00336
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
00355 int JackNetAdapter::Process()
00356 {
00357
00358
00359 if (Read() == SOCKET_ERROR)
00360 return SOCKET_ERROR;
00361
00362 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
00363
00364
00365
00366 if (Write() == SOCKET_ERROR)
00367 return SOCKET_ERROR;
00368
00369 return 0;
00370 }
00371
00372 }
00373
00374
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");
00390 strcpy(desc->desc, "netjack net <==> audio backend adapter");
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