globally remove all trailing whitespace from .cpp and .hpp files missed by previous...
[ardour.git] / libs / backends / wavesaudio / wavesapi / devicemanager / WCMRPortAudioDeviceManager.cpp
index 6095cd6a85ca0d7d0b2bba0a1a4e820706681806..c039b49c0b23c2eecb555fb7725dea9a2d73db6a 100644 (file)
 #include "WCMRPortAudioDeviceManager.h"
 #include "MiscUtils/safe_delete.h"
 #include "UMicroseconds.h"
+#include <iostream>
 #include <sstream>
 #include <algorithm>
+#include <list>
 using namespace wvNS;
 #include "IncludeWindows.h"
-#include <MMSystem.h>
+#include <mmsystem.h>
 #include "pa_asio.h"
 #include "asio.h"
 
-///< Supported Sample rates                                                                                                  
+#define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 200
+#define DEVICE_INFO_UPDATE_SLEEP_TIME_MILLISECONDS 500
+#define PROPERTY_CHANGE_TIMEOUT_SECONDS 2
+#define PROPERTY_CHANGE_RETRIES 3
+
+///< Supported Sample rates
 static const double gAllSampleRates[] =
        {
-               44100.0, 48000.0, 88200.0, 96000.0, -1 /* negative terminated  list */
+               44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, -1 /* negative terminated  list */
        };
 
 
@@ -57,7 +64,7 @@ DWORD WINAPI WCMRPortAudioDevice::__DoIdle__(LPVOID lpThreadParameter)
 }
 
 //**********************************************************************************************
-// WCMRPortAudioDevice::WCMRPortAudioDevice 
+// WCMRPortAudioDevice::WCMRPortAudioDevice
 //
 //! Constructor for the audio device. Opens the PA device
 //! and gets information about the device.
@@ -67,9 +74,9 @@ DWORD WINAPI WCMRPortAudioDevice::__DoIdle__(LPVOID lpThreadParameter)
 //! \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)
@@ -223,16 +230,16 @@ void WCMRPortAudioDevice::terminateDevice()
 
 
 //**********************************************************************************************
-// 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 ()
 {
@@ -286,13 +293,13 @@ WTErr WCMRPortAudioDevice::UpdateDeviceInfo ()
 
 
 //**********************************************************************************************
-// 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*/)
 {
@@ -304,14 +311,12 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
        //update name.
        m_DeviceName = pDeviceInfo->name;
 
-       std::cout << "API::Device " << m_DeviceName << " Getting device info " << std::endl;
-
        //following parameters are needed opening test stream and for sample rates validation
        PaStreamParameters inputParameters, outputParameters;
        PaStreamParameters *pInS = NULL, *pOutS = NULL;
 
        inputParameters.device = m_DeviceID;
-       inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels);
+       inputParameters.channelCount = pDeviceInfo->maxInputChannels;
        inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
        inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
        inputParameters.hostApiSpecificStreamInfo = 0;
@@ -320,7 +325,7 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
                pInS = &inputParameters;
 
        outputParameters.device = m_DeviceID;
-       outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels);
+       outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
        outputParameters.sampleFormat = paFloat32;
        outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
        outputParameters.hostApiSpecificStreamInfo = 0;
@@ -328,7 +333,6 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
        if (outputParameters.channelCount)
                pOutS = &outputParameters;
 
-       std::cout << "API::Device" << m_DeviceName << " Updating sample rates " << std::endl;
        ////////////////////////////////////////////////////////////////////////////////////
        //update list of supported SRs...
        m_SamplingRates.clear();
@@ -344,54 +348,27 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
                }
        }
 
-       std::cout << "API::Device" << m_DeviceName << " Updating buffer sizes" << std::endl;
        ///////////////////////////////////////////////////////////////////////////////////
        //update buffer sizes
        m_BufferSizes.clear();
        bool useDefaultBuffers = true;
-       PaError paErr = paNoError;
-
-       //sometimes devices change buffer size if sample rate changes
-       //it updates buffer size during stream opening
-       //we need to find out how device would behave with current sample rate
-       //try opening test stream to load device driver for current sample rate and buffer size
-       //(skip this step if the device is Active)
-       if ( !Active() )
-       {
-               if (paNoError != testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize) )
-               {
-                       //buffer size did change
-                       Pa_Terminate();
-                       Pa_Initialize();
-
-                       // test validness with current sample rate and device prefered buffer size
-                       paErr = testStateValidness(m_CurrentSamplingRate, 0);
-               }
-       }
 
