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