00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackPortAudioDevices.h"
00021 #include "JackError.h"
00022
00023 using namespace std;
00024
00025 PortAudioDevices::PortAudioDevices()
00026 {
00027 PaError err;
00028 PaDeviceIndex id;
00029 jack_log("Initializing PortAudio...");
00030 if ( ( err = Pa_Initialize() ) == paNoError )
00031 {
00032 fNumHostApi = Pa_GetHostApiCount();
00033 fNumDevice = Pa_GetDeviceCount();
00034 fDeviceInfo = new PaDeviceInfo*[fNumDevice];
00035 for ( id = 0; id < fNumDevice; id++ )
00036 fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id));
00037 fHostName = new string[fNumHostApi];
00038 for ( id = 0; id < fNumHostApi; id++ )
00039 fHostName[id] = string ( Pa_GetHostApiInfo(id)->name );
00040 }
00041 else
00042 jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err));
00043 }
00044
00045 PortAudioDevices::~PortAudioDevices()
00046 {
00047
00048
00049
00050 delete[] fDeviceInfo;
00051 delete[] fHostName;
00052 }
00053
00054 PaDeviceIndex PortAudioDevices::GetNumDevice()
00055 {
00056 return fNumDevice;
00057 }
00058
00059 PaDeviceInfo* PortAudioDevices::GetDeviceInfo ( PaDeviceIndex id )
00060 {
00061 return fDeviceInfo[id];
00062 }
00063
00064 string PortAudioDevices::GetDeviceName ( PaDeviceIndex id )
00065 {
00066 return string ( fDeviceInfo[id]->name );
00067 }
00068
00069 string PortAudioDevices::GetHostFromDevice ( PaDeviceInfo* device )
00070 {
00071 return fHostName[device->hostApi];
00072 }
00073
00074 string PortAudioDevices::GetHostFromDevice ( PaDeviceIndex id )
00075 {
00076 return fHostName[fDeviceInfo[id]->hostApi];
00077 }
00078
00079 string PortAudioDevices::GetFullName ( PaDeviceIndex id )
00080 {
00081 string hostname = GetHostFromDevice ( id );
00082 string devicename = GetDeviceName ( id );
00083
00084 if ( hostname.compare ( "Windows DirectSound" ) == 0 )
00085 hostname = string ( "DirectSound" );
00086 return ( hostname + "::" + devicename );
00087 }
00088
00089 string PortAudioDevices::GetFullName ( std::string hostname, std::string devicename )
00090 {
00091
00092 if ( hostname.compare ( "Windows DirectSound" ) == 0 )
00093 hostname = string ( "DirectSound" );
00094 return ( hostname + "::" + devicename );
00095 }
00096
00097 PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName ( string fullname, PaDeviceIndex& id, bool isInput )
00098 {
00099 PaDeviceInfo* ret = NULL;
00100
00101 if ( fullname.size() == 0 )
00102 return NULL;
00103
00104 string::size_type separator = fullname.find ( "::", 0 );
00105 if ( separator == 0 )
00106 return NULL;
00107 char* hostname = (char*)malloc(separator + 9);
00108 fill_n ( hostname, separator + 9, 0 );
00109 fullname.copy ( hostname, separator );
00110
00111
00112 if ( strcmp ( hostname, "DirectSound" ) == 0 )
00113 strcpy ( hostname, "Windows DirectSound" );
00114 string devicename = fullname.substr ( separator + 2 );
00115
00116 for ( PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++ )
00117 {
00118 bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0);
00119 if ( ( GetHostFromDevice(dev_id).compare(hostname) == 0 )
00120 && ( GetDeviceName(dev_id).compare(devicename) == 0 )
00121 && flag )
00122 {
00123 id = dev_id;
00124 ret = fDeviceInfo[dev_id];
00125 }
00126 }
00127 free(hostname);
00128 return ret;
00129 }
00130
00131 void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters)
00132 {
00133 static double standardSampleRates[] =
00134 {
00135 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
00136 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1
00137 };
00138 int i, printCount;
00139 PaError err;
00140
00141 printCount = 0;
00142 for (i = 0; standardSampleRates[i] > 0; i++)
00143 {
00144 err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
00145 if (err == paFormatIsSupported)
00146 {
00147 if (printCount == 0)
00148 {
00149 jack_info("\t%8.2f", standardSampleRates[i]);
00150 printCount = 1;
00151 }
00152 else if (printCount == 4)
00153 {
00154 jack_info(",\n\t%8.2f", standardSampleRates[i]);
00155 printCount = 1;
00156 }
00157 else
00158 {
00159 jack_info(", %8.2f", standardSampleRates[i]);
00160 ++printCount;
00161 }
00162 }
00163 }
00164 if (!printCount) {
00165 jack_info("None");
00166 } else {
00167 jack_info("\n");
00168 }
00169 }
00170
00171 int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input)
00172 {
00173 string fullname = string ( devicename );
00174 PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, true );
00175 if ( device )
00176 max_input = device->maxInputChannels;
00177 else
00178 {
00179 id = Pa_GetDefaultInputDevice();
00180 if ( fullname.size() )
00181 jack_error("Can't open %s, PortAudio will use default input device.", devicename);
00182 if ( id == paNoDevice )
00183 return -1;
00184 max_input = GetDeviceInfo(id)->maxInputChannels;
00185 }
00186 return id;
00187 }
00188
00189 int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output)
00190 {
00191 string fullname = string ( devicename );
00192 PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, false );
00193 if ( device )
00194 max_output = device->maxOutputChannels;
00195 else
00196 {
00197 id = Pa_GetDefaultOutputDevice();
00198 if ( fullname.size() )
00199 jack_error("Can't open %s, PortAudio will use default output device.", devicename);
00200 if ( id == paNoDevice )
00201 return -1;
00202 max_output = GetDeviceInfo(id)->maxOutputChannels;
00203 }
00204 return id;
00205 }
00206
00207 void PortAudioDevices::DisplayDevicesNames()
00208 {
00209 PaDeviceIndex id;
00210 PaStreamParameters inputParameters, outputParameters;
00211 jack_info ( "********************** Devices list, %d detected **********************", fNumDevice );
00212
00213 for ( id = 0; id < fNumDevice; id++ )
00214 {
00215 jack_info ( "-------- device #%d ------------------------------------------------", id );
00216
00217 if ( id == Pa_GetDefaultInputDevice() )
00218 {
00219 jack_info("[ Default Input ]");
00220 }
00221 else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi)->defaultInputDevice )
00222 {
00223 const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
00224 jack_info ( "[ Default %s Input ]", host_info->name );
00225 }
00226
00227 if ( id == Pa_GetDefaultOutputDevice() )
00228 {
00229 jack_info ( "[ Default Output ]" );
00230 }
00231 else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi )->defaultOutputDevice )
00232 {
00233 const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
00234 jack_info ( "[ Default %s Output ]", host_info->name );
00235 }
00236
00237
00238 jack_info ( "Name = %s", GetFullName ( id ).c_str() );
00239 jack_info ( "Max inputs = %d", fDeviceInfo[id]->maxInputChannels );
00240 jack_info ( "Max outputs = %d", fDeviceInfo[id]->maxOutputChannels );
00241
00242 #ifdef WIN32
00243
00244 if ( Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO )
00245 {
00246 long minLatency, maxLatency, preferredLatency, granularity;
00247
00248 PaAsio_GetAvailableLatencyValues ( id, &minLatency, &maxLatency, &preferredLatency, &granularity );
00249
00250 jack_info ( "ASIO minimum buffer size = %ld", minLatency );
00251 jack_info ( "ASIO maximum buffer size = %ld", maxLatency );
00252 jack_info ( "ASIO preferred buffer size = %ld", preferredLatency );
00253
00254 if ( granularity == -1 )
00255 jack_info ( "ASIO buffer granularity = power of 2" );
00256 else
00257 jack_info ( "ASIO buffer granularity = %ld", granularity );
00258 }
00259 #endif
00260
00261 jack_info ( "Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate );
00262
00263
00264 inputParameters.device = id;
00265 inputParameters.channelCount = fDeviceInfo[id]->maxInputChannels;
00266 inputParameters.sampleFormat = paInt16;
00267 inputParameters.suggestedLatency = 0;
00268 inputParameters.hostApiSpecificStreamInfo = NULL;
00269
00270 outputParameters.device = id;
00271 outputParameters.channelCount = fDeviceInfo[id]->maxOutputChannels;
00272 outputParameters.sampleFormat = paInt16;
00273 outputParameters.suggestedLatency = 0;
00274 outputParameters.hostApiSpecificStreamInfo = NULL;
00275 }
00276 jack_info ( "**************************** End of list ****************************" );
00277 }
00278
00279 bool PortAudioDevices::IsDuplex ( PaDeviceIndex id )
00280 {
00281
00282 if ( fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
00283 return true;
00284
00285 for ( PaDeviceIndex i = 0; i < fNumDevice; i++ )
00286 if ( ( i != id ) && ( GetDeviceName ( i ) == GetDeviceName ( id ) ) )
00287 if ( ( fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
00288 || ( fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels ) )
00289 return true;
00290
00291 return false;
00292 }