-       if (paErr == paNoError)
-       {
-               // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel 
-               long minSize, maxSize, preferredSize, granularity;
-               paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
+       // 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);
        
-               if (paErr == paNoError)
-               {
-                       std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
+       if (err == paNoError)
+       {
+               std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
                        
-                       m_BufferSizes.push_back (preferredSize);
-                       useDefaultBuffers = false;
-               }
-               else
-               {
-                       std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
-               }
+               m_BufferSizes.push_back (preferredSize);
+               useDefaultBuffers = false;
        }
        else
        {
-               std::cout << "API::Device" << m_DeviceName << " Device does not start with sample rate: "<< m_CurrentSamplingRate << " and default buffer size" << std::endl;
+               std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
        }
-
+       
        if (useDefaultBuffers)
        {
                std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl;
@@ -409,9 +386,22 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
                m_InputChannels.clear();
                for (int channel = 0; channel < maxInputChannels; channel++)
                {
+                       const char* channelName[32]; // 32 is max leth declared by PortAudio for this operation
                        std::stringstream chNameStream;
-                       //A better implementation would be to retrieve the names from ASIO or CoreAudio interfaces
-                       chNameStream << "Input " << (channel+1);
+
+                       PaError error = PaAsio_GetInputChannelName(m_DeviceID, channel, channelName);
+
+                       chNameStream << (channel+1) << " - ";
+
+                       if (error == paNoError)
+                       {
+                               chNameStream << *channelName;
+                       }
+                       else
+                       {
+                               chNameStream << "Input " << (channel+1);
+                       }
+
                        m_InputChannels.push_back (chNameStream.str());
                }
        
@@ -420,9 +410,22 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
                m_OutputChannels.clear();
                for (int channel = 0; channel < maxOutputChannels; channel++)
                {
+                       const char* channelName[32]; // 32 is max leth declared by PortAudio for this operation
                        std::stringstream chNameStream;
-                       //A better implementation would be to retrieve the names from ASIO or CoreAudio interfaces
-                       chNameStream << "Output " << (channel+1);
+                       
+                       PaError error = PaAsio_GetOutputChannelName(m_DeviceID, channel, channelName);
+                       
+                       chNameStream << (channel+1) << " - ";
+
+                       if (error == paNoError)
+                       {
+                               chNameStream << *channelName;
+                       }
+                       else
+                       {
+                               chNameStream << "Output " << (channel+1);
+                       }
+                       
                        m_OutputChannels.push_back (chNameStream.str());
                }
        }
@@ -446,18 +449,18 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
        PaStreamParameters *pInS = NULL, *pOutS = NULL;
 
        inputParameters.device = m_DeviceID;
-       inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels);
+       inputParameters.channelCount = pDeviceInfo->maxInputChannels;
        inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
-       inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+       inputParameters.suggestedLatency = 0;
        inputParameters.hostApiSpecificStreamInfo = 0;
 
        if (inputParameters.channelCount)
                pInS = &inputParameters;
 
        outputParameters.device = m_DeviceID;
-       outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels);
+       outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
        outputParameters.sampleFormat = paFloat32;
-       outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+       outputParameters.suggestedLatency = 0;
        outputParameters.hostApiSpecificStreamInfo = 0;
 
        if (outputParameters.channelCount)
@@ -469,7 +472,7 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
        //it updates buffer size during stream opening
        //we need to find out how device would behave with current sample rate
        //try opening test stream to load device driver for current sample rate and buffer size
