Jack2 1.9.8
|
00001 /* 00002 Copyright (C) 2008-2011 Romain Moret at Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 #include "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 // Use the hostname if no name parameter was given 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 //fParams.fSampleEncoder = JackIntEncoder; 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 //open, close, attach and detach------------------------------------------------------ 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 // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init) 00089 int JackNetDriver::Attach() 00090 { 00091 return 0; 00092 } 00093 00094 int JackNetDriver::Detach() 00095 { 00096 return 0; 00097 } 00098 00099 //init and restart-------------------------------------------------------------------- 00100 /* 00101 JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves 00102 as a "dummy driver, until Init method returns. 00103 */ 00104 00105 bool JackNetDriver::Initialize() 00106 { 00107 jack_log("JackNetDriver::Initialize"); 00108 SaveConnections(); 00109 FreePorts(); 00110 00111 // New loading, but existing socket, restart the driver 00112 if (fSocket.IsSocket()) { 00113 jack_info("Restarting driver..."); 00114 FreeAll(); 00115 } 00116 00117 // Set the parameters to send 00118 fParams.fSendAudioChannels = fCaptureChannels; 00119 fParams.fReturnAudioChannels = fPlaybackChannels; 00120 fParams.fSlaveSyncMode = fEngineControl->fSyncMode; 00121 00122 // Display some additional infos 00123 jack_info("NetDriver started in %s mode %s Master's transport sync.", 00124 (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without"); 00125 00126 // Init network 00127 if (!JackNetSlaveInterface::Init()) { 00128 jack_error("Starting network fails..."); 00129 return false; 00130 } 00131 00132 // Set global parameters 00133 if (!SetParams()) { 00134 jack_error("SetParams error..."); 00135 return false; 00136 } 00137 00138 // If -1 at connection time, in/out channels count is sent by the master 00139 fCaptureChannels = fParams.fSendAudioChannels; 00140 fPlaybackChannels = fParams.fReturnAudioChannels; 00141 00142 // Allocate midi ports lists 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 // Register jack ports 00157 if (AllocPorts() != 0) { 00158 jack_error("Can't allocate ports."); 00159 return false; 00160 } 00161 00162 // Init done, display parameters 00163 SessionParamsDisplay(&fParams); 00164 00165 // Monitor 00166 #ifdef JACK_MONITOR 00167 string plot_name; 00168 // NetTimeMon 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 // Driver parametering 00190 JackTimedDriver::SetBufferSize(fParams.fPeriodSize); 00191 JackTimedDriver::SetSampleRate(fParams.fSampleRate); 00192 00193 JackDriver::NotifyBufferSize(fParams.fPeriodSize); 00194 JackDriver::NotifySampleRate(fParams.fSampleRate); 00195 00196 // Transport engine parametering 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 //jack ports and buffers-------------------------------------------------------------- 00232 int JackNetDriver::AllocPorts() 00233 { 00234 jack_log("JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); 00235 00236 /* 00237 fNetAudioCaptureBuffer fNetAudioPlaybackBuffer 00238 fSendAudioChannels fReturnAudioChannels 00239 00240 fCapturePortList fPlaybackPortList 00241 fCaptureChannels ==> SLAVE ==> fPlaybackChannels 00242 "capture_" "playback_" 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 //audio 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 //port latency 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 //port latency 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 //midi 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 //port latency 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 //port latency 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 //transport--------------------------------------------------------------------------- 00397 void JackNetDriver::DecodeTransportData() 00398 { 00399 //is there a new timebase master on the net master ? 00400 // - release timebase master only if it's a non-conditional request 00401 // - no change or no request : don't do anything 00402 // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master 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 //is there a transport state change to handle ? 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 //fEngineControl->fTransport.SetCommand(TransportCommandStart); 00431 fEngineControl->fTransport.SetState(JackTransportRolling); 00432 jack_info("Master is rolling."); 00433 break; 00434 } 00435 } 00436 } 00437 00438 void JackNetDriver::EncodeTransportData() 00439 { 00440 //is there a timebase master change ? 00441 int refnum; 00442 bool conditional; 00443 fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional); 00444 if (refnum != fLastTimebaseMaster) { 00445 //timebase master has released its function 00446 if (refnum == -1) { 00447 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; 00448 jack_info("Sending a timebase master release request."); 00449 } else { 00450 //there is a new timebase master 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 //update transport state and position 00460 fReturnTransportData.fState = fEngineControl->fTransport.Query(&fReturnTransportData.fPosition); 00461 00462 //is it a new state (that the master need to know...) ? 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 //driver processes-------------------------------------------------------------------- 00473 00474 int JackNetDriver::Read() 00475 { 00476 //buffers 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 //receive sync (launch the cycle) 00498 if (SyncRecv() == SOCKET_ERROR) { 00499 return SOCKET_ERROR; 00500 } 00501 00502 #ifdef JACK_MONITOR 00503 // For timing 00504 fRcvSyncUst = GetMicroSeconds(); 00505 #endif 00506 00507 //decode sync 00508 //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified 00509 DecodeSyncPacket(); 00510 00511 #ifdef JACK_MONITOR 00512 fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); 00513 #endif 00514 //audio, midi or sync if driver is late 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)); // Better this value than nothing... 00521 } 00522 00523 //take the time at the beginning of the cycle 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 //buffers 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 // Port is connected on other side... 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 //sync 00562 EncodeSyncPacket(); 00563 00564 //send sync 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 //send data 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 //driver loader----------------------------------------------------------------------- 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 // Desactivated for now... 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 // Possibly use env variable 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 }