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"
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" );
35 fClientName
= const_cast<char*> ( fParams
.fName
);
37 fSendTransportData
.fState
= -1;
38 fReturnTransportData
.fState
= -1;
39 fLastTransportState
= -1;
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
;
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
;
59 fPeriodUsecs
= ( int ) ( 1000000.f
* ( ( float ) fParams
.fPeriodSize
/ ( float ) fParams
.fSampleRate
) );
61 plot_name
= string ( fParams
.fName
);
62 plot_name
+= string ( "_master" );
63 plot_name
+= string ( ( fParams
.fSlaveSyncMode
) ? "_sync" : "_async" );
64 switch ( fParams
.fNetworkMode
)
67 plot_name
+= string ( "_slow" );
70 plot_name
+= string ( "_normal" );
73 plot_name
+= string ( "_fast" );
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 );
93 JackNetMaster::~JackNetMaster()
95 jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams
.fID
);
99 jack_deactivate ( fJackClient
);
101 jack_client_close ( fJackClient
);
103 delete[] fAudioCapturePorts
;
104 delete[] fAudioPlaybackPorts
;
105 delete[] fMidiCapturePorts
;
106 delete[] fMidiPlaybackPorts
;
112 //init--------------------------------------------------------------------------------
113 bool JackNetMaster::Init(bool auto_connect
)
116 if ( !JackNetMasterInterface::Init() )
119 //set global parameters
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." );
130 if (jack_set_process_callback(fJackClient
, SetProcess
, this ) < 0)
133 if (jack_set_buffer_size_callback(fJackClient
, SetBufferSize
, this) < 0)
136 if ( AllocPorts() != 0 )
138 jack_error ( "Can't allocate jack ports." );
142 //process can now run
145 //finally activate jack client
146 if ( jack_activate ( fJackClient
) != 0 )
148 jack_error ( "Can't activate jack client." );
154 jack_info ( "New NetMaster started." );
159 jack_client_close ( fJackClient
);
164 //jack ports--------------------------------------------------------------------------
165 int JackNetMaster::AllocPorts()
169 jack_nframes_t port_latency
= jack_get_buffer_size ( fJackClient
);
171 jack_log ( "JackNetMaster::AllocPorts" );
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
)
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
)
189 switch ( fParams
.fNetworkMode
)
192 jack_port_set_latency ( fAudioPlaybackPorts
[i
], ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
195 jack_port_set_latency ( fAudioPlaybackPorts
[i
], port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
198 jack_port_set_latency ( fAudioPlaybackPorts
[i
], 2 * port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
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
)
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
)
219 switch ( fParams
.fNetworkMode
)
222 jack_port_set_latency ( fMidiPlaybackPorts
[i
], ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
225 jack_port_set_latency ( fMidiPlaybackPorts
[i
], port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
228 jack_port_set_latency ( fMidiPlaybackPorts
[i
], 2 * port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
235 void JackNetMaster::ConnectPorts()
239 ports
= jack_get_ports(fJackClient
, NULL
, NULL
, JackPortIsPhysical
| JackPortIsOutput
);
241 for (unsigned int i
= 0; i
< fParams
.fSendAudioChannels
&& ports
[i
]; i
++) {
242 jack_connect(fJackClient
, ports
[i
], jack_port_name(fAudioCapturePorts
[i
]));
247 ports
= jack_get_ports(fJackClient
, NULL
, NULL
, JackPortIsPhysical
| JackPortIsInput
);
249 for (unsigned int i
= 0; i
< fParams
.fReturnAudioChannels
&& ports
[i
]; i
++) {
250 jack_connect(fJackClient
, jack_port_name(fAudioPlaybackPorts
[i
]), ports
[i
]);
256 void JackNetMaster::FreePorts()
258 jack_log ( "JackNetMaster::FreePorts, ID %u", fParams
.fID
);
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
)
299 switch ( fReturnTransportData
.fTimebaseMaster
)
301 case RELEASE_TIMEBASEMASTER
:
302 timebase
= jack_release_timebase ( fJackClient
);
304 jack_error ( "Can't release timebase master." );
306 jack_info ( "'%s' isn't the timebase master anymore.", fParams
.fName
);
309 case TIMEBASEMASTER
:
310 timebase
= jack_set_timebase_callback ( fJackClient
, 0, SetTimebaseCallback
, this );
312 jack_error ( "Can't set a new timebase master." );
314 jack_info ( "'%s' is the new timebase master.", fParams
.fName
);
317 case CONDITIONAL_TIMEBASEMASTER
:
318 timebase
= jack_set_timebase_callback ( fJackClient
, 1, SetTimebaseCallback
, this );
319 if ( timebase
!= EBUSY
)
322 jack_error ( "Can't set a new timebase master." );
324 jack_info ( "'%s' is the new timebase master.", fParams
.fName
);
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
);
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
);
347 case JackTransportNetStarting
:
348 jack_info ( "'%s' is ready to roll..", fParams
.fName
);
351 case JackTransportRolling
:
352 jack_info ( "'%s' is rolling.", fParams
.fName
);
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();
389 //process-----------------------------------------------------------------------------
390 int JackNetMaster::SetProcess ( jack_nframes_t nframes
, void* arg
)
392 return static_cast<JackNetMaster
*> ( arg
)->Process();
395 int JackNetMaster::Process()
404 jack_time_t begin_time
= GetMicroSeconds();
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
428 if ( SyncSend() == SOCKET_ERROR
)
432 fNetTimeMon
->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
436 if ( DataSend() == SOCKET_ERROR
)
440 fNetTimeMon
->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
444 jack_error("Connection is not synched, skip cycle...");
449 if ( ( res
== 0 ) || ( res
== SOCKET_ERROR
) )
453 fNetTimeMon
->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
461 if ( ( res
== 0 ) || ( res
== SOCKET_ERROR
) )
465 fNetTimeMon
->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
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
);
482 fAutoConnect
= false;
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
)
492 if (strlen (param
->value
.str
) < 32)
493 strcpy(fMulticastIP
, param
->value
.str
);
495 jack_error("Can't use multicast address %s, using default %s", param
->value
.ui
, DEFAULT_MULTICAST_IP
);
499 fSocket
.SetPort ( param
->value
.ui
);
503 fAutoConnect
= param
->value
.i
;
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..." );
525 jack_client_kill_thread ( fManagerClient
, fManagerThread
);
526 master_list_t::iterator it
;
527 for ( it
= fMasterList
.begin(); it
!= fMasterList
.end(); it
++ )
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
543 for ( it
= fMasterList
.begin(); it
!= fMasterList
.end(); it
++ )
544 if ( ! ( *it
)->IsSlaveReadyToRoll() )
546 jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret
) ? "true" : "false" );
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();
559 void JackNetMasterManager::Run()
561 jack_log ( "JackNetMasterManager::Run" );
566 session_params_t host_params
;
568 JackNetMaster
* net_master
;
570 //init socket API (win32)
571 if ( SocketAPIInit() < 0 )
573 jack_error ( "Can't init Socket API, exiting..." );
578 if ( fSocket
.NewSocket() == SOCKET_ERROR
)
580 jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE
) );
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
) );
592 //join multicast group
593 if ( fSocket
.JoinMCastGroup ( fMulticastIP
) == SOCKET_ERROR
)
594 jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE
) );
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." );
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
);
629 jack_error ( "Can't init new net master..." );
630 jack_info ( "Waiting for a slave..." );
633 if ( KillMaster ( &host_params
) )
634 jack_info ( "Waiting for a slave..." );
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
);
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
);
673 void JackNetMasterManager::SetSlaveName ( session_params_t
& params
)
675 jack_log ( "JackNetMasterManager::SetSlaveName" );
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
);
688 for ( it
= fMasterList
.begin(); it
!= fMasterList
.end(); it
++ )
689 if ( ( *it
)->fParams
.fID
== id
)
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
);
709 static Jack::JackNetMasterManager
* master_manager
= NULL
;
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
725 desc
->params
= ( jack_driver_param_desc_t
* ) calloc ( desc
->nparams
, sizeof ( jack_driver_param_desc_t
) );
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
);
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
);
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
);
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" );
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;
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
, ¶ms
);
781 res
= jack_internal_initialize ( jack_client
, params
);
782 parser
.FreeParams ( params
);
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
;