-       paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, m_CurrentSamplingRate, m_CurrentBufferSize, paDitherOff, NULL, NULL);
+       paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, sampleRate, bufferSize, paDitherOff, NULL, NULL);
        
        if (portAudioStream)
        {
@@ -483,15 +486,15 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
 
 
 //**********************************************************************************************
-// 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 ()
 {
@@ -558,14 +561,14 @@ WTErr WCMRPortAudioDevice::ResetDevice()
 
 
 //**********************************************************************************************
-// 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)
 {
@@ -598,35 +601,18 @@ WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
                return (retVal);
        }
        
-       if (oldActive)
-       {
-               //Deactivate it for the change...
-               SetActive (false);
-       }
-       
        //make the change...
        m_CurrentSamplingRate = newRate;
+       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
 
-       // Before reactivating the device: opening stream we should try getting buffer size update from the device
-       // because for new sampling rate some devices may change buffer size as well
-       int oldBufferSize = m_CurrentBufferSize;
-       
-       retVal = ResetDevice();
-
-       //reactivate it.        
-       if (oldActive && retVal == eNoErr)
+       if (paErr != paNoError)
        {
-               retVal = SetActive (true);
-       }
+               std::cout << "Sample rate change failed: " <<  Pa_GetErrorText (paErr) << std::endl;
+               if (paErr ==  paUnanticipatedHostError)
+                       std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
 
-       if (retVal != eNoErr)
-       {
-               //revert changes if the device was not activated
-               m_CurrentSamplingRate = oldRate;
-               m_CurrentBufferSize = oldBufferSize;
-               int bufferSize = m_CurrentBufferSize;
-               m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
-               retVal = eCommandLineParameter;
+               retVal = eWrongObjectState;
        }
        
        return (retVal);
@@ -636,13 +622,13 @@ WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
 //**********************************************************************************************
 // 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 ()
 {
@@ -653,13 +639,13 @@ 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)
 {
@@ -667,43 +653,24 @@ 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);
-       
-       //see if this is one of our supported rates...
-       intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
-       if (intIter == m_BufferSizes.end())
-       {
-               //Can't change, perhaps use an "invalid param" type of error
-               retVal = eCommandLineParameter;
-               return (retVal);
-       }
-       
        if (Streaming())
        {
                //Can't change, perhaps use an "in use" type of error
                retVal = eGenericErr;
                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);
@@ -711,15 +678,15 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
 
 
 //**********************************************************************************************
-// 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 ()
 {
@@ -734,7 +701,7 @@ 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.
 //!
 //**********************************************************************************************
@@ -770,20 +737,44 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
 
                if (outputParameters.channelCount)
                        pOutS = &outputParameters;
-               
-               std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
+
+               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);
+               paErr = Pa_OpenStream(&m_PortAudioStream,
+                                                               pInS,
+                                                               pOutS,
+                                                               m_CurrentSamplingRate,
+                                                               m_CurrentBufferSize,
+                                                               paDitherOff,
+                                                               WCMRPortAudioDevice::TheCallback,
+                                                               this);
+                       
+               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_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&preferredSize);
+                       }
+
                        m_DropsDetected = 0;
                        m_DropsReported = 0;
                        m_IgnoreThisDrop = true;
@@ -796,6 +787,7 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
                                m_ResetReported = 0;
                                m_ResyncRequested = 0;
                                m_ResyncReported = 0;
+                               std::cout << "Installing new mesage hook "<< std::endl;
                                PaAsio_SetMessageHook (StaticASIOMessageHook, this);
                        }
                        m_IsActive = true;
@@ -805,8 +797,8 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
                else
                {
                        //failed, do not update device state
-                       std::cout << "Failed to open pa stream stream " << paErr << std::endl;
-                       DEBUG_MSG( "Failed to open pa stream stream " << paErr );
+                       std::cout << "Failed to open pa stream: " <<  Pa_GetErrorText (paErr) << std::endl;
+                       DEBUG_MSG( "Failed to open pa stream: " << Pa_GetErrorText (paErr) );
                        m_ConnectionStatus = DeviceErrors;
                        m_lastErr = eAsioFailed;
                }
@@ -814,6 +806,8 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
        
        }
 
+       std::cout << "Activation is DONE "<< std::endl;
+
        if (callerIsWaiting)
                SetEvent(m_hActivationDone);
 }
@@ -823,7 +817,7 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
 // 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*/)
