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