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(JackServerGlobals::fInstance->GetEngineControl()->fPeriod,
00230 JackServerGlobals::fInstance->GetEngineControl()->fComputation,
00231 JackServerGlobals::fInstance->GetEngineControl()->fConstraint);
00232
00233 if (fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority ) < 0) {
00234 jack_error("AcquireRealTime error");
00235 } else {
00236 set_threaded_log_function();
00237 }
00238
00239
00240 SessionParamsDisplay ( &fParams );
00241 return true;
00242 }
00243
00244 bool JackNetAdapter::Execute()
00245 {
00246 try {
00247
00248 while (fThread.GetStatus() == JackThread::kRunning)
00249 if (Process() == SOCKET_ERROR)
00250 return false;
00251 return false;
00252 } catch (JackNetException& e) {
00253 e.PrintMessage();
00254 jack_info("NetAdapter is restarted.");
00255 Reset();
00256 fThread.DropRealTime();
00257 fThread.SetStatus(JackThread::kIniting);
00258 if (Init()) {
00259 fThread.SetStatus(JackThread::kRunning);
00260 return true;
00261 } else {
00262 return false;
00263 }
00264 }
00265 }
00266
00267
00268 void JackNetAdapter::DecodeTransportData()
00269 {
00270
00271
00272
00273 if ( fSendTransportData.fNewState && ( fSendTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
00274 {
00275 switch ( fSendTransportData.fState )
00276 {
00277 case JackTransportStopped :
00278 jack_transport_stop ( fJackClient );
00279 jack_info ( "NetMaster : transport stops." );
00280 break;
00281
00282 case JackTransportStarting :
00283 jack_transport_reposition ( fJackClient, &fSendTransportData.fPosition );
00284 jack_transport_start ( fJackClient );
00285 jack_info ( "NetMaster : transport starts." );
00286 break;
00287
00288 case JackTransportRolling :
00289
00290
00291
00292 jack_info ( "NetMaster : transport rolls." );
00293 break;
00294 }
00295 }
00296 }
00297
00298 void JackNetAdapter::EncodeTransportData()
00299 {
00300
00301 int refnum = -1;
00302 bool conditional = 0;
00303
00304 if ( refnum != fLastTimebaseMaster )
00305 {
00306
00307 if ( refnum == -1 )
00308 {
00309 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00310 jack_info ( "Sending a timebase master release request." );
00311 }
00312
00313 else
00314 {
00315 fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
00316 jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" );
00317 }
00318 fLastTimebaseMaster = refnum;
00319 }
00320 else
00321 fReturnTransportData.fTimebaseMaster = NO_CHANGE;
00322
00323
00324 fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition );
00325
00326
00327 fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) &&
00328 ( fReturnTransportData.fState != fSendTransportData.fState ) );
00329 if ( fReturnTransportData.fNewState )
00330 jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) );
00331 fLastTransportState = fReturnTransportData.fState;
00332 }
00333
00334
00335 int JackNetAdapter::Read()
00336 {
00337
00338
00339 if ( SyncRecv() == SOCKET_ERROR )
00340 return 0;
00341
00342 DecodeSyncPacket();
00343 return DataRecv();
00344 }
00345
00346 int JackNetAdapter::Write()
00347 {
00348 EncodeSyncPacket();
00349
00350 if ( SyncSend() == SOCKET_ERROR )
00351 return SOCKET_ERROR;
00352
00353 return DataSend();
00354 }
00355
00356
00357 int JackNetAdapter::Process()
00358 {
00359
00360
00361 if (Read() == SOCKET_ERROR)
00362 return SOCKET_ERROR;
00363
00364 PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
00365
00366
00367
00368 if (Write() == SOCKET_ERROR)
00369 return SOCKET_ERROR;
00370
00371 return 0;
00372 }
00373
00374 }
00375
00376
00377 #ifdef __cplusplus
00378 extern "C"
00379 {
00380 #endif
00381
00382 #include "driver_interface.h"
00383 #include "JackAudioAdapter.h"
00384
00385 using namespace Jack;
00386
00387 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00388 {
00389 jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
00390
00391 strcpy(desc->name, "netadapter");
00392 strcpy(desc->desc, "netjack net <==> audio backend adapter");
00393
00394 desc->nparams = 11;
00395 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
00396
00397 int i = 0;
00398 strcpy ( desc->params[i].name, "multicast_ip" );
00399 desc->params[i].character = 'a';
00400 desc->params[i].type = JackDriverParamString;
00401 strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
00402 strcpy ( desc->params[i].short_desc, "Multicast Address" );
00403 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00404
00405 i++;
00406 strcpy ( desc->params[i].name, "udp_net_port" );
00407 desc->params[i].character = 'p';
00408 desc->params[i].type = JackDriverParamInt;
00409 desc->params[i].value.i = DEFAULT_PORT;
00410 strcpy ( desc->params[i].short_desc, "UDP port" );
00411 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00412
00413 i++;
00414 strcpy ( desc->params[i].name, "mtu" );
00415 desc->params[i].character = 'M';
00416 desc->params[i].type = JackDriverParamInt;
00417 desc->params[i].value.i = DEFAULT_MTU;
00418 strcpy ( desc->params[i].short_desc, "MTU to the master" );
00419 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00420
00421 i++;
00422 strcpy ( desc->params[i].name, "input-ports" );
00423 desc->params[i].character = 'C';
00424 desc->params[i].type = JackDriverParamInt;
00425 desc->params[i].value.i = 2;
00426 strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
00427 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00428
00429 i++;
00430 strcpy ( desc->params[i].name, "output-ports" );
00431 desc->params[i].character = 'P';
00432 desc->params[i].type = JackDriverParamInt;
00433 desc->params[i].value.i = 2;
00434 strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
00435 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00436
00437 i++;
00438 strcpy ( desc->params[i].name, "client-name" );
00439 desc->params[i].character = 'n';
00440 desc->params[i].type = JackDriverParamString;
00441 strcpy ( desc->params[i].value.str, "'hostname'" );
00442 strcpy ( desc->params[i].short_desc, "Name of the jack client" );
00443 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00444
00445 i++;
00446 strcpy ( desc->params[i].name, "transport-sync" );
00447 desc->params[i].character = 't';
00448 desc->params[i].type = JackDriverParamUInt;
00449 desc->params[i].value.ui = 1U;
00450 strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
00451 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00452
00453 i++;
00454 strcpy ( desc->params[i].name, "mode" );
00455 desc->params[i].character = 'm';
00456 desc->params[i].type = JackDriverParamString;
00457 strcpy ( desc->params[i].value.str, "slow" );
00458 strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
00459 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00460
00461 i++;
00462 strcpy(desc->params[i].name, "quality");
00463 desc->params[i].character = 'q';
00464 desc->params[i].type = JackDriverParamInt;
00465 desc->params[i].value.ui = 0;
00466 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
00467 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00468
00469 i++;
00470 strcpy(desc->params[i].name, "ring-buffer");
00471 desc->params[i].character = 'g';
00472 desc->params[i].type = JackDriverParamInt;
00473 desc->params[i].value.ui = 32768;
00474 strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
00475 strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
00476
00477 i++;
00478 strcpy ( desc->params[i].name, "auto-connect" );
00479 desc->params[i].character = 'c';
00480 desc->params[i].type = JackDriverParamBool;
00481 desc->params[i].value.i = false;
00482 strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" );
00483 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00484
00485 return desc;
00486 }
00487
00488 SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
00489 {
00490 jack_log ( "Loading netadapter" );
00491
00492 Jack::JackAudioAdapter* adapter;
00493 jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
00494 jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
00495
00496 try {
00497
00498 adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false);
00499 assert ( adapter );
00500
00501 if ( adapter->Open() == 0 )
00502 return 0;
00503 else
00504 {
00505 delete adapter;
00506 return 1;
00507 }
00508
00509 } catch (...) {
00510 return 1;
00511 }
00512 }
00513
00514 SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
00515 {
00516 JSList* params = NULL;
00517 bool parse_params = true;
00518 int res = 1;
00519 jack_driver_desc_t* desc = jack_get_descriptor();
00520
00521 Jack::JackArgParser parser ( load_init );
00522 if ( parser.GetArgc() > 0 )
00523 parse_params = parser.ParseParams ( desc, ¶ms );
00524
00525 if (parse_params) {
00526 res = jack_internal_initialize ( jack_client, params );
00527 parser.FreeParams ( params );
00528 }
00529 return res;
00530 }
00531
00532 SERVER_EXPORT void jack_finish ( void* arg )
00533 {
00534 Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
00535
00536 if (adapter) {
00537 jack_log ( "Unloading netadapter" );
00538 adapter->Close();
00539 delete adapter;
00540 }
00541 }
00542
00543 #ifdef __cplusplus
00544 }
00545 #endif