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