Use jack_client_open instead of old jack_client_new.
[jack2.git] / windows / portaudio / JackPortAudioDevices.cpp
blobd12cfca3ba5ccdf7edf40c8bfdd506b986f272b9
1 /*
2 Copyright (C) 2008 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"
23 using namespace std;
25 PortAudioDevices::PortAudioDevices()
27 PaError err;
28 PaDeviceIndex id;
29 jack_log("Initializing PortAudio...");
30 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));
37 fHostName = new string[fNumHostApi];
38 for ( id = 0; id < fNumHostApi; id++ )
39 fHostName[id] = string ( Pa_GetHostApiInfo(id)->name );
41 else
42 jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err));
45 PortAudioDevices::~PortAudioDevices()
47 // Desactivate for now: crash the server..
48 //Pa_Terminate();
50 delete[] fDeviceInfo;
51 delete[] fHostName;
54 PaDeviceIndex PortAudioDevices::GetNumDevice()
56 return fNumDevice;
59 PaDeviceInfo* PortAudioDevices::GetDeviceInfo ( PaDeviceIndex id )
61 return fDeviceInfo[id];
64 string PortAudioDevices::GetDeviceName ( PaDeviceIndex id )
66 return string ( fDeviceInfo[id]->name );
69 string PortAudioDevices::GetHostFromDevice ( PaDeviceInfo* device )
71 return fHostName[device->hostApi];
74 string PortAudioDevices::GetHostFromDevice ( PaDeviceIndex id )
76 return fHostName[fDeviceInfo[id]->hostApi];
79 string PortAudioDevices::GetFullName ( PaDeviceIndex id )
81 string hostname = GetHostFromDevice ( id );
82 string devicename = GetDeviceName ( id );
83 //some hostname are quite long...use shortcuts
84 if ( hostname.compare ( "Windows DirectSound" ) == 0 )
85 hostname = string ( "DirectSound" );
86 return ( hostname + "::" + devicename );
89 string PortAudioDevices::GetFullName ( std::string hostname, std::string devicename )
91 //some hostname are quite long...use shortcuts
92 if ( hostname.compare ( "Windows DirectSound" ) == 0 )
93 hostname = string ( "DirectSound" );
94 return ( hostname + "::" + devicename );
97 PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName ( string fullname, PaDeviceIndex& id, bool isInput )
99 PaDeviceInfo* ret = NULL;
100 //no driver to find
101 if ( fullname.size() == 0 )
102 return NULL;
103 //first get host and device names from fullname
104 string::size_type separator = fullname.find ( "::", 0 );
105 if ( separator == 0 )
106 return NULL;
107 char* hostname = (char*)malloc(separator + 9);
108 fill_n ( hostname, separator + 9, 0 );
109 fullname.copy ( hostname, separator );
111 //we need the entire hostname, replace shortcuts
112 if ( strcmp ( hostname, "DirectSound" ) == 0 )
113 strcpy ( hostname, "Windows DirectSound" );
114 string devicename = fullname.substr ( separator + 2 );
115 //then find the corresponding device
116 for ( PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++ )
118 bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0);
119 if ( ( GetHostFromDevice(dev_id).compare(hostname) == 0 )
120 && ( GetDeviceName(dev_id).compare(devicename) == 0 )
121 && flag )
123 id = dev_id;
124 ret = fDeviceInfo[dev_id];
127 free(hostname);
128 return ret;
131 void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters)
133 static double standardSampleRates[] =
135 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
136 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */
138 int i, printCount;
139 PaError err;
141 printCount = 0;
142 for (i = 0; standardSampleRates[i] > 0; i++)
144 err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
145 if (err == paFormatIsSupported)
147 if (printCount == 0)
149 jack_info("\t%8.2f", standardSampleRates[i]);
150 printCount = 1;
152 else if (printCount == 4)
154 jack_info(",\n\t%8.2f", standardSampleRates[i]);
155 printCount = 1;
157 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
179 id = Pa_GetDefaultInputDevice();
180 if ( fullname.size() )
181 jack_error("Can't open %s, PortAudio will use default input device.", devicename);
182 if ( id == paNoDevice )
183 return -1;
184 max_input = GetDeviceInfo(id)->maxInputChannels;
186 return id;
189 int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output)
191 string fullname = string ( devicename );
192 PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, false );
193 if ( device )
194 max_output = device->maxOutputChannels;
195 else
197 id = Pa_GetDefaultOutputDevice();
198 if ( fullname.size() )
199 jack_error("Can't open %s, PortAudio will use default output device.", devicename);
200 if ( id == paNoDevice )
201 return -1;
202 max_output = GetDeviceInfo(id)->maxOutputChannels;
204 return id;
207 void PortAudioDevices::DisplayDevicesNames()
209 PaDeviceIndex id;
210 PaStreamParameters inputParameters, outputParameters;
211 jack_info ( "********************** Devices list, %d detected **********************", fNumDevice );
213 for ( id = 0; id < fNumDevice; id++ )
215 jack_info ( "-------- device #%d ------------------------------------------------", id );
217 if ( id == Pa_GetDefaultInputDevice() )
219 jack_info("[ Default Input ]");
221 else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi)->defaultInputDevice )
223 const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
224 jack_info ( "[ Default %s Input ]", host_info->name );
227 if ( id == Pa_GetDefaultOutputDevice() )
229 jack_info ( "[ Default Output ]" );
231 else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi )->defaultOutputDevice )
233 const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
234 jack_info ( "[ Default %s Output ]", host_info->name );
237 /* print device info fields */
238 jack_info ( "Name = %s", GetFullName ( id ).c_str() );
239 jack_info ( "Max inputs = %d", fDeviceInfo[id]->maxInputChannels );
240 jack_info ( "Max outputs = %d", fDeviceInfo[id]->maxOutputChannels );
242 #ifdef WIN32
243 /* ASIO specific latency information */
244 if ( Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO )
246 long minLatency, maxLatency, preferredLatency, granularity;
248 PaAsio_GetAvailableLatencyValues ( id, &minLatency, &maxLatency, &preferredLatency, &granularity );
250 jack_info ( "ASIO minimum buffer size = %ld", minLatency );
251 jack_info ( "ASIO maximum buffer size = %ld", maxLatency );
252 jack_info ( "ASIO preferred buffer size = %ld", preferredLatency );
254 if ( granularity == -1 )
255 jack_info ( "ASIO buffer granularity = power of 2" );
256 else
257 jack_info ( "ASIO buffer granularity = %ld", granularity );
259 #endif
261 jack_info ( "Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate );
263 /* poll for standard sample rates */
264 inputParameters.device = id;
265 inputParameters.channelCount = fDeviceInfo[id]->maxInputChannels;
266 inputParameters.sampleFormat = paInt16;
267 inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
268 inputParameters.hostApiSpecificStreamInfo = NULL;
270 outputParameters.device = id;
271 outputParameters.channelCount = fDeviceInfo[id]->maxOutputChannels;
272 outputParameters.sampleFormat = paInt16;
273 outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
274 outputParameters.hostApiSpecificStreamInfo = NULL;
276 jack_info ( "**************************** End of list ****************************" );
279 bool PortAudioDevices::IsDuplex ( PaDeviceIndex id )
281 //does the device has in and out facilities
282 if ( fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
283 return true;
284 //else is another complementary device ? (search in devices with the same name)
285 for ( PaDeviceIndex i = 0; i < fNumDevice; i++ )
286 if ( ( i != id ) && ( GetDeviceName ( i ) == GetDeviceName ( id ) ) )
287 if ( ( fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
288 || ( fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels ) )
289 return true;
290 //then the device isn't full duplex
291 return false;