Add zalsa configure flag, enabled by default if possible
[jack2.git] / windows / portaudio / JackPortAudioDevices.cpp
blob362461bd3a958981813b91be0ee9975f0685a858
1 /*
2 Copyright (C) 2008-2011 Romain Moret at Grame
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.
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.
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.
20 #include "JackPortAudioDevices.h"
21 #include "JackError.h"
22 #include <stdlib.h>
24 using namespace std;
26 PortAudioDevices::PortAudioDevices()
28 PaError err;
29 PaDeviceIndex id;
30 jack_log("Initializing PortAudio...");
31 if ((err = Pa_Initialize()) == paNoError) {
32 fNumHostApi = Pa_GetHostApiCount();
33 fNumDevice = Pa_GetDeviceCount();
34 fDeviceInfo = new PaDeviceInfo*[fNumDevice];
35 for (id = 0; id < fNumDevice; id++) {
36 fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id));
38 fHostName = new string[fNumHostApi];
39 for (id = 0; id < fNumHostApi; id++) {
40 fHostName[id] = string(Pa_GetHostApiInfo(id)->name);
42 } else {
43 jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err));
47 PortAudioDevices::~PortAudioDevices()
49 jack_log("Terminate PortAudio...");
50 Pa_Terminate();
52 delete[] fDeviceInfo;
53 delete[] fHostName;
56 PaDeviceIndex PortAudioDevices::GetNumDevice()
58 return fNumDevice;
61 PaDeviceInfo* PortAudioDevices::GetDeviceInfo(PaDeviceIndex id)
63 return fDeviceInfo[id];
66 string PortAudioDevices::GetDeviceName(PaDeviceIndex id)
68 return string(fDeviceInfo[id]->name);
71 string PortAudioDevices::GetHostFromDevice(PaDeviceInfo* device)
73 return fHostName[device->hostApi];
76 string PortAudioDevices::GetHostFromDevice(PaDeviceIndex id)
78 return fHostName[fDeviceInfo[id]->hostApi];
81 string PortAudioDevices::GetFullName(PaDeviceIndex id)
83 string hostname = GetHostFromDevice(id);
84 string devicename = GetDeviceName(id);
85 //some hostname are quite long...use shortcuts
86 if (hostname.compare("Windows DirectSound") == 0) {
87 hostname = string("DirectSound");
89 return (hostname + "::" + devicename);
92 string PortAudioDevices::GetFullName(std::string hostname, std::string devicename)
94 //some hostname are quite long...use shortcuts
95 if (hostname.compare("Windows DirectSound") == 0) {
96 hostname = string("DirectSound");
98 return (hostname + "::" + devicename);
101 PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName(string fullname, PaDeviceIndex& id, bool isInput)
103 PaDeviceInfo* ret = NULL;
104 //no driver to find
105 if (fullname.size() == 0) {
106 return NULL;
108 //first get host and device names from fullname
109 string::size_type separator = fullname.find("::", 0);
111 if (separator == string::npos) {
112 return NULL;
115 char* hostname = (char*)malloc(separator + 9);
116 fill_n(hostname, separator + 9, 0);
117 fullname.copy(hostname, separator);
119 //we need the entire hostname, replace shortcuts
120 if (strcmp(hostname, "DirectSound") == 0) {
121 strcpy(hostname, "Windows DirectSound");
123 string devicename = fullname.substr(separator + 2);
124 //then find the corresponding device
125 for (PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++) {
126 bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0);
127 if ((GetHostFromDevice(dev_id).compare(hostname) == 0)
128 && (GetDeviceName(dev_id).compare(devicename) == 0)
129 && flag) {
130 id = dev_id;
131 ret = fDeviceInfo[dev_id];
134 free(hostname);
135 return ret;
138 void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters)
140 static double standardSampleRates[] =
142 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
143 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */
145 int i, printCount;
146 PaError err;
148 printCount = 0;
149 for (i = 0; standardSampleRates[i] > 0; i++) {
150 err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
151 if (err == paFormatIsSupported) {
152 if (printCount == 0) {
153 jack_info("\t%8.2f", standardSampleRates[i]);
154 printCount = 1;
155 } else if (printCount == 4) {
156 jack_info(",\n\t%8.2f", standardSampleRates[i]);
157 printCount = 1;
158 } else {
159 jack_info(", %8.2f", standardSampleRates[i]);
160 ++printCount;
164 if (!printCount) {
165 jack_info("None");
166 } else {
167 jack_info("\n");
171 int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input)
173 string fullname = string(devicename);
174 PaDeviceInfo* device = GetDeviceFromFullName(fullname, id, true);
175 if (device) {
176 max_input = device->maxInputChannels;
177 } else {
178 id = Pa_GetDefaultInputDevice();
179 if (fullname.size()) {
180 jack_error("Can't open %s, PortAudio will use default input device.", devicename);
182 if (id == paNoDevice) {
183 return -1;
185 max_input = GetDeviceInfo(id)->maxInputChannels;
187 return id;
190 int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output)
192 string fullname = string(devicename);
193 PaDeviceInfo* device = GetDeviceFromFullName(fullname, id, false);
194 if (device) {
195 max_output = device->maxOutputChannels;
196 } else {
197 id = Pa_GetDefaultOutputDevice();
198 if (fullname.size()) {
199 jack_error("Can't open %s, PortAudio will use default output device.", devicename);
201 if (id == paNoDevice) {
202 return -1;
204 max_output = GetDeviceInfo(id)->maxOutputChannels;
206 return id;
209 int PortAudioDevices::GetPreferredBufferSize(PaDeviceIndex id)
211 #if defined(WIN32) && defined(HAVE_ASIO)
212 /* ASIO specific latency information */
213 if (Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO) {
214 long minLatency, maxLatency, preferredLatency, granularity;
216 PaAsio_GetAvailableBufferSizes(id, &minLatency, &maxLatency, &preferredLatency, &granularity);
218 jack_info("ASIO minimum buffer size = %ld", minLatency);
219 jack_info("ASIO maximum buffer size = %ld", maxLatency);
220 jack_info("ASIO preferred buffer size = %ld", preferredLatency);
222 if (granularity == -1) {
223 jack_info("ASIO buffer granularity = power of 2");
224 } else {
225 jack_info("ASIO buffer granularity = %ld", granularity);
228 return preferredLatency;
229 } else
230 #endif
232 return 512; // Non ASIO driver, returns generic value
236 void PortAudioDevices::DisplayDevicesNames()
238 PaDeviceIndex id;
239 PaStreamParameters inputParameters, outputParameters;
240 jack_info("********************** Devices list, %d detected **********************", fNumDevice);
242 for (id = 0; id < fNumDevice; id++) {
243 jack_info("-------- device #%d ------------------------------------------------", id);
245 if (id == Pa_GetDefaultInputDevice()) {
246 jack_info("[ Default Input ]");
247 } else if (id == Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->defaultInputDevice) {
248 const PaHostApiInfo *host_info = Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi);
249 jack_info("[ Default %s Input ]", host_info->name);
252 if (id == Pa_GetDefaultOutputDevice()) {
253 jack_info("[ Default Output ]");
254 } else if (id == Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->defaultOutputDevice) {
255 const PaHostApiInfo *host_info = Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi);
256 jack_info("[ Default %s Output ]", host_info->name);
259 /* print device info fields */
260 jack_info("Name = %s", GetFullName(id).c_str());
261 jack_info("Max inputs = %d", fDeviceInfo[id]->maxInputChannels);
262 jack_info("Max outputs = %d", fDeviceInfo[id]->maxOutputChannels);
264 #if defined(WIN32) && defined(HAVE_ASIO)
265 /* ASIO specific latency information */
266 if (Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO) {
267 long minLatency, maxLatency, preferredLatency, granularity;
269 PaAsio_GetAvailableBufferSizes(id, &minLatency, &maxLatency, &preferredLatency, &granularity);
271 jack_info("ASIO minimum buffer size = %ld", minLatency);
272 jack_info("ASIO maximum buffer size = %ld", maxLatency);
273 jack_info("ASIO preferred buffer size = %ld", preferredLatency);
275 if (granularity == -1) {
276 jack_info("ASIO buffer granularity = power of 2");
277 } else {
278 jack_info("ASIO buffer granularity = %ld", granularity);
281 #endif
282 jack_info("Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate);
284 /* poll for standard sample rates */
285 inputParameters.device = id;
286 inputParameters.channelCount = fDeviceInfo[id]->maxInputChannels;
287 inputParameters.sampleFormat = paInt16;
288 inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
289 inputParameters.hostApiSpecificStreamInfo = NULL;
291 outputParameters.device = id;
292 outputParameters.channelCount = fDeviceInfo[id]->maxOutputChannels;
293 outputParameters.sampleFormat = paInt16;
294 outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
295 outputParameters.hostApiSpecificStreamInfo = NULL;
297 jack_info("**************************** End of list ****************************");
300 bool PortAudioDevices::IsDuplex(PaDeviceIndex id)
302 //does the device has in and out facilities
303 if (fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels) {
304 return true;
306 //else is another complementary device ? (search in devices with the same name)
307 for (PaDeviceIndex i = 0; i < fNumDevice; i++) {
308 if ((i != id) && (GetDeviceName(i) == GetDeviceName(id))) {
309 if ((fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels)
310 || (fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels)) {
311 return true;
315 //then the device isn't full duplex
316 return false;