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.

450 lines
15KB

  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 "JackServer.h"
  18. #include "JackEngineControl.h"
  19. #define DEFAULT_MULTICAST_IP "225.3.19.154"
  20. #define DEFAULT_PORT 19000
  21. namespace Jack
  22. {
  23. JackNetAdapter::JackNetAdapter ( 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. if ( SocketAPIInit() < 0 )
  28. jack_error ( "Can't init Socket API, exiting..." );
  29. //global parametering
  30. fMulticastIP = new char[16];
  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 = 1500;
  36. fParams.fTransportSync = 1;
  37. fParams.fSendAudioChannels = 2;
  38. fParams.fReturnAudioChannels = 2;
  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 = 'n';
  45. //options parsing
  46. const JSList* node;
  47. const jack_driver_param_t* param;
  48. for ( node = params; node; node = jack_slist_next ( node ) )
  49. {
  50. param = ( const jack_driver_param_t* ) node->data;
  51. switch ( param->character )
  52. {
  53. case 'a' :
  54. if ( strlen ( param->value.str ) < 16 )
  55. strcpy ( fMulticastIP, param->value.str );
  56. else
  57. jack_error ( "Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP );
  58. break;
  59. case 'p' :
  60. fSocket.SetPort ( param->value.ui );
  61. break;
  62. case 'M' :
  63. fParams.fMtu = param->value.i;
  64. break;
  65. case 'C' :
  66. fParams.fSendAudioChannels = param->value.i;
  67. break;
  68. case 'P' :
  69. fParams.fReturnAudioChannels = param->value.i;
  70. break;
  71. case 'n' :
  72. strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE );
  73. break;
  74. case 't' :
  75. fParams.fTransportSync = param->value.ui;
  76. break;
  77. case 'm' :
  78. if ( strcmp ( param->value.str, "normal" ) == 0 )
  79. fParams.fNetworkMode = 'n';
  80. else if ( strcmp ( param->value.str, "slow" ) == 0 )
  81. fParams.fNetworkMode = 's';
  82. else if ( strcmp ( param->value.str, "fast" ) == 0 )
  83. fParams.fNetworkMode = 'f';
  84. else
  85. jack_error ( "Unknown network mode, using 'normal' mode." );
  86. break;
  87. case 'S' :
  88. fParams.fSlaveSyncMode = 1;
  89. break;
  90. }
  91. }
  92. fSocket.SetPort ( port );
  93. fSocket.SetAddress ( fMulticastIP, port );
  94. SetInputs ( fParams.fSendAudioChannels );
  95. SetOutputs ( fParams.fReturnAudioChannels );
  96. fSoftCaptureBuffer = NULL;
  97. fSoftPlaybackBuffer = NULL;
  98. }
  99. JackNetAdapter::~JackNetAdapter()
  100. {
  101. jack_log ( "JackNetAdapter::~JackNetAdapter" );
  102. int port_index;
  103. if ( fSoftCaptureBuffer )
  104. {
  105. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  106. delete[] fSoftCaptureBuffer[port_index];
  107. delete[] fSoftCaptureBuffer;
  108. }
  109. if ( fSoftPlaybackBuffer )
  110. {
  111. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  112. delete[] fSoftPlaybackBuffer[port_index];
  113. delete[] fSoftPlaybackBuffer;
  114. }
  115. }
  116. int JackNetAdapter::Open()
  117. {
  118. jack_log ( "JackNetAdapter::Open" );
  119. jack_info ( "Net adapter started in %s mode %s Master's transport sync.",
  120. ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
  121. if ( fThread.StartSync() < 0 )
  122. {
  123. jack_error ( "Cannot start netadapter thread" );
  124. return -1;
  125. }
  126. fThread.AcquireRealTime ( JackServer::fInstance->GetEngineControl()->fPriority - 1 );
  127. return 0;
  128. }
  129. int JackNetAdapter::Close()
  130. {
  131. jack_log ( "JackNetAdapter::Close" );
  132. switch ( fThread.GetStatus() )
  133. {
  134. // Kill the thread in Init phase
  135. case JackThread::kStarting:
  136. case JackThread::kIniting:
  137. if ( fThread.Kill() < 0 )
  138. {
  139. jack_error ( "Cannot kill thread" );
  140. return -1;
  141. }
  142. break;
  143. // Stop when the thread cycle is finished
  144. case JackThread::kRunning:
  145. if ( fThread.Stop() < 0 )
  146. {
  147. jack_error ( "Cannot stop thread" );
  148. return -1;
  149. }
  150. break;
  151. default:
  152. break;
  153. }
  154. fSocket.Close();
  155. return 0;
  156. }
  157. int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  158. {
  159. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  160. return 0;
  161. }
  162. bool JackNetAdapter::Init()
  163. {
  164. jack_log ( "JackNetAdapter::Init" );
  165. int port_index;
  166. //init network connection
  167. if ( !JackNetSlaveInterface::Init() )
  168. return false;
  169. //then set global parameters
  170. SetParams();
  171. //set buffers
  172. fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
  173. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  174. {
  175. fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  176. fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] );
  177. }
  178. fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
  179. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  180. {
  181. fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  182. fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] );
  183. }
  184. //set audio adapter parameters
  185. SetAdaptedBufferSize ( fParams.fPeriodSize );
  186. SetAdaptedSampleRate ( fParams.fSampleRate );
  187. //init done, display parameters
  188. SessionParamsDisplay ( &fParams );
  189. return true;
  190. }
  191. bool JackNetAdapter::Execute()
  192. {
  193. try
  194. {
  195. // Keep running even in case of error
  196. while ( fThread.GetStatus() == JackThread::kRunning )
  197. if ( Process() == SOCKET_ERROR )
  198. return false;
  199. return false;
  200. }
  201. catch ( JackNetException& e )
  202. {
  203. e.PrintMessage();
  204. jack_log ( "NetAdapter is restarted." );
  205. fThread.DropRealTime();
  206. fThread.SetStatus ( JackThread::kIniting );
  207. if ( Init() )
  208. {
  209. fThread.SetStatus ( JackThread::kRunning );
  210. return true;
  211. }
  212. else
  213. return false;
  214. }
  215. }
  216. int JackNetAdapter::Read()
  217. {
  218. if ( SyncRecv() == SOCKET_ERROR )
  219. return 0;
  220. return DataRecv();
  221. }
  222. int JackNetAdapter::Write()
  223. {
  224. if ( SyncSend() == SOCKET_ERROR )
  225. return SOCKET_ERROR;
  226. return DataSend();
  227. }
  228. int JackNetAdapter::Process()
  229. {
  230. bool failure = false;
  231. int port_index;
  232. //read data from the network
  233. //in case of fatal network error, stop the process
  234. if ( Read() == SOCKET_ERROR )
  235. return SOCKET_ERROR;
  236. //get the resample factor,
  237. jack_nframes_t time1, time2;
  238. ResampleFactor ( time1, time2 );
  239. //resample input data,
  240. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  241. {
  242. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  243. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize )
  244. failure = true;
  245. }
  246. //and output data,
  247. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  248. {
  249. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  250. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize )
  251. failure = true;
  252. }
  253. //then write data to network
  254. //in case of failure, stop process
  255. if ( Write() == SOCKET_ERROR )
  256. return SOCKET_ERROR;
  257. //if there was any ringbuffer failure during resampling, reset
  258. if ( failure )
  259. {
  260. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  261. ResetRingBuffers();
  262. }
  263. return true;
  264. }
  265. } // namespace Jack
  266. #ifdef __cplusplus
  267. extern "C"
  268. {
  269. #endif
  270. #include "driver_interface.h"
  271. #include "JackAudioAdapter.h"
  272. using namespace Jack;
  273. EXPORT jack_driver_desc_t* jack_get_descriptor()
  274. {
  275. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  276. strcpy ( desc->name, "net" );
  277. desc->nparams = 9;
  278. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  279. int i = 0;
  280. strcpy ( desc->params[i].name, "multicast_ip" );
  281. desc->params[i].character = 'a';
  282. desc->params[i].type = JackDriverParamString;
  283. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  284. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  285. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  286. i++;
  287. strcpy ( desc->params[i].name, "udp_net_port" );
  288. desc->params[i].character = 'p';
  289. desc->params[i].type = JackDriverParamInt;
  290. desc->params[i].value.i = 19000;
  291. strcpy ( desc->params[i].short_desc, "UDP port" );
  292. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  293. i++;
  294. strcpy ( desc->params[i].name, "mtu" );
  295. desc->params[i].character = 'M';
  296. desc->params[i].type = JackDriverParamInt;
  297. desc->params[i].value.i = 1500;
  298. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  299. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  300. i++;
  301. strcpy ( desc->params[i].name, "input_ports" );
  302. desc->params[i].character = 'C';
  303. desc->params[i].type = JackDriverParamInt;
  304. desc->params[i].value.i = 2;
  305. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  306. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  307. i++;
  308. strcpy ( desc->params[i].name, "output_ports" );
  309. desc->params[i].character = 'P';
  310. desc->params[i].type = JackDriverParamInt;
  311. desc->params[i].value.i = 2;
  312. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  313. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  314. i++;
  315. strcpy ( desc->params[i].name, "client_name" );
  316. desc->params[i].character = 'n';
  317. desc->params[i].type = JackDriverParamString;
  318. strcpy ( desc->params[i].value.str, "'hostname'" );
  319. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  320. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  321. i++;
  322. strcpy ( desc->params[i].name, "transport_sync" );
  323. desc->params[i].character = 't';
  324. desc->params[i].type = JackDriverParamUInt;
  325. desc->params[i].value.ui = 1U;
  326. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  327. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  328. i++;
  329. strcpy ( desc->params[i].name, "mode" );
  330. desc->params[i].character = 'm';
  331. desc->params[i].type = JackDriverParamString;
  332. strcpy ( desc->params[i].value.str, "normal" );
  333. strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
  334. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  335. i++;
  336. strcpy ( desc->params[i].name, "sync_mode" );
  337. desc->params[i].character = 'S';
  338. desc->params[i].type = JackDriverParamString;
  339. strcpy ( desc->params[i].value.str, "" );
  340. strcpy ( desc->params[i].short_desc, "Sync mode (same as driver's sync mode) ?" );
  341. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  342. return desc;
  343. }
  344. EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  345. {
  346. jack_log ( "Loading netadapter" );
  347. Jack::JackAudioAdapter* adapter;
  348. jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
  349. jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
  350. adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( buffer_size, sample_rate, params ) );
  351. assert ( adapter );
  352. if ( adapter->Open() == 0 )
  353. return 0;
  354. else
  355. {
  356. delete adapter;
  357. return 1;
  358. }
  359. }
  360. EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  361. {
  362. JSList* params = NULL;
  363. jack_driver_desc_t *desc = jack_get_descriptor();
  364. JackArgParser parser ( load_init );
  365. if ( parser.GetArgc() > 0 )
  366. if ( parser.ParseParams ( desc, &params ) != 0 )
  367. jack_error ( "Internal client : JackArgParser::ParseParams error." );
  368. return jack_internal_initialize ( jack_client, params );
  369. }
  370. EXPORT void jack_finish ( void* arg )
  371. {
  372. Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
  373. if ( adapter )
  374. {
  375. jack_log ( "Unloading netadapter" );
  376. adapter->Close();
  377. delete adapter;
  378. }
  379. }
  380. #ifdef __cplusplus
  381. }
  382. #endif