Jack2 1.9.8

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