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.

305 lines
9.4KB

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