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 "JackCompilerDeps.h" 00020 #include "driver_interface.h" 00021 #include "JackNetDriver.h" 00022 #include "JackEngineControl.h" 00023 #include "JackLockedEngine.h" 00024 #include "JackWaitThreadedDriver.h" 00025 00026 using namespace std; 00027 00028 namespace Jack 00029 { 00030 JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, 00031 const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports, 00032 char* net_name, uint transport_sync, int network_latency, 00033 int celt_encoding, int opus_encoding, bool auto_save) 00034 : JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) 00035 { 00036 jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); 00037 00038 // Use the hostname if no name parameter was given 00039 if (strcmp(net_name, "") == 0) { 00040 GetHostName(net_name, JACK_CLIENT_NAME_SIZE); 00041 } 00042 00043 fParams.fMtu = mtu; 00044 00045 fWantedMIDICaptureChannels = midi_input_ports; 00046 fWantedMIDIPlaybackChannels = midi_output_ports; 00047 00048 if (celt_encoding > 0) { 00049 fParams.fSampleEncoder = JackCeltEncoder; 00050 fParams.fKBps = celt_encoding; 00051 } else if (opus_encoding > 0) { 00052 fParams.fSampleEncoder = JackOpusEncoder; 00053 fParams.fKBps = opus_encoding; 00054 } else { 00055 fParams.fSampleEncoder = JackFloatEncoder; 00056 //fParams.fSampleEncoder = JackIntEncoder; 00057 } 00058 strcpy(fParams.fName, net_name); 00059 fSocket.GetName(fParams.fSlaveNetName); 00060 fParams.fTransportSync = transport_sync; 00061 fParams.fNetworkLatency = network_latency; 00062 fSendTransportData.fState = -1; 00063 fReturnTransportData.fState = -1; 00064 fLastTransportState = -1; 00065 fLastTimebaseMaster = -1; 00066 fMidiCapturePortList = NULL; 00067 fMidiPlaybackPortList = NULL; 00068 fWantedAudioCaptureChannels = -1; 00069 fWantedAudioPlaybackChannels = -1; 00070 fAutoSave = auto_save; 00071 #ifdef JACK_MONITOR 00072 fNetTimeMon = NULL; 00073 fRcvSyncUst = 0; 00074 #endif 00075 } 00076 00077 JackNetDriver::~JackNetDriver() 00078 { 00079 delete[] fMidiCapturePortList; 00080 delete[] fMidiPlaybackPortList; 00081 #ifdef JACK_MONITOR 00082 delete fNetTimeMon; 00083 #endif 00084 } 00085 00086 //open, close, attach and detach------------------------------------------------------ 00087 00088 int JackNetDriver::Open(jack_nframes_t buffer_size, 00089 jack_nframes_t samplerate, 00090 bool capturing, 00091 bool playing, 00092 int inchannels, 00093 int outchannels, 00094 bool monitor, 00095 const char* capture_driver_name, 00096 const char* playback_driver_name, 00097 jack_nframes_t capture_latency, 00098 jack_nframes_t playback_latency) 00099 { 00100 // Keep initial wanted values 00101 fWantedAudioCaptureChannels = inchannels; 00102 fWantedAudioPlaybackChannels = outchannels; 00103 return JackWaiterDriver::Open(buffer_size, samplerate, 00104 capturing, playing, 00105 inchannels, outchannels, 00106 monitor, 00107 capture_driver_name, playback_driver_name, 00108 capture_latency, playback_latency); 00109 } 00110 00111 int JackNetDriver::Close() 00112 { 00113 #ifdef JACK_MONITOR 00114 if (fNetTimeMon) { 00115 fNetTimeMon->Save(); 00116 } 00117 #endif 00118 FreeAll(); 00119 return JackWaiterDriver::Close(); 00120 } 00121 00122 // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init) 00123 int JackNetDriver::Attach() 00124 { 00125 return 0; 00126 } 00127 00128 int JackNetDriver::Detach() 00129 { 00130 return 0; 00131 } 00132 00133 //init and restart-------------------------------------------------------------------- 00134 /* 00135 JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves 00136 as a "dummy driver, until Init method returns. 00137 */ 00138 00139 bool JackNetDriver::Initialize() 00140 { 00141 jack_log("JackNetDriver::Initialize"); 00142 if (fAutoSave) { 00143 SaveConnections(0); 00144 } 00145 FreePorts(); 00146 00147 // New loading, but existing socket, restart the driver 00148 if (fSocket.IsSocket()) { 00149 jack_info("Restarting driver..."); 00150 FreeAll(); 00151 } 00152 00153 // Set the parameters to send 00154 fParams.fSendAudioChannels = fWantedAudioCaptureChannels; 00155 fParams.fReturnAudioChannels = fWantedAudioPlaybackChannels; 00156 00157 fParams.fSendMidiChannels = fWantedMIDICaptureChannels; 00158 fParams.fReturnMidiChannels = fWantedMIDIPlaybackChannels; 00159 00160 fParams.fSlaveSyncMode = fEngineControl->fSyncMode; 00161 00162 // Display some additional infos 00163 jack_info("NetDriver started in %s mode %s Master's transport sync.", 00164 (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without"); 00165 00166 // Init network 00167 if (!JackNetSlaveInterface::Init()) { 00168 jack_error("Starting network fails..."); 00169 return false; 00170 } 00171 00172 // Set global parameters 00173 if (!SetParams()) { 00174 jack_error("SetParams error..."); 00175 return false; 00176 } 00177 00178 // If -1 at connection time for audio, in/out audio channels count is sent by the master 00179 fCaptureChannels = fParams.fSendAudioChannels; 00180 fPlaybackChannels = fParams.fReturnAudioChannels; 00181 00182 // If -1 at connection time for MIDI, in/out MIDI channels count is sent by the master (in fParams struct) 00183 00184 // Allocate midi ports lists 00185 delete[] fMidiCapturePortList; 00186 delete[] fMidiPlaybackPortList; 00187 00188 if (fParams.fSendMidiChannels > 0) { 00189 fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels]; 00190 assert(fMidiCapturePortList); 00191 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { 00192 fMidiCapturePortList[midi_port_index] = 0; 00193 } 00194 } 00195 00196 if (fParams.fReturnMidiChannels > 0) { 00197 fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels]; 00198 assert(fMidiPlaybackPortList); 00199 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { 00200 fMidiPlaybackPortList[midi_port_index] = 0; 00201 } 00202 } 00203 00204 // Register jack ports 00205 if (AllocPorts() != 0) { 00206 jack_error("Can't allocate ports."); 00207 return false; 00208 } 00209 00210 // Init done, display parameters 00211 SessionParamsDisplay(&fParams); 00212 00213 // Monitor 00214 #ifdef JACK_MONITOR 00215 string plot_name; 00216 // NetTimeMon 00217 plot_name = string(fParams.fName); 00218 plot_name += string("_slave"); 00219 plot_name += (fEngineControl->fSyncMode) ? string("_sync") : string("_async"); 00220 plot_name += string("_latency"); 00221 fNetTimeMon = new JackGnuPlotMonitor<float>(128, 5, plot_name); 00222 string net_time_mon_fields[] = 00223 { 00224 string("sync decoded"), 00225 string("end of read"), 00226 string("start of write"), 00227 string("sync send"), 00228 string("end of write") 00229 }; 00230 string net_time_mon_options[] = 00231 { 00232 string("set xlabel \"audio cycles\""), 00233 string("set ylabel \"% of audio cycle\"") 00234 }; 00235 fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 5); 00236 #endif 00237 // Driver parametering 00238 JackTimedDriver::SetBufferSize(fParams.fPeriodSize); 00239 JackTimedDriver::SetSampleRate(fParams.fSampleRate); 00240 00241 JackDriver::NotifyBufferSize(fParams.fPeriodSize); 00242 JackDriver::NotifySampleRate(fParams.fSampleRate); 00243 00244 // Transport engine parametering 00245 fEngineControl->fTransport.SetNetworkSync(fParams.fTransportSync); 00246 00247 if (fAutoSave) { 00248 LoadConnections(0); 00249 } 00250 return true; 00251 } 00252 00253 void JackNetDriver::FreeAll() 00254 { 00255 FreePorts(); 00256 00257 delete[] fTxBuffer; 00258 delete[] fRxBuffer; 00259 delete fNetAudioCaptureBuffer; 00260 delete fNetAudioPlaybackBuffer; 00261 delete fNetMidiCaptureBuffer; 00262 delete fNetMidiPlaybackBuffer; 00263 delete[] fMidiCapturePortList; 00264 delete[] fMidiPlaybackPortList; 00265 00266 fTxBuffer = NULL; 00267 fRxBuffer = NULL; 00268 fNetAudioCaptureBuffer = NULL; 00269 fNetAudioPlaybackBuffer = NULL; 00270 fNetMidiCaptureBuffer = NULL; 00271 fNetMidiPlaybackBuffer = NULL; 00272 fMidiCapturePortList = NULL; 00273 fMidiPlaybackPortList = NULL; 00274 00275 #ifdef JACK_MONITOR 00276 delete fNetTimeMon; 00277 fNetTimeMon = NULL; 00278 #endif 00279 } 00280 00281 void JackNetDriver::UpdateLatencies() 00282 { 00283 jack_latency_range_t input_range; 00284 jack_latency_range_t output_range; 00285 jack_latency_range_t monitor_range; 00286 00287 for (int i = 0; i < fCaptureChannels; i++) { 00288 input_range.max = input_range.min = float(fParams.fNetworkLatency * fEngineControl->fBufferSize) / 2.f; 00289 fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range); 00290 } 00291 00292 for (int i = 0; i < fPlaybackChannels; i++) { 00293 output_range.max = output_range.min = float(fParams.fNetworkLatency * fEngineControl->fBufferSize) / 2.f; 00294 if (!fEngineControl->fSyncMode) { 00295 output_range.max = output_range.min += fEngineControl->fBufferSize; 00296 } 00297 fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range); 00298 if (fWithMonitorPorts) { 00299 monitor_range.min = monitor_range.max = 0; 00300 fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range); 00301 } 00302 } 00303 } 00304 00305 //jack ports and buffers-------------------------------------------------------------- 00306 int JackNetDriver::AllocPorts() 00307 { 00308 jack_log("JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); 00309 00310 /* 00311 fNetAudioCaptureBuffer fNetAudioPlaybackBuffer 00312 fSendAudioChannels fReturnAudioChannels 00313 00314 fCapturePortList fPlaybackPortList 00315 fCaptureChannels ==> SLAVE ==> fPlaybackChannels 00316 "capture_" "playback_" 00317 */ 00318 00319 JackPort* port; 00320 jack_port_id_t port_index; 00321 char name[REAL_JACK_PORT_NAME_SIZE]; 00322 char alias[REAL_JACK_PORT_NAME_SIZE]; 00323 int audio_port_index; 00324 int midi_port_index; 00325 00326 //audio 00327 for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { 00328 snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1); 00329 snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, audio_port_index + 1); 00330 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, 00331 CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { 00332 jack_error("driver: cannot register port for %s", name); 00333 return -1; 00334 } 00335 00336 port = fGraphManager->GetPort(port_index); 00337 port->SetAlias(alias); 00338 fCapturePortList[audio_port_index] = port_index; 00339 jack_log("JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency()); 00340 } 00341 00342 for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { 00343 snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1); 00344 snprintf(name, sizeof(name), "%s:playback_%d",fClientControl.fName, audio_port_index + 1); 00345 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, 00346 PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { 00347 jack_error("driver: cannot register port for %s", name); 00348 return -1; 00349 } 00350 00351 port = fGraphManager->GetPort(port_index); 00352 port->SetAlias(alias); 00353 fPlaybackPortList[audio_port_index] = port_index; 00354 jack_log("JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency()); 00355 } 00356 00357 //midi 00358 for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { 00359 snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1); 00360 snprintf(name, sizeof (name), "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1); 00361 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, 00362 CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { 00363 jack_error("driver: cannot register port for %s", name); 00364 return -1; 00365 } 00366 00367 port = fGraphManager->GetPort(port_index); 00368 fMidiCapturePortList[midi_port_index] = port_index; 00369 jack_log("JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency()); 00370 } 00371 00372 for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { 00373 snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1); 00374 snprintf(name, sizeof(name), "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1); 00375 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, 00376 PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { 00377 jack_error("driver: cannot register port for %s", name); 00378 return -1; 00379 } 00380 00381 port = fGraphManager->GetPort(port_index); 00382 fMidiPlaybackPortList[midi_port_index] = port_index; 00383 jack_log("JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency()); 00384 } 00385 00386 UpdateLatencies(); 00387 return 0; 00388 } 00389 00390 int JackNetDriver::FreePorts() 00391 { 00392 jack_log("JackNetDriver::FreePorts"); 00393 00394 for (int audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { 00395 if (fCapturePortList[audio_port_index] > 0) { 00396 fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[audio_port_index]); 00397 fCapturePortList[audio_port_index] = 0; 00398 } 00399 } 00400 00401 for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { 00402 if (fPlaybackPortList[audio_port_index] > 0) { 00403 fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[audio_port_index]); 00404 fPlaybackPortList[audio_port_index] = 0; 00405 } 00406 } 00407 00408 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { 00409 if (fMidiCapturePortList && fMidiCapturePortList[midi_port_index] > 0) { 00410 fGraphManager->ReleasePort(fClientControl.fRefNum, fMidiCapturePortList[midi_port_index]); 00411 fMidiCapturePortList[midi_port_index] = 0; 00412 } 00413 } 00414 00415 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { 00416 if (fMidiPlaybackPortList && fMidiPlaybackPortList[midi_port_index] > 0) { 00417 fEngine->PortUnRegister(fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index]); 00418 fMidiPlaybackPortList[midi_port_index] = 0; 00419 } 00420 } 00421 return 0; 00422 } 00423 00424 void JackNetDriver::SaveConnections(int alias) 00425 { 00426 JackDriver::SaveConnections(alias); 00427 const char** connections; 00428 00429 if (fMidiCapturePortList) { 00430 for (int i = 0; i < fParams.fSendMidiChannels; ++i) { 00431 if (fMidiCapturePortList[i] && (connections = fGraphManager->GetConnections(fMidiCapturePortList[i])) != 0) { 00432 for (int j = 0; connections[j]; j++) { 00433 JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j])); 00434 fConnections.push_back(make_pair(port_id->GetType(), make_pair(fGraphManager->GetPort(fMidiCapturePortList[i])->GetName(), connections[j]))); 00435 jack_info("Save connection: %s %s", fGraphManager->GetPort(fMidiCapturePortList[i])->GetName(), connections[j]); 00436 } 00437 free(connections); 00438 } 00439 } 00440 } 00441 00442 if (fMidiPlaybackPortList) { 00443 for (int i = 0; i < fParams.fReturnMidiChannels; ++i) { 00444 if (fMidiPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fMidiPlaybackPortList[i])) != 0) { 00445 for (int j = 0; connections[j]; j++) { 00446 JackPort* port_id = fGraphManager->GetPort(fGraphManager->GetPort(connections[j])); 00447 fConnections.push_back(make_pair(port_id->GetType(), make_pair(connections[j], fGraphManager->GetPort(fMidiPlaybackPortList[i])->GetName()))); 00448 jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fMidiPlaybackPortList[i])->GetName()); 00449 } 00450 free(connections); 00451 } 00452 } 00453 } 00454 } 00455 00456 JackMidiBuffer* JackNetDriver::GetMidiInputBuffer(int port_index) 00457 { 00458 return static_cast<JackMidiBuffer*>(fGraphManager->GetBuffer(fMidiCapturePortList[port_index], fEngineControl->fBufferSize)); 00459 } 00460 00461 JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer(int port_index) 00462 { 00463 return static_cast<JackMidiBuffer*>(fGraphManager->GetBuffer(fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize)); 00464 } 00465 00466 //transport--------------------------------------------------------------------------- 00467 void JackNetDriver::DecodeTransportData() 00468 { 00469 //is there a new timebase master on the net master ? 00470 // - release timebase master only if it's a non-conditional request 00471 // - no change or no request : don't do anything 00472 // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master 00473 int refnum; 00474 bool conditional; 00475 if (fSendTransportData.fTimebaseMaster == TIMEBASEMASTER) { 00476 fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional); 00477 if (refnum != -1) { 00478 fEngineControl->fTransport.ResetTimebase(refnum); 00479 } 00480 jack_info("The NetMaster is now the new timebase master."); 00481 } 00482 00483 //is there a transport state change to handle ? 00484 if (fSendTransportData.fNewState &&(fSendTransportData.fState != fEngineControl->fTransport.GetState())) { 00485 00486 switch (fSendTransportData.fState) 00487 { 00488 case JackTransportStopped : 00489 fEngineControl->fTransport.SetCommand(TransportCommandStop); 00490 jack_info("Master stops transport."); 00491 break; 00492 00493 case JackTransportStarting : 00494 fEngineControl->fTransport.RequestNewPos(&fSendTransportData.fPosition); 00495 fEngineControl->fTransport.SetCommand(TransportCommandStart); 00496 jack_info("Master starts transport frame = %d", fSendTransportData.fPosition.frame); 00497 break; 00498 00499 case JackTransportRolling : 00500 //fEngineControl->fTransport.SetCommand(TransportCommandStart); 00501 fEngineControl->fTransport.SetState(JackTransportRolling); 00502 jack_info("Master is rolling."); 00503 break; 00504 } 00505 } 00506 } 00507 00508 void JackNetDriver::EncodeTransportData() 00509 { 00510 // is there a timebase master change ? 00511 int refnum; 00512 bool conditional; 00513 fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional); 00514 if (refnum != fLastTimebaseMaster) { 00515 // timebase master has released its function 00516 if (refnum == -1) { 00517 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; 00518 jack_info("Sending a timebase master release request."); 00519 } else { 00520 // there is a new timebase master 00521 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER; 00522 jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional"); 00523 } 00524 fLastTimebaseMaster = refnum; 00525 } else { 00526 fReturnTransportData.fTimebaseMaster = NO_CHANGE; 00527 } 00528 00529 // update transport state and position 00530 fReturnTransportData.fState = fEngineControl->fTransport.Query(&fReturnTransportData.fPosition); 00531 00532 // is it a new state (that the master need to know...) ? 00533 fReturnTransportData.fNewState = ((fReturnTransportData.fState == JackTransportNetStarting) && 00534 (fReturnTransportData.fState != fLastTransportState) && 00535 (fReturnTransportData.fState != fSendTransportData.fState)); 00536 if (fReturnTransportData.fNewState) { 00537 jack_info("Sending '%s'.", GetTransportState(fReturnTransportData.fState)); 00538 } 00539 fLastTransportState = fReturnTransportData.fState; 00540 } 00541 00542 //driver processes-------------------------------------------------------------------- 00543 00544 int JackNetDriver::Read() 00545 { 00546 // buffers 00547 for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { 00548 fNetMidiCaptureBuffer->SetBuffer(midi_port_index, GetMidiInputBuffer(midi_port_index)); 00549 } 00550 00551 for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { 00552 #ifdef OPTIMIZED_PROTOCOL 00553 if (fGraphManager->GetConnectionsNum(fCapturePortList[audio_port_index]) > 0) { 00554 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index)); 00555 } else { 00556 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL); 00557 } 00558 #else 00559 fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index)); 00560 #endif 00561 } 00562 00563 #ifdef JACK_MONITOR 00564 fNetTimeMon->New(); 00565 #endif 00566 00567 switch (SyncRecv()) { 00568 00569 case SOCKET_ERROR: 00570 return SOCKET_ERROR; 00571 00572 case SYNC_PACKET_ERROR: 00573 // since sync packet is incorrect, don't decode it and continue with data 00574 break; 00575 00576 default: 00577 // decode sync 00578 int unused_frames; 00579 DecodeSyncPacket(unused_frames); 00580 break; 00581 } 00582 00583 #ifdef JACK_MONITOR 00584 // For timing 00585 fRcvSyncUst = GetMicroSeconds(); 00586 #endif 00587 00588 #ifdef JACK_MONITOR 00589 fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); 00590 #endif 00591 // audio, midi or sync if driver is late 00592 switch (DataRecv()) { 00593 00594 case SOCKET_ERROR: 00595 return SOCKET_ERROR; 00596 00597 case DATA_PACKET_ERROR: 00598 jack_time_t cur_time = GetMicroSeconds(); 00599 NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... 00600 break; 00601 } 00602 00603 // take the time at the beginning of the cycle 00604 JackDriver::CycleTakeBeginTime(); 00605 00606 #ifdef JACK_MONITOR 00607 fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); 00608 #endif 00609 00610 return 0; 00611 } 00612 00613 int JackNetDriver::Write() 00614 { 00615 // buffers 00616 for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { 00617 fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, GetMidiOutputBuffer(midi_port_index)); 00618 } 00619 00620 for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { 00621 #ifdef OPTIMIZED_PROTOCOL 00622 // Port is connected on other side... 00623 if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index) 00624 && (fGraphManager->GetConnectionsNum(fPlaybackPortList[audio_port_index]) > 0)) { 00625 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index)); 00626 } else { 00627 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); 00628 } 00629 #else 00630 fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index)); 00631 #endif 00632 } 00633 00634 #ifdef JACK_MONITOR 00635 fNetTimeMon->AddLast(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); 00636 #endif 00637 00638 EncodeSyncPacket(); 00639 00640 // send sync 00641 if (SyncSend() == SOCKET_ERROR) { 00642 return SOCKET_ERROR; 00643 } 00644 00645 #ifdef JACK_MONITOR 00646 fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); 00647 #endif 00648 00649 // send data 00650 if (DataSend() == SOCKET_ERROR) { 00651 return SOCKET_ERROR; 00652 } 00653 00654 #ifdef JACK_MONITOR 00655 fNetTimeMon->AddLast(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); 00656 #endif 00657 00658 return 0; 00659 } 00660 00661 //driver loader----------------------------------------------------------------------- 00662 00663 #ifdef __cplusplus 00664 extern "C" 00665 { 00666 #endif 00667 00668 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() 00669 { 00670 jack_driver_desc_t * desc; 00671 jack_driver_desc_filler_t filler; 00672 jack_driver_param_value_t value; 00673 00674 desc = jack_driver_descriptor_construct("net", JackDriverMaster, "netjack slave backend component", &filler); 00675 00676 strcpy(value.str, DEFAULT_MULTICAST_IP); 00677 jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL); 00678 00679 value.i = DEFAULT_PORT; 00680 jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); 00681 00682 value.i = DEFAULT_MTU; 00683 jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL); 00684 00685 value.i = -1; 00686 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"); 00687 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"); 00688 00689 value.i = -1; 00690 jack_driver_descriptor_add_parameter(desc, &filler, "midi-in-ports", 'i', JackDriverParamInt, &value, NULL, "Number of midi input ports", "Number of MIDI input ports. If -1, MIDI physical input from the master"); 00691 jack_driver_descriptor_add_parameter(desc, &filler, "midi-out-ports", 'o', JackDriverParamInt, &value, NULL, "Number of midi output ports", "Number of MIDI output ports. If -1, MIDI physical output from the master"); 00692 00693 #if HAVE_CELT 00694 value.i = -1; 00695 jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL); 00696 #endif 00697 #if HAVE_OPUS 00698 value.i = -1; 00699 jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'O', JackDriverParamInt, &value, NULL, "Set Opus encoding and number of kBits per channel", NULL); 00700 #endif 00701 strcpy(value.str, "'hostname'"); 00702 jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); 00703 00704 value.i = false; 00705 jack_driver_descriptor_add_parameter(desc, &filler, "auto-save", 's', JackDriverParamBool, &value, NULL, "Save/restore connection state when restarting", NULL); 00706 00707 00708 /* 00709 Deactivated for now.. 00710 value.ui = 0U; 00711 jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); 00712 */ 00713 00714 value.ui = 5U; 00715 jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); 00716 00717 return desc; 00718 } 00719 00720 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) 00721 { 00722 char multicast_ip[32]; 00723 char net_name[JACK_CLIENT_NAME_SIZE + 1] = {0}; 00724 int udp_port; 00725 int mtu = DEFAULT_MTU; 00726 // Desactivated for now... 00727 uint transport_sync = 0; 00728 jack_nframes_t period_size = 1024; // to be used while waiting for master period_size 00729 jack_nframes_t sample_rate = 48000; // to be used while waiting for master sample_rate 00730 int audio_capture_ports = -1; 00731 int audio_playback_ports = -1; 00732 int midi_input_ports = -1; 00733 int midi_output_ports = -1; 00734 int celt_encoding = -1; 00735 int opus_encoding = -1; 00736 bool monitor = false; 00737 int network_latency = 5; 00738 const JSList* node; 00739 const jack_driver_param_t* param; 00740 bool auto_save = false; 00741 00742 // Possibly use env variable for UDP port 00743 const char* default_udp_port = getenv("JACK_NETJACK_PORT"); 00744 udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT; 00745 00746 // Possibly use env variable for multicast IP 00747 const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST"); 00748 strcpy(multicast_ip, (default_multicast_ip) ? default_multicast_ip : DEFAULT_MULTICAST_IP); 00749 00750 for (node = params; node; node = jack_slist_next(node)) { 00751 param = (const jack_driver_param_t*) node->data; 00752 switch (param->character) 00753 { 00754 case 'a' : 00755 assert(strlen(param->value.str) < 32); 00756 strcpy(multicast_ip, param->value.str); 00757 break; 00758 case 'p': 00759 udp_port = param->value.ui; 00760 break; 00761 case 'M': 00762 mtu = param->value.i; 00763 break; 00764 case 'C': 00765 audio_capture_ports = param->value.i; 00766 break; 00767 case 'P': 00768 audio_playback_ports = param->value.i; 00769 break; 00770 case 'i': 00771 midi_input_ports = param->value.i; 00772 break; 00773 case 'o': 00774 midi_output_ports = param->value.i; 00775 break; 00776 #if HAVE_CELT 00777 case 'c': 00778 celt_encoding = param->value.i; 00779 break; 00780 #endif 00781 #if HAVE_OPUS 00782 case 'O': 00783 opus_encoding = param->value.i; 00784 break; 00785 #endif 00786 case 'n' : 00787 strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE); 00788 break; 00789 case 's': 00790 auto_save = true; 00791 break; 00792 /* 00793 Deactivated for now.. 00794 case 't' : 00795 transport_sync = param->value.ui; 00796 break; 00797 */ 00798 case 'l' : 00799 network_latency = param->value.ui; 00800 if (network_latency > NETWORK_MAX_LATENCY) { 00801 printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); 00802 return NULL; 00803 } 00804 break; 00805 } 00806 } 00807 00808 try { 00809 00810 Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver( 00811 new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, 00812 midi_input_ports, midi_output_ports, 00813 net_name, transport_sync, 00814 network_latency, celt_encoding, opus_encoding, auto_save)); 00815 if (driver->Open(period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0) == 0) { 00816 return driver; 00817 } else { 00818 delete driver; 00819 return NULL; 00820 } 00821 00822 } catch (...) { 00823 return NULL; 00824 } 00825 } 00826 00827 #ifdef __cplusplus 00828 } 00829 #endif 00830 }