Support for BIG_ENDIAN machines in NetJack2.
[jack2.git] / common / JackNetManager.cpp
blob23104eac5a8b35fe60191de043bda3f29ba20864
1 /*
2 Copyright (C) 2008 Romain Moret at Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "JackNetManager.h"
21 using namespace std;
23 namespace Jack
25 //JackNetMaster******************************************************************************************************
27 JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip )
28 : JackNetMasterInterface ( params, socket, multicast_ip )
30 jack_log ( "JackNetMaster::JackNetMaster" );
32 //settings
33 fClientName = const_cast<char*> ( fParams.fName );
34 fJackClient = NULL;
35 uint port_index;
37 //jack audio ports
38 fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
39 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
40 fAudioCapturePorts[port_index] = NULL;
41 fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
42 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
43 fAudioPlaybackPorts[port_index] = NULL;
44 //jack midi ports
45 fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
46 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
47 fMidiCapturePorts[port_index] = NULL;
48 fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
49 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
50 fMidiPlaybackPorts[port_index] = NULL;
52 //monitor
53 #ifdef JACK_MONITOR
54 fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) );
55 string plot_name;
56 plot_name = string ( fParams.fName );
57 plot_name += string ( "_master" );
58 plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
59 switch ( fParams.fNetworkMode )
61 case 's' :
62 plot_name += string ( "_slow" );
63 break;
64 case 'n' :
65 plot_name += string ( "_normal" );
66 break;
67 case 'f' :
68 plot_name += string ( "_fast" );
69 break;
71 fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
72 string net_time_mon_fields[] =
74 string ( "sync send" ),
75 string ( "end of send" ),
76 string ( "sync recv" ),
77 string ( "end of cycle" )
79 string net_time_mon_options[] =
81 string ( "set xlabel \"audio cycles\"" ),
82 string ( "set ylabel \"% of audio cycle\"" )
84 fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
85 #endif
88 JackNetMaster::~JackNetMaster()
90 jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams.fID );
92 if ( fJackClient )
94 jack_deactivate ( fJackClient );
95 FreePorts();
96 jack_client_close ( fJackClient );
98 delete[] fAudioCapturePorts;
99 delete[] fAudioPlaybackPorts;
100 delete[] fMidiCapturePorts;
101 delete[] fMidiPlaybackPorts;
102 #ifdef JACK_MONITOR
103 fNetTimeMon->Save();
104 delete fNetTimeMon;
105 #endif
107 //init--------------------------------------------------------------------------------
108 bool JackNetMaster::Init()
110 //network init
111 if ( !JackNetMasterInterface::Init() )
112 return false;
114 //set global parameters
115 SetParams();
117 //jack client and process
118 jack_status_t status;
119 if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL )
121 jack_error ( "Can't open a new jack client." );
122 return false;
125 jack_set_process_callback ( fJackClient, SetProcess, this );
127 if ( AllocPorts() != 0 )
129 jack_error ( "Can't allocate jack ports." );
130 goto fail;
133 //process can now run
134 fRunning = true;
136 //finally activate jack client
137 if ( jack_activate ( fJackClient ) != 0 )
139 jack_error ( "Can't activate jack client." );
140 goto fail;
143 jack_info ( "New NetMaster started." );
145 return true;
147 fail:
148 FreePorts();
149 jack_client_close ( fJackClient );
150 fJackClient = NULL;
151 return false;
154 //jack ports--------------------------------------------------------------------------
155 int JackNetMaster::AllocPorts()
157 jack_log ( "JackNetMaster::AllocPorts" );
159 uint i;
160 char name[24];
161 jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient );
162 unsigned long port_flags;
163 //audio
164 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
165 for ( i = 0; i < fParams.fSendAudioChannels; i++ )
167 sprintf ( name, "to_slave_%d", i+1 );
168 if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL )
169 return -1;
170 //port latency
171 jack_port_set_latency ( fAudioCapturePorts[i], 0 );
173 port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
174 for ( i = 0; i < fParams.fReturnAudioChannels; i++ )
176 sprintf ( name, "from_slave_%d", i+1 );
177 if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL )
178 return -1;
179 //port latency
180 switch ( fParams.fNetworkMode )
182 case 'f' :
183 jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
184 break;
185 case 'n' :
186 jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
187 break;
188 case 's' :
189 jack_port_set_latency ( fAudioPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
190 break;
193 //midi
194 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
195 for ( i = 0; i < fParams.fSendMidiChannels; i++ )
197 sprintf ( name, "midi_to_slave_%d", i+1 );
198 if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL )
199 return -1;
200 //port latency
201 jack_port_set_latency ( fMidiCapturePorts[i], 0 );
203 port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
204 for ( i = 0; i < fParams.fReturnMidiChannels; i++ )
206 sprintf ( name, "midi_from_slave_%d", i+1 );
207 if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL )
208 return -1;
209 //port latency
210 switch ( fParams.fNetworkMode )
212 case 'f' :
213 jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
214 break;
215 case 'n' :
216 jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
217 break;
218 case 's' :
219 jack_port_set_latency ( fMidiPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
220 break;
223 return 0;
226 void JackNetMaster::FreePorts()
228 jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID );
230 uint port_index;
231 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
232 if ( fAudioCapturePorts[port_index] )
233 jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] );
234 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
235 if ( fAudioPlaybackPorts[port_index] )
236 jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] );
237 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
238 if ( fMidiCapturePorts[port_index] )
239 jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] );
240 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
241 if ( fMidiPlaybackPorts[port_index] )
242 jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
245 //transport---------------------------------------------------------------------------
246 int JackNetMaster::EncodeTransportData()
248 //is there a new timebase master ?
249 //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
250 fSendTransportData.fTimebaseMaster = NO_CHANGE;
252 //update state and position
253 fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) );
255 //is it a new state ?
256 fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
257 ( fSendTransportData.fState != fReturnTransportData.fState ) );
258 if ( fSendTransportData.fNewState )
259 jack_info ( "Sending '%s' to '%s'.", GetTransportState ( fSendTransportData.fState ), fParams.fName );
260 fLastTransportState = fSendTransportData.fState;
262 return 0;
265 int JackNetMaster::DecodeTransportData()
267 //is there timebase master change ?
268 if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE )
270 int timebase = 0;
271 switch ( fReturnTransportData.fTimebaseMaster )
273 case RELEASE_TIMEBASEMASTER :
274 timebase = jack_release_timebase ( fJackClient );
275 if ( timebase < 0 )
276 jack_error ( "Can't release timebase master." );
277 else
278 jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
279 break;
280 case TIMEBASEMASTER :
281 timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
282 if ( timebase < 0 )
283 jack_error ( "Can't set a new timebase master." );
284 else
285 jack_info ( "'%s' is the new timebase master.", fParams.fName );
286 break;
287 case CONDITIONAL_TIMEBASEMASTER :
288 timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
289 if ( timebase != EBUSY )
291 if ( timebase < 0 )
292 jack_error ( "Can't set a new timebase master." );
293 else
294 jack_info ( "'%s' is the new timebase master.", fParams.fName );
296 break;
300 //is the slave in a new transport state and is this state different from master's ?
301 if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
303 switch ( fReturnTransportData.fState )
305 case JackTransportStopped :
306 jack_transport_stop ( fJackClient );
307 jack_info ( "'%s' stops transport.", fParams.fName );
308 break;
309 case JackTransportStarting :
310 if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) < 0 )
311 jack_error ( "Can't set new position." );
312 jack_transport_start ( fJackClient );
313 jack_info ( "'%s' starts transport.", fParams.fName );
314 break;
315 case JackTransportNetStarting :
316 jack_info ( "'%s' is ready to roll..", fParams.fName );
317 break;
318 case JackTransportRolling :
319 jack_info ( "'%s' is rolling.", fParams.fName );
320 break;
323 return 0;
326 void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
328 static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
331 void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
333 pos->bar = fReturnTransportData.fPosition.bar;
334 pos->beat = fReturnTransportData.fPosition.beat;
335 pos->tick = fReturnTransportData.fPosition.tick;
336 pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
337 pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
338 pos->beat_type = fReturnTransportData.fPosition.beat_type;
339 pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
340 pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
343 //sync--------------------------------------------------------------------------------
344 int JackNetMaster::EncodeSyncPacket()
346 //this method contains every step of sync packet informations coding
347 //first of all, reset sync packet
348 memset ( fTxData, 0, fPayloadSize );
350 //then, first step : transport
351 if ( fParams.fTransportSync )
353 if ( EncodeTransportData() < 0 )
354 return -1;
355 //copy to TxBuffer
356 memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
358 //then others (freewheel etc.)
359 //...
360 return 0;
363 int JackNetMaster::DecodeSyncPacket()
365 //this method contains every step of sync packet informations decoding process
366 //first : transport
367 if ( fParams.fTransportSync )
369 //copy received transport data to transport data structure
370 memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
371 if ( DecodeTransportData() < 0 )
372 return -1;
374 //then others
375 //...
376 return 0;
379 bool JackNetMaster::IsSlaveReadyToRoll()
381 return ( fReturnTransportData.fState == JackTransportNetStarting );
384 //process-----------------------------------------------------------------------------
385 int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
387 return static_cast<JackNetMaster*> ( arg )->Process();
390 int JackNetMaster::Process()
392 if ( !fRunning )
393 return 0;
395 uint port_index;
396 int res = 0;
398 #ifdef JACK_MONITOR
399 jack_time_t begin_time = jack_get_time();
400 fNetTimeMon->New();
401 #endif
403 //buffers
404 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
405 fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
406 fParams.fPeriodSize ) ) );
407 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
408 fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
409 fParams.fPeriodSize ) ) );
410 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
411 fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
412 fParams.fPeriodSize ) ) );
413 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
414 fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
415 fParams.fPeriodSize ) ) );
417 if (IsSynched()) { // only send if connection is "synched"
419 //encode the first packet
420 if ( EncodeSyncPacket() < 0 )
421 return 0;
423 //send sync
424 if ( SyncSend() == SOCKET_ERROR )
425 return SOCKET_ERROR;
427 #ifdef JACK_MONITOR
428 fNetTimeMon->Add ( ( ( ( float ) ( jack_get_time() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
429 #endif
431 //send data
432 if ( DataSend() == SOCKET_ERROR )
433 return SOCKET_ERROR;
435 #ifdef JACK_MONITOR
436 fNetTimeMon->Add ( ( ( ( float ) ( jack_get_time() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
437 #endif
439 } else {
440 jack_error("Connection is not synched, skip cycle...");
443 //receive sync
444 res = SyncRecv();
445 if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
446 return res;
448 #ifdef JACK_MONITOR
449 fNetTimeMon->Add ( ( ( ( float ) ( jack_get_time() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
450 #endif
452 //decode sync
453 if ( DecodeSyncPacket() < 0 )
454 return 0;
456 //receive data
457 res = DataRecv();
458 if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
459 return res;
461 #ifdef JACK_MONITOR
462 fNetTimeMon->AddLast ( ( ( ( float ) ( jack_get_time() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
463 #endif
464 return 0;
467 //JackNetMasterManager***********************************************************************************************
469 JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket()
471 jack_log ( "JackNetMasterManager::JackNetMasterManager" );
473 fManagerClient = client;
474 fManagerName = jack_get_client_name ( fManagerClient );
475 fMulticastIP = DEFAULT_MULTICAST_IP;
476 fSocket.SetPort ( DEFAULT_PORT );
477 fGlobalID = 0;
478 fRunning = true;
480 const JSList* node;
481 const jack_driver_param_t* param;
482 for ( node = params; node; node = jack_slist_next ( node ) )
484 param = ( const jack_driver_param_t* ) node->data;
485 switch ( param->character )
487 case 'a' :
488 fMulticastIP = strdup ( param->value.str );
489 break;
490 case 'p':
491 fSocket.SetPort ( param->value.ui );
495 //set sync callback
496 jack_set_sync_callback ( fManagerClient, SetSyncCallback, this );
498 //activate the client (for sync callback)
499 if ( jack_activate ( fManagerClient ) != 0 )
500 jack_error ( "Can't activate the network manager client, transport disabled." );
502 //launch the manager thread
503 if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) )
504 jack_error ( "Can't create the network manager control thread." );
507 JackNetMasterManager::~JackNetMasterManager()
509 jack_log ( "JackNetMasterManager::~JackNetMasterManager" );
511 jack_info ( "Exiting net manager..." );
512 fRunning = false;
513 jack_client_stop_thread ( fManagerClient, fManagerThread );
514 master_list_t::iterator it;
515 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
516 delete ( *it );
517 fSocket.Close();
518 SocketAPIEnd();
521 int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
523 return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
526 int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
528 //check if each slave is ready to roll
529 int ret = 1;
530 master_list_it_t it;
531 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
532 if ( ! ( *it )->IsSlaveReadyToRoll() )
533 ret = 0;
534 jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
535 return ret;
538 void* JackNetMasterManager::NetManagerThread ( void* arg )
540 JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
541 jack_info ( "Starting Jack Network Manager." );
542 jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() );
543 master_manager->Run();
544 return NULL;
547 void JackNetMasterManager::Run()
549 jack_log ( "JackNetMasterManager::Run" );
550 //utility variables
551 int attempt = 0;
553 //data
554 session_params_t host_params;
555 int rx_bytes = 0;
556 JackNetMaster* net_master;
558 //init socket API (win32)
559 if ( SocketAPIInit() < 0 )
561 jack_error ( "Can't init Socket API, exiting..." );
562 return;
565 //socket
566 if ( fSocket.NewSocket() == SOCKET_ERROR )
568 jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) );
569 return;
572 //bind the socket to the local port
573 if ( fSocket.Bind() == SOCKET_ERROR )
575 jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) );
576 fSocket.Close();
577 return;
580 //join multicast group
581 if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR )
582 jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) );
584 //local loop
585 if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
586 jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) );
588 //set a timeout on the multicast receive (the thread can now be cancelled)
589 if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
590 jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
592 jack_info ( "Waiting for a slave..." );
594 //main loop, wait for data, deal with it and wait again
597 session_params_t net_params;
598 rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
599 SessionParamsNToH(&net_params, &host_params);
600 if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
602 jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
603 if ( ++attempt == 10 )
605 jack_error ( "Can't receive on the socket, exiting net manager." );
606 return;
609 if ( rx_bytes == sizeof ( session_params_t ) )
611 switch ( GetPacketType ( &host_params ) )
613 case SLAVE_AVAILABLE:
614 if ( ( net_master = MasterInit ( host_params ) ) )
615 SessionParamsDisplay ( &net_master->fParams );
616 else
617 jack_error ( "Can't init new net master..." );
618 jack_info ( "Waiting for a slave..." );
619 break;
620 case KILL_MASTER:
621 if ( KillMaster ( &host_params ) )
622 jack_info ( "Waiting for a slave..." );
623 break;
624 default:
625 break;
629 while ( fRunning );
632 JackNetMaster* JackNetMasterManager::MasterInit ( session_params_t& params )
634 jack_log ( "JackNetMasterManager::MasterInit, Slave : %s", params.fName );
636 //settings
637 fSocket.GetName ( params.fMasterNetName );
638 params.fID = ++fGlobalID;
639 params.fSampleRate = jack_get_sample_rate ( fManagerClient );
640 params.fPeriodSize = jack_get_buffer_size ( fManagerClient );
641 params.fBitdepth = 0;
642 SetSlaveName ( params );
644 //create a new master and add it to the list
645 JackNetMaster* master = new JackNetMaster ( fSocket, params, fMulticastIP );
646 if ( master->Init() )
648 fMasterList.push_back ( master );
649 return master;
651 delete master;
652 return NULL;
655 void JackNetMasterManager::SetSlaveName ( session_params_t& params )
657 jack_log ( "JackNetMasterManager::SetSlaveName" );
659 master_list_it_t it;
660 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
661 if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 )
662 sprintf ( params.fName, "%s-%u", params.fName, params.fID );
665 master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id )
667 jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id );
669 master_list_it_t it;
670 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
671 if ( ( *it )->fParams.fID == id )
672 return it;
673 return it;
676 int JackNetMasterManager::KillMaster ( session_params_t* params )
678 jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID );
680 master_list_it_t master = FindMaster ( params->fID );
681 if ( master != fMasterList.end() )
683 fMasterList.erase ( master );
684 delete *master;
685 return 1;
687 return 0;
689 }//namespace
691 static Jack::JackNetMasterManager* master_manager = NULL;
693 #ifdef __cplusplus
694 extern "C"
696 #endif
698 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
700 jack_driver_desc_t *desc;
701 desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
703 strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
704 strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
706 desc->nparams = 2;
707 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
709 int i = 0;
710 strcpy ( desc->params[i].name, "multicast_ip" );
711 desc->params[i].character = 'a';
712 desc->params[i].type = JackDriverParamString;
713 strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
714 strcpy ( desc->params[i].short_desc, "Multicast Address" );
715 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
717 i++;
718 strcpy ( desc->params[i].name, "udp_net_port" );
719 desc->params[i].character = 'p';
720 desc->params[i].type = JackDriverParamInt;
721 desc->params[i].value.i = DEFAULT_PORT;
722 strcpy ( desc->params[i].short_desc, "UDP port" );
723 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
725 return desc;
728 SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
730 if ( master_manager )
732 jack_error ( "Master Manager already loaded" );
733 return 1;
735 else
737 jack_log ( "Loading Master Manager" );
738 master_manager = new Jack::JackNetMasterManager ( jack_client, params );
739 return ( master_manager ) ? 0 : 1;
743 SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
745 JSList* params = NULL;
746 jack_driver_desc_t* desc = jack_get_descriptor();
748 Jack::JackArgParser parser ( load_init );
749 if ( parser.GetArgc() > 0 )
750 parser.ParseParams ( desc, &params );
752 int res = jack_internal_initialize ( jack_client, params );
753 parser.FreeParams ( params );
754 return res;
757 SERVER_EXPORT void jack_finish ( void* arg )
759 if ( master_manager )
761 jack_log ( "Unloading Master Manager" );
762 delete master_manager;
763 master_manager = NULL;
766 #ifdef __cplusplus
768 #endif