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.

317 lines
12KB

  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 "JackPortAudioAdapter.h"
  19. #include "JackError.h"
  20. namespace Jack
  21. {
  22. int JackPortAudioAdapter::Render(const void* inputBuffer,
  23. void* outputBuffer,
  24. unsigned long framesPerBuffer,
  25. const PaStreamCallbackTimeInfo* timeInfo,
  26. PaStreamCallbackFlags statusFlags,
  27. void* userData)
  28. {
  29. JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData);
  30. adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, framesPerBuffer);
  31. return paContinue;
  32. }
  33. JackPortAudioAdapter::JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
  34. : JackAudioAdapterInterface ( buffer_size, sample_rate )
  35. {
  36. jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate );
  37. const JSList* node;
  38. const jack_driver_param_t* param;
  39. int in_max = 0;
  40. int out_max = 0;
  41. fInputDevice = Pa_GetDefaultInputDevice();
  42. fOutputDevice = Pa_GetDefaultOutputDevice();
  43. for (node = params; node; node = jack_slist_next(node))
  44. {
  45. param = (const jack_driver_param_t*) node->data;
  46. switch (param->character)
  47. {
  48. case 'i' :
  49. fCaptureChannels = param->value.ui;
  50. break;
  51. case 'o' :
  52. fPlaybackChannels = param->value.ui;
  53. break;
  54. case 'C' :
  55. if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 )
  56. {
  57. jack_error ( "Can't use %s, taking default input device", param->value.str );
  58. fInputDevice = Pa_GetDefaultInputDevice();
  59. }
  60. break;
  61. case 'P' :
  62. if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 )
  63. {
  64. jack_error ( "Can't use %s, taking default output device", param->value.str );
  65. fOutputDevice = Pa_GetDefaultOutputDevice();
  66. }
  67. break;
  68. case 'r' :
  69. SetAdaptedSampleRate ( param->value.ui );
  70. break;
  71. case 'p' :
  72. SetAdaptedBufferSize ( param->value.ui );
  73. break;
  74. case 'd' :
  75. if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 )
  76. jack_error ( "Can't use %s, taking default input device", param->value.str );
  77. if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 )
  78. jack_error ( "Can't use %s, taking default output device", param->value.str );
  79. break;
  80. case 'l' :
  81. fPaDevices.DisplayDevicesNames();
  82. break;
  83. case 'q':
  84. fQuality = param->value.ui;
  85. break;
  86. case 'g':
  87. fRingbufferCurSize = param->value.ui;
  88. fAdaptative = false;
  89. break;
  90. }
  91. }
  92. //max channels
  93. if ( in_max == 0 && fInputDevice != paNoDevice)
  94. in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels;
  95. if ( out_max == 0 && fOutputDevice != paNoDevice)
  96. out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels;
  97. //effective channels
  98. if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
  99. fCaptureChannels = in_max;
  100. if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
  101. fPlaybackChannels = out_max;
  102. //set adapter interface channels
  103. SetInputs ( fCaptureChannels );
  104. SetOutputs ( fPlaybackChannels );
  105. }
  106. int JackPortAudioAdapter::Open()
  107. {
  108. PaError err;
  109. PaStreamParameters inputParameters;
  110. PaStreamParameters outputParameters;
  111. if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) {
  112. jack_error("No input and output device!!");
  113. return -1;
  114. }
  115. if ( JackAudioAdapterInterface::Open() < 0 )
  116. return -1;
  117. jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
  118. jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
  119. jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate);
  120. inputParameters.device = fInputDevice;
  121. inputParameters.channelCount = fCaptureChannels;
  122. inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  123. inputParameters.suggestedLatency = ( fInputDevice != paNoDevice ) // TODO: check how to setup this on ASIO
  124. ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
  125. : 0;
  126. inputParameters.hostApiSpecificStreamInfo = NULL;
  127. outputParameters.device = fOutputDevice;
  128. outputParameters.channelCount = fPlaybackChannels;
  129. outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
  130. outputParameters.suggestedLatency = ( fOutputDevice != paNoDevice ) // TODO: check how to setup this on ASIO
  131. ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
  132. : 0;
  133. outputParameters.hostApiSpecificStreamInfo = NULL;
  134. err = Pa_OpenStream( &fStream,
  135. ( fInputDevice == paNoDevice ) ? 0 : &inputParameters,
  136. ( fOutputDevice == paNoDevice ) ? 0 : &outputParameters,
  137. fAdaptedSampleRate,
  138. fAdaptedBufferSize,
  139. paNoFlag, // Clipping is on...
  140. Render,
  141. this );
  142. if ( err != paNoError )
  143. {
  144. jack_error ( "Pa_OpenStream error = %s", Pa_GetErrorText ( err ) );
  145. return -1;
  146. }
  147. err = Pa_StartStream ( fStream );
  148. if ( err != paNoError )
  149. {
  150. jack_error ( "Pa_StartStream error = %s", Pa_GetErrorText ( err ) );
  151. return -1;
  152. }
  153. jack_log ( "JackPortAudioAdapter::Open OK" );
  154. return 0;
  155. }
  156. int JackPortAudioAdapter::Close()
  157. {
  158. #ifdef JACK_MONITOR
  159. fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
  160. #endif
  161. jack_log ( "JackPortAudioAdapter::Close" );
  162. Pa_StopStream ( fStream );
  163. jack_log ( "JackPortAudioAdapter:: Pa_StopStream" );
  164. Pa_CloseStream ( fStream );
  165. jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" );
  166. return JackAudioAdapterInterface::Close();
  167. }
  168. int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate )
  169. {
  170. JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
  171. Close();
  172. return Open();
  173. }
  174. int JackPortAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size )
  175. {
  176. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  177. Close();
  178. return Open();
  179. }
  180. } // namespace
  181. #ifdef __cplusplus
  182. extern "C"
  183. {
  184. #endif
  185. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  186. {
  187. jack_driver_desc_t *desc;
  188. unsigned int i;
  189. desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
  190. strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  191. strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  192. desc->nparams = 10;
  193. desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
  194. i = 0;
  195. strcpy(desc->params[i].name, "inchannels");
  196. desc->params[i].character = 'i';
  197. desc->params[i].type = JackDriverParamInt;
  198. desc->params[i].value.ui = 0;
  199. strcpy(desc->params[i].short_desc, "Maximum number of input channels");
  200. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  201. i++;
  202. strcpy(desc->params[i].name, "outchannels");
  203. desc->params[i].character = 'o';
  204. desc->params[i].type = JackDriverParamInt;
  205. desc->params[i].value.ui = 0;
  206. strcpy(desc->params[i].short_desc, "Maximum number of output channels");
  207. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  208. i++;
  209. strcpy(desc->params[i].name, "capture");
  210. desc->params[i].character = 'C';
  211. desc->params[i].type = JackDriverParamString;
  212. strcpy(desc->params[i].value.str, "default input device");
  213. strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
  214. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  215. i++;
  216. strcpy(desc->params[i].name, "playback");
  217. desc->params[i].character = 'P';
  218. desc->params[i].type = JackDriverParamString;
  219. strcpy(desc->params[i].value.str, "default output device");
  220. strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
  221. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  222. i++;
  223. strcpy(desc->params[i].name, "rate");
  224. desc->params[i].character = 'r';
  225. desc->params[i].type = JackDriverParamUInt;
  226. desc->params[i].value.ui = 44100U;
  227. strcpy(desc->params[i].short_desc, "Sample rate");
  228. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  229. i++;
  230. strcpy(desc->params[i].name, "periodsize");
  231. desc->params[i].character = 'p';
  232. desc->params[i].type = JackDriverParamUInt;
  233. desc->params[i].value.ui = 512U;
  234. strcpy(desc->params[i].short_desc, "Period size");
  235. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  236. i++;
  237. strcpy(desc->params[i].name, "device");
  238. desc->params[i].character = 'd';
  239. desc->params[i].type = JackDriverParamString;
  240. desc->params[i].value.ui = 128U;
  241. strcpy(desc->params[i].value.str, "default device");
  242. strcpy(desc->params[i].short_desc, "PortAudio device name");
  243. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  244. i++;
  245. strcpy(desc->params[i].name, "list-devices");
  246. desc->params[i].character = 'l';
  247. desc->params[i].type = JackDriverParamBool;
  248. desc->params[i].value.i = true;
  249. strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
  250. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  251. i++;
  252. strcpy(desc->params[i].name, "quality");
  253. desc->params[i].character = 'q';
  254. desc->params[i].type = JackDriverParamInt;
  255. desc->params[i].value.ui = 0;
  256. strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
  257. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  258. i++;
  259. strcpy(desc->params[i].name, "ring-buffer");
  260. desc->params[i].character = 'g';
  261. desc->params[i].type = JackDriverParamInt;
  262. desc->params[i].value.ui = 32768;
  263. strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
  264. strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
  265. return desc;
  266. }
  267. #ifdef __cplusplus
  268. }
  269. #endif