Jack2 1.9.7
|
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 "JackNetManager.h" 00020 #include "JackArgParser.h" 00021 #include "JackTime.h" 00022 00023 using namespace std; 00024 00025 namespace Jack 00026 { 00027 //JackNetMaster****************************************************************************************************** 00028 00029 JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip) 00030 : JackNetMasterInterface ( params, socket, multicast_ip ) 00031 { 00032 jack_log ( "JackNetMaster::JackNetMaster" ); 00033 00034 //settings 00035 fClientName = const_cast<char*> ( fParams.fName ); 00036 fJackClient = NULL; 00037 fSendTransportData.fState = -1; 00038 fReturnTransportData.fState = -1; 00039 fLastTransportState = -1; 00040 uint port_index; 00041 00042 //jack audio ports 00043 fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels]; 00044 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ ) 00045 fAudioCapturePorts[port_index] = NULL; 00046 fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels]; 00047 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) 00048 fAudioPlaybackPorts[port_index] = NULL; 00049 //jack midi ports 00050 fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels]; 00051 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ ) 00052 fMidiCapturePorts[port_index] = NULL; 00053 fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels]; 00054 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ ) 00055 fMidiPlaybackPorts[port_index] = NULL; 00056 00057 //monitor 00058 #ifdef JACK_MONITOR 00059 fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) ); 00060 string plot_name; 00061 plot_name = string ( fParams.fName ); 00062 plot_name += string ( "_master" ); 00063 plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" ); 00064 switch ( fParams.fNetworkMode ) 00065 { 00066 case 's' : 00067 plot_name += string ( "_slow" ); 00068 break; 00069 case 'n' : 00070 plot_name += string ( "_normal" ); 00071 break; 00072 case 'f' : 00073 plot_name += string ( "_fast" ); 00074 break; 00075 } 00076 fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name ); 00077 string net_time_mon_fields[] = 00078 { 00079 string ( "sync send" ), 00080 string ( "end of send" ), 00081 string ( "sync recv" ), 00082 string ( "end of cycle" ) 00083 }; 00084 string net_time_mon_options[] = 00085 { 00086 string ( "set xlabel \"audio cycles\"" ), 00087 string ( "set ylabel \"% of audio cycle\"" ) 00088 }; 00089 fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 ); 00090 #endif 00091 } 00092 00093 JackNetMaster::~JackNetMaster() 00094 { 00095 jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams.fID ); 00096 00097 if ( fJackClient ) 00098 { 00099 jack_deactivate ( fJackClient ); 00100 FreePorts(); 00101 jack_client_close ( fJackClient ); 00102 } 00103 delete[] fAudioCapturePorts; 00104 delete[] fAudioPlaybackPorts; 00105 delete[] fMidiCapturePorts; 00106 delete[] fMidiPlaybackPorts; 00107 #ifdef JACK_MONITOR 00108 fNetTimeMon->Save(); 00109 delete fNetTimeMon; 00110 #endif 00111 } 00112 //init-------------------------------------------------------------------------------- 00113 bool JackNetMaster::Init(bool auto_connect) 00114 { 00115 //network init 00116 if ( !JackNetMasterInterface::Init() ) 00117 return false; 00118 00119 //set global parameters 00120 SetParams(); 00121 00122 //jack client and process 00123 jack_status_t status; 00124 if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL ) 00125 { 00126 jack_error ( "Can't open a new jack client." ); 00127 return false; 00128 } 00129 00130 if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0) 00131 goto fail; 00132 00133 if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0) 00134 goto fail; 00135 00136 if ( AllocPorts() != 0 ) 00137 { 00138 jack_error ( "Can't allocate jack ports." ); 00139 goto fail; 00140 } 00141 00142 //process can now run 00143 fRunning = true; 00144 00145 //finally activate jack client 00146 if ( jack_activate ( fJackClient ) != 0 ) 00147 { 00148 jack_error ( "Can't activate jack client." ); 00149 goto fail; 00150 } 00151 00152 if (auto_connect) 00153 ConnectPorts(); 00154 jack_info ( "New NetMaster started." ); 00155 return true; 00156 00157 fail: 00158 FreePorts(); 00159 jack_client_close ( fJackClient ); 00160 fJackClient = NULL; 00161 return false; 00162 } 00163 00164 //jack ports-------------------------------------------------------------------------- 00165 int JackNetMaster::AllocPorts() 00166 { 00167 uint i; 00168 char name[24]; 00169 jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient ); 00170 jack_latency_range_t range; 00171 00172 jack_log ( "JackNetMaster::AllocPorts" ); 00173 00174 //audio 00175 for ( i = 0; i < fParams.fSendAudioChannels; i++ ) 00176 { 00177 sprintf ( name, "to_slave_%d", i+1 ); 00178 if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) 00179 return -1; 00180 //port latency 00181 range.min = range.max = 0; 00182 jack_port_set_latency_range(fAudioCapturePorts[i], JackCaptureLatency, &range); 00183 } 00184 00185 for ( i = 0; i < fParams.fReturnAudioChannels; i++ ) 00186 { 00187 sprintf ( name, "from_slave_%d", i+1 ); 00188 if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) 00189 return -1; 00190 //port latency 00191 switch ( fParams.fNetworkMode ) 00192 { 00193 case 'f' : 00194 range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency; 00195 jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); 00196 break; 00197 case 'n' : 00198 range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; 00199 jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); 00200 break; 00201 case 's' : 00202 range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; 00203 jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range); 00204 break; 00205 } 00206 } 00207 00208 00209 //midi 00210 for ( i = 0; i < fParams.fSendMidiChannels; i++ ) 00211 { 00212 sprintf ( name, "midi_to_slave_%d", i+1 ); 00213 if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) 00214 return -1; 00215 //port latency 00216 range.min = range.max = 0; 00217 jack_port_set_latency_range(fMidiCapturePorts[i], JackCaptureLatency, &range); 00218 } 00219 for ( i = 0; i < fParams.fReturnMidiChannels; i++ ) 00220 { 00221 sprintf ( name, "midi_from_slave_%d", i+1 ); 00222 if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) 00223 return -1; 00224 //port latency 00225 switch ( fParams.fNetworkMode ) 00226 { 00227 case 'f' : 00228 range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency; 00229 jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); 00230 break; 00231 case 'n' : 00232 range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; 00233 jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); 00234 break; 00235 case 's' : 00236 range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; 00237 jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range); 00238 break; 00239 } 00240 } 00241 return 0; 00242 } 00243 00244 void JackNetMaster::ConnectPorts() 00245 { 00246 const char **ports; 00247 00248 ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); 00249 if (ports != NULL) { 00250 for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) { 00251 jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i])); 00252 } 00253 free(ports); 00254 } 00255 00256 ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); 00257 if (ports != NULL) { 00258 for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) { 00259 jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]); 00260 } 00261 free(ports); 00262 } 00263 } 00264 00265 void JackNetMaster::FreePorts() 00266 { 00267 jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID ); 00268 00269 uint port_index; 00270 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ ) 00271 if ( fAudioCapturePorts[port_index] ) 00272 jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] ); 00273 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) 00274 if ( fAudioPlaybackPorts[port_index] ) 00275 jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] ); 00276 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ ) 00277 if ( fMidiCapturePorts[port_index] ) 00278 jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] ); 00279 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ ) 00280 if ( fMidiPlaybackPorts[port_index] ) 00281 jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] ); 00282 } 00283 00284 //transport--------------------------------------------------------------------------- 00285 void JackNetMaster::EncodeTransportData() 00286 { 00287 //is there a new timebase master ? 00288 //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value... 00289 fSendTransportData.fTimebaseMaster = NO_CHANGE; 00290 00291 //update state and position 00292 fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) ); 00293 00294 //is it a new state ? 00295 fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) && 00296 ( fSendTransportData.fState != fReturnTransportData.fState ) ); 00297 if ( fSendTransportData.fNewState ) 00298 jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame ); 00299 fLastTransportState = fSendTransportData.fState; 00300 } 00301 00302 void JackNetMaster::DecodeTransportData() 00303 { 00304 //is there timebase master change ? 00305 if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE ) 00306 { 00307 int timebase = 0; 00308 switch ( fReturnTransportData.fTimebaseMaster ) 00309 { 00310 case RELEASE_TIMEBASEMASTER : 00311 timebase = jack_release_timebase ( fJackClient ); 00312 if ( timebase < 0 ) 00313 jack_error ( "Can't release timebase master." ); 00314 else 00315 jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName ); 00316 break; 00317 00318 case TIMEBASEMASTER : 00319 timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this ); 00320 if ( timebase < 0 ) 00321 jack_error ( "Can't set a new timebase master." ); 00322 else 00323 jack_info ( "'%s' is the new timebase master.", fParams.fName ); 00324 break; 00325 00326 case CONDITIONAL_TIMEBASEMASTER : 00327 timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this ); 00328 if ( timebase != EBUSY ) 00329 { 00330 if ( timebase < 0 ) 00331 jack_error ( "Can't set a new timebase master." ); 00332 else 00333 jack_info ( "'%s' is the new timebase master.", fParams.fName ); 00334 } 00335 break; 00336 } 00337 } 00338 00339 //is the slave in a new transport state and is this state different from master's ? 00340 if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) ) 00341 { 00342 switch ( fReturnTransportData.fState ) 00343 { 00344 case JackTransportStopped : 00345 jack_transport_stop ( fJackClient ); 00346 jack_info ( "'%s' stops transport.", fParams.fName ); 00347 break; 00348 00349 case JackTransportStarting : 00350 if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL ) 00351 jack_error ( "Can't set new position." ); 00352 jack_transport_start ( fJackClient ); 00353 jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame); 00354 break; 00355 00356 case JackTransportNetStarting : 00357 jack_info ( "'%s' is ready to roll..", fParams.fName ); 00358 break; 00359 00360 case JackTransportRolling : 00361 jack_info ( "'%s' is rolling.", fParams.fName ); 00362 break; 00363 } 00364 } 00365 } 00366 00367 void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg ) 00368 { 00369 static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos ); 00370 } 00371 00372 void JackNetMaster::TimebaseCallback ( jack_position_t* pos ) 00373 { 00374 pos->bar = fReturnTransportData.fPosition.bar; 00375 pos->beat = fReturnTransportData.fPosition.beat; 00376 pos->tick = fReturnTransportData.fPosition.tick; 00377 pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick; 00378 pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar; 00379 pos->beat_type = fReturnTransportData.fPosition.beat_type; 00380 pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat; 00381 pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute; 00382 } 00383 00384 //sync-------------------------------------------------------------------------------- 00385 00386 bool JackNetMaster::IsSlaveReadyToRoll() 00387 { 00388 return ( fReturnTransportData.fState == JackTransportNetStarting ); 00389 } 00390 00391 int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg) 00392 { 00393 JackNetMaster* obj = static_cast<JackNetMaster*>(arg); 00394 if (nframes != obj->fParams.fPeriodSize) { 00395 jack_error("Cannot handle bufer size change, so JackNetMaster proxy will be removed..."); 00396 obj->Exit(); 00397 } 00398 return 0; 00399 } 00400 00401 //process----------------------------------------------------------------------------- 00402 int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg ) 00403 { 00404 return static_cast<JackNetMaster*> ( arg )->Process(); 00405 } 00406 00407 int JackNetMaster::Process() 00408 { 00409 if ( !fRunning ) 00410 return 0; 00411 00412 uint port_index; 00413 int res = 0; 00414 00415 #ifdef JACK_MONITOR 00416 jack_time_t begin_time = GetMicroSeconds(); 00417 fNetTimeMon->New(); 00418 #endif 00419 00420 //buffers 00421 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ ) 00422 fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index], 00423 fParams.fPeriodSize ) ) ); 00424 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ ) 00425 fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index], 00426 fParams.fPeriodSize ) ) ); 00427 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ ) 00428 fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index], 00429 fParams.fPeriodSize ) ) ); 00430 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) 00431 fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index], 00432 fParams.fPeriodSize ) ) ); 00433 00434 if (IsSynched()) { // only send if connection is "synched" 00435 00436 //encode the first packet 00437 EncodeSyncPacket(); 00438 00439 //send sync 00440 if ( SyncSend() == SOCKET_ERROR ) 00441 return SOCKET_ERROR; 00442 00443 #ifdef JACK_MONITOR 00444 fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f ); 00445 #endif 00446 00447 //send data 00448 if ( DataSend() == SOCKET_ERROR ) 00449 return SOCKET_ERROR; 00450 00451 #ifdef JACK_MONITOR 00452 fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f ); 00453 #endif 00454 00455 } else { 00456 jack_error("Connection is not synched, skip cycle..."); 00457 } 00458 00459 //receive sync 00460 res = SyncRecv(); 00461 if ( ( res == 0 ) || ( res == SOCKET_ERROR ) ) 00462 return res; 00463 00464 #ifdef JACK_MONITOR 00465 fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f ); 00466 #endif 00467 00468 //decode sync 00469 DecodeSyncPacket(); 00470 00471 //receive data 00472 res = DataRecv(); 00473 if ( ( res == 0 ) || ( res == SOCKET_ERROR ) ) 00474 return res; 00475 00476 #ifdef JACK_MONITOR 00477 fNetTimeMon->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f ); 00478 #endif 00479 return 0; 00480 } 00481 00482 //JackNetMasterManager*********************************************************************************************** 00483 00484 JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket() 00485 { 00486 jack_log ( "JackNetMasterManager::JackNetMasterManager" ); 00487 00488 fManagerClient = client; 00489 fManagerName = jack_get_client_name ( fManagerClient ); 00490 strcpy(fMulticastIP, DEFAULT_MULTICAST_IP); 00491 fSocket.SetPort ( DEFAULT_PORT ); 00492 fGlobalID = 0; 00493 fRunning = true; 00494 fAutoConnect = false; 00495 00496 const JSList* node; 00497 const jack_driver_param_t* param; 00498 for ( node = params; node; node = jack_slist_next ( node ) ) 00499 { 00500 param = ( const jack_driver_param_t* ) node->data; 00501 switch ( param->character ) 00502 { 00503 case 'a' : 00504 if (strlen (param->value.str) < 32) 00505 strcpy(fMulticastIP, param->value.str); 00506 else 00507 jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); 00508 break; 00509 00510 case 'p': 00511 fSocket.SetPort ( param->value.ui ); 00512 break; 00513 00514 case 'c': 00515 fAutoConnect = param->value.i; 00516 break; 00517 } 00518 } 00519 00520 //set sync callback 00521 jack_set_sync_callback ( fManagerClient, SetSyncCallback, this ); 00522 00523 //activate the client (for sync callback) 00524 if ( jack_activate ( fManagerClient ) != 0 ) 00525 jack_error ( "Can't activate the network manager client, transport disabled." ); 00526 00527 //launch the manager thread 00528 if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) ) 00529 jack_error ( "Can't create the network manager control thread." ); 00530 } 00531 00532 JackNetMasterManager::~JackNetMasterManager() 00533 { 00534 jack_log ( "JackNetMasterManager::~JackNetMasterManager" ); 00535 jack_info ( "Exiting net manager..." ); 00536 fRunning = false; 00537 jack_client_kill_thread ( fManagerClient, fManagerThread ); 00538 master_list_t::iterator it; 00539 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) 00540 delete ( *it ); 00541 fSocket.Close(); 00542 SocketAPIEnd(); 00543 } 00544 00545 int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg ) 00546 { 00547 return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos ); 00548 } 00549 00550 int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos ) 00551 { 00552 //check if each slave is ready to roll 00553 int ret = 1; 00554 master_list_it_t it; 00555 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) 00556 if ( ! ( *it )->IsSlaveReadyToRoll() ) 00557 ret = 0; 00558 jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" ); 00559 return ret; 00560 } 00561 00562 void* JackNetMasterManager::NetManagerThread ( void* arg ) 00563 { 00564 JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg ); 00565 jack_info ( "Starting Jack Network Manager." ); 00566 jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() ); 00567 master_manager->Run(); 00568 return NULL; 00569 } 00570 00571 void JackNetMasterManager::Run() 00572 { 00573 jack_log ( "JackNetMasterManager::Run" ); 00574 //utility variables 00575 int attempt = 0; 00576 00577 //data 00578 session_params_t host_params; 00579 int rx_bytes = 0; 00580 JackNetMaster* net_master; 00581 00582 //init socket API (win32) 00583 if ( SocketAPIInit() < 0 ) 00584 { 00585 jack_error ( "Can't init Socket API, exiting..." ); 00586 return; 00587 } 00588 00589 //socket 00590 if ( fSocket.NewSocket() == SOCKET_ERROR ) 00591 { 00592 jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) ); 00593 return; 00594 } 00595 00596 //bind the socket to the local port 00597 if ( fSocket.Bind() == SOCKET_ERROR ) 00598 { 00599 jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) ); 00600 fSocket.Close(); 00601 return; 00602 } 00603 00604 //join multicast group 00605 if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR ) 00606 jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) ); 00607 00608 //local loop 00609 if ( fSocket.SetLocalLoop() == SOCKET_ERROR ) 00610 jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) ); 00611 00612 //set a timeout on the multicast receive (the thread can now be cancelled) 00613 if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR ) 00614 jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) ); 00615 00616 jack_info ( "Waiting for a slave..." ); 00617 00618 //main loop, wait for data, deal with it and wait again 00619 do 00620 { 00621 session_params_t net_params; 00622 rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 ); 00623 SessionParamsNToH(&net_params, &host_params); 00624 if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) 00625 { 00626 jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) ); 00627 if ( ++attempt == 10 ) 00628 { 00629 jack_error ( "Can't receive on the socket, exiting net manager." ); 00630 return; 00631 } 00632 } 00633 if ( rx_bytes == sizeof ( session_params_t ) ) 00634 { 00635 switch ( GetPacketType ( &host_params ) ) 00636 { 00637 case SLAVE_AVAILABLE: 00638 if ( ( net_master = InitMaster ( host_params ) ) ) 00639 SessionParamsDisplay ( &net_master->fParams ); 00640 else 00641 jack_error ( "Can't init new net master..." ); 00642 jack_info ( "Waiting for a slave..." ); 00643 break; 00644 case KILL_MASTER: 00645 if ( KillMaster ( &host_params ) ) 00646 jack_info ( "Waiting for a slave..." ); 00647 break; 00648 default: 00649 break; 00650 } 00651 } 00652 } 00653 while ( fRunning ); 00654 } 00655 00656 JackNetMaster* JackNetMasterManager::InitMaster ( session_params_t& params ) 00657 { 00658 jack_log ( "JackNetMasterManager::InitMaster, Slave : %s", params.fName ); 00659 00660 //check MASTER <<==> SLAVE network protocol coherency 00661 if (params.fProtocolVersion != MASTER_PROTOCOL) { 00662 jack_error ( "Error : slave is running with a different protocol %s", params.fName ); 00663 return NULL; 00664 } 00665 00666 //settings 00667 fSocket.GetName ( params.fMasterNetName ); 00668 params.fID = ++fGlobalID; 00669 params.fSampleRate = jack_get_sample_rate ( fManagerClient ); 00670 params.fPeriodSize = jack_get_buffer_size ( fManagerClient ); 00671 params.fBitdepth = 0; 00672 SetSlaveName ( params ); 00673 00674 //create a new master and add it to the list 00675 JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP); 00676 if ( master->Init(fAutoConnect) ) 00677 { 00678 fMasterList.push_back ( master ); 00679 return master; 00680 } 00681 delete master; 00682 return NULL; 00683 } 00684 00685 void JackNetMasterManager::SetSlaveName ( session_params_t& params ) 00686 { 00687 jack_log ( "JackNetMasterManager::SetSlaveName" ); 00688 00689 master_list_it_t it; 00690 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) 00691 if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 ) 00692 sprintf ( params.fName, "%s-%u", params.fName, params.fID ); 00693 } 00694 00695 master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id ) 00696 { 00697 jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id ); 00698 00699 master_list_it_t it; 00700 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) 00701 if ( ( *it )->fParams.fID == id ) 00702 return it; 00703 return it; 00704 } 00705 00706 int JackNetMasterManager::KillMaster ( session_params_t* params ) 00707 { 00708 jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID ); 00709 00710 master_list_it_t master = FindMaster ( params->fID ); 00711 if ( master != fMasterList.end() ) 00712 { 00713 fMasterList.erase ( master ); 00714 delete *master; 00715 return 1; 00716 } 00717 return 0; 00718 } 00719 }//namespace 00720 00721 static Jack::JackNetMasterManager* master_manager = NULL; 00722 00723 #ifdef __cplusplus 00724 extern "C" 00725 { 00726 #endif 00727 00728 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() 00729 { 00730 jack_driver_desc_t *desc; 00731 desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); 00732 00733 strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 00734 strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 00735 00736 desc->nparams = 3; 00737 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); 00738 00739 int i = 0; 00740 strcpy ( desc->params[i].name, "multicast_ip" ); 00741 desc->params[i].character = 'a'; 00742 desc->params[i].type = JackDriverParamString; 00743 strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP ); 00744 strcpy ( desc->params[i].short_desc, "Multicast Address" ); 00745 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00746 00747 i++; 00748 strcpy ( desc->params[i].name, "udp_net_port" ); 00749 desc->params[i].character = 'p'; 00750 desc->params[i].type = JackDriverParamInt; 00751 desc->params[i].value.i = DEFAULT_PORT; 00752 strcpy ( desc->params[i].short_desc, "UDP port" ); 00753 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00754 00755 i++; 00756 strcpy ( desc->params[i].name, "auto_connect" ); 00757 desc->params[i].character = 'c'; 00758 desc->params[i].type = JackDriverParamBool; 00759 desc->params[i].value.i = false; 00760 strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" ); 00761 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00762 00763 return desc; 00764 } 00765 00766 SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params ) 00767 { 00768 if ( master_manager ) 00769 { 00770 jack_error ( "Master Manager already loaded" ); 00771 return 1; 00772 } 00773 else 00774 { 00775 jack_log ( "Loading Master Manager" ); 00776 master_manager = new Jack::JackNetMasterManager ( jack_client, params ); 00777 return ( master_manager ) ? 0 : 1; 00778 } 00779 } 00780 00781 SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init ) 00782 { 00783 JSList* params = NULL; 00784 bool parse_params = true; 00785 int res = 1; 00786 jack_driver_desc_t* desc = jack_get_descriptor(); 00787 00788 Jack::JackArgParser parser ( load_init ); 00789 if ( parser.GetArgc() > 0 ) 00790 parse_params = parser.ParseParams ( desc, ¶ms ); 00791 00792 if (parse_params) { 00793 res = jack_internal_initialize ( jack_client, params ); 00794 parser.FreeParams ( params ); 00795 } 00796 return res; 00797 } 00798 00799 SERVER_EXPORT void jack_finish ( void* arg ) 00800 { 00801 if ( master_manager ) 00802 { 00803 jack_log ( "Unloading Master Manager" ); 00804 delete master_manager; 00805 master_manager = NULL; 00806 } 00807 } 00808 #ifdef __cplusplus 00809 } 00810 #endif