summaryrefslogtreecommitdiff
path: root/libs/backends/wavesaudio/wavesapi/devicemanager
diff options
context:
space:
mode:
Diffstat (limited to 'libs/backends/wavesaudio/wavesapi/devicemanager')
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/IncludeWindows.h50
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp692
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h271
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp3140
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h209
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp266
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h96
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp1782
-rw-r--r--libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h180
9 files changed, 0 insertions, 6686 deletions
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/IncludeWindows.h b/libs/backends/wavesaudio/wavesapi/devicemanager/IncludeWindows.h
deleted file mode 100644
index 53ed7e69bc..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/IncludeWindows.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- Copyright (C) 2014 Waves Audio Ltd.
-
- 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.
-
-*/
-
-#ifndef __IncludeWindows_h__
-#define __IncludeWindows_h__
-
-#ifdef PLATFORM_WINDOWS
-
-/* Copy to include
-#include "IncludeWindows.h"
-*/
-
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0601 // Windows 7
-#endif
-
-#ifndef WINVER
-#define WINVER 0x0601 // Windows 7
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#ifndef NOMINMAX
-#define NOMINMAX // DO NOT REMOVE NOMINMAX - DOING SO CAUSES CONFLICTS WITH STD INCLUDES (<limits> ...)
-#endif
-
-#include <winsock2.h>
-#include <windows.h>
-#include <objbase.h>
-#endif // #if PLATFORM_WINDOWS
-#endif // #ifndef __IncludeWindows_h__
-
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp
deleted file mode 100644
index 7c4a3e9962..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-//----------------------------------------------------------------------------------
-//
-// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
-//
-//! \file WCMRAudioDeviceManager.cpp
-//!
-//! WCMRAudioDeviceManager and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#include <iostream>
-#include "WCMRAudioDeviceManager.h"
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::WCMRAudioDevice
-//
-//! Constructor for the audio device. The derived classes will need to do more actual work, such
-//! as determining supported sampling rates, buffer sizes, and channel counts. Connection
-//! and streaming will also be provided by the derived implementations.
-//!
-//! \param *pManager : The audio device manager that's managing this device.
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRAudioDevice::WCMRAudioDevice (WCMRAudioDeviceManager *pManager) :
- m_pMyManager (pManager)
- , m_ConnectionStatus (DeviceDisconnected)
- , m_IsActive (false)
- , m_IsStreaming (false)
- , m_CurrentSamplingRate (-1)
- , m_CurrentBufferSize (0)
- , m_LeftMonitorChannel (-1)
- , m_RightMonitorChannel (-1)
- , m_MonitorGain (1.0f)
-{
- m_DeviceName = "Unknown";
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::~WCMRAudioDevice
-//
-//! Destructor for the audio device. It release all the connections that were created.
-//!
-//! \param none
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRAudioDevice::~WCMRAudioDevice ()
-{
- AUTO_FUNC_DEBUG;
- try
- {
- }
- catch (...)
- {
- //destructors should absorb exceptions, no harm in logging though!!
- DEBUG_MSG ("Exception during destructor");
- }
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::DeviceName
-//
-//! Retrieves Device's name.
-//!
-//! \param none
-//!
-//! \return The device name.
-//!
-//**********************************************************************************************
-const std::string& WCMRAudioDevice::DeviceName () const
-{
- return (m_DeviceName);
-
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::InputChannels
-//
-//! Retrieves Input Channel information. Note that the list may be changed at run-time.
-//!
-//! \param none
-//!
-//! \return A vector with Input Channel Names.
-//!
-//**********************************************************************************************
-const std::vector<std::string>& WCMRAudioDevice::InputChannels ()
-{
- return (m_InputChannels);
-
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::OutputChannels
-//
-//! Retrieves Output Channel Information. Note that the list may be changed at run-time.
-//!
-//! \param none
-//!
-//! \return A vector with Output Channel Names.
-//!
-//**********************************************************************************************
-const std::vector<std::string>& WCMRAudioDevice::OutputChannels ()
-{
- return (m_OutputChannels);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::SamplingRates
-//
-//! Retrieves supported sampling rate information.
-//!
-//! \param none
-//!
-//! \return A vector with supported sampling rates.
-//!
-//**********************************************************************************************
-const std::vector<int>& WCMRAudioDevice::SamplingRates ()
-{
- return (m_SamplingRates);
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::CurrentSamplingRate
-//
-//! 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 WCMRAudioDevice::CurrentSamplingRate ()
-{
- return (m_CurrentSamplingRate);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::SetCurrentSamplingRate
-//
-//! Change the sampling rate to be used by the device. This will most likely be overridden,
-//! the base class simply updates the member variable.
-//!
-//! \param newRate : The rate to use (samples per sec).
-//!
-//! \return eNoErr always. The derived classes may return error codes.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::SetCurrentSamplingRate (int newRate)
-{
- //changes the status.
- m_CurrentSamplingRate = newRate;
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::BufferSizes
-//
-//! Retrieves supported buffer size information.
-//!
-//! \param none
-//!
-//! \return A vector with supported buffer sizes.
-//!
-//**********************************************************************************************
-const std::vector<int>& WCMRAudioDevice::BufferSizes ()
-{
- return (m_BufferSizes);
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::CurrentBufferSize
-//
-//! 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 WCMRAudioDevice::CurrentBufferSize ()
-{
- return (m_CurrentBufferSize);
-}
-
-//**********************************************************************************************
-// WCMRAudioDevice::CurrentBlockSize
-//
-//! Device's block size we use for holding the audio samples.
-//! Usually this is equal to the buffer size, but in some cases the buffer size holds additional
-//! data other then the audio buffers, like frames info in SG, so it can be overridden
-//!
-//! \param none
-//!
-//! \return The device's current block size. 0 on error.
-//!
-//**********************************************************************************************
-int WCMRAudioDevice::CurrentBlockSize()
-{
- // By default - return the buffer size
- return CurrentBufferSize();
-}
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::SetCurrentBufferSize
-//
-//! 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 WCMRAudioDevice::SetCurrentBufferSize (int newSize)
-{
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_CurrentBufferSize = newSize;
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::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.
-//!
-//**********************************************************************************************
-WCMRAudioDevice::ConnectionStates WCMRAudioDevice::ConnectionStatus ()
-{
- return (m_ConnectionStatus);
-
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::Active
-//
-//! Retrieves Device activation status.
-//!
-//! \param none
-//!
-//! \return true if device is active, false otherwise.
-//!
-//**********************************************************************************************
-bool WCMRAudioDevice::Active ()
-{
- return (m_IsActive);
-
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::SetActive
-//
-//! Sets the device's activation status.
-//!
-//! \param newState : Should be true to activate, false to deactivate. This roughly corresponds
-//! to opening and closing the device handle/stream/audio unit.
-//!
-//! \return eNoErr always, the derived classes may return appropriate error code.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::SetActive (bool newState)
-{
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_IsActive = newState;
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::Streaming
-//
-//! Retrieves Device streaming status.
-//!
-//! \param none
-//!
-//! \return true if device is streaming, false otherwise.
-//!
-//**********************************************************************************************
-bool WCMRAudioDevice::Streaming ()
-{
- return (m_IsStreaming);
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::SetStreaming
-//
-//! Sets the device's streaming status.
-//!
-//! \param newState : Should be true to start streaming, false to stop streaming. This roughly
-//! corresponds to calling Start/Stop on the lower level interface.
-//!
-//! \return eNoErr always, the derived classes may return appropriate error code.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::SetStreaming (bool newState)
-{
- // We must notify angine about our intention to start streming
- // so Engine will provide all the initializations in the first audio callback
- if (newState) {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
- }
-
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_IsStreaming = newState;
- return (eNoErr);
-}
-
-
-WTErr WCMRAudioDevice::ResetDevice ()
-{
- // Keep device sates
- bool wasStreaming = Streaming();
- bool wasActive = Active();
-
- WTErr err = SetStreaming(false);
-
- if (err == eNoErr)
- err = SetActive(false);
-
- if (err == eNoErr && wasActive)
- err = SetActive(true);
-
- if (err == eNoErr && wasStreaming)
- SetStreaming(true);
-
- return err;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// IsProcessActive - returns true if process code is running.
-// A normal audio device should return the Streaming() value
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-bool WCMRAudioDevice::IsProcessActive()
-{
- return Streaming();
-}
-
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::DoIdle
-//
-//! A place for doing idle time processing. The derived classes will probably do something
-//! meaningful.
-//!
-//! \param none
-//!
-//! \return eNoErr always.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::DoIdle ()
-{
- //We don't need to do anything here...
- //the derived classes may want to use this however.
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::InputLevels
-//
-//! Retrieve current input levels.
-//!
-//! \param none
-//!
-//! \return A vector (the same size as input channels list) that contains current input levels.
-//!
-//**********************************************************************************************
-const std::vector<float>& WCMRAudioDevice::InputLevels ()
-{
- //The derived classes may override if they need to query
- //the driver for the levels.
- return (m_InputLevels);
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::OutputLevels
-//
-//! Retrieve current output levels.
-//!
-//! \param none
-//!
-//! \return A vector (the same size as output channels list) that contains current output levels.
-//!
-//**********************************************************************************************
-const std::vector<float>& WCMRAudioDevice::OutputLevels ()
-{
- //The derived classes may override if they need to query
- //the driver for the levels.
- return (m_OutputLevels);
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::GetMonitorInfo
-//
-//! Retrieves current monitoring information.
-//!
-//! \param *pLeftChannel : Pointer to receive left monitor channel index.
-//! \param *pRightChannel : Pointer to receive right monitor channel index.
-//! \param *pGain : Pointer to receive the gain (linear) to be applied.
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-void WCMRAudioDevice::GetMonitorInfo (int *pLeftChannel, int *pRightChannel, float *pGain)
-{
- if (pLeftChannel)
- *pLeftChannel = m_LeftMonitorChannel;
- if (pRightChannel)
- *pRightChannel = m_RightMonitorChannel;
- if (pGain)
- *pGain = m_MonitorGain;
- return;
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::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 WCMRAudioDevice::SetMonitorChannels (int leftChannel, int rightChannel)
-{
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_LeftMonitorChannel = leftChannel;
- m_RightMonitorChannel = rightChannel;
- return (eNoErr);
-}
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::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)
-//!
-//! \return eNoErr always, the derived classes may return appropriate errors.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::SetMonitorGain (float newGain)
-{
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_MonitorGain = newGain;
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::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 - optional.
-//!
-//! \return eNoErr always, the derived classes may return errors.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::ShowConfigPanel (void *WCUNUSEDPARAM(pParam))
-{
- //This will most likely be overridden...
- return (eNoErr);
-}
-
-
-//**********************************************************************************************
-// WCMRAudioDevice::SendCustomCommand
-//
-//! Used to Send a custom command to the audiodevice. Some interfaces may require the device
-//! to be active before it can do anything in this.
-//!
-//! \param customCommand : A device/interface specific command.
-//! \param pCommandParam : A device/interface/command specific parameter - optional.
-//!
-//! \return eNoErr always, the derived classes may return errors.
-//!
-//**********************************************************************************************
-WTErr WCMRAudioDevice::SendCustomCommand (int WCUNUSEDPARAM(customCommand), void *WCUNUSEDPARAM(pCommandParam))
-{
- //This will most likely be overridden...
- return (eNoErr);
-}
-
-//**********************************************************************************************
-// WCMRAudioDevice::GetLatency
-//
-//! Get Latency for device.
-//!
-//! Use 'kAudioDevicePropertyLatency' and 'kAudioDevicePropertySafetyOffset' + GetStreamLatencies
-//!
-//! \param isInput : Return latency for the input if isInput is true, otherwise the output latency
-//! wiil be returned.
-//! \return Latency in samples.
-//!
-//**********************************************************************************************
-uint32_t WCMRAudioDevice::GetLatency (bool isInput)
-{
- //This will most likely be overridden...
- return 0;
-}
-
-
-//**********************************************************************************************
-// WCMRAudioDeviceManager::WCMRAudioDeviceManager
-//
-//! The constructuor, most of the work will be done in the derived class' constructor.
-//!
-//! \param *pTheClient :
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRAudioDeviceManager::WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter)
- : m_eAudioDeviceFilter(eCurAudioDeviceFilter)
- , m_CurrentDevice(0)
- , m_pTheClient (pTheClient)
-{
-}
-
-
-//**********************************************************************************************
-// WCMRAudioDeviceManager::~WCMRAudioDeviceManager
-//
-//! It clears the device list, releasing each of the device.
-//!
-//! \param none
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRAudioDeviceManager::~WCMRAudioDeviceManager()
-{
- AUTO_FUNC_DEBUG;
-
- std::cout << "API::Destroying AudioDeviceManager " << std::endl;
- try
- {
- // clean up device info list
- {
- wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
- while( m_DeviceInfoVec.size() )
- {
- DeviceInfo* devInfo = m_DeviceInfoVec.back();
- m_DeviceInfoVec.pop_back();
- delete devInfo;
- }
- }
- delete m_CurrentDevice;
-
- }
- catch (...)
- {
- //destructors should absorb exceptions, no harm in logging though!!
- DEBUG_MSG ("Exception during destructor");
- }
-}
-
-
-WCMRAudioDevice* WCMRAudioDeviceManager::InitNewCurrentDevice(const std::string & deviceName)
-{
- return initNewCurrentDeviceImpl(deviceName);
-}
-
-
-void WCMRAudioDeviceManager::DestroyCurrentDevice()
-{
- return destroyCurrentDeviceImpl();
-}
-
-
-const DeviceInfoVec WCMRAudioDeviceManager::DeviceInfoList() const
-{
- wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
- return m_DeviceInfoVec;
-}
-
-
-WTErr WCMRAudioDeviceManager::GetDeviceInfoByName(const std::string & nameToMatch, DeviceInfo & devInfo) const
-{
- wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
- DeviceInfoVecConstIter iter = m_DeviceInfoVec.begin();
- for (; iter != m_DeviceInfoVec.end(); ++iter)
- {
- if (nameToMatch == (*iter)->m_DeviceName)
- {
- devInfo = *(*iter);
- return eNoErr;
- }
- }
-
- return eRMResNotFound;
-}
-
-
-WTErr WCMRAudioDeviceManager::GetDeviceSampleRates(const std::string & nameToMatch, std::vector<int>& sampleRates) const
-{
- return getDeviceSampleRatesImpl(nameToMatch, sampleRates);
-}
-
-
-
-WTErr WCMRAudioDeviceManager::GetDeviceBufferSizes(const std::string & nameToMatch, std::vector<int>& bufferSizes) const
-{
- return getDeviceBufferSizesImpl(nameToMatch, bufferSizes);
-}
-
-
-//**********************************************************************************************
-// WCMRAudioDeviceManager::NotifyClient
-//
-//! A helper routine used to call the client for notification.
-//!
-//! \param forReason : The reason for notification.
-//! \param *pParam : A parameter (if required) for notification.
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-void WCMRAudioDeviceManager::NotifyClient (WCMRAudioDeviceManagerClient::NotificationReason forReason, void *pParam)
-{
- if (m_pTheClient)
- m_pTheClient->AudioDeviceManagerNotification (forReason, pParam);
- return;
-}
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h
deleted file mode 100644
index b22e35263d..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- Copyright (C) 2014 Waves Audio Ltd.
-
- 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.
-
-*/
-
-//----------------------------------------------------------------------------------
-//
-//
-//! \file WCMRAudioDeviceManager.h
-//!
-//! WCMRAudioDeviceManager and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#ifndef __WCMRAudioDeviceManager_h_
- #define __WCMRAudioDeviceManager_h_
-
-/* Copy to include
-#include "WCMRAudioDeviceManager.h"
-*/
-
-#define AUTO_FUNC_DEBUG
-#define DEBUG_MSG(a)
-#define ASSERT_ERROR(a, b)
-#define TRACE_MSG(a)
-
-#include <string>
-#include <vector>
-#include <map>
-#include "WCRefManager.h"
-#include "BasicTypes/WUTypes.h"
-#include "WUErrors.h"
-#include "WCThreadSafe.h"
-
-#define WCUNUSEDPARAM(a)
-
-class WCMRAudioDevice;
-class WCMRAudioDeviceManager;
-
-typedef unsigned int DeviceID;
-
-struct DeviceInfo
-{
- DeviceID m_DeviceId;
- std::string m_DeviceName;
- std::vector<int> m_AvailableSampleRates;
- std::vector<int> m_AvailableBufferSizes;
- unsigned int m_MaxInputChannels;
- unsigned int m_MaxOutputChannels;
-
- DeviceInfo():
- m_DeviceId(-1), m_DeviceName("Unknown"), m_MaxInputChannels(0), m_MaxOutputChannels(0)
- {};
-
- DeviceInfo(unsigned int deviceID, const std::string & deviceName):
- m_DeviceId(deviceID), m_DeviceName(deviceName), m_MaxInputChannels(0), m_MaxOutputChannels(0)
- {};
-};
-
-typedef std::vector<DeviceInfo*> DeviceInfoVec;
-typedef DeviceInfoVec::iterator DeviceInfoVecIter;
-typedef DeviceInfoVec::const_iterator DeviceInfoVecConstIter;
-
-/// for notification... A client must derive it's class from us.
-class WCMRAudioDeviceManagerClient
-{
- public:
- enum NotificationReason
- {
- DeviceListChanged,
- Dropout,
- RequestReset,
- RequestResync,
- SamplingRateChanged, //param has new SR, or -1 if not known
- SamplingRateChangedSilent, //To indicate sampling rate changed but no need to notify user
- BufferSizeChanged,
- ClockSourceChanged,
- DeviceStoppedStreaming,
- DeviceStartsStreaming,
- DeviceDroppedSamples,
- DeviceConnectionLost,
- DeviceGenericError,
- DeviceStatusChanged,
- DeviceStatisticsUpdated,
- DeviceDebugInfo, //param has c string
- DeviceProgressInfo, //param has c string
- MIDIData,
- MIDINodeUp,
- MIDINodeDown,
- DeviceSampleRateMisMatch,
- SystemSamplingRateChangedInfoOnly,
- LostClockSource,
- IODeviceDisconnected,
- ChannelCountModified,
- MasterUp,
- MasterDown,
- AudioDropFound,
- ReflasherEvent,
- AGDeviceSamplingRateChangedInfoOnly,
- IODeviceNameChanged,
- SetDisplayNameFromIOModule,
- IOMStateChanged, ///< This is used when IOM state is changed.
- AudioCallback // VKamyshniy: param is AudioCallbackDataData*
- };
-
- WCMRAudioDeviceManagerClient () {}
- virtual ~WCMRAudioDeviceManagerClient () {}
-
- // VKamyshniy: This is a structure to call the client's AudioDeviceManagerNotification
- // every AudioCallback time
- struct AudioCallbackData
- {
- const float *acdInputBuffer;
- float *acdOutputBuffer;
- size_t acdFrames;
- int64_t acdSampleTime;
- uint64_t acdCycleStartTimeNanos;
- };
-
- virtual void AudioDeviceManagerNotification (NotificationReason WCUNUSEDPARAM(reason), void *WCUNUSEDPARAM(pParam)) {}
-};
-
-
-class WCMRAudioDevice : public WCRefManager
-{
-public:
-
- enum ConnectionStates
- {
- DeviceAvailable,
- DeviceDisconnected,
- DeviceErrors
- };
-
- WCMRAudioDevice (WCMRAudioDeviceManager *pManager);///<Constructor
- virtual ~WCMRAudioDevice ();///<Destructor
-
- virtual const std::string& DeviceName() const;///<Name?
- virtual const std::vector<std::string>& InputChannels();///<Current Input Channel List? - note that this may change with change in sampling rate.
- virtual const std::vector<std::string>& OutputChannels();///<Current Output Channel List? - note that this may change with change in sampling rate.
-
- virtual const std::vector<int>& SamplingRates();///<Supported Sampling Rate List?
- virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
- virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!
-
- virtual const std::vector<int>& BufferSizes();///<Supported Buffer Size List? - note that this may change with change in sampling rate.
- virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
- virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
-
- virtual int CurrentBlockSize();
-
- virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
-
- virtual bool Active();///<Active status - mainly significant for ASIO, as certain ops can only be performed on active devices!
- virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
-
- virtual bool Streaming();///<Streaming Status?
- virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
-
- virtual WTErr ResetDevice ();
-
- virtual bool IsProcessActive();
-
- virtual WTErr DoIdle();///<Do Idle Processing
-
- virtual const std::vector<float>& InputLevels();///<Retrieve Input Levels (for VU display)?
-
- virtual const std::vector<float>& OutputLevels();///<Retrieve Output Levels (for VU display)?
-
- void GetMonitorInfo (int *pLeftChannel = NULL, int *pRightChannel = NULL, float *pGain = NULL);///<Retrieve current monitor channel pair and gain - optional, will not be available with AG
- virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
- virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
-
- virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
- virtual WTErr SendCustomCommand (int customCommand, void *pCommandParam); ///< Send a custom command to the audiodevice...
-
- virtual uint32_t GetLatency (bool isInput); ///Get latency.
-
- virtual WTErr UpdateDeviceInfo () = 0;
-
-protected:
- WCMRAudioDeviceManager *m_pMyManager; ///< The manager who's managing this device, can be used for sending notifications!
-
- std::string m_DeviceName; ///< Name of the device.
- std::vector<std::string> m_InputChannels; ///< List of input channel names.
- std::vector<std::string> m_OutputChannels; ///< List of output channel names.
- std::vector<int> m_SamplingRates; ///< List of available sampling rates.
- std::vector<int> m_BufferSizes; ///< List of available buffer sizes.
-
- int m_CurrentSamplingRate; ///< Currently selected sampling rate.
- int m_CurrentBufferSize; ///< Currently selected buffer size.
-
- ConnectionStates m_ConnectionStatus; ///< Status of device connection
- bool m_IsActive; ///< Flag for teh active status.
- bool m_IsStreaming; ///< Flag for streaming status.
- std::vector<float> m_InputLevels; ///< List of input levels.
- std::vector<float> m_OutputLevels; ///< List of output levels.
-
- int m_LeftMonitorChannel; ///< The device channel to use for monitoring left channel data.
- int m_RightMonitorChannel; ///< The device channel to use for monitoring right channel data.
- float m_MonitorGain; ///< Amount of gain to apply for monitoring signal.
-};
-
-
-// This enum is for choosing filter for audio devices scan
-typedef enum eAudioDeviceFilter
-{
- eAllDevices = 0, // Choose all audio devices
- eInputOnlyDevices, // Choose only input audio devices
- eOutputOnlyDevices, // Choose only output audio devices
- eFullDuplexDevices, // Choose audio devices that have both input and output channels on the same device
- eMatchedDuplexDevices, // Match(aggregate) audio devices that have both input and output channels but are considered different audio devices (For mac)
- eAudioDeviceFilterNum // Number of enums
-} eAudioDeviceFilter;
-
-
-class WCMRAudioDeviceManager : public WCRefManager
-{
-public://< Public functions for the class.
-
- WCMRAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter); ///< constructor
- virtual ~WCMRAudioDeviceManager(void); ///< Destructor
-
- //interfaces
- WCMRAudioDevice* InitNewCurrentDevice(const std::string & deviceName);
- void DestroyCurrentDevice();
- const DeviceInfoVec DeviceInfoList () const;
- WTErr GetDeviceInfoByName(const std::string & nameToMatch, DeviceInfo & devInfo) const;
- WTErr GetDeviceSampleRates(const std::string & nameToMatch, std::vector<int>& sampleRates) const;
- WTErr GetDeviceBufferSizes(const std::string & nameToMatch, std::vector<int>& bufferSizes) const;
-
- //virtual void EnableVerboseLogging(bool /*bEnable*/, const std::string& /*logFilePath*/) { };
-
- //notify backend
- void NotifyClient (WCMRAudioDeviceManagerClient::NotificationReason forReason, void *pParam = NULL);
-
-protected:
-
- mutable wvNS::wvThread::ThreadMutex m_AudioDeviceInfoVecMutex; // mutex to lock device info list
- DeviceInfoVec m_DeviceInfoVec;
-
- eAudioDeviceFilter m_eAudioDeviceFilter;
- WCMRAudioDevice* m_CurrentDevice;
-
-private:
- // override in derived classes
- // made private to avoid pure virtual function call
- virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName) = 0;
- virtual void destroyCurrentDeviceImpl() = 0;
- virtual WTErr getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const = 0;
- virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const = 0;
- virtual WTErr generateDeviceListImpl() = 0;
- virtual WTErr updateDeviceListImpl() = 0;
-
- WCMRAudioDeviceManagerClient *m_pTheClient; ///< The device manager's client, used to send notifications.
-};
-
-#endif //#ifndef __WCMRAudioDeviceManager_h_
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp
deleted file mode 100644
index 2a9a9ba19f..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.cpp
+++ /dev/null
@@ -1,3140 +0,0 @@
-//----------------------------------------------------------------------------------
-//
-// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
-//
-//! \file WCMRCoreAudioDeviceManager.cpp
-//!
-//! WCMRCoreAudioDeviceManager and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#include "WCMRCoreAudioDeviceManager.h"
-#include <CoreServices/CoreServices.h>
-#include "MiscUtils/safe_delete.h"
-#include <sstream>
-#include <syslog.h>
-
-// This flag is turned to 1, but it does not work with aggregated devices.
-// due to problems with aggregated devices this flag is not functional there
-#define ENABLE_DEVICE_CHANGE_LISTNER 1
-
-#define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 10
-#define PROPERTY_CHANGE_TIMEOUT_SECONDS 5
-#define USE_IOCYCLE_TIMES 1 ///< Set this to 0 to use individual thread cpu measurement
-
-using namespace wvNS;
-///< Supported Sample rates
-static const double gAllSampleRates[] =
-{
- 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, -1 /* negative terminated list */
-};
-
-
-///< Default Supported Buffer Sizes.
-static const int gAllBufferSizes[] =
-{
- 32, 64, 96, 128, 192, 256, 512, 1024, 2048, -1 /* negative terminated list */
-};
-
-
-///< The default SR.
-static const int DEFAULT_SR = 44100;
-///< The default buffer size.
-static const int DEFAULT_BUFFERSIZE = 1024;
-
-static const int NONE_DEVICE_ID = -1;
-
-///< Number of stalls to wait before notifying user...
-static const int NUM_STALLS_FOR_NOTIFICATION = 2 * 50; // 2*50 corresponds to 2 * 50 x 42 ms idle timer - about 4 seconds.
-static const int CHANGE_CHECK_COUNTER_PERIOD = 100; // 120 corresponds to 120 x 42 ms idle timer - about 4 seconds.
-
-#define AUHAL_OUTPUT_ELEMENT 0
-#define AUHAL_INPUT_ELEMENT 1
-
-#include <sys/sysctl.h>
-
-static int getProcessorCount()
-{
- int count = 1;
- size_t size = sizeof(count);
-
- if (sysctlbyname("hw.ncpu", &count, &size, NULL, 0))
- return 1;
-
- //if something did not work, let's revert to a safe value...
- if (count == 0)
- count = 1;
-
- return count;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::WCMRCoreAudioDevice
-//
-//! Constructor for the audio device. Opens the PA device and gets information about the device.
-//! such as determining supported sampling rates, buffer sizes, and channel counts.
-//!
-//! \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.
-//!
-//**********************************************************************************************
-WCMRCoreAudioDevice::WCMRCoreAudioDevice (WCMRCoreAudioDeviceManager *pManager, AudioDeviceID deviceID, bool useMultithreading, bool bNocopy)
- : WCMRNativeAudioDevice (pManager, useMultithreading, bNocopy)
- , m_SampleCountAtLastIdle (0)
- , m_StalledSampleCounter(0)
- , m_SampleCounter(0)
- , m_BufferSizeChangeRequested (0)
- , m_BufferSizeChangeReported (0)
- , m_ResetRequested (0)
- , m_ResetReported (0)
- , m_ResyncRequested (0)
- , m_ResyncReported (0)
- , m_SRChangeRequested (0)
- , m_SRChangeReported (0)
- , m_ChangeCheckCounter(0)
- , m_IOProcThreadPort (0)
- , m_DropsDetected(0)
- , m_DropsReported(0)
- , m_IgnoreThisDrop(true)
- , m_LastCPULog(0)
-#if WV_USE_TONE_GEN
- , m_pToneData(0)
- , m_ToneDataSamples (0)
- , m_NextSampleToUse (0)
-#endif //WV_USE_TONE_GEN
-{
- AUTO_FUNC_DEBUG;
- UInt32 propSize = 0;
- OSStatus err = kAudioHardwareNoError;
-
- //Update device info...
- m_DeviceID = deviceID;
-
- m_CurrentSamplingRate = DEFAULT_SR;
- m_CurrentBufferSize = DEFAULT_BUFFERSIZE;
- m_StopRequested = true;
- m_pInputData = NULL;
-
- m_CPUCount = getProcessorCount();
- m_LastCPULog = wvThread::now() - 10 * wvThread::ktdOneSecond;
-
-
-
- /*
- @constant kAudioDevicePropertyNominalSampleRate
- A Float64 that indicates the current nominal sample rate of the AudioDevice.
- */
- Float64 currentNominalRate;
- propSize = sizeof (currentNominalRate);
- err = kAudioHardwareNoError;
- if (AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &currentNominalRate) != kAudioHardwareNoError)
- err = AudioDeviceGetProperty(m_DeviceID, 0, 1, kAudioDevicePropertyNominalSampleRate, &propSize, &currentNominalRate);
-
- if (err == kAudioHardwareNoError)
- m_CurrentSamplingRate = (int)currentNominalRate;
-
- /*
- @constant kAudioDevicePropertyBufferFrameSize
- A UInt32 whose value indicates the number of frames in the IO buffers.
- */
-
- UInt32 bufferSize;
- propSize = sizeof (bufferSize);
- err = kAudioHardwareNoError;
- if (AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyBufferFrameSize, &propSize, &bufferSize) != kAudioHardwareNoError)
- err = AudioDeviceGetProperty(m_DeviceID, 0, 1, kAudioDevicePropertyBufferFrameSize, &propSize, &bufferSize);
-
- if (err == kAudioHardwareNoError)
- m_CurrentBufferSize = (int)bufferSize;
-
-
- UpdateDeviceInfo();
-
- //should use a valid current SR...
- if (m_SamplingRates.size())
- {
- //see if the current sr is present in the sr list, if not, use the first one!
- std::vector<int>::iterator intIter = find(m_SamplingRates.begin(), m_SamplingRates.end(), m_CurrentSamplingRate);
- if (intIter == m_SamplingRates.end())
- {
- //not found... use the first one
- m_CurrentSamplingRate = m_SamplingRates[0];
- }
- }
-
- //should use a valid current buffer size
- if (m_BufferSizes.size())
- {
- //see if the current sr is present in the buffersize list, if not, use the first one!
- std::vector<int>::iterator intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), m_CurrentBufferSize);
- if (intIter == m_BufferSizes.end())
- {
- //not found... use the first one
- m_CurrentBufferSize = m_BufferSizes[0];
- }
- }
-
- //build our input/output level lists
- for (unsigned int currentChannel = 0; currentChannel < m_InputChannels.size(); currentChannel++)
- {
- m_InputLevels.push_back (0.0);
- }
-
- //build our input/output level lists
- for (unsigned int currentChannel = 0; currentChannel < m_OutputChannels.size(); currentChannel++)
- {
- m_OutputLevels.push_back (0.0);
- }
-
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::~WCMRCoreAudioDevice
-//
-//! 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.
-//!
-//**********************************************************************************************
-WCMRCoreAudioDevice::~WCMRCoreAudioDevice ()
-{
- AUTO_FUNC_DEBUG;
-
- try
- {
- //If device is streaming, need to stop it!
- if (Streaming())
- {
- SetStreaming (false);
- }
-
- //If device is active (meaning stream is open) we need to close it.
- if (Active())
- {
- SetActive (false);
- }
-
- }
- catch (...)
- {
- //destructors should absorb exceptions, no harm in logging though!!
- DEBUG_MSG ("Exception during destructor");
- }
-
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::UpdateDeviceInfo
-//
-//! Updates Device Information about channels, sampling rates, buffer sizes.
-//!
-//! \return WTErr.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::UpdateDeviceInfo ()
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
-
- // Some devices change the ID during restart
- WTErr errId = UpdateDeviceId();
-
- // Update all devices parts regardless of errors
- WTErr errName = UpdateDeviceName();
- WTErr errIn = UpdateDeviceInputs();
- WTErr errOut = UpdateDeviceOutputs();
- WTErr errSR = eNoErr;
- WTErr errBS = eNoErr;
-
- errSR = UpdateDeviceSampleRates();
- errBS = UpdateDeviceBufferSizes();
-
- if(errId != eNoErr || errName != eNoErr || errIn != eNoErr || errOut != eNoErr || errSR != eNoErr || errBS != eNoErr)
- {
- retVal = eCoreAudioFailed;
- }
-
- return retVal;
-}
-
-
-WTErr WCMRCoreAudioDevice::UpdateDeviceId()
-{
- //Get device count...
- UInt32 propSize = 0;
- WTErr retVal = eNoErr;
- OSStatus osErr = AudioHardwareGetPropertyInfo (kAudioHardwarePropertyDevices, &propSize, NULL);
- ASSERT_ERROR(osErr, "AudioHardwareGetProperty 1");
- if (WUIsError(osErr))
- throw osErr;
-
- size_t numDevices = propSize / sizeof (AudioDeviceID);
- AudioDeviceID* deviceIDs = new AudioDeviceID[numDevices];
-
- //retrieve the device IDs
- propSize = numDevices * sizeof (AudioDeviceID);
- osErr = AudioHardwareGetProperty (kAudioHardwarePropertyDevices, &propSize, deviceIDs);
- ASSERT_ERROR(osErr, "Error while getting audio devices: AudioHardwareGetProperty 2");
- if (WUIsError(osErr))
- throw osErr;
-
- //now add the ones that are not there...
- for (size_t deviceIndex = 0; deviceIndex < numDevices; deviceIndex++)
- {
- DeviceInfo* pDevInfo = 0;
-
- //Get device name and create new DeviceInfo entry
- //Get property name size.
- osErr = AudioDeviceGetPropertyInfo(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL);
- if (osErr == kAudioHardwareNoError)
- {
- //Get property: name.
- char* deviceName = new char[propSize];
- osErr = AudioDeviceGetProperty(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, deviceName);
- if (osErr == kAudioHardwareNoError)
- {
- if ( (m_DeviceName == deviceName) &&
- (m_DeviceID != deviceIDs[deviceIndex]) ) {
-
- m_DeviceID = deviceIDs[deviceIndex];
-
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Current device has changed it's id.");
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device name. Device ID: " << m_DeviceID);
- }
-
- delete [] deviceName;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device name prop Info. Device ID: " << m_DeviceID);
- }
- }
-
- delete [] deviceIDs;
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::UpdateDeviceName
-//
-//! Updates Device name.
-//!
-//! Use 'kAudioDevicePropertyDeviceName'
-//!
-//! 1. Get property name size.
-//! 2. Get property: name.
-//!
-//! \return WTErr.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::UpdateDeviceName()
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- // Initiate name to unknown.
- m_DeviceName = "Unknown";
-
- //! 1. Get property name size.
- err = AudioDeviceGetPropertyInfo(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: name.
- char* deviceName = new char[propSize];
- err = AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyDeviceName, &propSize, deviceName);
- if (err == kAudioHardwareNoError)
- {
- m_DeviceName = deviceName;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device name. Device ID: " << m_DeviceID);
- }
-
- delete [] deviceName;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device name property size. Device ID: " << m_DeviceID);
- }
-
- return retVal;
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::UpdateDeviceInputs
-//
-//! Updates Device Inputs.
-//!
-//! Use 'kAudioDevicePropertyStreamConfiguration'
-//! This property returns the stream configuration of the device in an
-//! AudioBufferList (with the buffer pointers set to NULL) which describes the
-//! list of streams and the number of channels in each stream. This corresponds
-//! to what will be passed into the IOProc.
-//!
-//! 1. Get property cannels input size.
-//! 2. Get property: cannels input.
-//! 3. Update input channels
-//!
-//! \return WTErr.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::UpdateDeviceInputs()
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
- int maxInputChannels = 0;
-
- // 1. Get property cannels input size.
- err = AudioDeviceGetPropertyInfo (m_DeviceID, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels input.
-
- // Allocate size according to the property size. Note that this is a variable sized struct...
- AudioBufferList *pStreamBuffers = (AudioBufferList *)malloc(propSize);
-
- if (pStreamBuffers)
- {
- memset (pStreamBuffers, 0, propSize);
-
- // Get the Input channels
- err = AudioDeviceGetProperty (m_DeviceID, 0, true/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
- if (err == kAudioHardwareNoError)
- {
- // Calculate the number of input channels
- for (UInt32 streamIndex = 0; streamIndex < pStreamBuffers->mNumberBuffers; streamIndex++)
- {
- maxInputChannels += pStreamBuffers->mBuffers[streamIndex].mNumberChannels;
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Input channels. Device Name: " << m_DeviceName.c_str());
- }
-
- free (pStreamBuffers);
- }
- else
- {
- retVal = eMemOutOfMemory;
- DEBUG_MSG("Faild to allocate memory. Device Name: " << m_DeviceName.c_str());
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Input channels property size. Device Name: " << m_DeviceName.c_str());
- }
-
- // Update input channels
- m_InputChannels.clear();
-
- for (int channel = 0; channel < maxInputChannels; channel++)
- {
- CFStringRef cfName;
- std::stringstream chNameStream;
- UInt32 nameSize = 0;
- OSStatus error = kAudioHardwareNoError;
-
- error = AudioDeviceGetPropertyInfo (m_DeviceID,
- channel + 1,
- true /* Input */,
- kAudioDevicePropertyChannelNameCFString,
- &nameSize,
- NULL);
-
- if (error == kAudioHardwareNoError)
- {
- error = AudioDeviceGetProperty (m_DeviceID,
- channel + 1,
- true /* Input */,
- kAudioDevicePropertyChannelNameCFString,
- &nameSize,
- &cfName);
- }
-
- bool decoded = false;
- char* cstr_name = 0;
- if (error == kAudioHardwareNoError)
- {
- CFIndex length = CFStringGetLength(cfName);
- CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
- cstr_name = new char[maxSize];
- decoded = CFStringGetCString(cfName, cstr_name, maxSize, kCFStringEncodingUTF8);
- }
-
- chNameStream << (channel+1) << " - ";
-
- if (cstr_name && decoded && (0 != std::strlen(cstr_name) ) ) {
- chNameStream << cstr_name;
- }
- else
- {
- chNameStream << "Input " << (channel+1);
- }
-
- m_InputChannels.push_back (chNameStream.str());
-
- delete [] cstr_name;
- }
-
- return retVal;
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::UpdateDeviceOutputs
-//
-//! Updates Device Outputs.
-//!
-//! Use 'kAudioDevicePropertyStreamConfiguration'
-//! This property returns the stream configuration of the device in an
-//! AudioBufferList (with the buffer pointers set to NULL) which describes the
-//! list of streams and the number of channels in each stream. This corresponds
-//! to what will be passed into the IOProc.
-//!
-//! 1. Get property cannels output size.
-//! 2. Get property: cannels output.
-//! 3. Update output channels
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::UpdateDeviceOutputs()
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
- int maxOutputChannels = 0;
-
- //! 1. Get property cannels output size.
- err = AudioDeviceGetPropertyInfo (m_DeviceID, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels output.
-
- // Allocate size according to the property size. Note that this is a variable sized struct...
- AudioBufferList *pStreamBuffers = (AudioBufferList *)malloc(propSize);
- if (pStreamBuffers)
- {
- memset (pStreamBuffers, 0, propSize);
-
- // Get the Output channels
- err = AudioDeviceGetProperty (m_DeviceID, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
- if (err == kAudioHardwareNoError)
- {
- // Calculate the number of output channels
- for (UInt32 streamIndex = 0; streamIndex < pStreamBuffers->mNumberBuffers; streamIndex++)
- {
- maxOutputChannels += pStreamBuffers->mBuffers[streamIndex].mNumberChannels;
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Output channels. Device Name: " << m_DeviceName.c_str());
- }
- free (pStreamBuffers);
- }
- else
- {
- retVal = eMemOutOfMemory;
- DEBUG_MSG("Faild to allocate memory. Device Name: " << m_DeviceName.c_str());
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Output channels property size. Device Name: " << m_DeviceName.c_str());
- }
-
- // Update output channels
- m_OutputChannels.clear();
- for (int channel = 0; channel < maxOutputChannels; channel++)
- {
- CFStringRef cfName;
- std::stringstream chNameStream;
- UInt32 nameSize = 0;
- OSStatus error = kAudioHardwareNoError;
-
- error = AudioDeviceGetPropertyInfo (m_DeviceID,
- channel + 1,
- false /* Output */,
- kAudioDevicePropertyChannelNameCFString,
- &nameSize,
- NULL);
-
- if (error == kAudioHardwareNoError)
- {
- error = AudioDeviceGetProperty (m_DeviceID,
- channel + 1,
- false /* Output */,
- kAudioDevicePropertyChannelNameCFString,
- &nameSize,
- &cfName);
- }
-
- bool decoded = false;
- char* cstr_name = 0;
- if (error == kAudioHardwareNoError )
- {
- CFIndex length = CFStringGetLength(cfName);
- CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
- cstr_name = new char[maxSize];
- decoded = CFStringGetCString(cfName, cstr_name, maxSize, kCFStringEncodingUTF8);
- }
-
- chNameStream << (channel+1) << " - ";
-
- if (cstr_name && decoded && (0 != std::strlen(cstr_name) ) ) {
- chNameStream << cstr_name;
- }
- else
- {
- chNameStream << "Output " << (channel+1);
- }
-
- m_OutputChannels.push_back (chNameStream.str());
-
- delete [] cstr_name;
- }
-
- return retVal;
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::UpdateDeviceSampleRates
-//
-//! Updates Device Sample rates.
-//!
-//! Use 'kAudioDevicePropertyAvailableNominalSampleRates'
-//!
-//! 1. Get sample rate property size.
-//! 2. Get property: sample rates.
-//! 3. Update sample rates
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::UpdateDeviceSampleRates()
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- m_SamplingRates.clear();
-
- //! 1. Get sample rate property size.
- err = AudioDeviceGetPropertyInfo(m_DeviceID, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels output.
-
- // Allocate size accrding to the number of audio values
- int numRates = propSize / sizeof(AudioValueRange);
- AudioValueRange* supportedRates = new AudioValueRange[numRates];
-
- // Get sampling rates from Audio device
- err = AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, supportedRates);
- if (err == kAudioHardwareNoError)
- {
- //! 3. Update sample rates
-
- // now iterate through our standard SRs
- for(int ourSR=0; gAllSampleRates[ourSR] > 0; ourSR++)
- {
- //check to see if our SR is in the supported rates...
- for (int deviceSR = 0; deviceSR < numRates; deviceSR++)
- {
- if ((supportedRates[deviceSR].mMinimum <= gAllSampleRates[ourSR]) &&
- (supportedRates[deviceSR].mMaximum >= gAllSampleRates[ourSR]))
- {
- m_SamplingRates.push_back ((int)gAllSampleRates[ourSR]);
- break;
- }
- }
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Sample rates. Device Name: " << m_DeviceName.c_str());
- }
-
- delete [] supportedRates;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Sample rates property size. Device Name: " << m_DeviceName.c_str());
- }
-
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::UpdateDeviceBufferSizes_Simple
-//
-// Use kAudioDevicePropertyBufferFrameSizeRange
-//
-// in case of 'eMatchedDuplexDevices' and a matching device exists return common device name
-// in all other cases retur base class function implementation
-//
-// 1. Get buffer size range
-// 2. Run on all ranges and add them to the list
-//
-// \return error code
-//
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::UpdateDeviceBufferSizes ()
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- // Clear buffer sizes
- m_BufferSizes.clear();
-
- // 1. Get buffer size range
- AudioValueRange bufferSizesRange;
- propSize = sizeof (AudioValueRange);
- err = AudioDeviceGetProperty (m_DeviceID, 0, 0, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &bufferSizesRange);
- if(err == kAudioHardwareNoError)
- {
- // 2. Run on all ranges and add them to the list
- for(int bsize=0; gAllBufferSizes[bsize] > 0; bsize++)
- {
- if ((bufferSizesRange.mMinimum <= gAllBufferSizes[bsize]) && (bufferSizesRange.mMaximum >= gAllBufferSizes[bsize]))
- {
- m_BufferSizes.push_back (gAllBufferSizes[bsize]);
- }
- }
-
- //if we didn't get a single hit, let's simply add the min. and the max...
- if (m_BufferSizes.empty())
- {
- m_BufferSizes.push_back ((int)bufferSizesRange.mMinimum);
- m_BufferSizes.push_back ((int)bufferSizesRange.mMaximum);
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device buffer sizes range. Device Name: " << m_DeviceName.c_str());
- }
-
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::DeviceName
-//
-//! in case of 'eMatchedDuplexDevices' and a matching device exists return common device name
-//! in all other cases retur base class function implementation
-//!
-//! \param none
-//!
-//! \return current device name
-//!
-//**********************************************************************************************
-const std::string& WCMRCoreAudioDevice::DeviceName() const
-{
- return WCMRAudioDevice::DeviceName();
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::InputChannels
-//
-//! return base class function implementation
-//!
-//! \param none
-//!
-//! \return base class function implementation
-//!
-//**********************************************************************************************
-const std::vector<std::string>& WCMRCoreAudioDevice::InputChannels()
-{
- return WCMRAudioDevice::InputChannels();
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::OutputChannels
-//
-//! in case of 'eMatchedDuplexDevices' return matching device output channel if there is one
-//! in all other cases retur base class function implementation
-//!
-//! \param none
-//!
-//! \return list of output channels of current device
-//!
-//**********************************************************************************************
-const std::vector<std::string>& WCMRCoreAudioDevice::OutputChannels()
-{
- return WCMRAudioDevice::OutputChannels();
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SamplingRates
-//
-//! in case of 'eMatchedDuplexDevices' and a matching device exists return common sample rate
-//! in all other cases retur base class function implementation
-//!
-//! \param none
-//!
-//! \return current sample rate
-//!
-//**********************************************************************************************
-const std::vector<int>& WCMRCoreAudioDevice::SamplingRates()
-{
- return WCMRAudioDevice::SamplingRates();
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::CurrentSamplingRate
-//
-//! 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 WCMRCoreAudioDevice::CurrentSamplingRate ()
-{
- AUTO_FUNC_DEBUG;
- //ToDo: Perhaps for ASIO devices that are active, we should retrive the SR from the device...
- UInt32 propSize = 0;
- OSStatus err = kAudioHardwareNoError;
-
- Float64 currentNominalRate;
- propSize = sizeof (currentNominalRate);
- err = kAudioHardwareNoError;
- if (AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &currentNominalRate) != kAudioHardwareNoError)
- err = AudioDeviceGetProperty(m_DeviceID, 0, 1, kAudioDevicePropertyNominalSampleRate, &propSize, &currentNominalRate);
-
- if (err == kAudioHardwareNoError)
- m_CurrentSamplingRate = (int)currentNominalRate;
- else
- {
- DEBUG_MSG("Unable to get sampling rate!");
- }
-
- return (m_CurrentSamplingRate);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetCurrentSamplingRate
-//
-//! 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 WCMRCoreAudioDevice::SetCurrentSamplingRate (int newRate)
-{
- AUTO_FUNC_DEBUG;
- std::vector<int>::iterator intIter;
- WTErr retVal = eNoErr;
-
- //changes the status.
- int oldRate = CurrentSamplingRate();
- bool oldActive = Active();
-
- //no change, nothing to do
- if (oldRate == newRate)
- goto Exit;
-
- //see if this is one of our supported rates...
- intIter = find(m_SamplingRates.begin(), m_SamplingRates.end(), newRate);
- if (intIter == m_SamplingRates.end())
- {
- //Can't change, perhaps use an "invalid param" type of error
- retVal = eCommandLineParameter;
- goto Exit;
- }
-
- if (Streaming())
- {
- //Can't change, perhaps use an "in use" type of error
- retVal = eGenericErr;
- goto Exit;
- }
-
- if (oldActive)
- {
- //Deactivate it for the change...
- SetActive (false);
- }
-
- retVal = SetAndCheckCurrentSamplingRate (newRate);
- if(retVal == eNoErr)
- {
- retVal = UpdateDeviceInfo ();
- }
-
- //reactivate it.
- if (oldActive)
- {
- retVal = SetActive (true);
- }
-
-Exit:
-
- return (retVal);
-
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate
-//
-//! 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 WCMRCoreAudioDevice::SetAndCheckCurrentSamplingRate (int newRate)
-{
- AUTO_FUNC_DEBUG;
- std::vector<int>::iterator intIter;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- // 1. Set new sampling rate
- Float64 newNominalRate = newRate;
- propSize = sizeof (Float64);
- err = AudioDeviceSetProperty(m_DeviceID, NULL, 0, 0, kAudioDevicePropertyNominalSampleRate, propSize, &newNominalRate);
-
- if (err != kAudioHardwareNoError)
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG ("Unable to set SR! Device name: " << m_DeviceName.c_str());
- }
- else
- {
- // 2. wait for the SR to actually change...
-
- // Set total time out time
- int tryAgain = ((PROPERTY_CHANGE_TIMEOUT_SECONDS * 1000) / PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS) ;
- int actualWait = 0;
- Float64 actualSamplingRate = 0.0;
-
- // Run as ling as time out is not finished
- while (tryAgain)
- {
- // Get current sampling rate
- err = AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &actualSamplingRate);
- if (err == kAudioHardwareNoError)
- {
- if (actualSamplingRate == newNominalRate)
- {
- //success, let's get out!
- break;
- }
- }
- else
- {
- //error reading rate, but let's not complain too much!
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Could not read Sampling Rate for verification.");
- DEBUG_MSG ("Unable to get SR. Device name: " << m_DeviceName.c_str());
- }
-
- // oh well...there's always another millisecond...
- wvThread::sleep_milliseconds (PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
- tryAgain--;
- actualWait++;
- }
-
- // If sample rate actually changed
- if (tryAgain != 0)
- {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Changed the Sampling Rate.");
-
- // Update member with new rate
- m_CurrentSamplingRate = newRate;
-
- char debugMsg[128];
- snprintf (debugMsg, sizeof(debugMsg), "Actual Wait for SR Change was %d milliseconds", actualWait * PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)debugMsg);
- }
- // If sample rate did not change after time out
- else
- {
- // Check if current device sample rate is supported
- bool found = false;
- for(int i = 0; gAllSampleRates[i] > 0; i++)
- {
- if (fabs(gAllSampleRates[i] - actualSamplingRate) < 0.01) {
- found = true;
- }
- }
-
- if (found) {
- // Update member with last read value
- m_CurrentSamplingRate = static_cast<int>(actualSamplingRate);
-
- char debugMsg[128];
- snprintf (debugMsg, sizeof(debugMsg), "Unable to change SR, even after waiting for %d milliseconds", actualWait * PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)debugMsg);
-
- float sample_rate_update = actualSamplingRate;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::SamplingRateChanged, (void *)&sample_rate_update);
- } else {
- retVal = eGenericErr;
- }
- }
- }
-
- return (retVal);
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::BufferSizes
-//
-//! in case of 'eMatchedDuplexDevices' and a matching device exists return common buffer sizes
-//! in all other cases retur base class function implementation
-//!
-//! \param none
-//!
-//! \return current sample rate
-//!
-//**********************************************************************************************
-const std::vector<int>& WCMRCoreAudioDevice::BufferSizes()
-{
- return WCMRAudioDevice::BufferSizes();
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::CurrentBufferSize
-//
-//! 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 WCMRCoreAudioDevice::CurrentBufferSize ()
-{
- AUTO_FUNC_DEBUG;
-
- return (m_CurrentBufferSize);
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetCurrentBufferSize
-//
-//! 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 WCMRCoreAudioDevice::SetCurrentBufferSize (int newSize)
-{
- AUTO_FUNC_DEBUG;
- 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)
- goto Exit;
-
- if (Streaming())
- {
- //Can't change, perhaps use an "in use" type of error
- retVal = eGenericErr;
- goto Exit;
- }
-
- if (oldActive)
- {
- //Deactivate it for the change...
- SetActive (false);
- }
-
- // when audio device is inactive it is safe to set a working buffer size according to new buffer size
- // if 'newSize' is not a valid buffer size, another valid buffer size will be set
- retVal = SetWorkingBufferSize(newSize);
- if(retVal != eNoErr)
- {
- DEBUG_MSG("Unable to set a working buffer size. Device Name: " << DeviceName().c_str());
- goto Exit;
- }
-
- //reactivate it.
- if (oldActive)
- {
- retVal = SetActive (true);
- if(retVal != eNoErr)
- {
- DEBUG_MSG("Unable to activate device. Device Name: " << DeviceName().c_str());
- goto Exit;
- }
- }
-
-Exit:
-
- return (retVal);
-}
-
-WTErr WCMRCoreAudioDevice::SetWorkingBufferSize(int newSize)
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
-
- // 1. Set new buffer size
- err = SetBufferSizesByIO(newSize);
-
- // If there's no error it means this buffer size is supported
- if(err == kAudioHardwareNoError)
- {
- m_CurrentBufferSize = newSize;
- }
- // If there was an error it means that this buffer size was not supported
- else
- {
- // In case the new buffer size could not be set, set another working buffer size
-
- // Run on all buffer sizes:
-
- // Try setting buffer sizes that are bigger then selected buffer size first,
- // Since bigger buffer sizes usually work safer
- for(std::vector<int>::const_iterator iter = m_BufferSizes.begin();iter != m_BufferSizes.end();++iter)
- {
- int nCurBS = *iter;
-
- if(nCurBS > newSize)
- {
- // Try setting current buffer size
- err = SetBufferSizesByIO(nCurBS);
-
- // in case buffer size is valid
- if(err == kAudioHardwareNoError)
- {
- // Set current buffer size
- m_CurrentBufferSize = nCurBS;
- break;
- }
- }
- }
-
- // If bigger buffer sizes failed, go to smaller buffer sizes
- if(err != kAudioHardwareNoError)
- {
- for(std::vector<int>::const_iterator iter = m_BufferSizes.begin();iter != m_BufferSizes.end();++iter)
- {
- int nCurBS = *iter;
-
- if(nCurBS < newSize)
- {
- // Try setting current buffer size
- err = SetBufferSizesByIO(*iter);
-
- // in case buffer size is valid
- if(err == kAudioHardwareNoError)
- {
- // Set current buffer size
- m_CurrentBufferSize = *iter;
- break;
- }
- }
- }
- }
-
- // Check if a valid buffer size was found
- if(err == kAudioHardwareNoError)
- {
- // Notify that a different sample rate is set
- char debugMsg[256];
- snprintf (debugMsg, sizeof(debugMsg), "Could not set buffer size: %d, Set buffer size to: %d.", newSize, m_CurrentBufferSize);
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)debugMsg);
- }
- // if there was no buffer size that could be set
- else
- {
- // Set the parameter buffer size by default, set a debug message
- m_CurrentBufferSize = newSize;
- DEBUG_MSG("Unable to set any buffer size. Device Name: " << m_DeviceName.c_str());
- }
- }
-
- return retVal;
-}
-
-OSStatus WCMRCoreAudioDevice::SetBufferSizesByIO(int newSize)
-{
- OSStatus err = kAudioHardwareNoError;
-
- // 1. Set new buffer size
- UInt32 bufferSize = (UInt32)newSize;
- UInt32 propSize = sizeof (UInt32);
-
- // Set new buffer size to input
- if (!m_InputChannels.empty())
- {
- err = AudioDeviceSetProperty(m_DeviceID, NULL, 0, 1, kAudioDevicePropertyBufferFrameSize, propSize, &bufferSize);
- }
- else
- {
- err = AudioDeviceSetProperty(m_DeviceID, NULL, 0, 0, kAudioDevicePropertyBufferFrameSize, propSize, &bufferSize);
- }
-
- return err;
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::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.
-//!
-//**********************************************************************************************
-WCMRCoreAudioDevice::ConnectionStates WCMRCoreAudioDevice::ConnectionStatus ()
-{
- AUTO_FUNC_DEBUG;
- //ToDo: May want to do something more to extract the actual status!
- return (m_ConnectionStatus);
-
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::EnableAudioUnitIO
-//
-//! Sets up the AUHAL for IO, allowing changes to the devices to be used by the AudioUnit.
-//!
-//! \param none
-//!
-//! \return eNoErr on success, an error code on failure.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::EnableAudioUnitIO()
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
-
- UInt32 enableIO = 1;
- if (!m_InputChannels.empty())
- {
- ///////////////
- //ENABLE IO (INPUT)
- //You must enable the Audio Unit (AUHAL) for input
-
- //Enable input on the AUHAL
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,
- AUHAL_INPUT_ELEMENT,
- &enableIO, sizeof(enableIO));
-
- if (err)
- {
- DEBUG_MSG("Couldn't Enable IO on input scope of input element, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
- }
-
- //disable Output on the AUHAL if there's no output
- if (m_OutputChannels.empty())
- enableIO = 0;
- else
- enableIO = 1;
-
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,
- AUHAL_OUTPUT_ELEMENT,
- &enableIO, sizeof(enableIO));
-
- if (err)
- {
- DEBUG_MSG("Couldn't Enable/Disable IO on output scope of output element, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
-Exit:
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::EnableListeners
-//
-//! Sets up listeners to listen for Audio Device property changes, so that app can be notified.
-//!
-//! \param none
-//!
-//! \return eNoErr on success, an error code on failure.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::EnableListeners()
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
-
- //listner for SR change...
- err = AudioDeviceAddPropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyNominalSampleRate,
- StaticPropertyChangeProc, this);
-
- if (err)
- {
- DEBUG_MSG("Couldn't Setup SR Property Listner, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
-#if ENABLE_DEVICE_CHANGE_LISTNER
- {
- //listner for device change...
-
- err = AudioDeviceAddPropertyListener (m_DeviceID,
- kAudioPropertyWildcardChannel,
- true,
- kAudioDevicePropertyDeviceHasChanged,
- StaticPropertyChangeProc,
- this);
-
- if (err)
- {
- DEBUG_MSG("Couldn't Setup device change Property Listner, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
- }
-#endif //ENABLE_DEVICE_CHANGE_LISTNER
-
- //listner for dropouts...
- err = AudioDeviceAddPropertyListener(m_DeviceID, 0, 0, kAudioDeviceProcessorOverload,
- StaticPropertyChangeProc, this);
-
- if (err)
- {
- DEBUG_MSG("Couldn't Setup Processor Overload Property Listner, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
-
-Exit:
- return retVal;
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::DisableListeners
-//
-//! Undoes the work done by EnableListeners
-//!
-//! \param none
-//!
-//! \return eNoErr on success, an error code on failure.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::DisableListeners()
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
-
- //listner for SR change...
- err = AudioDeviceRemovePropertyListener(m_DeviceID, 0, 0, kAudioDevicePropertyNominalSampleRate,
- StaticPropertyChangeProc);
-
- if (err)
- {
- DEBUG_MSG("Couldn't Cleanup SR Property Listner, error = " << err);
- //not sure if we need to report this...
- }
-
-#if ENABLE_DEVICE_CHANGE_LISTNER
- {
- err = AudioDeviceRemovePropertyListener (m_DeviceID,
- kAudioPropertyWildcardChannel,
- true/* Input */,
- kAudioDevicePropertyDeviceHasChanged,
- StaticPropertyChangeProc);
-
- if (err)
- {
- DEBUG_MSG("Couldn't Cleanup device input stream change Property Listner, error = " << err);
- //not sure if we need to report this...
- }
-
- }
-#endif //ENABLE_DEVICE_CHANGE_LISTNER
-
- err = AudioDeviceRemovePropertyListener(m_DeviceID, 0, 0, kAudioDeviceProcessorOverload,
- StaticPropertyChangeProc);
-
- if (err)
- {
- DEBUG_MSG("Couldn't Cleanup device change Property Listner, error = " << err);
- //not sure if we need to report this...
- }
-
-
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::StaticPropertyChangeProc
-//
-//! The property change function called (as a result of EnableListeners) when device properties change.
-//! It calls upon the non-static PropertyChangeProc to do the work.
-//!
-//! \param inDevice : The audio device in question.
-//! \param inChannel : The channel on which the property has change.
-//! \param isInput : If the change is for Input.
-//! \param inPropertyID : The property that has changed.
-//! \param inClientData: What was passed when listener was enabled, in our case teh WCMRCoreAudioDevice object.
-//!
-//! \return 0 always.
-//!
-//**********************************************************************************************
-OSStatus WCMRCoreAudioDevice::StaticPropertyChangeProc (AudioDeviceID /*inDevice*/, UInt32 /*inChannel*/, Boolean /*isInput*/,
- AudioDevicePropertyID inPropertyID, void *inClientData)
-{
- if (inClientData)
- {
- WCMRCoreAudioDevice* pCoreDevice = (WCMRCoreAudioDevice *)inClientData;
- pCoreDevice->PropertyChangeProc (inPropertyID);
- }
-
- return 0;
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::PropertyChangeProc
-//
-//! The non-static property change proc. Gets called when properties change. Since this gets called
-//! on an arbitrary thread, we simply update the request counters and return.
-//!
-//! \param none
-//!
-//! \return nothing.
-//!
-//**********************************************************************************************
-void WCMRCoreAudioDevice::PropertyChangeProc (AudioDevicePropertyID inPropertyID)
-{
- switch (inPropertyID)
- {
- case kAudioDevicePropertyNominalSampleRate:
- m_SRChangeRequested++;
- break;
-#if ENABLE_DEVICE_CHANGE_LISTNER
- case kAudioDevicePropertyDeviceHasChanged:
- {
- m_ResetRequested++;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
- }
- break;
-#endif //ENABLE_DEVICE_CHANGE_LISTNER
- case kAudioDeviceProcessorOverload:
- {
- if (m_IgnoreThisDrop)
- m_IgnoreThisDrop = false; //We'll ignore once, just once!
- else
- m_DropsDetected++;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout );
- break;
- }
- default:
- break;
- }
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetupAUHAL
-//
-//! Sets up the AUHAL AudioUnit for device IO.
-//!
-//! \param none
-//!
-//! \return eNoErr on success, an error code on failure.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::SetupAUHAL()
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
- Component comp;
- ComponentDescription desc;
- AudioStreamBasicDescription streamFormatToUse, auhalStreamFormat;
-
- //There are several different types of Audio Units.
- //Some audio units serve as Outputs, Mixers, or DSP
- //units. See AUComponent.h for listing
- desc.componentType = kAudioUnitType_Output;
-
- //Every Component has a subType, which will give a clearer picture
- //of what this components function will be.
- desc.componentSubType = kAudioUnitSubType_HALOutput;
-
- //all Audio Units in AUComponent.h must use
- //"kAudioUnitManufacturer_Apple" as the Manufacturer
- desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- desc.componentFlags = 0;
- desc.componentFlagsMask = 0;
-
- //Finds a component that meets the desc spec's
- comp = FindNextComponent(NULL, &desc);
- if (comp == NULL)
- {
- DEBUG_MSG("Couldn't find AUHAL Component");
- retVal = eGenericErr;
- goto Exit;
- }
-
- //gains access to the services provided by the component
- OpenAComponent(comp, &m_AUHALAudioUnit);
-
-
- retVal = EnableAudioUnitIO();
- if (retVal != eNoErr)
- goto Exit;
-
- //Now setup the device to use by the audio unit...
-
- //input
- if (!m_InputChannels.empty())
- {
- err = AudioUnitSetProperty(m_AUHALAudioUnit, kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, AUHAL_INPUT_ELEMENT,
- &m_DeviceID, sizeof(m_DeviceID));
-
- if (err)
- {
- DEBUG_MSG("Couldn't Set the audio device property for Input Element Global scope, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
- }
-
- //output
- if (!m_OutputChannels.empty())
- {
- err = AudioUnitSetProperty(m_AUHALAudioUnit, kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, AUHAL_OUTPUT_ELEMENT,
- &m_DeviceID, sizeof(m_DeviceID));
-
- if (err)
- {
- DEBUG_MSG("Couldn't Set the audio device property for Output Element Global scope, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
- }
-
- //also set Sample Rate...
- {
- retVal = SetAndCheckCurrentSamplingRate(m_CurrentSamplingRate);
- if(retVal != eNoErr)
- {
- DEBUG_MSG ("Unable to set SR, error = " << err);
- goto Exit;
- }
- }
-
- //now set the buffer size...
- {
- err = SetWorkingBufferSize(m_CurrentBufferSize);
- if (err)
- {
- DEBUG_MSG("Couldn't Set the buffer size property, error = " << err);
- //we don't really quit here..., just keep going even if this does not work,
- //the AUHAL is supposed to take care of this by way of slicing...
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Could not set buffer size.");
-
- }
- }
-
- //convertor quality
- {
- UInt32 quality = kAudioConverterQuality_Max;
- propSize = sizeof (quality);
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_RenderQuality, kAudioUnitScope_Global,
- AUHAL_OUTPUT_ELEMENT,
- &quality, sizeof (quality));
-
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to set Convertor Quality, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
- }
-
- memset (&auhalStreamFormat, 0, sizeof (auhalStreamFormat));
- propSize = sizeof (auhalStreamFormat);
- err = AudioUnitGetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
- AUHAL_INPUT_ELEMENT,
- &auhalStreamFormat, &propSize);
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to get Input format, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
- if (auhalStreamFormat.mSampleRate != (Float64)m_CurrentSamplingRate)
- {
- TRACE_MSG ("AUHAL's Input SR differs from expected SR, expected = " << m_CurrentSamplingRate << ", AUHAL's = " << (UInt32)auhalStreamFormat.mSampleRate);
- }
-
- //format, and slice size...
- memset (&streamFormatToUse, 0, sizeof (streamFormatToUse));
- streamFormatToUse.mFormatID = kAudioFormatLinearPCM;
- streamFormatToUse.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
- streamFormatToUse.mFramesPerPacket = 1;
- streamFormatToUse.mBitsPerChannel = sizeof (float) * 8;
- streamFormatToUse.mSampleRate = auhalStreamFormat.mSampleRate;
-
- if (!m_InputChannels.empty())
- {
- streamFormatToUse.mChannelsPerFrame = m_InputChannels.size();
- streamFormatToUse.mBytesPerFrame = sizeof (float)*streamFormatToUse.mChannelsPerFrame;
- streamFormatToUse.mBytesPerPacket = streamFormatToUse.mBytesPerFrame;
- propSize = sizeof (streamFormatToUse);
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
- AUHAL_INPUT_ELEMENT,
- &streamFormatToUse, sizeof (streamFormatToUse));
-
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to set Input format, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
- UInt32 bufferSize = m_CurrentBufferSize;
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output,
- AUHAL_INPUT_ELEMENT,
- &bufferSize, sizeof (bufferSize));
-
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to set Input frames, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
- }
-
- if (!m_OutputChannels.empty())
- {
- err = AudioUnitGetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
- AUHAL_OUTPUT_ELEMENT,
- &auhalStreamFormat, &propSize);
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to get Output format, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
- if (auhalStreamFormat.mSampleRate != (Float64)m_CurrentSamplingRate)
- {
- TRACE_MSG ("AUHAL's Output SR differs from expected SR, expected = " << m_CurrentSamplingRate << ", AUHAL's = " << (UInt32)auhalStreamFormat.mSampleRate);
- }
-
-
- streamFormatToUse.mChannelsPerFrame = m_OutputChannels.size();
- streamFormatToUse.mBytesPerFrame = sizeof (float)*streamFormatToUse.mChannelsPerFrame;
- streamFormatToUse.mBytesPerPacket = streamFormatToUse.mBytesPerFrame;
- streamFormatToUse.mSampleRate = auhalStreamFormat.mSampleRate;
- propSize = sizeof (streamFormatToUse);
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
- AUHAL_OUTPUT_ELEMENT,
- &streamFormatToUse, sizeof (streamFormatToUse));
-
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to set Output format, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
- UInt32 bufferSize = m_CurrentBufferSize;
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Input,
- AUHAL_OUTPUT_ELEMENT,
- &bufferSize, sizeof (bufferSize));
-
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to set Output frames, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
- }
-
- //setup callback (IOProc)
- {
- AURenderCallbackStruct renderCallback;
- memset (&renderCallback, 0, sizeof (renderCallback));
- propSize = sizeof (renderCallback);
- renderCallback.inputProc = StaticAudioIOProc;
- renderCallback.inputProcRefCon = this;
-
- err = AudioUnitSetProperty(m_AUHALAudioUnit,
- (m_OutputChannels.empty() ? (AudioUnitPropertyID)kAudioOutputUnitProperty_SetInputCallback : (AudioUnitPropertyID)kAudioUnitProperty_SetRenderCallback),
- kAudioUnitScope_Output,
- m_OutputChannels.empty() ? AUHAL_INPUT_ELEMENT : AUHAL_OUTPUT_ELEMENT,
- &renderCallback, sizeof (renderCallback));
-
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to set callback, error = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
- }
-
- retVal = EnableListeners();
- if (retVal != eNoErr)
- goto Exit;
-
- //initialize the audio-unit now!
- err = AudioUnitInitialize(m_AUHALAudioUnit);
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG ("Unable to Initialize AudioUnit = " << err);
- retVal = eGenericErr;
- goto Exit;
- }
-
-Exit:
- if (retVal != eNoErr)
- TearDownAUHAL();
-
- return retVal;
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::TearDownAUHAL
-//
-//! Undoes the work done by SetupAUHAL
-//!
-//! \param none
-//!
-//! \return eNoErr on success, an error code on failure.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::TearDownAUHAL()
-{
- WTErr retVal = eNoErr;
-
- if (m_AUHALAudioUnit)
- {
- DisableListeners ();
- AudioUnitUninitialize(m_AUHALAudioUnit);
- CloseComponent(m_AUHALAudioUnit);
- m_AUHALAudioUnit = NULL;
- }
-
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetActive
-//
-//! Sets the device's activation status. Essentially, opens or closes the PA device.
-//! If it's an ASIO device it may result in buffer size change in some cases.
-//!
-//! \param newState : Should be true to activate, false to deactivate. This roughly corresponds
-//! to opening and closing the device handle/stream/audio unit.
-//!
-//! \return eNoErr on success, an error code otherwise.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::SetActive (bool newState)
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
-
- if (Active() == newState)
- goto Exit;
-
-
- if (newState)
- {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Setting up AUHAL.");
- retVal = SetupAUHAL();
-
- if (retVal != eNoErr)
- goto Exit;
-
- m_BufferSizeChangeRequested = 0;
- m_BufferSizeChangeReported = 0;
- m_ResetRequested = 0;
- m_ResetReported = 0;
- m_ResyncRequested = 0;
- m_ResyncReported = 0;
- m_SRChangeRequested = 0;
- m_SRChangeReported = 0;
- m_DropsDetected = 0;
- m_DropsReported = 0;
- m_IgnoreThisDrop = true;
- }
- else
- {
- if (Streaming())
- {
- SetStreaming (false);
- }
-
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Tearing down AUHAL.");
- retVal = TearDownAUHAL();
- if (retVal != eNoErr)
- goto Exit;
-
- m_BufferSizeChangeRequested = 0;
- m_BufferSizeChangeReported = 0;
- m_ResetRequested = 0;
- m_ResetReported = 0;
- m_ResyncRequested = 0;
- m_ResyncReported = 0;
- m_SRChangeRequested = 0;
- m_SRChangeReported = 0;
- m_DropsDetected = 0;
- m_DropsReported = 0;
- m_IgnoreThisDrop = true;
-
- UpdateDeviceInfo();
- }
-
- m_IsActive = newState;
-
-Exit:
- return (retVal);
-}
-
-
-#if WV_USE_TONE_GEN
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetupToneGenerator
-//
-//! Sets up the Tone generator - only if a file /tmp/tonegen.txt is present. If the file is
-//! present, it reads the value in the file and uses that as the frequency for the tone. This
-//! code attempts to create an array of samples that would constitute an integral number of
-//! cycles - for the currently active sampling rate. If tonegen is active, then the input
-//! from the audio device is ignored, instead a data is supplied from the tone generator's
-//! array - for all channels. The array is in m_pToneData, the size of the array is in
-//! m_ToneDataSamples, and m_NextSampleToUse holds the index in the array from where
-//! the next sample is going to be taken.
-//!
-//!
-//! \return : Nothing
-//!
-//**********************************************************************************************
-void WCMRCoreAudioDevice::SetupToneGenerator ()
-{
- safe_delete_array(m_pToneData);
- m_ToneDataSamples = 0;
-
- //if tonegen exists?
- FILE *toneGenHandle = fopen ("/tmp/tonegen.txt", "r");
- if (toneGenHandle)
- {
- int toneFreq = 0;
- fscanf(toneGenHandle, "%d", &toneFreq);
- if ((toneFreq <= 0) || (toneFreq > (m_CurrentSamplingRate/2)))
- {
- toneFreq = 1000;
- }
-
-
- m_ToneDataSamples = m_CurrentSamplingRate / toneFreq;
- int toneDataSamplesFrac = m_CurrentSamplingRate % m_ToneDataSamples;
- int powerOfTen = 1;
- while (toneDataSamplesFrac)
- {
- m_ToneDataSamples = (uint32_t)((pow(10, powerOfTen) * m_CurrentSamplingRate) / toneFreq);
- toneDataSamplesFrac = m_CurrentSamplingRate % m_ToneDataSamples;
- powerOfTen++;
- }
-
- //allocate
- m_pToneData = new float_t[m_ToneDataSamples];
-
- //fill with a -6dB Sine Tone
- uint32_t numSamplesLeft = m_ToneDataSamples;
- float_t *pNextSample = m_pToneData;
- double phase = 0;
- double phaseIncrement = (M_PI * 2.0 * toneFreq ) / ((double)m_CurrentSamplingRate);
- while (numSamplesLeft)
- {
- *pNextSample = (float_t)(0.5 * sin(phase));
- phase += phaseIncrement;
- pNextSample++;
- numSamplesLeft--;
- }
-
- m_NextSampleToUse = 0;
-
- fclose(toneGenHandle);
- }
-}
-#endif //WV_USE_TONE_GEN
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::SetStreaming
-//
-//! Sets the device's streaming status. Calls PA's Start/Stop stream routines.
-//!
-//! \param newState : Should be true to start streaming, false to stop streaming. This roughly
-//! corresponds to calling Start/Stop on the lower level interface.
-//!
-//! \return eNoErr always, the derived classes may return appropriate error code.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::SetStreaming (bool newState)
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- ComponentResult err = 0;
-
- if (Streaming () == newState)
- goto Exit;
-
- if (newState)
- {
-#if WV_USE_TONE_GEN
- SetupToneGenerator ();
-#endif //WV_USE_TONE_GEN
-
- m_SampleCountAtLastIdle = 0;
- m_StalledSampleCounter = 0;
- m_SampleCounter = 0;
- m_IOProcThreadPort = 0;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Starting AUHAL.");
-
- // Prepare for streaming - tell Engine to do the initialization for process callback
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
-
- if (m_UseMultithreading)
- {
- //set thread constraints...
- unsigned int periodAndConstraintUS = (unsigned int)((1000000.0 * m_CurrentBufferSize) / m_CurrentSamplingRate);
- unsigned int computationUS = (unsigned int)(0.8 * periodAndConstraintUS); //assuming we may want to use up to 80% CPU
- //ErrandManager().SetRealTimeConstraintsForAllThreads (periodAndConstraintUS, computationUS, periodAndConstraintUS);
- }
-
- err = AudioOutputUnitStart (m_AUHALAudioUnit);
-
- m_StopRequested = false;
-
- if(err)
- {
- DEBUG_MSG( "Failed to start AudioUnit, err " << err );
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Failed to start AudioUnit.");
- retVal = eGenericErr;
- goto Exit;
- }
- }
- else
- {
- m_StopRequested = true;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDebugInfo, (void *)"Stopping AUHAL.");
- err = AudioOutputUnitStop (m_AUHALAudioUnit);
- if (!err)
- {
- //if (!m_InputChannels.empty());
- {
- err = AudioUnitReset (m_AUHALAudioUnit, kAudioUnitScope_Global, AUHAL_INPUT_ELEMENT);
- }
- //if (!m_OutputChannels.empty());
- {
- err = AudioUnitReset (m_AUHALAudioUnit, kAudioUnitScope_Global, AUHAL_OUTPUT_ELEMENT);
- }
- }
-
- if(err)
- {
- DEBUG_MSG( "Failed to stop AudioUnit " << err );
- retVal = eGenericErr;
- goto Exit;
- }
- m_IOProcThreadPort = 0;
- }
-
- // After units restart, reset request for reset and SR change
- m_SRChangeReported = m_SRChangeRequested;
- m_ResetReported = m_ResetRequested;
-
- m_IsStreaming = newState;
-
-Exit:
- return (retVal);
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::DoIdle
-//
-//! A place for doing idle time processing. The other derived classes will probably do something
-//! meaningful.
-//!
-//! \param none
-//!
-//! \return eNoErr always.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::DoIdle ()
-{
- /*
- if (m_BufferSizeChangeRequested != m_BufferSizeChangeReported)
- {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged);
- m_BufferSizeChangeReported = m_BufferSizeChangeRequested;
- }
-
- if (m_ResetRequested != m_ResetReported)
- {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
- m_ResetReported = m_ResetRequested;
- }
-
-
- if (m_ResyncRequested != m_ResyncReported)
- {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestResync);
- m_ResyncReported = m_ResyncRequested;
- }
-
- if (m_SRChangeReported != m_SRChangeRequested)
- {
- m_SRChangeReported = m_SRChangeRequested;
- int newSR = CurrentSamplingRate();
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::SamplingRateChanged, (void *)newSR);
- }
-
- if (m_DropsReported != m_DropsDetected)
- {
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceDroppedSamples);
- m_DropsReported = m_DropsDetected;
- }
-
-
- //Perhaps add checks to make sure a stream counter is incrementing if
- //stream is supposed to be streaming!
- if (Streaming())
- {
- //latch the value
- int64_t currentSampleCount = m_SampleCounter;
- if (m_SampleCountAtLastIdle == currentSampleCount)
- m_StalledSampleCounter++;
- else
- {
- m_SampleCountAtLastIdle = (int)currentSampleCount;
- m_StalledSampleCounter = 0;
- }
-
- if (m_StalledSampleCounter > NUM_STALLS_FOR_NOTIFICATION)
- {
- m_StalledSampleCounter = 0;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStoppedStreaming, (void *)currentSampleCount);
- }
- }*/
-
-
- return (eNoErr);
-}
-
-
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::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 WCMRCoreAudioDevice::SetMonitorChannels (int leftChannel, int rightChannel)
-{
- AUTO_FUNC_DEBUG;
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_LeftMonitorChannel = leftChannel;
- m_RightMonitorChannel = rightChannel;
- return (eNoErr);
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::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)
-//!
-//! \return eNoErr always, the derived classes may return appropriate errors.
-//!
-//**********************************************************************************************
-WTErr WCMRCoreAudioDevice::SetMonitorGain (float newGain)
-{
- AUTO_FUNC_DEBUG;
- //This will most likely be overridden, the base class simply
- //changes the member.
-
-
- m_MonitorGain = newGain;
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::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 WCMRCoreAudioDevice::ShowConfigPanel (void */*pParam*/)
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
-
- CFStringRef configAP;
- UInt32 propSize = sizeof (configAP);
- /*
- @constant kAudioDevicePropertyConfigurationApplication
- A CFString that contains the bundle ID for an application that provides a
- GUI for configuring the AudioDevice. By default, the value of this property
- is the bundle ID for Audio MIDI Setup. The caller is responsible for
- releasing the returned CFObject.
- */
-
- if (AudioDeviceGetProperty(m_DeviceID, 0, 0, kAudioDevicePropertyConfigurationApplication, &propSize, &configAP) == kAudioHardwareNoError)
- {
- // get the FSRef of the config app
- FSRef theAppFSRef;
- OSStatus theError = LSFindApplicationForInfo(kLSUnknownCreator, configAP, NULL, &theAppFSRef, NULL);
- if (!theError)
- {
- LSOpenFSRef(&theAppFSRef, NULL);
- }
- else
- {
- // open default AudioMIDISetup if device app is not found
- CFStringRef audiMidiSetupApp = CFStringCreateWithCString(kCFAllocatorDefault, "com.apple.audio.AudioMIDISetup", kCFStringEncodingMacRoman);
- theError = LSFindApplicationForInfo(kLSUnknownCreator, audiMidiSetupApp, NULL, &theAppFSRef, NULL);
-
- if (!theError)
- {
- LSOpenFSRef(&theAppFSRef, NULL);
- }
- }
-
- CFRelease (configAP);
- }
-
- return (retVal);
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::StaticAudioIOProc
-//
-//! The AudioIOProc that gets called when the AudioUnit is ready with recorded audio, and wants to get audio.
-//! This one simply calls the non-static member.
-//!
-//! \param inRefCon : What was passed when setting up the Callback (in our case a pointer to teh WCMRCoreAudioDevice object).
-//! \param ioActionFlags : What actios has to be taken.
-//! \param inTimeStamp: When the data will be played back.
-//! \param inBusNumber : The AU element.
-//! \param inNumberFrames: Number af Audio frames that are requested.
-//! \param ioData : Where the playback data is to be placed.
-//!
-//! \return 0 always
-//!
-//**********************************************************************************************
-OSStatus WCMRCoreAudioDevice::StaticAudioIOProc(void *inRefCon, AudioUnitRenderActionFlags * ioActionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList *ioData)
-{
- WCMRCoreAudioDevice *pMyDevice = (WCMRCoreAudioDevice *)inRefCon;
- if (pMyDevice)
- return pMyDevice->AudioIOProc (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
- else
- return 0;
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::AudioIOProc
-//
-//! The non-static AudioIOProc that gets called when the AudioUnit is ready with recorded audio, and wants to get audio.
-//! We retrieve the recorded audio, and then do our processing, to generate audio to be played back.
-//!
-//! \param ioActionFlags : What actios has to be taken.
-//! \param inTimeStamp: When the data will be played back.
-//! \param inBusNumber : The AU element.
-//! \param inNumberFrames: Number af Audio frames that are requested.
-//! \param ioData : Where the playback data is to be placed.
-//!
-//! \return 0 always
-//!
-//**********************************************************************************************
-OSStatus WCMRCoreAudioDevice::AudioIOProc(AudioUnitRenderActionFlags * ioActionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 /*inBusNumber*/, UInt32 inNumberFrames,
- AudioBufferList *ioData)
-{
- UInt64 theStartTime = AudioGetCurrentHostTime();
-
- OSStatus retVal = 0;
-
- if (m_StopRequested)
- return retVal;
-
- if (m_IOProcThreadPort == 0)
- m_IOProcThreadPort = mach_thread_self ();
-
- //cannot really deal with it unless the number of frames are the same as our buffer size!
- if (inNumberFrames != (UInt32)m_CurrentBufferSize)
- return retVal;
-
- //Retrieve the input data...
- if (!m_InputChannels.empty())
- {
- UInt32 expectedDataSize = m_InputChannels.size() * m_CurrentBufferSize * sizeof(float);
- AudioBufferList inputAudioBufferList;
- inputAudioBufferList.mNumberBuffers = 1;
- inputAudioBufferList.mBuffers[0].mNumberChannels = m_InputChannels.size();
- inputAudioBufferList.mBuffers[0].mDataByteSize = expectedDataSize;
- inputAudioBufferList.mBuffers[0].mData = NULL;//new float[expectedDataSize]; // we are going to get buffer from CoreAudio
-
- retVal = AudioUnitRender(m_AUHALAudioUnit, ioActionFlags, inTimeStamp, AUHAL_INPUT_ELEMENT, inNumberFrames, &inputAudioBufferList);
-
- if (retVal == kAudioHardwareNoError &&
- inputAudioBufferList.mBuffers[0].mNumberChannels == m_InputChannels.size() &&
- inputAudioBufferList.mBuffers[0].mDataByteSize == expectedDataSize )
- {
- m_pInputData = (float*)inputAudioBufferList.mBuffers[0].mData;
- }
- else
- {
- m_pInputData = NULL;
- return retVal;
- }
- }
-
- //is this an input only device?
- if (m_OutputChannels.empty())
- AudioCallback (NULL, inNumberFrames, (int64_t)inTimeStamp->mSampleTime, theStartTime);
- else if ((!m_OutputChannels.empty()) && (ioData->mBuffers[0].mNumberChannels == m_OutputChannels.size()))
- AudioCallback ((float *)ioData->mBuffers[0].mData, inNumberFrames, (int64_t)inTimeStamp->mSampleTime, theStartTime);
-
- return retVal;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::AudioCallback
-//
-//! 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 *pOutputBuffer : Points to a buffer to receive playback data. For Input only devices, this will be NULL
-//! \param framesPerBuffer : Number of sample frames in input and output buffers. Number of channels,
-//! which are interleaved, is fixed at Device Open (Active) time. In this implementation,
-//! the number of channels are fixed to use the maximum available.
-//!
-//! \return true
-//!
-//**********************************************************************************************
-int WCMRCoreAudioDevice::AudioCallback (float *pOutputBuffer, unsigned long framesPerBuffer, int64_t inSampleTime, uint64_t inCycleStartTime)
-{
- struct WCMRAudioDeviceManagerClient::AudioCallbackData audioCallbackData =
- {
- m_pInputData,
- pOutputBuffer,
- framesPerBuffer,
- inSampleTime,
- AudioConvertHostTimeToNanos(inCycleStartTime)
- };
-
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData);
-
- m_SampleCounter += framesPerBuffer;
- return m_StopRequested;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::GetLatency
-//
-//! Get Latency for device.
-//!
-//! Use 'kAudioDevicePropertyLatency' and 'kAudioDevicePropertySafetyOffset' + GetStreamLatencies
-//!
-//! \param isInput : Return latency for the input if isInput is true, otherwise the output latency
-//! wiil be returned.
-//! \return Latency in samples.
-//!
-//**********************************************************************************************
-uint32_t WCMRCoreAudioDevice::GetLatency(bool isInput)
-{
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
-
- UInt32 propSize = sizeof(UInt32);
- UInt32 value1 = 0;
- UInt32 value2 = 0;
-
- UInt32 latency = 0;
- std::vector<int> streamLatencies;
-
-
- err = AudioDeviceGetProperty(m_DeviceID, 0, isInput, kAudioDevicePropertyLatency, &propSize, &value1);
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG("GetLatency kAudioDevicePropertyLatency err = " << err);
- }
-
- err = AudioDeviceGetProperty(m_DeviceID, 0, isInput, kAudioDevicePropertySafetyOffset, &propSize, &value2);
- if (err != kAudioHardwareNoError)
- {
- DEBUG_MSG("GetLatency kAudioDevicePropertySafetyOffset err = " << err);
- }
-
- latency = value1 + value2;
-
- err = GetStreamLatency(m_DeviceID, isInput, streamLatencies);
- if (err == kAudioHardwareNoError)
- {
- for ( int i = 0; i < streamLatencies.size(); i++) {
- latency += streamLatencies[i];
- }
- }
-
- return latency;
-}
-
-//**********************************************************************************************
-// WCMRCoreAudioDevice::GetStreamLatency
-//
-//! Get stream latency for device.
-//!
-//! \param deviceID : The audio device ID.
-//!
-//! \param isInput : Return latency for the input if isInput is true, otherwise the output latency
-//! wiil be returned.
-//**********************************************************************************************
-OSStatus WCMRCoreAudioDevice::GetStreamLatency(AudioDeviceID device, bool isInput, std::vector<int>& latencies)
-{
- OSStatus err = kAudioHardwareNoError;
- UInt32 outSize1, outSize2, outSize3;
- Boolean outWritable;
-
- err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
- if (err == noErr) {
- int stream_count = outSize1 / sizeof(UInt32);
- AudioStreamID streamIDs[stream_count];
- AudioBufferList bufferList[stream_count];
- UInt32 streamLatency;
- outSize2 = sizeof(UInt32);
-
- err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
- if (err != noErr) {
- DEBUG_MSG("GetStreamLatencies kAudioDevicePropertyStreams err = " << err);
- return err;
- }
-
- err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
- if (err != noErr) {
- DEBUG_MSG("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = " << err);
- return err;
- }
-
- for (int i = 0; i < stream_count; i++) {
- err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
- if (err != noErr) {
- DEBUG_MSG("GetStreamLatencies kAudioStreamPropertyLatency err = " << err);
- return err;
- }
- err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
- if (err != noErr) {
- DEBUG_MSG("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = " << err);
- return err;
- }
- latencies.push_back(streamLatency);
- }
- }
- return err;
-}
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager
-//
-//! The constructuor, we initialize PA, and build the device list.
-//!
-//! \param *pTheClient : The manager's client object (which receives notifications).
-//! \param useMultithreading : Whether to use multi-threading for audio processing. Default is true.
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRCoreAudioDeviceManager::WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient,
- eAudioDeviceFilter eCurAudioDeviceFilter, bool useMultithreading, bool bNocopy)
- : WCMRAudioDeviceManager (pTheClient, eCurAudioDeviceFilter)
- , m_UseMultithreading (useMultithreading)
- , m_bNoCopyAudioBuffer(bNocopy)
-{
- AUTO_FUNC_DEBUG;
-
- //first of all, tell HAL to use it's own run loop, not to wait for our runloop to do
- //it's dirty work...
- //Essentially, this makes the HAL on Snow Leopard behave like Leopard.
- //It's not yet (as of October 2009 documented), but the following discussion
- //has the information provided by Jeff Moore @ Apple:
- // http://lists.apple.com/archives/coreaudio-api/2009/Oct/msg00214.html
- //
- // As per Jeff's suggestion, opened an Apple Bug on this - ID# 7364011
-
- CFRunLoopRef nullRunLoop = 0;
- OSStatus err = AudioHardwareSetProperty (kAudioHardwarePropertyRunLoop, sizeof(CFRunLoopRef), &nullRunLoop);
-
- if (err != kAudioHardwareNoError)
- {
- syslog (LOG_NOTICE, "Unable to set RunLoop for Audio Hardware");
- }
-
- //add a listener to find out when devices change...
- AudioHardwareAddPropertyListener (kAudioHardwarePropertyDevices, HardwarePropertyChangeCallback, this);
-
- //Always add the None device first...
- m_NoneDevice = new WCMRNativeAudioNoneDevice(this);
-
- //prepare our initial list...
- generateDeviceListImpl();
-
- return;
-}
-
-
-
-//**********************************************************************************************
-// WCMRCoreAudioDeviceManager::~WCMRCoreAudioDeviceManager
-//
-//! It clears the device list, releasing each of the device.
-//!
-//! \param none
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRCoreAudioDeviceManager::~WCMRCoreAudioDeviceManager()
-{
- AUTO_FUNC_DEBUG;
-
- try
- {
- delete m_NoneDevice;
- }
- catch (...)
- {
- //destructors should absorb exceptions, no harm in logging though!!
- DEBUG_MSG ("Exception during destructor");
- }
-
-}
-
-
-WCMRAudioDevice* WCMRCoreAudioDeviceManager::initNewCurrentDeviceImpl(const std::string & deviceName)
-{
- destroyCurrentDeviceImpl();
-
- std::cout << "API::PortAudioDeviceManager::initNewCurrentDevice " << deviceName << std::endl;
- if (deviceName == m_NoneDevice->DeviceName() )
- {
- m_CurrentDevice = m_NoneDevice;
- return m_CurrentDevice;
- }
-
- DeviceInfo devInfo;
- WTErr err = GetDeviceInfoByName(deviceName, devInfo);
-
- if (eNoErr == err)
- {
- try
- {
- std::cout << "API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName << std::endl;
- TRACE_MSG ("API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName);
-
- m_CurrentDevice = new WCMRCoreAudioDevice (this, devInfo.m_DeviceId, m_UseMultithreading, m_bNoCopyAudioBuffer);
- }
- catch (...)
- {
- std::cout << "Unabled to create PA Device: " << devInfo.m_DeviceId << std::endl;
- DEBUG_MSG ("Unabled to create PA Device: " << devInfo.m_DeviceId);
- }
- }
-
- return m_CurrentDevice;
-}
-
-
-void WCMRCoreAudioDeviceManager::destroyCurrentDeviceImpl()
-{
- if (m_CurrentDevice != m_NoneDevice)
- delete m_CurrentDevice;
-
- m_CurrentDevice = 0;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates)
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- sampleRates.clear();
-
- //! 1. Get sample rate property size.
- err = AudioDeviceGetPropertyInfo(deviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels output.
-
- // Allocate size according to the number of audio values
- int numRates = propSize / sizeof(AudioValueRange);
- AudioValueRange* supportedRates = new AudioValueRange[numRates];
-
- // Get sampling rates from Audio device
- err = AudioDeviceGetProperty(deviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, supportedRates);
- if (err == kAudioHardwareNoError)
- {
- //! 3. Update sample rates
-
- // now iterate through our standard SRs
- for(int ourSR=0; gAllSampleRates[ourSR] > 0; ourSR++)
- {
- //check to see if our SR is in the supported rates...
- for (int deviceSR = 0; deviceSR < numRates; deviceSR++)
- {
- if ((supportedRates[deviceSR].mMinimum <= gAllSampleRates[ourSR]) &&
- (supportedRates[deviceSR].mMaximum >= gAllSampleRates[ourSR]))
- {
- sampleRates.push_back ((int)gAllSampleRates[ourSR]);
- break;
- }
- }
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Sample rates. Device Name: " << m_DeviceName.c_str());
- }
-
- delete [] supportedRates;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Sample rates property size. Device Name: " << m_DeviceName.c_str());
- }
-
- return retVal;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels)
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
- inputChannels = 0;
-
- // 1. Get property cannels input size.
- err = AudioDeviceGetPropertyInfo (deviceId, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels input.
-
- // Allocate size according to the property size. Note that this is a variable sized struct...
- AudioBufferList *pStreamBuffers = (AudioBufferList *)malloc(propSize);
-
- if (pStreamBuffers)
- {
- memset (pStreamBuffers, 0, propSize);
-
- // Get the Input channels
- err = AudioDeviceGetProperty (deviceId, 0, 1/* Input */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
- if (err == kAudioHardwareNoError)
- {
- // Calculate the number of input channels
- for (UInt32 streamIndex = 0; streamIndex < pStreamBuffers->mNumberBuffers; streamIndex++)
- {
- inputChannels += pStreamBuffers->mBuffers[streamIndex].mNumberChannels;
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Input channels. Device Name: " << m_DeviceName.c_str());
- }
-
- free (pStreamBuffers);
- }
- else
- {
- retVal = eMemOutOfMemory;
- DEBUG_MSG("Faild to allocate memory. Device Name: " << m_DeviceName.c_str());
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Input channels property size. Device Name: " << m_DeviceName.c_str());
- }
-
- return retVal;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::getDeviceMaxOutputChannels(DeviceID deviceId, unsigned int& outputChannels)
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
- outputChannels = 0;
-
- //! 1. Get property cannels output size.
- err = AudioDeviceGetPropertyInfo (deviceId, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, NULL);
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels output.
-
- // Allocate size according to the property size. Note that this is a variable sized struct...
- AudioBufferList *pStreamBuffers = (AudioBufferList *)malloc(propSize);
- if (pStreamBuffers)
- {
- memset (pStreamBuffers, 0, propSize);
-
- // Get the Output channels
- err = AudioDeviceGetProperty (deviceId, 0, 0/* Output */, kAudioDevicePropertyStreamConfiguration, &propSize, pStreamBuffers);
- if (err == kAudioHardwareNoError)
- {
- // Calculate the number of output channels
- for (UInt32 streamIndex = 0; streamIndex < pStreamBuffers->mNumberBuffers; streamIndex++)
- {
- outputChannels += pStreamBuffers->mBuffers[streamIndex].mNumberChannels;
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Output channels. Device Name: " << m_DeviceName.c_str());
- }
- free (pStreamBuffers);
- }
- else
- {
- retVal = eMemOutOfMemory;
- DEBUG_MSG("Faild to allocate memory. Device Name: " << m_DeviceName.c_str());
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Output channels property size. Device Name: " << m_DeviceName.c_str());
- }
-
- return retVal;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::generateDeviceListImpl()
-{
- AUTO_FUNC_DEBUG;
-
- // lock the list first
- wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
- m_DeviceInfoVec.clear();
-
- //First, get info from None device which is always present
- if (m_NoneDevice)
- {
- DeviceInfo *pDevInfo = new DeviceInfo(NONE_DEVICE_ID, m_NoneDevice->DeviceName() );
- pDevInfo->m_AvailableSampleRates = m_NoneDevice->SamplingRates();
- m_DeviceInfoVec.push_back(pDevInfo);
- }
-
- WTErr retVal = eNoErr;
- OSStatus osErr = noErr;
- AudioDeviceID* deviceIDs = 0;
-
- openlog("WCMRCoreAudioDeviceManager", LOG_PID | LOG_CONS, LOG_USER);
-
- try
- {
- //Get device count...
- UInt32 propSize = 0;
- osErr = AudioHardwareGetPropertyInfo (kAudioHardwarePropertyDevices, &propSize, NULL);
- ASSERT_ERROR(osErr, "AudioHardwareGetProperty 1");
- if (WUIsError(osErr))
- throw osErr;
-
- size_t numDevices = propSize / sizeof (AudioDeviceID);
- deviceIDs = new AudioDeviceID[numDevices];
-
- //retrieve the device IDs
- propSize = numDevices * sizeof (AudioDeviceID);
- osErr = AudioHardwareGetProperty (kAudioHardwarePropertyDevices, &propSize, deviceIDs);
- ASSERT_ERROR(osErr, "Error while getting audio devices: AudioHardwareGetProperty 2");
- if (WUIsError(osErr))
- throw osErr;
-
- //now add the ones that are not there...
- for (size_t deviceIndex = 0; deviceIndex < numDevices; deviceIndex++)
- {
- DeviceInfo* pDevInfo = 0;
-
- //Get device name and create new DeviceInfo entry
- //Get property name size.
- osErr = AudioDeviceGetPropertyInfo(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL);
- if (osErr == kAudioHardwareNoError)
- {
- //Get property: name.
- char* deviceName = new char[propSize];
- osErr = AudioDeviceGetProperty(deviceIDs[deviceIndex], 0, 0, kAudioDevicePropertyDeviceName, &propSize, deviceName);
- if (osErr == kAudioHardwareNoError)
- {
- pDevInfo = new DeviceInfo(deviceIDs[deviceIndex], deviceName);
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device name. Device ID: " << m_DeviceID);
- }
-
- delete [] deviceName;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device name property size. Device ID: " << m_DeviceID);
- }
-
- if (pDevInfo)
- {
- //Retrieve all the information we need for the device
- WTErr wErr = eNoErr;
-
- //Get available sample rates for the device
- std::vector<int> availableSampleRates;
- wErr = getDeviceAvailableSampleRates(pDevInfo->m_DeviceId, availableSampleRates);
-
- if (wErr != eNoErr)
- {
- DEBUG_MSG ("Failed to get device available sample rates. Device ID: " << m_DeviceID);
- delete pDevInfo;
- continue; //proceed to the next device
- }
-
- pDevInfo->m_AvailableSampleRates = availableSampleRates;
-
- //Get max input channels
- uint32_t maxInputChannels;
- wErr = getDeviceMaxInputChannels(pDevInfo->m_DeviceId, maxInputChannels);
-
- if (wErr != eNoErr)
- {
- DEBUG_MSG ("Failed to get device max input channels count. Device ID: " << m_DeviceID);
- delete pDevInfo;
- continue; //proceed to the next device
- }
-
- pDevInfo->m_MaxInputChannels = maxInputChannels;
-
- //Get max output channels
- uint32_t maxOutputChannels;
- wErr = getDeviceMaxOutputChannels(pDevInfo->m_DeviceId, maxOutputChannels);
-
- if (wErr != eNoErr)
- {
- DEBUG_MSG ("Failed to get device max output channels count. Device ID: " << m_DeviceID);
- delete pDevInfo;
- continue; //proceed to the next device
- }
-
- pDevInfo->m_MaxOutputChannels = maxOutputChannels;
-
- //Now check if this device is acceptable according to current input/output settings
- bool bRejectDevice = false;
- switch(m_eAudioDeviceFilter)
- {
- case eInputOnlyDevices:
- if (pDevInfo->m_MaxInputChannels != 0)
- {
- m_DeviceInfoVec.push_back(pDevInfo);
- }
- else
- {
- // Delete unnecesarry device
- bRejectDevice = true;
- }
- break;
- case eOutputOnlyDevices:
- if (pDevInfo->m_MaxOutputChannels != 0)
- {
- m_DeviceInfoVec.push_back(pDevInfo);
- }
- else
- {
- // Delete unnecesarry device
- bRejectDevice = true;
- }
- break;
- case eFullDuplexDevices:
- if (pDevInfo->m_MaxInputChannels != 0 && pDevInfo->m_MaxOutputChannels != 0)
- {
- m_DeviceInfoVec.push_back(pDevInfo);
- }
- else
- {
- // Delete unnecesarry device
- bRejectDevice = true;
- }
- break;
- case eAllDevices:
- default:
- m_DeviceInfoVec.push_back(pDevInfo);
- break;
- }
-
- if(bRejectDevice)
- {
- syslog (LOG_NOTICE, "%s rejected, In Channels = %d, Out Channels = %d\n",
- pDevInfo->m_DeviceName.c_str(), pDevInfo->m_MaxInputChannels, pDevInfo->m_MaxOutputChannels);
- // In case of Input and Output both channels being Zero, we will release memory; since we created CoreAudioDevice but we are Not adding it in list.
- delete pDevInfo;
- }
- }
- }
-
-
- //If no devices were found, that's not a good thing!
- if (m_DeviceInfoVec.empty())
- {
- DEBUG_MSG ("No matching CoreAudio devices were found\n");
- }
- }
- catch (...)
- {
- if (WUNoError(retVal))
- retVal = eCoreAudioFailed;
- }
-
- delete[] deviceIDs;
- closelog();
-
- return retVal;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::updateDeviceListImpl()
-{
- wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
- WTErr err = generateDeviceListImpl();
-
- if (eNoErr != err)
- {
- std::cout << "API::PortAudioDeviceManager::updateDeviceListImpl: Device list update error: "<< err << std::endl;
- }
-
- if (m_CurrentDevice)
- {
- // if we have device initialized we should find out if this device is still connected
- DeviceInfo devInfo;
- WTErr deviceLookUpErr = GetDeviceInfoByName(m_CurrentDevice->DeviceName(), devInfo );
-
- if (eNoErr != deviceLookUpErr)
- {
- NotifyClient (WCMRAudioDeviceManagerClient::IODeviceDisconnected);
- return err;
- }
-
- WCMRCoreAudioDevice* current_device = dynamic_cast<WCMRCoreAudioDevice*>(m_CurrentDevice);
-
- if ( current_device &&
- (current_device->DeviceID() != devInfo.m_DeviceId ) )
- {
- NotifyClient (WCMRAudioDeviceManagerClient::RequestReset);
- return err;
- }
- }
-
- NotifyClient (WCMRAudioDeviceManagerClient::DeviceListChanged);
-
- return err;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- sampleRates.clear();
-
- //first check if the request has been made for None device
- if (deviceName == m_NoneDevice->DeviceName() )
- {
- sampleRates = m_NoneDevice->SamplingRates();
- return retVal;
- }
-
- if (m_CurrentDevice && m_CurrentDevice->DeviceName () == deviceName) {
- sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() );
- return retVal;
- }
-
- DeviceInfo devInfo;
- retVal = GetDeviceInfoByName(deviceName, devInfo);
-
- //! 1. Get sample rate property size.
- err = AudioDeviceGetPropertyInfo(devInfo.m_DeviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, NULL);
-
- if (err == kAudioHardwareNoError)
- {
- //! 2. Get property: cannels output.
-
- // Allocate size accrding to the number of audio values
- int numRates = propSize / sizeof(AudioValueRange);
- AudioValueRange* supportedRates = new AudioValueRange[numRates];
-
- // Get sampling rates from Audio device
- err = AudioDeviceGetProperty(devInfo.m_DeviceId, 0, 0, kAudioDevicePropertyAvailableNominalSampleRates, &propSize, supportedRates);
-
- if (err == kAudioHardwareNoError)
- {
- //! 3. Update sample rates
-
- // now iterate through our standard SRs
- for(int ourSR=0; gAllSampleRates[ourSR] > 0; ourSR++)
- {
- //check to see if our SR is in the supported rates...
- for (int deviceSR = 0; deviceSR < numRates; deviceSR++)
- {
- if ((supportedRates[deviceSR].mMinimum <= gAllSampleRates[ourSR]) &&
- (supportedRates[deviceSR].mMaximum >= gAllSampleRates[ourSR]))
- {
- sampleRates.push_back ((int)gAllSampleRates[ourSR]);
- break;
- }
- }
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Sample rates. Device Name: " << m_DeviceName.c_str());
- }
-
- delete [] supportedRates;
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device Sample rates property size. Device Name: " << m_DeviceName.c_str());
- }
-
- devInfo.m_AvailableSampleRates.assign(sampleRates.begin(), sampleRates.end() );
-
- return retVal;
-}
-
-
-WTErr WCMRCoreAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const
-{
- AUTO_FUNC_DEBUG;
-
- WTErr retVal = eNoErr;
- OSStatus err = kAudioHardwareNoError;
- UInt32 propSize = 0;
-
- bufferSizes.clear();
-
- //first check if the request has been made for None device
- if (deviceName == m_NoneDevice->DeviceName() )
- {
- bufferSizes = m_NoneDevice->BufferSizes();
- return retVal;
- }
-
- if (m_CurrentDevice && m_CurrentDevice->DeviceName () == deviceName) {
- bufferSizes.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() );
- return retVal;
- }
-
- DeviceInfo devInfo;
- retVal = GetDeviceInfoByName(deviceName, devInfo);
-
- if (eNoErr == retVal)
- {
- // 1. Get buffer size range
- AudioValueRange bufferSizesRange;
- propSize = sizeof (AudioValueRange);
- err = AudioDeviceGetProperty (devInfo.m_DeviceId, 0, 0, kAudioDevicePropertyBufferFrameSizeRange, &propSize, &bufferSizesRange);
- if(err == kAudioHardwareNoError)
- {
- // 2. Run on all ranges and add them to the list
- for(int bsize=0; gAllBufferSizes[bsize] > 0; bsize++)
- {
- if ((bufferSizesRange.mMinimum <= gAllBufferSizes[bsize]) && (bufferSizesRange.mMaximum >= gAllBufferSizes[bsize]))
- {
- bufferSizes.push_back (gAllBufferSizes[bsize]);
- }
- }
-
- //if we didn't get a single hit, let's simply add the min. and the max...
- if (bufferSizes.empty())
- {
- bufferSizes.push_back ((int)bufferSizesRange.mMinimum);
- bufferSizes.push_back ((int)bufferSizesRange.mMaximum);
- }
- }
- else
- {
- retVal = eCoreAudioFailed;
- DEBUG_MSG("Failed to get device buffer sizes range. Device Name: " << m_DeviceName.c_str());
- }
- }
- else
- {
- retVal = eRMResNotFound;
- std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl;
- }
-
-
- return retVal;
-}
-
-
-OSStatus WCMRCoreAudioDeviceManager::HardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData)
-{
- switch (inPropertyID)
- {
- case kAudioHardwarePropertyDevices:
- {
- WCMRCoreAudioDeviceManager* pManager = (WCMRCoreAudioDeviceManager*)inClientData;
- if (pManager)
- pManager->updateDeviceListImpl();
- }
- break;
-
- default:
- break;
- }
-
- return 0;
-}
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h
deleted file mode 100644
index 0d92493b51..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRCoreAudioDeviceManager.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- Copyright (C) 2014 Waves Audio Ltd.
-
- 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.
-
-*/
-
-//----------------------------------------------------------------------------------
-//
-//
-//! \file WCMRCoreAudioDeviceManager.h
-//!
-//! WCMRCoreAudioDeviceManager and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#ifndef __WCMRCoreAudioDeviceManager_h_
- #define __WCMRCoreAudioDeviceManager_h_
-
-#include "WCMRAudioDeviceManager.h"
-#include "WCMRNativeAudio.h"
-#include "Threads/WCThreadSafe.h"
-
-#include <AudioUnit/AudioUnit.h>
-#include <AudioToolbox/AudioToolbox.h>
-
-#include <mach/mach.h>
-
-#include <CoreAudio/CoreAudio.h>
-
-//forward decl.
-class WCMRCoreAudioDeviceManager;
-
-#define WV_USE_TONE_GEN 0 ///! Set this to 1 to use a tone generator for input. See description at SetupToneGenerator for details.
-
-// This enum is for choosing filter for audio devices scan
-typedef enum eCABS_Method
-{
- eCABS_Simple = 0,
- eCABS_DestructiveCache,
- eCABS_CacheOnDeviceSet,
- eCABS_MethodNum // Must be last
-} eCABS_Method;
-
-//! Manages a port audio device, providing information
-//! about the device, and managing audio callbacks.
-class WCMRCoreAudioDevice : public WCMRNativeAudioDevice
-{
-public:
-
- WCMRCoreAudioDevice (WCMRCoreAudioDeviceManager *pManager, AudioDeviceID deviceID, bool useMultithreading = true, bool bNocopy = false);///<Constructor
- virtual ~WCMRCoreAudioDevice ();///<Destructor
-
- virtual const std::string& DeviceName() const;///<Name?
- virtual const std::vector<std::string>& InputChannels();///<Current Input Channel List? - note that this may change with change in sampling rate.
- virtual const std::vector<std::string>& OutputChannels();///<Current Output Channel List? - note that this may change with change in sampling rate.
-
-
- virtual const std::vector<int>& SamplingRates();///<Supported Sampling Rate List?
- virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
- virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!
-
- virtual const std::vector<int>& BufferSizes();///<Supported Buffer Size List? - note that this may change with change in sampling rate.
- virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
- virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
-
- virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
-
- virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
- virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
-
- virtual WTErr DoIdle();///<Do Idle Processing
-
- virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
- virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
-
- virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
-
- virtual int AudioCallback (float *pOutputBuffer, unsigned long framesPerBuffer, int64_t inSampleTime, uint64_t inCycleStartTime);
-
- AudioDeviceID DeviceID () {return m_DeviceID;}
-
- virtual uint32_t GetLatency (bool isInput); ///< Get latency.
- virtual OSStatus GetStreamLatency(AudioDeviceID deviceID, bool isInput, std::vector<int>& latencies);
-
-
-protected:
-
- AudioDeviceID m_DeviceID; ///< The CoreAudio device id
- bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
- float *m_pInputData; ///< This is what came in with the most recent callback.
- int64_t m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
- int64_t m_SampleCountAtLastIdle; ///< What was the sample count last time we checked...
- int m_StalledSampleCounter; ///< The number of idle calls with same sample count detected
- int m_ChangeCheckCounter; ///< The number of idle calls passed since we checked the buffer size change.
-
- wvNS::wvThread::timestamp m_LastCPULog; ///< The time when the last CPU details log was sent as a notification.
-// unsigned int m_IOCyclesTimesTaken[MAX_IOCYCLE_TIMES]; ///< This stores the times taken by each IOCycle, in host-time units.
-// int m_CurrentIOCycle; ///< The location in m_IOCyclesTymesTaken array, where the next cycle's value will go.
-// int m_CyclesToAccumulate; ///< The number of cycles to accumulate the values for - maximum for last one second.
-// unsigned int m_CyclePeriod; ///< The number of host time units for a cycle period - determined by buffer size and sampling rate
-
-
- AudioUnit m_AUHALAudioUnit;///< The AUHAL AudioUnit
-
- int m_BufferSizeChangeRequested;
- int m_BufferSizeChangeReported;
- int m_ResetRequested;
- int m_ResetReported;
- int m_ResyncRequested;
- int m_ResyncReported;
- int m_SRChangeRequested;
- int m_SRChangeReported;
-
- int m_DropsDetected; ///< Number of times audio drops have been detected so far.
- int m_DropsReported; ///< Number of times audio drops have been reported so far to the client.
- bool m_IgnoreThisDrop; ///< Allows disregarding the first drop
-
- thread_t m_IOProcThreadPort; ///< Thread handle to calculate CPU consumption.
- int m_CPUCount; ///< Number of processors/core to normalize cpu consumption calculation.
-
-#if WV_USE_TONE_GEN
- //The Tone Generator...
- float_t *m_pToneData;
- uint32_t m_ToneDataSamples;
- uint32_t m_NextSampleToUse;
-#endif //WV_USE_TONE_GEN
-
- WTErr UpdateDeviceInfo ();
- WTErr UpdateDeviceId ();
- WTErr UpdateDeviceName();
- WTErr UpdateDeviceInputs();
- WTErr UpdateDeviceOutputs();
- WTErr UpdateDeviceSampleRates();
- WTErr UpdateDeviceBufferSizes();
- WTErr SetWorkingBufferSize(int newSize);
- OSStatus SetBufferSizesByIO(int newSize);
- WTErr SetAndCheckCurrentSamplingRate (int newRate);
-
- WTErr EnableAudioUnitIO();
- WTErr virtual EnableListeners();
- WTErr virtual DisableListeners();
- WTErr SetupAUHAL();
- WTErr TearDownAUHAL();
-
-#if WV_USE_TONE_GEN
- void SetupToneGenerator ();
-#endif //WV_USE_TONE_GEN
-
- static OSStatus StaticAudioIOProc(void *inRefCon, AudioUnitRenderActionFlags * ioActionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList *ioData);
- OSStatus AudioIOProc(AudioUnitRenderActionFlags * ioActionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList *ioData);
-
- static OSStatus StaticPropertyChangeProc (AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput,
- AudioDevicePropertyID inPropertyID, void *inClientData);
- void PropertyChangeProc (AudioDevicePropertyID inPropertyID);
-
-private:
-
-};
-
-
-//! WCMRCoreAudioDeviceManager
-/*! The CoreAudio Device Manager class */
-class WCMRCoreAudioDeviceManager : public WCMRAudioDeviceManager
-{
-public:
-
- WCMRCoreAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
- bool useMultithreading = true, bool bNocopy = false); ///< constructor
- virtual ~WCMRCoreAudioDeviceManager(void); ///< Destructor
-
-protected:
- static OSStatus HardwarePropertyChangeCallback (AudioHardwarePropertyID inPropertyID, void* inClientData);
-
- virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName);
- virtual void destroyCurrentDeviceImpl();
- virtual WTErr generateDeviceListImpl();
- virtual WTErr updateDeviceListImpl();
- virtual WTErr getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const;
- virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& bufferSizes) const;
-
- bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
- bool m_bNoCopyAudioBuffer;
-
-private:
- // helper functions for this class only
- WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates);
- WTErr getDeviceMaxInputChannels(DeviceID deviceId, unsigned int& inputChannels);
- WTErr getDeviceMaxOutputChannels(DeviceID deviceId, unsigned int& outputChannels);
-
- WCMRAudioDevice* m_NoneDevice;
-};
-
-#endif //#ifndef __WCMRCoreAudioDeviceManager_h_
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp
deleted file mode 100644
index bf5e4fbb90..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-//----------------------------------------------------------------------------------
-//
-// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
-//
-//! \file WCMRNativeAudio.cpp
-//!
-//! WCMRNativeAudioConnection and related class defienitions
-//!
-//---------------------------------------------------------------------------------*/
-#if defined(__APPLE__)
-#include <CoreAudio/CoreAudio.h>
-#endif
-
-#include "WCMRNativeAudio.h"
-#include "MiscUtils/pthread_utils.h"
-#include "MiscUtils/safe_delete.h"
-#include <iostream>
-#include <sstream>
-#include <boost/assign/list_of.hpp>
-
-#define NONE_DEVICE_NAME "None"
-#define NONE_DEVICE_INPUT_NAMES "Input "
-#define NONE_DEVICE_OUTPUT_NAMES "Output "
-
-//**********************************************************************************************
-// WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice
-//
-//! Constructor for the dummy "None" device. This constructor simply adds supported SRs,
-//! buffer sizes, and channels, so that it may look like a real native device to
-//! the applications.
-//!
-//! \param pManager : The managing device manager - simply passed on to the base class.
-//!
-//!
-//**********************************************************************************************
-WCMRNativeAudioNoneDevice::WCMRNativeAudioNoneDevice (WCMRAudioDeviceManager *pManager)
- : WCMRNativeAudioDevice (pManager, false /*useMultiThreading*/)
-#ifndef PTW32_VERSION
- , m_SilenceThread(0)
-#endif
-#if defined (PLATFORM_WINDOWS)
- , _waitableTimerForUsleep (CreateWaitableTimer(NULL, TRUE, NULL))
-#endif
-{
- mark_pthread_inactive (m_SilenceThread);
-
- m_DeviceName = NONE_DEVICE_NAME;
-
- m_SamplingRates = boost::assign::list_of (m_CurrentSamplingRate=44100)(48000)(88200)(96000)(176400)(192000);
-
- m_BufferSizes = boost::assign::list_of (32)(64)(128)(m_CurrentBufferSize=256)(512)(1024);
-
- for (int channel = 0; channel < __m_NumInputChannels; channel++)
- {
- std::stringstream name;
- name << NONE_DEVICE_INPUT_NAMES;
- name << (channel + 1);
- m_InputChannels.push_back(name.str());
- }
-
- for (int channel = 0; channel < __m_NumOutputChannels; channel++)
- {
- std::stringstream name;
- name << NONE_DEVICE_INPUT_NAMES;
- name << (channel + 1);
- m_OutputChannels.push_back(name.str());
- }
- _m_inputBuffer = new float[__m_NumInputChannels * m_BufferSizes.back()];
- _m_outputBuffer = new float[__m_NumOutputChannels * m_BufferSizes.back()];
- m_CurrentBufferSize = m_BufferSizes.back();
-}
-
-
-WCMRNativeAudioNoneDevice::~WCMRNativeAudioNoneDevice ()
-{
-#if defined (PLATFORM_WINDOWS)
- if(_waitableTimerForUsleep) {
- CloseHandle(_waitableTimerForUsleep);
- }
-#endif
-}
-
-WTErr WCMRNativeAudioNoneDevice::SetActive (bool newState)
-{
- //This will most likely be overridden, the base class simply
- //changes the member.
- if (Active() == newState)
- {
- return (eNoErr);
- }
-
- if (Active() && Streaming())
- {
- SetStreaming(false);
- }
- return WCMRAudioDevice::SetActive(newState);
-}
-
-WTErr WCMRNativeAudioNoneDevice::SetCurrentBufferSize (int newSize)
-{
-
- //changes the status.
- int oldSize = CurrentBufferSize();
- bool oldActive = Active();
-
- //same size, nothing to do.
- if (oldSize == newSize)
- return eNoErr;
-
- //see if this is one of our supported rates...
- std::vector<int>::iterator 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
- return eCommandLineParameter;
- }
-
- if (Streaming())
- {
- //Can't change, perhaps use an "in use" type of error
- return eGenericErr;
- }
-
-
- return WCMRAudioDevice::SetCurrentBufferSize(newSize);
-}
-
-
-WTErr WCMRNativeAudioNoneDevice::UpdateDeviceInfo ()
-{
- return eNoErr;
-}
-
-
-WTErr WCMRNativeAudioNoneDevice::SetStreaming (bool newState)
-{
- if (Streaming() == newState)
- {
- return (eNoErr);
- }
-
- WCMRAudioDevice::SetStreaming(newState);
-
- if (Streaming())
- {
- if (is_pthread_active (m_SilenceThread))
- std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the inactive NONE-DEVICE was streaming!" << std::endl;
-
- pthread_attr_t attributes;
- size_t stack_size = 100000;
-#ifdef __APPLE__
- stack_size = (((stack_size - 1) / PTHREAD_STACK_MIN) + 1) * PTHREAD_STACK_MIN;
-#endif
- if (pthread_attr_init (&attributes)) {
- std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_attr_init () failed!" << std::endl;
- return eGenericErr;
- }
-
- if (pthread_attr_setstacksize (&attributes, stack_size)) {
- std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_attr_setstacksize () failed!" << std::endl;
- return eGenericErr;
- }
-
- if (pthread_create (&m_SilenceThread, &attributes, __SilenceThread, this)) {
- mark_pthread_inactive (m_SilenceThread);
- std::cerr << "WCMRNativeAudioNoneDevice::SetStreaming (): pthread_create () failed!" << std::endl;
- return eGenericErr;
- }
- }
- else
- {
- if (!is_pthread_active (m_SilenceThread))
- {
- std::cerr << "\t\t\t\t\t !!!!!!!!!!!!!!! Warning: the active NONE-DEVICE was NOT streaming!" << std::endl;
- }
-
- while (is_pthread_active (m_SilenceThread))
- {
- _usleep(1); //now wait for ended thread;
- }
- }
-
- return eNoErr;
-}
-
-void WCMRNativeAudioNoneDevice::_SilenceThread()
-{
-#if defined(PLATFORM_WINDOWS)
- float* theInpBuffers[__m_NumInputChannels];
- for(int i = 0; i < __m_NumInputChannels; ++i)
- {
- theInpBuffers[i] = _m_inputBuffer + m_BufferSizes.back() * i;
- }
-#else
- float* theInpBuffers = _m_inputBuffer;
-#endif
-
- const size_t buffer_size = CurrentBufferSize();
- const uint64_t cyclePeriodNanos = (1000000000.0 * buffer_size) / CurrentSamplingRate();
-
- struct WCMRAudioDeviceManagerClient::AudioCallbackData audioCallbackData =
- {
- (const float*)theInpBuffers,
- _m_outputBuffer,
- buffer_size,
- 0,
- 0
- };
-
- audioCallbackData.acdCycleStartTimeNanos =__get_time_nanos();
-
- // VERY ROUGH IMPLEMENTATION:
- while(Streaming()) {
-
- uint64_t cycleEndTimeNanos = audioCallbackData.acdCycleStartTimeNanos + cyclePeriodNanos;
-
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData);
-
- audioCallbackData.acdSampleTime += buffer_size;
-
- int64_t timeToSleepUsecs = ((int64_t)cycleEndTimeNanos - (int64_t)__get_time_nanos())/1000;
-
- if (timeToSleepUsecs > 0) {
- _usleep (timeToSleepUsecs);
- }
- audioCallbackData.acdCycleStartTimeNanos = cycleEndTimeNanos+1;
- }
- mark_pthread_inactive (m_SilenceThread);
-}
-
-void* WCMRNativeAudioNoneDevice::__SilenceThread(void *This)
-{
- ((WCMRNativeAudioNoneDevice*)This)->_SilenceThread();
- return 0;
-}
-
-#if defined(PLATFORM_WINDOWS)
-void WCMRNativeAudioNoneDevice::_usleep(uint64_t duration_usec)
-{
- LARGE_INTEGER ft;
-
- ft.QuadPart = -(10*duration_usec); // Convert to 100 nanosecond interval, negative value indicates relative time
-
- SetWaitableTimer(_waitableTimerForUsleep, &ft, 0, NULL, NULL, 0);
- WaitForSingleObject(_waitableTimerForUsleep, INFINITE);
-}
-#endif
-
-uint64_t
-WCMRNativeAudioNoneDevice::__get_time_nanos ()
-{
-#ifdef __APPLE__
- // here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
- // the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
- // audio device transport timeß.
- return AudioConvertHostTimeToNanos (AudioGetCurrentHostTime ());
-
-#elif PLATFORM_WINDOWS
-
- LARGE_INTEGER Frequency, Count ;
-
- QueryPerformanceFrequency (&Frequency) ;
- QueryPerformanceCounter (&Count);
- return uint64_t ((Count.QuadPart * 1000000000.0 / Frequency.QuadPart));
-#endif
-}
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h
deleted file mode 100644
index 238d36fd74..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRNativeAudio.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- Copyright (C) 2014 Waves Audio Ltd.
-
- 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.
-
-*/
-
-//----------------------------------------------------------------------------------
-//
-//
-//! \file WCMRNativeAudio.h
-//!
-//! WCMRNativeAudio and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#ifndef __WCMRNativeAudio_h_
- #define __WCMRNativeAudio_h_
-
-#if defined(PLATFORM_WINDOWS)
-#include "windows.h"
-#endif
-#include "pthread.h"
-#include "WCRefManager.h"
-#include "WCMRAudioDeviceManager.h"
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9
-#include <unistd.h>
-#endif
-
-class WCMRNativeAudioDevice; //forward
-
-
-
-class WCMRNativeAudioDevice : public WCMRAudioDevice
-{
-public:
-
- WCMRNativeAudioDevice (WCMRAudioDeviceManager *pManager, bool useMultithreading = true, bool bNoCopy = false) :
- WCMRAudioDevice (pManager)
- , m_UseMultithreading (useMultithreading)
- , m_bNoCopyAudioBuffer(bNoCopy)
- {}
- virtual ~WCMRNativeAudioDevice () {}
-
-protected:
- bool m_UseMultithreading;
- bool m_bNoCopyAudioBuffer; ///< This flag determines whether the audio callback performs a copy of audio, or the source/sink perform the copy. It should be true to let source/sink do the copies.
-
-};
-
-
-//! A dummy device to allow apps to choose "None" in case no real device connection is required.
-class WCMRNativeAudioNoneDevice : public WCMRNativeAudioDevice
-{
-public:
- WCMRNativeAudioNoneDevice (WCMRAudioDeviceManager *pManager);
- virtual ~WCMRNativeAudioNoneDevice ();
- virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
- virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
- virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
- virtual WTErr UpdateDeviceInfo ();
-
-private:
-
- static void* __SilenceThread(void *This);
- void _SilenceThread();
-#if defined(PLATFORM_WINDOWS)
- void _usleep(uint64_t usec);
-#else
- inline void _usleep(uint64_t usec) { ::usleep(usec); }
-#endif
- static const size_t __m_NumInputChannels = 0;
- static const size_t __m_NumOutputChannels = 0;
- pthread_t m_SilenceThread;
- float *_m_inputBuffer;
- float *_m_outputBuffer;
- static uint64_t __get_time_nanos ();
-#if defined (PLATFORM_WINDOWS)
- HANDLE _waitableTimerForUsleep;
-#endif
-};
-
-
-#endif //#ifndef __WCMRNativeAudio_h_
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp
deleted file mode 100644
index 8e63887d37..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp
+++ /dev/null
@@ -1,1782 +0,0 @@
-//----------------------------------------------------------------------------------
-//
-// Copyright (c) 2008 Waves Audio Ltd. All rights reserved.
-//
-//! \file WCMRPortAudioDeviceManager.cpp
-//!
-//! WCMRPortAudioDeviceManager and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#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 "pa_asio.h"
-#include "asio.h"
-
-#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, 176400.0, 192000.0, -1 /* negative terminated list */
- };
-
-
-
-///< Default Supported Buffer Sizes.
-static const int gAllBufferSizes[] =
- {
- 32, 64, 96, 128, 192, 256, 512, 1024, 2048
- };
-
-
-///< The default SR.
-static const int DEFAULT_SR = 44100;
-///< The default buffer size.
-static const int DEFAULT_BUFFERSIZE = 128;
-
-static const int NONE_DEVICE_ID = -1;
-
-///< Number of stalls to wait before notifying user...
-static const int NUM_STALLS_FOR_NOTIFICATION = 100; // 100 corresponds to 100 x 42 ms idle timer - about 4 seconds.
-static const int CHANGE_CHECK_COUNTER_PERIOD = 100; // 120 corresponds to 120 x 42 ms idle timer - about 4 seconds.
-
-#define HUNDRED_NANO_TO_MILLI_CONSTANT 10000
-#define CONSUMPTION_CALCULATION_INTERVAL 500 // Milli Seconds
-
-
-// This wrapper is used to adapt device DoIdle method as entry point for MS thread
-DWORD WINAPI WCMRPortAudioDevice::__DoIdle__(LPVOID lpThreadParameter)
-{
- WCMRPortAudioDevice* pDevice = (WCMRPortAudioDevice*)lpThreadParameter;
- pDevice->DoIdle();
- return 0;
-}
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::WCMRPortAudioDevice
-//
-//! Constructor for the audio device. Opens the PA device
-//! and gets information about the device.
-//! Starts the thread which will process requests to this device
-//! such as determining supported sampling rates, buffer sizes, and channel counts.
-//!
-//! \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)
- , m_SampleCounter(0)
- , m_BufferSizeChangeRequested (0)
- , m_BufferSizeChangeReported (0)
- , m_ResetRequested (0)
- , m_ResetReported (0)
- , m_ResyncRequested (0)
- , m_ResyncReported (0)
- , m_DropsDetected(0)
- , m_DropsReported(0)
- , m_IgnoreThisDrop(true)
- , m_hDeviceProcessingThread(NULL)
- , m_DeviceProcessingThreadID(0)
- , m_hUpdateDeviceInfoRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hUpdateDeviceInfoDone(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hActivateRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hActivationDone(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hDeActivateRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hDeActivationDone(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hStartStreamingRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hStartStreamingDone(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hStopStreamingRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hStopStreamingDone(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hResetRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hResetDone(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hResetFromDevRequestedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hBufferSizeChangedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hSampleRateChangedEvent(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hExitIdleThread(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_hDeviceInitialized(CreateEvent(NULL, FALSE, FALSE, NULL))
- , m_lastErr(eNoErr)
-{
- AUTO_FUNC_DEBUG;
-
- //Set initial device info...
- m_DeviceID = deviceID;
- m_PortAudioStream = NULL;
- m_CurrentSamplingRate = DEFAULT_SR;
- m_CurrentBufferSize = DEFAULT_BUFFERSIZE;
- m_StopRequested = true;
- m_pInputData = NULL;
-
- //initialize device processing thread
- //the divice become alive and now is able to process requests
- m_hDeviceProcessingThread = CreateThread( NULL, 0, __DoIdle__, (LPVOID)this, 0, &m_DeviceProcessingThreadID );
-
- if (!m_hDeviceProcessingThread)
- {
- DEBUG_MSG("API::Device " << m_DeviceName << " cannot create processing thread");
- throw eGenericErr;
- }
-
- WaitForSingleObject(m_hDeviceInitialized, INFINITE);
-
- if (ConnectionStatus() == DeviceErrors)
- {
- throw m_lastErr;
- }
-}
-
-
-void WCMRPortAudioDevice::initDevice()
-{
- // Initialize COM for this thread
- std::cout << "API::Device " << m_DeviceID << " initializing COM" << std::endl;
-
- if (S_OK == CoInitialize(NULL) )
- {
- // Initialize PA
- Pa_Initialize();
-
- updateDeviceInfo();
-
- //should use a valid current SR...
- if (m_SamplingRates.size())
- {
- //see if the current sr is present in the sr list, if not, use the first one!
- std::vector<int>::iterator intIter = find(m_SamplingRates.begin(), m_SamplingRates.end(), m_CurrentSamplingRate);
- if (intIter == m_SamplingRates.end())
- {
- //not found... use the first one
- m_CurrentSamplingRate = m_SamplingRates[0];
- }
- }
- else
- std::cout << "API::Device " << m_DeviceName << " Device does not support any sample rate of ours" << std::endl;
-
- //should use a valid current buffer size
- if (m_BufferSizes.size())
- {
- //see if the current sr is present in the buffersize list, if not, use the first one!
- std::vector<int>::iterator intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), m_CurrentBufferSize);
- if (intIter == m_BufferSizes.end())
- {
- //not found... use the first one
- m_CurrentBufferSize = m_BufferSizes[0];
- }
- }
-
- //build our input/output level lists
- for (unsigned int currentChannel = 0; currentChannel < m_InputChannels.size(); currentChannel++)
- {
- m_InputLevels.push_back (0.0);
- }
-
- //build our input/output level lists
- for (unsigned int currentChannel = 0; currentChannel < m_OutputChannels.size(); currentChannel++)
- {
- m_OutputLevels.push_back (0.0);
- }
-
- std::cout << "API::Device " << m_DeviceName << " Device has been initialized" << std::endl;
- m_ConnectionStatus = DeviceDisconnected;
- m_lastErr = eNoErr;
- }
- else
- {
- /*Replace with debug trace*/std::cout << "API::Device " << m_DeviceName << " cannot initialize COM" << std::endl;
- DEBUG_MSG("Device " << m_DeviceName << " cannot initialize COM");
- m_ConnectionStatus = DeviceErrors;
- m_lastErr = eSomeThingNotInitailzed;
- SetEvent(m_hExitIdleThread);
- }
-
- SetEvent(m_hDeviceInitialized);
-}
-
-void WCMRPortAudioDevice::terminateDevice()
-{
- std::cout << "API::Device " << m_DeviceName << " Terminating DEVICE" << std::endl;
-
- //If device is streaming, need to stop it!
- if (Streaming())
- {
- stopStreaming();
- }
-
- //If device is active (meaning stream is open) we need to close it.
- if (Active())
- {
- deactivateDevice();
- }
-
- std::cout << "API::Device " << m_DeviceName << " Terminating PA" << std::endl;
-
- //Deinitialize PA
- Pa_Terminate();
-}
-
-
-//**********************************************************************************************
-// 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 ()
-{
- AUTO_FUNC_DEBUG;
-
- std::cout << "API::Destroying Device Instance: " << DeviceName() << std::endl;
- try
- {
- //Stop deviceprocessing thread
- SignalObjectAndWait(m_hExitIdleThread, m_hDeviceProcessingThread, INFINITE, false);
-
- std::cout << "API::Device " << m_DeviceName << " Processing Thread is stopped" << std::endl;
-
- CloseHandle(m_hDeviceProcessingThread);
-
- //Now it's safe to free all event handlers
- CloseHandle(m_hUpdateDeviceInfoRequestedEvent);
- CloseHandle(m_hUpdateDeviceInfoDone);
- CloseHandle(m_hActivateRequestedEvent);
- CloseHandle(m_hActivationDone);
- CloseHandle(m_hDeActivateRequestedEvent);
- CloseHandle(m_hDeActivationDone);
- CloseHandle(m_hStartStreamingRequestedEvent);
- CloseHandle(m_hStartStreamingDone);
- CloseHandle(m_hStopStreamingRequestedEvent);
- CloseHandle(m_hStopStreamingDone);
- CloseHandle(m_hResetRequestedEvent);
- CloseHandle(m_hResetDone);
- CloseHandle(m_hResetFromDevRequestedEvent);
- CloseHandle(m_hBufferSizeChangedEvent);
- CloseHandle(m_hSampleRateChangedEvent);
- CloseHandle(m_hExitIdleThread);
- CloseHandle(m_hDeviceInitialized);
- }
- catch (...)
- {
- //destructors should absorb exceptions, no harm in logging though!!
- DEBUG_MSG ("Exception during destructor");
- }
-}
-
-
-WTErr WCMRPortAudioDevice::UpdateDeviceInfo ()
-{
- std::cout << "API::Device (ID:)" << m_DeviceID << " Updating device info" << std::endl;
-
- SignalObjectAndWait(m_hUpdateDeviceInfoRequestedEvent, m_hUpdateDeviceInfoDone, INFINITE, false);
-
- return eNoErr;
-}
-
-
-//**********************************************************************************************
-// 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*/)
-{
- AUTO_FUNC_DEBUG;
-
- //get device info
- const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
-
- //update name.
- m_DeviceName = pDeviceInfo->name;
-
- //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 = pDeviceInfo->maxInputChannels;
- inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
- inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
- inputParameters.hostApiSpecificStreamInfo = 0;
-
- if (inputParameters.channelCount)
- pInS = &inputParameters;
-
- outputParameters.device = m_DeviceID;
- outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
- outputParameters.sampleFormat = paFloat32;
- outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
- outputParameters.hostApiSpecificStreamInfo = 0;
-
- if (outputParameters.channelCount)
- pOutS = &outputParameters;
-
- ////////////////////////////////////////////////////////////////////////////////////
- //update list of supported SRs...
- m_SamplingRates.clear();
-
- // now iterate through our standard SRs and check if they are supported by device
- // store them for this device
- for(int sr=0; gAllSampleRates[sr] > 0; sr++)
- {
- PaError err = Pa_IsFormatSupported(pInS, pOutS, gAllSampleRates[sr]);
- if( err == paFormatIsSupported)
- {
- m_SamplingRates.push_back ((int)gAllSampleRates[sr]);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////////
- //update buffer sizes
- m_BufferSizes.clear();
- bool useDefaultBuffers = true;
-
- // 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 (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;
- }
-
- if (useDefaultBuffers)
- {
- std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl;
- for(int bsize=0; bsize < (sizeof(gAllBufferSizes)/sizeof(gAllBufferSizes[0])); bsize++)
- m_BufferSizes.push_back (gAllBufferSizes[bsize]);
- }
-
- /////////////////////////////////////////////////////////////////////////////////////////
- //update channels info
- {
- int maxInputChannels = pDeviceInfo->maxInputChannels;
- int maxOutputChannels = pDeviceInfo->maxOutputChannels;
-
- //Update input channels
- 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;
-
- 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());
- }
-
-
- //Update output channels
- 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;
-
- 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());
- }
- }
-
- std::cout << "API::Device" << m_DeviceName << " Device info update has been finished" << std::endl;
-
- if (callerIsWaiting)
- SetEvent(m_hUpdateDeviceInfoDone);
-}
-
-
-PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
-{
- PaError paErr = paNoError;
-
- //get device info
- const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
-
- //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 = pDeviceInfo->maxInputChannels;
- inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
- inputParameters.suggestedLatency = 0;
- inputParameters.hostApiSpecificStreamInfo = 0;
-
- if (inputParameters.channelCount)
- pInS = &inputParameters;
-
- outputParameters.device = m_DeviceID;
- outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
- outputParameters.sampleFormat = paFloat32;
- outputParameters.suggestedLatency = 0;
- outputParameters.hostApiSpecificStreamInfo = 0;
-
- if (outputParameters.channelCount)
- pOutS = &outputParameters;
-
- PaStream *portAudioStream = NULL;
-
- //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
- paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, sampleRate, bufferSize, paDitherOff, NULL, NULL);
-
- if (portAudioStream)
- {
- // close test stream
- Pa_CloseStream (portAudioStream);
- portAudioStream = NULL;
- }
-
- return paErr;
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::CurrentSamplingRate
-//
-//! 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 ()
-{
- AUTO_FUNC_DEBUG;
- //ToDo: Perhaps for ASIO devices that are active, we should retrive the SR from the device...
-
- return (m_CurrentSamplingRate);
-}
-
-
-WTErr WCMRPortAudioDevice::SetActive (bool newState)
-{
- if (newState == true)
- {
- std::cout << "API::Device " << m_DeviceName << " Activation requested" << std::endl;
- SignalObjectAndWait(m_hActivateRequestedEvent, m_hActivationDone, INFINITE, false);
- }
- else
- {
- std::cout << "API::Device " << m_DeviceName << " Deactivation requested" << std::endl;
- SignalObjectAndWait(m_hDeActivateRequestedEvent, m_hDeActivationDone, INFINITE, false);
- }
-
- if (newState == Active() )
- return eNoErr;
- else
- return eGenericErr;
-}
-
-
-WTErr WCMRPortAudioDevice::SetStreaming (bool newState)
-{
- if (newState == true)
- {
- std::cout << "API::Device " << m_DeviceName << " Stream start requested" << std::endl;
- SignalObjectAndWait(m_hStartStreamingRequestedEvent, m_hStartStreamingDone, INFINITE, false);
- }
- else
- {
- std::cout << "API::Device " << m_DeviceName << " Stream stop requested" << std::endl;
- SignalObjectAndWait(m_hStopStreamingRequestedEvent, m_hStopStreamingDone, INFINITE, false);
- }
-
- if (newState == Streaming() )
- return eNoErr;
- else
- return eGenericErr;
-}
-
-
-WTErr WCMRPortAudioDevice::ResetDevice()
-{
- std::cout << "API::Device: " << m_DeviceName << " Reseting device" << std::endl;
-
- SignalObjectAndWait(m_hResetRequestedEvent, m_hResetDone, INFINITE, false);
-
- if (ConnectionStatus() == DeviceErrors)
- {
- return m_lastErr;
- }
-
- return eNoErr;
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::SetCurrentSamplingRate
-//
-//! 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)
-{
- AUTO_FUNC_DEBUG;
- std::vector<int>::iterator intIter;
- WTErr retVal = eNoErr;
-
- //changes the status.
- int oldRate = CurrentSamplingRate();
- bool oldActive = Active();
-
- //no change, nothing to do
- if (oldRate == newRate)
- return (retVal);
-
- //see if this is one of our supported rates...
- intIter = find(m_SamplingRates.begin(), m_SamplingRates.end(), newRate);
-
- if (intIter == m_SamplingRates.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);
- }
-
- //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
-
- if (paErr != paNoError)
- {
- 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;
-
- retVal = eWrongObjectState;
- }
-
- return (retVal);
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::CurrentBufferSize
-//
-//! 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 ()
-{
- return m_CurrentBufferSize;
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::SetCurrentBufferSize
-//
-//! 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)
-{
- AUTO_FUNC_DEBUG;
- WTErr retVal = eNoErr;
- std::vector<int>::iterator intIter;
-
- if (Streaming())
- {
- //Can't change, perhaps use an "in use" type of error
- retVal = eGenericErr;
- return (retVal);
- }
-
- // Buffer size for ASIO devices can be changed from the control panel only
- // We have driver driven logi here
- if (m_CurrentBufferSize != newSize )
- {
- // 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
-//
-//! 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 ()
-{
- AUTO_FUNC_DEBUG;
- //ToDo: May want to do something more to extract the actual status!
- return (m_ConnectionStatus);
-
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::activateDevice
-//
-//! IS CALLED BY PROCESS THREAD
-//! 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.
-//!
-//**********************************************************************************************
-void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
-{
- AUTO_FUNC_DEBUG;
-
- PaError paErr = paNoError;
-
- // if device is not active activate it
- if (!Active() )
- {
- PaStreamParameters inputParameters, outputParameters;
- PaStreamParameters *pInS = NULL, *pOutS = NULL;
-
- const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
- const PaHostApiInfo *pHostApiInfo = Pa_GetHostApiInfo(pDeviceInfo->hostApi);
-
- inputParameters.device = m_DeviceID;
- inputParameters.channelCount = (int)m_InputChannels.size();
- inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
- inputParameters.suggestedLatency = Pa_GetDeviceInfo(m_DeviceID)->defaultLowInputLatency;
- inputParameters.hostApiSpecificStreamInfo = 0;
-
- if (inputParameters.channelCount)
- pInS = &inputParameters;
-
- outputParameters.device = m_DeviceID;
- outputParameters.channelCount = (int)m_OutputChannels.size();
- outputParameters.sampleFormat = paFloat32;
- outputParameters.suggestedLatency = Pa_GetDeviceInfo(m_DeviceID)->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = 0;
-
- if (outputParameters.channelCount)
- pOutS = &outputParameters;
-
- 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)
- {
- 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;
-
- if (pHostApiInfo->type == paASIO)
- {
- m_BufferSizeChangeRequested = 0;
- m_BufferSizeChangeReported = 0;
- m_ResetRequested = 0;
- m_ResetReported = 0;
- m_ResyncRequested = 0;
- m_ResyncReported = 0;
- std::cout << "Installing new mesage hook "<< std::endl;
- PaAsio_SetMessageHook (StaticASIOMessageHook, this);
- }
- m_IsActive = true;
- m_ConnectionStatus = DeviceAvailable;
- m_lastErr = eNoErr;
- }
- else
- {
- //failed, do not update device state
- 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;
- }
-
-
- }
-
- 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.
-//!
-//**********************************************************************************************
-void WCMRPortAudioDevice::deactivateDevice (bool callerIsWaiting/*=false*/)
-{
- AUTO_FUNC_DEBUG;
-
- PaError paErr = paNoError;
-
- if (Active() )
- {
- if (Streaming())
- {
- stopStreaming ();
- }
-
- if (m_PortAudioStream)
- {
- //close the stream first
- std::cout << "API::Device" << m_DeviceName << " Closing device stream" << std::endl;
- paErr = Pa_CloseStream (m_PortAudioStream);
- if(paErr == paNoError)
- {
- m_PortAudioStream = NULL;
- m_DropsDetected = 0;
- m_DropsReported = 0;
- m_IgnoreThisDrop = true;
- m_BufferSizeChangeRequested = 0;
- m_BufferSizeChangeReported = 0;
- m_ResetRequested = 0;
- m_ResetReported = 0;
- m_ResyncRequested = 0;
- m_ResyncReported = 0;
- PaAsio_SetMessageHook (NULL, NULL);
-
- //finaly set device state to "not active"
- m_IsActive = false;
- m_ConnectionStatus = DeviceDisconnected;
- m_lastErr = eNoErr;
- }
- else
- {
- //failed, do not update device state
- 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;
- }
- }
- }
-
- if (callerIsWaiting)
- SetEvent(m_hDeActivationDone);
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::startStreaming
-//
-//! 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*/)
-{
- AUTO_FUNC_DEBUG;
-
- // proceed if the device is not streaming
- if (!Streaming () )
- {
- PaError paErr = paNoError;
- m_StopRequested = 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: " << Pa_GetErrorText (paErr) << std::endl;
- DEBUG_MSG( "Failed to start PA stream: " << Pa_GetErrorText (paErr) );
- m_lastErr = eGenericErr;
- }
- }
-
- if (callerIsWaiting)
- SetEvent(m_hStartStreamingDone);
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDevice::stopStreaming
-//
-//! 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*/)
-{
- AUTO_FUNC_DEBUG;
-
- // proceed if the device is streaming
- if (Streaming () )
- {
- PaError paErr = paNoError;
- m_StopRequested = true;
-
- std::cout << "API::Device " << m_DeviceName << " Stopping device stream" << std::endl;
- paErr = Pa_StopStream( m_PortAudioStream );
-
- if(paErr == paNoError || paErr == paStreamIsStopped)
- {
- // if the stream was stopped successfully
- m_IsStreaming = false;
- m_pInputData = NULL;
- }
- else
- {
- 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;
- }
- }
-
- if (callerIsWaiting)
- SetEvent(m_hStopStreamingDone);
-}
-
-
-//**********************************************************************************************
-// 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*/ )
-{
- PaError paErr = paNoError;
-
- // Keep device sates
- bool wasStreaming = Streaming();
- bool wasActive = Active();
-
- // Reset the device
- stopStreaming();
- deactivateDevice();
-
- // Cache device buffer size as it might be changed during reset
- int oldBufferSize = m_CurrentBufferSize;
-
- // 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;
-
- 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);
- }
-
- if (paErr == paNoError)
- {
- // 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();
-
- // 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)
- SetEvent(m_hResetDone);
-}
-
-
-#ifdef PLATFORM_WINDOWS
-
-long WCMRPortAudioDevice::StaticASIOMessageHook (void *pRefCon, long selector, long value, void* message, double* opt)
-{
- if (pRefCon)
- {
- return ((WCMRPortAudioDevice*)(pRefCon))->ASIOMessageHook (selector, value, message, opt);
- }
- else
- return -1;
-}
-
-long WCMRPortAudioDevice::ASIOMessageHook (long selector, long WCUNUSEDPARAM(value), void* WCUNUSEDPARAM(message), double* WCUNUSEDPARAM(opt))
-{
- switch(selector)
- {
- case kAsioResyncRequest:
- 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;
- 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_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::Dropout);
- break;
- }
- return 0;
-}
-
-#endif
-
-
-//**********************************************************************************************
-// 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[] =
- {
- m_hUpdateDeviceInfoRequestedEvent,
- m_hActivateRequestedEvent,
- m_hDeActivateRequestedEvent,
- m_hStartStreamingRequestedEvent,
- m_hStopStreamingRequestedEvent,
- m_hBufferSizeChangedEvent,
- m_hSampleRateChangedEvent,
- m_hResetRequestedEvent,
- m_hResetFromDevRequestedEvent,
- m_hExitIdleThread
- };
-
- const size_t hEventsSize = sizeof(hEvents)/sizeof(hEvents[0]);
-
- initDevice();
-
- for(;;)
- {
- DWORD result = WaitForMultipleObjects (hEventsSize, hEvents, FALSE, INFINITE);
- result = result - WAIT_OBJECT_0;
-
- if ((result < 0) || (result >= hEventsSize)) {
- std::cout << "\t\t\t\t\t\t\tWCMRPortAudioDevice::DoIdle () -> (result < 0) || (result >= hEventsSize):" << result << std::endl;
- retVal = eGenericErr;
- break;
- }
-
- if (hEvents[result] == m_hExitIdleThread) {
- std::cout << "\t\t\t\t\t\t\tWCMRPortAudioDevice::DoIdle () -> m_hExitIdleThread" << result << std::endl;
- retVal = eNoErr;
- break;
- }
-
- if (hEvents[result] == m_hUpdateDeviceInfoRequestedEvent) {
- std::cout << "\t\t\t\t\t\tupdate requested ..." << std::endl;
- updateDeviceInfo(true);
- }
-
- if (hEvents[result] == m_hActivateRequestedEvent) {
- std::cout << "\t\t\t\t\t\tactivation requested ..." << std::endl;
- activateDevice(true);
- }
-
- if (hEvents[result] == m_hDeActivateRequestedEvent) {
- std::cout << "\t\t\t\t\t\tdeactivation requested ..." << std::endl;
- deactivateDevice(true);
- }
-
- if (hEvents[result] == m_hStartStreamingRequestedEvent) {
- std::cout << "\t\t\t\t\t\tStart stream requested ..." << std::endl;
- startStreaming(true);
- }
-
- if (hEvents[result] == m_hStopStreamingRequestedEvent) {
- std::cout << "\t\t\t\t\t\tStop stream requested ..." << std::endl;
- stopStreaming(true);
- }
-
- if (hEvents[result] == m_hResetRequestedEvent) {
- std::cout << "\t\t\t\t\t\treset requested ..." << std::endl;
- resetDevice(true);
- }
-
- if (hEvents[result] == m_hResetFromDevRequestedEvent) {
- std::cout << "\t\t\t\t\t\treset requested from device..." << std::endl;
- resetDevice();
- }
-
- if (hEvents[result] == m_hBufferSizeChangedEvent) {
- std::cout << "\t\t\t\t\t\tbuffer size changed from device..." << std::endl;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged);
- }
-
- if (hEvents[result] == m_hSampleRateChangedEvent) {
- std::cout << "\t\t\t\t\t\tsample rate changed from device..." << std::endl;
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::SamplingRateChanged);
- }
- }
-
- terminateDevice();
-
- return retVal;
-}
-
-
-//**********************************************************************************************
-// 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)
-{
- AUTO_FUNC_DEBUG;
- //This will most likely be overridden, the base class simply
- //changes the member.
- m_LeftMonitorChannel = leftChannel;
- m_RightMonitorChannel = rightChannel;
- return (eNoErr);
-}
-
-
-
-//**********************************************************************************************
-// 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)
-//!
-//! \return eNoErr always, the derived classes may return appropriate errors.
-//!
-//**********************************************************************************************
-WTErr WCMRPortAudioDevice::SetMonitorGain (float newGain)
-{
- AUTO_FUNC_DEBUG;
- //This will most likely be overridden, the base class simply
- //changes the member.
-
- m_MonitorGain = newGain;
- return (eNoErr);
-}
-
-
-
-
-//**********************************************************************************************
-// 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() && !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;
-
- // 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;
-#endif //_windows
- }
-
- return (retVal);
-}
-
-
-//*****************************************************************************************************
-// WCMRPortAudioDevice::TheCallback
-//
-//! 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 pOutputBuffer: pointer to output buffer.
-//! \param framesPerBuffer: number of sample frames per 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,
- const PaStreamCallbackTimeInfo* /*pTimeInfo*/, PaStreamCallbackFlags statusFlags, void *pUserData )
-{
- WCMRPortAudioDevice *pMyDevice = (WCMRPortAudioDevice *)pUserData;
- if (pMyDevice)
- return pMyDevice->AudioCallback ((float *)pInputBuffer, (float *)pOutputBuffer, framesPerBuffer,
- (statusFlags & (paInputOverflow | paOutputUnderflow)) != 0);
- else
- return (true);
-
-}
-
-
-
-//**********************************************************************************************
-// 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
-//! input data available to any sources that may call upon us during this time!
-//!
-//! \param *pInputBuffer : Points to a buffer with recorded data.
-//! \param *pOutputBuffer : Points to a buffer to receive playback data.
-//! \param framesPerBuffer : Number of sample frames in input and output buffers. Number of channels,
-//! 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 )
-{
- UMicroseconds theStartTime;
-
- // detect drops
- if (dropsDetected)
- {
- if (m_IgnoreThisDrop)
- m_IgnoreThisDrop = false; //We'll ignore once, just once!
- else
- m_DropsDetected++;
- }
-
- m_pInputData = pInputBuffer;
-
- // VKamyshniy: Is this a right place to call the client???:
- struct WCMRAudioDeviceManagerClient::AudioCallbackData audioCallbackData =
- {
- m_pInputData,
- pOutputBuffer,
- framesPerBuffer,
- m_SampleCounter,
- theStartTime.MicroSeconds()*1000
- };
-
- m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData );
-
- //Don't try to access after this call returns!
- m_pInputData = NULL;
-
- m_SampleCounter += framesPerBuffer;
-
- return m_StopRequested;
-}
-
-
-
-
-//**********************************************************************************************
-// WCMRPortAudioDeviceManager::WCMRPortAudioDeviceManager
-//
-//! The constructuor, we initialize PA, and build the device list.
-//!
-//! \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,
- eAudioDeviceFilter eCurAudioDeviceFilter, bool useMultithreading, bool bNocopy)
- : WCMRAudioDeviceManager (pTheClient, eCurAudioDeviceFilter)
- , m_NoneDevice(0)
- , m_UseMultithreading(useMultithreading)
- , m_bNoCopyAudioBuffer(bNocopy)
-{
- AUTO_FUNC_DEBUG;
- std::cout << "API::PortAudioDeviceManager::PA Device manager constructor" << std::endl;
-
- //Always create the None device first...
- m_NoneDevice = new WCMRNativeAudioNoneDevice(this);
-
- WTErr err = generateDeviceListImpl();
-
- if (eNoErr != err)
- throw err;
-
- timeBeginPeriod (1);
-}
-
-
-//**********************************************************************************************
-// WCMRPortAudioDeviceManager::~WCMRPortAudioDeviceManager
-//
-//! It clears the device list, releasing each of the device.
-//!
-//! \param none
-//!
-//! \return Nothing.
-//!
-//**********************************************************************************************
-WCMRPortAudioDeviceManager::~WCMRPortAudioDeviceManager()
-{
- AUTO_FUNC_DEBUG;
-
- std::cout << "API::Destroying PortAudioDeviceManager " << std::endl;
-
- try
- {
- delete m_NoneDevice;
- }
- catch (...)
- {
- //destructors should absorb exceptions, no harm in logging though!!
- DEBUG_MSG ("Exception during destructor");
- }
-
- timeEndPeriod (1);
-}
-
-
-WCMRAudioDevice* WCMRPortAudioDeviceManager::initNewCurrentDeviceImpl(const std::string & deviceName)
-{
- destroyCurrentDeviceImpl();
-
- std::cout << "API::PortAudioDeviceManager::initNewCurrentDevice " << deviceName << std::endl;
- if (deviceName == m_NoneDevice->DeviceName() )
- {
- m_CurrentDevice = m_NoneDevice;
- return m_CurrentDevice;
- }
-
- DeviceInfo devInfo;
- WTErr err = GetDeviceInfoByName(deviceName, devInfo);
-
- if (eNoErr == err)
- {
- try
- {
- std::cout << "API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName << std::endl;
- TRACE_MSG ("API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName);
-
- m_CurrentDevice = new WCMRPortAudioDevice (this, devInfo.m_DeviceId, m_UseMultithreading, m_bNoCopyAudioBuffer);
- }
- catch (...)
- {
- std::cout << "Unabled to create PA Device: " << devInfo.m_DeviceId << std::endl;
- DEBUG_MSG ("Unabled to create PA Device: " << devInfo.m_DeviceId);
- }
- }
-
- return m_CurrentDevice;
-}
-
-
-void WCMRPortAudioDeviceManager::destroyCurrentDeviceImpl()
-{
- if (m_CurrentDevice != m_NoneDevice)
- delete m_CurrentDevice;
-
- m_CurrentDevice = 0;
-}
-
-
-WTErr WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates)
-{
- WTErr retVal = eNoErr;
-
- sampleRates.clear();
- const PaDeviceInfo *pPaDeviceInfo = Pa_GetDeviceInfo(deviceId);
-
- //now find supported sample rates
- //following parameters are needed for sample rates validation
- PaStreamParameters inputParameters, outputParameters;
- PaStreamParameters *pInS = NULL, *pOutS = NULL;
-
- inputParameters.device = deviceId;
- inputParameters.channelCount = std::min<int>(2, pPaDeviceInfo->maxInputChannels);
- inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
- inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
- inputParameters.hostApiSpecificStreamInfo = 0;
-
- if (inputParameters.channelCount)
- pInS = &inputParameters;
-
- outputParameters.device = deviceId;
- outputParameters.channelCount = std::min<int>(2, pPaDeviceInfo->maxOutputChannels);
- outputParameters.sampleFormat = paFloat32;
- outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
- outputParameters.hostApiSpecificStreamInfo = 0;
-
- if (outputParameters.channelCount)
- pOutS = &outputParameters;
-
- for(int sr=0; gAllSampleRates[sr] > 0; sr++)
- {
- if( paFormatIsSupported == Pa_IsFormatSupported(pInS, pOutS, gAllSampleRates[sr]) )
- {
- 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;
-}
-
-
-WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
-{
- std::cout << "API::PortAudioDeviceManager::Generating device list" << std::endl;
-
- WTErr retVal = eNoErr;
-
- //Initialize PortAudio and ASIO first
- PaError paErr = Pa_Initialize();
-
- if (paErr != paNoError)
- {
- //ToDo: throw an exception here!
- retVal = eSomeThingNotInitailzed;
- return retVal;
- }
-
- // lock DeviceInfoVec firts
- wvNS::wvThread::ThreadMutex::lock theLock(m_AudioDeviceInfoVecMutex);
-
- if (m_NoneDevice)
- {
- DeviceInfo *pDevInfo = new DeviceInfo(NONE_DEVICE_ID, m_NoneDevice->DeviceName() );
- pDevInfo->m_AvailableSampleRates = m_NoneDevice->SamplingRates();
- m_DeviceInfoVec.push_back(pDevInfo);
- }
-
- //Get device count...
- int numDevices = Pa_GetDeviceCount();
-
- //for each device,
- for (int thisDeviceID = 0; thisDeviceID < numDevices; thisDeviceID++)
- {
- //if it's of the required type...
- const PaDeviceInfo *pPaDeviceInfo = Pa_GetDeviceInfo(thisDeviceID);
-
- if (Pa_GetHostApiInfo(pPaDeviceInfo->hostApi)->type == paASIO)
- {
- //build a device object...
- try
- {
- std::cout << "API::PortAudioDeviceManager::DeviceID: " << thisDeviceID << ", Device Name: " << pPaDeviceInfo->name << std::endl;
- TRACE_MSG ("PA DeviceID: " << thisDeviceID << ", Device Name: " << pPaDeviceInfo->name);
-
- DeviceInfo *pDevInfo = new DeviceInfo(thisDeviceID, pPaDeviceInfo->name);
- if (pDevInfo)
- {
- //Get available sample rates
- std::vector<int> availableSampleRates;
- WTErr wErr = WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(thisDeviceID, availableSampleRates);
-
- if (wErr != eNoErr)
- {
- DEBUG_MSG ("Failed to get device available sample rates. Device ID: " << m_DeviceID);
- delete pDevInfo;
- continue; //proceed to the next device
- }
-
- pDevInfo->m_AvailableSampleRates = 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)
- {
- case eInputOnlyDevices:
- if (pDevInfo->m_MaxInputChannels != 0)
- {
- m_DeviceInfoVec.push_back(pDevInfo);
- }
- else
- {
- // Delete unnecesarry device
- bRejectDevice = true;
- }
- break;
- case eOutputOnlyDevices:
- if (pDevInfo->m_MaxOutputChannels != 0)
- {
- m_DeviceInfoVec.push_back(pDevInfo);
- }
- else
- {
- // Delete unnecesarry device
- bRejectDevice = true;
- }
- break;
- case eFullDuplexDevices:
- if (pDevInfo->m_MaxInputChannels != 0 && pDevInfo->m_MaxOutputChannels != 0)
- {
- m_DeviceInfoVec.push_back(pDevInfo);
- }
- else
- {
- // Delete unnecesarry device
- bRejectDevice = true;
- }
- break;
- case eAllDevices:
- default:
- m_DeviceInfoVec.push_back(pDevInfo);
- break;
- }
-
- if(bRejectDevice)
- {
- TRACE_MSG ("API::PortAudioDeviceManager::Device " << pDevInfo->m_DeviceName << "Rejected. \
- In Channels = " << pDevInfo->m_MaxInputChannels << "Out Channels = " <<pDevInfo->m_MaxOutputChannels );
- delete pDevInfo;
- }
- }
- }
- catch (...)
- {
- std::cout << "API::PortAudioDeviceManager::Unabled to create PA Device: " << std::endl;
- DEBUG_MSG ("Unabled to create PA Device: " << thisDeviceID);
- }
- }
- }
-
- //If no devices were found, that's not a good thing!
- if (m_DeviceInfoVec.empty() )
- {
- std::cout << "API::PortAudioDeviceManager::No matching PortAudio devices were found, total PA devices = " << numDevices << std::endl;
- DEBUG_MSG ("No matching PortAudio devices were found, total PA devices = " << numDevices);
- }
-
- //we don't need PA initialized right now
- Pa_Terminate();
-
- return retVal;
-}
-
-
-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;
-
- buffers.clear();
-
- //first check if the request has been made for None device
- if (deviceName == m_NoneDevice->DeviceName() )
- {
- buffers=m_NoneDevice->BufferSizes();
- return retVal;
- }
-
- if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
- {
- buffers=m_CurrentDevice->BufferSizes();
- return retVal;
- }
-
- DeviceInfo devInfo;
- retVal = GetDeviceInfoByName(deviceName, devInfo);
-
- if (eNoErr == retVal)
- {
- 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;
- }
-
- return retVal;
-}
diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h
deleted file mode 100644
index c028d09511..0000000000
--- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- Copyright (C) 2014 Waves Audio Ltd.
-
- 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.
-
-*/
-
-//----------------------------------------------------------------------------------
-//
-//
-//! \file WCMRPortAudioDeviceManager.h
-//!
-//! WCMRPortAudioDeviceManager and related class declarations
-//!
-//---------------------------------------------------------------------------------*/
-#ifndef __WCMRPortAudioDeviceManager_h_
- #define __WCMRPortAudioDeviceManager_h_
-
-#include "WCMRAudioDeviceManager.h"
-#include "WCMRNativeAudio.h"
-#include "portaudio.h"
-
-//forward decl.
-class WCMRPortAudioDeviceManager;
-
-//! Manages a port audio device, providing information
-//! about the device, and managing audio callbacks.
-class WCMRPortAudioDevice : public WCMRNativeAudioDevice
-{
-public:
-
- WCMRPortAudioDevice (WCMRPortAudioDeviceManager *pManager, unsigned int deviceID, bool useMultiThreading = true, bool bNoCopy = false);///<Constructor
- virtual ~WCMRPortAudioDevice ();///<Destructor
-
- virtual int CurrentSamplingRate(); ///<Current Sampling rate.?
- virtual WTErr SetCurrentSamplingRate(int newRate);///<Change Current Sampling Rate : This is a requset, might not be successful at run time!
-
- virtual int CurrentBufferSize();///<Current Buffer Size.? - note that this may change with change in sampling rate.
- virtual WTErr SetCurrentBufferSize (int newSize);///<Change Current Buffer Size : This is a requset, might not be successful at run time!
-
- virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
-
- virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
-
- virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
-
- virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
- virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
-
- virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
-
- virtual int AudioCallback (const float *pInputBuffer, float *pOutputBuffer, unsigned long framesPerBuffe, bool dropsDetectedr);
-
- virtual WTErr UpdateDeviceInfo ();
-
- virtual WTErr ResetDevice();
-
-#ifdef PLATFORM_WINDOWS
- static long StaticASIOMessageHook (void *pRefCon, long selector, long value, void* message, double* opt);
- long ASIOMessageHook (long selector, long value, void* message, double* opt);
-#endif //PLATFORM_WINDOWS
-
-protected:
- static DWORD WINAPI __DoIdle__(LPVOID lpThreadParameter);
-
- // Methods which are executed by device processing thread
- WTErr DoIdle();///<Do Idle Processing
- void initDevice();
- void terminateDevice();
- void updateDeviceInfo(bool callerIsWaiting = false);
- void activateDevice(bool callerIsWaiting = false);
- void deactivateDevice(bool callerIsWaiting = false);
- void startStreaming(bool callerIsWaiting = false);
- void stopStreaming(bool callerIsWaiting = false);
- void resetDevice (bool callerIsWaiting = false);///<Reset device - close and reopen stream, update device information!
-
- PaError testStateValidness(int sampleRate, int bufferSize);
- ///////////////////////////////////////////////////////////
-
- static int TheCallback (const void *pInputBuffer, void *pOutputBuffer, unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* /*pTimeInfo*/, PaStreamCallbackFlags /*statusFlags*/, void *pUserData );
-
- unsigned int m_DeviceID; ///< The PA device id
- PaStream* m_PortAudioStream; ///< Port audio stream, when the device is active!
- bool m_StopRequested; ///< should be set to true when want to stop, set to false otherwise.
- const float *m_pInputData; ///< This is what came in with the most recent callback.
- int64_t m_SampleCounter; ///< The current running sample counter, updated by the audio callback.
- int64_t m_SampleCountAtLastIdle;
-
- int m_DropsDetected; ///< Number of times audio drops have been detected so far.
- int m_DropsReported; ///< Number of times audio drops have been reported so far to the client.
- bool m_IgnoreThisDrop; ///< Allows disregarding the first drop
-
- int m_BufferSizeChangeRequested;
- int m_BufferSizeChangeReported;
- int m_ResetRequested;
- int m_ResetReported;
- int m_ResyncRequested;
- int m_ResyncReported;
-
- HANDLE m_hDeviceProcessingThread;
- DWORD m_DeviceProcessingThreadID;
-
- ///< Backend request events
- HANDLE m_hResetRequestedEvent;
- HANDLE m_hResetDone;
-
- HANDLE m_hUpdateDeviceInfoRequestedEvent;
- HANDLE m_hUpdateDeviceInfoDone;
-
- HANDLE m_hActivateRequestedEvent;
- HANDLE m_hActivationDone;
-
- HANDLE m_hDeActivateRequestedEvent;
- HANDLE m_hDeActivationDone;
-
- HANDLE m_hStartStreamingRequestedEvent;
- HANDLE m_hStartStreamingDone;
-
- HANDLE m_hStopStreamingRequestedEvent;
- HANDLE m_hStopStreamingDone;
- /////////////////////////
-
- ///< Device request events
- HANDLE m_hResetFromDevRequestedEvent;
- HANDLE m_hBufferSizeChangedEvent;
- HANDLE m_hSampleRateChangedEvent;
- /////////////////////////////
-
- ///< Sync events
- HANDLE m_hDeviceInitialized;
- HANDLE m_hExitIdleThread;
-
- //Should be set if the device connection status is "DeviceErrors"
- WTErr m_lastErr;
-};
-
-//! WCMRPortAudioDeviceManager
-/*! The PortAudio Device Manager class */
-class WCMRPortAudioDeviceManager : public WCMRAudioDeviceManager
-{
-public:
- WCMRPortAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
- bool useMultithreading = true, bool bNocopy = false); ///< constructor
-
- virtual ~WCMRPortAudioDeviceManager(void); ///< destructor
-
-protected:
-
- virtual WCMRAudioDevice* initNewCurrentDeviceImpl(const std::string & deviceName);
- virtual void destroyCurrentDeviceImpl();
- virtual WTErr generateDeviceListImpl(); // use this in derived class to fill device list
- virtual WTErr updateDeviceListImpl() {return eNoErr; } // not supported
- virtual WTErr getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const;
- virtual WTErr getDeviceSampleRatesImpl(const std::string & deviceName, std::vector<int>& sampleRates) const;
-
- bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
- bool m_bNoCopyAudioBuffer;
-
-private:
- // helper functions for this class only
- WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates);
- WTErr getDeviceAvailableBufferSizes(DeviceID deviceId, std::vector<int>& buffers);
-
- WCMRAudioDevice* m_NoneDevice;
-};
-
-#endif //#ifndef __WCMRPortAudioDeviceManager_h_