Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2001 Paul Davis 00003 Copyright (C) 2008 Romain Moret at Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00020 #include "JackNetDriver.h" 00021 #include "JackEngineControl.h" 00022 #include "JackGraphManager.h" 00023 #include "JackWaitThreadedDriver.h" 00024 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 port, int mtu, int midi_input_ports, int midi_output_ports, 00032 char* net_name, uint transport_sync, char network_mode ) 00033 : JackAudioDriver ( name, alias, engine, table ), JackNetSlaveInterface ( ip, port ) 00034 { 00035 jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port ); 00036 00037 // Use the hostname if no name parameter was given 00038 if ( strcmp ( net_name, "" ) == 0 ) 00039 GetHostName ( net_name, JACK_CLIENT_NAME_SIZE ); 00040 00041 fParams.fMtu = mtu; 00042 fParams.fSendMidiChannels = midi_input_ports; 00043 fParams.fReturnMidiChannels = midi_output_ports; 00044 strcpy ( fParams.fName, net_name ); 00045 fSocket.GetName ( fParams.fSlaveNetName ); 00046 fParams.fTransportSync = transport_sync; 00047 fParams.fNetworkMode = network_mode; 00048 fSendTransportData.fState = -1; 00049 fReturnTransportData.fState = -1; 00050 fLastTransportState = -1; 00051 fLastTimebaseMaster = -1; 00052 fMidiCapturePortList = NULL; 00053 fMidiPlaybackPortList = NULL; 00054 #ifdef JACK_MONITOR 00055 fNetTimeMon = NULL; 00056 fRcvSyncUst = 0; 00057 #endif 00058 } 00059 00060 JackNetDriver::~JackNetDriver() 00061 { 00062 delete[] fMidiCapturePortList; 00063 delete[] fMidiPlaybackPortList; 00064 #ifdef JACK_MONITOR 00065 delete fNetTimeMon; 00066 #endif 00067 } 00068 00069 //open, close, attach and detach------------------------------------------------------ 00070 int JackNetDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing, 00071 int inchannels, int outchannels, bool monitor, 00072 const char* capture_driver_name, const char* playback_driver_name, 00073 jack_nframes_t capture_latency, jack_nframes_t playback_latency ) 00074 { 00075 if ( JackAudioDriver::Open ( buffer_size, 00076 samplerate, 00077 capturing, 00078 playing, 00079 inchannels, 00080 outchannels, 00081 monitor, 00082 capture_driver_name, 00083 playback_driver_name, 00084 capture_latency, 00085 playback_latency ) == 0 ) 00086 { 00087 fEngineControl->fPeriod = 0; 00088 fEngineControl->fComputation = 500 * 1000; 00089 fEngineControl->fConstraint = 500 * 1000; 00090 return 0; 00091 } 00092 else 00093 { 00094 return -1; 00095 } 00096 } 00097 00098 int JackNetDriver::Close() 00099 { 00100 #ifdef JACK_MONITOR 00101 if ( fNetTimeMon ) 00102 fNetTimeMon->Save(); 00103 #endif 00104 FreeAll(); 00105 return JackDriver::Close(); 00106 } 00107 00108 // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init) 00109 int JackNetDriver::Attach() 00110 { 00111 return 0; 00112 } 00113 00114 int JackNetDriver::Detach() 00115 { 00116 return 0; 00117 } 00118 00119 //init and restart-------------------------------------------------------------------- 00120 /* 00121 JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves 00122 as a "dummy driver, until Init method returns. 00123 */ 00124 00125 bool JackNetDriver::Initialize() 00126 { 00127 jack_log("JackNetDriver::Initialize()"); 00128 00129 //new loading, but existing socket, restart the driver 00130 if (fSocket.IsSocket()) { 00131 jack_info("Restarting driver..."); 00132 FreeAll(); 00133 } 00134 00135 //set the parameters to send 00136 fParams.fSendAudioChannels = fCaptureChannels; 00137 fParams.fReturnAudioChannels = fPlaybackChannels; 00138 fParams.fSlaveSyncMode = fEngineControl->fSyncMode; 00139 00140 //display some additional infos 00141 jack_info ( "NetDriver started in %s mode %s Master's transport sync.", 00142 ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" ); 00143 00144 //init network 00145 if ( !JackNetSlaveInterface::Init() ) 00146 return false; 00147 00148 //set global parameters 00149 SetParams(); 00150 00151 //allocate midi ports lists 00152 fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels]; 00153 fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels]; 00154 assert ( fMidiCapturePortList ); 00155 assert ( fMidiPlaybackPortList ); 00156 00157 //register jack ports 00158 if ( AllocPorts() != 0 ) 00159 { 00160 jack_error ( "Can't allocate ports." ); 00161 return false; 00162 } 00163 00164 //init done, display parameters 00165 SessionParamsDisplay ( &fParams ); 00166 00167 //monitor 00168 #ifdef JACK_MONITOR 00169 string plot_name; 00170 //NetTimeMon 00171 plot_name = string ( fParams.fName ); 00172 plot_name += string ( "_slave" ); 00173 plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" ); 00174 switch ( fParams.fNetworkMode ) 00175 { 00176 case 's' : 00177 plot_name += string ( "_slow" ); 00178 break; 00179 00180 case 'n' : 00181 plot_name += string ( "_normal" ); 00182 break; 00183 00184 case 'f' : 00185 plot_name += string ( "_fast" ); 00186 break; 00187 } 00188 fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 5, plot_name ); 00189 string net_time_mon_fields[] = 00190 { 00191 string ( "sync decoded" ), 00192 string ( "end of read" ), 00193 string ( "start of write" ), 00194 string ( "sync send" ), 00195 string ( "end of write" ) 00196 }; 00197 string net_time_mon_options[] = 00198 { 00199 string ( "set xlabel \"audio cycles\"" ), 00200 string ( "set ylabel \"% of audio cycle\"" ) 00201 }; 00202 fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 5 ); 00203 #endif 00204 //driver parametering 00205 JackAudioDriver::SetBufferSize ( fParams.fPeriodSize ); 00206 JackAudioDriver::SetSampleRate ( fParams.fSampleRate ); 00207 00208 JackDriver::NotifyBufferSize ( fParams.fPeriodSize ); 00209 JackDriver::NotifySampleRate ( fParams.fSampleRate ); 00210 00211 //transport engine parametering 00212 fEngineControl->fTransport.SetNetworkSync ( fParams.fTransportSync ); 00213 return true; 00214 } 00215 00216 void JackNetDriver::FreeAll() 00217 { 00218 FreePorts(); 00219 00220 delete[] fTxBuffer; 00221 delete[] fRxBuffer; 00222 delete fNetAudioCaptureBuffer; 00223 delete fNetAudioPlaybackBuffer; 00224 delete fNetMidiCaptureBuffer; 00225 delete fNetMidiPlaybackBuffer; 00226 delete[] fMidiCapturePortList; 00227 delete[] fMidiPlaybackPortList; 00228 00229 fTxBuffer = NULL; 00230 fRxBuffer = NULL; 00231 fNetAudioCaptureBuffer = NULL; 00232 fNetAudioPlaybackBuffer = NULL; 00233 fNetMidiCaptureBuffer = NULL; 00234 fNetMidiPlaybackBuffer = NULL; 00235 fMidiCapturePortList = NULL; 00236 fMidiPlaybackPortList = NULL; 00237 00238 #ifdef JACK_MONITOR 00239 delete fNetTimeMon; 00240 fNetTimeMon = NULL; 00241 #endif 00242 } 00243 00244 //jack ports and buffers-------------------------------------------------------------- 00245 int JackNetDriver::AllocPorts() 00246 { 00247 jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate ); 00248 00249 JackPort* port; 00250 jack_port_id_t port_id; 00251 char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; 00252 char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; 00253 unsigned long port_flags; 00254 int audio_port_index; 00255 uint midi_port_index; 00256 00257 //audio 00258 port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; 00259 for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ ) 00260 { 00261 snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1 ); 00262 snprintf ( name, sizeof ( name ) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1 ); 00263 if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, 00264 static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT ) 00265 { 00266 jack_error ( "driver: cannot register port for %s", name ); 00267 return -1; 00268 } 00269 port = fGraphManager->GetPort ( port_id ); 00270 port->SetAlias ( alias ); 00271 //port latency 00272 port->SetLatency ( fEngineControl->fBufferSize ); 00273 fCapturePortList[audio_port_index] = port_id; 00274 jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() ); 00275 } 00276 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; 00277 for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ ) 00278 { 00279 snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1 ); 00280 snprintf ( name, sizeof ( name ) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1 ); 00281 if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, 00282 static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT ) 00283 { 00284 jack_error ( "driver: cannot register port for %s", name ); 00285 return -1; 00286 } 00287 port = fGraphManager->GetPort ( port_id ); 00288 port->SetAlias ( alias ); 00289 //port latency 00290 switch ( fParams.fNetworkMode ) 00291 { 00292 case 'f' : 00293 port->SetLatency ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); 00294 break; 00295 case 'n' : 00296 port->SetLatency ( fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); 00297 break; 00298 case 's' : 00299 port->SetLatency ( 2 * fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); 00300 break; 00301 } 00302 fPlaybackPortList[audio_port_index] = port_id; 00303 jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() ); 00304 } 00305 //midi 00306 port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; 00307 for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ ) 00308 { 00309 snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1 ); 00310 snprintf ( name, sizeof ( name ) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1 ); 00311 if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, 00312 static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT ) 00313 { 00314 jack_error ( "driver: cannot register port for %s", name ); 00315 return -1; 00316 } 00317 port = fGraphManager->GetPort ( port_id ); 00318 //port latency 00319 port->SetLatency ( fEngineControl->fBufferSize ); 00320 fMidiCapturePortList[midi_port_index] = port_id; 00321 jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() ); 00322 } 00323 00324 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; 00325 for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ ) 00326 { 00327 snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1 ); 00328 snprintf ( name, sizeof ( name ) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1 ); 00329 if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, 00330 static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT ) 00331 { 00332 jack_error ( "driver: cannot register port for %s", name ); 00333 return -1; 00334 } 00335 port = fGraphManager->GetPort ( port_id ); 00336 //port latency 00337 switch ( fParams.fNetworkMode ) 00338 { 00339 case 'f' : 00340 port->SetLatency ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); 00341 break; 00342 case 'n' : 00343 port->SetLatency ( fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) ; 00344 break; 00345 case 's' : 00346 port->SetLatency ( 2 * fEngineControl->fBufferSize + ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ); 00347 break; 00348 } 00349 fMidiPlaybackPortList[midi_port_index] = port_id; 00350 jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() ); 00351 } 00352 00353 return 0; 00354 } 00355 00356 int JackNetDriver::FreePorts() 00357 { 00358 jack_log ( "JackNetDriver::FreePorts" ); 00359 00360 int audio_port_index; 00361 uint midi_port_index; 00362 for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ ) 00363 if (fCapturePortList[audio_port_index] > 0) 00364 fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index] ); 00365 for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ ) 00366 if (fPlaybackPortList[audio_port_index] > 0) 00367 fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index] ); 00368 for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ ) 00369 if (fMidiCapturePortList[midi_port_index] > 0) 00370 fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index] ); 00371 for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ ) 00372 if (fMidiPlaybackPortList[midi_port_index] > 0) 00373 fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index] ); 00374 return 0; 00375 } 00376 00377 JackMidiBuffer* JackNetDriver::GetMidiInputBuffer ( int port_index ) 00378 { 00379 return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiCapturePortList[port_index], fEngineControl->fBufferSize ) ); 00380 } 00381 00382 JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer ( int port_index ) 00383 { 00384 return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) ); 00385 } 00386 00387 //transport--------------------------------------------------------------------------- 00388 void JackNetDriver::DecodeTransportData() 00389 { 00390 //is there a new timebase master on the net master ? 00391 // - release timebase master only if it's a non-conditional request 00392 // - no change or no request : don't do anything 00393 // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master 00394 int refnum; 00395 bool conditional; 00396 if ( fSendTransportData.fTimebaseMaster == TIMEBASEMASTER ) 00397 { 00398 fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional ); 00399 if ( refnum != -1 ) 00400 fEngineControl->fTransport.ResetTimebase ( refnum ); 00401 jack_info ( "The NetMaster is now the new timebase master." ); 00402 } 00403 00404 //is there a transport state change to handle ? 00405 if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) ) 00406 { 00407 00408 switch ( fSendTransportData.fState ) 00409 { 00410 case JackTransportStopped : 00411 fEngineControl->fTransport.SetCommand ( TransportCommandStop ); 00412 jack_info ( "Master stops transport." ); 00413 break; 00414 00415 case JackTransportStarting : 00416 fEngineControl->fTransport.RequestNewPos ( &fSendTransportData.fPosition ); 00417 fEngineControl->fTransport.SetCommand ( TransportCommandStart ); 00418 jack_info ( "Master starts transport frame = %d", fSendTransportData.fPosition.frame); 00419 break; 00420 00421 case JackTransportRolling : 00422 //fEngineControl->fTransport.SetCommand ( TransportCommandStart ); 00423 fEngineControl->fTransport.SetState ( JackTransportRolling ); 00424 jack_info ( "Master is rolling." ); 00425 break; 00426 } 00427 } 00428 } 00429 00430 void JackNetDriver::EncodeTransportData() 00431 { 00432 /* Desactivated 00433 //is there a timebase master change ? 00434 int refnum; 00435 bool conditional; 00436 fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional ); 00437 if ( refnum != fLastTimebaseMaster ) 00438 { 00439 //timebase master has released its function 00440 if ( refnum == -1 ) 00441 { 00442 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; 00443 jack_info ( "Sending a timebase master release request." ); 00444 } 00445 //there is a new timebase master 00446 else 00447 { 00448 fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER; 00449 jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" ); 00450 } 00451 fLastTimebaseMaster = refnum; 00452 } 00453 else 00454 fReturnTransportData.fTimebaseMaster = NO_CHANGE; 00455 */ 00456 00457 //update transport state and position 00458 fReturnTransportData.fState = fEngineControl->fTransport.Query ( &fReturnTransportData.fPosition ); 00459 00460 //is it a new state (that the master need to know...) ? 00461 fReturnTransportData.fNewState = (( fReturnTransportData.fState == JackTransportNetStarting) && 00462 ( fReturnTransportData.fState != fLastTransportState ) && 00463 ( fReturnTransportData.fState != fSendTransportData.fState ) ); 00464 if ( fReturnTransportData.fNewState ) 00465 jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) ); 00466 fLastTransportState = fReturnTransportData.fState; 00467 } 00468 00469 //driver processes-------------------------------------------------------------------- 00470 int JackNetDriver::Read() 00471 { 00472 uint midi_port_index; 00473 uint audio_port_index; 00474 00475 //buffers 00476 for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ ) 00477 fNetMidiCaptureBuffer->SetBuffer ( midi_port_index, GetMidiInputBuffer ( midi_port_index ) ); 00478 for ( audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++ ) 00479 fNetAudioCaptureBuffer->SetBuffer ( audio_port_index, GetInputBuffer ( audio_port_index ) ); 00480 00481 #ifdef JACK_MONITOR 00482 fNetTimeMon->New(); 00483 #endif 00484 00485 //receive sync (launch the cycle) 00486 if ( SyncRecv() == SOCKET_ERROR ) 00487 return 0; 00488 00489 #ifdef JACK_MONITOR 00490 // For timing 00491 fRcvSyncUst = GetMicroSeconds(); 00492 #endif 00493 00494 //decode sync 00495 //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified 00496 DecodeSyncPacket(); 00497 00498 #ifdef JACK_MONITOR 00499 fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); 00500 #endif 00501 //audio, midi or sync if driver is late 00502 if ( DataRecv() == SOCKET_ERROR ) 00503 return SOCKET_ERROR; 00504 00505 //take the time at the beginning of the cycle 00506 JackDriver::CycleTakeBeginTime(); 00507 00508 #ifdef JACK_MONITOR 00509 fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); 00510 #endif 00511 00512 return 0; 00513 } 00514 00515 int JackNetDriver::Write() 00516 { 00517 uint midi_port_index; 00518 int audio_port_index; 00519 00520 //buffers 00521 for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ ) 00522 fNetMidiPlaybackBuffer->SetBuffer ( midi_port_index, GetMidiOutputBuffer ( midi_port_index ) ); 00523 for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ ) 00524 fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) ); 00525 00526 #ifdef JACK_MONITOR 00527 fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); 00528 #endif 00529 00530 //sync 00531 EncodeSyncPacket(); 00532 00533 //send sync 00534 if ( SyncSend() == SOCKET_ERROR ) 00535 return SOCKET_ERROR; 00536 00537 #ifdef JACK_MONITOR 00538 fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); 00539 #endif 00540 00541 //send data 00542 if ( DataSend() == SOCKET_ERROR ) 00543 return SOCKET_ERROR; 00544 00545 #ifdef JACK_MONITOR 00546 fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); 00547 #endif 00548 00549 return 0; 00550 } 00551 00552 //driver loader----------------------------------------------------------------------- 00553 00554 #ifdef __cplusplus 00555 extern "C" 00556 { 00557 #endif 00558 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () 00559 { 00560 jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); 00561 00562 strcpy ( desc->name, "net" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 00563 strcpy ( desc->desc, "netjack slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 00564 00565 desc->nparams = 10; 00566 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); 00567 00568 int i = 0; 00569 strcpy ( desc->params[i].name, "multicast_ip" ); 00570 desc->params[i].character = 'a'; 00571 desc->params[i].type = JackDriverParamString; 00572 strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP ); 00573 strcpy ( desc->params[i].short_desc, "Multicast Address" ); 00574 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00575 00576 i++; 00577 strcpy ( desc->params[i].name, "udp_net_port" ); 00578 desc->params[i].character = 'p'; 00579 desc->params[i].type = JackDriverParamInt; 00580 desc->params[i].value.i = DEFAULT_PORT; 00581 strcpy ( desc->params[i].short_desc, "UDP port" ); 00582 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00583 00584 i++; 00585 strcpy ( desc->params[i].name, "mtu" ); 00586 desc->params[i].character = 'M'; 00587 desc->params[i].type = JackDriverParamInt; 00588 desc->params[i].value.i = DEFAULT_MTU; 00589 strcpy ( desc->params[i].short_desc, "MTU to the master" ); 00590 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00591 00592 i++; 00593 strcpy ( desc->params[i].name, "input_ports" ); 00594 desc->params[i].character = 'C'; 00595 desc->params[i].type = JackDriverParamInt; 00596 desc->params[i].value.i = 2; 00597 strcpy ( desc->params[i].short_desc, "Number of audio input ports" ); 00598 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00599 00600 i++; 00601 strcpy ( desc->params[i].name, "output_ports" ); 00602 desc->params[i].character = 'P'; 00603 desc->params[i].type = JackDriverParamInt; 00604 desc->params[i].value.i = 2; 00605 strcpy ( desc->params[i].short_desc, "Number of audio output ports" ); 00606 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00607 00608 i++; 00609 strcpy ( desc->params[i].name, "midi_in_ports" ); 00610 desc->params[i].character = 'i'; 00611 desc->params[i].type = JackDriverParamInt; 00612 desc->params[i].value.i = 0; 00613 strcpy ( desc->params[i].short_desc, "Number of midi input ports" ); 00614 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00615 00616 i++; 00617 strcpy ( desc->params[i].name, "midi_out_ports" ); 00618 desc->params[i].character = 'o'; 00619 desc->params[i].type = JackDriverParamUInt; 00620 desc->params[i].value.i = 0; 00621 strcpy ( desc->params[i].short_desc, "Number of midi output ports" ); 00622 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00623 00624 i++; 00625 strcpy ( desc->params[i].name, "client_name" ); 00626 desc->params[i].character = 'n'; 00627 desc->params[i].type = JackDriverParamString; 00628 strcpy ( desc->params[i].value.str, "'hostname'" ); 00629 strcpy ( desc->params[i].short_desc, "Name of the jack client" ); 00630 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00631 00632 i++; 00633 strcpy ( desc->params[i].name, "transport_sync" ); 00634 desc->params[i].character = 't'; 00635 desc->params[i].type = JackDriverParamUInt; 00636 desc->params[i].value.ui = 1U; 00637 strcpy ( desc->params[i].short_desc, "Sync transport with master's" ); 00638 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00639 00640 i++; 00641 strcpy ( desc->params[i].name, "mode" ); 00642 desc->params[i].character = 'm'; 00643 desc->params[i].type = JackDriverParamString; 00644 strcpy ( desc->params[i].value.str, "slow" ); 00645 strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." ); 00646 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); 00647 00648 return desc; 00649 } 00650 00651 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params ) 00652 { 00653 char multicast_ip[16]; 00654 strcpy ( multicast_ip, DEFAULT_MULTICAST_IP ); 00655 char net_name[JACK_CLIENT_NAME_SIZE + 1]; 00656 int udp_port = DEFAULT_PORT; 00657 int mtu = DEFAULT_MTU; 00658 uint transport_sync = 1; 00659 jack_nframes_t period_size = 128; 00660 jack_nframes_t sample_rate = 48000; 00661 int audio_capture_ports = 2; 00662 int audio_playback_ports = 2; 00663 int midi_input_ports = 0; 00664 int midi_output_ports = 0; 00665 bool monitor = false; 00666 char network_mode = 's'; 00667 const JSList* node; 00668 const jack_driver_param_t* param; 00669 00670 net_name[0] = 0; 00671 00672 for ( node = params; node; node = jack_slist_next ( node ) ) 00673 { 00674 param = ( const jack_driver_param_t* ) node->data; 00675 switch ( param->character ) 00676 { 00677 case 'a' : 00678 strncpy ( multicast_ip, param->value.str, 15 ); 00679 break; 00680 case 'p': 00681 udp_port = param->value.ui; 00682 break; 00683 case 'M': 00684 mtu = param->value.i; 00685 break; 00686 case 'C': 00687 audio_capture_ports = param->value.i; 00688 break; 00689 case 'P': 00690 audio_playback_ports = param->value.i; 00691 break; 00692 case 'i': 00693 midi_input_ports = param->value.i; 00694 break; 00695 case 'o': 00696 midi_output_ports = param->value.i; 00697 break; 00698 case 'n' : 00699 strncpy ( net_name, param->value.str, JACK_CLIENT_NAME_SIZE ); 00700 break; 00701 case 't' : 00702 transport_sync = param->value.ui; 00703 break; 00704 case 'm' : 00705 if ( strcmp ( param->value.str, "normal" ) == 0 ) 00706 network_mode = 'n'; 00707 else if ( strcmp ( param->value.str, "slow" ) == 0 ) 00708 network_mode = 's'; 00709 else if ( strcmp ( param->value.str, "fast" ) == 0 ) 00710 network_mode = 'f'; 00711 else 00712 jack_error ( "Unknown network mode, using 'normal' mode." ); 00713 break; 00714 } 00715 } 00716 00717 try 00718 { 00719 00720 Jack::JackDriverClientInterface* driver = 00721 new Jack::JackWaitThreadedDriver ( 00722 new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, 00723 midi_input_ports, midi_output_ports, net_name, transport_sync, network_mode ) ); 00724 if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, 00725 monitor, "from_master_", "to_master_", 0, 0 ) == 0 ) 00726 { 00727 return driver; 00728 } 00729 else 00730 { 00731 delete driver; 00732 return NULL; 00733 } 00734 00735 } 00736 catch ( ... ) 00737 { 00738 return NULL; 00739 } 00740 } 00741 00742 #ifdef __cplusplus 00743 } 00744 #endif 00745 }