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.

421 lines
14KB

  1. /*
  2. Copyright (C) 2008 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. #define DEFAULT_MULTICAST_IP "225.3.19.154"
  17. #define DEFAULT_PORT 19000
  18. namespace Jack
  19. {
  20. JackNetAdapter::JackNetAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
  21. : JackAudioAdapterInterface ( buffer_size, sample_rate ), fThread ( this )
  22. {
  23. jack_log ( "JackNetAdapter::JackNetAdapter" );
  24. if ( SocketAPIInit() < 0 )
  25. jack_error ( "Can't init Socket API, exiting..." );
  26. //global parametering
  27. fMulticastIP = new char[16];
  28. strcpy ( fMulticastIP, DEFAULT_MULTICAST_IP );
  29. fSocket.SetPort ( DEFAULT_PORT );
  30. GetHostName ( fParams.fName, JACK_CLIENT_NAME_SIZE );
  31. fSocket.GetName ( fParams.fSlaveNetName );
  32. fParams.fMtu = 1500;
  33. fParams.fTransportSync = 1;
  34. fParams.fSendAudioChannels = 2;
  35. fParams.fReturnAudioChannels = 2;
  36. fParams.fSendMidiChannels = 0;
  37. fParams.fReturnMidiChannels = 0;
  38. fParams.fSampleRate = 48000;
  39. fParams.fPeriodSize = 128;
  40. fParams.fSlaveSyncMode = 1;
  41. fParams.fNetworkMode = 'n';
  42. //options parsing
  43. const JSList* node;
  44. const jack_driver_param_t* param;
  45. for ( node = params; node; node = jack_slist_next ( node ) )
  46. {
  47. param = ( const jack_driver_param_t* ) node->data;
  48. switch ( param->character )
  49. {
  50. case 'a' :
  51. fMulticastIP = strdup ( param->value.str );
  52. break;
  53. case 'p':
  54. fSocket.SetPort ( param->value.ui );
  55. break;
  56. case 'M':
  57. fParams.fMtu = param->value.i;
  58. break;
  59. case 'C':
  60. fParams.fSendAudioChannels = param->value.i;
  61. break;
  62. case 'P':
  63. fParams.fReturnAudioChannels = param->value.i;
  64. break;
  65. case 'n' :
  66. strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE );
  67. break;
  68. case 't' :
  69. fParams.fTransportSync = param->value.ui;
  70. break;
  71. case 'm' :
  72. if ( strcmp ( param->value.str, "normal" ) == 0 )
  73. fParams.fNetworkMode = 'n';
  74. else if ( strcmp ( param->value.str, "slow" ) == 0 )
  75. fParams.fNetworkMode = 's';
  76. else if ( strcmp ( param->value.str, "fast" ) == 0 )
  77. fParams.fNetworkMode = 'f';
  78. else
  79. jack_error ( "Unknown network mode, using 'normal' mode." );
  80. break;
  81. case 'S' :
  82. fParams.fSlaveSyncMode = 1;
  83. }
  84. }
  85. fCaptureChannels = fParams.fSendAudioChannels;
  86. fPlaybackChannels = fParams.fReturnAudioChannels;
  87. fSoftCaptureBuffer = NULL;
  88. fSoftPlaybackBuffer = NULL;
  89. }
  90. JackNetAdapter::~JackNetAdapter()
  91. {
  92. int port_index;
  93. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  94. delete[] fSoftCaptureBuffer[port_index];
  95. delete[] fSoftCaptureBuffer;
  96. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  97. delete[] fSoftPlaybackBuffer[port_index];
  98. delete[] fSoftPlaybackBuffer;
  99. }
  100. int JackNetAdapter::Open()
  101. {
  102. jack_log ( "JackNetAdapter::Open()" );
  103. int port_index;
  104. //display some additional infos
  105. jack_info ( "Net adapter started in %s mode %s Master's transport sync.",
  106. ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
  107. //init network connection
  108. if ( !JackNetSlaveInterface::Init() )
  109. return -1;
  110. //then set global parameters
  111. SetParams();
  112. //set buffers
  113. fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
  114. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  115. {
  116. fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  117. fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] );
  118. }
  119. fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
  120. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  121. {
  122. fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  123. fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] );
  124. }
  125. fThread.AcquireRealTime ( 85 );
  126. return fThread.StartSync();
  127. }
  128. int JackNetAdapter::Close()
  129. {
  130. fSocket.Close();
  131. return 0;
  132. }
  133. int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  134. {
  135. fParams.fPeriodSize = buffer_size;
  136. return 0;
  137. }
  138. bool JackNetAdapter::Init()
  139. {
  140. jack_info ( "Starting NetAdapter." );
  141. return true;
  142. }
  143. bool JackNetAdapter::Execute()
  144. {
  145. //the sync mode is the equivalent of driver sync mode : data are sent back right after being computed
  146. //TODO : verify async mode is appropriate here, because of the ringbuffer usage
  147. switch ( fParams.fSlaveSyncMode )
  148. {
  149. case true :
  150. return ProcessSync();
  151. case false :
  152. return ProcessAsync();
  153. }
  154. return true;
  155. }
  156. bool JackNetAdapter::ProcessSync()
  157. {
  158. bool failure = false;
  159. int port_index;
  160. //receive
  161. if ( SyncRecv() == SOCKET_ERROR )
  162. return true;
  163. if ( DataRecv() == SOCKET_ERROR )
  164. return false;
  165. //resample
  166. jack_nframes_t time1, time2;
  167. ResampleFactor ( time1, time2 );
  168. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  169. {
  170. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  171. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fBufferSize ) < fBufferSize )
  172. failure = true;
  173. }
  174. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  175. {
  176. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  177. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fBufferSize ) < fBufferSize )
  178. failure = true;
  179. }
  180. //send
  181. if ( SyncSend() == SOCKET_ERROR )
  182. return false;
  183. if ( DataSend() == SOCKET_ERROR )
  184. return false;
  185. if ( failure )
  186. {
  187. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  188. ResetRingBuffers();
  189. }
  190. return true;
  191. }
  192. bool JackNetAdapter::ProcessAsync()
  193. {
  194. bool failure = false;
  195. int port_index;
  196. //receive
  197. if ( SyncRecv() == SOCKET_ERROR )
  198. return true;
  199. if ( DataRecv() == SOCKET_ERROR )
  200. return false;
  201. //send
  202. if ( SyncSend() == SOCKET_ERROR )
  203. return false;
  204. if ( DataSend() == SOCKET_ERROR )
  205. return false;
  206. if ( failure )
  207. {
  208. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  209. ResetRingBuffers();
  210. }
  211. //resample
  212. jack_nframes_t time1, time2;
  213. ResampleFactor ( time1, time2 );
  214. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  215. {
  216. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  217. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fBufferSize ) < fBufferSize )
  218. failure = true;
  219. }
  220. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  221. {
  222. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  223. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fBufferSize ) < fBufferSize )
  224. failure = true;
  225. }
  226. return true;
  227. }
  228. } // namespace Jack
  229. #ifdef __cplusplus
  230. extern "C"
  231. {
  232. #endif
  233. #include "driver_interface.h"
  234. #include "JackAudioAdapter.h"
  235. using namespace Jack;
  236. EXPORT jack_driver_desc_t* jack_get_descriptor()
  237. {
  238. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  239. strcpy ( desc->name, "net" );
  240. desc->nparams = 9;
  241. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  242. int i = 0;
  243. strcpy ( desc->params[i].name, "multicast_ip" );
  244. desc->params[i].character = 'a';
  245. desc->params[i].type = JackDriverParamString;
  246. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  247. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  248. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  249. i++;
  250. strcpy ( desc->params[i].name, "udp_net_port" );
  251. desc->params[i].character = 'p';
  252. desc->params[i].type = JackDriverParamInt;
  253. desc->params[i].value.i = 19000;
  254. strcpy ( desc->params[i].short_desc, "UDP port" );
  255. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  256. i++;
  257. strcpy ( desc->params[i].name, "mtu" );
  258. desc->params[i].character = 'M';
  259. desc->params[i].type = JackDriverParamInt;
  260. desc->params[i].value.i = 1500;
  261. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  262. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  263. i++;
  264. strcpy ( desc->params[i].name, "input_ports" );
  265. desc->params[i].character = 'C';
  266. desc->params[i].type = JackDriverParamInt;
  267. desc->params[i].value.i = 2;
  268. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  269. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  270. i++;
  271. strcpy ( desc->params[i].name, "output_ports" );
  272. desc->params[i].character = 'P';
  273. desc->params[i].type = JackDriverParamInt;
  274. desc->params[i].value.i = 2;
  275. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  276. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  277. i++;
  278. strcpy ( desc->params[i].name, "client_name" );
  279. desc->params[i].character = 'n';
  280. desc->params[i].type = JackDriverParamString;
  281. strcpy ( desc->params[i].value.str, "'hostname'" );
  282. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  283. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  284. i++;
  285. strcpy ( desc->params[i].name, "transport_sync" );
  286. desc->params[i].character = 't';
  287. desc->params[i].type = JackDriverParamUInt;
  288. desc->params[i].value.ui = 1U;
  289. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  290. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  291. i++;
  292. strcpy ( desc->params[i].name, "mode" );
  293. desc->params[i].character = 'm';
  294. desc->params[i].type = JackDriverParamString;
  295. strcpy ( desc->params[i].value.str, "normal" );
  296. strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
  297. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  298. i++;
  299. strcpy ( desc->params[i].name, "sync_mode" );
  300. desc->params[i].character = 'S';
  301. desc->params[i].type = JackDriverParamString;
  302. strcpy ( desc->params[i].value.str, "" );
  303. strcpy ( desc->params[i].short_desc, "Sync mode (same as driver's sync mode) ?" );
  304. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  305. return desc;
  306. }
  307. EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  308. {
  309. jack_log ( "Loading netadapter" );
  310. Jack::JackAudioAdapter* adapter;
  311. jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
  312. jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
  313. adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( buffer_size, sample_rate, params ) );
  314. assert ( adapter );
  315. if ( adapter->Open() == 0 )
  316. {
  317. return 0;
  318. }
  319. else
  320. {
  321. delete adapter;
  322. return 1;
  323. }
  324. }
  325. EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  326. {
  327. JSList* params = NULL;
  328. jack_driver_desc_t *desc = jack_get_descriptor();
  329. JackArgParser parser ( load_init );
  330. if ( parser.GetArgc() > 0 )
  331. {
  332. if ( parser.ParseParams ( desc, &params ) != 0 )
  333. jack_error ( "Internal client : JackArgParser::ParseParams error." );
  334. }
  335. return jack_internal_initialize ( jack_client, params );
  336. }
  337. EXPORT void jack_finish ( void* arg )
  338. {
  339. Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
  340. if ( adapter )
  341. {
  342. jack_log ( "Unloading netadapter" );
  343. adapter->Close();
  344. delete adapter;
  345. }
  346. }
  347. #ifdef __cplusplus
  348. }
  349. #endif