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.

242 lines
7.0KB

  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. namespace Jack
  20. {
  21. JackAlsaAdapter::JackAlsaAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
  22. :JackAudioAdapterInterface(buffer_size, sample_rate)
  23. ,fThread(this), fAudioInterface(GetInputs(), GetOutputs(), buffer_size, sample_rate)
  24. {
  25. const JSList* node;
  26. const jack_driver_param_t* param;
  27. fCaptureChannels = 2;
  28. fPlaybackChannels = 2;
  29. for (node = params; node; node = jack_slist_next(node)) {
  30. param = (const jack_driver_param_t*) node->data;
  31. switch (param->character) {
  32. case 'i':
  33. fCaptureChannels = param->value.ui;
  34. break;
  35. case 'o':
  36. fPlaybackChannels = param->value.ui;
  37. break;
  38. case 'C':
  39. break;
  40. case 'P':
  41. break;
  42. case 'D':
  43. break;
  44. case 'n':
  45. fAudioInterface.fPeriod = param->value.ui;
  46. break;
  47. case 'd':
  48. fAudioInterface.fCardName = strdup(param->value.str);
  49. break;
  50. case 'r':
  51. SetAudioSampleRate(param->value.ui);
  52. break;
  53. }
  54. }
  55. }
  56. int JackAlsaAdapter::Open()
  57. {
  58. if (fAudioInterface.open() == 0) {
  59. fAudioInterface.longinfo();
  60. fThread.AcquireRealTime(85);
  61. return fThread.StartSync();
  62. } else {
  63. return -1;
  64. }
  65. }
  66. int JackAlsaAdapter::Close()
  67. {
  68. #ifdef JACK_MONITOR
  69. fTable.Save();
  70. #endif
  71. fThread.Stop();
  72. return fAudioInterface.close();
  73. }
  74. bool JackAlsaAdapter::Init()
  75. {
  76. fAudioInterface.write();
  77. fAudioInterface.write();
  78. return true;
  79. }
  80. bool JackAlsaAdapter::Execute()
  81. {
  82. if (fAudioInterface.read() < 0)
  83. return false;
  84. bool failure = false;
  85. jack_nframes_t time1, time2;
  86. ResampleFactor(time1, time2);
  87. for (int i = 0; i < fCaptureChannels; i++) {
  88. fCaptureRingBuffer[i]->SetRatio(time1, time2);
  89. if (fCaptureRingBuffer[i]->WriteResample(fAudioInterface.fInputSoftChannels[i], fBufferSize) < fBufferSize)
  90. failure = true;
  91. }
  92. for (int i = 0; i < fPlaybackChannels; i++) {
  93. fPlaybackRingBuffer[i]->SetRatio(time2, time1);
  94. if (fPlaybackRingBuffer[i]->ReadResample(fAudioInterface.fOutputSoftChannels[i], fBufferSize) < fBufferSize)
  95. failure = true;
  96. }
  97. #ifdef JACK_MONITOR
  98. fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
  99. fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace());
  100. #endif
  101. if (fAudioInterface.write() < 0)
  102. return false;
  103. // Reset all ringbuffers in case of failure
  104. if (failure) {
  105. jack_error("JackAlsaAdapter::Execute ringbuffer failure... reset");
  106. ResetRingBuffers();
  107. }
  108. return true;
  109. }
  110. int JackAlsaAdapter::SetBufferSize(jack_nframes_t buffer_size)
  111. {
  112. JackAudioAdapterInterface::SetBufferSize(buffer_size);
  113. Close();
  114. return Open();
  115. }
  116. } // namespace
  117. #ifdef __cplusplus
  118. extern "C"
  119. {
  120. #endif
  121. EXPORT jack_driver_desc_t* jack_get_descriptor()
  122. {
  123. jack_driver_desc_t *desc;
  124. jack_driver_param_desc_t * params;
  125. unsigned int i;
  126. desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
  127. strcpy (desc->name, "alsa-adapter");
  128. desc->nparams = 8;
  129. params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
  130. i = 0;
  131. strcpy(params[i].name, "capture");
  132. params[i].character = 'C';
  133. params[i].type = JackDriverParamString;
  134. strcpy (params[i].value.str, "none");
  135. strcpy (params[i].short_desc,
  136. "Provide capture ports. Optionally set device");
  137. strcpy (params[i].long_desc, params[i].short_desc);
  138. i++;
  139. strcpy(params[i].name, "playback");
  140. params[i].character = 'P';
  141. params[i].type = JackDriverParamString;
  142. strcpy(params[i].value.str, "none");
  143. strcpy(params[i].short_desc,
  144. "Provide playback ports. Optionally set device");
  145. strcpy(params[i].long_desc, params[i].short_desc);
  146. i++;
  147. strcpy(params[i].name, "device");
  148. params[i].character = 'd';
  149. params[i].type = JackDriverParamString;
  150. strcpy(params[i].value.str, "hw:0");
  151. strcpy(params[i].short_desc, "ALSA device name");
  152. strcpy(params[i].long_desc, params[i].short_desc);
  153. i++;
  154. strcpy (params[i].name, "rate");
  155. params[i].character = 'r';
  156. params[i].type = JackDriverParamUInt;
  157. params[i].value.ui = 48000U;
  158. strcpy(params[i].short_desc, "Sample rate");
  159. strcpy(params[i].long_desc, params[i].short_desc);
  160. i++;
  161. strcpy(params[i].name, "nperiods");
  162. params[i].character = 'n';
  163. params[i].type = JackDriverParamUInt;
  164. params[i].value.ui = 2U;
  165. strcpy(params[i].short_desc, "Number of periods of playback latency");
  166. strcpy(params[i].long_desc, params[i].short_desc);
  167. i++;
  168. strcpy(params[i].name, "duplex");
  169. params[i].character = 'D';
  170. params[i].type = JackDriverParamBool;
  171. params[i].value.i = 1;
  172. strcpy(params[i].short_desc,
  173. "Provide both capture and playback ports");
  174. strcpy(params[i].long_desc, params[i].short_desc);
  175. i++;
  176. strcpy(params[i].name, "inchannels");
  177. params[i].character = 'i';
  178. params[i].type = JackDriverParamUInt;
  179. params[i].value.i = 0;
  180. strcpy(params[i].short_desc,
  181. "Number of capture channels (defaults to hardware max)");
  182. strcpy(params[i].long_desc, params[i].short_desc);
  183. i++;
  184. strcpy(params[i].name, "outchannels");
  185. params[i].character = 'o';
  186. params[i].type = JackDriverParamUInt;
  187. params[i].value.i = 0;
  188. strcpy(params[i].short_desc,
  189. "Number of playback channels (defaults to hardware max)");
  190. strcpy(params[i].long_desc, params[i].short_desc);
  191. desc->params = params;
  192. return desc;
  193. }
  194. #ifdef __cplusplus
  195. }
  196. #endif