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.

560 lines
20KB

  1. /*
  2. Copyright (C) 2008 Romain Moret at Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackNetAdapter.h"
  16. #include "JackException.h"
  17. #include "JackServerGlobals.h"
  18. #include "JackEngineControl.h"
  19. #include "JackArgParser.h"
  20. #include <assert.h>
  21. namespace Jack
  22. {
  23. JackNetAdapter::JackNetAdapter ( jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
  24. : JackAudioAdapterInterface ( buffer_size, sample_rate ), JackNetSlaveInterface(), fThread ( this )
  25. {
  26. jack_log ( "JackNetAdapter::JackNetAdapter" );
  27. //global parametering
  28. //we can't call JackNetSlaveInterface constructor with some parameters before
  29. //because we don't have full parametering right now
  30. //parameters will be parsed from the param list, and then JackNetSlaveInterface will be filled with proper values
  31. fMulticastIP = new char[16];
  32. strcpy ( fMulticastIP, DEFAULT_MULTICAST_IP );
  33. uint port = DEFAULT_PORT;
  34. GetHostName ( fParams.fName, JACK_CLIENT_NAME_SIZE );
  35. fSocket.GetName ( fParams.fSlaveNetName );
  36. fParams.fMtu = DEFAULT_MTU;
  37. fParams.fTransportSync = 0;
  38. fParams.fSendAudioChannels = 2;
  39. fParams.fReturnAudioChannels = 2;
  40. fParams.fSendMidiChannels = 0;
  41. fParams.fReturnMidiChannels = 0;
  42. fParams.fSampleRate = sample_rate;
  43. fParams.fPeriodSize = buffer_size;
  44. fParams.fSlaveSyncMode = 1;
  45. fParams.fNetworkMode = 's';
  46. fJackClient = jack_client;
  47. //options parsing
  48. const JSList* node;
  49. const jack_driver_param_t* param;
  50. for ( node = params; node; node = jack_slist_next ( node ) )
  51. {
  52. param = ( const jack_driver_param_t* ) node->data;
  53. switch ( param->character )
  54. {
  55. case 'a' :
  56. if ( strlen ( param->value.str ) < 16 )
  57. strcpy ( fMulticastIP, param->value.str );
  58. else
  59. jack_error ( "Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP );
  60. break;
  61. case 'p' :
  62. fSocket.SetPort ( param->value.ui );
  63. break;
  64. case 'M' :
  65. fParams.fMtu = param->value.i;
  66. break;
  67. case 'C' :
  68. fParams.fSendAudioChannels = param->value.i;
  69. break;
  70. case 'P' :
  71. fParams.fReturnAudioChannels = param->value.i;
  72. break;
  73. case 'n' :
  74. strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE );
  75. break;
  76. case 't' :
  77. //fParams.fTransportSync = param->value.ui;
  78. break;
  79. case 'm' :
  80. if ( strcmp ( param->value.str, "normal" ) == 0 )
  81. fParams.fNetworkMode = 'n';
  82. else if ( strcmp ( param->value.str, "slow" ) == 0 )
  83. fParams.fNetworkMode = 's';
  84. else if ( strcmp ( param->value.str, "fast" ) == 0 )
  85. fParams.fNetworkMode = 'f';
  86. else
  87. jack_error ( "Unknown network mode, using 'normal' mode." );
  88. break;
  89. case 'q':
  90. fQuality = param->value.ui;
  91. break;
  92. }
  93. }
  94. //set the socket parameters
  95. fSocket.SetPort ( port );
  96. fSocket.SetAddress ( fMulticastIP, port );
  97. //set the audio adapter interface channel values
  98. SetInputs ( fParams.fSendAudioChannels );
  99. SetOutputs ( fParams.fReturnAudioChannels );
  100. //soft buffers will be allocated later (once network initialization done)
  101. fSoftCaptureBuffer = NULL;
  102. fSoftPlaybackBuffer = NULL;
  103. }
  104. JackNetAdapter::~JackNetAdapter()
  105. {
  106. jack_log ( "JackNetAdapter::~JackNetAdapter" );
  107. int port_index;
  108. if ( fSoftCaptureBuffer )
  109. {
  110. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  111. delete[] fSoftCaptureBuffer[port_index];
  112. delete[] fSoftCaptureBuffer;
  113. }
  114. if ( fSoftPlaybackBuffer )
  115. {
  116. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  117. delete[] fSoftPlaybackBuffer[port_index];
  118. delete[] fSoftPlaybackBuffer;
  119. }
  120. }
  121. //open/close--------------------------------------------------------------------------
  122. int JackNetAdapter::Open()
  123. {
  124. jack_log ( "JackNetAdapter::Open" );
  125. jack_info ( "NetAdapter started in %s mode %s Master's transport sync.",
  126. ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
  127. if ( fThread.StartSync() < 0 )
  128. {
  129. jack_error ( "Cannot start netadapter thread" );
  130. return -1;
  131. }
  132. return 0;
  133. }
  134. int JackNetAdapter::Close()
  135. {
  136. jack_log ( "JackNetAdapter::Close" );
  137. switch ( fThread.GetStatus() )
  138. {
  139. // Kill the thread in Init phase
  140. case JackThread::kStarting:
  141. case JackThread::kIniting:
  142. if ( fThread.Kill() < 0 )
  143. {
  144. jack_error ( "Cannot kill thread" );
  145. return -1;
  146. }
  147. break;
  148. // Stop when the thread cycle is finished
  149. case JackThread::kRunning:
  150. if ( fThread.Stop() < 0 )
  151. {
  152. jack_error ( "Cannot stop thread" );
  153. return -1;
  154. }
  155. break;
  156. default:
  157. break;
  158. }
  159. fSocket.Close();
  160. return 0;
  161. }
  162. int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  163. {
  164. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  165. return 0;
  166. }
  167. //thread------------------------------------------------------------------------------
  168. bool JackNetAdapter::Init()
  169. {
  170. jack_log ( "JackNetAdapter::Init" );
  171. int port_index;
  172. //init network connection
  173. if ( !JackNetSlaveInterface::Init() )
  174. return false;
  175. //then set global parameters
  176. SetParams();
  177. //set buffers
  178. fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
  179. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  180. {
  181. fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  182. fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] );
  183. }
  184. fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
  185. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  186. {
  187. fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  188. fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] );
  189. }
  190. //set audio adapter parameters
  191. SetAdaptedBufferSize ( fParams.fPeriodSize );
  192. SetAdaptedSampleRate ( fParams.fSampleRate );
  193. // Will do "something" on OSX only...
  194. fThread.SetParams(JackServerGlobals::fInstance->GetEngineControl()->fPeriod,
  195. JackServerGlobals::fInstance->GetEngineControl()->fComputation,
  196. JackServerGlobals::fInstance->GetEngineControl()->fConstraint);
  197. if (fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority ) < 0) {
  198. jack_error("AcquireRealTime error");
  199. } else {
  200. set_threaded_log_function();
  201. }
  202. //init done, display parameters
  203. SessionParamsDisplay ( &fParams );
  204. return true;
  205. }
  206. bool JackNetAdapter::Execute()
  207. {
  208. try
  209. {
  210. // Keep running even in case of error
  211. while ( fThread.GetStatus() == JackThread::kRunning )
  212. if ( Process() == SOCKET_ERROR )
  213. return false;
  214. return false;
  215. }
  216. catch ( JackNetException& e )
  217. {
  218. e.PrintMessage();
  219. jack_log ( "NetAdapter is restarted." );
  220. fThread.DropRealTime();
  221. fThread.SetStatus ( JackThread::kIniting );
  222. if ( Init() )
  223. {
  224. fThread.SetStatus ( JackThread::kRunning );
  225. return true;
  226. }
  227. else
  228. return false;
  229. }
  230. }
  231. //transport---------------------------------------------------------------------------
  232. int JackNetAdapter::DecodeTransportData()
  233. {
  234. //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver)
  235. //is there a new transport state ?
  236. if ( fSendTransportData.fNewState && ( fSendTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
  237. {
  238. switch ( fSendTransportData.fState )
  239. {
  240. case JackTransportStopped :
  241. jack_transport_stop ( fJackClient );
  242. jack_info ( "NetMaster : transport stops." );
  243. break;
  244. case JackTransportStarting :
  245. jack_transport_reposition ( fJackClient, &fSendTransportData.fPosition );
  246. jack_transport_start ( fJackClient );
  247. jack_info ( "NetMaster : transport starts." );
  248. break;
  249. case JackTransportRolling :
  250. //TODO , we need to :
  251. // - find a way to call TransportEngine->SetNetworkSync()
  252. // - turn the transport state to JackTransportRolling
  253. jack_info ( "NetMaster : transport rolls." );
  254. break;
  255. }
  256. }
  257. return 0;
  258. }
  259. int JackNetAdapter::EncodeTransportData()
  260. {
  261. //is there a timebase master change ?
  262. int refnum = -1;
  263. bool conditional = 0;
  264. //TODO : get the actual timebase master
  265. if ( refnum != fLastTimebaseMaster )
  266. {
  267. //timebase master has released its function
  268. if ( refnum == -1 )
  269. {
  270. fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
  271. jack_info ( "Sending a timebase master release request." );
  272. }
  273. //there is a new timebase master
  274. else
  275. {
  276. fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
  277. jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" );
  278. }
  279. fLastTimebaseMaster = refnum;
  280. }
  281. else
  282. fReturnTransportData.fTimebaseMaster = NO_CHANGE;
  283. //update transport state and position
  284. fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition );
  285. //is it a new state (that the master need to know...) ?
  286. fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) &&
  287. ( fReturnTransportData.fState != fSendTransportData.fState ) );
  288. if ( fReturnTransportData.fNewState )
  289. jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) );
  290. fLastTransportState = fReturnTransportData.fState;
  291. return 0;
  292. }
  293. //read/write operations---------------------------------------------------------------
  294. int JackNetAdapter::Read()
  295. {
  296. //don't return -1 in case of sync recv failure
  297. //we need the process to continue for network error detection
  298. if ( SyncRecv() == SOCKET_ERROR )
  299. return 0;
  300. if ( DecodeSyncPacket() < 0 )
  301. return 0;
  302. return DataRecv();
  303. }
  304. int JackNetAdapter::Write()
  305. {
  306. if ( EncodeSyncPacket() < 0 )
  307. return 0;
  308. if ( SyncSend() == SOCKET_ERROR )
  309. return SOCKET_ERROR;
  310. return DataSend();
  311. }
  312. //process-----------------------------------------------------------------------------
  313. int JackNetAdapter::Process()
  314. {
  315. bool failure = false;
  316. int port_index;
  317. //read data from the network
  318. //in case of fatal network error, stop the process
  319. if ( Read() == SOCKET_ERROR )
  320. return SOCKET_ERROR;
  321. //get the resample factor,
  322. jack_nframes_t time1, time2;
  323. ResampleFactor ( time1, time2 );
  324. //resample input data,
  325. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  326. {
  327. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  328. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize )
  329. failure = true;
  330. }
  331. //and output data,
  332. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  333. {
  334. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  335. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize )
  336. failure = true;
  337. }
  338. //then write data to network
  339. //in case of failure, stop process
  340. if ( Write() == SOCKET_ERROR )
  341. return SOCKET_ERROR;
  342. //if there was any ringbuffer failure during resampling, reset
  343. if ( failure )
  344. {
  345. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  346. ResetRingBuffers();
  347. }
  348. return 0;
  349. }
  350. } // namespace Jack
  351. //loader------------------------------------------------------------------------------
  352. #ifdef __cplusplus
  353. extern "C"
  354. {
  355. #endif
  356. #include "driver_interface.h"
  357. #include "JackAudioAdapter.h"
  358. using namespace Jack;
  359. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  360. {
  361. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  362. strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  363. strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  364. desc->nparams = 9;
  365. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  366. int i = 0;
  367. strcpy ( desc->params[i].name, "multicast_ip" );
  368. desc->params[i].character = 'a';
  369. desc->params[i].type = JackDriverParamString;
  370. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  371. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  372. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  373. i++;
  374. strcpy ( desc->params[i].name, "udp_net_port" );
  375. desc->params[i].character = 'p';
  376. desc->params[i].type = JackDriverParamInt;
  377. desc->params[i].value.i = DEFAULT_PORT;
  378. strcpy ( desc->params[i].short_desc, "UDP port" );
  379. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  380. i++;
  381. strcpy ( desc->params[i].name, "mtu" );
  382. desc->params[i].character = 'M';
  383. desc->params[i].type = JackDriverParamInt;
  384. desc->params[i].value.i = DEFAULT_MTU;
  385. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  386. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  387. i++;
  388. strcpy ( desc->params[i].name, "input_ports" );
  389. desc->params[i].character = 'C';
  390. desc->params[i].type = JackDriverParamInt;
  391. desc->params[i].value.i = 2;
  392. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  393. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  394. i++;
  395. strcpy ( desc->params[i].name, "output_ports" );
  396. desc->params[i].character = 'P';
  397. desc->params[i].type = JackDriverParamInt;
  398. desc->params[i].value.i = 2;
  399. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  400. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  401. i++;
  402. strcpy ( desc->params[i].name, "client_name" );
  403. desc->params[i].character = 'n';
  404. desc->params[i].type = JackDriverParamString;
  405. strcpy ( desc->params[i].value.str, "'hostname'" );
  406. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  407. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  408. i++;
  409. strcpy ( desc->params[i].name, "transport_sync" );
  410. desc->params[i].character = 't';
  411. desc->params[i].type = JackDriverParamUInt;
  412. desc->params[i].value.ui = 1U;
  413. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  414. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  415. i++;
  416. strcpy ( desc->params[i].name, "mode" );
  417. desc->params[i].character = 'm';
  418. desc->params[i].type = JackDriverParamString;
  419. strcpy ( desc->params[i].value.str, "slow" );
  420. strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
  421. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  422. i++;
  423. strcpy(desc->params[i].name, "quality");
  424. desc->params[i].character = 'q';
  425. desc->params[i].type = JackDriverParamInt;
  426. desc->params[i].value.ui = 0;
  427. strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
  428. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  429. return desc;
  430. }
  431. SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  432. {
  433. jack_log ( "Loading netadapter" );
  434. Jack::JackAudioAdapter* adapter;
  435. jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
  436. jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
  437. try {
  438. adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( jack_client, buffer_size, sample_rate, params ) );
  439. assert ( adapter );
  440. if ( adapter->Open() == 0 )
  441. return 0;
  442. else
  443. {
  444. delete adapter;
  445. return 1;
  446. }
  447. } catch (...) {
  448. return 1;
  449. }
  450. }
  451. SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  452. {
  453. JSList* params = NULL;
  454. bool parse_params = true;
  455. int res = 1;
  456. jack_driver_desc_t* desc = jack_get_descriptor();
  457. Jack::JackArgParser parser ( load_init );
  458. if ( parser.GetArgc() > 0 )
  459. parse_params = parser.ParseParams ( desc, &params );
  460. if (parse_params) {
  461. res = jack_internal_initialize ( jack_client, params );
  462. parser.FreeParams ( params );
  463. }
  464. return res;
  465. }
  466. SERVER_EXPORT void jack_finish ( void* arg )
  467. {
  468. Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
  469. if (adapter) {
  470. jack_log ( "Unloading netadapter" );
  471. adapter->Close();
  472. delete adapter;
  473. }
  474. }
  475. #ifdef __cplusplus
  476. }
  477. #endif