00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "JackNetDriver.h"
00020 #include "JackEngineControl.h"
00021 #include "JackLockedEngine.h"
00022 #include "JackWaitThreadedDriver.h"
00023
00024 using namespace std;
00025
00026 namespace Jack
00027 {
00028 JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
00029 const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports,
00030 char* net_name, uint transport_sync, int network_latency, int celt_encoding)
00031 : JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port)
00032 {
00033 jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port);
00034
00035
00036 if (strcmp(net_name, "") == 0) {
00037 GetHostName(net_name, JACK_CLIENT_NAME_SIZE);
00038 }
00039
00040 fParams.fMtu = mtu;
00041 fParams.fSendMidiChannels = midi_input_ports;
00042 fParams.fReturnMidiChannels = midi_output_ports;
00043 if (celt_encoding > 0) {
00044 fParams.fSampleEncoder = JackCeltEncoder;
00045 fParams.fKBps = celt_encoding;
00046 } else {
00047 fParams.fSampleEncoder = JackFloatEncoder;
00048
00049 }
00050 strcpy(fParams.fName, net_name);
00051 fSocket.GetName(fParams.fSlaveNetName);
00052 fParams.fTransportSync = transport_sync;
00053 fParams.fNetworkLatency = network_latency;
00054 fSendTransportData.fState = -1;
00055 fReturnTransportData.fState = -1;
00056 fLastTransportState = -1;
00057 fLastTimebaseMaster = -1;
00058 fMidiCapturePortList = NULL;
00059 fMidiPlaybackPortList = NULL;
00060 #ifdef JACK_MONITOR
00061 fNetTimeMon = NULL;
00062 fRcvSyncUst = 0;
00063 #endif
00064 }
00065
00066 JackNetDriver::~JackNetDriver()
00067 {
00068 delete[] fMidiCapturePortList;
00069 delete[] fMidiPlaybackPortList;
00070 #ifdef JACK_MONITOR
00071 delete fNetTimeMon;
00072 #endif
00073 }
00074
00075
00076
00077 int JackNetDriver::Close()
00078 {
00079 #ifdef JACK_MONITOR
00080 if (fNetTimeMon) {
00081 fNetTimeMon->Save();
00082 }
00083 #endif
00084 FreeAll();
00085 return JackWaiterDriver::Close();
00086 }
00087
00088
00089 int JackNetDriver::Attach()
00090 {
00091 return 0;
00092 }
00093
00094 int JackNetDriver::Detach()
00095 {
00096 return 0;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105 bool JackNetDriver::Initialize()
00106 {
00107 jack_log("JackNetDriver::Initialize");
00108 SaveConnections();
00109 FreePorts();
00110
00111
00112 if (fSocket.IsSocket()) {
00113 jack_info("Restarting driver...");
00114 FreeAll();
00115 }
00116
00117
00118 fParams.fSendAudioChannels = fCaptureChannels;
00119 fParams.fReturnAudioChannels = fPlaybackChannels;
00120 fParams.fSlaveSyncMode = fEngineControl->fSyncMode;
00121
00122
00123 jack_info("NetDriver started in %s mode %s Master's transport sync.",
00124 (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
00125
00126
00127 if (!JackNetSlaveInterface::Init()) {
00128 jack_error("Starting network fails...");
00129 return false;
00130 }
00131
00132
00133 if (!SetParams()) {
00134 jack_error("SetParams error...");
00135 return false;
00136 }
00137
00138
00139 fCaptureChannels = fParams.fSendAudioChannels;
00140 fPlaybackChannels = fParams.fReturnAudioChannels;
00141
00142
00143 fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels];
00144 fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels];
00145
00146 assert(fMidiCapturePortList);
00147 assert(fMidiPlaybackPortList);
00148
00149 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
00150 fMidiCapturePortList[midi_port_index] = 0;
00151 }
00152 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
00153 fMidiPlaybackPortList[midi_port_index] = 0;
00154 }
00155
00156
00157 if (AllocPorts() != 0) {
00158 jack_error("Can't allocate ports.");
00159 return false;
00160 }
00161
00162
00163 SessionParamsDisplay(&fParams);
00164
00165
00166 #ifdef JACK_MONITOR
00167 string plot_name;
00168
00169 plot_name = string(fParams.fName);
00170 plot_name += string("_slave");
00171 plot_name += (fEngineControl->fSyncMode) ? string("_sync") : string("_async");
00172 plot_name += string("_latency");
00173 fNetTimeMon = new JackGnuPlotMonitor<float>(128, 5, plot_name);
00174 string net_time_mon_fields[] =
00175 {
00176 string("sync decoded"),
00177 string("end of read"),
00178 string("start of write"),
00179 string("sync send"),
00180 string("end of write")
00181 };
00182 string net_time_mon_options[] =
00183 {
00184 string("set xlabel \"audio cycles\""),
00185 string("set ylabel \"% of audio cycle\"")
00186 };
00187 fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 5);
00188 #endif
00189
00190 JackTimedDriver::SetBufferSize(fParams.fPeriodSize);
00191 JackTimedDriver::SetSampleRate(fParams.fSampleRate);
00192
00193 JackDriver::NotifyBufferSize(fParams.fPeriodSize);
00194 JackDriver::NotifySampleRate(fParams.fSampleRate);
00195
00196
00197 fEngineControl->fTransport.SetNetworkSync(fParams.fTransportSync);
00198
00199 RestoreConnections();
00200 return true;
00201 }
00202
00203 void JackNetDriver::FreeAll()
00204 {
00205 FreePorts();
00206
00207 delete[] fTxBuffer;
00208 delete[] fRxBuffer;
00209 delete fNetAudioCaptureBuffer;
00210 delete fNetAudioPlaybackBuffer;
00211 delete fNetMidiCaptureBuffer;
00212 delete fNetMidiPlaybackBuffer;
00213 delete[] fMidiCapturePortList;
00214 delete[] fMidiPlaybackPortList;
00215
00216 fTxBuffer = NULL;
00217 fRxBuffer = NULL;
00218 fNetAudioCaptureBuffer = NULL;
00219 fNetAudioPlaybackBuffer = NULL;
00220 fNetMidiCaptureBuffer = NULL;
00221 fNetMidiPlaybackBuffer = NULL;
00222 fMidiCapturePortList = NULL;
00223 fMidiPlaybackPortList = NULL;
00224
00225 #ifdef JACK_MONITOR
00226 delete fNetTimeMon;
00227 fNetTimeMon = NULL;
00228 #endif
00229 }
00230
00231
00232 int JackNetDriver::AllocPorts()
00233 {
00234 jack_log("JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 JackPort* port;
00246 jack_port_id_t port_index;
00247 char name[REAL_JACK_PORT_NAME_SIZE];
00248 char alias[REAL_JACK_PORT_NAME_SIZE];
00249 int audio_port_index;
00250 int midi_port_index;
00251 jack_latency_range_t range;
00252
00253
00254 for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) {
00255 snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1);
00256 snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, audio_port_index + 1);
00257 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
00258 CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00259 jack_error("driver: cannot register port for %s", name);
00260 return -1;
00261 }
00262
00263
00264 port = fGraphManager->GetPort(port_index);
00265 port->SetAlias(alias);
00266 range.min = range.max = fEngineControl->fBufferSize;
00267 port->SetLatencyRange(JackCaptureLatency, &range);
00268 fCapturePortList[audio_port_index] = port_index;
00269 jack_log("JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency());
00270 }
00271
00272 for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
00273 snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1);
00274 snprintf(name, sizeof(name), "%s:playback_%d",fClientControl.fName, audio_port_index + 1);
00275 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
00276 PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00277 jack_error("driver: cannot register port for %s", name);
00278 return -1;
00279 }
00280
00281
00282 port = fGraphManager->GetPort(port_index);
00283 port->SetAlias(alias);
00284 range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
00285 port->SetLatencyRange(JackPlaybackLatency, &range);
00286 fPlaybackPortList[audio_port_index] = port_index;
00287 jack_log("JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency());
00288 }
00289
00290
00291 for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
00292 snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1);
00293 snprintf(name, sizeof (name), "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1);
00294 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
00295 CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00296 jack_error("driver: cannot register port for %s", name);
00297 return -1;
00298 }
00299
00300
00301 port = fGraphManager->GetPort(port_index);
00302 range.min = range.max = fEngineControl->fBufferSize;
00303 port->SetLatencyRange(JackCaptureLatency, &range);
00304 fMidiCapturePortList[midi_port_index] = port_index;
00305 jack_log("JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency());
00306 }
00307
00308 for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
00309 snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1);
00310 snprintf(name, sizeof(name), "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1);
00311 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
00312 PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00313 jack_error("driver: cannot register port for %s", name);
00314 return -1;
00315 }
00316
00317
00318 port = fGraphManager->GetPort(port_index);
00319 range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
00320 port->SetLatencyRange(JackPlaybackLatency, &range);
00321 fMidiPlaybackPortList[midi_port_index] = port_index;
00322 jack_log("JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency());
00323 }
00324
00325 return 0;
00326 }
00327
00328 int JackNetDriver::FreePorts()
00329 {
00330 jack_log("JackNetDriver::FreePorts");
00331
00332 for (int audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) {
00333 if (fCapturePortList[audio_port_index] > 0) {
00334 fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[audio_port_index]);
00335 fCapturePortList[audio_port_index] = 0;
00336 }
00337 }
00338
00339 for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
00340 if (fPlaybackPortList[audio_port_index] > 0) {
00341 fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[audio_port_index]);
00342 fPlaybackPortList[audio_port_index] = 0;
00343 }
00344 }
00345
00346 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
00347 if (fMidiCapturePortList && fMidiCapturePortList[midi_port_index] > 0) {
00348 fGraphManager->ReleasePort(fClientControl.fRefNum, fMidiCapturePortList[midi_port_index]);
00349 fMidiCapturePortList[midi_port_index] = 0;
00350 }
00351 }
00352
00353 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
00354 if (fMidiPlaybackPortList && fMidiPlaybackPortList[midi_port_index] > 0) {
00355 fEngine->PortUnRegister(fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index]);
00356 fMidiPlaybackPortList[midi_port_index] = 0;
00357 }
00358 }
00359 return 0;
00360 }
00361
00362 void JackNetDriver::SaveConnections()
00363 {
00364 JackDriver::SaveConnections();
00365 const char** connections;
00366
00367 for (int i = 0; i < fParams.fSendMidiChannels; ++i) {
00368 if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fMidiCapturePortList[i])) != 0) {
00369 for (int j = 0; connections[j]; j++) {
00370 fConnections.push_back(make_pair(fGraphManager->GetPort(fMidiCapturePortList[i])->GetName(), connections[j]));
00371 }
00372 free(connections);
00373 }
00374 }
00375
00376 for (int i = 0; i < fParams.fReturnMidiChannels; ++i) {
00377 if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fMidiPlaybackPortList[i])) != 0) {
00378 for (int j = 0; connections[j]; j++) {
00379 fConnections.push_back(make_pair(connections[j], fGraphManager->GetPort(fMidiPlaybackPortList[i])->GetName()));
00380 }
00381 free(connections);
00382 }
00383 }
00384 }
00385
00386 JackMidiBuffer* JackNetDriver::GetMidiInputBuffer(int port_index)
00387 {
00388 return static_cast<JackMidiBuffer*>(fGraphManager->GetBuffer(fMidiCapturePortList[port_index], fEngineControl->fBufferSize));
00389 }
00390
00391 JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer(int port_index)
00392 {
00393 return static_cast<JackMidiBuffer*>(fGraphManager->GetBuffer(fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize));
00394 }
00395
00396
00397 void JackNetDriver::DecodeTransportData()
00398 {
00399
00400
00401
00402
00403 int refnum;
00404 bool conditional;
00405 if (fSendTransportData.fTimebaseMaster == TIMEBASEMASTER) {
00406 fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional);
00407 if (refnum != -1) {
00408 fEngineControl->fTransport.ResetTimebase(refnum);
00409 }
00410 jack_info("The NetMaster is now the new timebase master.");
00411 }
00412
00413
00414 if (fSendTransportData.fNewState &&(fSendTransportData.fState != fEngineControl->fTransport.GetState())) {
00415
00416 switch (fSendTransportData.fState)
00417 {
00418 case JackTransportStopped :
00419 fEngineControl->fTransport.SetCommand(TransportCommandStop);
00420 jack_info("Master stops transport.");
00421 break;
00422
00423 case JackTransportStarting :
00424 fEngineControl->fTransport.RequestNewPos(&fSendTransportData.fPosition);
00425 fEngineControl->fTransport.SetCommand(TransportCommandStart);
00426 jack_info("Master starts transport frame = %d", fSendTransportData.fPosition.frame);
00427 break;
00428
00429 case JackTransportRolling :
00430
00431 fEngineControl->fTransport.SetState(JackTransportRolling);
00432 jack_info("Master is rolling.");
00433 break;
00434 }
00435 }
00436 }
00437
00438 void JackNetDriver::EncodeTransportData()
00439 {
00440
00441 int refnum;
00442 bool conditional;
00443 fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional);
00444 if (refnum != fLastTimebaseMaster) {
00445
00446 if (refnum == -1) {
00447 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00448 jack_info("Sending a timebase master release request.");
00449 } else {
00450
00451 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
00452 jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
00453 }
00454 fLastTimebaseMaster = refnum;
00455 } else {
00456 fReturnTransportData.fTimebaseMaster = NO_CHANGE;
00457 }
00458
00459
00460 fReturnTransportData.fState = fEngineControl->fTransport.Query(&fReturnTransportData.fPosition);
00461
00462
00463 fReturnTransportData.fNewState = ((fReturnTransportData.fState == JackTransportNetStarting) &&
00464 (fReturnTransportData.fState != fLastTransportState) &&
00465 (fReturnTransportData.fState != fSendTransportData.fState));
00466 if (fReturnTransportData.fNewState) {
00467 jack_info("Sending '%s'.", GetTransportState(fReturnTransportData.fState));
00468 }
00469 fLastTransportState = fReturnTransportData.fState;
00470 }
00471
00472
00473
00474 int JackNetDriver::Read()
00475 {
00476
00477 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
00478 fNetMidiCaptureBuffer->SetBuffer(midi_port_index, GetMidiInputBuffer(midi_port_index));
00479 }
00480
00481 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
00482 #ifdef OPTIMIZED_PROTOCOL
00483 if (fGraphManager->GetConnectionsNum(fCapturePortList[audio_port_index]) > 0) {
00484 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index));
00485 } else {
00486 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL);
00487 }
00488 #else
00489 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index));
00490 #endif
00491 }
00492
00493 #ifdef JACK_MONITOR
00494 fNetTimeMon->New();
00495 #endif
00496
00497
00498 if (SyncRecv() == SOCKET_ERROR) {
00499 return SOCKET_ERROR;
00500 }
00501
00502 #ifdef JACK_MONITOR
00503
00504 fRcvSyncUst = GetMicroSeconds();
00505 #endif
00506
00507
00508
00509 DecodeSyncPacket();
00510
00511 #ifdef JACK_MONITOR
00512 fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f);
00513 #endif
00514
00515 int res = DataRecv();
00516 if (res == SOCKET_ERROR) {
00517 return SOCKET_ERROR;
00518 } else if (res == NET_PACKET_ERROR) {
00519 jack_time_t cur_time = GetMicroSeconds();
00520 NotifyXRun(cur_time, float(cur_time - fBeginDateUst));
00521 }
00522
00523
00524 JackDriver::CycleTakeBeginTime();
00525
00526 #ifdef JACK_MONITOR
00527 fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f);
00528 #endif
00529
00530 return 0;
00531 }
00532
00533 int JackNetDriver::Write()
00534 {
00535
00536 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
00537 fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, GetMidiOutputBuffer(midi_port_index));
00538 }
00539
00540 for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
00541 #ifdef OPTIMIZED_PROTOCOL
00542
00543 if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index)) {
00544 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[audio_port_index]) > 0) {
00545 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index));
00546 } else {
00547 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL);
00548 }
00549 } else {
00550 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL);
00551 }
00552 #else
00553 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index));
00554 #endif
00555 }
00556
00557 #ifdef JACK_MONITOR
00558 fNetTimeMon->AddLast((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f);
00559 #endif
00560
00561
00562 EncodeSyncPacket();
00563
00564
00565 if (SyncSend() == SOCKET_ERROR) {
00566 return SOCKET_ERROR;
00567 }
00568
00569 #ifdef JACK_MONITOR
00570 fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f);
00571 #endif
00572
00573
00574 if (DataSend() == SOCKET_ERROR) {
00575 return SOCKET_ERROR;
00576 }
00577
00578 #ifdef JACK_MONITOR
00579 fNetTimeMon->AddLast(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f);
00580 #endif
00581
00582 return 0;
00583 }
00584
00585
00586
00587 #ifdef __cplusplus
00588 extern "C"
00589 {
00590 #endif
00591 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
00592 {
00593 jack_driver_desc_t * desc;
00594 jack_driver_desc_filler_t filler;
00595 jack_driver_param_value_t value;
00596
00597 desc = jack_driver_descriptor_construct("net", JackDriverMaster, "netjack slave backend component", &filler);
00598
00599 strcpy(value.str, DEFAULT_MULTICAST_IP);
00600 jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
00601
00602 value.i = DEFAULT_PORT;
00603 jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
00604
00605 value.i = DEFAULT_MTU;
00606 jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
00607
00608 value.i = -1;
00609 jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", "Number of audio input ports. If -1, audio physical input from the master");
00610 jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'P', JackDriverParamInt, &value, NULL, "Number of audio output ports", "Number of audio output ports. If -1, audio physical output from the master");
00611
00612 value.i = 0;
00613 jack_driver_descriptor_add_parameter(desc, &filler, "midi-in-ports", 'i', JackDriverParamInt, &value, NULL, "Number of midi input ports", NULL);
00614 jack_driver_descriptor_add_parameter(desc, &filler, "midi-out-ports", 'o', JackDriverParamInt, &value, NULL, "Number of midi output ports", NULL);
00615
00616 #if HAVE_CELT
00617 value.i = -1;
00618 jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
00619 #endif
00620 strcpy(value.str, "'hostname'");
00621 jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
00622
00623 value.ui = 0U;
00624 jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
00625
00626 value.ui = 5U;
00627 jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);
00628
00629 return desc;
00630 }
00631
00632 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
00633 {
00634 char multicast_ip[32];
00635 char net_name[JACK_CLIENT_NAME_SIZE + 1];
00636 int udp_port;
00637 int mtu = DEFAULT_MTU;
00638
00639 uint transport_sync = 0;
00640 jack_nframes_t period_size = 1024;
00641 jack_nframes_t sample_rate = 48000;
00642 int audio_capture_ports = -1;
00643 int audio_playback_ports = -1;
00644 int midi_input_ports = 0;
00645 int midi_output_ports = 0;
00646 int celt_encoding = -1;
00647 bool monitor = false;
00648 int network_latency = 5;
00649 const JSList* node;
00650 const jack_driver_param_t* param;
00651
00652 net_name[0] = 0;
00653
00654
00655 const char* default_udp_port = getenv("JACK_NETJACK_PORT");
00656 udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
00657
00658 const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
00659 if (default_multicast_ip) {
00660 strcpy(multicast_ip, default_multicast_ip);
00661 } else {
00662 strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
00663 }
00664
00665 for (node = params; node; node = jack_slist_next(node)) {
00666 param = (const jack_driver_param_t*) node->data;
00667 switch (param->character)
00668 {
00669 case 'a' :
00670 assert(strlen(param->value.str) < 32);
00671 strcpy(multicast_ip, param->value.str);
00672 break;
00673 case 'p':
00674 udp_port = param->value.ui;
00675 break;
00676 case 'M':
00677 mtu = param->value.i;
00678 break;
00679 case 'C':
00680 audio_capture_ports = param->value.i;
00681 break;
00682 case 'P':
00683 audio_playback_ports = param->value.i;
00684 break;
00685 case 'i':
00686 midi_input_ports = param->value.i;
00687 break;
00688 case 'o':
00689 midi_output_ports = param->value.i;
00690 break;
00691 #if HAVE_CELT
00692 case 'c':
00693 celt_encoding = param->value.i;
00694 break;
00695 #endif
00696 case 'n' :
00697 strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE);
00698 break;
00699 case 't' :
00700 transport_sync = param->value.ui;
00701 break;
00702 case 'l' :
00703 network_latency = param->value.ui;
00704 if (network_latency > NETWORK_MAX_LATENCY) {
00705 printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
00706 return NULL;
00707 }
00708 break;
00709 }
00710 }
00711
00712 try {
00713
00714 Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver(
00715 new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
00716 midi_input_ports, midi_output_ports,
00717 net_name, transport_sync,
00718 network_latency, celt_encoding));
00719 if (driver->Open(period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0) == 0) {
00720 return driver;
00721 } else {
00722 delete driver;
00723 return NULL;
00724 }
00725
00726 } catch (...) {
00727 return NULL;
00728 }
00729 }
00730
00731 #ifdef __cplusplus
00732 }
00733 #endif
00734 }