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.

332 lines
11KB

  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. #if defined(HAVE_CONFIG_H)
  16. #include "config.h"
  17. #endif
  18. #include "JackAlsaAdapter.h"
  19. #include "JackServerGlobals.h"
  20. #include "JackEngineControl.h"
  21. namespace Jack
  22. {
  23. JackAlsaAdapter::JackAlsaAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params ) :
  24. JackAudioAdapterInterface ( buffer_size, sample_rate ),
  25. fThread ( this ),
  26. fAudioInterface ( buffer_size, sample_rate )
  27. {
  28. const JSList* node;
  29. const jack_driver_param_t* param;
  30. fCaptureChannels = 2;
  31. fPlaybackChannels = 2;
  32. fAudioInterface.fPeriod = 2;
  33. for ( node = params; node; node = jack_slist_next ( node ) )
  34. {
  35. param = ( const jack_driver_param_t* ) node->data;
  36. switch ( param->character )
  37. {
  38. case 'i':
  39. fCaptureChannels = param->value.ui;
  40. break;
  41. case 'o':
  42. fPlaybackChannels = param->value.ui;
  43. break;
  44. case 'C':
  45. break;
  46. case 'P':
  47. break;
  48. case 'D':
  49. break;
  50. case 'n':
  51. fAudioInterface.fPeriod = param->value.ui;
  52. break;
  53. case 'd':
  54. fAudioInterface.fCardName = strdup ( param->value.str );
  55. break;
  56. case 'r':
  57. fAudioInterface.fFrequency = param->value.ui;
  58. SetAdaptedSampleRate ( param->value.ui );
  59. break;
  60. case 'p':
  61. fAudioInterface.fBuffering = param->value.ui;
  62. SetAdaptedBufferSize ( param->value.ui );
  63. break;
  64. case 'q':
  65. fQuality = param->value.ui;
  66. break;
  67. case 'g':
  68. fRingbufferSize = param->value.ui;
  69. break;
  70. }
  71. }
  72. fAudioInterface.setInputs ( fCaptureChannels );
  73. fAudioInterface.setOutputs ( fPlaybackChannels );
  74. }
  75. int JackAlsaAdapter::Open()
  76. {
  77. //open audio interface
  78. if ( fAudioInterface.open() )
  79. return -1;
  80. //start adapter thread
  81. if ( fThread.StartSync() < 0 )
  82. {
  83. jack_error ( "Cannot start audioadapter thread" );
  84. return -1;
  85. }
  86. //display card info
  87. fAudioInterface.longinfo();
  88. //turn the thread realtime
  89. fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority );
  90. return 0;
  91. }
  92. int JackAlsaAdapter::Close()
  93. {
  94. #ifdef JACK_MONITOR
  95. fTable.Save();
  96. #endif
  97. switch ( fThread.GetStatus() )
  98. {
  99. // Kill the thread in Init phase
  100. case JackThread::kStarting:
  101. case JackThread::kIniting:
  102. if ( fThread.Kill() < 0 )
  103. {
  104. jack_error ( "Cannot kill thread" );
  105. return -1;
  106. }
  107. break;
  108. // Stop when the thread cycle is finished
  109. case JackThread::kRunning:
  110. if ( fThread.Stop() < 0 )
  111. {
  112. jack_error ( "Cannot stop thread" );
  113. return -1;
  114. }
  115. break;
  116. default:
  117. break;
  118. }
  119. return fAudioInterface.close();
  120. }
  121. bool JackAlsaAdapter::Init()
  122. {
  123. //fill the hardware buffers
  124. for ( unsigned int i = 0; i < fAudioInterface.fPeriod; i++ )
  125. fAudioInterface.write();
  126. return true;
  127. }
  128. bool JackAlsaAdapter::Execute()
  129. {
  130. //read data from audio interface
  131. if ( fAudioInterface.read() < 0 )
  132. return false;
  133. bool failure = false;
  134. //compute resampling factor
  135. jack_time_t time1, time2;
  136. ResampleFactor ( time1, time2 );
  137. //resample inputs
  138. for ( int i = 0; i < fCaptureChannels; i++ )
  139. {
  140. fCaptureRingBuffer[i]->SetRatio ( time1, time2 );
  141. if ( fCaptureRingBuffer[i]->WriteResample ( fAudioInterface.fInputSoftChannels[i], fAdaptedBufferSize ) < fAdaptedBufferSize )
  142. failure = true;
  143. }
  144. //resample outputs
  145. for ( int i = 0; i < fPlaybackChannels; i++ )
  146. {
  147. fPlaybackRingBuffer[i]->SetRatio ( time2, time1 );
  148. if ( fPlaybackRingBuffer[i]->ReadResample ( fAudioInterface.fOutputSoftChannels[i], fAdaptedBufferSize ) < fAdaptedBufferSize )
  149. failure = true;
  150. }
  151. #ifdef JACK_MONITOR
  152. fTable.Write ( time1, time2, double ( time1 ) / double ( time2 ), double ( time2 ) / double ( time1 ),
  153. fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace() );
  154. #endif
  155. //write data to audio interface
  156. if ( fAudioInterface.write() < 0 )
  157. return false;
  158. //reset all ringbuffers in case of failure
  159. if ( failure )
  160. {
  161. jack_error ( "JackAlsaAdapter::Execute ringbuffer failure... reset" );
  162. ResetRingBuffers();
  163. }
  164. return true;
  165. }
  166. int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate )
  167. {
  168. JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
  169. Close();
  170. return Open();
  171. }
  172. int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  173. {
  174. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  175. Close();
  176. return Open();
  177. }
  178. } // namespace
  179. #ifdef __cplusplus
  180. extern "C"
  181. {
  182. #endif
  183. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  184. {
  185. jack_driver_desc_t *desc;
  186. unsigned int i;
  187. desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  188. strcpy ( desc->name, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  189. strcpy ( desc->desc, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  190. desc->nparams = 11;
  191. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  192. i = 0;
  193. strcpy ( desc->params[i].name, "capture" );
  194. desc->params[i].character = 'C';
  195. desc->params[i].type = JackDriverParamString;
  196. strcpy ( desc->params[i].value.str, "none" );
  197. strcpy ( desc->params[i].short_desc,
  198. "Provide capture ports. Optionally set device" );
  199. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  200. i++;
  201. strcpy ( desc->params[i].name, "playback" );
  202. desc->params[i].character = 'P';
  203. desc->params[i].type = JackDriverParamString;
  204. strcpy ( desc->params[i].value.str, "none" );
  205. strcpy ( desc->params[i].short_desc,
  206. "Provide playback ports. Optionally set device" );
  207. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  208. i++;
  209. strcpy ( desc->params[i].name, "device" );
  210. desc->params[i].character = 'd';
  211. desc->params[i].type = JackDriverParamString;
  212. strcpy ( desc->params[i].value.str, "hw:0" );
  213. strcpy ( desc->params[i].short_desc, "ALSA device name" );
  214. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  215. i++;
  216. strcpy ( desc->params[i].name, "rate" );
  217. desc->params[i].character = 'r';
  218. desc->params[i].type = JackDriverParamUInt;
  219. desc->params[i].value.ui = 48000U;
  220. strcpy ( desc->params[i].short_desc, "Sample rate" );
  221. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  222. i++;
  223. strcpy ( desc->params[i].name, "periodsize" );
  224. desc->params[i].character = 'p';
  225. desc->params[i].type = JackDriverParamUInt;
  226. desc->params[i].value.ui = 512U;
  227. strcpy ( desc->params[i].short_desc, "Period size" );
  228. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  229. i++;
  230. strcpy ( desc->params[i].name, "nperiods" );
  231. desc->params[i].character = 'n';
  232. desc->params[i].type = JackDriverParamUInt;
  233. desc->params[i].value.ui = 2U;
  234. strcpy ( desc->params[i].short_desc, "Number of periods of playback latency" );
  235. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  236. i++;
  237. strcpy ( desc->params[i].name, "duplex" );
  238. desc->params[i].character = 'D';
  239. desc->params[i].type = JackDriverParamBool;
  240. desc->params[i].value.i = 1;
  241. strcpy ( desc->params[i].short_desc,
  242. "Provide both capture and playback ports" );
  243. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  244. i++;
  245. strcpy ( desc->params[i].name, "inchannels" );
  246. desc->params[i].character = 'i';
  247. desc->params[i].type = JackDriverParamUInt;
  248. desc->params[i].value.i = 0;
  249. strcpy ( desc->params[i].short_desc,
  250. "Number of capture channels (defaults to hardware max)" );
  251. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  252. i++;
  253. strcpy ( desc->params[i].name, "outchannels" );
  254. desc->params[i].character = 'o';
  255. desc->params[i].type = JackDriverParamUInt;
  256. desc->params[i].value.i = 0;
  257. strcpy ( desc->params[i].short_desc,
  258. "Number of playback channels (defaults to hardware max)" );
  259. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  260. i++;
  261. strcpy(desc->params[i].name, "quality");
  262. desc->params[i].character = 'q';
  263. desc->params[i].type = JackDriverParamInt;
  264. desc->params[i].value.ui = 0;
  265. strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
  266. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  267. i++;
  268. strcpy(desc->params[i].name, "ring-buffer");
  269. desc->params[i].character = 'g';
  270. desc->params[i].type = JackDriverParamInt;
  271. desc->params[i].value.ui = 0;
  272. strcpy(desc->params[i].short_desc, "Resampling ringbuffer size in frames (default = 32768)");
  273. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  274. return desc;
  275. }
  276. #ifdef __cplusplus
  277. }
  278. #endif