@@ -866,8 +860,8 @@ void WCMRPortAudioDevice::deactivateDevice (bool callerIsWaiting/*=false*/)
                        else
                        {
                                //failed, do not update device state
-                               std::cout << "Failed to close pa stream stream " << paErr << std::endl;
-                               DEBUG_MSG( "Failed to open pa stream stream " << paErr );
+                               std::cout << "Failed to close pa stream stream " <<  Pa_GetErrorText (paErr) << std::endl;
+                               DEBUG_MSG( "Failed to open pa stream stream " << Pa_GetErrorText (paErr) );
                                m_ConnectionStatus = DeviceErrors;
                                m_lastErr = eAsioFailed;
                        }
@@ -884,7 +878,7 @@ 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*/)
 {
@@ -898,17 +892,28 @@ void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/)
                m_SampleCounter = 0;
 
                std::cout << "API::Device" << m_DeviceName << " Starting device stream" << std::endl;
+               
+               //get device info
+               const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
+       
+               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)
                {
                        // if the stream was started successfully
                        m_IsStreaming = true;
+                       std::cout << "API::Device" << m_DeviceName << " Device is streaming" << std::endl;
                }
                else
                {
-                       std::cout << "Failed to start PA stream: " << paErr << std::endl;
-                       DEBUG_MSG( "Failed to start PA stream: " << paErr );
+                       std::cout << "Failed to start PA stream: " <<  Pa_GetErrorText (paErr) << std::endl;
+                       DEBUG_MSG( "Failed to start PA stream: " << Pa_GetErrorText (paErr) );
                        m_lastErr = eGenericErr;
                }
        }
@@ -923,7 +928,7 @@ void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/)
 //
 //! 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*/)
 {
@@ -938,7 +943,7 @@ 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;
@@ -946,8 +951,8 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
                }
                else
                {
-                       std::cout << "Failed to stop PA stream: " << paErr << std::endl;
-                       DEBUG_MSG( "Failed to stop PA stream " << 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;
                }
        }
@@ -958,74 +963,93 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
 
 
 //**********************************************************************************************
-// 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
        bool wasStreaming = Streaming();
        bool wasActive = Active();
 
-       // Notify the Application about reset
-       m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
-
        // Reset the device
        stopStreaming();
        deactivateDevice();
 
-       // Reinitialize PA
-       Pa_Terminate();
-       Pa_Initialize();
-
-       updateDeviceInfo();
-
        // Cache device buffer size as it might be changed during reset
        int oldBufferSize = m_CurrentBufferSize;
 
-       // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
-       // Backend should always use preffered buffer size value in this case
-       long minSize, maxSize, preferredSize, granularity;
-       PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
-
-       if (paErr == paNoError)
+       // Now, validate the state and update device info if required
+       unsigned int retry = PROPERTY_CHANGE_RETRIES;
+       while (retry-- )
        {
+               // Reinitialize PA
+               Pa_Terminate();
+               Pa_Initialize();
+                       
+               std::cout << "Updating device state... " << std::endl;
+               // update device info
+               updateDeviceInfo();
+
+               // take up buffers
+               long minSize, maxSize, preferredSize, granularity;
+               PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
+
+               if (paErr != paNoError)
+               {
+                       continue;
+               }
                m_CurrentBufferSize = preferredSize;
-       }
-       else
-       {
-               // if we can't get device buffer sizes, use the first one among supported
-               if (m_BufferSizes.size() != 0)
-                       m_CurrentBufferSize = m_BufferSizes.front();
+
+               paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize);
+               if (paNoError ==  paErr)
+               {
+                       std::cout << "Device state is valid" << std::endl;
+                       break;
+               }
+
+               std::cout << "Cannot start with current state: sr: " << m_CurrentSamplingRate << " bs:" << m_CurrentBufferSize \
+                                       << "\nReason: " <<  Pa_GetErrorText (paErr) << std::endl;
+               if (paErr ==  paUnanticipatedHostError)
+                       std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
+
+               std::cout << "Will try again in " << DEVICE_INFO_UPDATE_SLEEP_TIME_MILLISECONDS << "msec" << std::endl;
+
+               Pa_Sleep(DEVICE_INFO_UPDATE_SLEEP_TIME_MILLISECONDS);
        }
 
-       // Notify the Application about device setting changes
-       if (oldBufferSize != m_CurrentBufferSize)
+       if (paErr == paNoError)
        {
-               std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
-               int bufferSize = m_CurrentBufferSize;
-               m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
-       }
+               // Notify the Application about device setting changes
+               if (oldBufferSize != m_CurrentBufferSize)
+               {
+                       std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
+                       int bufferSize = m_CurrentBufferSize;
+                       m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
+               }
 
