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.

764 lines
28KB

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