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