Jack2 1.9.6

JackNetManager.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 "JackNetManager.h"
00020 #include "JackArgParser.h"
00021 #include "JackTime.h"
00022 
00023 using namespace std;
00024 
00025 namespace Jack
00026 {
00027 //JackNetMaster******************************************************************************************************
00028 
00029     JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip)
00030             : JackNetMasterInterface ( params, socket, multicast_ip )
00031     {
00032         jack_log ( "JackNetMaster::JackNetMaster" );
00033 
00034         //settings
00035         fClientName = const_cast<char*> ( fParams.fName );
00036         fJackClient = NULL;
00037         fSendTransportData.fState = -1;
00038         fReturnTransportData.fState = -1;
00039         fLastTransportState = -1;
00040         uint port_index;
00041 
00042         //jack audio ports
00043         fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
00044         for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
00045             fAudioCapturePorts[port_index] = NULL;
00046         fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
00047         for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
00048             fAudioPlaybackPorts[port_index] = NULL;
00049         //jack midi ports
00050         fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
00051         for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
00052             fMidiCapturePorts[port_index] = NULL;
00053         fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
00054         for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
00055             fMidiPlaybackPorts[port_index] = NULL;
00056 
00057         //monitor
00058 #ifdef JACK_MONITOR
00059         fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) );
00060         string plot_name;
00061         plot_name = string ( fParams.fName );
00062         plot_name += string ( "_master" );
00063         plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
00064         switch ( fParams.fNetworkMode )
00065         {
00066             case 's' :
00067                 plot_name += string ( "_slow" );
00068                 break;
00069             case 'n' :
00070                 plot_name += string ( "_normal" );
00071                 break;
00072             case 'f' :
00073                 plot_name += string ( "_fast" );
00074                 break;
00075         }
00076         fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
00077         string net_time_mon_fields[] =
00078         {
00079             string ( "sync send" ),
00080             string ( "end of send" ),
00081             string ( "sync recv" ),
00082             string ( "end of cycle" )
00083         };
00084         string net_time_mon_options[] =
00085         {
00086             string ( "set xlabel \"audio cycles\"" ),
00087             string ( "set ylabel \"% of audio cycle\"" )
00088         };
00089         fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
00090 #endif
00091     }
00092 
00093     JackNetMaster::~JackNetMaster()
00094     {
00095         jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams.fID );
00096 
00097         if ( fJackClient )
00098         {
00099             jack_deactivate ( fJackClient );
00100             FreePorts();
00101             jack_client_close ( fJackClient );
00102         }
00103         delete[] fAudioCapturePorts;
00104         delete[] fAudioPlaybackPorts;
00105         delete[] fMidiCapturePorts;
00106         delete[] fMidiPlaybackPorts;
00107 #ifdef JACK_MONITOR
00108         fNetTimeMon->Save();
00109         delete fNetTimeMon;
00110 #endif
00111     }
00112 //init--------------------------------------------------------------------------------
00113     bool JackNetMaster::Init(bool auto_connect)
00114     {
00115         //network init
00116         if ( !JackNetMasterInterface::Init() )
00117             return false;
00118 
00119         //set global parameters
00120         SetParams();
00121 
00122         //jack client and process
00123         jack_status_t status;
00124         if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL )
00125         {
00126             jack_error ( "Can't open a new jack client." );
00127             return false;
00128         }
00129 
00130         if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0)
00131              goto fail;
00132              
00133         if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0)
00134              goto fail;
00135 
00136         if ( AllocPorts() != 0 )
00137         {
00138             jack_error ( "Can't allocate jack ports." );
00139             goto fail;
00140         }
00141 
00142         //process can now run
00143         fRunning = true;
00144 
00145         //finally activate jack client
00146         if ( jack_activate ( fJackClient ) != 0 )
00147         {
00148             jack_error ( "Can't activate jack client." );
00149             goto fail;
00150         }
00151         
00152         if (auto_connect)
00153             ConnectPorts();
00154         jack_info ( "New NetMaster started." );
00155         return true;
00156 
00157     fail:
00158         FreePorts();
00159         jack_client_close ( fJackClient );
00160         fJackClient = NULL;
00161         return false;
00162     }
00163 
00164 //jack ports--------------------------------------------------------------------------
00165     int JackNetMaster::AllocPorts()
00166     {
00167         uint i;
00168         char name[24];
00169         jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient );
00170         
00171         jack_log ( "JackNetMaster::AllocPorts" );
00172 
00173         //audio
00174         for ( i = 0; i < fParams.fSendAudioChannels; i++ )
00175         {
00176             sprintf ( name, "to_slave_%d", i+1 );
00177             if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
00178                 return -1;
00179             //port latency
00180             jack_port_set_latency ( fAudioCapturePorts[i], 0 );
00181         }
00182         
00183         for ( i = 0; i < fParams.fReturnAudioChannels; i++ )
00184         {
00185             sprintf ( name, "from_slave_%d", i+1 );
00186             if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
00187                 return -1;
00188             //port latency
00189             switch ( fParams.fNetworkMode )
00190             {
00191                 case 'f' :
00192                     jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
00193                     break;
00194                 case 'n' :
00195                     jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
00196                     break;
00197                 case 's' :
00198                     jack_port_set_latency ( fAudioPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
00199                     break;
00200             }
00201         }
00202         
00203         
00204         //midi
00205         for ( i = 0; i < fParams.fSendMidiChannels; i++ )
00206         {
00207             sprintf ( name, "midi_to_slave_%d", i+1 );
00208             if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
00209                 return -1;
00210             //port latency
00211             jack_port_set_latency ( fMidiCapturePorts[i], 0 );
00212         }
00213         for ( i = 0; i < fParams.fReturnMidiChannels; i++ )
00214         {
00215             sprintf ( name, "midi_from_slave_%d", i+1 );
00216             if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE,  JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
00217                 return -1;
00218             //port latency
00219             switch ( fParams.fNetworkMode )
00220             {
00221                 case 'f' :
00222                     jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
00223                     break;
00224                 case 'n' :
00225                     jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
00226                     break;
00227                 case 's' :
00228                     jack_port_set_latency ( fMidiPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
00229                     break;
00230             }
00231         }
00232         return 0;
00233     }
00234     
00235     void JackNetMaster::ConnectPorts()
00236     {
00237         const char **ports;
00238          
00239         ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
00240         if (ports != NULL) {
00241             for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
00242                 jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i]));
00243             }
00244             free(ports);
00245         }
00246         
00247         ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
00248         if (ports != NULL) {
00249             for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
00250                 jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]);
00251             }
00252             free(ports);
00253         }
00254     }
00255 
00256     void JackNetMaster::FreePorts()
00257     {
00258         jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID );
00259 
00260         uint port_index;
00261         for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
00262             if ( fAudioCapturePorts[port_index] )
00263                 jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] );
00264         for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
00265             if ( fAudioPlaybackPorts[port_index] )
00266                 jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] );
00267         for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
00268             if ( fMidiCapturePorts[port_index] )
00269                 jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] );
00270         for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
00271             if ( fMidiPlaybackPorts[port_index] )
00272                 jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
00273     }
00274 
00275 //transport---------------------------------------------------------------------------
00276     void JackNetMaster::EncodeTransportData()
00277     {
00278         //is there a new timebase master ?
00279         //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
00280         fSendTransportData.fTimebaseMaster = NO_CHANGE;
00281 
00282         //update state and position
00283         fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) );
00284 
00285         //is it a new state ?
00286         fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
00287                                          ( fSendTransportData.fState != fReturnTransportData.fState ) );
00288         if ( fSendTransportData.fNewState )
00289             jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame );
00290         fLastTransportState = fSendTransportData.fState;
00291    }
00292 
00293     void JackNetMaster::DecodeTransportData()
00294     {
00295         //is there timebase master change ?
00296         if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE )
00297         {
00298             int timebase = 0;
00299             switch ( fReturnTransportData.fTimebaseMaster )
00300             {
00301                 case RELEASE_TIMEBASEMASTER :
00302                     timebase = jack_release_timebase ( fJackClient );
00303                     if ( timebase < 0 )
00304                         jack_error ( "Can't release timebase master." );
00305                     else
00306                         jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
00307                     break;
00308                     
00309                 case TIMEBASEMASTER :
00310                     timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
00311                     if ( timebase < 0 )
00312                         jack_error ( "Can't set a new timebase master." );
00313                     else
00314                         jack_info ( "'%s' is the new timebase master.", fParams.fName );
00315                     break;
00316                     
00317                 case CONDITIONAL_TIMEBASEMASTER :
00318                     timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
00319                     if ( timebase != EBUSY )
00320                     {
00321                         if ( timebase < 0 )
00322                             jack_error ( "Can't set a new timebase master." );
00323                         else
00324                             jack_info ( "'%s' is the new timebase master.", fParams.fName );
00325                     }
00326                     break;
00327             }
00328         }
00329 
00330         //is the slave in a new transport state and is this state different from master's ?
00331         if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
00332         {
00333             switch ( fReturnTransportData.fState )
00334             {
00335                 case JackTransportStopped :
00336                     jack_transport_stop ( fJackClient );
00337                     jack_info ( "'%s' stops transport.", fParams.fName );
00338                     break;
00339                     
00340                 case JackTransportStarting :
00341                     if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL )
00342                         jack_error ( "Can't set new position." );
00343                     jack_transport_start ( fJackClient );
00344                     jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
00345                     break;
00346                     
00347                 case JackTransportNetStarting :
00348                     jack_info ( "'%s' is ready to roll..", fParams.fName );
00349                     break;
00350                     
00351                 case JackTransportRolling :
00352                     jack_info ( "'%s' is rolling.", fParams.fName );
00353                     break;
00354             }
00355         }
00356     }
00357 
00358     void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
00359     {
00360         static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
00361     }
00362 
00363     void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
00364     {
00365         pos->bar = fReturnTransportData.fPosition.bar;
00366         pos->beat = fReturnTransportData.fPosition.beat;
00367         pos->tick = fReturnTransportData.fPosition.tick;
00368         pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
00369         pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
00370         pos->beat_type = fReturnTransportData.fPosition.beat_type;
00371         pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
00372         pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
00373     }
00374 
00375 //sync--------------------------------------------------------------------------------
00376  
00377     bool JackNetMaster::IsSlaveReadyToRoll()
00378     {
00379         return ( fReturnTransportData.fState == JackTransportNetStarting );
00380     }
00381     
00382     int JackNetMaster::SetBufferSize (jack_nframes_t nframes, void* arg)
00383     {
00384         jack_error("Cannot handle bufer size change, so proxy will be removed...");
00385         static_cast<JackNetMaster*> ( arg )->Exit();
00386         return 0;
00387     }
00388 
00389 //process-----------------------------------------------------------------------------
00390     int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
00391     {
00392         return static_cast<JackNetMaster*> ( arg )->Process();
00393     }
00394 
00395     int JackNetMaster::Process()
00396     {
00397         if ( !fRunning )
00398             return 0;
00399 
00400         uint port_index;
00401         int res = 0;
00402 
00403 #ifdef JACK_MONITOR
00404         jack_time_t begin_time = GetMicroSeconds();
00405         fNetTimeMon->New();
00406 #endif
00407 
00408         //buffers
00409         for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
00410             fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
00411                                                fParams.fPeriodSize ) ) );
00412         for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
00413             fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
00414                                                 fParams.fPeriodSize ) ) );
00415         for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
00416             fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
00417                                                 fParams.fPeriodSize ) ) );
00418         for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
00419             fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
00420                                                  fParams.fPeriodSize ) ) );
00421 
00422         if (IsSynched()) {  // only send if connection is "synched"
00423         
00424             //encode the first packet
00425             EncodeSyncPacket();
00426    
00427             //send sync
00428             if ( SyncSend() == SOCKET_ERROR )
00429                 return SOCKET_ERROR;
00430 
00431     #ifdef JACK_MONITOR
00432             fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
00433     #endif
00434 
00435             //send data
00436             if ( DataSend() == SOCKET_ERROR )
00437                 return SOCKET_ERROR;
00438 
00439     #ifdef JACK_MONITOR
00440             fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
00441     #endif
00442     
00443         } else {
00444             jack_error("Connection is not synched, skip cycle...");
00445         }
00446 
00447         //receive sync
00448         res = SyncRecv();
00449         if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
00450             return res;
00451 
00452 #ifdef JACK_MONITOR
00453         fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
00454 #endif
00455 
00456         //decode sync
00457         DecodeSyncPacket();
00458   
00459         //receive data
00460         res = DataRecv();
00461         if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
00462             return res;
00463 
00464 #ifdef JACK_MONITOR
00465         fNetTimeMon->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
00466 #endif
00467         return 0;
00468     }
00469 
00470 //JackNetMasterManager***********************************************************************************************
00471 
00472     JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket()
00473     {
00474         jack_log ( "JackNetMasterManager::JackNetMasterManager" );
00475 
00476         fManagerClient = client;
00477         fManagerName = jack_get_client_name ( fManagerClient );
00478         strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
00479         fSocket.SetPort ( DEFAULT_PORT );
00480         fGlobalID = 0;
00481         fRunning = true;
00482         fAutoConnect = false;
00483 
00484         const JSList* node;
00485         const jack_driver_param_t* param;
00486         for ( node = params; node; node = jack_slist_next ( node ) )
00487         {
00488             param = ( const jack_driver_param_t* ) node->data;
00489             switch ( param->character )
00490             {
00491                 case 'a' :
00492                     if (strlen (param->value.str) < 32)
00493                         strcpy(fMulticastIP, param->value.str);
00494                     else
00495                         jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
00496                     break;
00497                     
00498                 case 'p':
00499                     fSocket.SetPort ( param->value.ui );
00500                     break;
00501                     
00502                 case 'c':
00503                     fAutoConnect = param->value.i;
00504                     break;
00505             }
00506         }
00507 
00508         //set sync callback
00509         jack_set_sync_callback ( fManagerClient, SetSyncCallback, this );
00510 
00511         //activate the client (for sync callback)
00512         if ( jack_activate ( fManagerClient ) != 0 )
00513             jack_error ( "Can't activate the network manager client, transport disabled." );
00514 
00515         //launch the manager thread
00516         if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) )
00517             jack_error ( "Can't create the network manager control thread." );
00518     }
00519 
00520     JackNetMasterManager::~JackNetMasterManager()
00521     {
00522         jack_log ( "JackNetMasterManager::~JackNetMasterManager" );
00523         jack_info ( "Exiting net manager..." );
00524         fRunning = false;
00525         jack_client_kill_thread ( fManagerClient, fManagerThread );
00526         master_list_t::iterator it;
00527         for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
00528             delete ( *it );
00529         fSocket.Close();
00530         SocketAPIEnd();
00531     }
00532 
00533     int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
00534     {
00535         return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
00536     }
00537 
00538     int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
00539     {
00540         //check if each slave is ready to roll
00541         int ret = 1;
00542         master_list_it_t it;
00543         for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
00544             if ( ! ( *it )->IsSlaveReadyToRoll() )
00545                 ret = 0;
00546         jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
00547         return ret;
00548     }
00549 
00550     void* JackNetMasterManager::NetManagerThread ( void* arg )
00551     {
00552         JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
00553         jack_info ( "Starting Jack Network Manager." );
00554         jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() );
00555         master_manager->Run();
00556         return NULL;
00557     }
00558 
00559     void JackNetMasterManager::Run()
00560     {
00561         jack_log ( "JackNetMasterManager::Run" );
00562         //utility variables
00563         int attempt = 0;
00564 
00565         //data
00566         session_params_t host_params;
00567         int rx_bytes = 0;
00568         JackNetMaster* net_master;
00569 
00570         //init socket API (win32)
00571         if ( SocketAPIInit() < 0 )
00572         {
00573             jack_error ( "Can't init Socket API, exiting..." );
00574             return;
00575         }
00576 
00577         //socket
00578         if ( fSocket.NewSocket() == SOCKET_ERROR )
00579         {
00580             jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) );
00581             return;
00582         }
00583 
00584         //bind the socket to the local port
00585         if ( fSocket.Bind() == SOCKET_ERROR )
00586         {
00587             jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) );
00588             fSocket.Close();
00589             return;
00590         }
00591 
00592         //join multicast group
00593         if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR )
00594             jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) );
00595 
00596         //local loop
00597         if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
00598             jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) );
00599 
00600         //set a timeout on the multicast receive (the thread can now be cancelled)
00601         if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
00602             jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
00603 
00604         jack_info ( "Waiting for a slave..." );
00605 
00606         //main loop, wait for data, deal with it and wait again
00607         do
00608         {
00609             session_params_t net_params;
00610             rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
00611             SessionParamsNToH(&net_params, &host_params);
00612             if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
00613             {
00614                 jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
00615                 if ( ++attempt == 10 )
00616                 {
00617                     jack_error ( "Can't receive on the socket, exiting net manager." );
00618                     return;
00619                 }
00620             }
00621             if ( rx_bytes == sizeof ( session_params_t ) )
00622             {
00623                 switch ( GetPacketType ( &host_params ) )
00624                 {
00625                     case SLAVE_AVAILABLE:
00626                         if ( ( net_master = InitMaster ( host_params ) ) )
00627                             SessionParamsDisplay ( &net_master->fParams );
00628                         else
00629                             jack_error ( "Can't init new net master..." );
00630                         jack_info ( "Waiting for a slave..." );
00631                         break;
00632                     case KILL_MASTER:
00633                         if ( KillMaster ( &host_params ) )
00634                             jack_info ( "Waiting for a slave..." );
00635                         break;
00636                     default:
00637                         break;
00638                 }
00639             }
00640         }
00641         while ( fRunning );
00642     }
00643 
00644     JackNetMaster* JackNetMasterManager::InitMaster ( session_params_t& params )
00645     {
00646         jack_log ( "JackNetMasterManager::InitMaster, Slave : %s", params.fName );
00647         
00648         //check MASTER <<==> SLAVE network protocol coherency
00649         if (params.fProtocolVersion != MASTER_PROTOCOL) {
00650             jack_error ( "Error : slave is running with a different protocol %s", params.fName );
00651             return NULL;
00652         }
00653 
00654         //settings
00655         fSocket.GetName ( params.fMasterNetName );
00656         params.fID = ++fGlobalID;
00657         params.fSampleRate = jack_get_sample_rate ( fManagerClient );
00658         params.fPeriodSize = jack_get_buffer_size ( fManagerClient );
00659         params.fBitdepth = 0;
00660         SetSlaveName ( params );
00661 
00662         //create a new master and add it to the list
00663         JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP);
00664         if ( master->Init(fAutoConnect) )
00665         {
00666             fMasterList.push_back ( master );
00667             return master;
00668         }
00669         delete master;
00670         return NULL;
00671     }
00672 
00673     void JackNetMasterManager::SetSlaveName ( session_params_t& params )
00674     {
00675         jack_log ( "JackNetMasterManager::SetSlaveName" );
00676 
00677         master_list_it_t it;
00678         for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
00679             if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 )
00680                 sprintf ( params.fName, "%s-%u", params.fName, params.fID );
00681     }
00682 
00683     master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id )
00684     {
00685         jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id );
00686 
00687         master_list_it_t it;
00688         for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
00689             if ( ( *it )->fParams.fID == id )
00690                 return it;
00691         return it;
00692     }
00693 
00694     int JackNetMasterManager::KillMaster ( session_params_t* params )
00695     {
00696         jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID );
00697 
00698         master_list_it_t master = FindMaster ( params->fID );
00699         if ( master != fMasterList.end() )
00700         {
00701             fMasterList.erase ( master );
00702             delete *master;
00703             return 1;
00704         }
00705         return 0;
00706     }
00707 }//namespace
00708 
00709 static Jack::JackNetMasterManager* master_manager = NULL;
00710 
00711 #ifdef __cplusplus
00712 extern "C"
00713 {
00714 #endif
00715 
00716     SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00717     {
00718         jack_driver_desc_t *desc;
00719         desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
00720 
00721         strcpy ( desc->name, "netmanager" );                        // size MUST be less then JACK_DRIVER_NAME_MAX + 1
00722         strcpy ( desc->desc, "netjack multi-cast master component" );  // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
00723 
00724         desc->nparams = 3;
00725         desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
00726 
00727         int i = 0;
00728         strcpy ( desc->params[i].name, "multicast_ip" );
00729         desc->params[i].character = 'a';
00730         desc->params[i].type = JackDriverParamString;
00731         strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
00732         strcpy ( desc->params[i].short_desc, "Multicast Address" );
00733         strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00734 
00735         i++;
00736         strcpy ( desc->params[i].name, "udp_net_port" );
00737         desc->params[i].character = 'p';
00738         desc->params[i].type = JackDriverParamInt;
00739         desc->params[i].value.i = DEFAULT_PORT;
00740         strcpy ( desc->params[i].short_desc, "UDP port" );
00741         strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00742         
00743         i++;
00744         strcpy ( desc->params[i].name, "auto_connect" );
00745         desc->params[i].character = 'c';
00746         desc->params[i].type = JackDriverParamBool;
00747         desc->params[i].value.i = false;
00748         strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" );
00749         strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
00750 
00751         return desc;
00752     }
00753 
00754     SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
00755     {
00756         if ( master_manager )
00757         {
00758             jack_error ( "Master Manager already loaded" );
00759             return 1;
00760         }
00761         else
00762         {
00763             jack_log ( "Loading Master Manager" );
00764             master_manager = new Jack::JackNetMasterManager ( jack_client, params );
00765             return ( master_manager ) ? 0 : 1;
00766         }
00767     }
00768 
00769     SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
00770     {
00771         JSList* params = NULL;
00772         bool parse_params = true;
00773         int res = 1;
00774         jack_driver_desc_t* desc = jack_get_descriptor();
00775 
00776         Jack::JackArgParser parser ( load_init );
00777         if ( parser.GetArgc() > 0 )
00778             parse_params = parser.ParseParams ( desc, &params );
00779 
00780         if (parse_params) {
00781             res = jack_internal_initialize ( jack_client, params );
00782             parser.FreeParams ( params );
00783         }
00784         return res;
00785     }
00786 
00787     SERVER_EXPORT void jack_finish ( void* arg )
00788     {
00789         if ( master_manager )
00790         {
00791             jack_log ( "Unloading Master Manager" );
00792             delete master_manager;
00793             master_manager = NULL;
00794         }
00795     }
00796 #ifdef __cplusplus
00797 }
00798 #endif