00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
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
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
00110 bool JackNetMaster::Init(bool auto_connect)
00111 {
00112
00113 if (!JackNetMasterInterface::Init()) {
00114 jack_error("JackNetMasterInterface::Init() error...");
00115 return false;
00116 }
00117
00118
00119 if (!SetParams()) {
00120 jack_error("SetParams error...");
00121 return false;
00122 }
00123
00124
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
00149
00150
00151
00152
00153 if (AllocPorts() != 0) {
00154 jack_error("Can't allocate JACK ports");
00155 goto fail;
00156 }
00157
00158
00159 fRunning = true;
00160
00161
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
00181 int JackNetMaster::AllocPorts()
00182 {
00183 int i;
00184 char name[32];
00185 jack_log("JackNetMaster::AllocPorts");
00186
00187
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
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
00266 void JackNetMaster::EncodeTransportData()
00267 {
00268
00269
00270 fSendTransportData.fTimebaseMaster = NO_CHANGE;
00271
00272
00273 fSendTransportData.fState = static_cast<uint>(jack_transport_query(fClient, &fSendTransportData.fPosition));
00274
00275
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
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
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
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
00400 for (int i = 0; i < obj->fParams.fSendAudioChannels; i++) {
00401
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
00407 for (int i = 0; i < obj->fParams.fReturnAudioChannels; i++) {
00408
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
00414 for (int i = 0; i < obj->fParams.fSendMidiChannels; i++) {
00415
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
00421 for (int i = 0; i < obj->fParams.fReturnMidiChannels; i++) {
00422
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
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
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
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
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
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
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
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
00542 break;
00543
00544 default:
00545
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
00556 res = DataRecv();
00557 switch (res) {
00558
00559 case 0:
00560 case SOCKET_ERROR:
00561 return res;
00562
00563 case DATA_PACKET_ERROR:
00564
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
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
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
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
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
00690 jack_set_sync_callback(fClient, SetSyncCallback, this);
00691
00692
00693 if (jack_activate(fClient) != 0) {
00694 jack_error("Can't activate the NetManager client, transport disabled");
00695 }
00696
00697
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
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
00773 int attempt = 0;
00774
00775
00776 session_params_t host_params;
00777 int rx_bytes = 0;
00778 JackNetMaster* net_master;
00779
00780
00781 if (SocketAPIInit() < 0) {
00782 jack_error("Can't init Socket API, exiting...");
00783 return;
00784 }
00785
00786
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
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
00800 if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
00801 jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
00802 }
00803
00804
00805 if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
00806 jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
00807 }
00808
00809
00810 if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
00811 jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
00812 }
00813
00814
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
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
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
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 }
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