Jack2  1.9.9
JackPortAudioAdapter.cpp
1 /*
2 Copyright (C) 2008 Grame
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include "JackPortAudioAdapter.h"
21 #include "JackError.h"
22 
23 namespace Jack
24 {
25 
26  int JackPortAudioAdapter::Render(const void* inputBuffer,
27  void* outputBuffer,
28  unsigned long framesPerBuffer,
29  const PaStreamCallbackTimeInfo* timeInfo,
30  PaStreamCallbackFlags statusFlags,
31  void* userData)
32  {
33  JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData);
34  adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, framesPerBuffer);
35  return paContinue;
36  }
37 
38  JackPortAudioAdapter::JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
39  : JackAudioAdapterInterface(buffer_size, sample_rate)
40  {
41  jack_log("JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate);
42 
43  const JSList* node;
44  const jack_driver_param_t* param;
45  int in_max = 0;
46  int out_max = 0;
47 
48  fInputDevice = Pa_GetDefaultInputDevice();
49  fOutputDevice = Pa_GetDefaultOutputDevice();
50 
51  for (node = params; node; node = jack_slist_next(node)) {
52  param = (const jack_driver_param_t*) node->data;
53 
54  switch (param->character)
55  {
56  case 'i' :
57  fCaptureChannels = param->value.ui;
58  break;
59  case 'o' :
60  fPlaybackChannels = param->value.ui;
61  break;
62  case 'C' :
63  if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) {
64  jack_error("Can't use %s, taking default input device", param->value.str);
65  fInputDevice = Pa_GetDefaultInputDevice();
66  }
67  break;
68  case 'P' :
69  if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) {
70  jack_error("Can't use %s, taking default output device", param->value.str);
71  fOutputDevice = Pa_GetDefaultOutputDevice();
72  }
73  break;
74  case 'r' :
75  SetAdaptedSampleRate(param->value.ui);
76  break;
77  case 'p' :
78  SetAdaptedBufferSize(param->value.ui);
79  break;
80  case 'd' :
81  if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0)
82  jack_error("Can't use %s, taking default input device", param->value.str);
83  if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0)
84  jack_error("Can't use %s, taking default output device", param->value.str);
85  break;
86  case 'l' :
87  fPaDevices.DisplayDevicesNames();
88  break;
89  case 'q':
90  fQuality = param->value.ui;
91  break;
92  case 'g':
93  fRingbufferCurSize = param->value.ui;
94  fAdaptative = false;
95  break;
96  }
97  }
98 
99  //max channels
100  if (in_max == 0 && fInputDevice != paNoDevice)
101  in_max = fPaDevices.GetDeviceInfo(fInputDevice)->maxInputChannels;
102  if (out_max == 0 && fOutputDevice != paNoDevice)
103  out_max = fPaDevices.GetDeviceInfo(fOutputDevice)->maxOutputChannels;
104 
105  //effective channels
106  if ((fCaptureChannels == 0) || (fCaptureChannels > in_max))
107  fCaptureChannels = in_max;
108  if ((fPlaybackChannels == 0) || (fPlaybackChannels > out_max))
109  fPlaybackChannels = out_max;
110 
111  //set adapter interface channels
112  SetInputs(fCaptureChannels);
113  SetOutputs(fPlaybackChannels);
114  }
115 
116  int JackPortAudioAdapter::Open()
117  {
118  PaError err;
119  PaStreamParameters inputParameters;
120  PaStreamParameters outputParameters;
121 
122  if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) {
123  jack_error("No input and output device!!");
124  return -1;
125  }
126 
127  jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
128  jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
129  jack_log("JackPortAudioAdapter::Open fAdaptedBufferSize = %u fAdaptedSampleRate %u", fAdaptedBufferSize, fAdaptedSampleRate);
130 
131  inputParameters.device = fInputDevice;
132  inputParameters.channelCount = fCaptureChannels;
133  inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
134  inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
135  ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
136  : 0;
137  inputParameters.hostApiSpecificStreamInfo = NULL;
138 
139  outputParameters.device = fOutputDevice;
140  outputParameters.channelCount = fPlaybackChannels;
141  outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
142  outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
143  ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
144  : 0;
145  outputParameters.hostApiSpecificStreamInfo = NULL;
146 
147  err = Pa_OpenStream( &fStream,
148  (fInputDevice == paNoDevice) ? 0 : &inputParameters,
149  (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
150  fAdaptedSampleRate,
151  fAdaptedBufferSize,
152  paNoFlag, // Clipping is on...
153  Render,
154  this);
155 
156  if (err != paNoError) {
157  jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
158  return -1;
159  }
160 
161  err = Pa_StartStream(fStream);
162 
163  if (err != paNoError) {
164  jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
165  return -1;
166  }
167 
168  jack_log("JackPortAudioAdapter::Open OK");
169  return 0;
170  }
171 
172  int JackPortAudioAdapter::Close()
173  {
174 #ifdef JACK_MONITOR
175  fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
176 #endif
177  jack_log("JackPortAudioAdapter::Close");
178  Pa_StopStream(fStream);
179  jack_log("JackPortAudioAdapter:: Pa_StopStream");
180  Pa_CloseStream(fStream);
181  jack_log("JackPortAudioAdapter:: Pa_CloseStream");
182  return 0;
183  }
184 
185  int JackPortAudioAdapter::SetSampleRate(jack_nframes_t sample_rate)
186  {
187  JackAudioAdapterInterface::SetHostSampleRate(sample_rate);
188  Close();
189  return Open();
190  }
191 
192  int JackPortAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
193  {
194  JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
195  Close();
196  return Open();
197  }
198 
199 } // namespace
200 
201 #ifdef __cplusplus
202 extern "C"
203 {
204 #endif
205 
206  SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
207  {
208  jack_driver_desc_t * desc;
211 
212  desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
213 
214  value.ui = 0;
215  jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", NULL);
216  jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", NULL);
217 
218  jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL);
219 
220  jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set PortAudio device name", NULL);
221 
222  value.ui = 44100U;
223  jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
224 
225  value.ui = 512U;
226  jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL);
227 
228  jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL);
229 
230  value.i = true;
231  jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available PortAudio devices", NULL);
232 
233  value.ui = 0;
234  jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
235 
236  value.ui = 32768;
237  jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
238 
239  return desc;
240  }
241 
242 #ifdef __cplusplus
243 }
244 #endif
245 
PaDeviceIndex Pa_GetDefaultInputDevice(void)
PaError Pa_StopStream(PaStream *stream)
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:91
PaError Pa_OpenStream(PaStream **stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData)
#define paNoFlag
Definition: portaudio.h:593
PaError Pa_StartStream(PaStream *stream)
void * hostApiSpecificStreamInfo
Definition: portaudio.h:515
#define paFloat32
Definition: portaudio.h:424
PaSampleFormat sampleFormat
Definition: portaudio.h:495
int PaError
Definition: portaudio.h:63
PaTime suggestedLatency
Definition: portaudio.h:508
unsigned long PaStreamCallbackFlags
Definition: portaudio.h:646
#define paNoDevice
Definition: portaudio.h:161
PaDeviceIndex Pa_GetDefaultOutputDevice(void)
PaDeviceIndex device
Definition: portaudio.h:482
const char * Pa_GetErrorText(PaError errorCode)
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:107
PaError Pa_CloseStream(PaStream *stream)