|
- /*
- Copyright (C) 2008 Romain Moret at Grame
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #include "JackPortAudioDevices.h"
- #include "JackError.h"
-
- using namespace std;
-
- PortAudioDevices::PortAudioDevices()
- {
- PaError err;
- if ( ( err = Pa_Initialize() ) == paNoError )
- {
- fNumHostApi = Pa_GetHostApiCount();
- fNumDevice = Pa_GetDeviceCount();
- fDeviceInfo = new PaDeviceInfo*[fNumDevice];
- for ( PaDeviceIndex id = 0; id < fNumDevice; id++ )
- fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id));
- fHostName = new string[fNumHostApi];
- for ( PaHostApiIndex id = 0; id < fNumHostApi; id++ )
- fHostName[id] = string ( Pa_GetHostApiInfo(id)->name );
- }
- else
- printf("JackPortAudioDriver::Pa_Initialize error = %s\n", Pa_GetErrorText(err));
- }
-
- PortAudioDevices::~PortAudioDevices()
- {
- Pa_Terminate();
- delete[] fDeviceInfo;
- delete[] fHostName;
- }
-
- PaDeviceIndex PortAudioDevices::GetNumDevice()
- {
- return fNumDevice;
- }
-
- PaDeviceInfo* PortAudioDevices::GetDeviceInfo ( PaDeviceIndex id )
- {
- return fDeviceInfo[id];
- }
-
- string PortAudioDevices::GetDeviceName ( PaDeviceIndex id )
- {
- return string ( fDeviceInfo[id]->name );
- }
-
- string PortAudioDevices::GetHostFromDevice ( PaDeviceInfo* device )
- {
- return fHostName[device->hostApi];
- }
-
- string PortAudioDevices::GetHostFromDevice ( PaDeviceIndex id )
- {
- return fHostName[fDeviceInfo[id]->hostApi];
- }
-
- string PortAudioDevices::GetFullName ( PaDeviceIndex id )
- {
- string hostname = GetHostFromDevice ( id );
- string devicename = GetDeviceName ( id );
- //some hostname are quite long...use shortcuts
- if ( hostname.compare ( "Windows DirectSound" ) == 0 )
- hostname = string ( "DirectSound" );
- return ( hostname + "::" + devicename );
- }
-
- string PortAudioDevices::GetFullName ( std::string hostname, std::string devicename )
- {
- //some hostname are quite long...use shortcuts
- if ( hostname.compare ( "Windows DirectSound" ) == 0 )
- hostname = string ( "DirectSound" );
- return ( hostname + "::" + devicename );
- }
-
- PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName ( string fullname, PaDeviceIndex& id )
- {
- PaDeviceInfo* ret = NULL;
- //no driver to find
- if ( fullname.size() == 0 )
- return NULL;
- //first get host and device names from fullname
- string::size_type separator = fullname.find ( "::", 0 );
- if ( separator == 0 )
- return NULL;
- char hostname[separator + 9];
- fill_n ( hostname, separator + 9, 0 );
- fullname.copy ( hostname, separator );
- //we need the entire hostname, replace shortcuts
- if ( strcmp ( hostname, "DirectSound" ) == 0 )
- strcpy ( hostname, "Windows DirectSound" );
- string devicename = fullname.substr ( separator + 2 );
- //then find the corresponding device
- for ( PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++ )
- {
- if ( ( GetHostFromDevice(dev_id).compare(hostname) == 0 ) && ( GetDeviceName(dev_id).compare(devicename) == 0 ) )
- {
- id = dev_id;
- ret = fDeviceInfo[dev_id];
- }
- }
- return ret;
- }
-
- void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters)
- {
- static double standardSampleRates[] =
- {
- 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
- 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */
- };
- int i, printCount;
- PaError err;
-
- printCount = 0;
- for (i = 0; standardSampleRates[i] > 0; i++)
- {
- err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
- if (err == paFormatIsSupported)
- {
- if (printCount == 0)
- {
- printf("\t%8.2f", standardSampleRates[i]);
- printCount = 1;
- }
- else if (printCount == 4)
- {
- printf(",\n\t%8.2f", standardSampleRates[i]);
- printCount = 1;
- }
- else
- {
- printf(", %8.2f", standardSampleRates[i]);
- ++printCount;
- }
- }
- }
- if (!printCount)
- printf("None\n");
- else
- printf("\n");
- }
-
- int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input)
- {
- string fullname = string ( devicename );
- PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id );
- if ( device )
- max_input = device->maxInputChannels;
- else
- {
- id = Pa_GetDefaultInputDevice();
- if ( fullname.size() )
- printf("Can't open %s, PortAudio will use default input device.\n", devicename);
- if ( id == paNoDevice )
- return -1;
- max_input = GetDeviceInfo(id)->maxInputChannels;
- devicename = strdup ( GetDeviceInfo(id)->name );
- }
- return id;
- }
-
- int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output)
- {
- string fullname = string ( devicename );
- PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id );
- if ( device )
- max_output = device->maxOutputChannels;
- else
- {
- id = Pa_GetDefaultOutputDevice();
- if ( fullname.size() )
- printf("Can't open %s, PortAudio will use default output device.\n", devicename);
- if ( id == paNoDevice )
- return -1;
- max_output = GetDeviceInfo(id)->maxOutputChannels;
- devicename = strdup ( GetDeviceInfo(id)->name );
- }
- return id;
- }
-
- void PortAudioDevices::DisplayDevicesNames()
- {
- int def_display;
- PaStreamParameters inputParameters, outputParameters;
- printf ( "********************** Devices list, %d detected **********************\n", fNumDevice );
-
- for ( PaDeviceIndex id = 0; id < fNumDevice; id++ )
- {
- printf ( "-------- device #%d ------------------------------------------------\n", id );
-
- def_display = 0;
- if ( id == Pa_GetDefaultInputDevice() )
- {
- printf("[ Default Input");
- def_display = 1;
- }
- else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi)->defaultInputDevice )
- {
- const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
- printf ( "[ Default %s Input", host_info->name );
- def_display = 1;
- }
-
- if ( id == Pa_GetDefaultOutputDevice() )
- {
- printf ( ( def_display ? "," : "[" ) );
- printf ( " Default Output" );
- def_display = 1;
- }
- else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi )->defaultOutputDevice )
- {
- const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
- printf ( ( def_display ? "," : "[" ) );
- printf ( " Default %s Output", host_info->name );
- def_display = 1;
- }
-
- if ( def_display )
- printf ( " ]\n" );
-
- /* print device info fields */
- printf ( "Name = %s\n", GetFullName ( id ).c_str() );
- printf ( "Max inputs = %d\n", fDeviceInfo[id]->maxInputChannels );
- printf ( "Max outputs = %d\n", fDeviceInfo[id]->maxOutputChannels );
-
- #ifdef WIN32
- /* ASIO specific latency information */
- if ( Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO )
- {
- long minLatency, maxLatency, preferredLatency, granularity;
-
- PaAsio_GetAvailableLatencyValues ( id, &minLatency, &maxLatency, &preferredLatency, &granularity );
-
- printf ( "ASIO minimum buffer size = %ld\n", minLatency );
- printf ( "ASIO maximum buffer size = %ld\n", maxLatency );
- printf ( "ASIO preferred buffer size = %ld\n", preferredLatency );
-
- if ( granularity == -1 )
- printf ( "ASIO buffer granularity = power of 2\n" );
- else
- printf ( "ASIO buffer granularity = %ld\n", granularity );
- }
- #endif
-
- printf ( "Default sample rate = %8.2f\n", fDeviceInfo[id]->defaultSampleRate );
-
- /* poll for standard sample rates */
- inputParameters.device = id;
- inputParameters.channelCount = fDeviceInfo[id]->maxInputChannels;
- inputParameters.sampleFormat = paInt16;
- inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
- inputParameters.hostApiSpecificStreamInfo = NULL;
-
- outputParameters.device = id;
- outputParameters.channelCount = fDeviceInfo[id]->maxOutputChannels;
- outputParameters.sampleFormat = paInt16;
- outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
- outputParameters.hostApiSpecificStreamInfo = NULL;
- }
- printf ( "**************************** End of list ****************************\n" );
- }
-
- bool PortAudioDevices::IsDuplex ( PaDeviceIndex id )
- {
- //does the device has in and out facilities
- if ( fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
- return true;
- //else is another complementary device ? (search in devices with the same name)
- for ( PaDeviceIndex i = 0; i < fNumDevice; i++ )
- if ( ( i != id ) && ( GetDeviceName ( i ) == GetDeviceName ( id ) ) )
- if ( ( fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
- || ( fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels ) )
- return true;
- //then the device isn't full duplex
- return false;
- }
|