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