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
30KB

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