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.

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