-       // Activate the device if it was active before
-       if (wasActive)
-               activateDevice();
+               // Activate the device if it was active before
+               if (wasActive)
+                       activateDevice();
 
-       // Resume streaming if the device was streaming before
-       if(wasStreaming)
-       {
-               // Notify the Application to prepare for the stream start
-               m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
-               startStreaming();
+               // Resume streaming if the device was streaming before
+               if(wasStreaming && m_lastErr == eNoErr && m_ConnectionStatus == DeviceAvailable)
+               {
+                       // start streaming
+                       startStreaming();
+               }
+       } else {
+               m_ConnectionStatus = DeviceErrors;
+               m_lastErr = eWrongObjectState;
        }
 
        if (callerIsWaiting)
@@ -1049,32 +1073,39 @@ long WCMRPortAudioDevice::ASIOMessageHook (long selector, long WCUNUSEDPARAM(val
 {
        switch(selector)
        {
-               case kAsioBufferSizeChange:
-                       m_BufferSizeChangeRequested++;
-                       std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- m_BufferSizeChangeRequested" << std::endl;
-                       SetEvent(m_hBufferSizeChangedEvent);
-                       break;
-
-               case kAsioResetRequest:
-                       m_ResetRequested++;
-                       std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResetRequest" << std::endl;
-                       SetEvent(m_hResetFromDevRequestedEvent);
-                       break;
-
                case kAsioResyncRequest:
-                       std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResyncRequest" << std::endl;
                        m_ResyncRequested++;
+                       std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResyncRequest" << std::endl;
                        break;
 
                case kAsioLatenciesChanged:
+                       m_BufferSizeChangeRequested++;
                        std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioLatenciesChanged" << std::endl;
-                       SetEvent(m_hBufferSizeChangedEvent);
+                       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;
+                       if (m_ResetRequested == 0) {
+                               m_ResetRequested++;
+                               m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
+                       }
+                       break;
+
+               case kAsioResetRequest:
+                       std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResetRequest" << std::endl;
+                       m_ResetRequested++;
+                       m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
                        break;
 
         case kAsioOverload:
+                       m_DropsDetected++;
                        std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioOverload" << std::endl;
-            m_DropsDetected++;
+                       m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout);
             break;
        }
        return 0;
@@ -1084,22 +1115,22 @@ long WCMRPortAudioDevice::ASIOMessageHook (long selector, long WCUNUSEDPARAM(val
 
 
 //**********************************************************************************************
-// 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,
@@ -1187,15 +1218,15 @@ WTErr WCMRPortAudioDevice::DoIdle ()
 
 
 //**********************************************************************************************
-// 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)
 {
@@ -1210,14 +1241,14 @@ 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)
 {
@@ -1233,22 +1264,22 @@ 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)
@@ -1256,15 +1287,21 @@ WTErr WCMRPortAudioDevice::ShowConfigPanel (void *pParam)
                        // 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;
@@ -1278,7 +1315,7 @@ WTErr WCMRPortAudioDevice::ShowConfigPanel (void *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.
@@ -1287,10 +1324,10 @@ WTErr WCMRPortAudioDevice::ShowConfigPanel (void *pParam)
 //! \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;
@@ -1305,10 +1342,10 @@ int WCMRPortAudioDevice::TheCallback (const void *pInputBuffer, void *pOutputBuf
 
 
 //**********************************************************************************************
-// 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.
@@ -1317,9 +1354,9 @@ int WCMRPortAudioDevice::TheCallback (const void *pInputBuffer, void *pOutputBuf
 //!            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 )
 {
@@ -1345,7 +1382,7 @@ int WCMRPortAudioDevice::AudioCallback( const float *pInputBuffer, float *pOutpu
                m_SampleCounter,
                theStartTime.MicroSeconds()*1000
     };
-    
+
     m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData );
 
        //Don't try to  access after this call returns!
@@ -1367,11 +1404,11 @@ int WCMRPortAudioDevice::AudioCallback( const float *pInputBuffer, float *pOutpu
 //! \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)
@@ -1399,9 +1436,9 @@ WCMRPortAudioDeviceManager::WCMRPortAudioDeviceManager (WCMRAudioDeviceManagerCl
 //! It clears the device list, releasing each of the device.
 //!
 //! \param none
-//! 
+//!
 //! \return Nothing.
-//! 
+//!
 //**********************************************************************************************
 WCMRPortAudioDeviceManager::~WCMRPortAudioDeviceManager()
 {
@@ -1426,7 +1463,7 @@ WCMRPortAudioDeviceManager::~WCMRPortAudioDeviceManager()
 WCMRAudioDevice* WCMRPortAudioDeviceManager::initNewCurrentDeviceImpl(const std::string & deviceName)
 {
     destroyCurrentDeviceImpl();
-    
+
        std::cout << "API::PortAudioDeviceManager::initNewCurrentDevice " << deviceName << std::endl;
        if (deviceName == m_NoneDevice->DeviceName() )
        {
@@ -1468,6 +1505,8 @@ void WCMRPortAudioDeviceManager::destroyCurrentDeviceImpl()
 
 WTErr WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates)
 {
+       WTErr retVal = eNoErr;
+
        sampleRates.clear();
        const PaDeviceInfo *pPaDeviceInfo = Pa_GetDeviceInfo(deviceId);
 
@@ -1501,6 +1540,34 @@ WTErr WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI
                        sampleRates.push_back ((int)gAllSampleRates[sr]);
                }
        }
+
+       return retVal;
+}
+
+
+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;
 }
 
 
@@ -1550,6 +1617,7 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
                                DeviceInfo *pDevInfo = new DeviceInfo(thisDeviceID, pPaDeviceInfo->name);
                                if (pDevInfo)
                                {
+                                       //Get available sample rates
                                        std::vector<int> availableSampleRates;
                                        WTErr wErr = WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(thisDeviceID, availableSampleRates);
 
@@ -1564,6 +1632,19 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
                                        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)
@@ -1606,7 +1687,7 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
                                                        m_DeviceInfoVec.push_back(pDevInfo);
                                                        break;
                                        }
-                
+
                                        if(bRejectDevice)
                                        {
                                                TRACE_MSG ("API::PortAudioDeviceManager::Device " << pDevInfo->m_DeviceName << "Rejected. \
@@ -1637,61 +1718,65 @@ WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
 }
 
 
+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=m_CurrentDevice->SamplingRates();
+               return retVal;
+       }
+
+    DeviceInfo devInfo;
+       retVal = GetDeviceInfoByName(deviceName, devInfo);
+
+       if (eNoErr == retVal)
+       {
+               sampleRates=devInfo.m_AvailableSampleRates;
+       }
+       else
+       {
+               std::cout << "API::PortAudioDeviceManager::GetSampleRates: Device not found: "<< deviceName << std::endl;
+       }
+
+       return retVal;
+}
+
+
 WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const
 {
        WTErr retVal = eNoErr;
-       std::cout << "API::PortAudioDeviceManager::GetBufferSizes: getting buffer size for device: "<< deviceName << std::endl;
+       
+       buffers.clear();
+
        //first check if the request has been made for None device
        if (deviceName == m_NoneDevice->DeviceName() )
        {
-               buffers = m_NoneDevice->BufferSizes();
+               buffers=m_NoneDevice->BufferSizes();
                return retVal;
        }
-
-       //if we have current device initialized and it's PA device, reset it
-       //this procedure will reset PA corrently and update info for all PA devices as well
        
-       bool paLocalInit = false;
-       WCMRPortAudioDevice* portaudioDevice = dynamic_cast<WCMRPortAudioDevice*>(m_CurrentDevice);
-       if (portaudioDevice)
-       {
-               portaudioDevice->ResetDevice();
-       }
-       else
+       if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
        {
-               //initialize PA to get buffers for the device
-               Pa_Initialize();
-               paLocalInit = true;
+               buffers=m_CurrentDevice->BufferSizes();
+               return retVal;
        }
 
-       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: " << paErr << " getting buffer size fo 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;
        }
 
-       //deinitialize PA now
-       if (paLocalInit)
-               Pa_Terminate();
-
        return retVal;
 }