summaryrefslogtreecommitdiff
path: root/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp')
-rwxr-xr-xdistrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp394
1 files changed, 394 insertions, 0 deletions
diff --git a/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp b/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp
new file mode 100755
index 00000000..7d3bf8a3
--- /dev/null
+++ b/distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp
@@ -0,0 +1,394 @@
+/* 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.
+*/
+#include "CAAUParameter.h"
+
+CAAUParameter::CAAUParameter()
+{
+ memset(this, 0, sizeof(CAAUParameter));
+}
+
+CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
+{
+ memset(this, 0, sizeof(CAAUParameter));
+ Init (au, param, scope, element);
+}
+
+CAAUParameter::CAAUParameter (AudioUnitParameter &inParam)
+{
+ memset(this, 0, sizeof(CAAUParameter));
+ Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement);
+}
+
+CAAUParameter::CAAUParameter(const CAAUParameter &a)
+{
+ memset(this, 0, sizeof(CAAUParameter));
+ *this = a;
+}
+
+CAAUParameter & CAAUParameter::operator = (const CAAUParameter &a)
+{
+ if (mParamName) CFRelease(mParamName);
+ if (mParamTag) CFRelease(mParamTag);
+ if (mNamedParams) CFRelease(mNamedParams);
+
+ memcpy(this, &a, sizeof(CAAUParameter));
+
+ if (mParamName) CFRetain(mParamName);
+ if (mParamTag) CFRetain(mParamTag);
+ if (mNamedParams) CFRetain(mNamedParams);
+
+ return *this;
+}
+
+CAAUParameter::~CAAUParameter()
+{
+ if (mParamName) CFRelease(mParamName);
+ if (mParamTag) CFRelease(mParamTag);
+ if (mNamedParams) CFRelease (mNamedParams);
+}
+
+void CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
+{
+ mAudioUnit = au;
+ mParameterID = param;
+ mScope = scope;
+ mElement = element;
+
+ UInt32 propertySize = sizeof(mParamInfo);
+ OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
+ scope, param, &mParamInfo, &propertySize);
+ if (err)
+ memset(&mParamInfo, 0, sizeof(mParamInfo));
+ if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) {
+ mParamName = mParamInfo.cfNameString;
+ if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease))
+ CFRetain (mParamName);
+ } else
+ mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
+
+ const char* str = 0;
+ switch (mParamInfo.unit)
+ {
+ case kAudioUnitParameterUnit_Boolean:
+ str = "T/F";
+ break;
+ case kAudioUnitParameterUnit_Percent:
+ case kAudioUnitParameterUnit_EqualPowerCrossfade:
+ str = "%";
+ break;
+ case kAudioUnitParameterUnit_Seconds:
+ str = "Secs";
+ break;
+ case kAudioUnitParameterUnit_SampleFrames:
+ str = "Samps";
+ break;
+ case kAudioUnitParameterUnit_Phase:
+ case kAudioUnitParameterUnit_Degrees:
+ str = "Degr.";
+ break;
+ case kAudioUnitParameterUnit_Hertz:
+ str = "Hz";
+ break;
+ case kAudioUnitParameterUnit_Cents:
+ case kAudioUnitParameterUnit_AbsoluteCents:
+ str = "Cents";
+ break;
+ case kAudioUnitParameterUnit_RelativeSemiTones:
+ str = "S-T";
+ break;
+ case kAudioUnitParameterUnit_MIDINoteNumber:
+ case kAudioUnitParameterUnit_MIDIController:
+ str = "MIDI";
+ //these are inclusive, so add one value here
+ mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
+ break;
+ case kAudioUnitParameterUnit_Decibels:
+ str = "dB";
+ break;
+ case kAudioUnitParameterUnit_MixerFaderCurve1:
+ case kAudioUnitParameterUnit_LinearGain:
+ str = "Gain";
+ break;
+ case kAudioUnitParameterUnit_Pan:
+ str = "L/R";
+ break;
+ case kAudioUnitParameterUnit_Meters:
+ str = "Mtrs";
+ break;
+ case kAudioUnitParameterUnit_Octaves:
+ str = "8ve";
+ break;
+ case kAudioUnitParameterUnit_BPM:
+ str = "BPM";
+ break;
+ case kAudioUnitParameterUnit_Beats:
+ str = "Beats";
+ break;
+ case kAudioUnitParameterUnit_Milliseconds:
+ str = "msecs";
+ break;
+ case kAudioUnitParameterUnit_Ratio:
+ str = "Ratio";
+ break;
+ case kAudioUnitParameterUnit_Indexed:
+ {
+ propertySize = sizeof(mNamedParams);
+ err = AudioUnitGetProperty (au,
+ kAudioUnitProperty_ParameterValueStrings,
+ scope,
+ param,
+ &mNamedParams,
+ &propertySize);
+ if (!err && mNamedParams) {
+ mNumIndexedParams = CFArrayGetCount(mNamedParams);
+ } else {
+ //these are inclusive, so add one value here
+ mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
+ }
+ str = NULL;
+ }
+ break;
+ case kAudioUnitParameterUnit_CustomUnit:
+ {
+ CFStringRef unitName = mParamInfo.unitName;
+ static char paramStr[256];
+ CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8);
+ if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)
+ CFRelease (unitName);
+ str = paramStr;
+ break;
+ }
+ case kAudioUnitParameterUnit_Generic:
+ case kAudioUnitParameterUnit_Rate:
+ default:
+ str = NULL;
+ break;
+ }
+
+ if (str)
+ mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
+ else
+ mParamTag = NULL;
+}
+
+
+Float32 CAAUParameter::GetValue() const
+{
+ Float32 value = 0.;
+ //OSStatus err =
+ AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value);
+ return value;
+}
+
+CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
+ const CAAUParameter * inParameter,
+ UInt32 inDigits,
+ UInt32 minDigits) {
+ if (!inParameter) return nil;
+
+ AudioUnitParameterInfo info = inParameter->ParamInfo();
+ int pow10;
+
+ switch (info.unit) {
+ case kAudioUnitParameterUnit_Hertz:
+ // number of significant digits based on value
+ pow10 = int(log10(fmax(inParameterValue, .000001)));
+ break;
+ default:
+ // number of significant digits based on parameter range
+ pow10 = int(log10(fmax(double(info.maxValue - info.minValue), .000001)));
+ break;
+ }
+
+ // pow10 range nDigitsAfterDecimal
+ // -2 .0100-.0999 4
+ // -1 .100-.999 3
+ // 0 1.00-9.99 2
+ // 1 10.0-99.9 1
+ // 2 100-999 0
+ // 3 1000-9990 -1
+ // 4 10000-99900 -2
+
+ int nDigitsAfterDecimal = inDigits - (pow10 + 1);
+ if (nDigitsAfterDecimal < 0)
+ nDigitsAfterDecimal = 0; // the least number of digits possible is zero
+
+ if (info.flags & kAudioUnitParameterFlag_IsHighResolution)
+ nDigitsAfterDecimal = 4;
+
+ CFLocaleRef currentLocale = CFLocaleCopyCurrent();
+ CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
+
+ CFNumberRef maxFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
+
+ if (nDigitsAfterDecimal > 0)
+ nDigitsAfterDecimal = minDigits;
+
+ CFNumberRef minFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
+
+ CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMinFractionDigits, minFractionDigits);
+ CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMaxFractionDigits, maxFractionDigits);
+ CFStringRef formattedNumberString = CFNumberFormatterCreateStringWithValue (NULL, numberFormatter, kCFNumberDoubleType, &inParameterValue);
+
+ CFRelease(currentLocale);
+ CFRelease(numberFormatter);
+ CFRelease(maxFractionDigits);
+ CFRelease(minFractionDigits);
+
+ return formattedNumberString;
+}
+
+CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
+ const CAAUParameter * inParameter,
+ UInt32 inDigits) {
+ return CreateLocalizedStringForParameterValue (inParameterValue, inParameter, inDigits, 1);
+}
+
+double ValueForLocalizedParameterString (CFStringRef string, const CAAUParameter * inParameter) {
+ CFLocaleRef currentLocale = CFLocaleCopyCurrent();
+ CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
+
+ double value = 0;
+ Boolean worked = CFNumberFormatterGetValueFromString (numberFormatter, string, NULL, kCFNumberDoubleType, &value);
+
+ CFRelease(currentLocale);
+ CFRelease(numberFormatter);
+
+ if (worked)
+ return value;
+ else {
+ AudioUnitParameterInfo info = inParameter->ParamInfo();
+ return info.defaultValue;
+ }
+}
+
+CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const
+{
+ if (HasNamedParams())
+ {
+ Float32 val = (value == NULL ? GetValue() : *value);
+ int index = int(mParamInfo.minValue) + int(val);
+ CFStringRef str = GetParamName (index);
+ if (str) {
+ CFRetain (str);
+ return str;
+ }
+ }
+ else if (ValuesHaveStrings())
+ {
+ AudioUnitParameterStringFromValue stringValue;
+ stringValue.inParamID = mParameterID;
+ stringValue.inValue = value;
+ stringValue.outString = NULL;
+ UInt32 propertySize = sizeof(stringValue);
+
+ OSStatus err = AudioUnitGetProperty (mAudioUnit,
+ kAudioUnitProperty_ParameterStringFromValue,
+ mScope,
+ mParameterID,
+ &stringValue,
+ &propertySize);
+
+ if (!err && stringValue.outString != NULL)
+ return stringValue.outString;
+ }
+
+ Float32 val = (value == NULL ? GetValue() : *value);
+ AudioUnitParameterUnit unit = this->ParamInfo().unit;
+ if (unit == kAudioUnitParameterUnit_Cents || unit == kAudioUnitParameterUnit_AbsoluteCents)
+ return CreateLocalizedStringForParameterValue(val, this, 4, 0);
+ else
+ return CreateLocalizedStringForParameterValue(val, this, 4);
+}
+
+Float32 CAAUParameter::GetValueFromString(CFStringRef str) const
+{
+ if (ValuesHaveStrings())
+ {
+ AudioUnitParameterValueFromString valueString;
+ valueString.inParamID = mParameterID;
+ valueString.inString = str;
+ UInt32 propertySize = sizeof(valueString);
+
+ OSStatus err = AudioUnitGetProperty (mAudioUnit,
+ kAudioUnitProperty_ParameterValueFromString,
+ mScope,
+ mParameterID,
+ &valueString,
+ &propertySize);
+
+ if (!err) {
+ return valueString.outValue;
+ }
+ }
+
+ return (Float32) ValueForLocalizedParameterString(str, this);
+}
+
+void CAAUParameter::SetValue( AUParameterListenerRef inListener,
+ void * inObject,
+ Float32 inValue) const
+{
+ // clip inValue as: maxValue >= inValue >= minValue before setting
+ Float32 valueToSet = inValue;
+ if (valueToSet > mParamInfo.maxValue)
+ valueToSet = mParamInfo.maxValue;
+ if (valueToSet < mParamInfo.minValue)
+ valueToSet = mParamInfo.minValue;
+
+ AUParameterSet(inListener, inObject, this, valueToSet, 0);
+}
+
+#if DEBUG
+void CAAUParameter::Print() const
+{
+ UInt32 clump = 0;
+ GetClumpID (clump);
+
+ UInt32 len = CFStringGetLength(mParamName);
+ char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
+ if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
+ chars[0] = 0;
+
+ printf ("ID: %ld, Clump: %u, Name: %s\n", (long unsigned int) mParameterID, (unsigned int) clump, chars);
+ free (chars);
+}
+#endif