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.

847 lines
32KB

  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. if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0)
  116. goto fail;
  117. if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0)
  118. goto fail;
  119. if ( AllocPorts() != 0 )
  120. {
  121. jack_error ( "Can't allocate jack ports." );
  122. goto fail;
  123. }
  124. //process can now run
  125. fRunning = true;
  126. //finally activate jack client
  127. if ( jack_activate ( fJackClient ) != 0 )
  128. {
  129. jack_error ( "Can't activate jack client." );
  130. goto fail;
  131. }
  132. if (auto_connect)
  133. ConnectPorts();
  134. jack_info ( "New NetMaster started." );
  135. return true;
  136. fail:
  137. FreePorts();
  138. jack_client_close ( fJackClient );
  139. fJackClient = NULL;
  140. return false;
  141. }
  142. //jack ports--------------------------------------------------------------------------
  143. int JackNetMaster::AllocPorts()
  144. {
  145. uint i;
  146. char name[24];
  147. jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient );
  148. jack_latency_range_t range;
  149. jack_log ( "JackNetMaster::AllocPorts" );
  150. //audio
  151. for ( i = 0; i < fParams.fSendAudioChannels; i++ )
  152. {
  153. sprintf ( name, "to_slave_%d", i+1 );
  154. if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
  155. return -1;
  156. //port latency
  157. range.min = range.max = 0;
  158. jack_port_set_latency_range(fAudioCapturePorts[i], JackCaptureLatency, &range);
  159. }
  160. for ( i = 0; i < fParams.fReturnAudioChannels; i++ )
  161. {
  162. sprintf ( name, "from_slave_%d", i+1 );
  163. if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
  164. return -1;
  165. //port latency
  166. switch ( fParams.fNetworkMode )
  167. {
  168. case 'f' :
  169. range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency;
  170. jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
  171. break;
  172. case 'n' :
  173. range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
  174. jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
  175. break;
  176. case 's' :
  177. range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
  178. jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
  179. break;
  180. }
  181. }
  182. //midi
  183. for ( i = 0; i < fParams.fSendMidiChannels; i++ )
  184. {
  185. sprintf ( name, "midi_to_slave_%d", i+1 );
  186. if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
  187. return -1;
  188. //port latency
  189. range.min = range.max = 0;
  190. jack_port_set_latency_range(fMidiCapturePorts[i], JackCaptureLatency, &range);
  191. }
  192. for ( i = 0; i < fParams.fReturnMidiChannels; i++ )
  193. {
  194. sprintf ( name, "midi_from_slave_%d", i+1 );
  195. if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
  196. return -1;
  197. //port latency
  198. switch ( fParams.fNetworkMode )
  199. {
  200. case 'f' :
  201. range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency;
  202. jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
  203. break;
  204. case 'n' :
  205. range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
  206. jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
  207. break;
  208. case 's' :
  209. range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
  210. jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
  211. break;
  212. }
  213. }
  214. return 0;
  215. }
  216. void JackNetMaster::ConnectPorts()
  217. {
  218. const char **ports;
  219. ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
  220. if (ports != NULL) {
  221. for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
  222. jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i]));
  223. }
  224. free(ports);
  225. }
  226. ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
  227. if (ports != NULL) {
  228. for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
  229. jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]);
  230. }
  231. free(ports);
  232. }
  233. }
  234. void JackNetMaster::FreePorts()
  235. {
  236. jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID );
  237. uint port_index;
  238. for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
  239. if ( fAudioCapturePorts[port_index] )
  240. jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] );
  241. for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
  242. if ( fAudioPlaybackPorts[port_index] )
  243. jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] );
  244. for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
  245. if ( fMidiCapturePorts[port_index] )
  246. jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] );
  247. for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
  248. if ( fMidiPlaybackPorts[port_index] )
  249. jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
  250. }
  251. //transport---------------------------------------------------------------------------
  252. void JackNetMaster::EncodeTransportData()
  253. {
  254. //is there a new timebase master ?
  255. //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
  256. fSendTransportData.fTimebaseMaster = NO_CHANGE;
  257. //update state and position
  258. fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) );
  259. //is it a new state ?
  260. fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
  261. ( fSendTransportData.fState != fReturnTransportData.fState ) );
  262. if ( fSendTransportData.fNewState )
  263. jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame );
  264. fLastTransportState = fSendTransportData.fState;
  265. }
  266. void JackNetMaster::DecodeTransportData()
  267. {
  268. //is there timebase master change ?
  269. if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE )
  270. {
  271. int timebase = 0;
  272. switch ( fReturnTransportData.fTimebaseMaster )
  273. {
  274. case RELEASE_TIMEBASEMASTER :
  275. timebase = jack_release_timebase ( fJackClient );
  276. if ( timebase < 0 )
  277. jack_error ( "Can't release timebase master." );
  278. else
  279. jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
  280. break;
  281. case TIMEBASEMASTER :
  282. timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
  283. if ( timebase < 0 )
  284. jack_error ( "Can't set a new timebase master." );
  285. else
  286. jack_info ( "'%s' is the new timebase master.", fParams.fName );
  287. break;
  288. case CONDITIONAL_TIMEBASEMASTER :
  289. timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
  290. if ( timebase != EBUSY )
  291. {
  292. if ( timebase < 0 )
  293. jack_error ( "Can't set a new timebase master." );
  294. else
  295. jack_info ( "'%s' is the new timebase master.", fParams.fName );
  296. }
  297. break;
  298. }
  299. }
  300. //is the slave in a new transport state and is this state different from master's ?
  301. if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
  302. {
  303. switch ( fReturnTransportData.fState )
  304. {
  305. case JackTransportStopped :
  306. jack_transport_stop ( fJackClient );
  307. jack_info ( "'%s' stops transport.", fParams.fName );
  308. break;
  309. case JackTransportStarting :
  310. if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL )
  311. jack_error ( "Can't set new position." );
  312. jack_transport_start ( fJackClient );
  313. jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
  314. break;
  315. case JackTransportNetStarting :
  316. jack_info ( "'%s' is ready to roll..", fParams.fName );
  317. break;
  318. case JackTransportRolling :
  319. jack_info ( "'%s' is rolling.", fParams.fName );
  320. break;
  321. }
  322. }
  323. }
  324. void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
  325. {
  326. static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
  327. }
  328. void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
  329. {
  330. pos->bar = fReturnTransportData.fPosition.bar;
  331. pos->beat = fReturnTransportData.fPosition.beat;
  332. pos->tick = fReturnTransportData.fPosition.tick;
  333. pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
  334. pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
  335. pos->beat_type = fReturnTransportData.fPosition.beat_type;
  336. pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
  337. pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
  338. }
  339. //sync--------------------------------------------------------------------------------
  340. bool JackNetMaster::IsSlaveReadyToRoll()
  341. {
  342. return ( fReturnTransportData.fState == JackTransportNetStarting );
  343. }
  344. int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg)
  345. {
  346. JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
  347. if (nframes != obj->fParams.fPeriodSize) {
  348. jack_error("Cannot handle buffer size change, so JackNetMaster proxy will be removed...");
  349. obj->Exit();
  350. }
  351. return 0;
  352. }
  353. //process-----------------------------------------------------------------------------
  354. int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
  355. {
  356. return static_cast<JackNetMaster*> ( arg )->Process();
  357. }
  358. int JackNetMaster::Process()
  359. {
  360. if ( !fRunning )
  361. return 0;
  362. uint port_index;
  363. int res = 0;
  364. #ifdef JACK_MONITOR
  365. jack_time_t begin_time = GetMicroSeconds();
  366. fNetTimeMon->New();
  367. #endif
  368. //buffers
  369. for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
  370. fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
  371. fParams.fPeriodSize ) ) );
  372. for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
  373. fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
  374. fParams.fPeriodSize ) ) );
  375. for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
  376. fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
  377. fParams.fPeriodSize ) ) );
  378. for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
  379. fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
  380. fParams.fPeriodSize ) ) );
  381. if (IsSynched()) { // only send if connection is "synched"
  382. //encode the first packet
  383. EncodeSyncPacket();
  384. //send sync
  385. if ( SyncSend() == SOCKET_ERROR )
  386. return SOCKET_ERROR;
  387. #ifdef JACK_MONITOR
  388. fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  389. #endif
  390. //send data
  391. if ( DataSend() == SOCKET_ERROR )
  392. return SOCKET_ERROR;
  393. #ifdef JACK_MONITOR
  394. fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  395. #endif
  396. } else {
  397. jack_error("Connection is not synched, skip cycle...");
  398. }
  399. //receive sync
  400. res = SyncRecv();
  401. if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
  402. return res;
  403. #ifdef JACK_MONITOR
  404. fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  405. #endif
  406. //decode sync
  407. DecodeSyncPacket();
  408. //receive data
  409. res = DataRecv();
  410. if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
  411. return res;
  412. #ifdef JACK_MONITOR
  413. fNetTimeMon->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
  414. #endif
  415. return 0;
  416. }
  417. //JackNetMasterManager***********************************************************************************************
  418. JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket()
  419. {
  420. jack_log ( "JackNetMasterManager::JackNetMasterManager" );
  421. fManagerClient = client;
  422. fManagerName = jack_get_client_name ( fManagerClient );
  423. strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
  424. fSocket.SetPort ( DEFAULT_PORT );
  425. fGlobalID = 0;
  426. fRunning = true;
  427. fAutoConnect = false;
  428. const JSList* node;
  429. const jack_driver_param_t* param;
  430. for ( node = params; node; node = jack_slist_next ( node ) )
  431. {
  432. param = ( const jack_driver_param_t* ) node->data;
  433. switch ( param->character )
  434. {
  435. case 'a' :
  436. if (strlen (param->value.str) < 32)
  437. strcpy(fMulticastIP, param->value.str);
  438. else
  439. jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
  440. break;
  441. case 'p':
  442. fSocket.SetPort ( param->value.ui );
  443. break;
  444. case 'c':
  445. fAutoConnect = param->value.i;
  446. break;
  447. }
  448. }
  449. //set sync callback
  450. jack_set_sync_callback ( fManagerClient, SetSyncCallback, this );
  451. //activate the client (for sync callback)
  452. if ( jack_activate ( fManagerClient ) != 0 )
  453. jack_error ( "Can't activate the network manager client, transport disabled." );
  454. //launch the manager thread
  455. if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) )
  456. jack_error ( "Can't create the network manager control thread." );
  457. }
  458. JackNetMasterManager::~JackNetMasterManager()
  459. {
  460. jack_log ( "JackNetMasterManager::~JackNetMasterManager" );
  461. jack_info ( "Exiting net manager..." );
  462. fRunning = false;
  463. jack_client_kill_thread ( fManagerClient, fManagerThread );
  464. master_list_t::iterator it;
  465. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  466. delete ( *it );
  467. fSocket.Close();
  468. SocketAPIEnd();
  469. }
  470. int JackNetMasterManager::CountPhysicalInputs()
  471. {
  472. const char **ports;
  473. int count = 0;
  474. ports = jack_get_ports(fManagerClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
  475. if (ports != NULL) {
  476. while(ports[count]) count++;
  477. free(ports);
  478. }
  479. return count;
  480. }
  481. int JackNetMasterManager::CountPhysicalOutputs()
  482. {
  483. const char **ports;
  484. int count = 0;
  485. ports = jack_get_ports(fManagerClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
  486. if (ports != NULL) {
  487. while(ports[count]) count++;
  488. free(ports);
  489. }
  490. return count;
  491. }
  492. int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
  493. {
  494. return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
  495. }
  496. int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
  497. {
  498. //check if each slave is ready to roll
  499. int ret = 1;
  500. master_list_it_t it;
  501. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  502. if ( ! ( *it )->IsSlaveReadyToRoll() )
  503. ret = 0;
  504. jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
  505. return ret;
  506. }
  507. void* JackNetMasterManager::NetManagerThread ( void* arg )
  508. {
  509. JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
  510. jack_info ( "Starting Jack Network Manager." );
  511. jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() );
  512. master_manager->Run();
  513. return NULL;
  514. }
  515. void JackNetMasterManager::Run()
  516. {
  517. jack_log ( "JackNetMasterManager::Run" );
  518. //utility variables
  519. int attempt = 0;
  520. //data
  521. session_params_t host_params;
  522. int rx_bytes = 0;
  523. JackNetMaster* net_master;
  524. //init socket API (win32)
  525. if ( SocketAPIInit() < 0 )
  526. {
  527. jack_error ( "Can't init Socket API, exiting..." );
  528. return;
  529. }
  530. //socket
  531. if ( fSocket.NewSocket() == SOCKET_ERROR )
  532. {
  533. jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) );
  534. return;
  535. }
  536. //bind the socket to the local port
  537. if ( fSocket.Bind() == SOCKET_ERROR )
  538. {
  539. jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) );
  540. fSocket.Close();
  541. return;
  542. }
  543. //join multicast group
  544. if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR )
  545. jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) );
  546. //local loop
  547. if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
  548. jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) );
  549. //set a timeout on the multicast receive (the thread can now be cancelled)
  550. if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
  551. jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
  552. jack_info ( "Waiting for a slave..." );
  553. //main loop, wait for data, deal with it and wait again
  554. do
  555. {
  556. session_params_t net_params;
  557. rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
  558. SessionParamsNToH(&net_params, &host_params);
  559. if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
  560. {
  561. jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
  562. if ( ++attempt == 10 )
  563. {
  564. jack_error ( "Can't receive on the socket, exiting net manager." );
  565. return;
  566. }
  567. }
  568. if ( rx_bytes == sizeof ( session_params_t ) )
  569. {
  570. switch ( GetPacketType ( &host_params ) )
  571. {
  572. case SLAVE_AVAILABLE:
  573. if ( ( net_master = InitMaster ( host_params ) ) )
  574. SessionParamsDisplay ( &net_master->fParams );
  575. else
  576. jack_error ( "Can't init new net master..." );
  577. jack_info ( "Waiting for a slave..." );
  578. break;
  579. case KILL_MASTER:
  580. if ( KillMaster ( &host_params ) )
  581. jack_info ( "Waiting for a slave..." );
  582. break;
  583. default:
  584. break;
  585. }
  586. }
  587. }
  588. while ( fRunning );
  589. }
  590. JackNetMaster* JackNetMasterManager::InitMaster ( session_params_t& params )
  591. {
  592. jack_log ( "JackNetMasterManager::InitMaster, Slave : %s", params.fName );
  593. //check MASTER <<==> SLAVE network protocol coherency
  594. if (params.fProtocolVersion != MASTER_PROTOCOL) {
  595. jack_error ( "Error : slave is running with a different protocol %s", params.fName );
  596. return NULL;
  597. }
  598. //settings
  599. fSocket.GetName ( params.fMasterNetName );
  600. params.fID = ++fGlobalID;
  601. params.fSampleRate = jack_get_sample_rate ( fManagerClient );
  602. params.fPeriodSize = jack_get_buffer_size ( fManagerClient );
  603. params.fBitdepth = 0;
  604. if (params.fSendAudioChannels == -1) {
  605. params.fSendAudioChannels = CountPhysicalInputs();
  606. jack_info( "Takes physical %d inputs for client", params.fSendAudioChannels);
  607. }
  608. if (params.fReturnAudioChannels == -1) {
  609. params.fReturnAudioChannels = CountPhysicalOutputs();
  610. jack_info("Takes physical %d outputs for client", params.fReturnAudioChannels);
  611. }
  612. SetSlaveName (params);
  613. //create a new master and add it to the list
  614. JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP);
  615. if (master->Init(fAutoConnect)) {
  616. fMasterList.push_back(master);
  617. return master;
  618. }
  619. delete master;
  620. return NULL;
  621. }
  622. void JackNetMasterManager::SetSlaveName ( session_params_t& params )
  623. {
  624. jack_log ( "JackNetMasterManager::SetSlaveName" );
  625. master_list_it_t it;
  626. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  627. if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 )
  628. sprintf ( params.fName, "%s-%u", params.fName, params.fID );
  629. }
  630. master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id )
  631. {
  632. jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id );
  633. master_list_it_t it;
  634. for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
  635. if ( ( *it )->fParams.fID == id )
  636. return it;
  637. return it;
  638. }
  639. int JackNetMasterManager::KillMaster ( session_params_t* params )
  640. {
  641. jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID );
  642. master_list_it_t master = FindMaster ( params->fID );
  643. if ( master != fMasterList.end() )
  644. {
  645. fMasterList.erase ( master );
  646. delete *master;
  647. return 1;
  648. }
  649. return 0;
  650. }
  651. }//namespace
  652. static Jack::JackNetMasterManager* master_manager = NULL;
  653. #ifdef __cplusplus
  654. extern "C"
  655. {
  656. #endif
  657. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  658. {
  659. jack_driver_desc_t *desc;
  660. desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  661. strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  662. strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  663. desc->nparams = 3;
  664. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  665. int i = 0;
  666. strcpy ( desc->params[i].name, "multicast_ip" );
  667. desc->params[i].character = 'a';
  668. desc->params[i].type = JackDriverParamString;
  669. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  670. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  671. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  672. i++;
  673. strcpy ( desc->params[i].name, "udp_net_port" );
  674. desc->params[i].character = 'p';
  675. desc->params[i].type = JackDriverParamInt;
  676. desc->params[i].value.i = DEFAULT_PORT;
  677. strcpy ( desc->params[i].short_desc, "UDP port" );
  678. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  679. i++;
  680. strcpy ( desc->params[i].name, "auto_connect" );
  681. desc->params[i].character = 'c';
  682. desc->params[i].type = JackDriverParamBool;
  683. desc->params[i].value.i = false;
  684. strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" );
  685. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  686. return desc;
  687. }
  688. SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  689. {
  690. if ( master_manager )
  691. {
  692. jack_error ( "Master Manager already loaded" );
  693. return 1;
  694. }
  695. else
  696. {
  697. jack_log ( "Loading Master Manager" );
  698. master_manager = new Jack::JackNetMasterManager ( jack_client, params );
  699. return ( master_manager ) ? 0 : 1;
  700. }
  701. }
  702. SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  703. {
  704. JSList* params = NULL;
  705. bool parse_params = true;
  706. int res = 1;
  707. jack_driver_desc_t* desc = jack_get_descriptor();
  708. Jack::JackArgParser parser ( load_init );
  709. if ( parser.GetArgc() > 0 )
  710. parse_params = parser.ParseParams ( desc, &params );
  711. if (parse_params) {
  712. res = jack_internal_initialize ( jack_client, params );
  713. parser.FreeParams ( params );
  714. }
  715. return res;
  716. }
  717. SERVER_EXPORT void jack_finish ( void* arg )
  718. {
  719. if ( master_manager )
  720. {
  721. jack_log ( "Unloading Master Manager" );
  722. delete master_manager;
  723. master_manager = NULL;
  724. }
  725. }
  726. #ifdef __cplusplus
  727. }
  728. #endif