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