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.

372 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 ), JackNetSlaveInterface(), 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. uint port = 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 = sample_rate;
  39. fParams.fPeriodSize = buffer_size;
  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. if ( strlen ( param->value.str ) < 16 )
  52. strcpy ( fMulticastIP, param->value.str );
  53. else
  54. jack_error ( "Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP );
  55. break;
  56. case 'p' :
  57. fSocket.SetPort ( param->value.ui );
  58. break;
  59. case 'M' :
  60. fParams.fMtu = param->value.i;
  61. break;
  62. case 'C' :
  63. fParams.fSendAudioChannels = param->value.i;
  64. break;
  65. case 'P' :
  66. fParams.fReturnAudioChannels = param->value.i;
  67. break;
  68. case 'n' :
  69. strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE );
  70. break;
  71. case 't' :
  72. fParams.fTransportSync = param->value.ui;
  73. break;
  74. case 'm' :
  75. if ( strcmp ( param->value.str, "normal" ) == 0 )
  76. fParams.fNetworkMode = 'n';
  77. else if ( strcmp ( param->value.str, "slow" ) == 0 )
  78. fParams.fNetworkMode = 's';
  79. else if ( strcmp ( param->value.str, "fast" ) == 0 )
  80. fParams.fNetworkMode = 'f';
  81. else
  82. jack_error ( "Unknown network mode, using 'normal' mode." );
  83. break;
  84. case 'S' :
  85. fParams.fSlaveSyncMode = 1;
  86. break;
  87. }
  88. }
  89. fSocket.SetPort ( port );
  90. fSocket.SetAddress ( fMulticastIP, port );
  91. jack_info ( "netadapter : this %x", this );
  92. jack_info ( "netadapter : input %x", &fCaptureChannels );
  93. jack_info ( "netadapter : output %x", &fPlaybackChannels );
  94. SetInputs ( fParams.fSendAudioChannels );
  95. SetOutputs ( fParams.fReturnAudioChannels );
  96. fSoftCaptureBuffer = NULL;
  97. fSoftPlaybackBuffer = NULL;
  98. }
  99. JackNetAdapter::~JackNetAdapter()
  100. {
  101. int port_index;
  102. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  103. delete[] fSoftCaptureBuffer[port_index];
  104. delete[] fSoftCaptureBuffer;
  105. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  106. delete[] fSoftPlaybackBuffer[port_index];
  107. delete[] fSoftPlaybackBuffer;
  108. }
  109. int JackNetAdapter::Open()
  110. {
  111. jack_log ( "JackNetAdapter::Open" );
  112. jack_info ( "Net adapter started in %s mode %s Master's transport sync.",
  113. ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
  114. fThread.AcquireRealTime ( 85 );
  115. return fThread.StartSync();
  116. }
  117. int JackNetAdapter::Close()
  118. {
  119. fThread.Stop();
  120. fSocket.Close();
  121. return 0;
  122. }
  123. int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  124. {
  125. fParams.fPeriodSize = buffer_size;
  126. return 0;
  127. }
  128. bool JackNetAdapter::Init()
  129. {
  130. jack_log ( "JackNetAdapter::Init" );
  131. int port_index;
  132. //init network connection
  133. if ( !JackNetSlaveInterface::Init() )
  134. return false;
  135. //then set global parameters
  136. SetParams();
  137. //set buffers
  138. fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
  139. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  140. {
  141. fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  142. fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] );
  143. }
  144. fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
  145. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  146. {
  147. fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  148. fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] );
  149. }
  150. //init done, display parameters
  151. SessionParamsDisplay ( &fParams );
  152. return true;
  153. }
  154. bool JackNetAdapter::Execute()
  155. {
  156. bool failure = false;
  157. int port_index;
  158. //receive
  159. if ( SyncRecv() == SOCKET_ERROR )
  160. return true;
  161. if ( DataRecv() == SOCKET_ERROR )
  162. return false;
  163. //resample
  164. jack_nframes_t time1, time2;
  165. ResampleFactor ( time1, time2 );
  166. for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
  167. {
  168. fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 );
  169. if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fBufferSize ) < fBufferSize )
  170. failure = true;
  171. }
  172. for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
  173. {
  174. fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 );
  175. if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fBufferSize ) < fBufferSize )
  176. failure = true;
  177. }
  178. //send
  179. if ( SyncSend() == SOCKET_ERROR )
  180. return false;
  181. if ( DataSend() == SOCKET_ERROR )
  182. return false;
  183. if ( failure )
  184. {
  185. jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." );
  186. ResetRingBuffers();
  187. }
  188. return true;
  189. }
  190. } // namespace Jack
  191. #ifdef __cplusplus
  192. extern "C"
  193. {
  194. #endif
  195. #include "driver_interface.h"
  196. #include "JackAudioAdapter.h"
  197. using namespace Jack;
  198. EXPORT jack_driver_desc_t* jack_get_descriptor()
  199. {
  200. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  201. strcpy ( desc->name, "net" );
  202. desc->nparams = 9;
  203. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  204. int i = 0;
  205. strcpy ( desc->params[i].name, "multicast_ip" );
  206. desc->params[i].character = 'a';
  207. desc->params[i].type = JackDriverParamString;
  208. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  209. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  210. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  211. i++;
  212. strcpy ( desc->params[i].name, "udp_net_port" );
  213. desc->params[i].character = 'p';
  214. desc->params[i].type = JackDriverParamInt;
  215. desc->params[i].value.i = 19000;
  216. strcpy ( desc->params[i].short_desc, "UDP port" );
  217. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  218. i++;
  219. strcpy ( desc->params[i].name, "mtu" );
  220. desc->params[i].character = 'M';
  221. desc->params[i].type = JackDriverParamInt;
  222. desc->params[i].value.i = 1500;
  223. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  224. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  225. i++;
  226. strcpy ( desc->params[i].name, "input_ports" );
  227. desc->params[i].character = 'C';
  228. desc->params[i].type = JackDriverParamInt;
  229. desc->params[i].value.i = 2;
  230. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  231. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  232. i++;
  233. strcpy ( desc->params[i].name, "output_ports" );
  234. desc->params[i].character = 'P';
  235. desc->params[i].type = JackDriverParamInt;
  236. desc->params[i].value.i = 2;
  237. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  238. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  239. i++;
  240. strcpy ( desc->params[i].name, "client_name" );
  241. desc->params[i].character = 'n';
  242. desc->params[i].type = JackDriverParamString;
  243. strcpy ( desc->params[i].value.str, "'hostname'" );
  244. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  245. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  246. i++;
  247. strcpy ( desc->params[i].name, "transport_sync" );
  248. desc->params[i].character = 't';
  249. desc->params[i].type = JackDriverParamUInt;
  250. desc->params[i].value.ui = 1U;
  251. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  252. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  253. i++;
  254. strcpy ( desc->params[i].name, "mode" );
  255. desc->params[i].character = 'm';
  256. desc->params[i].type = JackDriverParamString;
  257. strcpy ( desc->params[i].value.str, "normal" );
  258. strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
  259. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  260. i++;
  261. strcpy ( desc->params[i].name, "sync_mode" );
  262. desc->params[i].character = 'S';
  263. desc->params[i].type = JackDriverParamString;
  264. strcpy ( desc->params[i].value.str, "" );
  265. strcpy ( desc->params[i].short_desc, "Sync mode (same as driver's sync mode) ?" );
  266. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  267. return desc;
  268. }
  269. EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
  270. {
  271. jack_log ( "Loading netadapter" );
  272. Jack::JackAudioAdapter* adapter;
  273. jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
  274. jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
  275. adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( buffer_size, sample_rate, params ) );
  276. assert ( adapter );
  277. if ( adapter->Open() == 0 )
  278. return 0;
  279. else
  280. {
  281. delete adapter;
  282. return 1;
  283. }
  284. }
  285. EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
  286. {
  287. JSList* params = NULL;
  288. jack_driver_desc_t *desc = jack_get_descriptor();
  289. JackArgParser parser ( load_init );
  290. if ( parser.GetArgc() > 0 )
  291. if ( parser.ParseParams ( desc, &params ) != 0 )
  292. jack_error ( "Internal client : JackArgParser::ParseParams error." );
  293. return jack_internal_initialize ( jack_client, params );
  294. }
  295. EXPORT void jack_finish ( void* arg )
  296. {
  297. Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
  298. if ( adapter )
  299. {
  300. jack_log ( "Unloading netadapter" );
  301. adapter->Close();
  302. delete adapter;
  303. }
  304. }
  305. #ifdef __cplusplus
  306. }
  307. #endif