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.

300 lines
9.9KB

  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. fRingbufferCurSize = param->value.ui;
  69. fAdaptative = false;
  70. break;
  71. }
  72. }
  73. fAudioInterface.setInputs ( fCaptureChannels );
  74. fAudioInterface.setOutputs ( fPlaybackChannels );
  75. }
  76. int JackAlsaAdapter::Open()
  77. {
  78. //open audio interface
  79. if ( fAudioInterface.open() )
  80. return -1;
  81. //start adapter thread
  82. if ( fThread.StartSync() < 0 )
  83. {
  84. jack_error ( "Cannot start audioadapter thread" );
  85. return -1;
  86. }
  87. //display card info
  88. fAudioInterface.longinfo();
  89. //turn the thread realtime
  90. fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority );
  91. return 0;
  92. }
  93. int JackAlsaAdapter::Close()
  94. {
  95. #ifdef JACK_MONITOR
  96. fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
  97. #endif
  98. switch ( fThread.GetStatus() )
  99. {
  100. // Kill the thread in Init phase
  101. case JackThread::kStarting:
  102. case JackThread::kIniting:
  103. if ( fThread.Kill() < 0 )
  104. {
  105. jack_error ( "Cannot kill thread" );
  106. return -1;
  107. }
  108. break;
  109. // Stop when the thread cycle is finished
  110. case JackThread::kRunning:
  111. if ( fThread.Stop() < 0 )
  112. {
  113. jack_error ( "Cannot stop thread" );
  114. return -1;
  115. }
  116. break;
  117. default:
  118. break;
  119. }
  120. return fAudioInterface.close();
  121. }
  122. bool JackAlsaAdapter::Init()
  123. {
  124. //fill the hardware buffers
  125. for ( unsigned int i = 0; i < fAudioInterface.fPeriod; i++ )
  126. fAudioInterface.write();
  127. return true;
  128. }
  129. bool JackAlsaAdapter::Execute()
  130. {
  131. //read data from audio interface
  132. if (fAudioInterface.read() < 0)
  133. return false;
  134. PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize);
  135. //write data to audio interface
  136. if (fAudioInterface.write() < 0)
  137. return false;
  138. return true;
  139. }
  140. int JackAlsaAdapter::SetSampleRate ( jack_nframes_t sample_rate )
  141. {
  142. JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
  143. Close();
  144. return Open();
  145. }
  146. int JackAlsaAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  147. {
  148. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  149. Close();
  150. return Open();
  151. }
  152. } // namespace
  153. #ifdef __cplusplus
  154. extern "C"
  155. {
  156. #endif
  157. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  158. {
  159. jack_driver_desc_t *desc;
  160. unsigned int i;
  161. desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  162. strcpy ( desc->name, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  163. strcpy ( desc->desc, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  164. desc->nparams = 11;
  165. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  166. i = 0;
  167. strcpy ( desc->params[i].name, "capture" );
  168. desc->params[i].character = 'C';
  169. desc->params[i].type = JackDriverParamString;
  170. strcpy ( desc->params[i].value.str, "none" );
  171. strcpy ( desc->params[i].short_desc,
  172. "Provide capture ports. Optionally set device" );
  173. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  174. i++;
  175. strcpy ( desc->params[i].name, "playback" );
  176. desc->params[i].character = 'P';
  177. desc->params[i].type = JackDriverParamString;
  178. strcpy ( desc->params[i].value.str, "none" );
  179. strcpy ( desc->params[i].short_desc,
  180. "Provide playback ports. Optionally set device" );
  181. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  182. i++;
  183. strcpy ( desc->params[i].name, "device" );
  184. desc->params[i].character = 'd';
  185. desc->params[i].type = JackDriverParamString;
  186. strcpy ( desc->params[i].value.str, "hw:0" );
  187. strcpy ( desc->params[i].short_desc, "ALSA device name" );
  188. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  189. i++;
  190. strcpy ( desc->params[i].name, "rate" );
  191. desc->params[i].character = 'r';
  192. desc->params[i].type = JackDriverParamUInt;
  193. desc->params[i].value.ui = 48000U;
  194. strcpy ( desc->params[i].short_desc, "Sample rate" );
  195. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  196. i++;
  197. strcpy ( desc->params[i].name, "periodsize" );
  198. desc->params[i].character = 'p';
  199. desc->params[i].type = JackDriverParamUInt;
  200. desc->params[i].value.ui = 512U;
  201. strcpy ( desc->params[i].short_desc, "Period size" );
  202. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  203. i++;
  204. strcpy ( desc->params[i].name, "nperiods" );
  205. desc->params[i].character = 'n';
  206. desc->params[i].type = JackDriverParamUInt;
  207. desc->params[i].value.ui = 2U;
  208. strcpy ( desc->params[i].short_desc, "Number of periods of playback latency" );
  209. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  210. i++;
  211. strcpy ( desc->params[i].name, "duplex" );
  212. desc->params[i].character = 'D';
  213. desc->params[i].type = JackDriverParamBool;
  214. desc->params[i].value.i = true;
  215. strcpy ( desc->params[i].short_desc,
  216. "Provide both capture and playback ports" );
  217. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  218. i++;
  219. strcpy ( desc->params[i].name, "inchannels" );
  220. desc->params[i].character = 'i';
  221. desc->params[i].type = JackDriverParamUInt;
  222. desc->params[i].value.i = 0;
  223. strcpy ( desc->params[i].short_desc,
  224. "Number of capture channels (defaults to hardware max)" );
  225. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  226. i++;
  227. strcpy ( desc->params[i].name, "outchannels" );
  228. desc->params[i].character = 'o';
  229. desc->params[i].type = JackDriverParamUInt;
  230. desc->params[i].value.i = 0;
  231. strcpy ( desc->params[i].short_desc,
  232. "Number of playback channels (defaults to hardware max)" );
  233. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  234. i++;
  235. strcpy(desc->params[i].name, "quality");
  236. desc->params[i].character = 'q';
  237. desc->params[i].type = JackDriverParamInt;
  238. desc->params[i].value.ui = 0;
  239. strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
  240. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  241. i++;
  242. strcpy(desc->params[i].name, "ring-buffer");
  243. desc->params[i].character = 'g';
  244. desc->params[i].type = JackDriverParamInt;
  245. desc->params[i].value.ui = 32768;
  246. strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
  247. strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
  248. return desc;
  249. }
  250. #ifdef __cplusplus
  251. }
  252. #endif