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.

891 lines
33KB

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