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