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.

414 lines
13KB

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