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.

405 lines
12KB

  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 = 0;
  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. switch ( fParams.fSlaveSyncMode )
  139. {
  140. case true :
  141. return ProcessSync();
  142. case false :
  143. return ProcessAsync();
  144. }
  145. return true;
  146. }
  147. bool JackNetAdapter::ProcessSync()
  148. {
  149. bool failure = false;
  150. int port_index;
  151. //receive
  152. if ( SyncRecv() == SOCKET_ERROR )
  153. return true;
  154. if ( DataRecv() == SOCKET_ERROR )
  155. return false;
  156. //resample
  157. jack_nframes_t time1, time2;
  158. ResampleFactor ( time1, time2 );
  159. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  160. {
  161. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  162. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fBufferSize ) < fBufferSize )
  163. failure = true;
  164. }
  165. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  166. {
  167. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  168. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fBufferSize ) < fBufferSize )
  169. failure = true;
  170. }
  171. //send
  172. if ( SyncSend() == SOCKET_ERROR )
  173. return false;
  174. if ( failure )
  175. {
  176. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  177. ResetRingBuffers();
  178. }
  179. return true;
  180. }
  181. bool JackNetAdapter::ProcessAsync()
  182. {
  183. bool failure = false;
  184. int port_index;
  185. //receive
  186. if ( SyncRecv() == SOCKET_ERROR )
  187. return true;
  188. if ( DataRecv() == SOCKET_ERROR )
  189. return false;
  190. //send
  191. if ( SyncSend() == SOCKET_ERROR )
  192. return false;
  193. if ( failure )
  194. {
  195. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  196. ResetRingBuffers();
  197. }
  198. //resample
  199. jack_nframes_t time1, time2;
  200. ResampleFactor ( time1, time2 );
  201. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  202. {
  203. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  204. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fBufferSize ) < fBufferSize )
  205. failure = true;
  206. }
  207. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  208. {
  209. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  210. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fBufferSize ) < fBufferSize )
  211. failure = true;
  212. }
  213. return true;
  214. }
  215. } // namespace Jack
  216. #ifdef __cplusplus
  217. extern "C"
  218. {
  219. #endif
  220. #include "driver_interface.h"
  221. #include "JackAudioAdapter.h"
  222. using namespace Jack;
  223. EXPORT jack_driver_desc_t* jack_get_descriptor()
  224. {
  225. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  226. strcpy ( desc->name, "net" );
  227. desc->nparams = 9;
  228. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  229. int i = 0;
  230. strcpy ( desc->params[i].name, "multicast_ip" );
  231. desc->params[i].character = 'a';
  232. desc->params[i].type = JackDriverParamString;
  233. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  234. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  235. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  236. i++;
  237. strcpy ( desc->params[i].name, "udp_net_port" );
  238. desc->params[i].character = 'p';
  239. desc->params[i].type = JackDriverParamInt;
  240. desc->params[i].value.i = 19000;
  241. strcpy ( desc->params[i].short_desc, "UDP port" );
  242. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  243. i++;
  244. strcpy ( desc->params[i].name, "mtu" );
  245. desc->params[i].character = 'M';
  246. desc->params[i].type = JackDriverParamInt;
  247. desc->params[i].value.i = 1500;
  248. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  249. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  250. i++;
  251. strcpy ( desc->params[i].name, "input_ports" );
  252. desc->params[i].character = 'C';
  253. desc->params[i].type = JackDriverParamInt;
  254. desc->params[i].value.i = 2;
  255. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  256. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  257. i++;
  258. strcpy ( desc->params[i].name, "output_ports" );
  259. desc->params[i].character = 'P';
  260. desc->params[i].type = JackDriverParamInt;
  261. desc->params[i].value.i = 2;
  262. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  263. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  264. i++;
  265. strcpy ( desc->params[i].name, "client_name" );
  266. desc->params[i].character = 'n';
  267. desc->params[i].type = JackDriverParamString;
  268. strcpy ( desc->params[i].value.str, "'hostname'" );
  269. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  270. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  271. i++;
  272. strcpy ( desc->params[i].name, "transport_sync" );
  273. desc->params[i].character = 't';
  274. desc->params[i].type = JackDriverParamUInt;
  275. desc->params[i].value.ui = 1U;
  276. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  277. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  278. i++;
  279. strcpy ( desc->params[i].name, "fast_mode" );
  280. desc->params[i].character = 'f';
  281. desc->params[i].type = JackDriverParamString;
  282. strcpy ( desc->params[i].value.str, "" );
  283. strcpy ( desc->params[i].short_desc, "Fast mode allows a zero latency transmission." );
  284. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  285. i++;
  286. strcpy ( desc->params[i].name, "sync_mode" );
  287. desc->params[i].character = 'S';
  288. desc->params[i].type = JackDriverParamString;
  289. strcpy ( desc->params[i].value.str, "" );
  290. strcpy ( desc->params[i].short_desc, "Sync mode (same as driver's sync mode) ?" );
  291. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  292. return desc;
  293. }
  294. EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  295. {
  296. jack_log ( "Loading netadapter" );
  297. Jack::JackAudioAdapter* adapter;
  298. jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
  299. jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
  300. adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( buffer_size, sample_rate, params ) );
  301. assert ( adapter );
  302. if ( adapter->Open() == 0 )
  303. {
  304. return 0;
  305. }
  306. else
  307. {
  308. delete adapter;
  309. return 1;
  310. }
  311. }
  312. EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  313. {
  314. JSList* params = NULL;
  315. jack_driver_desc_t *desc = jack_get_descriptor();
  316. JackArgParser parser ( load_init );
  317. if ( parser.GetArgc() > 0 )
  318. {
  319. if ( parser.ParseParams ( desc, &params ) != 0 )
  320. jack_error ( "Internal client : JackArgParser::ParseParams error." );
  321. }
  322. return jack_internal_initialize ( jack_client, params );
  323. }
  324. EXPORT void jack_finish ( void* arg )
  325. {
  326. Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
  327. if ( adapter )
  328. {
  329. jack_log ( "Unloading netadapter" );
  330. adapter->Close();
  331. delete adapter;
  332. }
  333. }
  334. #ifdef __cplusplus
  335. }
  336. #endif