Jack2 1.9.8

JackNetAdapter.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 "JackNetAdapter.h"
00020 #include "JackException.h"
00021 #include "JackServerGlobals.h"
00022 #include "JackEngineControl.h"
00023 #include "JackArgParser.h"
00024 #include <assert.h>
00025 
00026 namespace Jack
00027 {
00028     JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
00029             : JackAudioAdapterInterface(buffer_size, sample_rate), JackNetSlaveInterface(), fThread(this)
00030     {
00031         jack_log("JackNetAdapter::JackNetAdapter");
00032 
00033         /*
00034         Global parameter setting : we can't call JackNetSlaveInterface constructor with some parameters before,
00035         because we don't have full parametering right now, parameters will be parsed from the param list,
00036         and then JackNetSlaveInterface will be filled with proper values.
00037         */
00038         char multicast_ip[32];
00039         uint udp_port;
00040         GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
00041         fSocket.GetName(fParams.fSlaveNetName);
00042         fParams.fMtu = DEFAULT_MTU;
00043         // Desactivated for now...
00044         fParams.fTransportSync = 0;
00045         int send_audio = -1;
00046         int return_audio = -1;
00047         fParams.fSendMidiChannels = 0;
00048         fParams.fReturnMidiChannels = 0;
00049         fParams.fSampleRate = sample_rate;
00050         fParams.fPeriodSize = buffer_size;
00051         fParams.fSlaveSyncMode = 1;
00052         fParams.fNetworkLatency = 2;
00053         fParams.fSampleEncoder = JackFloatEncoder;
00054         fClient = jack_client;
00055 
00056         // Possibly use env variable
00057         const char* default_udp_port = getenv("JACK_NETJACK_PORT");
00058         udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
00059 
00060         const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
00061         if (default_multicast_ip) {
00062             strcpy(multicast_ip, default_multicast_ip);
00063         } else {
00064             strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
00065         }
00066 
00067         //options parsing
00068         const JSList* node;
00069         const jack_driver_param_t* param;
00070         for (node = params; node; node = jack_slist_next(node))
00071         {
00072             param = (const jack_driver_param_t*) node->data;
00073 
00074             switch (param->character) {
00075                 case 'a' :
00076                     assert(strlen(param->value.str) < 32);
00077                     strcpy(multicast_ip, param->value.str);
00078                     break;
00079                 case 'p' :
00080                     udp_port = param->value.ui;
00081                     break;
00082                 case 'M' :
00083                     fParams.fMtu = param->value.i;
00084                     break;
00085                 case 'C' :
00086                     send_audio = param->value.i;
00087                     break;
00088                 case 'P' :
00089                     return_audio = param->value.i;
00090                     break;
00091                 case 'n' :
00092                     strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE);
00093                     break;
00094                 case 't' :
00095                     fParams.fTransportSync = param->value.ui;
00096                     break;
00097             #if HAVE_CELT
00098                 case 'c':
00099                     if (param->value.i > 0) {
00100                         fParams.fSampleEncoder = JackCeltEncoder;
00101                         fParams.fKBps = param->value.i;
00102                     }
00103                     break;
00104             #endif
00105                 case 'l' :
00106                     fParams.fNetworkLatency = param->value.i;
00107                     if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
00108                         jack_error("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
00109                         throw std::bad_alloc();
00110                     }
00111                     break;
00112                 case 'q':
00113                     fQuality = param->value.ui;
00114                     break;
00115                 case 'g':
00116                     fRingbufferCurSize = param->value.ui;
00117                     fAdaptative = false;
00118                     break;
00119              }
00120         }
00121 
00122         strcpy(fMulticastIP, multicast_ip);
00123 
00124         // Set the socket parameters
00125         fSocket.SetPort(udp_port);
00126         fSocket.SetAddress(fMulticastIP, udp_port);
00127 
00128         // If not set, takes default
00129         fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
00130 
00131         // If not set, takes default
00132         fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
00133 
00134         // Set the audio adapter interface channel values
00135         SetInputs(fParams.fSendAudioChannels);
00136         SetOutputs(fParams.fReturnAudioChannels);
00137 
00138         // Soft buffers will be allocated later (once network initialization done)
00139         fSoftCaptureBuffer = NULL;
00140         fSoftPlaybackBuffer = NULL;
00141     }
00142 
00143     JackNetAdapter::~JackNetAdapter()
00144     {
00145         jack_log("JackNetAdapter::~JackNetAdapter");
00146 
00147         if (fSoftCaptureBuffer) {
00148             for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
00149                 delete[] fSoftCaptureBuffer[port_index];
00150             }
00151             delete[] fSoftCaptureBuffer;
00152         }
00153         if (fSoftPlaybackBuffer) {
00154             for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
00155                 delete[] fSoftPlaybackBuffer[port_index];
00156             }
00157             delete[] fSoftPlaybackBuffer;
00158         }
00159     }
00160 
00161 //open/close--------------------------------------------------------------------------
00162     int JackNetAdapter::Open()
00163     {
00164         jack_info("NetAdapter started in %s mode %s Master's transport sync.",
00165                     (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
00166 
00167         if (fThread.StartSync() < 0) {
00168             jack_error("Cannot start netadapter thread");
00169             return -1;
00170         }
00171 
00172         return 0;
00173     }
00174 
00175     int JackNetAdapter::Close()
00176     {
00177         int res = 0;
00178         jack_log("JackNetAdapter::Close");
00179 
00180 #ifdef JACK_MONITOR
00181         fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
00182 #endif
00183 
00184         if (fThread.Kill() < 0) {
00185             jack_error("Cannot kill thread");
00186             res = -1;
00187         }
00188 
00189         fSocket.Close();
00190         return res;
00191    }
00192 
00193     int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
00194     {
00195         JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
00196         return 0;
00197     }
00198 
00199 //thread------------------------------------------------------------------------------
00200     // TODO : if failure, thread exist... need to restart ?
00201 
00202     bool JackNetAdapter::Init()
00203     {
00204         jack_log("JackNetAdapter::Init");
00205 
00206         //init network connection
00207         if (!JackNetSlaveInterface::Init()) {
00208             jack_error("JackNetSlaveInterface::Init() error...");
00209             return false;
00210         }
00211 
00212         //then set global parameters
00213         if (!SetParams()) {
00214             jack_error("SetParams error...");
00215             return false;
00216         }
00217 
00218         //set buffers
00219         if (fCaptureChannels > 0) {
00220             fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
00221             for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
00222                 fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
00223                 fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
00224             }
00225         }
00226 
00227         if (fPlaybackChannels > 0) {
00228             fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
00229             for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
00230                 fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
00231                 fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
00232             }
00233         }
00234 
00235         //set audio adapter parameters
00236         SetAdaptedBufferSize(fParams.fPeriodSize);
00237         SetAdaptedSampleRate(fParams.fSampleRate);
00238 
00239         // Will do "something" on OSX only...
00240         fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
00241 
00242         if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
00243             jack_error("AcquireSelfRealTime error");
00244         } else {
00245             set_threaded_log_function();
00246         }
00247 
00248         //init done, display parameters
00249         SessionParamsDisplay(&fParams);
00250         return true;
00251     }
00252 
00253     bool JackNetAdapter::Execute()
00254     {
00255         try {
00256             // Keep running even in case of error
00257             while (fThread.GetStatus() == JackThread::kRunning)
00258                 if (Process() == SOCKET_ERROR) {
00259                     return false;
00260                 }
00261             return false;
00262         } catch (JackNetException& e) {
00263             e.PrintMessage();
00264             jack_info("NetAdapter is restarted");
00265             Reset();
00266             fThread.DropSelfRealTime();
00267             fThread.SetStatus(JackThread::kIniting);
00268             if (Init()) {
00269                 fThread.SetStatus(JackThread::kRunning);
00270                 return true;
00271             } else {
00272                 return false;
00273             }
00274         }
00275     }
00276 
00277 //transport---------------------------------------------------------------------------
00278     void JackNetAdapter::DecodeTransportData()
00279     {
00280         //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver)
00281 
00282         //is there a new transport state ?
00283         if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fClient, NULL))) {
00284             switch (fSendTransportData.fState)
00285             {
00286                 case JackTransportStopped :
00287                     jack_transport_stop(fClient);
00288                     jack_info("NetMaster : transport stops");
00289                     break;
00290 
00291                 case JackTransportStarting :
00292                     jack_transport_reposition(fClient, &fSendTransportData.fPosition);
00293                     jack_transport_start(fClient);
00294                     jack_info("NetMaster : transport starts");
00295                     break;
00296 
00297                 case JackTransportRolling :
00298                     // TODO, we need to :
00299                     // - find a way to call TransportEngine->SetNetworkSync()
00300                     // - turn the transport state to JackTransportRolling
00301                     jack_info("NetMaster : transport rolls");
00302                     break;
00303             }
00304         }
00305     }
00306 
00307     void JackNetAdapter::EncodeTransportData()
00308     {
00309         //is there a timebase master change ?
00310         int refnum = -1;
00311         bool conditional = 0;
00312         //TODO : get the actual timebase master
00313         if (refnum != fLastTimebaseMaster) {
00314             //timebase master has released its function
00315             if (refnum == -1) {
00316                 fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
00317                 jack_info("Sending a timebase master release request.");
00318             } else {
00319                 //there is a new timebase master
00320                 fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
00321                 jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
00322             }
00323             fLastTimebaseMaster = refnum;
00324         } else {
00325             fReturnTransportData.fTimebaseMaster = NO_CHANGE;
00326         }
00327 
00328         //update transport state and position
00329         fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition);
00330 
00331         //is it a new state (that the master need to know...) ?
00332         fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
00333                                            (fReturnTransportData.fState != fSendTransportData.fState));
00334         if (fReturnTransportData.fNewState) {
00335             jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
00336         }
00337         fLastTransportState = fReturnTransportData.fState;
00338     }
00339 
00340 //read/write operations---------------------------------------------------------------
00341     int JackNetAdapter::Read()
00342     {
00343         //don't return -1 in case of sync recv failure
00344         //we need the process to continue for network error detection
00345         if (SyncRecv() == SOCKET_ERROR) {
00346             return 0;
00347         }
00348 
00349         DecodeSyncPacket();
00350         return DataRecv();
00351     }
00352 
00353     int JackNetAdapter::Write()
00354     {
00355         EncodeSyncPacket();
00356 
00357         if (SyncSend() == SOCKET_ERROR) {
00358             return SOCKET_ERROR;
00359         }
00360 
00361         return DataSend();
00362     }
00363 
00364 //process-----------------------------------------------------------------------------
00365     int JackNetAdapter::Process()
00366     {
00367         //read data from the network
00368         //in case of fatal network error, stop the process
00369         if (Read() == SOCKET_ERROR) {
00370             return SOCKET_ERROR;
00371         }
00372 
00373         PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
00374 
00375         //then write data to network
00376         //in case of failure, stop process
00377         if (Write() == SOCKET_ERROR) {
00378             return SOCKET_ERROR;
00379         }
00380 
00381         return 0;
00382     }
00383 
00384 } // namespace Jack
00385 
00386 //loader------------------------------------------------------------------------------
00387 #ifdef __cplusplus
00388 extern "C"
00389 {
00390 #endif
00391 
00392 #include "driver_interface.h"
00393 #include "JackAudioAdapter.h"
00394 
00395     using namespace Jack;
00396 
00397     SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00398     {
00399         jack_driver_desc_t * desc;
00400         jack_driver_desc_filler_t filler;
00401         jack_driver_param_value_t value;
00402 
00403         desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler);
00404 
00405         strcpy(value.str, DEFAULT_MULTICAST_IP);
00406         jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
00407 
00408         value.i = DEFAULT_PORT;
00409         jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
00410 
00411         value.i = DEFAULT_MTU;
00412         jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
00413 
00414         value.i = 2;
00415         jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL);
00416         jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL);
00417 
00418     #if HAVE_CELT
00419         value.i = -1;
00420         jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
00421     #endif
00422 
00423         strcpy(value.str, "'hostname'");
00424         jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
00425 
00426         value.ui = 0U;
00427         jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
00428 
00429         value.ui = 5U;
00430         jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);
00431 
00432         value.i = 0;
00433         jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
00434 
00435         value.i = 32768;
00436         jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
00437 
00438         value.i = false;
00439         jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", "");
00440 
00441         return desc;
00442     }
00443 
00444     SERVER_EXPORT int jack_internal_initialize(jack_client_t* client, const JSList* params)
00445     {
00446         jack_log("Loading netadapter");
00447 
00448         Jack::JackAudioAdapter* adapter;
00449         jack_nframes_t buffer_size = jack_get_buffer_size(client);
00450         jack_nframes_t sample_rate = jack_get_sample_rate(client);
00451 
00452         try {
00453 
00454             adapter = new Jack::JackAudioAdapter(client, new Jack::JackNetAdapter(client, buffer_size, sample_rate, params), params);
00455             assert(adapter);
00456 
00457             if (adapter->Open() == 0) {
00458                 return 0;
00459             } else {
00460                 delete adapter;
00461                 return 1;
00462             }
00463 
00464         } catch (...) {
00465             jack_info("NetAdapter allocation error");
00466             return 1;
00467         }
00468     }
00469 
00470     SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
00471     {
00472         JSList* params = NULL;
00473         bool parse_params = true;
00474         int res = 1;
00475         jack_driver_desc_t* desc = jack_get_descriptor();
00476 
00477         Jack::JackArgParser parser(load_init);
00478         if (parser.GetArgc() > 0) {
00479             parse_params = parser.ParseParams(desc, &params);
00480         }
00481 
00482         if (parse_params) {
00483             res = jack_internal_initialize(jack_client, params);
00484             parser.FreeParams(params);
00485         }
00486         return res;
00487     }
00488 
00489     SERVER_EXPORT void jack_finish(void* arg)
00490     {
00491         Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*>(arg);
00492 
00493         if (adapter) {
00494             jack_log("Unloading netadapter");
00495             adapter->Close();
00496             delete adapter;
00497         }
00498     }
00499 
00500 #ifdef __cplusplus
00501 }
00502 #endif