Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/SHP_Control.cpp
/* Copyright © 2007 Apple Inc. All Rights Reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by |
Apple Inc. ("Apple") in consideration of your agreement to the |
following terms, and your use, installation, modification or |
redistribution of this Apple software constitutes acceptance of these |
terms. If you do not agree with these terms, please do not use, |
install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. |
may be used to endorse or promote products derived from the Apple |
Software without specific prior written permission from Apple. Except |
as expressly stated in this notice, no other rights or licenses, express |
or implied, are granted by Apple herein, including but not limited to |
any patent rights that may be infringed by your derivative works or by |
other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
*/ |
//================================================================================================== |
// Includes |
//================================================================================================== |
// Self Include |
#include "SHP_Control.h" |
// Local Includes |
#include "SHP_Device.h" |
#include "SHP_PlugIn.h" |
// PublicUtility Includes |
#include "CACFArray.h" |
#include "CACFDictionary.h" |
#include "CACFNumber.h" |
#include "CACFString.h" |
#include "CADebugMacros.h" |
#include "CAException.h" |
//================================================================================================== |
// SHP_LevelControl |
//================================================================================================== |
SHP_LevelControl::SHP_LevelControl(AudioObjectID inObjectID, AudioClassID inClassID, AudioObjectPropertyScope inDevicePropertyScope, AudioObjectPropertyElement inDevicePropertyElement, SHP_PlugIn* inPlugIn, SHP_Device* inOwningDevice) |
: |
HP_LevelControl(inObjectID, inClassID, inPlugIn, inOwningDevice), |
mDevicePropertyScope(inDevicePropertyScope), |
mDevicePropertyElement(inDevicePropertyElement), |
mVolumeCurve(), |
mCurrentRawValue(0) |
{ |
} |
SHP_LevelControl::~SHP_LevelControl() |
{ |
} |
void SHP_LevelControl::Initialize() |
{ |
// cache the info about the control |
SInt32 theMinRaw = 0; |
SInt32 theMaxRaw = 1024; |
Float32 theMinDB = -90; |
Float32 theMaxDB = 0; |
// set up the volume curve |
mVolumeCurve.ResetRange(); |
mVolumeCurve.AddRange(theMinRaw, theMaxRaw, theMinDB, theMaxDB); |
// cache the raw value |
CacheRawValue(); |
} |
void SHP_LevelControl::Teardown() |
{ |
} |
AudioObjectPropertyScope SHP_LevelControl::GetPropertyScope() const |
{ |
return mDevicePropertyScope; |
} |
AudioObjectPropertyElement SHP_LevelControl::GetPropertyElement() const |
{ |
return mDevicePropertyElement; |
} |
Float32 SHP_LevelControl::GetMinimumDBValue() const |
{ |
return mVolumeCurve.GetMinimumDB(); |
} |
Float32 SHP_LevelControl::GetMaximumDBValue() const |
{ |
return mVolumeCurve.GetMaximumDB(); |
} |
Float32 SHP_LevelControl::GetDBValue() const |
{ |
SInt32 theRawValue = GetRawValue(); |
Float32 thDBValue = mVolumeCurve.ConvertRawToDB(theRawValue); |
return thDBValue; |
} |
void SHP_LevelControl::SetDBValue(Float32 inDBValue) |
{ |
SInt32 theNewRawValue = mVolumeCurve.ConvertDBToRaw(inDBValue); |
SetRawValue(theNewRawValue); |
} |
Float32 SHP_LevelControl::GetScalarValue() const |
{ |
SInt32 theRawValue = GetRawValue(); |
Float32 theScalarValue = mVolumeCurve.ConvertRawToScalar(theRawValue); |
return theScalarValue; |
} |
void SHP_LevelControl::SetScalarValue(Float32 inScalarValue) |
{ |
SInt32 theNewRawValue = mVolumeCurve.ConvertScalarToRaw(inScalarValue); |
SetRawValue(theNewRawValue); |
} |
Float32 SHP_LevelControl::ConverScalarValueToDBValue(Float32 inScalarValue) const |
{ |
Float32 theDBValue = mVolumeCurve.ConvertScalarToDB(inScalarValue); |
return theDBValue; |
} |
Float32 SHP_LevelControl::ConverDBValueToScalarValue(Float32 inDBValue) const |
{ |
Float32 theScalarValue = mVolumeCurve.ConvertDBToScalar(inDBValue); |
return theScalarValue; |
} |
SInt32 SHP_LevelControl::GetRawValue() const |
{ |
// Always get the value from the hardware and cache it in mCurrentRawValue. Note that if |
// getting the value from the hardware fails for any reason, we just return mCurrentRawValue. |
// We always just return mCurrentRawValue here because there is no hardware to talk to. |
return mCurrentRawValue; |
} |
void SHP_LevelControl::SetRawValue(SInt32 inRawValue) |
{ |
// Set the value in hardware. Note that mCurrentRawValue should be updated only if setting the |
// hardware value is synchronous. Otherwise, mCurrentRawValue will be updated when the hardware |
// notifies us that the value of the control changed. Here, we just directly set |
// mCurrentRawValue because there is no hardware. |
if(inRawValue != mCurrentRawValue) |
{ |
mCurrentRawValue = inRawValue; |
// we also have to send the change notification |
ValueChanged(); |
} |
} |
void SHP_LevelControl::CacheRawValue() |
{ |
// Set mCurrentRawValue to the value of the hardware. We do nothing here because there is no |
// hardware. |
} |
//================================================================================================== |
// SHP_BooleanControl |
//================================================================================================== |
SHP_BooleanControl::SHP_BooleanControl(AudioObjectID inObjectID, AudioClassID inClassID, AudioObjectPropertyScope inDevicePropertyScope, AudioObjectPropertyElement inDevicePropertyElement, SHP_PlugIn* inPlugIn, SHP_Device* inOwningDevice) |
: |
HP_BooleanControl(inObjectID, inClassID, inPlugIn, inOwningDevice), |
mDevicePropertyScope(inDevicePropertyScope), |
mDevicePropertyElement(inDevicePropertyElement), |
mCurrentValue(false) |
{ |
} |
SHP_BooleanControl::~SHP_BooleanControl() |
{ |
} |
void SHP_BooleanControl::Initialize() |
{ |
// cache the value |
CacheValue(); |
} |
void SHP_BooleanControl::Teardown() |
{ |
} |
AudioObjectPropertyScope SHP_BooleanControl::GetPropertyScope() const |
{ |
return mDevicePropertyScope; |
} |
AudioObjectPropertyElement SHP_BooleanControl::GetPropertyElement() const |
{ |
return mDevicePropertyElement; |
} |
bool SHP_BooleanControl::GetValue() const |
{ |
// Always get the value from the hardware and cache it in mCurrentValue. Note that if |
// getting the value from the hardware fails for any reason, we just return mCurrentValue. |
// We always just return mCurrentValue here because there is no hardware to talk to. |
return mCurrentValue; |
} |
void SHP_BooleanControl::SetValue(bool inValue) |
{ |
// Set the value in hardware. Note that mCurrentValue should be updated only if setting the |
// hardware value is synchronous. Otherwise, mCurrentValue will be updated when the hardware |
// notifies us that the value of the control changed. Here, we just directly set |
// mCurrentValue because there is no hardware. |
if(inValue != mCurrentValue) |
{ |
mCurrentValue = inValue; |
// we also have to send the change notification |
ValueChanged(); |
} |
} |
void SHP_BooleanControl::CacheValue() |
{ |
// Set mCurrentValue to the value of the hardware. We do nothing here because there is no hardware. |
} |
//================================================================================================== |
// SHP_SelectorControl |
//================================================================================================== |
SHP_SelectorControl::SHP_SelectorControl(AudioObjectID inObjectID, AudioClassID inClassID, AudioObjectPropertyScope inDevicePropertyScope, AudioObjectPropertyElement inDevicePropertyElement, SHP_PlugIn* inPlugIn, SHP_Device* inOwningDevice) |
: |
HP_SelectorControl(inObjectID, inClassID, inPlugIn, inOwningDevice), |
mDevicePropertyScope(inDevicePropertyScope), |
mDevicePropertyElement(inDevicePropertyElement), |
mSelectorMap(), |
mCurrentItemID(0) |
{ |
} |
SHP_SelectorControl::~SHP_SelectorControl() |
{ |
} |
void SHP_SelectorControl::Initialize() |
{ |
// clear the current items |
mSelectorMap.clear(); |
// Insert items into mSelectorMap for all the items in this control. Here, we just stick in a |
// few fake items. |
for(UInt32 theItemIndex = 0; theItemIndex < 4; ++theItemIndex) |
{ |
// make a name for the item |
CACFString theName(CFStringCreateWithFormat(NULL, NULL, CFSTR("Item %u"), theItemIndex)); |
// insert it into the map, using the item index as the item ID |
mSelectorMap.insert(SelectorMap::value_type(theItemIndex, SelectorItem(theName.CopyCFString(), 0))); |
} |
// cache the current item ID |
CacheCurrentItemID(); |
} |
void SHP_SelectorControl::Teardown() |
{ |
mSelectorMap.clear(); |
} |
AudioObjectPropertyScope SHP_SelectorControl::GetPropertyScope() const |
{ |
return mDevicePropertyScope; |
} |
AudioObjectPropertyElement SHP_SelectorControl::GetPropertyElement() const |
{ |
return mDevicePropertyElement; |
} |
UInt32 SHP_SelectorControl::GetNumberItems() const |
{ |
return mSelectorMap.size(); |
} |
UInt32 SHP_SelectorControl::GetCurrentItemID() const |
{ |
// Always get the value from the hardware and cache it in mCurrentItemID. Note that if |
// getting the value from the hardware fails for any reason, we just return mCurrentItemID. |
// We always just return mCurrentItemID here because there is no hardware to talk to. |
return mCurrentItemID; |
} |
UInt32 SHP_SelectorControl::GetCurrentItemIndex() const |
{ |
UInt32 theItemID = GetCurrentItemID(); |
return GetItemIndexForID(theItemID); |
} |
void SHP_SelectorControl::SetCurrentItemByID(UInt32 inItemID) |
{ |
// Set the value in hardware. Note that mCurrentItemID should be updated only if setting the |
// hardware value is synchronous. Otherwise, mCurrentItemID will be updated when the hardware |
// notifies us that the value of the control changed. Here, we just directly set |
// mCurrentItemID because there is no hardware. |
if(inItemID != mCurrentItemID) |
{ |
mCurrentItemID = inItemID; |
// we also have to send the change notification |
ValueChanged(); |
} |
} |
void SHP_SelectorControl::SetCurrentItemByIndex(UInt32 inItemIndex) |
{ |
UInt32 theItemID = GetItemIDForIndex(inItemIndex); |
SetCurrentItemByID(theItemID); |
} |
UInt32 SHP_SelectorControl::GetItemIDForIndex(UInt32 inItemIndex) const |
{ |
ThrowIf(inItemIndex >= mSelectorMap.size(), CAException(kAudioHardwareIllegalOperationError), "SHP_SelectorControl::GetItemIDForIndex: index out of range"); |
SelectorMap::const_iterator theIterator = mSelectorMap.begin(); |
std::advance(theIterator, inItemIndex); |
return theIterator->first; |
} |
UInt32 SHP_SelectorControl::GetItemIndexForID(UInt32 inItemID) const |
{ |
UInt32 theIndex = 0; |
bool wasFound = false; |
SelectorMap::const_iterator theIterator = mSelectorMap.begin(); |
while(!wasFound && (theIterator != mSelectorMap.end())) |
{ |
if(theIterator->first == inItemID) |
{ |
wasFound = true; |
} |
else |
{ |
++theIndex; |
std::advance(theIterator, 1); |
} |
} |
ThrowIf(!wasFound, CAException(kAudioHardwareIllegalOperationError), "SHP_SelectorControl::GetItemIndexForID: ID not in selector map"); |
return theIndex; |
} |
CFStringRef SHP_SelectorControl::CopyItemNameByID(UInt32 inItemID) const |
{ |
SelectorMap::const_iterator theIterator = mSelectorMap.find(inItemID); |
ThrowIf(theIterator == mSelectorMap.end(), CAException(kAudioHardwareIllegalOperationError), "SHP_SelectorControl::CopyItemNameByID: ID not in selector map"); |
return (CFStringRef)CFRetain(theIterator->second.mItemName); |
} |
CFStringRef SHP_SelectorControl::CopyItemNameByIndex(UInt32 inItemIndex) const |
{ |
CFStringRef theAnswer = NULL; |
if(inItemIndex < mSelectorMap.size()) |
{ |
SelectorMap::const_iterator theIterator = mSelectorMap.begin(); |
std::advance(theIterator, inItemIndex); |
ThrowIf(theIterator == mSelectorMap.end(), CAException(kAudioHardwareIllegalOperationError), "SHP_SelectorControl::CopyItemNameByIndex: index out of range"); |
theAnswer = (CFStringRef)CFRetain(theIterator->second.mItemName); |
} |
return theAnswer; |
} |
CFStringRef SHP_SelectorControl::CopyItemNameByIDWithoutLocalizing(UInt32 inItemID) const |
{ |
return CopyItemNameByID(inItemID); |
} |
CFStringRef SHP_SelectorControl::CopyItemNameByIndexWithoutLocalizing(UInt32 inItemIndex) const |
{ |
return CopyItemNameByIndex(inItemIndex); |
} |
UInt32 SHP_SelectorControl::GetItemKindByID(UInt32 inItemID) const |
{ |
SelectorMap::const_iterator theIterator = mSelectorMap.find(inItemID); |
ThrowIf(theIterator == mSelectorMap.end(), CAException(kAudioHardwareIllegalOperationError), "SHP_SelectorControl::GetItemKindByID: ID not in selector map"); |
return theIterator->second.mItemKind; |
} |
UInt32 SHP_SelectorControl::GetItemKindByIndex(UInt32 inItemIndex) const |
{ |
UInt32 theAnswer = 0; |
if(inItemIndex < mSelectorMap.size()) |
{ |
SelectorMap::const_iterator theIterator = mSelectorMap.begin(); |
std::advance(theIterator, inItemIndex); |
ThrowIf(theIterator == mSelectorMap.end(), CAException(kAudioHardwareIllegalOperationError), "SHP_SelectorControl::GetItemKindByIndex: index out of range"); |
theAnswer = theIterator->second.mItemKind; |
} |
return theAnswer; |
} |
void SHP_SelectorControl::CacheCurrentItemID() |
{ |
// Set mCurrentItemID to the value of the hardware. We do nothing here because there is no hardware. |
} |
//================================================================================================== |
// SHP_StereoPanControl |
//================================================================================================== |
SHP_StereoPanControl::SHP_StereoPanControl(AudioObjectID inObjectID, AudioClassID inClassID, AudioObjectPropertyScope inDevicePropertyScope, AudioObjectPropertyElement inDevicePropertyElement, UInt32 inLeftChannel, UInt32 inRightChannel, SHP_PlugIn* inPlugIn, SHP_Device* inOwningDevice) |
: |
HP_StereoPanControl(inObjectID, inClassID, inPlugIn, inOwningDevice), |
mDevicePropertyScope(inDevicePropertyScope), |
mDevicePropertyElement(inDevicePropertyElement), |
mLeftChannel(inLeftChannel), |
mRightChannel(inRightChannel), |
mFullLeftRawValue(0), |
mCenterRawValue(0), |
mFullRightRawValue(0), |
mCurrentRawValue(0) |
{ |
} |
SHP_StereoPanControl::~SHP_StereoPanControl() |
{ |
} |
void SHP_StereoPanControl::Initialize() |
{ |
// cache the info about the control |
mFullLeftRawValue = 0; |
mCenterRawValue = 512; |
mFullRightRawValue = 1024; |
// set the value to center, since we don't have any hardware |
mCurrentRawValue = mCenterRawValue; |
// cache the current raw value |
CacheRawValue(); |
} |
void SHP_StereoPanControl::Teardown() |
{ |
} |
AudioObjectPropertyScope SHP_StereoPanControl::GetPropertyScope() const |
{ |
return mDevicePropertyScope; |
} |
AudioObjectPropertyElement SHP_StereoPanControl::GetPropertyElement() const |
{ |
return mDevicePropertyElement; |
} |
Float32 SHP_StereoPanControl::GetValue() const |
{ |
Float32 theAnswer = 0.0; |
SInt32 theRawValue = GetRawValue(); |
Float32 theSpan; |
if(theRawValue == mCenterRawValue) |
{ |
theAnswer = 0.5; |
} |
else if(theRawValue > mCenterRawValue) |
{ |
theSpan = mFullRightRawValue - mCenterRawValue; |
theAnswer = theRawValue - mCenterRawValue; |
theAnswer *= 0.5; |
theAnswer /= theSpan; |
theAnswer += 0.5; |
} |
else |
{ |
theSpan = mCenterRawValue - mFullLeftRawValue; |
theAnswer = theRawValue - mFullLeftRawValue; |
theAnswer *= 0.5; |
theAnswer /= theSpan; |
} |
return theAnswer; |
} |
void SHP_StereoPanControl::SetValue(Float32 inValue) |
{ |
SInt32 theRawValue = 0; |
Float32 theSpan; |
if(inValue == 0.5) |
{ |
theRawValue = mCenterRawValue; |
} |
else if(inValue > 0.5) |
{ |
theSpan = mFullRightRawValue - mCenterRawValue; |
inValue -= 0.5; |
inValue *= theSpan; |
inValue *= 2.0; |
theRawValue = static_cast<SInt32>(inValue); |
theRawValue += mCenterRawValue; |
} |
else |
{ |
theSpan = mCenterRawValue - mFullLeftRawValue; |
inValue *= theSpan; |
inValue *= 2.0; |
theRawValue = static_cast<SInt32>(inValue); |
} |
SetRawValue(theRawValue); |
} |
void SHP_StereoPanControl::GetChannels(UInt32& outLeftChannel, UInt32& outRightChannel) const |
{ |
outLeftChannel = mLeftChannel; |
outRightChannel = mRightChannel; |
} |
SInt32 SHP_StereoPanControl::GetRawValue() const |
{ |
// Always get the value from the hardware and cache it in mCurrentRawValue. Note that if |
// getting the value from the hardware fails for any reason, we just return mCurrentRawValue. |
// We always just return mCurrentRawValue here because there is no hardware to talk to. |
return mCurrentRawValue; |
} |
void SHP_StereoPanControl::SetRawValue(SInt32 inValue) |
{ |
// Set the value in hardware. Note that mCurrentRawValue should be updated only if setting the |
// hardware value is synchronous. Otherwise, mCurrentRawValue will be updated when the hardware |
// notifies us that the value of the control changed. Here, we just directly set |
// mCurrentRawValue because there is no hardware. |
if(inValue != mCurrentRawValue) |
{ |
mCurrentRawValue = inValue; |
// we also have to send the change notification |
ValueChanged(); |
} |
} |
void SHP_StereoPanControl::CacheRawValue() |
{ |
// Set mCurrentRawValue to the value of the hardware. We do nothing here because there is no |
// hardware. |
} |
Copyright © 2009 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2009-04-15