13
0
livetrax/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRAudioDeviceManager.cpp
Paul Davis 1de00ab6bb new audio engine backend for native CoreAudio audio I/O, and PortMIDI for MIDI.
Code builds, runs and functions. Full code review still pending, and some possibly changes to organization of code within the backend is possible
2014-02-24 14:49:13 -05:00

744 lines
22 KiB
C++

/*
Copyright (C) 2013 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.cpp
//!
//! WCMRAudioDeviceManager and related class declarations
//!
//---------------------------------------------------------------------------------*/
#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_DeviceName = "Unknown";
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;
}
//**********************************************************************************************
// 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 overriden
//!
//! \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)
{
//This will most likely be overridden, the base class simply
//changes the member.
m_IsStreaming = newState;
return (eNoErr);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
// 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_pTheClient (pTheClient)
, m_eAudioDeviceFilter(eCurAudioDeviceFilter)
{
//The derived classes will do lot more init!
return;
}
//**********************************************************************************************
// WCMRAudioDeviceManager::~WCMRAudioDeviceManager
//
//! It clears the device list, releasing each of the device.
//!
//! \param none
//!
//! \return Nothing.
//!
//**********************************************************************************************
WCMRAudioDeviceManager::~WCMRAudioDeviceManager()
{
AUTO_FUNC_DEBUG;
try
{
//Need to call release on our devices, and erase them from list
std::vector<WCMRAudioDevice*>::iterator deviceIter;
while (m_Devices.size())
{
WCMRAudioDevice *pDeviceToRelease = m_Devices.back();
m_Devices.pop_back();
if (pDeviceToRelease)
SAFE_RELEASE (pDeviceToRelease);
}
//The derived classes may want to do additional de-int!
}
catch (...)
{
//destructors should absorb exceptions, no harm in logging though!!
DEBUG_MSG ("Exception during destructor");
}
}
//**********************************************************************************************
// WCMRAudioDeviceManager::DoIdle_Private
//
//! Used for idle time processing. This calls each device's DoIdle so that it can perform it's own idle processing.
//!
//! \param none
//!
//! \return noErr if no devices have returned an error. An error code if any of the devices returned error.
//!
//**********************************************************************************************
WTErr WCMRAudioDeviceManager::DoIdle_Private()
{
WTErr retVal = eNoErr;
//Need to call DoIdle of all our devices...
std::vector<WCMRAudioDevice*>::iterator deviceIter;
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
{
WTErr thisDeviceErr = (*deviceIter)->DoIdle();
if (thisDeviceErr != eNoErr)
retVal = thisDeviceErr;
}
return (retVal);
}
//**********************************************************************************************
// WCMRAudioDeviceManager::Devices_Private
//
//! Retrieve list of devices managed by this manager.
//!
//! \param none
//!
//! \return A vector containing the list of devices.
//!
//**********************************************************************************************
const WCMRAudioDeviceList& WCMRAudioDeviceManager::Devices_Private() const
{
return (m_Devices);
}
//**********************************************************************************************
// *WCMRAudioDeviceManager::GetDeviceByName_Private
//
//! Locates a device based on device name.
//!
//! \param nameToMatch : Device to look for.
//!
//! \return Pointer to the device object if found, NULL otherwise.
//!
//**********************************************************************************************
WCMRAudioDevice *WCMRAudioDeviceManager::GetDeviceByName_Private(const std::string& nameToMatch) const
{
//Need to check all our devices...
WCMRAudioDevice *pRetVal = NULL;
WCMRAudioDeviceListConstIter deviceIter;
for (deviceIter = m_Devices.begin(); deviceIter != m_Devices.end(); deviceIter++)
{
if ((*deviceIter)->DeviceName() == nameToMatch)
{
pRetVal = *deviceIter;
break;
}
}
return (pRetVal);
}
//**********************************************************************************************
// *WCMRAudioDeviceManager::GetDefaultDevice
//
//! Locates a device based on device name.
//!
//! \param nameToMatch : Device to look for.
//!
//! \return Pointer to the device object if found, NULL otherwise.
//!
//**********************************************************************************************
WCMRAudioDevice *WCMRAudioDeviceManager::GetDefaultDevice_Private()
{
//Need to check all our devices...
WCMRAudioDevice *pRetVal = NULL;
WCMRAudioDeviceListIter deviceIter = m_Devices.begin();
if(deviceIter != m_Devices.end())
{
pRetVal = *deviceIter;
}
return (pRetVal);
}
//**********************************************************************************************
// 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;
}