#define PROPERTY_CHANGE_TIMEOUT_SECONDS 2
#define PROPERTY_CHANGE_RETRIES 3
-///< Supported Sample rates
+///< Supported Sample rates
static const double gAllSampleRates[] =
{
- 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 -1 /* negative terminated list */
+ 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, -1 /* negative terminated list */
};
}
//**********************************************************************************************
-// WCMRPortAudioDevice::WCMRPortAudioDevice
+// WCMRPortAudioDevice::WCMRPortAudioDevice
//
//! Constructor for the audio device. Opens the PA device
//! and gets information about the device.
//! \param *pManager : The audio device manager that's managing this device.
//! \param deviceID : The port audio device ID.
//! \param useMultithreading : Whether to use multi-threading for audio processing. Default is true.
-//!
+//!
//! \return Nothing.
-//!
+//!
//**********************************************************************************************
WCMRPortAudioDevice::WCMRPortAudioDevice (WCMRPortAudioDeviceManager *pManager, unsigned int deviceID, bool useMultithreading, bool bNoCopy) :
WCMRNativeAudioDevice (pManager, useMultithreading, bNoCopy)
//**********************************************************************************************
-// WCMRPortAudioDevice::~WCMRPortAudioDevice
+// WCMRPortAudioDevice::~WCMRPortAudioDevice
//
//! Destructor for the audio device. The base release all the connections that were created, if
//! they have not been already destroyed! Here we simply stop streaming, and close device
//! handles if necessary.
//!
//! \param none
-//!
+//!
//! \return Nothing.
-//!
+//!
//**********************************************************************************************
WCMRPortAudioDevice::~WCMRPortAudioDevice ()
{
//**********************************************************************************************
-// WCMRPortAudioDevice::updateDeviceInfo
+// WCMRPortAudioDevice::updateDeviceInfo
//
//! Must be called be device processing thread
//! Updates Device Information about channels, sampling rates, buffer sizes.
//!
//! \return Nothing.
-//!
+//!
//**********************************************************************************************
void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
{
m_BufferSizes.clear();
bool useDefaultBuffers = true;
- // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
+ // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
long minSize, maxSize, preferredSize, granularity;
PaError err = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
//**********************************************************************************************
-// WCMRPortAudioDevice::CurrentSamplingRate
+// WCMRPortAudioDevice::CurrentSamplingRate
//
-//! The device's current sampling rate. This may be overridden, if the device needs to
+//! The device's current sampling rate. This may be overridden, if the device needs to
//! query the driver for the current rate.
//!
//! \param none
-//!
+//!
//! \return The device's current sampling rate. -1 on error.
-//!
+//!
//**********************************************************************************************
int WCMRPortAudioDevice::CurrentSamplingRate ()
{
//**********************************************************************************************
-// WCMRPortAudioDevice::SetCurrentSamplingRate
+// WCMRPortAudioDevice::SetCurrentSamplingRate
//
-//! Change the sampling rate to be used by the device.
+//! Change the sampling rate to be used by the device.
//!
//! \param newRate : The rate to use (samples per sec).
-//!
+//!
//! \return eNoErr always. The derived classes may return error codes.
-//!
+//!
//**********************************************************************************************
WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
{
//make the change...
m_CurrentSamplingRate = newRate;
- PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
+ PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
Pa_Sleep(PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS); // sleep some time to make sure the change has place
if (paErr != paNoError)
//**********************************************************************************************
// WCMRPortAudioDevice::CurrentBufferSize
//
-//! The device's current buffer size in use. This may be overridden, if the device needs to
+//! The device's current buffer size in use. This may be overridden, if the device needs to
//! query the driver for the current size.
//!
//! \param none
-//!
+//!
//! \return The device's current buffer size. 0 on error.
-//!
+//!
//**********************************************************************************************
int WCMRPortAudioDevice::CurrentBufferSize ()
{
//**********************************************************************************************
// WCMRPortAudioDevice::SetCurrentBufferSize
//
-//! Change the buffer size to be used by the device. This will most likely be overridden,
+//! Change the buffer size to be used by the device. This will most likely be overridden,
//! the base class simply updates the member variable.
//!
//! \param newSize : The buffer size to use (in sample-frames)
-//!
+//!
//! \return eNoErr always. The derived classes may return error codes.
-//!
+//!
//**********************************************************************************************
WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
{
WTErr retVal = eNoErr;
std::vector<int>::iterator intIter;
- //changes the status.
- int oldSize = CurrentBufferSize();
- bool oldActive = Active();
-
- //same size, nothing to do.
- if (oldSize == newSize)
- return (retVal);
-
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
return (retVal);
}
- std::cout << "Setting buffer: " << newSize << std::endl;
-
- //see if this is one of our supported rates...
- intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
- if (intIter == m_BufferSizes.end())
- {
- //Sample rate proposed by client is not supported any more
- if (m_BufferSizes.size() == 1)
- {
- // we have only one aloved buffer size which is preffered by PA
- // this is the only value which could be set
- newSize = m_BufferSizes[0];
- int bufferSize = newSize;
- // notify client to update sample rate after us
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
- return retVal;
-
- } else {
- // more then one buffer size value is available
- //Can't change, perhaps use an "invalid param" type of error
- retVal = eCommandLineParameter;
- return (retVal);
- }
- }
-
- if (oldActive)
- {
- //Deactivate it for the change...
- SetActive (false);
- }
-
- //make the change...
- m_CurrentBufferSize = newSize;
-
- //reactivate it.
- if (oldActive)
+ // Buffer size for ASIO devices can be changed from the control panel only
+ // We have driver driven logi here
+ if (m_CurrentBufferSize != newSize )
{
- retVal = SetActive (true);
+ // we have only one aloved buffer size which is preffered by PA
+ // this is the only value which could be set
+ newSize = m_BufferSizes[0];
+ int bufferSize = newSize;
+ // notify client to update buffer size
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
+ return retVal;
}
return (retVal);
//**********************************************************************************************
-// WCMRPortAudioDevice::ConnectionStatus
+// WCMRPortAudioDevice::ConnectionStatus
//
//! Retrieves the device's current connection status. This will most likely be overridden,
//! in case some driver communication is required to query the status.
//!
//! \param none
-//!
+//!
//! \return A ConnectionStates value.
-//!
+//!
//**********************************************************************************************
WCMRPortAudioDevice::ConnectionStates WCMRPortAudioDevice::ConnectionStatus ()
{
// WCMRPortAudioDevice::activateDevice
//
//! IS CALLED BY PROCESS THREAD
-//! Sets the device into "active" state. Essentially, opens the PA device.
+//! Sets the device into "active" state. Essentially, opens the PA device.
//! If it's an ASIO device it may result in buffer size change in some cases.
//!
//**********************************************************************************************
// if device is not active activate it
if (!Active() )
{
- std::list<long> buffersSizes;
- buffersSizes.push_back(m_CurrentBufferSize);
-
- long minSize, maxSize, preferredSize, granularity;
- PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
-
- if (paErr == paNoError)
- {
- buffersSizes.push_front(preferredSize);
- }
-
PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL;
if (outputParameters.channelCount)
pOutS = &outputParameters;
- // try opening stream with current buffer and the rest if not successful
- std::list<long>::const_iterator bufferIter = buffersSizes.begin();
- for (; bufferIter != buffersSizes.end(); ++bufferIter) {
-
- std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
- std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << *bufferIter << std::endl;
- paErr = Pa_OpenStream(&m_PortAudioStream,
- pInS,
- pOutS,
- m_CurrentSamplingRate,
- m_CurrentBufferSize,
- paDitherOff,
- WCMRPortAudioDevice::TheCallback,
- this);
+ std::cout << "API::Device " << m_DeviceName << " Opening device stream " << std::endl;
+ std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << m_CurrentBufferSize << std::endl;
+ paErr = Pa_OpenStream(&m_PortAudioStream,
+ pInS,
+ pOutS,
+ m_CurrentSamplingRate,
+ m_CurrentBufferSize,
+ paDitherOff,
+ WCMRPortAudioDevice::TheCallback,
+ this);
- if(paErr == paNoError)
- {
- break;
- }
-
- std::cout << "Cannot open streamm with buffer: "<< *bufferIter << " Error: " << Pa_GetErrorText (paErr) << std::endl;
+ if(paErr != paNoError)
+ {
+ std::cout << "Cannot open streamm with buffer: "<< m_CurrentBufferSize << " Error: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Error details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
if(paErr == paNoError)
{
+ std::cout << "Stream has been opened! "<< std::endl;
+
+ // check for possible changes
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
+ std::cout << "Checked if buffer size changed "<< std::endl;
if (paErr == paNoError && m_CurrentBufferSize != preferredSize)
{
+ std::cout << "Buffer size has changed "<< std::endl;
m_CurrentBufferSize = preferredSize;
m_BufferSizes.clear();
m_BufferSizes.push_back(preferredSize);
m_ResetReported = 0;
m_ResyncRequested = 0;
m_ResyncReported = 0;
+ std::cout << "Installing new mesage hook "<< std::endl;
PaAsio_SetMessageHook (StaticASIOMessageHook, this);
}
m_IsActive = true;
}
+ std::cout << "Activation is DONE "<< std::endl;
+
if (callerIsWaiting)
SetEvent(m_hActivationDone);
}
// WCMRPortAudioDevice::deactivateDevice
//
//! IS CALLED BY PROCESS THREAD
-//! Sets the device into "inactive" state. Essentially, closes the PA device.
+//! Sets the device into "inactive" state. Essentially, closes the PA device.
//!
//**********************************************************************************************
void WCMRPortAudioDevice::deactivateDevice (bool callerIsWaiting/*=false*/)
//
//! Sets the devices into "streaming" state. Calls PA's Start stream routines.
//! This roughly corresponds to calling Start on the lower level interface.
-//!
+//!
//**********************************************************************************************
void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/)
{
unsigned int inChannelCount = pDeviceInfo->maxInputChannels;
unsigned int outChannelCount = pDeviceInfo->maxOutputChannels;
+ // Prepare for streaming - tell Engine to do the initialization for process callback
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
+
paErr = Pa_StartStream( m_PortAudioStream );
if(paErr == paNoError)
//
//! Sets the devices into "not streaming" state. Calls PA's Stop stream routines.
//! This roughly corresponds to calling Stop on the lower level interface.
-//!
+//!
//**********************************************************************************************
void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
{
std::cout << "API::Device " << m_DeviceName << " Stopping device stream" << std::endl;
paErr = Pa_StopStream( m_PortAudioStream );
- if(paErr == paNoError)
+ if(paErr == paNoError || paErr == paStreamIsStopped)
{
// if the stream was stopped successfully
m_IsStreaming = false;
}
else
{
- std::cout << "Failed to stop PA stream: " << Pa_GetErrorText (paErr) << std::endl;
- DEBUG_MSG( "Failed to stop PA stream " << Pa_GetErrorText (paErr) );
+ std::cout << "Failed to stop PA stream normaly! Error:" << Pa_GetErrorText (paErr) << std::endl;
+ DEBUG_MSG( "Failed to stop PA stream normaly! Error:" << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr;
}
}
//**********************************************************************************************
-// WCMRPortAudioDevice::resetDevice
+// WCMRPortAudioDevice::resetDevice
//
//! Resets the device, updates device info. Importnat: does PA reinitialization calling
//! Pa_terminate/Pa_initialize functions.
//!
//! \param none
-//!
+//!
//! \return nothing
-//!
+//!
//**********************************************************************************************
void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
{
- std::cout << "API::Device" << m_DeviceName << "Reseting device" << std::endl;
-
PaError paErr = paNoError;
// Keep device sates
if (paErr != paNoError)
{
continue;
- }
+ }
m_CurrentBufferSize = preferredSize;
paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize);
// Resume streaming if the device was streaming before
if(wasStreaming && m_lastErr == eNoErr && m_ConnectionStatus == DeviceAvailable)
{
- // Notify the Application to prepare for the stream start
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
+ // start streaming
startStreaming();
}
} else {
case kAsioResyncRequest:
m_ResyncRequested++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResyncRequest" << std::endl;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
break;
case kAsioLatenciesChanged:
m_BufferSizeChangeRequested++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioLatenciesChanged" << std::endl;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ if (m_ResetRequested == 0) {
+ m_ResetRequested++;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ }
break;
case kAsioBufferSizeChange:
m_BufferSizeChangeRequested++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- m_BufferSizeChangeRequested" << std::endl;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ if (m_ResetRequested == 0) {
+ m_ResetRequested++;
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ }
break;
case kAsioResetRequest:
- m_ResetRequested++;
std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResetRequest" << std::endl;
+ m_ResetRequested++;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
break;
//**********************************************************************************************
-// WCMRPortAudioDevice::DoIdle
+// WCMRPortAudioDevice::DoIdle
//
//! A place for doing idle time processing. The other derived classes will probably do something
//! meaningful.
//!
//! \param none
-//!
+//!
//! \return eNoErr always.
-//!
+//!
//**********************************************************************************************
WTErr WCMRPortAudioDevice::DoIdle ()
{
WTErr retVal = eNoErr;
std::cout << "WCMRPortAudioDevice::DoIdle ()" << std::endl;
- HANDLE hEvents[] =
+ HANDLE hEvents[] =
{
m_hUpdateDeviceInfoRequestedEvent,
m_hActivateRequestedEvent,
//**********************************************************************************************
-// WCMRPortAudioDevice::SetMonitorChannels
+// WCMRPortAudioDevice::SetMonitorChannels
//
//! Used to set the channels to be used for monitoring.
//!
//! \param leftChannel : Left monitor channel index.
//! \param rightChannel : Right monitor channel index.
-//!
+//!
//! \return eNoErr always, the derived classes may return appropriate errors.
-//!
+//!
//**********************************************************************************************
WTErr WCMRPortAudioDevice::SetMonitorChannels (int leftChannel, int rightChannel)
{
//**********************************************************************************************
-// WCMRPortAudioDevice::SetMonitorGain
+// WCMRPortAudioDevice::SetMonitorGain
//
//! Used to set monitor gain (or atten).
//!
-//! \param newGain : The new gain or atten. value to use. Specified as a linear multiplier (not dB)
-//!
+//! \param newGain : The new gain or atten. value to use. Specified as a linear multiplier (not dB)
+//!
//! \return eNoErr always, the derived classes may return appropriate errors.
-//!
+//!
//**********************************************************************************************
WTErr WCMRPortAudioDevice::SetMonitorGain (float newGain)
{
//**********************************************************************************************
-// WCMRPortAudioDevice::ShowConfigPanel
+// WCMRPortAudioDevice::ShowConfigPanel
//
//! Used to show device specific config/control panel. Some interfaces may not support it.
//! Some interfaces may require the device to be active before it can display a panel.
//!
//! \param pParam : A device/interface specific parameter, should be the app window handle for ASIO.
-//!
+//!
//! \return eNoErr always, the derived classes may return errors.
-//!
+//!
//**********************************************************************************************
WTErr WCMRPortAudioDevice::ShowConfigPanel (void *pParam)
{
AUTO_FUNC_DEBUG;
WTErr retVal = eNoErr;
- if (Active())
+ if (Active() && !m_ResetRequested )
{
#ifdef PLATFORM_WINDOWS
if(Pa_GetHostApiInfo(Pa_GetDeviceInfo(m_DeviceID)->hostApi)->type == paASIO)
// stop and deactivate the device
bool wasStreaming = Streaming();
SetActive(false);
+
// show control panel for the device
if (PaAsio_ShowControlPanel (m_DeviceID, pParam) != paNoError)
retVal = eGenericErr;
- // reset device to pick up changes
- ResetDevice();
+
// restore previous state for the device
SetActive(true);
if (wasStreaming)
SetStreaming(true);
+
+
+ // reset device to pick up changes
+ if (!m_ResetRequested) {
+ m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+ }
}
#else
pParam = pParam;
//*****************************************************************************************************
// WCMRPortAudioDevice::TheCallback
//
-//! The (static) Port Audio Callback function. This is a static member. It calls on the AudioCallback in the
+//! The (static) Port Audio Callback function. This is a static member. It calls on the AudioCallback in the
//! WCMRPortAudioDevice to do the real work.
//!
//! \param pInputBuffer: pointer to input buffer.
//! \param pTimeInfo: time info for PaStream callback.
//! \param statusFlags:
//! \param pUserData: pointer to user data, in our case the WCMRPortAudioDevice object.
-//!
+//!
//! \return true to stop streaming else returns false.
//******************************************************************************************************
-int WCMRPortAudioDevice::TheCallback (const void *pInputBuffer, void *pOutputBuffer, unsigned long framesPerBuffer,
+int WCMRPortAudioDevice::TheCallback (const void *pInputBuffer, void *pOutputBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* /*pTimeInfo*/, PaStreamCallbackFlags statusFlags, void *pUserData )
{
WCMRPortAudioDevice *pMyDevice = (WCMRPortAudioDevice *)pUserData;
//**********************************************************************************************
-// WCMRPortAudioDevice::AudoiCallback
+// WCMRPortAudioDevice::AudoiCallback
//
-//! Here's where the actual audio processing happens. We call upon all the active connections'
-//! sinks to provide data to us which can be put/mixed in the output buffer! Also, we make the
+//! Here's where the actual audio processing happens. We call upon all the active connections'
+//! sinks to provide data to us which can be put/mixed in the output buffer! Also, we make the
//! input data available to any sources that may call upon us during this time!
//!
//! \param *pInputBuffer : Points to a buffer with recorded data.
//! which are interleaved, is fixed at Device Open (Active) time. In this implementation,
//! the number of channels are fixed to use the maximum available.
//! \param dropsDetected : True if dropouts were detected in input or output. Can be used to signal the GUI.
-//!
+//!
//! \return true
-//!
+//!
//**********************************************************************************************
int WCMRPortAudioDevice::AudioCallback( const float *pInputBuffer, float *pOutputBuffer, unsigned long framesPerBuffer, bool dropsDetected )
{
m_SampleCounter,
theStartTime.MicroSeconds()*1000
};
-
+
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData );
//Don't try to access after this call returns!
//! \param *pTheClient : The manager's client object (which receives notifications).
//! \param interfaceType : The PortAudio interface type to use for this manager - acts as a filter.
//! \param useMultithreading : Whether to use multi-threading for audio processing. Default is true.
-//!
+//!
//! \return Nothing.
-//!
+//!
//**********************************************************************************************
-WCMRPortAudioDeviceManager::WCMRPortAudioDeviceManager (WCMRAudioDeviceManagerClient *pTheClient,
+WCMRPortAudioDeviceManager::WCMRPortAudioDeviceManager (WCMRAudioDeviceManagerClient *pTheClient,
eAudioDeviceFilter eCurAudioDeviceFilter, bool useMultithreading, bool bNocopy)
: WCMRAudioDeviceManager (pTheClient, eCurAudioDeviceFilter)
, m_NoneDevice(0)
//! It clears the device list, releasing each of the device.
//!
//! \param none
-//!
+//!
//! \return Nothing.
-//!
+//!
//**********************************************************************************************
WCMRPortAudioDeviceManager::~WCMRPortAudioDeviceManager()
{
WCMRAudioDevice* WCMRPortAudioDeviceManager::initNewCurrentDeviceImpl(const std::string & deviceName)
{
destroyCurrentDeviceImpl();
-
+
std::cout << "API::PortAudioDeviceManager::initNewCurrentDevice " << deviceName << std::endl;
if (deviceName == m_NoneDevice->DeviceName() )
{
}
+WTErr WCMRPortAudioDeviceManager::getDeviceAvailableBufferSizes(DeviceID deviceId, std::vector<int>& buffers)
+{
+ WTErr retVal = eNoErr;
+
+ buffers.clear();
+
+ //make PA request to get actual device buffer sizes
+ long minSize, maxSize, preferredSize, granularity;
+
+ PaError paErr = PaAsio_GetAvailableBufferSizes(deviceId, &minSize, &maxSize, &preferredSize, &granularity);
+
+ //for Windows ASIO devices we always use prefferes buffer size ONLY
+ if (paNoError == paErr )
+ {
+ buffers.push_back(preferredSize);
+ }
+ else
+ {
+ retVal = eAsioFailed;
+ std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer sizes for device: "<< deviceId << std::endl;
+ }
+
+ return retVal;
+}
+
+
WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
{
std::cout << "API::PortAudioDeviceManager::Generating device list" << std::endl;
DeviceInfo *pDevInfo = new DeviceInfo(thisDeviceID, pPaDeviceInfo->name);
if (pDevInfo)
{
+ //Get available sample rates
std::vector<int> availableSampleRates;
WTErr wErr = WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(thisDeviceID, availableSampleRates);
pDevInfo->m_MaxInputChannels = pPaDeviceInfo->maxInputChannels;
pDevInfo->m_MaxOutputChannels = pPaDeviceInfo->maxOutputChannels;
+ //Get available buffer sizes
+ std::vector<int> availableBuffers;
+ wErr = getDeviceAvailableBufferSizes(thisDeviceID, availableBuffers);
+
+ if (wErr != eNoErr)
+ {
+ DEBUG_MSG ("Failed to get device available buffer sizes. Device ID: " << m_DeviceID);
+ delete pDevInfo;
+ continue; //proceed to the next device
+ }
+
+ pDevInfo->m_AvailableBufferSizes = availableBuffers;
+
//Now check if this device is acceptable according to current input/output settings
bool bRejectDevice = false;
switch(m_eAudioDeviceFilter)
m_DeviceInfoVec.push_back(pDevInfo);
break;
}
-
+
if(bRejectDevice)
{
TRACE_MSG ("API::PortAudioDeviceManager::Device " << pDevInfo->m_DeviceName << "Rejected. \
WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const
{
sampleRates.clear ();
-
+
WTErr retVal = eNoErr;
-
+
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
- sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() );
+ sampleRates=m_CurrentDevice->SamplingRates();
return retVal;
}
DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo);
-
+
if (eNoErr == retVal)
{
- sampleRates.assign(devInfo.m_AvailableSampleRates.begin(), devInfo.m_AvailableSampleRates.end() );
+ sampleRates=devInfo.m_AvailableSampleRates;
}
else
{
//first check if the request has been made for None device
if (deviceName == m_NoneDevice->DeviceName() )
{
- buffers.assign(m_NoneDevice->BufferSizes().begin(), m_NoneDevice->BufferSizes().end() );
+ buffers=m_NoneDevice->BufferSizes();
return retVal;
}
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
- buffers.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() );
+ buffers=m_CurrentDevice->BufferSizes();
return retVal;
}
- Pa_Initialize();
-
- DeviceInfo devInfo;
+ DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo);
if (eNoErr == retVal)
{
- //make PA request to get actual device buffer sizes
- long minSize, maxSize, preferredSize, granularity;
- PaError paErr = PaAsio_GetAvailableBufferSizes(devInfo.m_DeviceId, &minSize, &maxSize, &preferredSize, &granularity);
-
- //for Windows ASIO devices we always use prefferes buffer size ONLY
- if (paNoError == paErr )
- {
- buffers.push_back(preferredSize);
- }
- else
- {
- retVal = eAsioFailed;
- std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer sizes for device: "<< deviceName << std::endl;
- }
+ std::cout << "API::PortAudioDeviceManager::GetBufferSizes: got buffer :"<< devInfo.m_AvailableBufferSizes.front() << std::endl;
+ buffers = devInfo.m_AvailableBufferSizes;
}
else
{
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl;
}
- Pa_Terminate();
-
return retVal;
}