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"
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" );
33 fClientName
= const_cast<char*> ( fParams
.fName
);
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
;
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
;
54 fPeriodUsecs
= ( int ) ( 1000000.f
* ( ( float ) fParams
.fPeriodSize
/ ( float ) fParams
.fSampleRate
) );
56 plot_name
= string ( fParams
.fName
);
57 plot_name
+= string ( "_master" );
58 plot_name
+= string ( ( fParams
.fSlaveSyncMode
) ? "_sync" : "_async" );
59 switch ( fParams
.fNetworkMode
)
62 plot_name
+= string ( "_slow" );
65 plot_name
+= string ( "_normal" );
68 plot_name
+= string ( "_fast" );
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 );
88 JackNetMaster::~JackNetMaster()
90 jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams
.fID
);
94 jack_deactivate ( fJackClient
);
96 jack_client_close ( fJackClient
);
98 delete[] fAudioCapturePorts
;
99 delete[] fAudioPlaybackPorts
;
100 delete[] fMidiCapturePorts
;
101 delete[] fMidiPlaybackPorts
;
107 //init--------------------------------------------------------------------------------
108 bool JackNetMaster::Init()
111 if ( !JackNetMasterInterface::Init() )
114 //set global parameters
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." );
125 jack_set_process_callback ( fJackClient
, SetProcess
, this );
127 if ( AllocPorts() != 0 )
129 jack_error ( "Can't allocate jack ports." );
133 //process can now run
136 //finally activate jack client
137 if ( jack_activate ( fJackClient
) != 0 )
139 jack_error ( "Can't activate jack client." );
143 jack_info ( "New NetMaster started." );
149 jack_client_close ( fJackClient
);
154 //jack ports--------------------------------------------------------------------------
155 int JackNetMaster::AllocPorts()
157 jack_log ( "JackNetMaster::AllocPorts" );
161 jack_nframes_t port_latency
= jack_get_buffer_size ( fJackClient
);
162 unsigned long port_flags
;
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
)
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
)
180 switch ( fParams
.fNetworkMode
)
183 jack_port_set_latency ( fAudioPlaybackPorts
[i
], ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
186 jack_port_set_latency ( fAudioPlaybackPorts
[i
], port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
189 jack_port_set_latency ( fAudioPlaybackPorts
[i
], 2 * port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
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
)
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
)
210 switch ( fParams
.fNetworkMode
)
213 jack_port_set_latency ( fMidiPlaybackPorts
[i
], ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
216 jack_port_set_latency ( fMidiPlaybackPorts
[i
], port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
219 jack_port_set_latency ( fMidiPlaybackPorts
[i
], 2 * port_latency
+ ( fParams
.fSlaveSyncMode
) ? 0 : port_latency
);
226 void JackNetMaster::FreePorts()
228 jack_log ( "JackNetMaster::FreePorts, ID %u", fParams
.fID
);
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
;
265 int JackNetMaster::DecodeTransportData()
267 //is there timebase master change ?
268 if ( fReturnTransportData
.fTimebaseMaster
!= NO_CHANGE
)
271 switch ( fReturnTransportData
.fTimebaseMaster
)
273 case RELEASE_TIMEBASEMASTER
:
274 timebase
= jack_release_timebase ( fJackClient
);
276 jack_error ( "Can't release timebase master." );
278 jack_info ( "'%s' isn't the timebase master anymore.", fParams
.fName
);
280 case TIMEBASEMASTER
:
281 timebase
= jack_set_timebase_callback ( fJackClient
, 0, SetTimebaseCallback
, this );
283 jack_error ( "Can't set a new timebase master." );
285 jack_info ( "'%s' is the new timebase master.", fParams
.fName
);
287 case CONDITIONAL_TIMEBASEMASTER
:
288 timebase
= jack_set_timebase_callback ( fJackClient
, 1, SetTimebaseCallback
, this );
289 if ( timebase
!= EBUSY
)
292 jack_error ( "Can't set a new timebase master." );
294 jack_info ( "'%s' is the new timebase master.", fParams
.fName
);
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
);
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
);
315 case JackTransportNetStarting
:
316 jack_info ( "'%s' is ready to roll..", fParams
.fName
);
318 case JackTransportRolling
:
319 jack_info ( "'%s' is rolling.", fParams
.fName
);
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 )
356 memcpy ( fTxData
, &fSendTransportData
, sizeof ( net_transport_data_t
) );
358 //then others (freewheel etc.)
363 int JackNetMaster::DecodeSyncPacket()
365 //this method contains every step of sync packet informations decoding process
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 )
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()
399 jack_time_t begin_time
= jack_get_time();
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 )
424 if ( SyncSend() == SOCKET_ERROR
)
428 fNetTimeMon
->Add ( ( ( ( float ) ( jack_get_time() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
432 if ( DataSend() == SOCKET_ERROR
)
436 fNetTimeMon
->Add ( ( ( ( float ) ( jack_get_time() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
440 jack_error("Connection is not synched, skip cycle...");
445 if ( ( res
== 0 ) || ( res
== SOCKET_ERROR
) )
449 fNetTimeMon
->Add ( ( ( ( float ) ( jack_get_time() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
453 if ( DecodeSyncPacket() < 0 )
458 if ( ( res
== 0 ) || ( res
== SOCKET_ERROR
) )
462 fNetTimeMon
->AddLast ( ( ( ( float ) ( jack_get_time() - begin_time
) ) / ( float ) fPeriodUsecs
) * 100.f
);
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
);
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
)
488 fMulticastIP
= strdup ( param
->value
.str
);
491 fSocket
.SetPort ( param
->value
.ui
);
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..." );
513 jack_client_stop_thread ( fManagerClient
, fManagerThread
);
514 master_list_t::iterator it
;
515 for ( it
= fMasterList
.begin(); it
!= fMasterList
.end(); it
++ )
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
531 for ( it
= fMasterList
.begin(); it
!= fMasterList
.end(); it
++ )
532 if ( ! ( *it
)->IsSlaveReadyToRoll() )
534 jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret
) ? "true" : "false" );
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();
547 void JackNetMasterManager::Run()
549 jack_log ( "JackNetMasterManager::Run" );
554 session_params_t host_params
;
556 JackNetMaster
* net_master
;
558 //init socket API (win32)
559 if ( SocketAPIInit() < 0 )
561 jack_error ( "Can't init Socket API, exiting..." );
566 if ( fSocket
.NewSocket() == SOCKET_ERROR
)
568 jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE
) );
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
) );
580 //join multicast group
581 if ( fSocket
.JoinMCastGroup ( fMulticastIP
) == SOCKET_ERROR
)
582 jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE
) );
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." );
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
);
617 jack_error ( "Can't init new net master..." );
618 jack_info ( "Waiting for a slave..." );
621 if ( KillMaster ( &host_params
) )
622 jack_info ( "Waiting for a slave..." );
632 JackNetMaster
* JackNetMasterManager::MasterInit ( session_params_t
& params
)
634 jack_log ( "JackNetMasterManager::MasterInit, Slave : %s", params
.fName
);
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
);
655 void JackNetMasterManager::SetSlaveName ( session_params_t
& params
)
657 jack_log ( "JackNetMasterManager::SetSlaveName" );
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
);
670 for ( it
= fMasterList
.begin(); it
!= fMasterList
.end(); it
++ )
671 if ( ( *it
)->fParams
.fID
== id
)
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
);
691 static Jack::JackNetMasterManager
* master_manager
= NULL
;
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
707 desc
->params
= ( jack_driver_param_desc_t
* ) calloc ( desc
->nparams
, sizeof ( jack_driver_param_desc_t
) );
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
);
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
);
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" );
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
, ¶ms
);
752 int res
= jack_internal_initialize ( jack_client
, params
);
753 parser
.FreeParams ( params
);
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
;