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.

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