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.

306 lines
9.5KB

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