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.

288 lines
8.1KB

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