jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

779 lines
29KB

  1. /*
  2. Copyright (C) 2008 Romain Moret at Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackNetManager.h"
  16. #include "JackArgParser.h"
  17. using namespace std;
  18. namespace Jack
  19. {
  20. //JackNetMaster******************************************************************************************************
  21. JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip )
  22. : JackNetMasterInterface ( params, socket, multicast_ip )
  23. {
  24. jack_log ( "JackNetMaster::JackNetMaster" );
  25. //settings
  26. fClientName = const_cast<char*> ( fParams.fName );
  27. fJackClient = NULL;
  28. uint port_index;
  29. //jack audio ports
  30. fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
  31. for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
  32. fAudioCapturePorts[port_index] = NULL;
  33. fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
  34. for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
  35. fAudioPlaybackPorts[port_index] = NULL;
  36. //jack midi ports
  37. fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
  38. for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
  39. fMidiCapturePorts[port_index] = NULL;
  40. fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
  41. for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
  42. fMidiPlaybackPorts[port_index] = NULL;
  43. //monitor
  44. #ifdef JACK_MONITOR
  45. fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) );
  46. string plot_name;
  47. plot_name = string ( fParams.fName );
  48. plot_name += string ( "_master" );
  49. plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
  50. switch ( fParams.fNetworkMode )
  51. {
  52. case 's' :
  53. plot_name += string ( "_slow" );
  54. break;
  55. case 'n' :
  56. plot_name += string ( "_normal" );
  57. break;
  58. case 'f' :
  59. plot_name += string ( "_fast" );
  60. break;
  61. }
  62. fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
  63. string net_time_mon_fields[] =
  64. {
  65. string ( "sync send" ),
  66. string ( "end of send" ),
  67. string ( "sync recv" ),
  68. string ( "end of cycle" )
  69. };
  70. string net_time_mon_options[] =
  71. {
  72. string ( "set xlabel \"audio cycles\"" ),
  73. string ( "set ylabel \"% of audio cycle\"" )
  74. };
  75. fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
  76. #endif
  77. }
  78. JackNetMaster::~JackNetMaster()
  79. {
  80. jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams.fID );
  81. if ( fJackClient )
  82. {
  83. jack_deactivate ( fJackClient );
  84. FreePorts();
  85. jack_client_close ( fJackClient );
  86. }
  87. delete[] fAudioCapturePorts;
  88. delete[] fAudioPlaybackPorts;
  89. delete[] fMidiCapturePorts;
  90. delete[] fMidiPlaybackPorts;
  91. #ifdef JACK_MONITOR
  92. fNetTimeMon->Save();
  93. delete fNetTimeMon;
  94. #endif
  95. }
  96. //init--------------------------------------------------------------------------------
  97. bool JackNetMaster::Init()
  98. {
  99. //network init
  100. if ( !JackNetMasterInterface::Init() )
  101. return false;
  102. //set global parameters
  103. SetParams();
  104. //jack client and process
  105. jack_status_t status;
  106. if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL )
  107. {
  108. jack_error ( "Can't open a new jack client." );
  109. return false;
  110. }
  111. jack_set_process_callback ( fJackClient, SetProcess, this );
  112. if ( AllocPorts() != 0 )
  113. {
  114. jack_error ( "Can't allocate jack ports." );
  115. goto fail;
  116. }
  117. //process can now run
  118. fRunning = true;
  119. //finally activate jack client
  120. if ( jack_activate ( fJackClient ) != 0 )
  121. {
  122. jack_error ( "Can't activate jack client." );
  123. goto fail;
  124. }
  125. jack_info ( "New NetMaster started." );
  126. return true;
  127. fail:
  128. FreePorts();
  129. jack_client_close ( fJackClient );
  130. fJackClient = NULL;
  131. return false;
  132. }
  133. //jack ports--------------------------------------------------------------------------
  134. int JackNetMaster::AllocPorts()
  135. {
  136. jack_log ( "JackNetMaster::AllocPorts" );
  137. uint i;
  138. char name[24];
  139. jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient );
  140. unsigned long port_flags;
  141. //audio
  142. port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
  143. for ( i = 0; i < fParams.fSendAudioChannels; i++ )
  144. {
  145. sprintf ( name, "to_slave_%d", i+1 );
  146. if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL )
  147. return -1;
  148. //port latency
  149. jack_port_set_latency ( fAudioCapturePorts[i], 0 );
  150. }
  151. port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
  152. for ( i = 0; i < fParams.fReturnAudioChannels; i++ )
  153. {
  154. sprintf ( name, "from_slave_%d", i+1 );
  155. if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL )
  156. return -1;
  157. //port latency
  158. switch ( fParams.fNetworkMode )
  159. {
  160. case 'f' :
  161. jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
  162. break;
  163. case 'n' :
  164. jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
  165. break;
  166. case 's' :
  167. jack_port_set_latency ( fAudioPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
  168. break;
  169. }
  170. }
  171. //midi
  172. port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
  173. for ( i = 0; i < fParams.fSendMidiChannels; i++ )
  174. {
  175. sprintf ( name, "midi_to_slave_%d", i+1 );
  176. if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL )
  177. return -1;
  178. //port latency
  179. jack_port_set_latency ( fMidiCapturePorts[i], 0 );
  180. }
  181. port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
  182. for ( i = 0; i < fParams.fReturnMidiChannels; i++ )
  183. {
  184. sprintf ( name, "midi_from_slave_%d", i+1 );
  185. if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL )
  186. return -1;
  187. //port latency
  188. switch ( fParams.fNetworkMode )
  189. {
  190. case 'f' :
  191. jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
  192. break;
  193. case 'n' :
  194. jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
  195. break;
  196. case 's' :
  197. jack_port_set_latency ( fMidiPlaybackPorts[i], 2 * port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency );
  198. break;
  199. }
  200. }
  201. return 0;
  202. }
  203. void JackNetMaster::FreePorts()
  204. {
  205. jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID );
  206. uint port_index;
  207. for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
  208. if ( fAudioCapturePorts[port_index] )
  209. jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] );
  210. for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
  211. if ( fAudioPlaybackPorts[port_index] )
  212. jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] );
  213. for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
  214. if ( fMidiCapturePorts[port_index] )
  215. jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] );
  216. for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
  217. if ( fMidiPlaybackPorts[port_index] )
  218. jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
  219. }
  220. //transport---------------------------------------------------------------------------
  221. int JackNetMaster::EncodeTransportData()
  222. {
  223. //is there a new timebase master ?
  224. //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
  225. fSendTransportData.fTimebaseMaster = NO_CHANGE;
  226. //update state and position
  227. fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) );
  228. //is it a new state ?
  229. fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
  230. ( fSendTransportData.fState != fReturnTransportData.fState ) );
  231. if ( fSendTransportData.fNewState )
  232. jack_info ( "Sending '%s' to '%s'.", GetTransportState ( fSendTransportData.fState ), fParams.fName );
  233. fLastTransportState = fSendTransportData.fState;
  234. return 0;
  235. }
  236. int JackNetMaster::DecodeTransportData()
  237. {
  238. //is there timebase master change ?
  239. if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE )
  240. {
  241. int timebase = 0;
  242. switch ( fReturnTransportData.fTimebaseMaster )
  243. {
  244. case RELEASE_TIMEBASEMASTER :
  245. timebase = jack_release_timebase ( fJackClient );
  246. if ( timebase < 0 )
  247. jack_error ( "Can't release timebase master." );
  248. else
  249. jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
  250. break;
  251. case TIMEBASEMASTER :
  252. timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
  253. if ( timebase < 0 )
  254. jack_error ( "Can't set a new timebase master." );
  255. else
  256. jack_info ( "'%s' is the new timebase master.", fParams.fName );
  257. break;
  258. case CONDITIONAL_TIMEBASEMASTER :
  259. timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
  260. if ( timebase != EBUSY )
  261. {
  262. if ( timebase < 0 )
  263. jack_error ( "Can't set a new timebase master." );
  264. else
  265. jack_info ( "'%s' is the new timebase master.", fParams.fName );
  266. }
  267. break;
  268. }
  269. }
  270. //is the slave in a new transport state and is this state different from master's ?
  271. if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
  272. {
  273. switch ( fReturnTransportData.fState )
  274. {
  275. case JackTransportStopped :
  276. jack_transport_stop ( fJackClient );
  277. jack_info ( "'%s' stops transport.", fParams.fName );
  278. break;
  279. case JackTransportStarting :
  280. if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) < 0 )
  281. jack_error ( "Can't set new position." );
  282. jack_transport_start ( fJackClient );
  283. jack_info ( "'%s' starts transport.", fParams.fName );
  284. break;
  285. case JackTransportNetStarting :
  286. jack_info ( "'%s' is ready to roll..", fParams.fName );
  287. break;
  288. case JackTransportRolling :
  289. jack_info ( "'%s' is rolling.", fParams.fName );
  290. break;
  291. }
  292. }
  293. return 0;
  294. }
  295. void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
  296. {
  297. static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
  298. }
  299. void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
  300. {
  301. pos->bar = fReturnTransportData.fPosition.bar;
  302. pos->beat = fReturnTransportData.fPosition.beat;
  303. pos->tick = fReturnTransportData.fPosition.tick;
  304. pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
  305. pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
  306. pos->beat_type = fReturnTransportData.fPosition.beat_type;
  307. pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
  308. pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
  309. }
  310. //sync--------------------------------------------------------------------------------
  311. int JackNetMaster::EncodeSyncPacket()
  312. {
  313. //this method contains every step of sync packet informations coding
  314. //first of all, reset sync packet
  315. memset ( fTxData, 0, fPayloadSize );
  316. //then, first step : transport
  317. if ( fParams.fTransportSync )
  318. {
  319. if ( EncodeTransportData() < 0 )
  320. return -1;
  321. //copy to TxBuffer
  322. memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
  323. }
  324. //then others (freewheel etc.)
  325. //...
  326. return 0;
  327. }
  328. int JackNetMaster::DecodeSyncPacket()
  329. {
  330. //this method contains every step of sync packet informations decoding process
  331. //first : transport
  332. if ( fParams.fTransportSync )
  333. {
  334. //copy received transport data to transport data structure
  335. memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
  336. if ( DecodeTransportData() < 0 )
  337. return -1;
  338. }
  339. //then others
  340. //...
  341. return 0;
  342. }
  343. bool JackNetMaster::IsSlaveReadyToRoll()
  344. {
  345. return ( fReturnTransportData.fState == JackTransportNetStarting );
  346. }
  347. //process-----------------------------------------------------------------------------
  348. int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
  349. {
  350. return static_cast<JackNetMaster*> ( arg )->Process();
  351. }
  352. int JackNetMaster::Process()
  353. {
  354. if ( !fRunning )
  355. return 0;
  356. uint port_index;
  357. int res = 0;
  358. #ifdef JACK_MONITOR
  359. jack_time_t begin_time = GetMicroSeconds();
  360. fNetTimeMon->New();
  361. #endif
  362. //buffers
  363. for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
  364. fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
  365. fParams.fPeriodSize ) ) );
  366. for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
  367. fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
  368. fParams.fPeriodSize ) ) );
  369. for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
  370. fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
  371. fParams.fPeriodSize ) ) );
  372. for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
  373. fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
  374. fParams.fPeriodSize ) ) );
  375. if (IsSynched()) { // only send if connection is "synched"
  376. //encode the first packet
  377. if ( EncodeSyncPacket() < 0 )
  378. return 0;
  379. //send sync
  380. if ( SyncSend() == SOCKET_ERROR )
  381. return SOCKET_ERROR;
  382. #ifdef JACK_MONITOR
  383. fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  384. #endif
  385. //send data
  386. if ( DataSend() == SOCKET_ERROR )
  387. return SOCKET_ERROR;
  388. #ifdef JACK_MONITOR
  389. fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  390. #endif
  391. } else {
  392. jack_error("Connection is not synched, skip cycle...");
  393. }
  394. //receive sync
  395. res = SyncRecv();
  396. if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
  397. return res;
  398. #ifdef JACK_MONITOR
  399. fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  400. #endif
  401. //decode sync
  402. if ( DecodeSyncPacket() < 0 )
  403. return 0;
  404. //receive data
  405. res = DataRecv();
  406. if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
  407. return res;
  408. #ifdef JACK_MONITOR
  409. fNetTimeMon->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  410. #endif
  411. return 0;
  412. }
  413. //JackNetMasterManager***********************************************************************************************
  414. JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket()
  415. {
  416. jack_log ( "JackNetMasterManager::JackNetMasterManager" );
  417. fManagerClient = client;
  418. fManagerName = jack_get_client_name ( fManagerClient );
  419. fMulticastIP = DEFAULT_MULTICAST_IP;
  420. fSocket.SetPort ( DEFAULT_PORT );
  421. fGlobalID = 0;
  422. fRunning = true;
  423. const JSList* node;
  424. const jack_driver_param_t* param;
  425. for ( node = params; node; node = jack_slist_next ( node ) )
  426. {
  427. param = ( const jack_driver_param_t* ) node->data;
  428. switch ( param->character )
  429. {
  430. case 'a' :
  431. fMulticastIP = strdup ( param->value.str );
  432. break;
  433. case 'p':
  434. fSocket.SetPort ( param->value.ui );
  435. }
  436. }
  437. //set sync callback
  438. jack_set_sync_callback ( fManagerClient, SetSyncCallback, this );
  439. //activate the client (for sync callback)
  440. if ( jack_activate ( fManagerClient ) != 0 )
  441. jack_error ( "Can't activate the network manager client, transport disabled." );
  442. //launch the manager thread
  443. if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) )
  444. jack_error ( "Can't create the network manager control thread." );
  445. }
  446. JackNetMasterManager::~JackNetMasterManager()
  447. {
  448. jack_log ( "JackNetMasterManager::~JackNetMasterManager" );
  449. jack_info ( "Exiting net manager..." );
  450. fRunning = false;
  451. jack_client_kill_thread ( fManagerClient, fManagerThread );
  452. master_list_t::iterator it;
  453. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  454. delete ( *it );
  455. fSocket.Close();
  456. SocketAPIEnd();
  457. }
  458. int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
  459. {
  460. return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
  461. }
  462. int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
  463. {
  464. //check if each slave is ready to roll
  465. int ret = 1;
  466. master_list_it_t it;
  467. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  468. if ( ! ( *it )->IsSlaveReadyToRoll() )
  469. ret = 0;
  470. jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
  471. return ret;
  472. }
  473. void* JackNetMasterManager::NetManagerThread ( void* arg )
  474. {
  475. JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
  476. jack_info ( "Starting Jack Network Manager." );
  477. jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() );
  478. master_manager->Run();
  479. return NULL;
  480. }
  481. void JackNetMasterManager::Run()
  482. {
  483. jack_log ( "JackNetMasterManager::Run" );
  484. //utility variables
  485. int attempt = 0;
  486. //data
  487. session_params_t host_params;
  488. int rx_bytes = 0;
  489. JackNetMaster* net_master;
  490. //init socket API (win32)
  491. if ( SocketAPIInit() < 0 )
  492. {
  493. jack_error ( "Can't init Socket API, exiting..." );
  494. return;
  495. }
  496. //socket
  497. if ( fSocket.NewSocket() == SOCKET_ERROR )
  498. {
  499. jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) );
  500. return;
  501. }
  502. //bind the socket to the local port
  503. if ( fSocket.Bind() == SOCKET_ERROR )
  504. {
  505. jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) );
  506. fSocket.Close();
  507. return;
  508. }
  509. //join multicast group
  510. if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR )
  511. jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) );
  512. //local loop
  513. if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
  514. jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) );
  515. //set a timeout on the multicast receive (the thread can now be cancelled)
  516. if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
  517. jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
  518. jack_info ( "Waiting for a slave..." );
  519. //main loop, wait for data, deal with it and wait again
  520. do
  521. {
  522. session_params_t net_params;
  523. rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
  524. SessionParamsNToH(&net_params, &host_params);
  525. if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
  526. {
  527. jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
  528. if ( ++attempt == 10 )
  529. {
  530. jack_error ( "Can't receive on the socket, exiting net manager." );
  531. return;
  532. }
  533. }
  534. if ( rx_bytes == sizeof ( session_params_t ) )
  535. {
  536. switch ( GetPacketType ( &host_params ) )
  537. {
  538. case SLAVE_AVAILABLE:
  539. if ( ( net_master = MasterInit ( host_params ) ) )
  540. SessionParamsDisplay ( &net_master->fParams );
  541. else
  542. jack_error ( "Can't init new net master..." );
  543. jack_info ( "Waiting for a slave..." );
  544. break;
  545. case KILL_MASTER:
  546. if ( KillMaster ( &host_params ) )
  547. jack_info ( "Waiting for a slave..." );
  548. break;
  549. default:
  550. break;
  551. }
  552. }
  553. }
  554. while ( fRunning );
  555. }
  556. JackNetMaster* JackNetMasterManager::MasterInit ( session_params_t& params )
  557. {
  558. jack_log ( "JackNetMasterManager::MasterInit, Slave : %s", params.fName );
  559. //check MASTER <<==> SLAVE network protocol coherency
  560. if (params.fProtocolVersion != MASTER_PROTOCOL) {
  561. jack_error ( "Error : slave is running with a different protocol %s", params.fName );
  562. return NULL;
  563. }
  564. //settings
  565. fSocket.GetName ( params.fMasterNetName );
  566. params.fID = ++fGlobalID;
  567. params.fSampleRate = jack_get_sample_rate ( fManagerClient );
  568. params.fPeriodSize = jack_get_buffer_size ( fManagerClient );
  569. params.fBitdepth = 0;
  570. SetSlaveName ( params );
  571. //create a new master and add it to the list
  572. JackNetMaster* master = new JackNetMaster ( fSocket, params, fMulticastIP );
  573. if ( master->Init() )
  574. {
  575. fMasterList.push_back ( master );
  576. return master;
  577. }
  578. delete master;
  579. return NULL;
  580. }
  581. void JackNetMasterManager::SetSlaveName ( session_params_t& params )
  582. {
  583. jack_log ( "JackNetMasterManager::SetSlaveName" );
  584. master_list_it_t it;
  585. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  586. if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 )
  587. sprintf ( params.fName, "%s-%u", params.fName, params.fID );
  588. }
  589. master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id )
  590. {
  591. jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id );
  592. master_list_it_t it;
  593. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  594. if ( ( *it )->fParams.fID == id )
  595. return it;
  596. return it;
  597. }
  598. int JackNetMasterManager::KillMaster ( session_params_t* params )
  599. {
  600. jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID );
  601. master_list_it_t master = FindMaster ( params->fID );
  602. if ( master != fMasterList.end() )
  603. {
  604. fMasterList.erase ( master );
  605. delete *master;
  606. return 1;
  607. }
  608. return 0;
  609. }
  610. }//namespace
  611. static Jack::JackNetMasterManager* master_manager = NULL;
  612. #ifdef __cplusplus
  613. extern "C"
  614. {
  615. #endif
  616. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  617. {
  618. jack_driver_desc_t *desc;
  619. desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  620. strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  621. strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  622. desc->nparams = 2;
  623. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  624. int i = 0;
  625. strcpy ( desc->params[i].name, "multicast_ip" );
  626. desc->params[i].character = 'a';
  627. desc->params[i].type = JackDriverParamString;
  628. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  629. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  630. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  631. i++;
  632. strcpy ( desc->params[i].name, "udp_net_port" );
  633. desc->params[i].character = 'p';
  634. desc->params[i].type = JackDriverParamInt;
  635. desc->params[i].value.i = DEFAULT_PORT;
  636. strcpy ( desc->params[i].short_desc, "UDP port" );
  637. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  638. return desc;
  639. }
  640. SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  641. {
  642. if ( master_manager )
  643. {
  644. jack_error ( "Master Manager already loaded" );
  645. return 1;
  646. }
  647. else
  648. {
  649. jack_log ( "Loading Master Manager" );
  650. master_manager = new Jack::JackNetMasterManager ( jack_client, params );
  651. return ( master_manager ) ? 0 : 1;
  652. }
  653. }
  654. SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  655. {
  656. JSList* params = NULL;
  657. bool parse_params = true;
  658. int res = 1;
  659. jack_driver_desc_t* desc = jack_get_descriptor();
  660. Jack::JackArgParser parser ( load_init );
  661. if ( parser.GetArgc() > 0 )
  662. parse_params = parser.ParseParams ( desc, &params );
  663. if (parse_params) {
  664. res = jack_internal_initialize ( jack_client, params );
  665. parser.FreeParams ( params );
  666. }
  667. return res;
  668. }
  669. SERVER_EXPORT void jack_finish ( void* arg )
  670. {
  671. if ( master_manager )
  672. {
  673. jack_log ( "Unloading Master Manager" );
  674. delete master_manager;
  675. master_manager = NULL;
  676. }
  677. }
  678. #ifdef __cplusplus
  679. }
  680. #endif