Jack2 1.9.7
JackNetDriver.cpp
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         jack_latency_range_t range;
00257 
00258         //audio
00259         port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
00260         for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
00261         {
00262             snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1 );
00263             snprintf ( name, sizeof ( name ) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1 );
00264             if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
00265                              static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
00266             {
00267                 jack_error ( "driver: cannot register port for %s", name );
00268                 return -1;
00269             }
00270             port = fGraphManager->GetPort ( port_id );
00271             port->SetAlias ( alias );
00272             //port latency
00273             range.min = range.max = fEngineControl->fBufferSize;
00274             port->SetLatencyRange(JackCaptureLatency, &range);
00275             fCapturePortList[audio_port_index] = port_id;
00276             jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
00277         }
00278         port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
00279         for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
00280         {
00281             snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1 );
00282             snprintf ( name, sizeof ( name ) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1 );
00283             if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
00284                              static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
00285             {
00286                 jack_error ( "driver: cannot register port for %s", name );
00287                 return -1;
00288             }
00289             port = fGraphManager->GetPort ( port_id );
00290             port->SetAlias ( alias );
00291             //port latency
00292             switch ( fParams.fNetworkMode )
00293             {
00294                 case 'f' :
00295                     range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
00296                     break;
00297                 case 'n' :
00298                     range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
00299                     break;
00300                 case 's' :
00301                     range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
00302                     break;
00303             }
00304             port->SetLatencyRange(JackPlaybackLatency, &range);
00305             fPlaybackPortList[audio_port_index] = port_id;
00306             jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
00307         }
00308         //midi
00309         port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
00310         for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
00311         {
00312             snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1 );
00313             snprintf ( name, sizeof ( name ) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1 );
00314             if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
00315                              static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
00316             {
00317                 jack_error ( "driver: cannot register port for %s", name );
00318                 return -1;
00319             }
00320             port = fGraphManager->GetPort ( port_id );
00321             //port latency
00322             range.min = range.max = fEngineControl->fBufferSize;
00323             port->SetLatencyRange(JackCaptureLatency, &range);
00324             fMidiCapturePortList[midi_port_index] = port_id;
00325             jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
00326         }
00327 
00328         port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
00329         for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
00330         {
00331             snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1 );
00332             snprintf ( name, sizeof ( name ) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1 );
00333             if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
00334                              static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
00335             {
00336                 jack_error ( "driver: cannot register port for %s", name );
00337                 return -1;
00338             }
00339             port = fGraphManager->GetPort ( port_id );
00340             //port latency
00341             switch ( fParams.fNetworkMode )
00342             {
00343                 case 'f' :
00344                     range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
00345                     break;
00346                 case 'n' :
00347                     range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
00348                     break;
00349                 case 's' :
00350                     range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
00351                     break;
00352             }
00353             port->SetLatencyRange(JackPlaybackLatency, &range);
00354             fMidiPlaybackPortList[midi_port_index] = port_id;
00355             jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
00356         }
00357 
00358         return 0;
00359     }
00360 
00361     int JackNetDriver::FreePorts()
00362     {
00363         jack_log ( "JackNetDriver::FreePorts" );
00364 
00365         int audio_port_index;
00366         uint midi_port_index;
00367         for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
00368             if (fCapturePortList[audio_port_index] > 0)
00369                 fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index] );
00370         for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
00371             if (fPlaybackPortList[audio_port_index] > 0)
00372                 fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index] );
00373         for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
00374             if (fMidiCapturePortList[midi_port_index] > 0)
00375                 fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index] );
00376         for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
00377             if (fMidiPlaybackPortList[midi_port_index] > 0)
00378                 fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index] );
00379         return 0;
00380     }
00381 
00382     JackMidiBuffer* JackNetDriver::GetMidiInputBuffer ( int port_index )
00383     {
00384         return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiCapturePortList[port_index], fEngineControl->fBufferSize ) );
00385     }
00386 
00387     JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer ( int port_index )
00388     {
00389         return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
00390     }
00391 
00392 //transport---------------------------------------------------------------------------
00393     void JackNetDriver::DecodeTransportData()
00394     {
00395         //is there a new timebase master on the net master ?
00396         // - release timebase master only if it's a non-conditional request
00397         // - no change or no request : don't do anything
00398         // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master
00399         int refnum;
00400         bool conditional;
00401         if ( fSendTransportData.fTimebaseMaster == TIMEBASEMASTER )
00402         {
00403             fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
00404             if ( refnum != -1 )
00405                 fEngineControl->fTransport.ResetTimebase ( refnum );
00406             jack_info ( "The NetMaster is now the new timebase master." );
00407         }
00408 
00409         //is there a transport state change to handle ?
00410         if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) )
00411         {
00412 
00413             switch ( fSendTransportData.fState )
00414             {
00415                 case JackTransportStopped :
00416                     fEngineControl->fTransport.SetCommand ( TransportCommandStop );
00417                     jack_info ( "Master stops transport." );
00418                     break;
00419 
00420                 case JackTransportStarting :
00421                     fEngineControl->fTransport.RequestNewPos ( &fSendTransportData.fPosition );
00422                     fEngineControl->fTransport.SetCommand ( TransportCommandStart );
00423                     jack_info ( "Master starts transport frame = %d", fSendTransportData.fPosition.frame);
00424                     break;
00425 
00426                 case JackTransportRolling :
00427                     //fEngineControl->fTransport.SetCommand ( TransportCommandStart );
00428                     fEngineControl->fTransport.SetState ( JackTransportRolling );
00429                     jack_info ( "Master is rolling." );
00430                     break;
00431             }
00432         }
00433     }
00434 
00435     void JackNetDriver::EncodeTransportData()
00436     {
00437         /* Desactivated
00438         //is there a timebase master change ?
00439         int refnum;
00440         bool conditional;
00441         fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
00442         if ( refnum != fLastTimebaseMaster )
00443         {
00444             //timebase master has released its function
00445             if ( refnum == -1 )
00446             {
00447                 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00448                 jack_info ( "Sending a timebase master release request." );
00449             }
00450             //there is a new timebase master
00451             else
00452             {
00453                 fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
00454                 jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" );
00455             }
00456             fLastTimebaseMaster = refnum;
00457         }
00458         else
00459             fReturnTransportData.fTimebaseMaster = NO_CHANGE;
00460         */
00461 
00462         //update transport state and position
00463         fReturnTransportData.fState = fEngineControl->fTransport.Query ( &fReturnTransportData.fPosition );
00464 
00465         //is it a new state (that the master need to know...) ?
00466         fReturnTransportData.fNewState = (( fReturnTransportData.fState == JackTransportNetStarting) &&
00467                                            ( fReturnTransportData.fState != fLastTransportState ) &&
00468                                            ( fReturnTransportData.fState != fSendTransportData.fState ) );
00469         if ( fReturnTransportData.fNewState )
00470             jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) );
00471         fLastTransportState = fReturnTransportData.fState;
00472     }
00473 
00474 //driver processes--------------------------------------------------------------------
00475     int JackNetDriver::Read()
00476     {
00477         uint midi_port_index;
00478         uint audio_port_index;
00479 
00480         //buffers
00481         for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
00482             fNetMidiCaptureBuffer->SetBuffer ( midi_port_index, GetMidiInputBuffer ( midi_port_index ) );
00483         for ( audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++ )
00484             fNetAudioCaptureBuffer->SetBuffer ( audio_port_index, GetInputBuffer ( audio_port_index ) );
00485 
00486 #ifdef JACK_MONITOR
00487         fNetTimeMon->New();
00488 #endif
00489 
00490         //receive sync (launch the cycle)
00491         if ( SyncRecv() == SOCKET_ERROR )
00492             return 0;
00493 
00494 #ifdef JACK_MONITOR
00495         // For timing
00496         fRcvSyncUst = GetMicroSeconds();
00497 #endif
00498 
00499         //decode sync
00500         //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified
00501         DecodeSyncPacket();
00502 
00503 #ifdef JACK_MONITOR
00504         fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
00505 #endif
00506         //audio, midi or sync if driver is late
00507         if ( DataRecv() == SOCKET_ERROR )
00508             return SOCKET_ERROR;
00509 
00510         //take the time at the beginning of the cycle
00511         JackDriver::CycleTakeBeginTime();
00512 
00513 #ifdef JACK_MONITOR
00514         fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
00515 #endif
00516 
00517         return 0;
00518     }
00519 
00520     int JackNetDriver::Write()
00521     {
00522         uint midi_port_index;
00523         int audio_port_index;
00524 
00525         //buffers
00526         for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
00527             fNetMidiPlaybackBuffer->SetBuffer ( midi_port_index, GetMidiOutputBuffer ( midi_port_index ) );
00528         for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
00529             fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) );
00530 
00531 #ifdef JACK_MONITOR
00532         fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
00533 #endif
00534 
00535         //sync
00536         EncodeSyncPacket();
00537 
00538         //send sync
00539         if ( SyncSend() == SOCKET_ERROR )
00540             return SOCKET_ERROR;
00541 
00542 #ifdef JACK_MONITOR
00543         fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
00544 #endif
00545 
00546         //send data
00547         if ( DataSend() == SOCKET_ERROR )
00548             return SOCKET_ERROR;
00549 
00550 #ifdef JACK_MONITOR
00551         fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
00552 #endif
00553 
00554         return 0;
00555     }
00556 
00557 //driver loader-----------------------------------------------------------------------
00558 
00559 #ifdef __cplusplus
00560     extern "C"
00561     {
00562 #endif
00563         SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
00564         {
00565             jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
00566 
00567             strcpy ( desc->name, "net" );                             // size MUST be less then JACK_DRIVER_NAME_MAX + 1
00568             strcpy ( desc->desc, "netjack slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
00569 
00570             desc->nparams = 10;
00571             desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
00572 
00573             int i = 0;
00574             strcpy ( desc->params[i].name, "multicast_ip" );
00575             desc->params[i].character = 'a';
00576             desc->params[i].type = JackDriverParamString;
00577             strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
00578             strcpy ( desc->params[i].short_desc, "Multicast Address" );
00579             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00580 
00581             i++;
00582             strcpy ( desc->params[i].name, "udp_net_port" );
00583             desc->params[i].character = 'p';
00584             desc->params[i].type = JackDriverParamInt;
00585             desc->params[i].value.i = DEFAULT_PORT;
00586             strcpy ( desc->params[i].short_desc, "UDP port" );
00587             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00588 
00589             i++;
00590             strcpy ( desc->params[i].name, "mtu" );
00591             desc->params[i].character = 'M';
00592             desc->params[i].type = JackDriverParamInt;
00593             desc->params[i].value.i = DEFAULT_MTU;
00594             strcpy ( desc->params[i].short_desc, "MTU to the master" );
00595             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00596 
00597             i++;
00598             strcpy ( desc->params[i].name, "input_ports" );
00599             desc->params[i].character = 'C';
00600             desc->params[i].type = JackDriverParamInt;
00601             desc->params[i].value.i = 2;
00602             strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
00603             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00604 
00605             i++;
00606             strcpy ( desc->params[i].name, "output_ports" );
00607             desc->params[i].character = 'P';
00608             desc->params[i].type = JackDriverParamInt;
00609             desc->params[i].value.i = 2;
00610             strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
00611             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00612 
00613             i++;
00614             strcpy ( desc->params[i].name, "midi_in_ports" );
00615             desc->params[i].character = 'i';
00616             desc->params[i].type = JackDriverParamInt;
00617             desc->params[i].value.i = 0;
00618             strcpy ( desc->params[i].short_desc, "Number of midi input ports" );
00619             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00620 
00621             i++;
00622             strcpy ( desc->params[i].name, "midi_out_ports" );
00623             desc->params[i].character = 'o';
00624             desc->params[i].type = JackDriverParamUInt;
00625             desc->params[i].value.i = 0;
00626             strcpy ( desc->params[i].short_desc, "Number of midi output ports" );
00627             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00628 
00629             i++;
00630             strcpy ( desc->params[i].name, "client_name" );
00631             desc->params[i].character = 'n';
00632             desc->params[i].type = JackDriverParamString;
00633             strcpy ( desc->params[i].value.str, "'hostname'" );
00634             strcpy ( desc->params[i].short_desc, "Name of the jack client" );
00635             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00636 
00637             i++;
00638             strcpy ( desc->params[i].name, "transport_sync" );
00639             desc->params[i].character  = 't';
00640             desc->params[i].type = JackDriverParamUInt;
00641             desc->params[i].value.ui = 1U;
00642             strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
00643             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00644 
00645             i++;
00646             strcpy ( desc->params[i].name, "mode" );
00647             desc->params[i].character  = 'm';
00648             desc->params[i].type = JackDriverParamString;
00649             strcpy ( desc->params[i].value.str, "slow" );
00650             strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
00651             strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00652 
00653             return desc;
00654         }
00655 
00656         SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
00657         {
00658             char multicast_ip[16];
00659             strcpy ( multicast_ip, DEFAULT_MULTICAST_IP );
00660             char net_name[JACK_CLIENT_NAME_SIZE + 1];
00661             int udp_port = DEFAULT_PORT;
00662             int mtu = DEFAULT_MTU;
00663             uint transport_sync = 1;
00664             jack_nframes_t period_size = 128;
00665             jack_nframes_t sample_rate = 48000;
00666             int audio_capture_ports = 2;
00667             int audio_playback_ports = 2;
00668             int midi_input_ports = 0;
00669             int midi_output_ports = 0;
00670             bool monitor = false;
00671             char network_mode = 's';
00672             const JSList* node;
00673             const jack_driver_param_t* param;
00674 
00675             net_name[0] = 0;
00676 
00677             for ( node = params; node; node = jack_slist_next ( node ) )
00678             {
00679                 param = ( const jack_driver_param_t* ) node->data;
00680                 switch ( param->character )
00681                 {
00682                     case 'a' :
00683                         strncpy ( multicast_ip, param->value.str, 15 );
00684                         break;
00685                     case 'p':
00686                         udp_port = param->value.ui;
00687                         break;
00688                     case 'M':
00689                         mtu = param->value.i;
00690                         break;
00691                     case 'C':
00692                         audio_capture_ports = param->value.i;
00693                         break;
00694                     case 'P':
00695                         audio_playback_ports = param->value.i;
00696                         break;
00697                     case 'i':
00698                         midi_input_ports = param->value.i;
00699                         break;
00700                     case 'o':
00701                         midi_output_ports = param->value.i;
00702                         break;
00703                     case 'n' :
00704                         strncpy ( net_name, param->value.str, JACK_CLIENT_NAME_SIZE );
00705                         break;
00706                     case 't' :
00707                         transport_sync = param->value.ui;
00708                         break;
00709                     case 'm' :
00710                         if ( strcmp ( param->value.str, "normal" ) == 0 )
00711                             network_mode = 'n';
00712                         else if ( strcmp ( param->value.str, "slow" ) == 0 )
00713                             network_mode = 's';
00714                         else if ( strcmp ( param->value.str, "fast" ) == 0 )
00715                             network_mode = 'f';
00716                         else
00717                             jack_error ( "Unknown network mode, using 'normal' mode." );
00718                         break;
00719                 }
00720             }
00721 
00722             try
00723             {
00724 
00725                 Jack::JackDriverClientInterface* driver =
00726                     new Jack::JackWaitThreadedDriver (
00727                     new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
00728                                               midi_input_ports, midi_output_ports, net_name, transport_sync, network_mode ) );
00729                 if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports,
00730                                     monitor, "from_master_", "to_master_", 0, 0 ) == 0 )
00731                 {
00732                     return driver;
00733                 }
00734                 else
00735                 {
00736                     delete driver;
00737                     return NULL;
00738                 }
00739 
00740             }
00741             catch ( ... )
00742             {
00743                 return NULL;
00744             }
00745         }
00746 
00747 #ifdef __cplusplus
00748     }
00749 #endif
00750 }