Fix XCode project.
[jack2.git] / common / JackNetManager.cpp
blobb42d970eeb3ea20d927074518c18c0819be2f889
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"
20 #include "JackArgParser.h"
21 #include "JackTime.h"
23 using namespace std;
25 namespace Jack
27 //JackNetMaster******************************************************************************************************
29 JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip)
30 : JackNetMasterInterface ( params, socket, multicast_ip )
32 jack_log ( "JackNetMaster::JackNetMaster" );
34 //settings
35 fClientName = const_cast<char*> ( fParams.fName );
36 fJackClient = NULL;
37 fSendTransportData.fState = -1;
38 fReturnTransportData.fState = -1;
39 fLastTransportState = -1;
40 uint port_index;
42 //jack audio ports
43 fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
44 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
45 fAudioCapturePorts[port_index] = NULL;
46 fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
47 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
48 fAudioPlaybackPorts[port_index] = NULL;
49 //jack midi ports
50 fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
51 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
52 fMidiCapturePorts[port_index] = NULL;
53 fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
54 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
55 fMidiPlaybackPorts[port_index] = NULL;
57 //monitor
58 #ifdef JACK_MONITOR
59 fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) );
60 string plot_name;
61 plot_name = string ( fParams.fName );
62 plot_name += string ( "_master" );
63 plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
64 switch ( fParams.fNetworkMode )
66 case 's' :
67 plot_name += string ( "_slow" );
68 break;
69 case 'n' :
70 plot_name += string ( "_normal" );
71 break;
72 case 'f' :
73 plot_name += string ( "_fast" );
74 break;
76 fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
77 string net_time_mon_fields[] =
79 string ( "sync send" ),
80 string ( "end of send" ),
81 string ( "sync recv" ),
82 string ( "end of cycle" )
84 string net_time_mon_options[] =
86 string ( "set xlabel \"audio cycles\"" ),
87 string ( "set ylabel \"% of audio cycle\"" )
89 fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
90 #endif
93 JackNetMaster::~JackNetMaster()
95 jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams.fID );
97 if ( fJackClient )
99 jack_deactivate ( fJackClient );
100 FreePorts();
101 jack_client_close ( fJackClient );
103 delete[] fAudioCapturePorts;
104 delete[] fAudioPlaybackPorts;
105 delete[] fMidiCapturePorts;
106 delete[] fMidiPlaybackPorts;
107 #ifdef JACK_MONITOR
108 fNetTimeMon->Save();
109 delete fNetTimeMon;
110 #endif
112 //init--------------------------------------------------------------------------------
113 bool JackNetMaster::Init(bool auto_connect)
115 //network init
116 if ( !JackNetMasterInterface::Init() )
117 return false;
119 //set global parameters
120 SetParams();
122 //jack client and process
123 jack_status_t status;
124 if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL )
126 jack_error ( "Can't open a new jack client." );
127 return false;
130 if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0)
131 goto fail;
133 if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0)
134 goto fail;
136 if ( AllocPorts() != 0 )
138 jack_error ( "Can't allocate jack ports." );
139 goto fail;
142 //process can now run
143 fRunning = true;
145 //finally activate jack client
146 if ( jack_activate ( fJackClient ) != 0 )
148 jack_error ( "Can't activate jack client." );
149 goto fail;
152 if (auto_connect)
153 ConnectPorts();
154 jack_info ( "New NetMaster started." );
155 return true;
157 fail:
158 FreePorts();
159 jack_client_close ( fJackClient );
160 fJackClient = NULL;
161 return false;
164 //jack ports--------------------------------------------------------------------------
165 int JackNetMaster::AllocPorts()
167 uint i;
168 char name[24];
169 jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient );
171 jack_log ( "JackNetMaster::AllocPorts" );
173 //audio
174 for ( i = 0; i < fParams.fSendAudioChannels; i++ )
176 sprintf ( name, "to_slave_%d", i+1 );
177 if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
178 return -1;
179 //port latency
180 jack_port_set_latency ( fAudioCapturePorts[i], 0 );
183 for ( i = 0; i < fParams.fReturnAudioChannels; i++ )
185 sprintf ( name, "from_slave_%d", i+1 );
186 if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
187 return -1;
188 //port latency
189 switch ( fParams.fNetworkMode )
191 case 'f' :
192 jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
193 break;
194 case 'n' :
195 jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
196 break;
197 case 's' :
198 jack_port_set_latency ( fAudioPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
199 break;
204 //midi
205 for ( i = 0; i < fParams.fSendMidiChannels; i++ )
207 sprintf ( name, "midi_to_slave_%d", i+1 );
208 if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
209 return -1;
210 //port latency
211 jack_port_set_latency ( fMidiCapturePorts[i], 0 );
213 for ( i = 0; i < fParams.fReturnMidiChannels; i++ )
215 sprintf ( name, "midi_from_slave_%d", i+1 );
216 if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
217 return -1;
218 //port latency
219 switch ( fParams.fNetworkMode )
221 case 'f' :
222 jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
223 break;
224 case 'n' :
225 jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
226 break;
227 case 's' :
228 jack_port_set_latency ( fMidiPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
229 break;
232 return 0;
235 void JackNetMaster::ConnectPorts()
237 const char **ports;
239 ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
240 if (ports != NULL) {
241 for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
242 jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i]));
244 free(ports);
247 ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
248 if (ports != NULL) {
249 for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
250 jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]);
252 free(ports);
256 void JackNetMaster::FreePorts()
258 jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID );
260 uint port_index;
261 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
262 if ( fAudioCapturePorts[port_index] )
263 jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] );
264 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
265 if ( fAudioPlaybackPorts[port_index] )
266 jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] );
267 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
268 if ( fMidiCapturePorts[port_index] )
269 jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] );
270 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
271 if ( fMidiPlaybackPorts[port_index] )
272 jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
275 //transport---------------------------------------------------------------------------
276 void JackNetMaster::EncodeTransportData()
278 //is there a new timebase master ?
279 //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
280 fSendTransportData.fTimebaseMaster = NO_CHANGE;
282 //update state and position
283 fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) );
285 //is it a new state ?
286 fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
287 ( fSendTransportData.fState != fReturnTransportData.fState ) );
288 if ( fSendTransportData.fNewState )
289 jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame );
290 fLastTransportState = fSendTransportData.fState;
293 void JackNetMaster::DecodeTransportData()
295 //is there timebase master change ?
296 if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE )
298 int timebase = 0;
299 switch ( fReturnTransportData.fTimebaseMaster )
301 case RELEASE_TIMEBASEMASTER :
302 timebase = jack_release_timebase ( fJackClient );
303 if ( timebase < 0 )
304 jack_error ( "Can't release timebase master." );
305 else
306 jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
307 break;
309 case TIMEBASEMASTER :
310 timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
311 if ( timebase < 0 )
312 jack_error ( "Can't set a new timebase master." );
313 else
314 jack_info ( "'%s' is the new timebase master.", fParams.fName );
315 break;
317 case CONDITIONAL_TIMEBASEMASTER :
318 timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
319 if ( timebase != EBUSY )
321 if ( timebase < 0 )
322 jack_error ( "Can't set a new timebase master." );
323 else
324 jack_info ( "'%s' is the new timebase master.", fParams.fName );
326 break;
330 //is the slave in a new transport state and is this state different from master's ?
331 if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
333 switch ( fReturnTransportData.fState )
335 case JackTransportStopped :
336 jack_transport_stop ( fJackClient );
337 jack_info ( "'%s' stops transport.", fParams.fName );
338 break;
340 case JackTransportStarting :
341 if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL )
342 jack_error ( "Can't set new position." );
343 jack_transport_start ( fJackClient );
344 jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
345 break;
347 case JackTransportNetStarting :
348 jack_info ( "'%s' is ready to roll..", fParams.fName );
349 break;
351 case JackTransportRolling :
352 jack_info ( "'%s' is rolling.", fParams.fName );
353 break;
358 void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
360 static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
363 void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
365 pos->bar = fReturnTransportData.fPosition.bar;
366 pos->beat = fReturnTransportData.fPosition.beat;
367 pos->tick = fReturnTransportData.fPosition.tick;
368 pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
369 pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
370 pos->beat_type = fReturnTransportData.fPosition.beat_type;
371 pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
372 pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
375 //sync--------------------------------------------------------------------------------
377 bool JackNetMaster::IsSlaveReadyToRoll()
379 return ( fReturnTransportData.fState == JackTransportNetStarting );
382 int JackNetMaster::SetBufferSize (jack_nframes_t nframes, void* arg)
384 jack_error("Cannot handle bufer size change, so proxy will be removed...");
385 static_cast<JackNetMaster*> ( arg )->Exit();
386 return 0;
389 //process-----------------------------------------------------------------------------
390 int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
392 return static_cast<JackNetMaster*> ( arg )->Process();
395 int JackNetMaster::Process()
397 if ( !fRunning )
398 return 0;
400 uint port_index;
401 int res = 0;
403 #ifdef JACK_MONITOR
404 jack_time_t begin_time = GetMicroSeconds();
405 fNetTimeMon->New();
406 #endif
408 //buffers
409 for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
410 fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
411 fParams.fPeriodSize ) ) );
412 for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
413 fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
414 fParams.fPeriodSize ) ) );
415 for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
416 fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
417 fParams.fPeriodSize ) ) );
418 for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
419 fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
420 fParams.fPeriodSize ) ) );
422 if (IsSynched()) { // only send if connection is "synched"
424 //encode the first packet
425 EncodeSyncPacket();
427 //send sync
428 if ( SyncSend() == SOCKET_ERROR )
429 return SOCKET_ERROR;
431 #ifdef JACK_MONITOR
432 fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
433 #endif
435 //send data
436 if ( DataSend() == SOCKET_ERROR )
437 return SOCKET_ERROR;
439 #ifdef JACK_MONITOR
440 fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
441 #endif
443 } else {
444 jack_error("Connection is not synched, skip cycle...");
447 //receive sync
448 res = SyncRecv();
449 if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
450 return res;
452 #ifdef JACK_MONITOR
453 fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
454 #endif
456 //decode sync
457 DecodeSyncPacket();
459 //receive data
460 res = DataRecv();
461 if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
462 return res;
464 #ifdef JACK_MONITOR
465 fNetTimeMon->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
466 #endif
467 return 0;
470 //JackNetMasterManager***********************************************************************************************
472 JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket()
474 jack_log ( "JackNetMasterManager::JackNetMasterManager" );
476 fManagerClient = client;
477 fManagerName = jack_get_client_name ( fManagerClient );
478 strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
479 fSocket.SetPort ( DEFAULT_PORT );
480 fGlobalID = 0;
481 fRunning = true;
482 fAutoConnect = false;
484 const JSList* node;
485 const jack_driver_param_t* param;
486 for ( node = params; node; node = jack_slist_next ( node ) )
488 param = ( const jack_driver_param_t* ) node->data;
489 switch ( param->character )
491 case 'a' :
492 if (strlen (param->value.str) < 32)
493 strcpy(fMulticastIP, param->value.str);
494 else
495 jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
496 break;
498 case 'p':
499 fSocket.SetPort ( param->value.ui );
500 break;
502 case 'c':
503 fAutoConnect = param->value.i;
504 break;
508 //set sync callback
509 jack_set_sync_callback ( fManagerClient, SetSyncCallback, this );
511 //activate the client (for sync callback)
512 if ( jack_activate ( fManagerClient ) != 0 )
513 jack_error ( "Can't activate the network manager client, transport disabled." );
515 //launch the manager thread
516 if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) )
517 jack_error ( "Can't create the network manager control thread." );
520 JackNetMasterManager::~JackNetMasterManager()
522 jack_log ( "JackNetMasterManager::~JackNetMasterManager" );
523 jack_info ( "Exiting net manager..." );
524 fRunning = false;
525 jack_client_kill_thread ( fManagerClient, fManagerThread );
526 master_list_t::iterator it;
527 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
528 delete ( *it );
529 fSocket.Close();
530 SocketAPIEnd();
533 int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
535 return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
538 int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
540 //check if each slave is ready to roll
541 int ret = 1;
542 master_list_it_t it;
543 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
544 if ( ! ( *it )->IsSlaveReadyToRoll() )
545 ret = 0;
546 jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
547 return ret;
550 void* JackNetMasterManager::NetManagerThread ( void* arg )
552 JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
553 jack_info ( "Starting Jack Network Manager." );
554 jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() );
555 master_manager->Run();
556 return NULL;
559 void JackNetMasterManager::Run()
561 jack_log ( "JackNetMasterManager::Run" );
562 //utility variables
563 int attempt = 0;
565 //data
566 session_params_t host_params;
567 int rx_bytes = 0;
568 JackNetMaster* net_master;
570 //init socket API (win32)
571 if ( SocketAPIInit() < 0 )
573 jack_error ( "Can't init Socket API, exiting..." );
574 return;
577 //socket
578 if ( fSocket.NewSocket() == SOCKET_ERROR )
580 jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) );
581 return;
584 //bind the socket to the local port
585 if ( fSocket.Bind() == SOCKET_ERROR )
587 jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) );
588 fSocket.Close();
589 return;
592 //join multicast group
593 if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR )
594 jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) );
596 //local loop
597 if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
598 jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) );
600 //set a timeout on the multicast receive (the thread can now be cancelled)
601 if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
602 jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
604 jack_info ( "Waiting for a slave..." );
606 //main loop, wait for data, deal with it and wait again
609 session_params_t net_params;
610 rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
611 SessionParamsNToH(&net_params, &host_params);
612 if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
614 jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
615 if ( ++attempt == 10 )
617 jack_error ( "Can't receive on the socket, exiting net manager." );
618 return;
621 if ( rx_bytes == sizeof ( session_params_t ) )
623 switch ( GetPacketType ( &host_params ) )
625 case SLAVE_AVAILABLE:
626 if ( ( net_master = InitMaster ( host_params ) ) )
627 SessionParamsDisplay ( &net_master->fParams );
628 else
629 jack_error ( "Can't init new net master..." );
630 jack_info ( "Waiting for a slave..." );
631 break;
632 case KILL_MASTER:
633 if ( KillMaster ( &host_params ) )
634 jack_info ( "Waiting for a slave..." );
635 break;
636 default:
637 break;
641 while ( fRunning );
644 JackNetMaster* JackNetMasterManager::InitMaster ( session_params_t& params )
646 jack_log ( "JackNetMasterManager::InitMaster, Slave : %s", params.fName );
648 //check MASTER <<==> SLAVE network protocol coherency
649 if (params.fProtocolVersion != MASTER_PROTOCOL) {
650 jack_error ( "Error : slave is running with a different protocol %s", params.fName );
651 return NULL;
654 //settings
655 fSocket.GetName ( params.fMasterNetName );
656 params.fID = ++fGlobalID;
657 params.fSampleRate = jack_get_sample_rate ( fManagerClient );
658 params.fPeriodSize = jack_get_buffer_size ( fManagerClient );
659 params.fBitdepth = 0;
660 SetSlaveName ( params );
662 //create a new master and add it to the list
663 JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP);
664 if ( master->Init(fAutoConnect) )
666 fMasterList.push_back ( master );
667 return master;
669 delete master;
670 return NULL;
673 void JackNetMasterManager::SetSlaveName ( session_params_t& params )
675 jack_log ( "JackNetMasterManager::SetSlaveName" );
677 master_list_it_t it;
678 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
679 if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 )
680 sprintf ( params.fName, "%s-%u", params.fName, params.fID );
683 master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id )
685 jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id );
687 master_list_it_t it;
688 for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
689 if ( ( *it )->fParams.fID == id )
690 return it;
691 return it;
694 int JackNetMasterManager::KillMaster ( session_params_t* params )
696 jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID );
698 master_list_it_t master = FindMaster ( params->fID );
699 if ( master != fMasterList.end() )
701 fMasterList.erase ( master );
702 delete *master;
703 return 1;
705 return 0;
707 }//namespace
709 static Jack::JackNetMasterManager* master_manager = NULL;
711 #ifdef __cplusplus
712 extern "C"
714 #endif
716 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
718 jack_driver_desc_t *desc;
719 desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
721 strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
722 strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
724 desc->nparams = 3;
725 desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
727 int i = 0;
728 strcpy ( desc->params[i].name, "multicast_ip" );
729 desc->params[i].character = 'a';
730 desc->params[i].type = JackDriverParamString;
731 strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
732 strcpy ( desc->params[i].short_desc, "Multicast Address" );
733 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
735 i++;
736 strcpy ( desc->params[i].name, "udp_net_port" );
737 desc->params[i].character = 'p';
738 desc->params[i].type = JackDriverParamInt;
739 desc->params[i].value.i = DEFAULT_PORT;
740 strcpy ( desc->params[i].short_desc, "UDP port" );
741 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
743 i++;
744 strcpy ( desc->params[i].name, "auto_connect" );
745 desc->params[i].character = 'c';
746 desc->params[i].type = JackDriverParamBool;
747 desc->params[i].value.i = false;
748 strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" );
749 strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
751 return desc;
754 SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
756 if ( master_manager )
758 jack_error ( "Master Manager already loaded" );
759 return 1;
761 else
763 jack_log ( "Loading Master Manager" );
764 master_manager = new Jack::JackNetMasterManager ( jack_client, params );
765 return ( master_manager ) ? 0 : 1;
769 SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
771 JSList* params = NULL;
772 bool parse_params = true;
773 int res = 1;
774 jack_driver_desc_t* desc = jack_get_descriptor();
776 Jack::JackArgParser parser ( load_init );
777 if ( parser.GetArgc() > 0 )
778 parse_params = parser.ParseParams ( desc, &params );
780 if (parse_params) {
781 res = jack_internal_initialize ( jack_client, params );
782 parser.FreeParams ( params );
784 return res;
787 SERVER_EXPORT void jack_finish ( void* arg )
789 if ( master_manager )
791 jack_log ( "Unloading Master Manager" );
792 delete master_manager;
793 master_manager = NULL;
796 #ifdef __cplusplus
798 #endif