Jack2 1.9.6

JackNetAdapter.cpp

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