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.

919 lines
34KB

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