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.

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