CoreAudio/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
/* |
File: AUCarbonViewControl.cpp |
Abstract: AUCarbonViewControl.h |
Version: 1.1 |
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. |
Copyright (C) 2014 Apple Inc. All Rights Reserved. |
*/ |
#include "AUCarbonViewControl.h" |
#include "AUCarbonViewBase.h" |
#include "AUViewLocalizedStringKeys.h" |
AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter ¶m, ControlRef control) : |
mOwnerView(ownerView), |
mListener(listener), |
mType(type), |
mParam(param), |
mControl(control), |
mInControlInitialization(0) |
{ |
#if !__LP64__ |
SetControlReference(control, SRefCon(this)); |
#endif |
} |
AUCarbonViewControl::~AUCarbonViewControl() |
{ |
AUListenerRemoveParameter(mListener, this, &mParam); |
} |
AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL; |
void AUCarbonViewControl::Bind() |
{ |
#if !__LP64__ |
mInControlInitialization = 1; // true |
AUListenerAddParameter(mListener, this, &mParam); |
// will cause an almost-immediate callback |
EventTypeSpec events[] = { |
{ kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only |
}; |
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events); |
if (mType == kTypeContinuous || mType == kTypeText || mType == kTypeDiscrete) { |
EventTypeSpec events[] = { |
{ kEventClassControl, kEventControlHit }, |
{ kEventClassControl, kEventControlClick }, |
{ kEventClassControl, kEventControlTrack } |
}; |
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events); |
} |
if (mType == kTypeText) { |
EventTypeSpec events[] = { |
{ kEventClassControl, kEventControlSetFocusPart } |
}; |
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events); |
ControlKeyFilterUPP proc = mParam.ValuesHaveStrings() ? StdKeyFilterCallback : NumericKeyFilterCallback; |
// this will fail for a static text field |
SetControlData(mControl, 0, kControlEditTextKeyFilterTag, sizeof(proc), &proc); |
} |
Update(true); |
mInControlInitialization = 0; // false |
#endif |
} |
void AUCarbonViewControl::ParameterToControl(Float32 paramValue) |
{ |
#if !__LP64__ |
++mInControlInitialization; |
switch (mType) { |
case kTypeContinuous: |
SetValueFract(AUParameterValueToLinear(paramValue, &mParam)); |
break; |
case kTypeDiscrete: |
{ |
long value = long(paramValue); |
// special case [1] -- menu parameters |
if (mParam.HasNamedParams()) { |
// if we're dealing with menus they behave differently! |
// becaue setting min and max doesn't work correctly for the control value |
// first menu item always reports a control value of 1 |
ControlKind ctrlKind; |
if (GetControlKind(mControl, &ctrlKind) == noErr) { |
if ((ctrlKind.kind == kControlKindPopupArrow) |
|| (ctrlKind.kind == kControlKindPopupButton)) |
{ |
value = value - long(mParam.ParamInfo().minValue) + 1; |
} |
} |
} |
// special case [2] -- Write-only boolean parameters |
AudioUnitParameterInfo AUPI = mParam.ParamInfo(); |
bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) && |
(AUPI.flags & kAudioUnitParameterFlag_IsWritable) && |
!(AUPI.flags & kAudioUnitParameterFlag_IsReadable) ); |
if (!isWriteOnlyBoolParameter) { |
SetValue (value); |
} |
} |
break; |
case kTypeText: |
{ |
CFStringRef cfstr = mParam.GetStringFromValueCopy(¶mValue); |
if ( !(mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsWritable) //READ ONLY PARAMS |
&& (mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsReadable)) |
{ |
if (mParam.GetParamTag()) { |
CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 256, cfstr); |
CFRelease (cfstr); |
CFStringAppend (str, CFSTR(" ")); |
CFStringAppend (str, mParam.GetParamTag()); |
cfstr = str; |
} |
} |
SetTextValue(cfstr); |
CFRelease (cfstr); |
} |
break; |
} |
--mInControlInitialization; |
#endif |
} |
void AUCarbonViewControl::ControlToParameter() |
{ |
#if !__LP64__ |
if (mInControlInitialization) |
return; |
switch (mType) { |
case kTypeContinuous: |
{ |
double controlValue = GetValueFract(); |
Float32 paramValue = AUParameterValueFromLinear(controlValue, &mParam); |
mParam.SetValue(mListener, this, paramValue); |
} |
break; |
case kTypeDiscrete: |
{ |
long value = GetValue(); |
// special case [1] -- Menus |
if (mParam.HasNamedParams()) { |
// if we're dealing with menus they behave differently! |
// becaue setting min and max doesn't work correctly for the control value |
// first menu item always reports a control value of 1 |
ControlKind ctrlKind; |
if (GetControlKind(mControl, &ctrlKind) == noErr) { |
if ((ctrlKind.kind == kControlKindPopupArrow) |
|| (ctrlKind.kind == kControlKindPopupButton)) |
{ |
value = value + long(mParam.ParamInfo().minValue) - 1; |
} |
} |
} |
// special case [2] -- Write-only boolean parameters |
AudioUnitParameterInfo AUPI = mParam.ParamInfo(); |
bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) && |
(AUPI.flags & kAudioUnitParameterFlag_IsWritable) && |
!(AUPI.flags & kAudioUnitParameterFlag_IsReadable) ); |
if (isWriteOnlyBoolParameter) { |
value = 1; |
} |
mParam.SetValue (mListener, this, value); |
} |
break; |
case kTypeText: |
{ |
Float32 val = mParam.GetValueFromString (GetTextValue()); |
mParam.SetValue(mListener, this, (mParam.IsIndexedParam() ? (int)val : val)); |
if (mParam.ValuesHaveStrings()) |
ParameterToControl(val); //make sure we display the correct text (from the AU) |
} |
break; |
} |
#endif |
} |
void AUCarbonViewControl::SetValueFract(double value) |
{ |
#if !__LP64__ |
SInt32 minimum = GetControl32BitMinimum(mControl); |
SInt32 maximum = GetControl32BitMaximum(mControl); |
SInt32 cval = SInt32(value * (maximum - minimum) + minimum + 0.5); |
SetControl32BitValue(mControl, cval); |
// printf("set: value=%lf, min=%ld, max=%ld, ctl value=%ld\n", value, minimum, maximum, cval); |
#endif |
} |
double AUCarbonViewControl::GetValueFract() |
{ |
#if !__LP64__ |
SInt32 minimum = GetControl32BitMinimum(mControl); |
SInt32 maximum = GetControl32BitMaximum(mControl); |
SInt32 cval = GetControl32BitValue(mControl); |
double result = double(cval - minimum) / double(maximum - minimum); |
// printf("get: min=%ld, max=%ld, value=%ld, result=%f\n", minimum, maximum, cval, result); |
return result; |
#else |
return 0; |
#endif |
} |
void AUCarbonViewControl::SetTextValue(CFStringRef cfstr) |
{ |
#if !__LP64__ |
verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr)); |
#endif |
} |
CFStringRef AUCarbonViewControl::GetTextValue() |
{ |
#if !__LP64__ |
CFStringRef cfstr; |
verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL)); |
return cfstr; |
#else |
return CFSTR(""); |
#endif |
} |
void AUCarbonViewControl::SetValue(long value) |
{ |
#if !__LP64__ |
SetControl32BitValue(mControl, value); |
#endif |
} |
long AUCarbonViewControl::GetValue() |
{ |
#if !__LP64__ |
return GetControl32BitValue(mControl); |
#else |
return 0; |
#endif |
} |
/* Notes on event handling |
Button (Click and release on button) |
kEventControlClick received |
kEventControlTrack received |
kEventControlValueFieldChanged received |
kEventControlHit received |
Button (Click and release outside of button bounds) |
kEventControlClick received |
kEventControlTrack received |
Slider (Click, drag, and release) |
kEventControlClick received |
kEventControlTrack received |
kEventControlValueFieldChanged received |
kEventControlValueFieldChanged received |
kEventControlHit received |
Slider (Click, release without changing value) |
kEventControlClick received |
kEventControlTrack received |
*/ |
bool AUCarbonViewControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) |
{ |
UInt32 eclass = GetEventClass(event); |
UInt32 ekind = GetEventKind(event); |
ControlRef control; |
bool handled = true; |
switch (eclass) { |
case kEventClassControl: |
{ |
AudioUnitParameterInfo AUPI = mParam.ParamInfo(); |
bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) && |
(AUPI.flags & kAudioUnitParameterFlag_IsWritable) && |
!(AUPI.flags & kAudioUnitParameterFlag_IsReadable) ); |
switch (ekind) { |
case kEventControlSetFocusPart: // tab |
handled = !handled; // fall through to next case |
mLastControl = this; |
case kEventControlValueFieldChanged: |
GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control); |
verify(control == mControl); |
ControlToParameter(); |
return handled; |
case kEventControlClick: |
if (isWriteOnlyBoolParameter) { |
GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control); |
verify(control == mControl); |
ControlToParameter(); |
} else if (mLastControl != this) { |
if (mLastControl != NULL) { |
mLastControl->Update(false); |
} |
mLastControl = this; |
} |
mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseDownInControl, NULL); |
break; // don't return true, continue normal processing |
case kEventControlHit: |
if (mLastControl != this) { |
if (mLastControl != NULL) |
mLastControl->Update(false); |
mLastControl = this; |
} |
mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL); |
break; // don't return true, continue normal processing |
case kEventControlTrack: |
if (mLastControl != this) { |
if (mLastControl != NULL) |
mLastControl->Update(false); |
mLastControl = this; |
} |
CallNextEventHandler(inHandlerRef, event); |
ControlToParameter(); // new code |
mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL); |
// old code: |
// break; // don't return true, continue normal processing |
return handled; // don't return true, continue normal processing |
} |
} |
} |
return !handled; |
} |
pascal void AUCarbonViewControl::SliderTrackProc(ControlRef theControl, ControlPartCode partCode) |
{ |
// this doesn't need to actually do anything |
// AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl); |
} |
pascal ControlKeyFilterResult AUCarbonViewControl::StdKeyFilterCallback(ControlRef theControl, |
SInt16 *keyCode, SInt16 *charCode, |
EventModifiers *modifiers) |
{ |
#if !__LP64__ |
SInt16 c = *charCode; |
if (c >= ' ' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f) || c == '\t') |
return kControlKeyFilterPassKey; |
if (c == '\r' || c == 3) { // return or Enter |
AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl); |
ControlEditTextSelectionRec sel = { 0, 32767 }; |
SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel); |
This->ControlToParameter(); |
} |
#endif |
return kControlKeyFilterBlockKey; |
} |
pascal ControlKeyFilterResult AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl, |
SInt16 *keyCode, SInt16 *charCode, |
EventModifiers *modifiers) |
{ |
#if !__LP64__ |
SInt16 c = *charCode; |
if (isdigit(c) || c == '+' || c == '-' || c == '.' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f) |
|| c == '\t') |
return kControlKeyFilterPassKey; |
if (c == '\r' || c == 3) { // return or Enter |
AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl); |
ControlEditTextSelectionRec sel = { 0, 32767 }; |
SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel); |
This->ControlToParameter(); |
} |
#endif |
return kControlKeyFilterBlockKey; |
} |
Boolean AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight) |
{ |
#if !__LP64__ |
if (inControl == 0) return false; |
Boolean bValue = false; |
// this only works on text controls -- returns an error for other controls, but doesn't do anything, |
// so the error is irrelevant |
SetControlData(inControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue); |
SInt16 baseLineOffset; |
Rect bestRect; |
OSErr err = GetBestControlRect(inControl, &bestRect, &baseLineOffset); |
if (err != noErr) return false; |
int width = (bestRect.right - bestRect.left) + 1; |
int height = (bestRect.bottom - bestRect.top) + 1; |
Rect boundsRect; |
GetControlBounds (inControl, &boundsRect); |
Rect newRect; |
newRect.top = boundsRect.top; |
newRect.bottom = newRect.top + height; |
newRect.left = boundsRect.left; |
newRect.right = newRect.left + width; |
SetControlBounds (inControl, &newRect); |
if (outWidth) |
*outWidth = width; |
if (outHeight) |
*outHeight = height; |
#endif |
return true; |
} |
#pragma mark ___AUPropertyControl |
bool AUPropertyControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) |
{ |
UInt32 eclass = GetEventClass(event); |
UInt32 ekind = GetEventKind(event); |
switch (eclass) { |
case kEventClassControl: |
switch (ekind) { |
case kEventControlValueFieldChanged: |
HandleControlChange(); |
return true; // handled |
} |
} |
return false; |
} |
void AUPropertyControl::RegisterEvents () |
{ |
#if !__LP64__ |
EventTypeSpec events[] = { |
{ kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only |
}; |
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events); |
#endif |
} |
void AUPropertyControl::EmbedControl (ControlRef theControl) |
{ |
mView->EmbedControl (theControl); |
} |
WindowRef AUPropertyControl::GetCarbonWindow() |
{ |
return mView->GetCarbonWindow(); |
} |
#pragma mark ___AUVPreset |
#if !__LP64__ |
static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset; |
static bool sAUVPresetLocalized = false; |
#endif |
AUVPresets::AUVPresets (AUCarbonViewBase* inParentView, |
CFArrayRef& inPresets, |
Point inLocation, |
int nameWidth, |
int controlWidth, |
ControlFontStyleRec & inFontStyle) |
: AUPropertyControl (inParentView), |
mPresets (inPresets), |
mView (inParentView) |
{ |
#if !__LP64__ |
Rect r; |
// ok we now have an array of factory presets |
// get their strings and display them |
r.top = inLocation.v; r.bottom = r.top; |
r.left = inLocation.h; r.right = r.left; |
// localize as necessary |
if (!sAUVPresetLocalized) { |
CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView); |
if (mainBundle) { |
kStringFactoryPreset = CFCopyLocalizedStringFromTableInBundle( |
kAUViewLocalizedStringKey_FactoryPreset, kLocalizedStringTable_AUView, |
mainBundle, CFSTR("FactoryPreset title string")); |
sAUVPresetLocalized = true; |
} |
} |
// create localized title string |
CFMutableStringRef factoryPresetsTitle = CFStringCreateMutable(NULL, 0); |
CFStringAppend(factoryPresetsTitle, kStringFactoryPreset); |
CFStringAppend(factoryPresetsTitle, kAUViewUnlocalizedString_TitleSeparator); |
ControlRef theControl; |
verify_noerr(CreateStaticTextControl(mView->GetCarbonWindow(), &r, factoryPresetsTitle, &inFontStyle, &theControl)); |
SInt16 width = 0; |
AUCarbonViewControl::SizeControlToFit(theControl, &width, &mHeight); |
CFRelease(factoryPresetsTitle); |
EmbedControl(theControl); |
r.top -= 2; |
r.left += width + 10; |
r.right = r.left; |
r.bottom = r.top; |
verify_noerr(CreatePopupButtonControl ( mView->GetCarbonWindow(), &r, NULL, |
-12345, // DON'T GET MENU FROM RESOURCE mMenuID,!!! |
FALSE, // variableWidth, |
0, // titleWidth, |
0, // titleJustification, |
0, // titleStyle, |
&mControl)); |
MenuRef menuRef; |
verify_noerr(CreateNewMenu(1, 0, &menuRef)); |
int numPresets = CFArrayGetCount(mPresets); |
for (int i = 0; i < numPresets; ++i) |
{ |
AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i); |
verify_noerr(AppendMenuItemTextWithCFString (menuRef, preset->presetName, 0, 0, 0)); |
} |
verify_noerr(SetControlData(mControl, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef)); |
verify_noerr (SetControlFontStyle (mControl, &inFontStyle)); |
SetControl32BitMaximum (mControl, numPresets); |
// size popup |
SInt16 height = 0; |
AUCarbonViewControl::SizeControlToFit(mControl, &width, &height); |
if (height > mHeight) mHeight = height; |
if (mHeight < 0) mHeight = 0; |
// find which menu item is the Default preset |
UInt32 propertySize = sizeof(AUPreset); |
AUPreset defaultPreset; |
OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(), |
kAudioUnitProperty_PresentPreset, |
kAudioUnitScope_Global, |
0, |
&defaultPreset, |
&propertySize); |
mPropertyID = kAudioUnitProperty_PresentPreset; |
#endif |
#ifndef __LP64__ |
if (result != noErr) { // if the PresentPreset property is not implemented, fall back to the CurrentPreset property |
OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(), |
kAudioUnitProperty_CurrentPreset, |
kAudioUnitScope_Global, |
0, |
&defaultPreset, |
&propertySize); |
mPropertyID = kAudioUnitProperty_CurrentPreset; |
if (result == noErr) |
CFRetain (defaultPreset.presetName); |
} |
#endif |
#if !__LP64__ |
EmbedControl (mControl); |
HandlePropertyChange(defaultPreset); |
RegisterEvents(); |
#endif |
} |
void AUVPresets::AddInterest (AUEventListenerRef inListener, |
void * inObject) |
{ |
AudioUnitEvent e; |
e.mEventType = kAudioUnitEvent_PropertyChange; |
e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit(); |
e.mArgument.mProperty.mPropertyID = mPropertyID; |
e.mArgument.mProperty.mScope = kAudioUnitScope_Global; |
e.mArgument.mProperty.mElement = 0; |
AUEventListenerAddEventType(inListener, inObject, &e); |
} |
void AUVPresets::RemoveInterest (AUEventListenerRef inListener, |
void * inObject) |
{ |
AudioUnitEvent e; |
e.mEventType = kAudioUnitEvent_PropertyChange; |
e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit(); |
e.mArgument.mProperty.mPropertyID = mPropertyID; |
e.mArgument.mProperty.mScope = kAudioUnitScope_Global; |
e.mArgument.mProperty.mElement = 0; |
AUEventListenerRemoveEventType(inListener, inObject, &e); |
} |
void AUVPresets::HandleControlChange () |
{ |
#if !__LP64__ |
SInt32 i = GetControl32BitValue(mControl); |
if (i > 0) |
{ |
AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i-1); |
verify_noerr(AudioUnitSetProperty (mView->GetEditAudioUnit(), |
mPropertyID, // either currentPreset or PresentPreset depending on which is supported |
kAudioUnitScope_Global, |
0, |
preset, |
sizeof(AUPreset))); |
// when we change a preset we can't expect the AU to update its state |
// as it isn't meant to know that its being viewed! |
// so we broadcast a notification to all listeners that all parameters on this AU have changed |
AudioUnitParameter changedUnit; |
changedUnit.mAudioUnit = mView->GetEditAudioUnit(); |
changedUnit.mParameterID = kAUParameterListener_AnyParameter; |
verify_noerr (AUParameterListenerNotify (NULL, NULL, &changedUnit) ); |
} |
#endif |
} |
void AUVPresets::HandlePropertyChange(AUPreset &preset) |
{ |
#if !__LP64__ |
// check to see if the preset is in our menu |
int numPresets = CFArrayGetCount(mPresets); |
if (preset.presetNumber < 0) { |
SetControl32BitValue (mControl, 0); //controls are one-based |
} else { |
for (SInt32 i = 0; i < numPresets; ++i) { |
AUPreset* currPreset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i); |
if (preset.presetNumber == currPreset->presetNumber) { |
SetControl32BitValue (mControl, ++i); //controls are one-based |
break; |
} |
} |
} |
if (preset.presetName) |
CFRelease (preset.presetName); |
#endif |
} |
bool AUVPresets::HandlePropertyChange (const AudioUnitProperty &inProp) |
{ |
if (inProp.mPropertyID == mPropertyID) |
{ |
UInt32 theSize = sizeof(AUPreset); |
AUPreset currentPreset; |
OSStatus result = AudioUnitGetProperty(inProp.mAudioUnit, |
inProp.mPropertyID, |
inProp.mScope, |
inProp.mElement, ¤tPreset, &theSize); |
if (result == noErr) { |
#ifndef __LP64__ |
if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName) |
CFRetain (currentPreset.presetName); |
#endif |
HandlePropertyChange(currentPreset); |
return true; |
} |
} |
return false; |
} |
Copyright © 2014 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2014-07-08