Browse Source

Add CoreAudio 10.6 files

Signed-off-by: falkTX <falktx@gmail.com>
pull/116/head
falkTX 7 years ago
parent
commit
f73640618c
Signed by: falkTX <falktx@gmail.com> GPG Key ID: 2D3445A829213837
100 changed files with 25755 additions and 0 deletions
  1. +2124
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.cpp
  2. +893
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.h
  3. +477
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.cpp
  4. +71
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.h
  5. +146
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.cpp
  6. +111
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.h
  7. +56
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp
  8. +60
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.h
  9. +134
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUResources.r
  10. +506
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp
  11. +535
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h
  12. +189
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.cpp
  13. +226
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.h
  14. +386
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp
  15. +182
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h
  16. +667
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp
  17. +224
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h
  18. +119
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp
  19. +343
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp
  20. +84
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h
  21. +84
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp
  22. +65
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h
  23. +760
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp
  24. +246
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h
  25. +167
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h
  26. +266
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp
  27. +262
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h
  28. +140
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h
  29. +113
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp
  30. +170
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h
  31. +87
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp
  32. +226
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h
  33. +82
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h
  34. +483
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp
  35. +269
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.h
  36. +481
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp
  37. +207
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h
  38. +158
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp
  39. +83
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h
  40. +105
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp
  41. +76
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.h
  42. +700
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp
  43. +263
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.h
  44. +343
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp
  45. +123
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h
  46. +128
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp
  47. +74
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.h
  48. +203
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.cpp
  49. +261
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.h
  50. +423
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.cpp
  51. +131
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.h
  52. +149
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h
  53. +87
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUSilentTimeout.h
  54. +185
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp
  55. +148
    -0
      distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h
  56. +163
    -0
      distrho/src/CoreAudio106/PublicUtility/AUOutputBL.cpp
  57. +112
    -0
      distrho/src/CoreAudio106/PublicUtility/AUOutputBL.h
  58. +133
    -0
      distrho/src/CoreAudio106/PublicUtility/AUParamInfo.cpp
  59. +106
    -0
      distrho/src/CoreAudio106/PublicUtility/AUParamInfo.h
  60. +194
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.cpp
  61. +535
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.h
  62. +227
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.cpp
  63. +96
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.h
  64. +394
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp
  65. +185
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAUParameter.h
  66. +288
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAtomic.h
  67. +209
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h
  68. +225
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.cpp
  69. +93
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.h
  70. +142
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.cpp
  71. +191
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.h
  72. +193
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayoutObject.cpp
  73. +415
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.cpp
  74. +143
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.h
  75. +127
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.cpp
  76. +90
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.h
  77. +1257
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.cpp
  78. +417
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.h
  79. +137
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioUnitOutputCapturer.h
  80. +244
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.cpp
  81. +114
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.h
  82. +502
    -0
      distrho/src/CoreAudio106/PublicUtility/CAAutoDisposer.h
  83. +192
    -0
      distrho/src/CoreAudio106/PublicUtility/CABitOperations.h
  84. +82
    -0
      distrho/src/CoreAudio106/PublicUtility/CABool.h
  85. +252
    -0
      distrho/src/CoreAudio106/PublicUtility/CABufferList.cpp
  86. +298
    -0
      distrho/src/CoreAudio106/PublicUtility/CABufferList.h
  87. +78
    -0
      distrho/src/CoreAudio106/PublicUtility/CABundleLocker.cpp
  88. +61
    -0
      distrho/src/CoreAudio106/PublicUtility/CABundleLocker.h
  89. +155
    -0
      distrho/src/CoreAudio106/PublicUtility/CAByteOrder.h
  90. +788
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFArray.cpp
  91. +186
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFArray.h
  92. +101
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFData.h
  93. +561
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFDictionary.cpp
  94. +162
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFDictionary.h
  95. +100
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.cpp
  96. +67
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.h
  97. +138
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFMachPort.cpp
  98. +83
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFMachPort.h
  99. +129
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.cpp
  100. +109
    -0
      distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.h

+ 2124
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.cpp
File diff suppressed because it is too large
View File


+ 893
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUBase.h View File

@@ -0,0 +1,893 @@
/* 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.
*/
#ifndef __AUBase_h__
#define __AUBase_h__

#include <TargetConditionals.h>

#if TARGET_OS_MAC
#include <pthread.h>
#elif TARGET_OS_WIN32
#include <windows.h>
#else
#error Unsupported Operating System
#endif

#include <vector>

#include "ComponentBase.h"
#include "AUScopeElement.h"
#include "AUInputElement.h"
#include "AUOutputElement.h"
#include "AUBuffer.h"
#include "CAMath.h"
#include "CAThreadSafeList.h"
#include "CAVectorUnit.h"

#if 0 && DEBUG
#include "CATrace.h"
#else
#define CATRACE(code, a, b, c, d)
#endif

typedef AUElement AUGlobalElement;
#if !TARGET_OS_IPHONE
typedef AUElement AUGroupElement;
typedef AUElement AUPartElement;
#endif



// ________________________________________________________________________
// These are to be moved to the public AudioUnit headers

#define kAUDefaultSampleRate 44100.0
#if !TARGET_OS_WIN32
#define kAUDefaultMaxFramesPerSlice 1156
//this allows enough default frames for a 512 dest 44K and SRC from 96K
// add a padding of 4 frames for any altivec rounding
#else
#define kAUDefaultMaxFramesPerSlice 2048
#endif

class AUDebugDispatcher;

// ________________________________________________________________________

/*! @class AUBase */
class AUBase : public ComponentBase, public AUElementCreator {
public:

/*! @ctor AUBase */
AUBase( AudioComponentInstance inInstance,
UInt32 numInputElements,
UInt32 numOutputElements,
UInt32 numGroupElements = 0,
UInt32 numPartElements = 0);
/*! @dtor AUBase */
virtual ~AUBase();
/*! @method PostConstructor */
virtual void PostConstructor() { CreateElements(); }
/*! @method PreDestructor */
virtual void PreDestructor();

/*! @method CreateElements */
void CreateElements();
// Called immediately after construction, when virtual methods work.
// Or, a subclass may call this in order to have access to elements
// in its constructor.

// ________________________________________________________________________
// Virtual methods (mostly) directly corresponding to the entry points. Many of these
// have useful implementations here and will not need overriding.
/*! @method DoInitialize */
OSStatus DoInitialize();
// this implements the entry point and makes sure that initialization
// is only attempted exactly once...

/*! @method Initialize */
virtual OSStatus Initialize();
// ... so that overrides to this method can assume that they will only
// be called exactly once.
/*! @method IsInitialized */
bool IsInitialized() const { return mInitialized; }
/*! @method HasBegunInitializing */
bool HasBegunInitializing() const { return mHasBegunInitializing; }
/*! @method DoCleanup */
void DoCleanup();
// same pattern as with Initialize
/*! @method Cleanup */
virtual void Cleanup();

/*! @method Reset */
virtual OSStatus Reset( AudioUnitScope inScope,
AudioUnitElement inElement);

// Note about GetPropertyInfo, GetProperty, SetProperty:
// Certain properties are trapped out in these dispatch functions and handled with different virtual
// methods. (To discourage hacks and keep vtable size down, these are non-virtual)

/*! @method DispatchGetPropertyInfo */
OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method DispatchGetProperty */
OSStatus DispatchGetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);

/*! @method DispatchSetProperty */
OSStatus DispatchSetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
OSStatus DispatchRemovePropertyValue( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement);

/*! @method GetPropertyInfo */
virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method GetProperty */
virtual OSStatus GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);

/*! @method SetProperty */
virtual OSStatus SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
/*! @method ClearPropertyUsage */
virtual OSStatus RemovePropertyValue ( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement);

/*! @method AddPropertyListener */
virtual OSStatus AddPropertyListener( AudioUnitPropertyID inID,
AudioUnitPropertyListenerProc inProc,
void * inProcRefCon);
/*! @method RemovePropertyListener */
virtual OSStatus RemovePropertyListener( AudioUnitPropertyID inID,
AudioUnitPropertyListenerProc inProc,
void * inProcRefCon,
bool refConSpecified);
/*! @method SetRenderNotification */
virtual OSStatus SetRenderNotification( AURenderCallback inProc,
void * inRefCon);
/*! @method RemoveRenderNotification */
virtual OSStatus RemoveRenderNotification(
AURenderCallback inProc,
void * inRefCon);
/*! @method GetParameter */
virtual OSStatus GetParameter( AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
AudioUnitParameterValue & outValue);
/*! @method SetParameter */
virtual OSStatus SetParameter( AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
AudioUnitParameterValue inValue,
UInt32 inBufferOffsetInFrames);

#if !TARGET_OS_IPHONE
/*! @method SetGroupParameter */
virtual OSStatus SetGroupParameter( AudioUnitParameterID inID,
AudioUnitElement inElement,
AudioUnitParameterValue inValue,
UInt32 inBufferOffsetInFrames);

/*! @method GetGroupParameter */
virtual OSStatus GetGroupParameter( AudioUnitParameterID inID,
AudioUnitElement inElement,
AudioUnitParameterValue & outValue);
#endif

/*! @method ScheduleParameter */
virtual OSStatus ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent,
UInt32 inNumEvents);

/*! @method DoRender */
OSStatus DoRender( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList & ioData);

// Override this method if your AU processes multiple output busses completely independently --
// you'll want to just call Render without the NeedsToRender check.
// Otherwise, override Render().
//
// N.B. Implementations of this method can assume that the output's buffer list has already been
// prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
// GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
// copy may occur after rendering.
/*! @method RenderBus */
virtual OSStatus RenderBus( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames)
{
if (NeedsToRender(inTimeStamp.mSampleTime))
return Render(ioActionFlags, inTimeStamp, inNumberFrames);
return noErr; // was presumably already rendered via another bus
}

// N.B. For a unit with only one output bus, it can assume in its implementation of this
// method that the output's buffer list has already been prepared and access it with
// GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
// -- if PrepareBuffer is called, a copy may occur after rendering.
/*! @method Render */
virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
return noErr;
}

static const Float64 kNoLastRenderedSampleTime;

// ________________________________________________________________________
// These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty

/*! @method BusCountWritable */
virtual bool BusCountWritable( AudioUnitScope inScope)
{
return false;
}
virtual OSStatus SetBusCount( AudioUnitScope inScope,
UInt32 inCount);

/*! @method SetConnection */
virtual OSStatus SetConnection( const AudioUnitConnection & inConnection);
/*! @method SetInputCallback */
virtual OSStatus SetInputCallback( UInt32 inPropertyID,
AudioUnitElement inElement,
AURenderCallback inProc,
void * inRefCon);

/*! @method GetParameterList */
virtual OSStatus GetParameterList( AudioUnitScope inScope,
AudioUnitParameterID * outParameterList,
UInt32 & outNumParameters);
// outParameterList may be a null pointer

/*! @method GetParameterInfo */
virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo & outParameterInfo);

/*! @method SaveState */
virtual OSStatus SaveState( CFPropertyListRef * outData);

/*! @method RestoreState */
virtual OSStatus RestoreState( CFPropertyListRef inData);

/*! @method GetParameterValueStrings */
virtual OSStatus GetParameterValueStrings(AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
CFArrayRef * outStrings);

/*! @method CopyClumpName */
virtual OSStatus CopyClumpName( AudioUnitScope inScope,
UInt32 inClumpID,
UInt32 inDesiredNameLength,
CFStringRef * outClumpName);

/*! @method GetPresets */
virtual OSStatus GetPresets ( CFArrayRef * outData) const;

// set the default preset for the unit -> the number of the preset MUST be >= 0
// and the name should be valid, or the preset WON'T take
/*! @method SetAFactoryPresetAsCurrent */
bool SetAFactoryPresetAsCurrent (const AUPreset & inPreset);
// Called when someone sets a new, valid preset
// If this is a valid preset, then the subclass sets its state to that preset
// and returns noErr.
// If not a valid preset, return an error, and the pre-existing preset is restored
/*! @method NewFactoryPresetSet */
virtual OSStatus NewFactoryPresetSet (const AUPreset & inNewFactoryPreset);

/*! @method GetNumCustomUIComponents */
virtual int GetNumCustomUIComponents ();
#if !TARGET_OS_IPHONE
/*! @method GetUIComponentDescs */
virtual void GetUIComponentDescs (ComponentDescription* inDescArray);
#endif
/*! @method CopyIconLocation */
virtual CFURLRef CopyIconLocation ();
// default is no latency, and unimplemented tail time
/*! @method GetLatency */
virtual Float64 GetLatency() {return 0.0;}
/*! @method GetTailTime */
virtual Float64 GetTailTime() {return 0;}
/*! @method SupportsRampAndTail */
virtual bool SupportsTail () { return false; }

/*! @method IsStreamFormatWritable */
bool IsStreamFormatWritable( AudioUnitScope scope,
AudioUnitElement element);
/*! @method StreamFormatWritable */
virtual bool StreamFormatWritable( AudioUnitScope scope,
AudioUnitElement element) = 0;
// scope will always be input or output
// pass in a pointer to get the struct, and num channel infos
// you can pass in NULL to just get the number
// a return value of 0 (the default in AUBase) means the property is not supported...
/*! @method SupportedNumChannels */
virtual UInt32 SupportedNumChannels ( const AUChannelInfo** outInfo);
/*! @method ValidFormat */
virtual bool ValidFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inNewFormat);
// Will only be called after StreamFormatWritable
// has succeeded.
// Default implementation requires canonical format:
// native-endian 32-bit float, any sample rate,
// any number of channels; override when other
// formats are supported. A subclass's override can
// choose to always return true and trap invalid
// formats in ChangeStreamFormat.


/*! @method FormatIsCanonical */
bool FormatIsCanonical( const CAStreamBasicDescription &format);

/*! @method MakeCanonicalFormat */
void MakeCanonicalFormat( CAStreamBasicDescription & outDesc,
int numChannels = 2);

/*! @method GetStreamFormat */
virtual const CAStreamBasicDescription &
GetStreamFormat( AudioUnitScope inScope,
AudioUnitElement inElement);

/*! @method ChangeStreamFormat */
virtual OSStatus ChangeStreamFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat);
// Will only be called after StreamFormatWritable
// and ValidFormat have succeeded.
// ________________________________________________________________________

#if !TARGET_OS_IPHONE
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
AUBase * This);
#endif

// ________________________________________________________________________
// Methods useful for subclasses
/*! @method GetScope */
AUScope & GetScope( AudioUnitScope inScope)
{
if (inScope >= kNumScopes) COMPONENT_THROW(kAudioUnitErr_InvalidScope);
return mScopes[inScope];
}
/*! @method GlobalScope */
AUScope & GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
/*! @method Inputs */
AUScope & Inputs() { return mScopes[kAudioUnitScope_Input]; }
/*! @method Outputs */
AUScope & Outputs() { return mScopes[kAudioUnitScope_Output]; }
/*! @method Groups */
#if !TARGET_OS_IPHONE
AUScope & Groups() { return mScopes[kAudioUnitScope_Group]; }
/*! @method Parts */
AUScope & Parts() { return mScopes[kAudioUnitScope_Part]; }
#endif
/*! @method Globals */
AUElement * Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); }
/*! @method SetNumberOfElements */
void SetNumberOfElements( AudioUnitScope inScope,
UInt32 numElements);

/*! @method GetElement */
AUElement * GetElement( AudioUnitScope inScope,
AudioUnitElement inElement)
{
return GetScope(inScope).GetElement(inElement);
}
/*! @method GetIOElement */
AUIOElement * GetIOElement( AudioUnitScope inScope,
AudioUnitElement inElement)
{
return GetScope(inScope).GetIOElement(inElement);
}
/*! @method SafeGetElement */
AUElement * SafeGetElement( AudioUnitScope inScope,
AudioUnitElement inElement)
{
return GetScope(inScope).SafeGetElement(inElement);
}

/*! @method GetInput */
AUInputElement * GetInput( AudioUnitElement inElement)
{
return static_cast<AUInputElement *>(Inputs().SafeGetElement(inElement));
}
/*! @method GetOutput */
AUOutputElement * GetOutput( AudioUnitElement inElement)
{
return static_cast<AUOutputElement *>(Outputs().SafeGetElement(inElement));
}
#if !TARGET_OS_IPHONE
/*! @method GetGroup */
AUGroupElement * GetGroup( AudioUnitElement inElement)
{
return static_cast<AUGroupElement *>(Groups().SafeGetElement(inElement));
}
#endif
/*! @method PullInput */
OSStatus PullInput( UInt32 inBusNumber,
AudioUnitRenderActionFlags &ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
AUInputElement *input = GetInput(inBusNumber); // throws if error
return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
}

/*! @method GetMaxFramesPerSlice */
UInt32 GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; }
/*! @method GetVectorUnitType */
static SInt32 GetVectorUnitType() { return sVectorUnitType; }
/*! @method HasVectorUnit */
static bool HasVectorUnit() { return sVectorUnitType > 0; }
/*! @method HasAltivec */
static bool HasAltivec() { return sVectorUnitType == kVecAltivec; }
/*! @method HasSSE2 */
static bool HasSSE2() { return sVectorUnitType >= kVecSSE2; }
/*! @method HasSSE3 */
static bool HasSSE3() { return sVectorUnitType == kVecSSE3; }
/*! @method AudioUnitAPIVersion */
UInt8 AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; }
/*! @method IsRenderThread */
bool InRenderThread () const
{
#if TARGET_OS_MAC
return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false);
#elif TARGET_OS_WIN32
return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false);
#endif
}

/*! @method HasInput */
bool HasInput( AudioUnitElement inElement) {
AUInputElement *in = static_cast<AUInputElement *>(Inputs().GetElement(inElement));
return in != NULL && in->IsActive();
}
// says whether an input is connected or has a callback

/*! @method PropertyChanged */
void PropertyChanged( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement);

#if !TARGET_OS_IPHONE
// These calls can be used to call a Host's Callbacks. The method returns -1 if the host
// hasn't supplied the callback. Any other result is returned by the host.
// As in the API contract, for a parameter's value, you specify a pointer
// to that data type. Specify NULL for a parameter that you are not interested
// as this can save work in the host.

/*! @method CallHostBeatAndTempo */
OSStatus CallHostBeatAndTempo (Float64 *outCurrentBeat,
Float64 *outCurrentTempo)
{
return (mHostCallbackInfo.beatAndTempoProc
? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData,
outCurrentBeat,
outCurrentTempo)
: -1);
}

/*! @method CallHostMusicalTimeLocation */
OSStatus CallHostMusicalTimeLocation (UInt32 *outDeltaSampleOffsetToNextBeat,
Float32 *outTimeSig_Numerator,
UInt32 *outTimeSig_Denominator,
Float64 *outCurrentMeasureDownBeat)
{
return (mHostCallbackInfo.musicalTimeLocationProc
? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData,
outDeltaSampleOffsetToNextBeat,
outTimeSig_Numerator,
outTimeSig_Denominator,
outCurrentMeasureDownBeat)
: -1);
}

/*! @method CallHostTransportState */
OSStatus CallHostTransportState (Boolean *outIsPlaying,
Boolean *outTransportStateChanged,
Float64 *outCurrentSampleInTimeLine,
Boolean *outIsCycling,
Float64 *outCycleStartBeat,
Float64 *outCycleEndBeat)
{
return (mHostCallbackInfo.transportStateProc
? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData,
outIsPlaying,
outTransportStateChanged,
outCurrentSampleInTimeLine,
outIsCycling,
outCycleStartBeat,
outCycleEndBeat)
: -1);
}
#endif

char* GetLoggingString () const;
protected:
// ________________________________________________________________________
// AUElementCreator override, may be further overridden by subclasses
/*! @method CreateElement */
virtual AUElement * CreateElement( AudioUnitScope scope,
AudioUnitElement element);
/*! @method ReallocateBuffers */
virtual void ReallocateBuffers();
// needs to be called when mMaxFramesPerSlice changes
/*! @method FillInParameterName */
static void FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
{
ioInfo.cfNameString = inName;
ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
if (inShouldRelease)
ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8);
}
static void HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID)
{
ioInfo.clumpID = inClumpID;
ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
}
/*! @method SetMaxFramesPerSlice */
virtual void SetMaxFramesPerSlice(UInt32 nFrames);

/*! @method CanSetMaxFrames */
virtual OSStatus CanSetMaxFrames() const;
/*! @method WantsRenderThreadID */
bool WantsRenderThreadID () const { return mWantsRenderThreadID; }
/*! @method SetWantsRenderThreadID */
void SetWantsRenderThreadID (bool inFlag);
/*! @method SetRenderError */
OSStatus SetRenderError (OSStatus inErr)
{
if (inErr && mLastRenderError == 0) {
mLastRenderError = inErr;
PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
}
return inErr;
}
private:
/*! @method DoRenderBus */
// shared between Render and RenderSlice, inlined to minimize function call overhead
OSStatus DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inBusNumber,
AUOutputElement * theOutput,
UInt32 inNumberFrames,
AudioBufferList & ioData)
{
if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1))
// will render into cache buffer
theOutput->PrepareBuffer(inNumberFrames);
else
// will render into caller's buffer
theOutput->SetBufferList(ioData);
OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
if (result == noErr) {
if (ioData.mBuffers[0].mData == NULL) {
theOutput->CopyBufferListTo(ioData);
CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (int)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData);
} else {
theOutput->CopyBufferContentsTo(ioData);
CATRACE(kCATrace_AUBaseDoRenderBus, inNumberFrames, (int)theOutput->GetBufferList().mBuffers[0].mData, (int)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData);
theOutput->InvalidateBufferList();
}
}
return result;
}

/*! @method HasIcon */
bool HasIcon ();

protected:
/*! @method GetAudioChannelLayout */
virtual UInt32 GetChannelLayoutTags( AudioUnitScope scope,
AudioUnitElement element,
AudioChannelLayoutTag * outLayoutTags);
/*! @method GetAudioChannelLayout */
virtual UInt32 GetAudioChannelLayout( AudioUnitScope scope,
AudioUnitElement element,
AudioChannelLayout * outLayoutPtr,
Boolean & outWritable);

/*! @method SetAudioChannelLayout */
virtual OSStatus SetAudioChannelLayout( AudioUnitScope scope,
AudioUnitElement element,
const AudioChannelLayout * inLayout);

/*! @method RemoveAudioChannelLayout */
virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);
/*! @method NeedsToRender */
bool NeedsToRender( Float64 inSampleTime)
{
bool needsToRender = fnotequal(inSampleTime, mLastRenderedSampleTime);
mLastRenderedSampleTime = inSampleTime;
return needsToRender;
}
// Scheduled parameter implementation:

typedef std::vector<AudioUnitParameterEvent> ParameterEventList;

// Usually, you won't override this method. You only need to call this if your DSP code
// is prepared to handle scheduled immediate and ramped parameter changes.
// Before calling this method, it is assumed you have already called PullInput() on the input busses
// for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly)
// virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of
// the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller
// pieces according to the scheduled times found in the ParameterEventList (usually coming
// directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or
// ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice()
// to do the actual DSP for each of these divisions.
virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList,
UInt32 inFramesToProcess,
void *inUserData );
// This method is called (potentially repeatedly) by ProcessForScheduledParams()
// in order to perform the actual DSP required for this portion of the entire buffer
// being processed. The entire buffer can be divided up into smaller "slices"
// according to the timestamps on the scheduled parameters...
//
// sub-classes wishing to handle scheduled parameter changes should override this method
// in order to do the appropriate DSP. AUEffectBase already overrides this for standard
// effect AudioUnits.
virtual OSStatus ProcessScheduledSlice( void *inUserData,
UInt32 inStartFrameInBuffer,
UInt32 inSliceFramesToProcess,
UInt32 inTotalBufferFrames ) {return noErr;}; // default impl does nothing...

// ________________________________________________________________________
// Private data members to discourage hacking in subclasses
private:
struct RenderCallback {
RenderCallback(AURenderCallback proc, void *ref) :
mRenderNotify(proc),
mRenderNotifyRefCon(ref)
{ }
AURenderCallback mRenderNotify;
void * mRenderNotifyRefCon;
bool operator == (const RenderCallback &other) {
return this->mRenderNotify == other.mRenderNotify &&
this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
}
};
typedef TThreadSafeList<RenderCallback> RenderCallbackList;
#if TARGET_OS_IPHONE
enum { kNumScopes = 3 };
#else
enum { kNumScopes = 5 };
#endif
/*! @var mElementsCreated */
bool mElementsCreated;
protected:
/*! @var mInitialized */
bool mInitialized;
/*! @var mHasBegunInitializing */
bool mHasBegunInitializing;
private:
/*! @var mAudioUnitAPIVersion */
UInt8 mAudioUnitAPIVersion;
/*! @var mInitNumInputEls */
UInt32 mInitNumInputEls;
/*! @var mInitNumOutputEls */
UInt32 mInitNumOutputEls;
#if !TARGET_OS_IPHONE
/*! @var mInitNumGroupEls */
UInt32 mInitNumGroupEls;
/*! @var mInitNumPartEls */
UInt32 mInitNumPartEls;
#endif
/*! @var mScopes */
AUScope mScopes[kNumScopes];
/*! @var mRenderCallbacks */
RenderCallbackList mRenderCallbacks;
bool mRenderCallbacksTouched;
/*! @var mRenderThreadID */
#if TARGET_OS_MAC
pthread_t mRenderThreadID;
#elif TARGET_OS_WIN32
UInt32 mRenderThreadID;
#endif
/*! @var mWantsRenderThreadID */
bool mWantsRenderThreadID;
/*! @var mLastRenderedSampleTime */
Float64 mLastRenderedSampleTime;
/*! @var mMaxFramesPerSlice */
UInt32 mMaxFramesPerSlice;
/*! @var mLastRenderError */
OSStatus mLastRenderError;
/*! @var mCurrentPreset */
AUPreset mCurrentPreset;
protected:
struct PropertyListener {
AudioUnitPropertyID propertyID;
AudioUnitPropertyListenerProc listenerProc;
void * listenerRefCon;
};
typedef std::vector<PropertyListener> PropertyListeners;

/*! @var mParamList */
ParameterEventList mParamList;
/*! @var mPropertyListeners */
PropertyListeners mPropertyListeners;
/*! @var mBuffersAllocated */
bool mBuffersAllocated;
/*! @var mLogString */
// if this is NOT null, it will contain identifying info about this AU.
char* mLogString;

private:
/*! @var sVectorUnitType */
static SInt32 sVectorUnitType;

#if !TARGET_OS_IPHONE
protected:
/*! @var mHostCallbackInfo */
HostCallbackInfo mHostCallbackInfo;

/*! @var mContextInfo */
CFStringRef mContextName;

public:
AUDebugDispatcher* mDebugDispatcher;
#endif
};

inline OSStatus AUInputElement::PullInputWithBufferList(
AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 nFrames,
AudioBufferList * inBufferList)
{
OSStatus theResult;
if (HasConnection()) {
// only support connections for V2 audio units
#if !TARGET_OS_IPHONE
if (mConnRenderProc != NULL)
theResult = reinterpret_cast<AudioUnitRenderProc>(mConnRenderProc)(
mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
else
#endif
theResult = AudioUnitRender(
mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList);
} else {
// kFromCallback:
theResult = (mInputProc)(
mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList);
}
if (mInputType == kNoInput) // defense: the guy upstream could have disconnected
// it's a horrible thing to do, but may happen!
return kAudioUnitErr_NoConnection;


return theResult;
}

#endif // __AUBase_h__

+ 477
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.cpp View File

@@ -0,0 +1,477 @@
/* 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 "AUBase.h"
#include "CAXException.h"



#if TARGET_OS_MAC
#if __LP64__
// comp instance, parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index + 1];
#else
// parameters in reverse order, then comp instance
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
#endif
#elif TARGET_OS_WIN32
// (no comp instance), parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index];
#endif


#if AU_DEBUG_DISPATCHER
#include "AUDebugDispatcher.h"

#define INIT_DEBUG_DISPATCHER(This) \
UInt64 nowTime = 0; \
if (This->mDebugDispatcher != NULL) \
nowTime = CAHostTimeBase::GetTheCurrentTime();
#endif

OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
{
if (This == NULL) return paramErr;

#if AU_DEBUG_DISPATCHER
INIT_DEBUG_DISPATCHER(This)
#endif
OSStatus result = noErr;

switch (params->what) {
case kComponentCanDoSelect:
switch (params->params[0]) {
// any selectors
case kAudioUnitInitializeSelect:
case kAudioUnitUninitializeSelect:
case kAudioUnitGetPropertyInfoSelect:
case kAudioUnitGetPropertySelect:
case kAudioUnitSetPropertySelect:
case kAudioUnitAddPropertyListenerSelect:
#if (!__LP64__)
case kAudioUnitRemovePropertyListenerSelect:
#endif
case kAudioUnitGetParameterSelect:
case kAudioUnitSetParameterSelect:
case kAudioUnitResetSelect:
result = 1;
break;
// v1 selectors

// v2 selectors
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
case kAudioUnitAddRenderNotifySelect:
case kAudioUnitRemoveRenderNotifySelect:
case kAudioUnitScheduleParametersSelect:
case kAudioUnitRenderSelect:
result = (This->AudioUnitAPIVersion() > 1);
break;
default:
return ComponentBase::ComponentEntryDispatch(params, This);
}
break;
case kAudioUnitInitializeSelect:
{
result = This->DoInitialize();

#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->Initialize (nowTime, result);
#endif
}
break;
case kAudioUnitUninitializeSelect:
{
This->DoCleanup();
result = noErr;

#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->Uninitialize (nowTime, result);
#endif
}
break;

case kAudioUnitGetPropertyInfoSelect:
{
PARAM(AudioUnitPropertyID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(UInt32 *, poutDataSize, 3, 5);
PARAM(Boolean *, poutWritable, 4, 5);

// pass our own copies so that we assume responsibility for testing
// the caller's pointers against null and our C++ classes can
// always assume they're non-null
UInt32 dataSize;
Boolean writable;
result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
if (poutDataSize != NULL)
*poutDataSize = dataSize;
if (poutWritable != NULL)
*poutWritable = writable;

#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->GetPropertyInfo (nowTime, result, pinID, pinScope, pinElement,
poutDataSize, poutWritable);
#endif
}
break;

case kAudioUnitGetPropertySelect:
{
PARAM(AudioUnitPropertyID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(void *, poutData, 3, 5);
PARAM(UInt32 *, pioDataSize, 4, 5);

UInt32 actualPropertySize, clientBufferSize;
Boolean writable;
char *tempBuffer;
void *destBuffer;
if (pioDataSize == NULL) {
ca_debug_string("AudioUnitGetProperty: null size pointer");
result = paramErr;
goto finishGetProperty;
}
if (poutData == NULL) {
UInt32 dataSize;
Boolean writable;
result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
*pioDataSize = dataSize;
goto finishGetProperty;
}
clientBufferSize = *pioDataSize;
if (clientBufferSize == 0)
{
ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
// $$$ or should we allow this as a shortcut for finding the size?
result = paramErr;
goto finishGetProperty;
}
result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement,
actualPropertySize, writable);
if (result)
goto finishGetProperty;
if (clientBufferSize < actualPropertySize)
{
tempBuffer = new char[actualPropertySize];
destBuffer = tempBuffer;
} else {
tempBuffer = NULL;
destBuffer = poutData;
}
result = This->DispatchGetProperty(pinID, pinScope, pinElement, destBuffer);
if (result == noErr) {
if (clientBufferSize < actualPropertySize)
{
memcpy(poutData, tempBuffer, clientBufferSize);
delete[] tempBuffer;
// pioDataSize remains correct, the number of bytes we wrote
} else
*pioDataSize = actualPropertySize;
} else
*pioDataSize = 0;

finishGetProperty:
#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->GetProperty (nowTime, result, pinID, pinScope, pinElement,
pioDataSize, poutData);
#else
;
#endif

}
break;
case kAudioUnitSetPropertySelect:
{
PARAM(AudioUnitPropertyID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(const void *, pinData, 3, 5);
PARAM(UInt32, pinDataSize, 4, 5);
if (pinData && pinDataSize)
result = This->DispatchSetProperty(pinID, pinScope, pinElement, pinData, pinDataSize);
else {
if (pinData == NULL && pinDataSize == 0) {
result = This->DispatchRemovePropertyValue (pinID, pinScope, pinElement);
} else {
if (pinData == NULL) {
ca_debug_string("AudioUnitSetProperty: inData == NULL");
result = paramErr;
goto finishSetProperty;
}

if (pinDataSize == 0) {
ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
result = paramErr;
goto finishSetProperty;
}
}
}
finishSetProperty:
#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->SetProperty (nowTime, result, pinID, pinScope, pinElement,
pinData, pinDataSize);
#else
;
#endif

}
break;
case kAudioUnitAddPropertyListenerSelect:
{
PARAM(AudioUnitPropertyID, pinID, 0, 3);
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
PARAM(void *, pinProcRefCon, 2, 3);
result = This->AddPropertyListener(pinID, pinProc, pinProcRefCon);
}
break;

#if (!__LP64__)
case kAudioUnitRemovePropertyListenerSelect:
{
PARAM(AudioUnitPropertyID, pinID, 0, 2);
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
}
break;
#endif

case kAudioUnitRemovePropertyListenerWithUserDataSelect:
{
PARAM(AudioUnitPropertyID, pinID, 0, 3);
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
PARAM(void *, pinProcRefCon, 2, 3);
result = This->RemovePropertyListener(pinID, pinProc, pinProcRefCon, true);
}
break;
case kAudioUnitAddRenderNotifySelect:
{
PARAM(AURenderCallback, pinProc, 0, 2);
PARAM(void *, pinProcRefCon, 1, 2);
result = This->SetRenderNotification (pinProc, pinProcRefCon);
}
break;

case kAudioUnitRemoveRenderNotifySelect:
{
PARAM(AURenderCallback, pinProc, 0, 2);
PARAM(void *, pinProcRefCon, 1, 2);
result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
}
break;

case kAudioUnitGetParameterSelect:
{
PARAM(AudioUnitParameterID, pinID, 0, 4);
PARAM(AudioUnitScope, pinScope, 1, 4);
PARAM(AudioUnitElement, pinElement, 2, 4);
PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
result = (poutValue == NULL ? paramErr : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
}
break;

case kAudioUnitSetParameterSelect:
{
PARAM(AudioUnitParameterID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(AudioUnitParameterValue, pinValue, 3, 5);
PARAM(UInt32, pinBufferOffsetInFrames, 4, 5);
result = This->SetParameter(pinID, pinScope, pinElement, pinValue, pinBufferOffsetInFrames);
}
break;

case kAudioUnitScheduleParametersSelect:
{
if (This->AudioUnitAPIVersion() > 1)
{
PARAM(AudioUnitParameterEvent *, pinParameterEvent, 0, 2);
PARAM(UInt32, pinNumParamEvents, 1, 2);
result = This->ScheduleParameter (pinParameterEvent, pinNumParamEvents);
} else
result = badComponentSelector;
}
break;


case kAudioUnitRenderSelect:
{
{
PARAM(AudioUnitRenderActionFlags *, pinActionFlags, 0, 5);
PARAM(const AudioTimeStamp *, pinTimeStamp, 1, 5);
PARAM(UInt32, pinOutputBusNumber, 2, 5);
PARAM(UInt32, pinNumberFrames, 3, 5);
PARAM(AudioBufferList *, pioData, 4, 5);
AudioUnitRenderActionFlags tempFlags;
if (pinTimeStamp == NULL || pioData == NULL)
result = paramErr;
else {
if (pinActionFlags == NULL) {
tempFlags = 0;
pinActionFlags = &tempFlags;
}
result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
}
#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->Render (nowTime, result, pinActionFlags, pinTimeStamp,
pinOutputBusNumber, pinNumberFrames, pioData);
#endif
}
}
break;

case kAudioUnitResetSelect:
{
PARAM(AudioUnitScope, pinScope, 0, 2);
PARAM(AudioUnitElement, pinElement, 1, 2);
This->mLastRenderedSampleTime = -1;
result = This->Reset(pinScope, pinElement);
}
break;

default:
result = ComponentBase::ComponentEntryDispatch(params, This);
break;
}

return result;
}

// Fast dispatch entry points -- these need to replicate all error-checking logic from above

OSStatus AudioUnitBaseGetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float *outValue)
{
OSStatus result = AUBase::noErr;
try {
if (This == NULL || outValue == NULL) return AUBase::paramErr;
result = This->GetParameter(inID, inScope, inElement, *outValue);
}
COMPONENT_CATCH
return result;
}

OSStatus AudioUnitBaseSetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float inValue,
UInt32 inBufferOffset)
{
OSStatus result = AUBase::noErr;
try {
if (This == NULL) return AUBase::paramErr;
result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
}
COMPONENT_CATCH
return result;
}

OSStatus AudioUnitBaseRender( AUBase * This,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
if (inTimeStamp == NULL || ioData == NULL) return AUBase::paramErr;

#if AU_DEBUG_DISPATCHER
INIT_DEBUG_DISPATCHER(This)
#endif
OSStatus result = AUBase::noErr;
AudioUnitRenderActionFlags tempFlags;
try {
if (ioActionFlags == NULL) {
tempFlags = 0;
ioActionFlags = &tempFlags;
}
result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
}
COMPONENT_CATCH

#if AU_DEBUG_DISPATCHER
if (This->mDebugDispatcher)
This->mDebugDispatcher->Render (nowTime, result, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
#endif
return result;
}

+ 71
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUDispatch.h View File

@@ -0,0 +1,71 @@
/* 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.
*/
#ifndef __AUDispatch_h__
#define __AUDispatch_h__

// Fast dispatch function prototypes

#include <TargetConditionals.h>

/*! @function AudioUnitBaseGetParameter */
OSStatus AudioUnitBaseGetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float * outValue);

/*! @function AudioUnitBaseSetParameter */
OSStatus AudioUnitBaseSetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float inValue,
UInt32 inBufferOffset);

/*! @function AudioUnitBaseRender */
OSStatus AudioUnitBaseRender( AUBase * This,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);

#endif // __AUDispatch_h__

+ 146
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.cpp View File

@@ -0,0 +1,146 @@
/* 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 "AUBase.h"

inline bool HasGoodBufferPointers(const AudioBufferList &abl, UInt32 nBytes)
{
const AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = abl.mNumberBuffers; i--;++buf) {
if (buf->mData == NULL || buf->mDataByteSize < nBytes)
return false;
}
return true;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::AUInputElement
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AUInputElement::AUInputElement(AUBase *audioUnit) :
AUIOElement(audioUnit),
mInputType(kNoInput)
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::SetConnection
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AUInputElement::SetConnection(const AudioUnitConnection &conn)
{
if (conn.sourceAudioUnit == 0) {
Disconnect();
return;
}
mInputType = kFromConnection;
mConnection = conn;
mConnRenderProc = NULL;
AllocateBuffer();

#if !CA_AU_IS_ONLY_PLUGIN
UInt32 size = sizeof(AudioUnitRenderProc);
OSStatus result = AudioUnitGetProperty( conn.sourceAudioUnit,
kAudioUnitProperty_FastDispatch,
kAudioUnitScope_Global,
kAudioUnitRenderSelect,
&mConnRenderProc,
&size);
if (result == noErr)
mConnInstanceStorage = GetComponentInstanceStorage (conn.sourceAudioUnit);
else
mConnRenderProc = NULL;
#else // !TARGET_OS_IPHONE
mConnInstanceStorage = NULL;
mConnRenderProc = NULL;
#endif
}

void AUInputElement::Disconnect()
{
mInputType = kNoInput;
mIOBuffer.Deallocate();
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::SetInputCallback
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AUInputElement::SetInputCallback(AURenderCallback proc, void *refCon)
{
if (proc == NULL)
Disconnect();
else {
mInputType = kFromCallback;
mInputProc = proc;
mInputProcRefCon = refCon;
AllocateBuffer();
}
}

OSStatus AUInputElement::SetStreamFormat(const CAStreamBasicDescription &fmt)
{
OSStatus err = AUIOElement::SetStreamFormat(fmt);
if (err == AUBase::noErr)
AllocateBuffer();
return err;
}

OSStatus AUInputElement::PullInput( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 nFrames)
{
if (!IsActive())
return kAudioUnitErr_NoConnection;
AudioBufferList *pullBuffer;
if (HasConnection() || !WillAllocateBuffer())
pullBuffer = &mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
else
pullBuffer = &mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
return PullInputWithBufferList (ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer);
}

+ 111
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUInputElement.h View File

@@ -0,0 +1,111 @@
/* 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.
*/
#ifndef __AUInput_h__
#define __AUInput_h__

#include "AUScopeElement.h"
#include "AUBuffer.h"

/*! @class AUInputElement */
class AUInputElement : public AUIOElement {
public:
/*! @ctor AUInputElement */
AUInputElement(AUBase *audioUnit);
/*! @dtor ~AUInputElement */
virtual ~AUInputElement() { }

// AUElement override
/*! @method SetStreamFormat */
virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
/*! @method NeedsBufferSpace */
virtual bool NeedsBufferSpace() const { return IsCallback(); }

/*! @method SetConnection */
void SetConnection(const AudioUnitConnection &conn);
/*! @method SetInputCallback */
void SetInputCallback(AURenderCallback proc, void *refCon);

/*! @method IsActive */
bool IsActive() const { return mInputType != kNoInput; }
/*! @method IsCallback */
bool IsCallback() const { return mInputType == kFromCallback; }
/*! @method HasConnection */
bool HasConnection() const { return mInputType == kFromConnection; }

/*! @method PullInput */
OSStatus PullInput( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 inNumberFrames);

/*! @method PullInputWithBufferList */
OSStatus PullInputWithBufferList( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 nFrames,
AudioBufferList * inBufferList);
protected:
/*! @method Disconnect */
void Disconnect();

enum EInputType { kNoInput, kFromConnection, kFromCallback };

/*! @var mInputType */
EInputType mInputType;

// if from callback:
/*! @var mInputProc */
AURenderCallback mInputProc;
/*! @var mInputProcRefCon */
void * mInputProcRefCon;
// if from connection:
/*! @var mConnection */
AudioUnitConnection mConnection;
/*! @var mConnRenderProc */
AudioUnitRenderProc mConnRenderProc;
/*! @var mConnInstanceStorage */
void * mConnInstanceStorage; // for the input component
};


#endif // __AUInput_h__

+ 56
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.cpp View File

@@ -0,0 +1,56 @@
/* 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 "AUOutputElement.h"
#include "AUBase.h"

AUOutputElement::AUOutputElement(AUBase *audioUnit) :
AUIOElement(audioUnit)
{
AllocateBuffer();
}

OSStatus AUOutputElement::SetStreamFormat(const CAStreamBasicDescription &desc)
{
OSStatus result = AUIOElement::SetStreamFormat(desc); // inherited
if (result == AUBase::noErr)
AllocateBuffer();
return result;
}

+ 60
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUOutputElement.h View File

@@ -0,0 +1,60 @@
/* 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.
*/
#ifndef __AUOutput_h__
#define __AUOutput_h__

#include "AUScopeElement.h"
#include "AUBuffer.h"

/*! @class AUOutputElement */
class AUOutputElement : public AUIOElement {
public:
/*! @ctor AUOutputElement */
AUOutputElement(AUBase *audioUnit);

// AUElement override
/*! @method SetStreamFormat */
virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
/*! @method NeedsBufferSpace */
virtual bool NeedsBufferSpace() const { return true; }
};

#endif // __AUOutput_h__

+ 134
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUResources.r View File

@@ -0,0 +1,134 @@
/* 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.
*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUResources.r
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* sample macro definitions -- all of these symbols must be defined
#define RES_ID kHALOutputResID
#define COMP_TYPE kAudioUnitComponentType
#define COMP_SUBTYPE kAudioUnitOutputSubType
#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
#define VERSION 0x00010000
#define NAME "AudioHALOutput"
#define DESCRIPTION "Audio hardware output AudioUnit"
#define ENTRY_POINT "AUHALEntry"
*/
#define UseExtendedThingResource 1

#include <CoreServices/CoreServices.r>

// this is a define used to indicate that a component has no static data that would mean
// that no more than one instance could be open at a time - never been true for AUs
#ifndef cmpThreadSafeOnMac
#define cmpThreadSafeOnMac 0x10000000
#endif

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

resource 'STR ' (RES_ID, purgeable) {
NAME
};

resource 'STR ' (RES_ID + 1, purgeable) {
DESCRIPTION
};

resource 'dlle' (RES_ID) {
ENTRY_POINT
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

resource 'thng' (RES_ID, NAME) {
COMP_TYPE,
COMP_SUBTYPE,
COMP_MANUF,
0, 0, 0, 0, // no 68K
'STR ', RES_ID,
'STR ', RES_ID + 1,
0, 0, /* icon */
VERSION,
componentHasMultiplePlatforms | componentDoAutoVersion,
0,
{
#if defined(ppc_YES)
cmpThreadSafeOnMac,
'dlle', RES_ID, platformPowerPCNativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(ppc64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, platformPowerPC64NativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(i386_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, platformIA32NativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(x86_64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, 8
#define NeedLeadingComma 1
#endif
}
};

#undef RES_ID
#undef COMP_TYPE
#undef COMP_SUBTYPE
#undef COMP_MANUF
#undef VERSION
#undef NAME
#undef DESCRIPTION
#undef ENTRY_POINT
#undef NeedLeadingComma

+ 506
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.cpp View File

@@ -0,0 +1,506 @@
/* 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 "AUScopeElement.h"
#include "AUBase.h"

//_____________________________________________________________________________
//
// By default, parameterIDs may be arbitrarily spaced, and an STL map
// will be used for access. Calling UseIndexedParameters() will
// instead use an STL vector for faster indexed access.
// This assumes the paramIDs are numbered 0.....inNumberOfParameters-1
// Call this before defining/adding any parameters with SetParameter()
//
void AUElement::UseIndexedParameters(int inNumberOfParameters)
{
mIndexedParameters.resize (inNumberOfParameters);
mUseIndexedParameters = true;
}

//_____________________________________________________________________________
//
// Helper method.
// returns the ParameterMapEvent object associated with the paramID
//
inline ParameterMapEvent& AUElement::GetParamEvent(AudioUnitParameterID paramID)
{
ParameterMapEvent *event;
if(mUseIndexedParameters)
{
if(paramID >= mIndexedParameters.size() )
COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
event = &mIndexedParameters[paramID];
}
else
{
ParameterMap::iterator i = mParameters.find(paramID);
if (i == mParameters.end())
COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
event = &(*i).second;
}
return *event;
}

//_____________________________________________________________________________
//
// caller assumes that this is actually an immediate parameter
//
AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID)
{
ParameterMapEvent &event = GetParamEvent(paramID);
return event.GetValue();
}


//_____________________________________________________________________________
//
void AUElement::GetRampSliceStartEnd( AudioUnitParameterID paramID,
AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue,
AudioUnitParameterValue & outValuePerFrameDelta )

{
ParameterMapEvent &event = GetParamEvent(paramID);
// works even if the value is constant (immediate parameter value)
event.GetRampSliceStartEnd(outStartValue, outEndValue, outValuePerFrameDelta );
}

//_____________________________________________________________________________
//
AudioUnitParameterValue AUElement::GetEndValue( AudioUnitParameterID paramID)

{
ParameterMapEvent &event = GetParamEvent(paramID);
// works even if the value is constant (immediate parameter value)
return event.GetEndValue();
}

//_____________________________________________________________________________
//
void AUElement::SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized)
{
if(mUseIndexedParameters)
{
ParameterMapEvent &event = GetParamEvent(paramID);
event.SetValue(inValue);
}
else
{
ParameterMap::iterator i = mParameters.find(paramID);
if (i == mParameters.end())
{
if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
// The AU should not be creating new parameters once initialized.
// If a client tries to set an undefined parameter, we could throw as follows,
// but this might cause a regression. So it is better to just fail silently.
// COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
#if DEBUG
fprintf(stderr, "WARNING: %s SetParameter for undefined param ID %d while initialized. Ignoring..\n",
mAudioUnit->GetLoggingString(), (int)paramID);
#endif
} else {
// create new entry in map for the paramID (only happens first time)
ParameterMapEvent event(inValue);
mParameters[paramID] = event;
}
}
else
{
// paramID already exists in map so simply change its value
ParameterMapEvent &event = (*i).second;
event.SetValue(inValue);
}
}
}

//_____________________________________________________________________________
//
void AUElement::SetScheduledEvent( AudioUnitParameterID paramID,
const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames,
bool okWhenInitialized )
{
if(mUseIndexedParameters)
{
ParameterMapEvent &event = GetParamEvent(paramID);
event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
}
else
{
ParameterMap::iterator i = mParameters.find(paramID);
if (i == mParameters.end())
{
if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
// The AU should not be creating new parameters once initialized.
// If a client tries to set an undefined parameter, we could throw as follows,
// but this might cause a regression. So it is better to just fail silently.
// COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
#if DEBUG
fprintf(stderr, "WARNING: %s SetScheduledEvent for undefined param ID %d while initialized. Ignoring..\n",
mAudioUnit->GetLoggingString(), (int)paramID);
#endif
} else {
// create new entry in map for the paramID (only happens first time)
ParameterMapEvent event(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames);
mParameters[paramID] = event;
}
}
else
{
// paramID already exists in map so simply change its value
ParameterMapEvent &event = (*i).second;
event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
}
}
}



//_____________________________________________________________________________
//
void AUElement::GetParameterList(AudioUnitParameterID *outList)
{
if(mUseIndexedParameters)
{
UInt32 nparams = mIndexedParameters.size();
for (UInt32 i = 0; i < nparams; i++ )
*outList++ = (AudioUnitParameterID)i;
}
else
{
for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i)
*outList++ = (*i).first;
}
}

//_____________________________________________________________________________
//
void AUElement::SaveState(CFMutableDataRef data)
{
if(mUseIndexedParameters)
{
UInt32 nparams = mIndexedParameters.size();
UInt32 theData = CFSwapInt32HostToBig(nparams);
CFDataAppendBytes(data, (UInt8 *)&theData, sizeof(nparams));
for (UInt32 i = 0; i < nparams; i++)
{
struct {
UInt32 paramID;
//CFSwappedFloat32 value; crashes gcc3 PFE
UInt32 value; // really a big-endian float
} entry;
entry.paramID = CFSwapInt32HostToBig(i);
AudioUnitParameterValue v = mIndexedParameters[i].GetValue();
entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
}
}
else
{
UInt32 nparams = CFSwapInt32HostToBig(mParameters.size());
CFDataAppendBytes(data, (UInt8 *)&nparams, sizeof(nparams));
for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i) {
struct {
UInt32 paramID;
//CFSwappedFloat32 value; crashes gcc3 PFE
UInt32 value; // really a big-endian float
} entry;
entry.paramID = CFSwapInt32HostToBig((*i).first);
AudioUnitParameterValue v = (*i).second.GetValue();
entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
}
}
}

//_____________________________________________________________________________
//
const UInt8 * AUElement::RestoreState(const UInt8 *state)
{
union FloatInt32 { UInt32 i; AudioUnitParameterValue f; };
const UInt8 *p = state;
UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
p += sizeof(UInt32);
for (UInt32 i = 0; i < nparams; ++i) {
struct {
AudioUnitParameterID paramID;
AudioUnitParameterValue value;
} entry;
entry.paramID = CFSwapInt32BigToHost(*(UInt32 *)p);
p += sizeof(UInt32);
FloatInt32 temp;
temp.i = CFSwapInt32BigToHost(*(UInt32 *)p);
entry.value = temp.f;
p += sizeof(AudioUnitParameterValue);
SetParameter(entry.paramID, entry.value);
}
return p;
}

//_____________________________________________________________________________
//
void AUElement::SetName (CFStringRef inName)
{
if (mElementName) CFRelease (mElementName);
mElementName = inName;
if (mElementName) CFRetain (mElementName);
}


//_____________________________________________________________________________
//
AUIOElement::AUIOElement(AUBase *audioUnit) :
AUElement(audioUnit),
mWillAllocate (true)
{
mStreamFormat.SetAUCanonical(2, // stereo
audioUnit->AudioUnitAPIVersion() == 1);
// interleaved if API version 1, deinterleaved if version 2
mStreamFormat.mSampleRate = kAUDefaultSampleRate;
}

//_____________________________________________________________________________
//
OSStatus AUIOElement::SetStreamFormat(const CAStreamBasicDescription &desc)
{
mStreamFormat = desc;
return AUBase::noErr;
}

//_____________________________________________________________________________
// inFramesToAllocate == 0 implies the AudioUnit's max-frames-per-slice will be used
void AUIOElement::AllocateBuffer(UInt32 inFramesToAllocate)
{
if (GetAudioUnit()->HasBegunInitializing())
{
UInt32 framesToAllocate = inFramesToAllocate > 0 ? inFramesToAllocate : GetAudioUnit()->GetMaxFramesPerSlice();
// printf ("will allocate: %d\n", (int)((mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0));
mIOBuffer.Allocate(mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0);
}
}

//_____________________________________________________________________________
//
void AUIOElement::DeallocateBuffer()
{
mIOBuffer.Deallocate();
}

//_____________________________________________________________________________
//
// AudioChannelLayout support

// outLayoutTagsPtr WILL be NULL if called to find out how many
// layouts that Audio Unit will report
// return 0 (ie. NO channel layouts) if the AU doesn't require channel layout knowledge
UInt32 AUIOElement::GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr)
{
return 0;
}
// As the AudioChannelLayout can be a variable length structure
// (though in most cases it won't be!!!)
// The size of the ACL is always returned by the method
// if outMapPtr is NOT-NULL, then AU should copy into this pointer (outMapPtr) the current ACL that it has in use.
// the AU should also return whether the property is writable (that is the client can provide any arbitrary ACL that the audio unit will then honour)
// or if the property is read only - which is the generally preferred mode.
// If the AU doesn't require an AudioChannelLayout, then just return 0.
UInt32 AUIOElement::GetAudioChannelLayout (AudioChannelLayout *outMapPtr,
Boolean &outWritable)
{
return 0;
}

// the incoming channel map will be at least as big as a basic AudioChannelLayout
// but its contents will determine its actual size
// Subclass should overide if channel map is writable
OSStatus AUIOElement::SetAudioChannelLayout (const AudioChannelLayout &inData)
{
return kAudioUnitErr_InvalidProperty;
}

// Some units support optional usage of channel maps - typically converter units
// that can do channel remapping between different maps. In that optional case
// the user should be able to remove a channel map if that is possible.
// Typically this is NOT the case (e.g., the 3DMixer even in the stereo case
// needs to know if it is rendering to speakers or headphones)
OSStatus AUIOElement::RemoveAudioChannelLayout ()
{
return kAudioUnitErr_InvalidPropertyValue;
}


//_____________________________________________________________________________
//
AUScope::~AUScope()
{
for (ElementVector::iterator it = mElements.begin(); it != mElements.end(); ++it)
delete *it;
}

//_____________________________________________________________________________
//
void AUScope::SetNumberOfElements(UInt32 numElements)
{
if (mDelegate)
return mDelegate->SetNumberOfElements(numElements);

if (numElements > mElements.size()) {
mElements.reserve(numElements);
while (numElements > mElements.size()) {
AUElement *elem = GetCreator()->CreateElement(GetScope(), mElements.size());
mElements.push_back(elem);
}
} else
while (numElements < mElements.size()) {
AUElement *elem = mElements.back();
mElements.pop_back();
delete elem;
}
}

//_____________________________________________________________________________
//
bool AUScope::HasElementWithName () const
{
for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
AUElement * el = const_cast<AUScope*>(this)->GetElement (i);
if (el && el->HasName()) {
return true;
}
}
return false;
}

//_____________________________________________________________________________
//

void AUScope::AddElementNamesToDict (CFMutableDictionaryRef & inNameDict)
{
if (HasElementWithName())
{
static char string[32];
CFMutableDictionaryRef elementDict = CFDictionaryCreateMutable (NULL, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFStringRef str;
for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
AUElement * el = GetElement (i);
if (el && el->HasName()) {
snprintf (string, sizeof(string), "%d", int(i));
str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
CFDictionarySetValue (elementDict, str, el->GetName());
CFRelease (str);
}
}

snprintf (string, sizeof(string), "%d", int(mScope));
str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
CFDictionarySetValue (inNameDict, str, elementDict);
CFRelease (str);
CFRelease (elementDict);
}
}

//_____________________________________________________________________________
//
bool AUScope::RestoreElementNames (CFDictionaryRef& inNameDict)
{
static char string[32];

//first we have to see if we have enough elements and if not create them
bool didAddElements = false;
unsigned int maxElNum = 0;
int dictSize = CFDictionaryGetCount(inNameDict);
CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef));
CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast<const void**>(keys), NULL);
for (int i = 0; i < dictSize; i++)
{
unsigned int intKey;
CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
sscanf (string, "%u", &intKey);
if (UInt32(intKey) > maxElNum)
maxElNum = intKey;
}
if (maxElNum >= GetNumberOfElements()) {
SetNumberOfElements (maxElNum+1);
didAddElements = true;
}
// OK, now we have the number of elements that we need - lets restate their names
for (int i = 0; i < dictSize; i++)
{
CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict, keys[i]));
int intKey;
CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
sscanf (string, "%d", &intKey);
GetElement (intKey)->SetName (elName);
}
free (keys);
return didAddElements;
}


+ 535
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/AUScopeElement.h View File

@@ -0,0 +1,535 @@
/* 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.
*/
#ifndef __AUScopeElement_h__
#define __AUScopeElement_h__

#include <map>
#include <vector>

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioUnit.h>
#else
#include <AudioUnit.h>
#endif
#include "ComponentBase.h"
#include "AUBuffer.h"


class AUBase;

// ____________________________________________________________________________
//
// represents a parameter's value (either constant or ramped)
/*! @class ParameterMapEvent */
class ParameterMapEvent
{
public:
/*! @ctor ParameterMapEvent */
ParameterMapEvent()
: mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0), mValue2(0.0), mSliceDurationFrames(0)
{}

/*! @ctor ParameterMapEvent */
ParameterMapEvent(AudioUnitParameterValue inValue)
: mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0)
{}
// constructor for scheduled event
/*! @ctor ParameterMapEvent */
ParameterMapEvent( const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames )
{
SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
};
/*! @method SetScheduledEvent */
void SetScheduledEvent( const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames )
{
mEventType = inEvent.eventType;
mSliceDurationFrames = inSliceDurationFrames;
if(mEventType == kParameterEvent_Immediate )
{
// constant immediate value for the whole slice
mValue1 = inEvent.eventValues.immediate.value;
mValue2 = mValue1;
mDurationInFrames = inSliceDurationFrames;
mBufferOffset = 0;
}
else
{
mDurationInFrames = inEvent.eventValues.ramp.durationInFrames;
mBufferOffset = inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer; // shift over for this slice
mValue1 = inEvent.eventValues.ramp.startValue;
mValue2 = inEvent.eventValues.ramp.endValue;
}
};
/*! @method GetEventType */
AUParameterEventType GetEventType() const {return mEventType;};

/*! @method GetValue */
AudioUnitParameterValue GetValue() const {return mValue1;}; // only valid if immediate event type
/*! @method GetEndValue */
AudioUnitParameterValue GetEndValue() const {return mValue2;}; // only valid if immediate event type
/*! @method SetValue */
void SetValue(AudioUnitParameterValue inValue)
{
mEventType = kParameterEvent_Immediate;
mValue1 = inValue;
mValue2 = inValue;
}
// interpolates the start and end values corresponding to the current processing slice
// most ramp parameter implementations will want to use this method
// the start value will correspond to the start of the slice
// the end value will correspond to the end of the slice
/*! @method GetRampSliceStartEnd */
void GetRampSliceStartEnd( AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue,
AudioUnitParameterValue & outValuePerFrameDelta )
{
if (mEventType == kParameterEvent_Ramped) {
outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames;
outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset); // corresponds to frame 0 of this slice
outEndValue = outStartValue + outValuePerFrameDelta * mSliceDurationFrames;
} else {
outValuePerFrameDelta = 0;
outStartValue = outEndValue = mValue1;
}
};

// Some ramp parameter implementations will want to interpret the ramp using their
// own interpolation method (perhaps non-linear)
// This method gives the raw ramp information, relative to this processing slice
// for the client to interpret as desired
/*! @method GetRampInfo */
void GetRampInfo( SInt32 & outBufferOffset,
UInt32 & outDurationInFrames,
AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue )
{
outBufferOffset = mBufferOffset;
outDurationInFrames = mDurationInFrames;
outStartValue = mValue1;
outEndValue = mValue2;
};

#if DEBUG
void Print()
{
printf("ParameterEvent @ %p\n", this);
printf(" mEventType = %d\n", (int)mEventType);
printf(" mBufferOffset = %d\n", (int)mBufferOffset);
printf(" mDurationInFrames = %d\n", (int)mDurationInFrames);
printf(" mSliceDurationFrames = %d\n", (int)mSliceDurationFrames);
printf(" mValue1 = %.5f\n", mValue1);
printf(" mValue2 = %.5f\n", mValue2);
}
#endif

private:
AUParameterEventType mEventType;
SInt32 mBufferOffset; // ramp start offset relative to start of this slice (may be negative)
UInt32 mDurationInFrames; // total duration of ramp parameter
AudioUnitParameterValue mValue1; // value if immediate : startValue if ramp
AudioUnitParameterValue mValue2; // endValue (only used for ramp)
UInt32 mSliceDurationFrames; // duration of this processing slice
};



// ____________________________________________________________________________
//

/*! @class AUElement */
class AUElement {
public:
/*! @ctor AUElement */
AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit),
mUseIndexedParameters(false), mElementName(0) { }
/*! @dtor ~AUElement */
virtual ~AUElement() { if (mElementName) CFRelease (mElementName); }
/*! @method GetNumberOfParameters */
UInt32 GetNumberOfParameters()
{
if(mUseIndexedParameters) return mIndexedParameters.size(); else return mParameters.size();
}
/*! @method GetParameterList */
void GetParameterList(AudioUnitParameterID *outList);
/*! @method GetParameter */
AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID);
/*! @method SetParameter */
void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false);
// Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.

// interpolates the start and end values corresponding to the current processing slice
// most ramp parameter implementations will want to use this method
/*! @method GetRampSliceStartEnd */
void GetRampSliceStartEnd( AudioUnitParameterID paramID,
AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue,
AudioUnitParameterValue & outValuePerFrameDelta );
/*! @method GetEndValue */
AudioUnitParameterValue GetEndValue( AudioUnitParameterID paramID);

/*! @method SetRampParameter */
void SetScheduledEvent( AudioUnitParameterID paramID,
const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames,
bool okWhenInitialized = false );
// Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.


/*! @method GetAudioUnit */
AUBase * GetAudioUnit() const { return mAudioUnit; };

/*! @method SaveState */
void SaveState(CFMutableDataRef data);
/*! @method RestoreState */
const UInt8 * RestoreState(const UInt8 *state);
/*! @method GetName */
CFStringRef GetName () const { return mElementName; }
/*! @method SetName */
void SetName (CFStringRef inName);
/*! @method HasName */
bool HasName () const { return mElementName != 0; }
/*! @method UseIndexedParameters */
virtual void UseIndexedParameters(int inNumberOfParameters);

protected:
inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID);
private:
typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID> > ParameterMap;
/*! @var mAudioUnit */
AUBase * mAudioUnit;
/*! @var mParameters */
ParameterMap mParameters;

/*! @var mUseIndexedParameters */
bool mUseIndexedParameters;
/*! @var mIndexedParameters */
std::vector<ParameterMapEvent> mIndexedParameters;
/*! @var mElementName */
CFStringRef mElementName;
};



// ____________________________________________________________________________
//
/*! @class AUIOElement */
class AUIOElement : public AUElement {
public:
/*! @ctor AUIOElement */
AUIOElement(AUBase *audioUnit);

/*! @method GetStreamFormat */
const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
/*! @method SetStreamFormat */
virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);

/*! @method AllocateBuffer */
virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);
/*! @method DeallocateBuffer */
void DeallocateBuffer();
/*! @method NeedsBufferSpace */
virtual bool NeedsBufferSpace() const = 0;

/*! @method DeallocateBuffer */
void SetWillAllocateBuffer(bool inFlag) {
mWillAllocate = inFlag;
}
/*! @method DeallocateBuffer */
bool WillAllocateBuffer() const {
return mWillAllocate;
}
/*! @method UseExternalBuffer */
void UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
}
/*! @method PrepareBuffer */
AudioBufferList & PrepareBuffer(UInt32 nFrames) {
if (mWillAllocate)
return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
}
/*! @method PrepareNullBuffer */
AudioBufferList & PrepareNullBuffer(UInt32 nFrames) {
return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
}
/*! @method SetBufferList */
AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
/*! @method SetBuffer */
void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
/*! @method InvalidateBufferList */
void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }

/*! @method GetBufferList */
AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); }

/*! @method GetChannelData */
AudioUnitSampleType * GetChannelData(int ch) const {
if (mStreamFormat.IsInterleaved())
return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
else
return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
}
SInt16 * GetInt16ChannelData(int ch) const {
if (mStreamFormat.IsInterleaved())
return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
else
return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
}

/*! @method CopyBufferListTo */
void CopyBufferListTo(AudioBufferList &abl) const {
mIOBuffer.CopyBufferListTo(abl);
}
/*! @method CopyBufferContentsTo */
void CopyBufferContentsTo(AudioBufferList &abl) const {
mIOBuffer.CopyBufferContentsTo(abl);
}

/* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
UInt32 BytesToFrames(AudioBufferList &abl) {
return BytesToFrames(abl.mBuffers[0].mDataByteSize);
}
UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/

/*! @method IsInterleaved */
bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
/*! @method NumberChannels */
UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); }
/*! @method NumberInterleavedChannels */
UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }

/*! @method GetChannelMapTags */
virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr);

/*! @method GetAudioChannelLayout */
virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable);

/*! @method SetAudioChannelLayout */
virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData);
/*! @method RemoveAudioChannelLayout */
virtual OSStatus RemoveAudioChannelLayout ();

protected:
/*! @var mStreamFormat */
CAStreamBasicDescription mStreamFormat;
/*! @var mIOBuffer */
AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed
// for output: output cache, usually allocated early on
/*! @var mWillAllocate */
bool mWillAllocate;
};

// ____________________________________________________________________________
//
/*! @class AUElementCreator */
class AUElementCreator {
public:
/*! @method CreateElement */
virtual AUElement * CreateElement(AudioUnitScope scope, AudioUnitElement element) = 0;
virtual ~AUElementCreator() { }
};

// ____________________________________________________________________________
//
// AUScopeDelegates are a way to get virtual scopes.
/*! @class AUScopeDelegate */
class AUScopeDelegate {
public:
/*! @ctor AUScopeDelegate */
AUScopeDelegate() : mCreator(NULL), mScope(0) { }
/*! @dtor ~AUScopeDelegate */
virtual ~AUScopeDelegate() {}
/*! @method Initialize */
virtual void Initialize( AUElementCreator *creator,
AudioUnitScope scope,
UInt32 numElements)
{
mCreator = creator;
mScope = scope;
SetNumberOfElements(numElements);
}
/*! @method SetNumberOfElements */
virtual void SetNumberOfElements(UInt32 numElements) = 0;
/*! @method GetNumberOfElements */
virtual UInt32 GetNumberOfElements() = 0;
/*! @method GetElement */
virtual AUElement * GetElement(UInt32 elementIndex) = 0;
AUElementCreator * GetCreator() const { return mCreator; }
AudioUnitScope GetScope() const { return mScope; }

private:
/*! @var mCreator */
AUElementCreator * mCreator;
/*! @var mScope */
AudioUnitScope mScope;
};



// ____________________________________________________________________________
//
/*! @class AUScope */
class AUScope {
public:
/*! @ctor AUScope */
AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { }
/*! @dtor ~AUScope */
~AUScope();
/*! @method Initialize */
void Initialize(AUElementCreator *creator,
AudioUnitScope scope,
UInt32 numElements)
{
if (mDelegate)
return mDelegate->Initialize(creator, scope, numElements);
mCreator = creator;
mScope = scope;
SetNumberOfElements(numElements);
}
/*! @method SetNumberOfElements */
void SetNumberOfElements(UInt32 numElements);
/*! @method GetNumberOfElements */
UInt32 GetNumberOfElements() const
{
if (mDelegate)
return mDelegate->GetNumberOfElements();
return mElements.size();
}
/*! @method GetElement */
AUElement * GetElement(UInt32 elementIndex) const
{
if (mDelegate)
return mDelegate->GetElement(elementIndex);

ElementVector::const_iterator i = mElements.begin() + elementIndex;
// catch passing -1 in as the elementIndex - causes a wrap around
return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i;
}
/*! @method SafeGetElement */
AUElement * SafeGetElement(UInt32 elementIndex)
{
AUElement *element = GetElement(elementIndex);
if (element == NULL)
COMPONENT_THROW(kAudioUnitErr_InvalidElement);
return element;
}
/*! @method GetIOElement */
AUIOElement * GetIOElement(UInt32 elementIndex) const
{
AUElement *element = GetElement(elementIndex);
AUIOElement *ioel;
#if !CA_NO_RTTI
if (element == NULL || (ioel = dynamic_cast<AUIOElement *>(element)) == NULL)
COMPONENT_THROW (kAudioUnitErr_InvalidElement);
#else
if (element == NULL || (ioel = static_cast<AUIOElement *>(element)) == NULL)
COMPONENT_THROW (kAudioUnitErr_InvalidElement);
#endif
return ioel;
}
/*! @method HasElementWithName */
bool HasElementWithName () const;
/*! @method AddElementNamesToDict */
void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
bool RestoreElementNames (CFDictionaryRef& inNameDict);
AUElementCreator * GetCreator() const { return mCreator; }
AudioUnitScope GetScope() const { return mScope; }

void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
private:
typedef std::vector<AUElement *> ElementVector;
/*! @var mCreator */
AUElementCreator * mCreator;
/*! @var mScope */
AudioUnitScope mScope;
/*! @var mElements */
ElementVector mElements;
/*! @var mDelegate */
AUScopeDelegate * mDelegate;
};



#endif // __AUScopeElement_h__

+ 189
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.cpp View File

@@ -0,0 +1,189 @@
/* 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 "ComponentBase.h"
#include "CAXException.h"

#if TARGET_OS_MAC
pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
#elif TARGET_OS_WIN32
CAGuard ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
#endif

#if CA_DO_NOT_USE_AUDIO_COMPONENT
#include <dlfcn.h>
#endif

ComponentBase::~ComponentBase()
{
}

void ComponentBase::PostConstructor()
{
}

void ComponentBase::PreDestructor()
{
}

#if !TARGET_OS_IPHONE
OSStatus ComponentBase::Version()
{
return 0x00000001;
}

OSStatus ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
{
if (This == NULL) return paramErr;

OSStatus result = noErr;
switch (p->what) {
case kComponentCloseSelect:
This->PreDestructor();
delete This;
break;
case kComponentVersionSelect:
result = This->Version();
break;

case kComponentCanDoSelect:
switch (p->params[0]) {
case kComponentOpenSelect:
case kComponentCloseSelect:
case kComponentVersionSelect:
case kComponentCanDoSelect:
return 1;
default:
return 0;
}
default:
result = badComponentSelector;
break;
}
return result;
}
#endif

#if CA_DO_NOT_USE_AUDIO_COMPONENT
static OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription &outDesc);
#endif

AudioComponentDescription ComponentBase::GetComponentDescription() const
{
AudioComponentDescription desc;
OSStatus result;
#if CA_DO_NOT_USE_AUDIO_COMPONENT
ca_require_noerr (result = ComponentBase_GetComponentDescription (mComponentInstance, desc), home);
#else
AudioComponent comp = AudioComponentInstanceGetComponent(mComponentInstance);
XAssert (comp);
if (comp) {
ca_require_noerr(result = AudioComponentGetDescription(comp, &desc), home);
} else
ca_require_noerr(result = -1, home);
#endif

home:
if (result)
memset (&desc, 0, sizeof(AudioComponentDescription));
return desc;
}


#if CA_DO_NOT_USE_AUDIO_COMPONENT
OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription & outDesc)
{
// we prefer to use the new API. If it is not available however, we have to go back to using the ComponentMgr one.
typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
static AudioComponentGetDescriptionProc acGDProc = NULL;
typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
static GetComponentInfoProc gciProc = NULL;

static int doneInit = 0;
if (doneInit == 0) {
doneInit = 1;
bool loadCMgr = true;
void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
if (theImage != NULL)
{
// we assume that all routine names passed here have a leading underscore which gets shaved
// off when passed to dlsym
aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
if (aciGCProc) {
acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
if (acGDProc)
loadCMgr = false;
}
}
if (loadCMgr) {
theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
if (theImage != NULL)
{
gciProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
}
}
}
OSStatus result = noErr;
if (acGDProc && aciGCProc) {
AudioComponent comp = (*aciGCProc)(inInstance);
XAssert (comp);
if (comp) {
ca_require_noerr(result = (*acGDProc)(comp, &outDesc), home);
} else
ca_require_noerr(result = -1, home);
} else if (gciProc) {
// in this case we know that inInstance is directly castable to a Component
ca_require_noerr(result = (*gciProc)((Component)inInstance, (ComponentDescription*)&outDesc, NULL, NULL, NULL), home);
}
home:
return result;
}
#endif //CA_DO_NOT_USE_AUDIO_COMPONENT

+ 226
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUBase/ComponentBase.h View File

@@ -0,0 +1,226 @@
/* 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.
*/
#ifndef __ComponentBase_h__
#define __ComponentBase_h__

#include <new>
#include "CADebugMacros.h"

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <AudioUnit/AudioUnit.h>

#if !TARGET_OS_IPHONE
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
#define AudioComponentInstance ComponentInstance
#define AudioComponentDescription ComponentDescription
#define AudioComponent Component
#define CA_DO_NOT_USE_AUDIO_COMPONENT 1
#endif
#endif

#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
typedef Float32 AudioUnitParameterValue;
#endif
#if COREAUDIOTYPES_VERSION < 1051
typedef Float32 AudioUnitSampleType;
#endif

#include <pthread.h>
#else
#include "CoreAudioTypes.h"
#include "Components.h"
#include "AudioUnit.h"
#include "CAGuard.h"
#endif

#ifndef COMPONENT_THROW
#if VERBOSE_COMPONENT_THROW
#define COMPONENT_THROW(err) \
do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
#else
#define COMPONENT_THROW(err) \
throw static_cast<OSStatus>(err)
#endif
#endif

#define COMPONENT_CATCH \
catch (std::bad_alloc &) { result = -108/*memFullErr*/; } \
catch (OSStatus err) { result = err; } \
catch (OSErr err) { result = err; } \
catch (...) { result = -1; }

class ComponentInitLocker
{
#if TARGET_OS_MAC
public:
ComponentInitLocker() { pthread_mutex_lock(&sComponentOpenMutex); }
~ComponentInitLocker() { pthread_mutex_unlock(&sComponentOpenMutex); }
private:
static pthread_mutex_t sComponentOpenMutex;
#elif TARGET_OS_WIN32
public:
bool sNeedsUnlocking;
ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
private:
static CAGuard sComponentOpenGuard;
#endif
};

#if !TARGET_OS_IPHONE
/*! @class ComponentEntryPoint */
template <class Class>
class ComponentEntryPoint {
public:
/*! @method Dispatch */
static OSStatus Dispatch(ComponentParameters *params, Class *obj)
{
OSStatus result = noErr;
try {
if (params->what == kComponentOpenSelect) {
// solve a host of initialization thread safety issues.
ComponentInitLocker lock;

ComponentInstance ci = (ComponentInstance)(params->params[0]);
Class *This = new Class((AudioComponentInstance)ci);
This->PostConstructor(); // allows base class to do additional initialization
// once the derived class is fully constructed
#if !CA_AU_IS_ONLY_PLUGIN
SetComponentInstanceStorage(ci, (Handle)This);
#endif
} else
result = Class::ComponentEntryDispatch(params, obj);
}
COMPONENT_CATCH
return result;
}
/*! @method Register */
static Component Register(OSType compType, OSType subType, OSType manufacturer)
{
ComponentDescription description = {compType, subType, manufacturer, 0, 0};
Component component = RegisterComponent(&description, (ComponentRoutineUPP) Dispatch, registerComponentGlobal, NULL, NULL, NULL);
if (component != NULL) {
SetDefaultComponent(component, defaultComponentAnyFlagsAnyManufacturerAnySubType);
}
return component;
}
};

#if TARGET_OS_MAC && TARGET_CPU_PPC && !TARGET_RT_MAC_MACHO
// for OS 9, a PPC native component's entry point must be a routine descriptor
#define COMPONENT_ENTRY(Class) \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
return ComponentEntryPoint<Class>::Dispatch(params, obj); \
} \
\
struct RoutineDescriptor Class##EntryRD = \
BUILD_ROUTINE_DESCRIPTOR((kPascalStackBased | RESULT_SIZE (kFourByteCode) | \
STACK_ROUTINE_PARAMETER (1, kFourByteCode) | \
STACK_ROUTINE_PARAMETER (2, kFourByteCode)), Class##Entry);
#else
#define COMPONENT_ENTRY(Class) \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
return ComponentEntryPoint<Class>::Dispatch(params, obj); \
}
#endif

/*! @class ComponentRegistrar */
template <class Class, OSType Type, OSType Subtype, OSType Manufacturer>
class ComponentRegistrar {
public:
/*! @ctor ComponentRegistrar */
ComponentRegistrar() { ComponentEntryPoint<Class>::Register(Type, Subtype, Manufacturer); }
};

#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \
static ComponentRegistrar<Class, Type, Subtype, Manufacturer> gRegistrar##Class
#else
#define COMPONENT_ENTRY(Class)
#define COMPONENT_REGISTER(Class)
#endif // !TARGET_OS_IPHONE


/*! @class ComponentBase */
class ComponentBase {
public:
// classic MacErrors
enum { noErr = 0, paramErr = -50, memFullErr = -108 };

/*! @ctor ComponentBase */
ComponentBase(AudioComponentInstance inInstance) : mComponentInstance(inInstance) { }
/*! @dtor ~ComponentBase */
virtual ~ComponentBase();
/*! @method PostConstructor */
virtual void PostConstructor();
/*! @method PreDestructor */
virtual void PreDestructor();

#if !TARGET_OS_IPHONE
/*! @method Version */
virtual OSStatus Version();

/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
#endif
/*! @method GetComponentInstance */
AudioComponentInstance GetComponentInstance() const { return mComponentInstance; }

/*! @method GetComponentDescription */
AudioComponentDescription GetComponentDescription() const;

protected:
/*! @var mComponentInstance */
AudioComponentInstance mComponentInstance;
};

#endif // __ComponentBase_h__

+ 386
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.cpp View File

@@ -0,0 +1,386 @@
/* 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 "AUCarbonViewBase.h"
#include "AUCarbonViewControl.h"
#include <algorithm>

AUCarbonViewBase::AUCarbonViewBase(AudioUnitCarbonView inInstance, Float32 inNotificationInterval /* in seconds */) :
ComponentBase(inInstance),
mEditAudioUnit(0),
mParameterListener(NULL),
#if !__LP64__
mEventListener(NULL),
#endif
mTimerRef (NULL),
mTimerUPP (NULL),
mCarbonWindow(NULL),
mCarbonPane(NULL),
mXOffset(0),
mYOffset(0)
{
AUEventListenerCreate (ParameterListener, this,
CFRunLoopGetCurrent(), kCFRunLoopCommonModes,
inNotificationInterval, inNotificationInterval,
&mParameterListener);
}

AUCarbonViewBase::~AUCarbonViewBase()
{
if (mCarbonPane)
DisposeControl(mCarbonPane);

for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
AUCarbonViewControl *ctl = *it;
delete ctl;
}
AUListenerDispose(mParameterListener);

if (mTimerRef)
::RemoveEventLoopTimer (mTimerRef);
if (mTimerUPP)
DisposeEventLoopTimerUPP (mTimerUPP);
}
void AUCarbonViewBase::AddControl(AUCarbonViewControl *control)
{
ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
if (it == mControlList.end())
mControlList.push_back(control);
}

void AUCarbonViewBase::RemoveControl(AUCarbonViewControl *control)
{
ControlList::iterator it = find(mControlList.begin(), mControlList.end(), control);
if (it != mControlList.end()) {
AUCarbonViewControl *ctl = *it;
mControlList.erase(it);
delete ctl;
}
}

void AUCarbonViewBase::ClearControls ()
{
for (ControlList::iterator it = mControlList.begin(); it != mControlList.end(); ++it) {
AUCarbonViewControl *ctl = *it;
delete ctl;
}
mControlList.clear();
}

void AUCarbonViewBase::ParameterListener(void * inCallbackRefCon,
void * inObject,
const AudioUnitEvent * inEvent,
UInt64 inEventHostTime,
Float32 inParameterValue)
{
if (inEvent->mEventType == kAudioUnitEvent_ParameterValueChange) {
AUCarbonViewControl *ctl = (AUCarbonViewControl *)inObject;
ctl->ParameterToControl(inParameterValue);
}
}

OSStatus AUCarbonViewBase::CreateCarbonView(AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl)
{
mEditAudioUnit = inAudioUnit;
mCarbonWindow = inWindow;

WindowAttributes attributes;
verify_noerr(GetWindowAttributes(mCarbonWindow, &attributes));
mCompositWindow = (attributes & kWindowCompositingAttribute) != 0;

Rect area;
area.left = short(inLocation.x); area.top = short(inLocation.y);
area.right = short(area.left + inSize.x); area.bottom = short(area.top + inSize.y);
OSStatus err = ::CreateUserPaneControl(inWindow, &area,
kControlSupportsEmbedding,
&mCarbonPane); // subclass can resize mCarbonPane to taste
verify_noerr(err);
if (err) return err;
outParentControl = mCarbonPane;
// register for mouse-down in our pane -- we want to clear focus
EventTypeSpec paneEvents[] = {
{ kEventClassControl, kEventControlClick }
};
WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(paneEvents), paneEvents);
if (IsCompositWindow()) {
verify_noerr(::HIViewAddSubview(inParentControl, mCarbonPane));
mXOffset = 0;
mYOffset = 0;
}
else {
verify_noerr(::EmbedControl(mCarbonPane, inParentControl));
mXOffset = inLocation.x;
mYOffset = inLocation.y;
}
mBottomRight.h = mBottomRight.v = 0;
SizeControl(mCarbonPane, 0, 0);
if (err = CreateUI(mXOffset, mYOffset))
return err;

// we should only resize the control if a subclass has embedded
// controls in this AND this is done with the EmbedControl call below
// if mBottomRight is STILL equal to zero, then that wasn't done
// so don't size the control
Rect paneBounds;
GetControlBounds(mCarbonPane, &paneBounds);
// only resize mCarbonPane if it has not already been resized during CreateUI
if ((paneBounds.top == paneBounds.bottom) && (paneBounds.left == paneBounds.right)) {
if (mBottomRight.h != 0 && mBottomRight.v != 0)
SizeControl(mCarbonPane, (short) (mBottomRight.h - mXOffset), (short) (mBottomRight.v - mYOffset));
}

if (IsCompositWindow()) {
// prepare for handling scroll-events
EventTypeSpec scrollEvents[] = {
{ kEventClassScrollable, kEventScrollableGetInfo },
{ kEventClassScrollable, kEventScrollableScrollTo }
};
WantEventTypes(GetControlEventTarget(mCarbonPane), GetEventTypeCount(scrollEvents), scrollEvents);
mCurrentScrollPoint.x = mCurrentScrollPoint.y = 0.0f;
}
return err;
}

OSStatus AUCarbonViewBase::CreateUI(Float32 inXOffset, Float32 inYOffset)
{
return noErr;
}

OSStatus AUCarbonViewBase::EmbedControl(ControlRef ctl)
{
Rect r;
::GetControlBounds(ctl, &r);
if (r.right > mBottomRight.h) mBottomRight.h = r.right;
if (r.bottom > mBottomRight.v) mBottomRight.v = r.bottom;

if (IsCompositWindow())
return ::HIViewAddSubview(mCarbonPane, ctl);
else
return ::EmbedControl(ctl, mCarbonPane);
}

void AUCarbonViewBase::AddCarbonControl(AUCarbonViewControl::ControlType type, const CAAUParameter &param, ControlRef control)
{
verify_noerr(EmbedControl(control));
AUCarbonViewControl *auvc = new AUCarbonViewControl(this, mParameterListener, type, param, control);
auvc->Bind();
AddControl(auvc);
}

bool AUCarbonViewBase::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
{
UInt32 eclass = GetEventClass(event);
UInt32 ekind = GetEventKind(event);
ControlRef control;
switch (eclass) {
case kEventClassControl:
{
switch (ekind) {
case kEventControlClick:
GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
if (control == mCarbonPane) {
ClearKeyboardFocus(mCarbonWindow);
return true;
}
}
}
break;
case kEventClassScrollable:
{
switch (ekind) {
case kEventScrollableGetInfo:
{
// [1/4]
/* <-- kEventParamImageSize (out, typeHISize)
* On exit, contains the size of the entire scrollable view.
*/
HISize originalSize = { mBottomRight.h, mBottomRight.v };
verify_noerr(SetEventParameter(event, kEventParamImageSize, typeHISize, sizeof(HISize), &originalSize));
// [2/4]
/* <-- kEventParamViewSize (out, typeHISize)
* On exit, contains the amount of the scrollable view that is
* visible.
*/
HIViewRef parentView = HIViewGetSuperview(mCarbonPane);
HIRect parentBounds;
verify_noerr(HIViewGetBounds(parentView, &parentBounds));
//HISize windowSize = { float(windowBounds.right - windowBounds.left),
// float(windowBounds.bottom - windowBounds.top) };
verify_noerr(SetEventParameter(event, kEventParamViewSize, typeHISize, sizeof(HISize), &(parentBounds.size)));
// [3/4]
/* <-- kEventParamLineSize (out, typeHISize)
* On exit, contains the amount that should be scrolled in
* response to a single click on a scrollbar arrow.
*/
HISize scrollIncrementSize = { 16.0f, float(20) };
verify_noerr(SetEventParameter(event, kEventParamLineSize, typeHISize, sizeof(HISize), &scrollIncrementSize));
// [4/4]
/* <-- kEventParamOrigin (out, typeHIPoint)
* On exit, contains the scrollable viewÕs current origin (the
* view-relative coordinate that is drawn at the top left
* corner of its frame). These coordinates should always be
* greater than or equal to zero. They should be less than or
* equal to the viewÕs image size minus its view size.
*/
verify_noerr(SetEventParameter(event, kEventParamOrigin, typeHIPoint, sizeof(HIPoint), &mCurrentScrollPoint));
}
return true;
case kEventScrollableScrollTo:
{
/*
* kEventClassScrollable / kEventScrollableScrollTo
*
* Summary:
* Requests that an HIScrollViewÕs scrollable view should scroll to
* a particular origin.
*/
/* --> kEventParamOrigin (in, typeHIPoint)
* The new origin for the scrollable view. The origin
* coordinates will vary from (0,0) to scrollable viewÕs image
* size minus its view size.
*/
HIPoint pointToScrollTo;
verify_noerr(GetEventParameter(event, kEventParamOrigin, typeHIPoint, NULL, sizeof(HIPoint), NULL, &pointToScrollTo));
float xDelta = mCurrentScrollPoint.x - pointToScrollTo.x;
float yDelta = mCurrentScrollPoint.y - pointToScrollTo.y;
// move visible portion the appropriate amount
verify_noerr(HIViewScrollRect(mCarbonPane, NULL, xDelta, yDelta));
// set new content to be drawn
verify_noerr(HIViewSetBoundsOrigin(mCarbonPane, pointToScrollTo.x, pointToScrollTo.y));
mCurrentScrollPoint = pointToScrollTo;
}
return true;
default:
break;
}
}
break;
default:
break;
}

return false;
}

/*! @method TellListener */
void AUCarbonViewBase::TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar)
{
#if !__LP64__
if (mEventListener)
(*mEventListener)(mEventListenerUserData, mComponentInstance, &auvp, event, evpar);
#endif

AudioUnitEvent auEvent;
auEvent.mArgument.mParameter = auvp;
if (event == kAudioUnitCarbonViewEvent_MouseDownInControl) {
auEvent.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
} else {
auEvent.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
}
AUEventListenerNotify(mParameterListener, this, &auEvent);
}


void AUCarbonViewBase::Update (bool inUIThread)
{
for (ControlList::iterator iter = mControlList.begin(); iter != mControlList.end(); ++iter)
{
(*iter)->Update(inUIThread);
}
}

pascal void AUCarbonViewBase::TheTimerProc (EventLoopTimerRef inTimer, void *inUserData)
{
AUCarbonViewBase* This = reinterpret_cast<AUCarbonViewBase*>(inUserData);
This->RespondToEventTimer (inTimer);
}

void AUCarbonViewBase::RespondToEventTimer (EventLoopTimerRef inTimer)
{}

/*
THESE are reasonable values for these two times
0.005 // delay
0.050 // interval
*/

OSStatus AUCarbonViewBase::CreateEventLoopTimer (Float32 inDelay, Float32 inInterval)
{
if (mTimerUPP)
return noErr;
mTimerUPP = NewEventLoopTimerUPP(TheTimerProc);
EventLoopRef mainEventLoop = GetMainEventLoop();
//doesn't seem to like too small a value
if (inDelay < 0.005)
inDelay = 0.005;
OSStatus timerResult = ::InstallEventLoopTimer(
mainEventLoop,
inDelay,
inInterval,
mTimerUPP,
this,
&mTimerRef);
return timerResult;
}

+ 182
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewBase.h View File

@@ -0,0 +1,182 @@
/* 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.
*/
#ifndef __AUCarbonViewBase_h__
#define __AUCarbonViewBase_h__

#include <vector>
#include "AUCarbonViewControl.h"
#include "ComponentBase.h"

static const Float32 kDefaultNotificationInterval = 0.100;

/*! @class AUCarbonViewBase */
class AUCarbonViewBase : public ComponentBase, public CarbonEventHandler
{
public:
/*! @ctor AUCarbonViewBase */
AUCarbonViewBase ( AudioUnitCarbonView inInstance,
Float32 inNotificationInterval = kDefaultNotificationInterval /* in seconds */);
/*! @dtor ~AUCarbonViewBase */
virtual ~AUCarbonViewBase();
// AUViewBase overrides
/*! @method CreateCarbonView */
virtual OSStatus CreateCarbonView (AudioUnit inAudioUnit, WindowRef inWindow, ControlRef inParentControl, const Float32Point &inLocation, const Float32Point &inSize, ControlRef &outParentControl);

// our own virtual methods
/*! @method CreateUI */
virtual OSStatus CreateUI (Float32 inXOffset, Float32 inYOffset);

/*! @method HandleEvent */
virtual bool HandleEvent (EventHandlerCallRef inHandlerRef, EventRef event);
/*! @method GetEditAudioUnit */
const AudioUnit GetEditAudioUnit () const { return mEditAudioUnit; }
//
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch (
ComponentParameters * params,
AUCarbonViewBase * This);

/*! @method AddCarbonControl */
void AddCarbonControl (
AUCarbonViewControl::ControlType type,
const CAAUParameter & param,
ControlRef control);

/*! @method GetCarbonWindow */
WindowRef GetCarbonWindow () { return mCarbonWindow; }
/*! @method GetCarbonPane */
ControlRef GetCarbonPane () { return mCarbonPane; }
/*! @method EmbedControl */
OSStatus EmbedControl (ControlRef ctl);
/*! @method TellListener */
void TellListener (const CAAUParameter &auvp, AudioUnitCarbonViewEventID event, void *evpar);
// pass in true if wanting an update to the view and you're calling this from a thread
// that is safe to do UI in.
// If you don't know, pass in false!
/*! @method Update */
void Update (bool inUIThread);
/*! @method GetXOffset */
Float32 GetXOffset () { return mXOffset; }
/*! @method GetYOffset */
Float32 GetYOffset () { return mYOffset; }
/*! @method ClearControls */
void ClearControls ();
/*! @method IsCompositWindow */
bool IsCompositWindow () const { return mCompositWindow; }
protected:
#if !__LP64__
/*! @method SetEventListener */
void SetEventListener (AudioUnitCarbonViewEventListener listener, void *userData)
{
mEventListener = listener;
mEventListenerUserData = userData;
}
#endif

/*! @method AddControl */
void AddControl (AUCarbonViewControl *control);
/*! @method RemoveControl */
void RemoveControl (AUCarbonViewControl *control);

OSStatus CreateEventLoopTimer (Float32 inDelay, Float32 inInterval);
/*! @method ParameterListener */
static void ParameterListener (void * inCallbackRefCon,
void * inObject,
const AudioUnitEvent * inEvent,
UInt64 inEventHostTime,
Float32 inParameterValue);
static pascal void TheTimerProc ( EventLoopTimerRef inTimer,
void * inUserData);

virtual void RespondToEventTimer (EventLoopTimerRef inTimer);

/*! @var mEditAudioUnit */
AudioUnit mEditAudioUnit; // the AU we're controlling
/*! @var mParameterListener */
AUEventListenerRef mParameterListener;

#if !__LP64__
/*! @var mEventListener */
AudioUnitCarbonViewEventListener
mEventListener;
#endif

/*! @var mEventListenerUserData */
void * mEventListenerUserData;

private:
typedef std::vector<AUCarbonViewControl *> ControlList;
/*! @var mControlList */
ControlList mControlList;

EventLoopTimerRef mTimerRef;

EventLoopTimerUPP mTimerUPP;

protected:
/*! @var mCarbonWindow */
WindowRef mCarbonWindow;
/*! @var mCarbonPane */
ControlRef mCarbonPane; // user pane, contains all other controls
/*! @var mBottomRight */
Point mBottomRight; // largest width and height of child controls
/*! @var mXOffset */
Float32 mXOffset;
/*! @var mYOffset */
Float32 mYOffset;
/*! @var mCompositWindow */
bool mCompositWindow;
/*! @var mCurrentScrollPoint */
HIPoint mCurrentScrollPoint; // needed for scrolling
};


#endif // __AUCarbonViewBase_h__

+ 667
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.cpp View File

@@ -0,0 +1,667 @@
/* 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 "AUCarbonViewControl.h"
#include "AUCarbonViewBase.h"
#include "AUViewLocalizedStringKeys.h"

AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control) :
mOwnerView(ownerView),
mListener(listener),
mType(type),
mParam(param),
mControl(control),
mInControlInitialization(0)
{
#if __LP64__
SetControlReference(control, SRefCon(this));
#else
SetControlReference(control, SInt32(this));
#endif
}

AUCarbonViewControl::~AUCarbonViewControl()
{
AUListenerRemoveParameter(mListener, this, &mParam);
}

AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL;

void AUCarbonViewControl::Bind()
{
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
}

void AUCarbonViewControl::ParameterToControl(Float32 paramValue)
{
++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(&paramValue);

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;
}

void AUCarbonViewControl::ControlToParameter()
{
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;
}
}

void AUCarbonViewControl::SetValueFract(double value)
{
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);
}

double AUCarbonViewControl::GetValueFract()
{
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;
}

void AUCarbonViewControl::SetTextValue(CFStringRef cfstr)
{
verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr));
}

CFStringRef AUCarbonViewControl::GetTextValue()
{
CFStringRef cfstr;
verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL));
return cfstr;
}

void AUCarbonViewControl::SetValue(long value)
{
SetControl32BitValue(mControl, value);
}

long AUCarbonViewControl::GetValue()
{
return GetControl32BitValue(mControl);
}

/* 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)
{
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();
}
return kControlKeyFilterBlockKey;
}

pascal ControlKeyFilterResult AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl,
SInt16 *keyCode, SInt16 *charCode,
EventModifiers *modifiers)
{
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();
}
return kControlKeyFilterBlockKey;
}

Boolean AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight)
{
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;
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 ()
{
EventTypeSpec events[] = {
{ kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
};
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
}

void AUPropertyControl::EmbedControl (ControlRef theControl)
{
mView->EmbedControl (theControl);
}

WindowRef AUPropertyControl::GetCarbonWindow()
{
return mView->GetCarbonWindow();
}

#pragma mark ___AUVPreset
static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset;
static bool sAUVPresetLocalized = false;

AUVPresets::AUVPresets (AUCarbonViewBase* inParentView,
CFArrayRef& inPresets,
Point inLocation,
int nameWidth,
int controlWidth,
ControlFontStyleRec & inFontStyle)
: AUPropertyControl (inParentView),
mPresets (inPresets),
mView (inParentView)
{
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;
#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
EmbedControl (mControl);
HandlePropertyChange(defaultPreset);
RegisterEvents();
}

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 ()
{
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) );
}
}

void AUVPresets::HandlePropertyChange(AUPreset &preset)
{
// 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);
}

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, &currentPreset, &theSize);
if (result == noErr) {
#ifndef __LP64__
if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName)
CFRetain (currentPreset.presetName);
#endif
HandlePropertyChange(currentPreset);
return true;
}
}
return false;
}

+ 224
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewControl.h View File

@@ -0,0 +1,224 @@
/* 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.
*/
#ifndef __AUCarbonViewControl_h__
#define __AUCarbonViewControl_h__

#include <Carbon/Carbon.h>
#include <AudioUnit/AudioUnitCarbonView.h>
#include <AudioToolbox/AudioUnitUtilities.h>
#include "CarbonEventHandler.h"
#include "CAAUParameter.h"

class AUCarbonViewBase;

// ____________________________________________________________________________
// AUCarbonViewControl
// Wrapper for a control that is wired to an AudioUnit parameter.
/*! @class AUCarbonViewControl */
class AUCarbonViewControl : public CarbonEventHandler {
// note that the controls are never disposed; that's managed by the AUCarbonViewBase's
// parent pane which contains all of them ... if we later need to be able to delete
// individual controls on the fly, extra work needed
public:
enum ControlType {
kTypeContinuous, // e.g. slider
kTypeDiscrete, // e.g. pop-up menu
kTypeText
};
AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter &param, ControlRef control);
~AUCarbonViewControl();

/*! @method Bind */
virtual void Bind(); // second-stage construction

/*! @method ControlToParameter */
virtual void ControlToParameter();
/*! @method ParameterToControl */
virtual void ParameterToControl(Float32 newValue);
/*! @method SetValueFract */
virtual void SetValueFract(double value);
/*! @method GetValueFract */
virtual double GetValueFract();
/*! @method SetTextValue */
virtual void SetTextValue(CFStringRef str);
/*! @method GetTextValue */
virtual CFStringRef GetTextValue();
/*! @method SetValue */
virtual void SetValue(long value);
/*! @method GetValue */
virtual long GetValue();
/*! @method GetOwnerView */
AUCarbonViewBase * GetOwnerView() {return mOwnerView;}

/*! @method Update */
void Update (bool inUIThread)
{
if (inUIThread)
ParameterToControl (mParam.GetValue());
else
AUParameterListenerNotify (mListener, this, &mParam);
}
// CarbonEventHandler overrides
/*! @method HandleEvent */
virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);
/*! @method ControlRef */
operator ControlRef() { return mControl; }
/*! @method SizeControlToFit */
static Boolean SizeControlToFit(ControlRef inControl, SInt16 *outWidth = NULL, SInt16 *outHeight = NULL);
/*! @method SliderTrackProc */
static pascal void SliderTrackProc(ControlRef theControl, ControlPartCode partCode);
/*! @method NumericKeyFilterCallback */
static pascal ControlKeyFilterResult NumericKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
EventModifiers *modifiers);
protected:
/*! @method ParamInfo */
const AudioUnitParameterInfo &ParamInfo() { return mParam.ParamInfo(); }

/*! @var mOwnerView */
AUCarbonViewBase * mOwnerView;
/*! @var mListener */
AUParameterListenerRef mListener;
/*! @var mType */
ControlType mType;
/*! @var mParam */
CAAUParameter mParam;

/*! @var mControl */
ControlRef mControl;
/*! @method StdKeyFilterCallback */
static pascal ControlKeyFilterResult StdKeyFilterCallback(ControlRef theControl, SInt16 *keyCode, SInt16 *charCode,
EventModifiers *modifiers);
SInt16 mInControlInitialization;
static AUCarbonViewControl* mLastControl;
};

/*! @class AUPropertyControl */
class AUPropertyControl : public CarbonEventHandler {
public:
/*! @ctor AUPropertyControl */
AUPropertyControl (AUCarbonViewBase * inBase) : mControl(0), mView (inBase), mHeight(0) {}
/*! @method HandleEvent */
virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event);

/*! @method HandlePropertyChange */
virtual bool HandlePropertyChange (const AudioUnitProperty &inProp) = 0;
/*! @method AddInterest */
virtual void AddInterest (AUEventListenerRef inListener,
void * inObject) = 0;
/*! @method RemoveInterest */
virtual void RemoveInterest (AUEventListenerRef inListener,
void * inObject) = 0;
/*! @method GetHeight */
int GetHeight() { return mHeight;}
protected:
/*! @method HandleControlChange */
virtual void HandleControlChange () = 0;

/*! @method RegisterEvents */
void RegisterEvents ();

/*! @method EmbedControl */
void EmbedControl (ControlRef theControl);
/*! @method GetCarbonWindow */
WindowRef GetCarbonWindow();

/*! @var mControl */
ControlRef mControl;
/*! @var mView */
AUCarbonViewBase* mView;
/*! @var mHeight */
SInt16 mHeight;
};

/*! @class AUVPresets */
class AUVPresets : public AUPropertyControl {
public:
/*! @ctor HandleControlChange */
AUVPresets (AUCarbonViewBase * inBase,
CFArrayRef& inPresets,
Point inLocation,
int nameWidth,
int controlWidth,
ControlFontStyleRec & inFontStyle);

virtual ~AUVPresets () { CFRelease (mPresets); }

/*! @method HandlePropertyChange */
virtual bool HandlePropertyChange (const AudioUnitProperty &inProp);
/*! @method AddInterest */
virtual void AddInterest (AUEventListenerRef inListener,
void * inObject);
/*! @method RemoveInterest */
virtual void RemoveInterest (AUEventListenerRef inListener,
void * inObject);

protected:
/*! @method HandleControlChange */
virtual void HandleControlChange ();
/*! @var mPresets */
CFArrayRef mPresets;
/*! @var mView */
AUCarbonViewBase* mView;
AudioUnitPropertyID mPropertyID;

void HandlePropertyChange(AUPreset &preset);
};

#endif // __AUCarbonViewControl_h__

+ 119
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUCarbonViewDispatch.cpp View File

@@ -0,0 +1,119 @@
/* 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 "AUCarbonViewBase.h"

// ____________________________________________________________________________
// component dispatch

#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
struct AudioUnitCarbonViewCreateGluePB {
unsigned char componentFlags;
unsigned char componentParamSize;
short componentWhat;
ControlRef* outControl;
const Float32Point* inSize;
const Float32Point* inLocation;
ControlRef inParentControl;
WindowRef inWindow;
AudioUnit inAudioUnit;
AudioUnitCarbonView inView;
};
#if !__LP64__
struct AudioUnitCarbonViewSetEventListenerGluePB {
unsigned char componentFlags;
unsigned char componentParamSize;
short componentWhat;
void* inUserData;
AudioUnitCarbonViewEventListener inCallback;
AudioUnitCarbonView inView;
};
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif

#define CheckNull(x) if ((x) == NULL) return paramErr;

OSStatus AUCarbonViewBase::ComponentEntryDispatch(ComponentParameters *p, AUCarbonViewBase *This)
{
if (This == NULL) return paramErr;

OSStatus result = noErr;
switch (p->what) {
case kAudioUnitCarbonViewCreateSelect:
{
AudioUnitCarbonViewCreateGluePB *pb = (AudioUnitCarbonViewCreateGluePB *)p;
CheckNull(pb->inAudioUnit);
CheckNull(pb->inWindow);
CheckNull(pb->inParentControl);
CheckNull(pb->inSize);
CheckNull(pb->inLocation);
CheckNull(pb->outControl);
result = This->CreateCarbonView(pb->inAudioUnit, pb->inWindow, pb->inParentControl,
*pb->inLocation, *pb->inSize, *pb->outControl);
}
break;
#if !__LP64__
case kAudioUnitCarbonViewSetEventListenerSelect:
{
AudioUnitCarbonViewSetEventListenerGluePB *pb = (AudioUnitCarbonViewSetEventListenerGluePB *)p;
This->SetEventListener(pb->inCallback, pb->inUserData);
}
break;
#endif
default:
result = ComponentBase::ComponentEntryDispatch(p, This);
break;
}
return result;
}

+ 343
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.cpp View File

@@ -0,0 +1,343 @@
/* 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 <Carbon/Carbon.h>
#include "AUCarbonViewBase.h"
#include "AUCarbonViewControl.h"
#include "AUControlGroup.h"
#include "AUViewLocalizedStringKeys.h"

#define kSliderThinDimension 10
#define kLabelAndSliderSpacing 4

static CFStringRef kStringManufacturer = kAUViewLocalizedStringKey_Manufacturer;
static bool sLocalized = false;

void AUControlGroup::CreateLabelledSlider(
AUCarbonViewBase * auView,
const CAAUParameter & auvp,
const Rect & area,
Point labelSize,
const ControlFontStyleRec & inFontStyle)
{
ControlFontStyleRec fontStyle = inFontStyle;
Rect minValRect, maxValRect, sliderRect;
ControlRef newControl;
int width = area.right - area.left, height = area.bottom - area.top;
CFStringRef cfstr;
int sliderValueMax, sliderValueMin, sliderValueDefault;
AUCarbonViewControl::ControlType sliderType;
bool horizontal = (width > height);

if (horizontal) {
maxValRect.top = minValRect.top = area.top + (height - labelSize.v) / 2;
minValRect.left = area.left;
maxValRect.left = area.right - labelSize.h;
minValRect.bottom = minValRect.top + labelSize.v;
minValRect.right = minValRect.left + labelSize.h;
maxValRect.bottom = maxValRect.top + labelSize.v;
maxValRect.right = maxValRect.left + labelSize.h;

sliderRect.left = minValRect.right + kLabelAndSliderSpacing;
sliderRect.right = maxValRect.left - kLabelAndSliderSpacing;
sliderRect.top = area.top + (height - kSliderThinDimension) / 2;
sliderRect.bottom = sliderRect.top + kSliderThinDimension + 4;

if (auvp.IsIndexedParam ()) {
sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
sliderValueMax = int(auvp.ParamInfo().maxValue);
sliderType = AUCarbonViewControl::kTypeDiscrete;
} else {
sliderValueMin = sliderValueDefault = 0;
sliderValueMax = sliderRect.right - sliderRect.left;
sliderType = AUCarbonViewControl::kTypeContinuous;
}
} else {
maxValRect.left = minValRect.left = area.left + (width - labelSize.h) / 2;
maxValRect.top = area.top;
minValRect.top = area.bottom - labelSize.v;
minValRect.bottom = minValRect.top + labelSize.v;
minValRect.right = minValRect.left + labelSize.h;
maxValRect.bottom = maxValRect.top + labelSize.v;
maxValRect.right = maxValRect.left + labelSize.h;
sliderRect.left = area.left + (width - kSliderThinDimension) / 2;
sliderRect.right = sliderRect.left + kSliderThinDimension + 4;
sliderRect.top = maxValRect.bottom + kLabelAndSliderSpacing;
sliderRect.bottom = minValRect.top - kLabelAndSliderSpacing;

if (auvp.IsIndexedParam ()) {
sliderValueMin = sliderValueDefault = int(auvp.ParamInfo().minValue);
sliderValueMax = int(auvp.ParamInfo().maxValue);
sliderType = AUCarbonViewControl::kTypeDiscrete;
} else {
sliderValueMin = sliderValueDefault = 0;
sliderValueMax = sliderRect.bottom - sliderRect.top;
sliderType = AUCarbonViewControl::kTypeContinuous;
}
}

// minimum value label
if (labelSize.v > 0 && labelSize.h > 0) {
// check to see if the minimum value has a label
cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().minValue);
fontStyle.just = horizontal ? teFlushRight : teCenter;
verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &minValRect, cfstr, &fontStyle, &newControl));
CFRelease(cfstr);
verify_noerr(auView->EmbedControl(newControl));
// maximum value label
cfstr = auvp.GetStringFromValueCopy(&auvp.ParamInfo().maxValue);
fontStyle.just = horizontal ? teFlushLeft : teCenter;
verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &maxValRect, cfstr, &fontStyle, &newControl));
CFRelease(cfstr);
verify_noerr(auView->EmbedControl(newControl));
}
// slider
verify_noerr(CreateSliderControl(auView->GetCarbonWindow(), &sliderRect, sliderValueDefault, sliderValueMin, sliderValueMax, kControlSliderDoesNotPoint, 0, true, AUCarbonViewControl::SliderTrackProc, &newControl));


ControlSize small = kControlSizeSmall;
SetControlData(newControl, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
auView->AddCarbonControl(sliderType, auvp, newControl);
}

void AUControlGroup::CreateLabelledSliderAndEditText(
AUCarbonViewBase * auView,
const CAAUParameter & auvp,
const Rect & area,
Point labelSize,
Point editTextSize,
const ControlFontStyleRec & inFontStyle)
{
ControlFontStyleRec fontStyle = inFontStyle;
Rect sliderArea, textArea;
ControlRef newControl;
int width = area.right - area.left, height = area.bottom - area.top;
bool horizontal = (width > height);

sliderArea = area;
textArea = area;
if (horizontal) {
textArea.left = area.right - editTextSize.h;
// provide a large text box if param is generic and its values have strings...
if (auvp.ValuesHaveStrings() && (auvp.ParamInfo().unit == kAudioUnitParameterUnit_Generic))
{
textArea.right += 30;
}
sliderArea.right = textArea.left - kLabelAndSliderSpacing;
textArea.top = area.top + (height - editTextSize.v) / 2;
textArea.bottom = textArea.top + editTextSize.v;
} else {
textArea.top = area.bottom - editTextSize.v;
sliderArea.bottom = textArea.top - kLabelAndSliderSpacing;
textArea.left = area.left + (width - editTextSize.h) / 2;
textArea.right = textArea.left + editTextSize.h;
}
CreateLabelledSlider(auView, auvp, sliderArea, labelSize, fontStyle);
verify_noerr(CreateEditUnicodeTextControl(auView->GetCarbonWindow(), &textArea, CFSTR(""), false,
&fontStyle, &newControl));
auView->AddCarbonControl(AUCarbonViewControl::kTypeText, auvp, newControl);
}

void AUControlGroup::CreatePopupMenu (AUCarbonViewBase * auView,
const CAAUParameter & auvp,
const Rect & area,
const ControlFontStyleRec & inFontStyle,
const bool inSizeToFit)
{
ControlRef thePopUp;
verify_noerr(CreatePopupButtonControl (auView->GetCarbonWindow(), &area, NULL,
-12345, // DON'T GET MENU FROM RESOURCE mMenuID
FALSE, // variableWidth,
0, // titleWidth,
0, // titleJustification,
0, // titleStyle,
&thePopUp));
ControlSize small = kControlSizeSmall;
SetControlData(thePopUp, kControlEntireControl, kControlSizeTag, sizeof(ControlSize), &small);
MenuRef menuRef;
verify_noerr(CreateNewMenu( 1, 0, &menuRef));
for (int i = 0; i < auvp.GetNumIndexedParams(); ++i) {
verify_noerr(AppendMenuItemTextWithCFString (menuRef, auvp.GetParamName(i), kMenuItemAttrIgnoreMeta, 0, 0));
}
verify_noerr(SetControlData(thePopUp, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
SetControl32BitMaximum(thePopUp, auvp.GetNumIndexedParams());

verify_noerr (SetControlFontStyle (thePopUp, &inFontStyle));
if (inSizeToFit) {
AUCarbonViewControl::SizeControlToFit(thePopUp);
}
auView->AddCarbonControl(AUCarbonViewControl::kTypeDiscrete, auvp, thePopUp);
}

void AUControlGroup::AddAUInfo ( AUCarbonViewBase * auView,
const Point & inLocation,
const SInt16 inRightOffset,
const SInt16 inTotalWidth)
{
// get component info
ComponentDescription desc;
Handle h1 = NewHandleClear(4);
OSStatus err = GetComponentInfo ((Component)auView->GetEditAudioUnit(), &desc, h1, 0, 0);
if (err == noErr) {
// Get the manufacturer's name... look for the ':' character convention
HLock(h1);
char* ptr1 = *h1;
int len = *ptr1++;
char* displayStr = 0;
for (int i = 0; i < len; ++i) {
if (ptr1[i] == ':') { // found the name
ptr1[i++] = 0;
displayStr = ptr1;
break;
}
}
// localize as necessary:
if (!sLocalized) {
CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
if (mainBundle) {
kStringManufacturer = CFCopyLocalizedStringFromTableInBundle(
kAUViewLocalizedStringKey_Manufacturer, kLocalizedStringTable_AUView,
mainBundle, CFSTR("Manufacturer title string"));
sLocalized = true;
}
}
// display strings
ControlRef newControl;
Rect r;
r.top = SInt16(inLocation.v); r.bottom = SInt16(inLocation.v) + 16;
ControlFontStyleRec fontStyle;
fontStyle.flags = kControlUseFontMask | kControlUseJustMask;
fontStyle.font = kControlFontSmallBoldSystemFont;
// display manufacturer string
if (displayStr) {
CFMutableStringRef mfrstring = CFStringCreateMutable(NULL, 0);
CFStringAppend(mfrstring, kStringManufacturer); // "Manufacturer"
CFStringAppend(mfrstring, kAUViewUnlocalizedString_TitleSeparator);
// "Manufacturer: "
CFStringRef mfrname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
if (mfrname) {
CFStringAppend(mfrstring, mfrname); // "Manufacturer: MFRName"
CFRelease (mfrname);
}
r.left = inLocation.h + inRightOffset;
r.right = inLocation.h + inTotalWidth - 28;
fontStyle.just = teFlushRight;
verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, mfrstring, &fontStyle, &newControl));
verify_noerr(auView->EmbedControl(newControl));
CFRelease (mfrstring);
//move displayStr ptr past the manu, to the name
// we move the characters down an index, because the handle doesn't have any room
// at the end for the \0
int i = strlen(displayStr), j = 0;
while (displayStr[++i] == ' ' && i < len)
;
while (i < len)
displayStr[j++] = displayStr[i++];
displayStr[j] = 0;
} else {
displayStr = ptr1;
int i = 0, j = 0;
do {
displayStr[j] = displayStr[i];
++j; ++i;
} while (i < len);
displayStr[j] = 0;
}
// display AudioUnit string
r.left = inLocation.h; r.right = r.left + inRightOffset;
fontStyle.just = 0;
CFMutableStringRef cfstr = CFStringCreateMutable(NULL, 0);
CFStringAppend(cfstr, kAUViewLocalizedStringKey_AudioUnit); // "Audio Unit"
CFStringAppend(cfstr, kAUViewUnlocalizedString_TitleSeparator);
// "Audio Unit: "
CFStringRef auname = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingUTF8);
CFStringAppend(cfstr, auname); // "Audio Unit: AUName"
CFRelease (auname);
verify_noerr(CreateStaticTextControl(auView->GetCarbonWindow(), &r, cfstr, &fontStyle, &newControl));
// size text control correctly
Boolean bValue = false;
SetControlData(newControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
SInt16 baseLineOffset;
Rect bestRect;
err = GetBestControlRect(newControl, &bestRect, &baseLineOffset);
if (err == noErr)
{
int width = (bestRect.right - bestRect.left) + 1;
int height = (bestRect.bottom - bestRect.top) + 1;
SizeControl (newControl, width, height);
}
verify_noerr(auView->EmbedControl(newControl));
CFRelease (cfstr);
}
DisposeHandle (h1);
}



+ 84
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/AUControlGroup.h View File

@@ -0,0 +1,84 @@
/* 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.
*/
#ifndef __AUControlGroup_h__
#define __AUControlGroup_h__

#include <Carbon/Carbon.h>

class AUCarbonViewBase;
class CAAUParameter;

// Utility class to create clusters of controls related to a single parameter
/*! @class AUControlGroup */
class AUControlGroup {
public:
/*! @method CreateLabelledSlider */
static void CreateLabelledSlider( AUCarbonViewBase * auView,
const CAAUParameter & auvp,
const Rect & area,
Point labelSize,
const ControlFontStyleRec & fontStyle);

/*! @method CreateLabelledSliderAndEditText */
static void CreateLabelledSliderAndEditText(
AUCarbonViewBase * auView,
const CAAUParameter & auvp,
const Rect & area,
Point labelSize,
Point editTextSize,
const ControlFontStyleRec & fontStyle);

/*! @method CreatePopupMenu */
static void CreatePopupMenu ( AUCarbonViewBase * auView,
const CAAUParameter & auvp,
const Rect & area,
const ControlFontStyleRec & inFontStyle,
const bool inSizeToFit = false);

/*! @method AddAUInfo */
static void AddAUInfo ( AUCarbonViewBase * auView,
const Point & inLocation,
const SInt16 inRightOffset,
const SInt16 inTotalWidth);
};


#endif // __AUControlGroup_h__

+ 84
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.cpp View File

@@ -0,0 +1,84 @@
/* 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 "CarbonEventHandler.h"

static pascal OSStatus TheEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData)
{
CarbonEventHandler *handler = (CarbonEventHandler *)inUserData;
if (handler->HandleEvent(inHandlerRef, inEvent))
return noErr;
else return eventNotHandledErr;
}

CarbonEventHandler::CarbonEventHandler() :
mHandlers(NULL)
{
}

CarbonEventHandler::~CarbonEventHandler()
{
if (mHandlers != NULL) {
int count = CFDictionaryGetCount(mHandlers);
EventHandlerRef *theHandlers = (EventHandlerRef*) malloc(count * sizeof(EventHandlerRef));
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **)theHandlers);
for (int i = 0; i < count; i++)
RemoveEventHandler(theHandlers[i]);
CFDictionaryRemoveAllValues(mHandlers);
CFRelease (mHandlers);
free(theHandlers);
}
}

void CarbonEventHandler::WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList)
{
if (mHandlers == NULL)
mHandlers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
EventHandlerRef handler;
if (CFDictionaryGetValueIfPresent (mHandlers, target, (const void **)&handler)) // if there is already a handler for the target, add the type
verify_noerr(AddEventTypesToHandler(handler, inNumTypes, inList));
else {
verify_noerr(InstallEventHandler(target, TheEventHandler, inNumTypes, inList, this, &handler));
CFDictionaryAddValue(mHandlers, target, handler);
}
}

+ 65
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUCarbonViewBase/CarbonEventHandler.h View File

@@ -0,0 +1,65 @@
/* 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.
*/
#ifndef __CarbonEventHandler_h__
#define __CarbonEventHandler_h__

#include <Carbon/Carbon.h>

/*! @class CarbonEventHandler */
class CarbonEventHandler {
public:
/*! @ctor CarbonEventHandler */
CarbonEventHandler();
/*! @dtor ~CarbonEventHandler */
virtual ~CarbonEventHandler();
/*! @method WantEventTypes */
virtual void WantEventTypes(EventTargetRef target, UInt32 inNumTypes, const EventTypeSpec *inList);

/*! @method HandleEvent */
virtual bool HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event) = 0;

protected:
/*! @var mHandlers */
CFMutableDictionaryRef mHandlers;
};

#endif // __CarbonEventHandler_h__

+ 760
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp View File

@@ -0,0 +1,760 @@
/* 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 "AUInstrumentBase.h"

#if DEBUG
#define DEBUG_PRINT 0
#define DEBUG_PRINT_RENDER 0
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////

const UInt32 kEventQueueSize = 1024;

AUInstrumentBase::AUInstrumentBase(
ComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups,
UInt32 numParts)
: MusicDeviceBase(inInstance, numInputs, numOutputs, numGroups, numParts),
mAbsoluteSampleFrame(0),
mEventQueue(kEventQueueSize),
mNumNotes(0),
mNumActiveNotes(0),
mMaxActiveNotes(0),
mNotes(0),
mNoteSize(0)
{
#if DEBUG_PRINT
printf("new AUInstrumentBase\n");
#endif
mFreeNotes.mState = kNoteState_Free;
}

AUInstrumentBase::~AUInstrumentBase()
{
#if DEBUG_PRINT
printf("delete AUInstrumentBase\n");
#endif
}

AUElement* AUInstrumentBase::CreateElement( AudioUnitScope scope,
AudioUnitElement element)
{
#if DEBUG_PRINT
printf("AUInstrumentBase::CreateElement %d %d\n", scope, element);
#endif
switch (scope)
{
case kAudioUnitScope_Group :
return new SynthGroupElement(this, element);
case kAudioUnitScope_Part :
return new SynthPartElement(this, element);
default :
return AUBase::CreateElement(scope, element);
}
}


void AUInstrumentBase::SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteDataSize)
{
#if DEBUG_PRINT
printf("AUInstrumentBase::SetNotes %d %d %08X %d\n", inNumNotes, inMaxActiveNotes, inNotes, inNoteDataSize);
#endif
mNumNotes = inNumNotes;
mMaxActiveNotes = inMaxActiveNotes;
mNoteSize = inNoteDataSize;
mNotes = inNotes;
for (UInt32 i=0; i<mNumNotes; ++i)
{
SynthNote *note = GetNote(i);
note->Reset();
mFreeNotes.AddNote(note);
}
}

UInt32 AUInstrumentBase::CountActiveNotes()
{
// debugging tool.
UInt32 sum = 0;
for (UInt32 i=0; i<mNumNotes; ++i)
{
SynthNote *note = GetNote(i);
if (note->mState <= kNoteState_Released)
sum++;
}
return sum;
}

void AUInstrumentBase::AddFreeNote(SynthNote* inNote)
{
if (inNote->mState != kNoteState_FastReleased)
DecNumActiveNotes();
#if DEBUG_PRINT
printf("AUInstrumentBase::AddFreeNote mNumActiveNotes %lu\n", mNumActiveNotes);
#endif
mFreeNotes.AddNote(inNote);
}

OSStatus AUInstrumentBase::Initialize()
{
/*
TO DO:
Currently ValidFormat will check and validate that the num channels is not being
changed if the AU doesn't support the SupportedNumChannels property - which is correct
What needs to happen here is that IFF the AU does support this property, (ie, the AU
can be configured to have different num channels than its original configuration) then
the state of the AU at Initialization needs to be validated.
This is work still to be done - see AUEffectBase for the kind of logic that needs to be applied here
*/

// override to call SetNotes
mNoteIDCounter = 128; // reset this every time we initialise
mAbsoluteSampleFrame = 0;
return noErr;
}

void AUInstrumentBase::Cleanup()
{
}


OSStatus AUInstrumentBase::Reset( AudioUnitScope inScope,
AudioUnitElement inElement)
{
#if DEBUG_PRINT
printf("AUInstrumentBase::Reset\n");
#endif
if (inScope == kAudioUnitScope_Global)
{
// kill all notes..
mFreeNotes.Empty();
for (UInt32 i=0; i<mNumNotes; ++i)
{
SynthNote *note = GetNote(i);
if (note->IsSounding())
note->Kill(0);
note->ListRemove();
mFreeNotes.AddNote(note);
}
mNumActiveNotes = 0;
mAbsoluteSampleFrame = 0;

// empty lists.
UInt32 numGroups = Groups().GetNumberOfElements();
for (UInt32 j = 0; j < numGroups; ++j)
{
SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
group->Reset();
}
}
return MusicDeviceBase::Reset(inScope, inElement);
}

void AUInstrumentBase::PerformEvents(const AudioTimeStamp& inTimeStamp)
{
#if DEBUG_PRINT_RENDER
printf("AUInstrumentBase::PerformEvents\n");
#endif
SynthEvent *event;
SynthGroupElement *group;
while ((event = mEventQueue.ReadItem()) != NULL)
{
#if DEBUG_PRINT_RENDER
printf("event %08X %d\n", event, event->GetEventType());
#endif
switch(event->GetEventType())
{
case SynthEvent::kEventType_NoteOn :
RealTimeStartNote(GetElForGroupID (event->GetGroupID()), event->GetNoteID(),
event->GetOffsetSampleFrame(), *event->GetParams());
break;
case SynthEvent::kEventType_NoteOff :
RealTimeStopNote(event->GetGroupID(), event->GetNoteID(),
event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_SustainOn :
group = GetElForGroupID (event->GetGroupID());
group->SustainOn(event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_SustainOff :
group = GetElForGroupID (event->GetGroupID());
group->SustainOff(event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_SostenutoOn :
group = GetElForGroupID (event->GetGroupID());
group->SostenutoOn(event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_SostenutoOff :
group = GetElForGroupID (event->GetGroupID());
group->SostenutoOff(event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_AllNotesOff :
group = GetElForGroupID (event->GetGroupID());
group->AllNotesOff(event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_AllSoundOff :
group = GetElForGroupID (event->GetGroupID());
group->AllSoundOff(event->GetOffsetSampleFrame());
break;
case SynthEvent::kEventType_ResetAllControllers :
group = GetElForGroupID (event->GetGroupID());
group->ResetAllControllers(event->GetOffsetSampleFrame());
break;
}
mEventQueue.AdvanceReadPtr();
}
}

OSStatus AUInstrumentBase::Render( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
PerformEvents(inTimeStamp);

UInt32 numOutputs = Outputs().GetNumberOfElements();
for (UInt32 j = 0; j < numOutputs; ++j)
{
AudioBufferList& bufferList = GetOutput(j)->GetBufferList();
for (UInt32 k = 0; k < bufferList.mNumberBuffers; ++k)
{
memset(bufferList.mBuffers[k].mData, 0, bufferList.mBuffers[k].mDataByteSize);
}
}
UInt32 numGroups = Groups().GetNumberOfElements();
for (UInt32 j = 0; j < numGroups; ++j)
{
SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
OSStatus err = group->Render(inNumberFrames);
if (err) return err;
}
mAbsoluteSampleFrame += inNumberFrames;
return noErr;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInstrumentBase::ValidFormat
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool AUInstrumentBase::ValidFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inNewFormat)
{
// if the AU supports this, then we should just let this go through to the Init call
if (SupportedNumChannels (NULL))
return MusicDeviceBase::ValidFormat(inScope, inElement, inNewFormat);

bool isGood = MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat);
if (!isGood) return false;
// if we get to here, then the basic criteria is that the
// num channels cannot change on an existing bus
AUIOElement *el = GetIOElement (inScope, inElement);
return (el->GetStreamFormat().NumberChannels() == inNewFormat.NumberChannels());
}


bool AUInstrumentBase::StreamFormatWritable( AudioUnitScope scope,
AudioUnitElement element)
{
return IsInitialized() ? false : true;
}

OSStatus AUInstrumentBase::RealTimeStartNote( SynthGroupElement *inGroup,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams)
{
return noErr;
}

SynthGroupElement * AUInstrumentBase::GetElForGroupID (MusicDeviceGroupID inGroupID)
{
AUScope & groups = Groups();
unsigned int numEls = groups.GetNumberOfElements();
SynthGroupElement* unassignedEl = NULL;
for (unsigned int i = 0; i < numEls; ++i) {
SynthGroupElement* el = reinterpret_cast<SynthGroupElement*>(groups.GetElement(i));
if (el->GroupID() == inGroupID)
return el;
if (el->GroupID() == SynthGroupElement::kUnassignedGroup) {
unassignedEl = el;
break; // we fill this up from the start of the group scope vector
}
}
if (unassignedEl) {
unassignedEl->SetGroupID(inGroupID);
return unassignedEl;
}
throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
}

OSStatus AUInstrumentBase::RealTimeStopNote(
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame)
{
#if DEBUG_PRINT
printf("AUInstrumentBase::RealTimeStopNote %d %d\n", inGroupID, inNoteInstanceID);
#endif
SynthGroupElement *gp = (inGroupID == kMusicNoteEvent_Unused
? GetElForNoteID (inNoteInstanceID)
: GetElForGroupID(inGroupID));

gp->NoteOff (inNoteInstanceID, inOffsetSampleFrame);
return noErr;
}

SynthGroupElement * AUInstrumentBase::GetElForNoteID (NoteInstanceID inNoteID)
{
#if DEBUG_PRINT
printf("GetElForNoteID id %d\n", (int)inNoteID);
#endif
if (!mNotes) throw std::runtime_error("no notes");
for (unsigned int i = 0; i < mNumNotes; ++i) {
if (inNoteID == mNotes[i].GetNoteID()) {
return mNotes[i].GetGroup();
}
}
throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
}

OSStatus AUInstrumentBase::StartNote( MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams)
{
#if DEBUG_PRINT
printf("AUInstrumentBase::StartNote %d\n", inGroupID);
#endif
OSStatus err = noErr;
NoteInstanceID noteID;
if (outNoteInstanceID) {
noteID = NextNoteID();
*outNoteInstanceID = noteID;
} else
noteID = (UInt32)inParams.mPitch;
if (InRenderThread ())
{
err = RealTimeStartNote(
GetElForGroupID(inGroupID),
noteID,
inOffsetSampleFrame,
inParams);
}
else
{
SynthEvent *event = mEventQueue.WriteItem();
if (!event) return -1; // queue full

event->Set(
SynthEvent::kEventType_NoteOn,
inGroupID,
noteID,
inOffsetSampleFrame,
&inParams
);
mEventQueue.AdvanceWritePtr();
}
return err;
}

OSStatus AUInstrumentBase::StopNote( MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame)
{
#if DEBUG_PRINT
printf("AUInstrumentBase::StopNote %d %d\n", inGroupID, inNoteInstanceID);
#endif
OSStatus err = noErr;

if (InRenderThread ())
{
err = RealTimeStopNote(
inGroupID,
inNoteInstanceID,
inOffsetSampleFrame);
}
else
{
SynthEvent *event = mEventQueue.WriteItem();
if (!event) return -1; // queue full

event->Set(
SynthEvent::kEventType_NoteOff,
inGroupID,
inNoteInstanceID,
inOffsetSampleFrame,
NULL
);
mEventQueue.AdvanceWritePtr();
}
return err;
}

OSStatus AUInstrumentBase::SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame)
{
if (InRenderThread ())
{
SynthGroupElement *group = GetElForGroupID(inGroupID);
switch (inEventType)
{
case SynthEvent::kEventType_SustainOn :
group->SustainOn(inOffsetSampleFrame);
break;
case SynthEvent::kEventType_SustainOff :
group->SustainOff(inOffsetSampleFrame);
break;
case SynthEvent::kEventType_SostenutoOn :
group->SostenutoOn(inOffsetSampleFrame);
break;
case SynthEvent::kEventType_SostenutoOff :
group->SostenutoOff(inOffsetSampleFrame);
break;
case SynthEvent::kEventType_AllNotesOff :
group->AllNotesOff(inOffsetSampleFrame);
mNumActiveNotes = CountActiveNotes();
break;
case SynthEvent::kEventType_AllSoundOff :
group->AllSoundOff(inOffsetSampleFrame);
mNumActiveNotes = CountActiveNotes();
break;
case SynthEvent::kEventType_ResetAllControllers :
group->ResetAllControllers(inOffsetSampleFrame);
break;
}
}
else
{
SynthEvent *event = mEventQueue.WriteItem();
if (!event) return -1; // queue full

event->Set(inEventType, inGroupID, 0, 0, NULL);
mEventQueue.AdvanceWritePtr();
}
return noErr;
}

OSStatus AUInstrumentBase::HandleControlChange( UInt8 inChannel,
UInt8 inController,
UInt8 inValue,
UInt32 inStartFrame)
{
GetControls(inChannel)->mControls[inController] = inValue;
switch (inController)
{
case kMidiController_Sustain :
if (inValue >= 64)
SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOn, inStartFrame);
else
SendPedalEvent(inChannel, SynthEvent::kEventType_SustainOff, inStartFrame);
break;
case kMidiController_Sostenuto :
if (inValue >= 64)
SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOn, inStartFrame);
else
SendPedalEvent(inChannel, SynthEvent::kEventType_SostenutoOff, inStartFrame);
break;
}
return noErr;
}
OSStatus AUInstrumentBase::HandlePitchWheel( UInt8 inChannel,
UInt8 inPitch1,
UInt8 inPitch2,
UInt32 inStartFrame)
{
MidiControls* controls = GetControls(inChannel);
controls->mPitchBend = (inPitch2 << 7) | inPitch1;
controls->mFPitchBend = (float)((SInt16)controls->mPitchBend - 8192) / 8192.;
return noErr;
}

OSStatus AUInstrumentBase::HandleChannelPressure(UInt8 inChannel,
UInt8 inValue,
UInt32 inStartFrame)
{
GetControls(inChannel)->mMonoPressure = inValue;
return noErr;
}


OSStatus AUInstrumentBase::HandleProgramChange( UInt8 inChannel,
UInt8 inValue)
{
GetControls(inChannel)->mMonoPressure = inValue;
return noErr;
}


OSStatus AUInstrumentBase::HandlePolyPressure( UInt8 inChannel,
UInt8 inKey,
UInt8 inValue,
UInt32 inStartFrame)
{
GetControls(inChannel)->mPolyPressure[inKey] = inValue;
return noErr;
}


OSStatus AUInstrumentBase::HandleResetAllControllers( UInt8 inChannel)
{
SendPedalEvent (inChannel, SynthEvent::kEventType_ResetAllControllers, 0);
return noErr;
}

OSStatus AUInstrumentBase::HandleAllNotesOff( UInt8 inChannel)
{
SendPedalEvent (inChannel, SynthEvent::kEventType_AllNotesOff, 0);
return noErr;
}

OSStatus AUInstrumentBase::HandleAllSoundOff( UInt8 inChannel)
{
SendPedalEvent (inChannel, SynthEvent::kEventType_AllSoundOff, 0);
return noErr;
}

SynthNote* AUInstrumentBase::GetAFreeNote(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("GetAFreeNote size %d\n", mFreeNotes.Length());
#endif
SynthNote *note = mFreeNotes.mHead;
if (note)
{
mFreeNotes.RemoveNote(note);
return note;
}
return VoiceStealing(inFrame, true);
}

SynthNote* AUInstrumentBase::VoiceStealing(UInt32 inFrame, bool inKillIt)
{

#if DEBUG_PRINT
printf("enter voice stealing\n");
#endif
// free list was empty so we need to kill a note.
UInt32 startState = inKillIt ? kNoteState_FastReleased : kNoteState_Released;
for (UInt32 i = startState; i <= startState; --i)
{
#if DEBUG_PRINT
printf(" steal state %d\n", i);
#endif
UInt32 numGroups = Groups().GetNumberOfElements();
for (UInt32 j = 0; j < numGroups; ++j)
{
SynthGroupElement *group = (SynthGroupElement*)Groups().GetElement(j);
#if DEBUG_PRINT
printf(" steal group %d size %d\n", j, group->mNoteList[i].Length());
#endif
if (group->mNoteList[i].NotEmpty()) {
#if DEBUG_PRINT
printf("not empty %d %d\n", i, j);
#endif
SynthNote *note = group->mNoteList[i].FindMostQuietNote();
if (inKillIt) {
#if DEBUG_PRINT
printf("--=== KILL ===---\n");
#endif
note->mRelativeKillFrame = inFrame;
note->Kill(inFrame);
group->mNoteList[i].RemoveNote(note);
if (i != kNoteState_FastReleased)
DecNumActiveNotes();
return note;
} else {
#if DEBUG_PRINT
printf("--=== FAST RELEASE ===---\n");
#endif
group->mNoteList[i].RemoveNote(note);
note->FastRelease(inFrame);
group->mNoteList[kNoteState_FastReleased].AddNote(note);
DecNumActiveNotes(); // kNoteState_FastReleased counts as inactive for voice stealing purposes.
return NULL;
}
}
}
}
#if DEBUG_PRINT
printf("no notes to steal????\n");
#endif
return NULL; // It should be impossible to get here. It means there were no notes to kill in any state.
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////

AUMonotimbralInstrumentBase::AUMonotimbralInstrumentBase(
ComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups,
UInt32 numParts)
: AUInstrumentBase(inInstance, numInputs, numOutputs, numGroups, numParts)
{
}

OSStatus AUMonotimbralInstrumentBase::RealTimeStartNote(
SynthGroupElement *inGroup,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams)
{
#if DEBUG_PRINT_RENDER
printf("AUMonotimbralInstrumentBase::RealTimeStartNote %d\n", inNoteInstanceID);
#endif

if (NumActiveNotes() + 1 > MaxActiveNotes())
{
VoiceStealing(inOffsetSampleFrame, false);
}
SynthNote *note = GetAFreeNote(inOffsetSampleFrame);
if (!note) return -1;
IncNumActiveNotes();
note->AttackNote(NULL, inGroup, inNoteInstanceID,
mAbsoluteSampleFrame + inOffsetSampleFrame, inOffsetSampleFrame, inParams);
inGroup->mNoteList[kNoteState_Attacked].AddNote(note);
return noErr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////


OSStatus AUMultitimbralInstrumentBase::GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus result = noErr;
switch (inID)
{
case kMusicDeviceProperty_PartGroup:
if (inScope != kAudioUnitScope_Part) return kAudioUnitErr_InvalidScope;
outDataSize = sizeof(UInt32);
outWritable = true;
break;

default:
result = AUInstrumentBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
}
return result;
}

OSStatus AUMultitimbralInstrumentBase::GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus result = noErr;

switch (inID)
{
case kMusicDeviceProperty_PartGroup:
if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
// ??
return -1; //unimpl
break;

default:
result = AUInstrumentBase::GetProperty (inID, inScope, inElement, outData);
}
return result;
}



OSStatus AUMultitimbralInstrumentBase::SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
OSStatus result = noErr;

switch (inID)
{
case kMusicDeviceProperty_PartGroup:
if (inScope != kAudioUnitScope_Group) return kAudioUnitErr_InvalidScope;
// ??
return -1; //unimpl
break;

default:
result = MusicDeviceBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
}
return result;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 246
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/AUInstrumentBase.h View File

@@ -0,0 +1,246 @@
/* 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.
*/
#ifndef __AUInstrumentBase__
#define __AUInstrumentBase__

#include <vector>
#include <stdexcept>
#include <AudioUnit/AudioUnit.h>
#include <CoreAudio/CoreAudio.h>
#include "MusicDeviceBase.h"
#include "LockFreeFIFO.h"
#include "SynthEvent.h"
#include "SynthNote.h"
#include "SynthElement.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef LockFreeFIFOWithFree<SynthEvent> SynthEventQueue;

class AUInstrumentBase : public MusicDeviceBase
{
public:
AUInstrumentBase(
ComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups = 32,
UInt32 numParts = 0);
virtual ~AUInstrumentBase();

virtual OSStatus Initialize();
virtual void Cleanup();
virtual AUElement* CreateElement( AudioUnitScope scope,
AudioUnitElement element);

virtual OSStatus Reset( AudioUnitScope inScope,
AudioUnitElement inElement);
virtual bool ValidFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inNewFormat);

virtual bool StreamFormatWritable( AudioUnitScope scope,
AudioUnitElement element);

virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames);

virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams);

virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);

virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams);
virtual OSStatus RealTimeStopNote( MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);
virtual OSStatus HandleControlChange( UInt8 inChannel,
UInt8 inController,
UInt8 inValue,
UInt32 inStartFrame);
virtual OSStatus HandlePitchWheel( UInt8 inChannel,
UInt8 inPitch1,
UInt8 inPitch2,
UInt32 inStartFrame);
virtual OSStatus HandleChannelPressure( UInt8 inChannel,
UInt8 inValue,
UInt32 inStartFrame);

virtual OSStatus HandleProgramChange( UInt8 inChannel,
UInt8 inValue);

virtual OSStatus HandlePolyPressure( UInt8 inChannel,
UInt8 inKey,
UInt8 inValue,
UInt32 inStartFrame);

virtual OSStatus HandleResetAllControllers( UInt8 inChannel);
virtual OSStatus HandleAllNotesOff( UInt8 inChannel);
virtual OSStatus HandleAllSoundOff( UInt8 inChannel);

SynthNote* GetNote(UInt32 inIndex)
{
if (!mNotes) throw std::runtime_error("no notes");
return (SynthNote*)((char*)mNotes + inIndex * mNoteSize);
}
SynthNote* GetAFreeNote(UInt32 inFrame);
void AddFreeNote(SynthNote* inNote);
MidiControls* GetControls( MusicDeviceGroupID inChannel)
{
SynthGroupElement *group = GetElForGroupID(inChannel);
return &(group->mMidiControls);
}


protected:

UInt32 NextNoteID() { return IncrementAtomic(&mNoteIDCounter); }
// call SetNotes in your Initialize() method to give the base class your note structures and to set the maximum
// number of active notes. inNoteData should be an array of size inMaxActiveNotes.
void SetNotes(UInt32 inNumNotes, UInt32 inMaxActiveNotes, SynthNote* inNotes, UInt32 inNoteSize);
void PerformEvents( const AudioTimeStamp & inTimeStamp);
OSStatus SendPedalEvent(MusicDeviceGroupID inGroupID, UInt32 inEventType, UInt32 inOffsetSampleFrame);
virtual SynthNote* VoiceStealing(UInt32 inFrame, bool inKillIt);
UInt32 MaxActiveNotes() const { return mMaxActiveNotes; }
UInt32 NumActiveNotes() const { return mNumActiveNotes; }
void IncNumActiveNotes() { mNumActiveNotes ++; }
void DecNumActiveNotes() { mNumActiveNotes --; }
UInt32 CountActiveNotes();
// this call throws if there's no assigned element for the group ID
SynthGroupElement * GetElForGroupID (MusicDeviceGroupID inGroupID);
SynthGroupElement * GetElForNoteID (NoteInstanceID inNoteID);

SInt64 mAbsoluteSampleFrame;

private:
SInt32 mNoteIDCounter;
SynthEventQueue mEventQueue;
UInt32 mNumNotes;
UInt32 mNumActiveNotes;
UInt32 mMaxActiveNotes;
SynthNote* mNotes;
SynthNoteList mFreeNotes;
UInt32 mNoteSize;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////

class AUMonotimbralInstrumentBase : public AUInstrumentBase
{
public:
AUMonotimbralInstrumentBase(
ComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups = 32,
UInt32 numParts = 0);
virtual OSStatus RealTimeStartNote( SynthGroupElement *inGroup,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////

// this is a work in progress! The mono-timbral one is finished though!
class AUMultitimbralInstrumentBase : public AUInstrumentBase
{
public:
AUMultitimbralInstrumentBase(
ComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups,
UInt32 numParts);
virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

virtual OSStatus GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);

virtual OSStatus SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);

private:

};

////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif


+ 167
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/LockFreeFIFO.h View File

@@ -0,0 +1,167 @@
/* 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 <Carbon/Carbon.h>


template <class ITEM>
class LockFreeFIFOWithFree
{
LockFreeFIFOWithFree(); // private, unimplemented.
public:
LockFreeFIFOWithFree(UInt32 inMaxSize)
: mReadIndex(0), mWriteIndex(0), mFreeIndex(0)
{
//assert(IsPowerOfTwo(inMaxSize));
mItems = new ITEM[inMaxSize];
mMask = inMaxSize - 1;
}
~LockFreeFIFOWithFree()
{
delete [] mItems;
}

void Reset()
{
FreeItems();
mReadIndex = 0;
mWriteIndex = 0;
mFreeIndex = 0;
}
ITEM* WriteItem()
{
//printf("WriteItem %d %d\n", mReadIndex, mWriteIndex);
FreeItems(); // free items on the write thread.
UInt32 nextWriteIndex = (mWriteIndex + 1) & mMask;
if (nextWriteIndex == mFreeIndex) return NULL;
return &mItems[mWriteIndex];
}
ITEM* ReadItem()
{
//printf("ReadItem %d %d\n", mReadIndex, mWriteIndex);
if (mReadIndex == mWriteIndex) return NULL;
return &mItems[mReadIndex];
}
// the CompareAndSwap will always succeed. We use CompareAndSwap because it calls the PowerPC sync instruction,
// plus any processor bug workarounds for various CPUs.
void AdvanceWritePtr() { CompareAndSwap(mWriteIndex, (mWriteIndex + 1) & mMask, (UInt32*)&mWriteIndex); }
void AdvanceReadPtr() { CompareAndSwap(mReadIndex, (mReadIndex + 1) & mMask, (UInt32*)&mReadIndex); }
private:
ITEM* FreeItem()
{
if (mFreeIndex == mReadIndex) return NULL;
return &mItems[mFreeIndex];
}
void AdvanceFreePtr() { CompareAndSwap(mFreeIndex, (mFreeIndex + 1) & mMask, (UInt32*)&mFreeIndex); }
void FreeItems()
{
ITEM* item;
while ((item = FreeItem()) != NULL)
{
item->Free();
AdvanceFreePtr();
}
}
volatile UInt32 mReadIndex, mWriteIndex, mFreeIndex;
UInt32 mMask;
ITEM *mItems;
};



// Same as above but no free.

template <class ITEM>
class LockFreeFIFO
{
LockFreeFIFO(); // private, unimplemented.
public:
LockFreeFIFO(UInt32 inMaxSize)
: mReadIndex(0), mWriteIndex(0)
{
//assert(IsPowerOfTwo(inMaxSize));
mItems = new ITEM[inMaxSize];
mMask = inMaxSize - 1;
}
~LockFreeFIFO()
{
delete [] mItems;
}
void Reset()
{
mReadIndex = 0;
mWriteIndex = 0;
}
ITEM* WriteItem()
{
UInt32 nextWriteIndex = (mWriteIndex + 1) & mMask;
if (nextWriteIndex == mReadIndex) return NULL;
return &mItems[mWriteIndex];
}
ITEM* ReadItem()
{
if (mReadIndex == mWriteIndex) return NULL;
return &mItems[mReadIndex];
}
// the CompareAndSwap will always succeed. We use CompareAndSwap because it calls the PowerPC sync instruction,
// plus any processor bug workarounds for various CPUs.
void AdvanceWritePtr() { CompareAndSwap(mWriteIndex, (mWriteIndex + 1) & mMask, (UInt32*)&mWriteIndex); }
void AdvanceReadPtr() { CompareAndSwap(mReadIndex, (mReadIndex + 1) & mMask, (UInt32*)&mReadIndex); }
private:
volatile UInt32 mReadIndex, mWriteIndex;
UInt32 mMask;
ITEM *mItems;
};


+ 266
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.cpp View File

@@ -0,0 +1,266 @@
/* 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 "SynthElement.h"
#include "AUInstrumentBase.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////
MidiControls::MidiControls()
{
Reset();
}

void MidiControls::Reset()
{
memset(this, 0, sizeof(MidiControls));
mControls[kMidiController_Pan] = 64;
mControls[kMidiController_Expression] = 127;
mPitchBendDepth = 2 << 7;
mFPitchBendDepth = 2.;
}


SynthElement::SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement)
: AUElement(audioUnit), mName(0), mIndex(inElement)
{
}

SynthElement::~SynthElement()
{
if (mName) CFRelease(mName);
}

SynthGroupElement::SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement)
: SynthElement(audioUnit, inElement), mSustainIsOn(false), mSostenutoIsOn(false), mOutputBus(0), mGroupID(kUnassignedGroup)
{
#if DEBUG_PRINT
printf("SynthGroupElement::SynthGroupElement %d\n", inElement);
#endif
for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
mNoteList[i].mState = i;
}

void SynthGroupElement::SetGroupID (MusicDeviceGroupID inGroup)
{
// can't re-assign a group once its been assigned
if (mGroupID != kUnassignedGroup) throw static_cast<OSStatus>(kAudioUnitErr_InvalidElement);
mGroupID = inGroup;
}

void SynthGroupElement::Reset()
{
#if DEBUG_PRINT
printf("SynthGroupElement::Reset\n");
#endif
mMidiControls.Reset();
for (UInt32 i=0; i<kNumberOfSoundingNoteStates; ++i)
mNoteList[i].Empty();
}

SynthPartElement::SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement)
: SynthElement(audioUnit, inElement)
{
}

void SynthGroupElement::NoteOff(NoteInstanceID inNoteID, UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::NoteOff %d\n", inNoteID);
#endif
SynthNote *note = mNoteList[kNoteState_Attacked].mHead;
// see if this note is attacked.
while (note && note->mNoteID != inNoteID)
{
#if DEBUG_PRINT
printf(" ? %08X %d\n", note, note->mNoteID);
#endif
note = note->mNext;
}
#if DEBUG_PRINT
printf(" found %08X\n", note);
#endif
if (note)
{
#if DEBUG_PRINT
printf(" old state %d\n", note->mState);
#endif
mNoteList[kNoteState_Attacked].RemoveNote(note);
note->Release(inFrame);
if (mSustainIsOn) {
mNoteList[kNoteState_ReleasedButSustained].AddNote(note);
} else {
mNoteList[kNoteState_Released].AddNote(note);
}
#if DEBUG_PRINT
printf(" new state %d\n", note->mState);
#endif
}
else if (mSostenutoIsOn)
{
// see if this note is sostenutoed.
note = mNoteList[kNoteState_Sostenutoed].mHead;
while (note && note->mNoteID != inNoteID)
note = note->mNext;
if (note)
{
mNoteList[kNoteState_Sostenutoed].RemoveNote(note);
mNoteList[kNoteState_ReleasedButSostenutoed].AddNote(note);
}
}
}

void SynthGroupElement::NoteEnded(SynthNote *inNote, UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::NoteEnded %d %d\n", inNote->mNoteID, inNote->mState);
#endif
SynthNoteList *list = mNoteList + inNote->mState;
list->RemoveNote(inNote);
GetAUInstrument()->AddFreeNote(inNote);
}

void SynthGroupElement::SostenutoOn(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::SostenutoOn\n");
#endif
mSostenutoIsOn = true;
mNoteList[kNoteState_Sostenutoed].TransferAllFrom(&mNoteList[kNoteState_Attacked], inFrame);
}

void SynthGroupElement::SostenutoOff(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::SostenutoOff\n");
#endif
mSostenutoIsOn = false;
mNoteList[kNoteState_Attacked].TransferAllFrom(&mNoteList[kNoteState_Sostenutoed], inFrame);
if (mSustainIsOn)
mNoteList[kNoteState_ReleasedButSustained].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
else
mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSostenutoed], inFrame);
}


void SynthGroupElement::SustainOn(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::SustainOn\n");
#endif
mSustainIsOn = true;
}

void SynthGroupElement::SustainOff(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::SustainOff\n");
#endif
mSustainIsOn = false;
mNoteList[kNoteState_Released].TransferAllFrom(&mNoteList[kNoteState_ReleasedButSustained], inFrame);
}

void SynthGroupElement::AllNotesOff(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::AllNotesOff\n");
#endif
SynthNote *note;
for (UInt32 i=0 ; i<kNumberOfActiveNoteStates; ++i)
{
note = mNoteList[i].mHead;
while (note)
{
SynthNote *nextNote = note->mNext;
mNoteList[i].RemoveNote(note);
note->FastRelease(inFrame);
mNoteList[kNoteState_FastReleased].AddNote(note);
note = nextNote;
}
}
}

void SynthGroupElement::AllSoundOff(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::AllSoundOff\n");
#endif
AllNotesOff(inFrame);
}

void SynthGroupElement::ResetAllControllers(UInt32 inFrame)
{
#if DEBUG_PRINT
printf("SynthGroupElement::ResetAllControllers\n");
#endif
mMidiControls.Reset();
}

OSStatus SynthGroupElement::Render(UInt32 inNumberFrames)
{
SynthNote *note;
AudioBufferList& bufferList = GetAudioUnit()->GetOutput(mOutputBus)->GetBufferList();
for (UInt32 i=0 ; i<kNumberOfSoundingNoteStates; ++i)
{
note = mNoteList[i].mHead;
while (note)
{
#if DEBUG_PRINT
printf(" note %d %08X %d\n", i, note, inNumberFrames);
#endif
SynthNote *nextNote = note->mNext;
OSStatus err = note->Render(inNumberFrames, bufferList);
if (err) return err;
note = nextNote;
}
}
return noErr;
}



+ 262
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthElement.h View File

@@ -0,0 +1,262 @@
/* 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.
*/
#ifndef __SynthElement__
#define __SynthElement__

#include <Carbon/Carbon.h>
#include <AudioUnit/AudioUnit.h>
#include "MusicDeviceBase.h"
#include "SynthNoteList.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////
class AUInstrumentBase;

class SynthElement : public AUElement
{
public:
SynthElement(AUInstrumentBase *audioUnit, UInt32 inElement);
virtual ~SynthElement();

UInt32 GetIndex() const { return mIndex; }
AUInstrumentBase* GetAUInstrument() { return (AUInstrumentBase*)GetAudioUnit(); }
CFStringRef GetName() const { return mName; }
void SetName(CFStringRef inName)
{
CFStringRef oldName = mName;
mName = inName;
CFRetain(mName);
if (oldName) CFRelease(oldName);
}
private:
CFStringRef mName;
UInt32 mIndex;
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////
enum {
kMidiController_BankSelect = 0,
kMidiController_ModWheel = 1,
kMidiController_Breath = 2,
kMidiController_Foot = 4,
kMidiController_PortamentoTime = 5,
kMidiController_DataEntry = 6,
kMidiController_Volume = 7,
kMidiController_Balance = 8,
kMidiController_Pan = 10,
kMidiController_Expression = 11,

// these controls have a (0-63) == off, (64-127) == on
kMidiController_Sustain = 64, //hold1
kMidiController_Portamento = 65,
kMidiController_Sostenuto = 66,
kMidiController_Soft = 67,
kMidiController_LegatoPedal = 68,
kMidiController_Hold2Pedal = 69,
kMidiController_FilterResonance = 71,
kMidiController_ReleaseTime = 72,
kMidiController_AttackTime = 73,
kMidiController_Brightness = 74,
kMidiController_DecayTime = 75,
kMidiController_VibratoRate = 76,
kMidiController_VibratoDepth = 77,
kMidiController_VibratoDelay = 78,
// these controls have a 0-127 range and in MIDI they have no LSB (so fractional values are lost in MIDI)
kMidiController_ReverbLevel = 91,
kMidiController_ChorusLevel = 93,

kMidiController_AllSoundOff = 120,
kMidiController_ResetAllControllers = 121,
kMidiController_AllNotesOff = 123
};

struct MidiControls
{
MidiControls();
void Reset();
UInt8 mControls[128];
UInt8 mPolyPressure[128];
UInt8 mMonoPressure;
UInt8 mProgramChange;
UInt16 mPitchBend;
UInt16 mActiveRPN;
UInt16 mActiveNRPN;
UInt16 mActiveRPValue;
UInt16 mActiveNRPValue;
UInt16 mPitchBendDepth;
float mFPitchBendDepth;
float mFPitchBend;
SInt16 GetHiResControl(UInt32 inIndex) const
{
return ((mControls[inIndex] & 127) << 7) | (mControls[inIndex + 32] & 127);
}
void SetHiResControl(UInt32 inIndex, UInt8 inMSB, UInt8 inLSB)
{
mControls[inIndex] = inMSB;
mControls[inIndex + 32] = inLSB;
}
float GetControl(UInt32 inIndex) const
{
if (inIndex < 32) {
return (float)mControls[inIndex] + (float)mControls[inIndex + 32] / 127.;
} else {
return (float)mControls[inIndex];
}
}
float PitchBend() const { return mFPitchBend * mFPitchBendDepth; }
};


class SynthGroupElement : public SynthElement
{
public:
enum {
kUnassignedGroup = 0xFFFFFFFF
};
SynthGroupElement(AUInstrumentBase *audioUnit, UInt32 inElement);

void NoteOff(NoteInstanceID inNoteID, UInt32 inFrame);
void SustainOn(UInt32 inFrame);
void SustainOff(UInt32 inFrame);
void SostenutoOn(UInt32 inFrame);
void SostenutoOff(UInt32 inFrame);
void NoteEnded(SynthNote *inNote, UInt32 inFrame);
void AllNotesOff(UInt32 inFrame);
void AllSoundOff(UInt32 inFrame);
void ResetAllControllers(UInt32 inFrame);
UInt32 GetOutputBus() const { return mOutputBus; }
void SetOutputBus(UInt32 inBus) { mOutputBus = inBus; }
void Reset();
virtual OSStatus Render(UInt32 inNumberFrames);
float GetControl(UInt32 inIndex) const { return mMidiControls.GetControl(inIndex); }
float PitchBend() const { return mMidiControls.PitchBend(); }
MusicDeviceGroupID GroupID () const { return mGroupID; }
void SetGroupID (MusicDeviceGroupID inGroup);
private:
friend class AUInstrumentBase;
friend class AUMonotimbralInstrumentBase;
friend class AUMultitimbralInstrumentBase;
MidiControls mMidiControls;
bool mSustainIsOn;
bool mSostenutoIsOn;
UInt32 mOutputBus;
MusicDeviceGroupID mGroupID;
SynthNoteList mNoteList[kNumberOfSoundingNoteStates];
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct SynthKeyZone
{
UInt8 mLoNote;
UInt8 mHiNote;
UInt8 mLoVelocity;
UInt8 mHiVelocity;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////

const UInt32 kUnlimitedPolyphony = 0xFFFFFFFF;

class SynthPartElement : public SynthElement
{
public:
SynthPartElement(AUInstrumentBase *audioUnit, UInt32 inElement);

UInt32 GetGroupIndex() const { return mGroupIndex; }
bool InRange(Float32 inNote, Float32 inVelocity);
UInt32 GetMaxPolyphony() const { return mMaxPolyphony; }
void SetMaxPolyphony(UInt32 inMaxPolyphony) { mMaxPolyphony = inMaxPolyphony; }
private:
UInt32 mGroupIndex;
UInt32 mPatchIndex;
UInt32 mMaxPolyphony;
SynthKeyZone mKeyZone;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline AUInstrumentBase* SynthNote::GetAudioUnit() const
{
return (AUInstrumentBase*)mGroup->GetAudioUnit();
}

inline Float32 SynthNote::GetGlobalParameter(AudioUnitParameterID inParamID) const
{
return mGroup->GetAudioUnit()->Globals()->GetParameter(inParamID);
}

inline void SynthNote::NoteEnded(UInt32 inFrame)
{
mGroup->NoteEnded(this, inFrame);
mNoteID = 0xFFFFFFFF;
}

inline float SynthNote::PitchBend() const
{
return mGroup->PitchBend();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

+ 140
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthEvent.h View File

@@ -0,0 +1,140 @@
/* 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.
*/
/* You can either fill in code here or remove this and create or add new files. */

#ifndef __SynthEvent__
#define __SynthEvent__

#include <Carbon/Carbon.h>
#include <AudioUnit/AudioUnit.h>
#include <CoreAudio/CoreAudio.h>
#include "MusicDeviceBase.h"
#include <stdexcept>

////////////////////////////////////////////////////////////////////////////////////////////////////////////


class SynthEvent
{
public:
enum {
kEventType_NoteOn = 1,
kEventType_NoteOff = 2,
kEventType_SustainOn = 3,
kEventType_SustainOff = 4,
kEventType_SostenutoOn = 5,
kEventType_SostenutoOff = 6,
kEventType_AllNotesOff = 7,
kEventType_AllSoundOff = 8,
kEventType_ResetAllControllers = 9
};


SynthEvent() {}
~SynthEvent() {}

void Set(
UInt32 inEventType,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams* inNoteParams
)
{
mEventType = inEventType;
mGroupID = inGroupID;
mNoteID = inNoteID;
mOffsetSampleFrame = inOffsetSampleFrame;
if (inNoteParams)
{
UInt32 paramSize = offsetof(MusicDeviceNoteParams, mControls) + (inNoteParams->argCount-2)*sizeof(NoteParamsControlValue);
mNoteParams = inNoteParams->argCount > 3
? (MusicDeviceNoteParams*)malloc(paramSize)
: &mSmallNoteParams;
memcpy(mNoteParams, inNoteParams, paramSize);
}
else
mNoteParams = NULL;
}
void Free()
{
if (mNoteParams)
{
if (mNoteParams->argCount > 3)
free(mNoteParams);
mNoteParams = NULL;
}
}
UInt32 GetEventType() const { return mEventType; }
MusicDeviceGroupID GetGroupID() const { return mGroupID; }
NoteInstanceID GetNoteID() const { return mNoteID; }
UInt32 GetOffsetSampleFrame() const { return mOffsetSampleFrame; }
MusicDeviceNoteParams* GetParams() const { return mNoteParams; }

UInt32 GetArgCount() const { return mNoteParams->argCount; }
UInt32 NumberParameters() const { return mNoteParams->argCount - 2; }
Float32 GetNote() const { return mNoteParams->mPitch; }
Float32 GetVelocity() const { return mNoteParams->mVelocity; }
NoteParamsControlValue GetParameter(UInt32 inIndex) const
{
if (inIndex >= NumberParameters())
throw std::runtime_error("index out of range");
return mNoteParams->mControls[inIndex];
}
private:
UInt32 mEventType;
MusicDeviceGroupID mGroupID;
NoteInstanceID mNoteID;
UInt32 mOffsetSampleFrame;
MusicDeviceNoteParams* mNoteParams;
MusicDeviceNoteParams mSmallNoteParams; // inline a small one to eliminate malloc for the simple case.
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

+ 113
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.cpp View File

@@ -0,0 +1,113 @@
/* 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 "SynthNote.h"
#include "SynthElement.h"
#include "AUInstrumentBase.h"

void SynthNote::AttackNote(
SynthPartElement * inPart,
SynthGroupElement * inGroup,
NoteInstanceID inNoteID,
SInt64 inAbsoluteSampleFrame,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams)
{
#if DEBUG_PRINT
printf("SynthNote::AttackNote %d %d %d\n", inPart, inGroup->GroupID(), inNoteID);
#endif
mPart = inPart;
mGroup = inGroup;
mNoteID = inNoteID;

mAbsoluteStartFrame = inAbsoluteSampleFrame;
mRelativeStartFrame = inOffsetSampleFrame;
mRelativeReleaseFrame = -1;
mRelativeKillFrame = -1;

mPitch = inParams.mPitch;
mVelocity = inParams.mVelocity;
Attack(inParams);
}


void SynthNote::Reset()
{
mPart = 0;
mGroup = 0;
mAbsoluteStartFrame = 0;
mRelativeStartFrame = 0;
mRelativeReleaseFrame = 0;
mRelativeKillFrame = 0;
}

void SynthNote::Kill(UInt32 inFrame)
{
mRelativeKillFrame = inFrame;
}

void SynthNote::Release(UInt32 inFrame)
{
mRelativeReleaseFrame = inFrame;
}

void SynthNote::FastRelease(UInt32 inFrame)
{
mRelativeReleaseFrame = inFrame;
}

double SynthNote::TuningA() const
{
return 440.0;
}

double SynthNote::Frequency()
{
return TuningA() * pow(2., (mPitch - 69. + PitchBend()) / 12.);
}

double SynthNote::SampleRate()
{
return GetAudioUnit()->GetOutput(0)->GetStreamFormat().mSampleRate;
}



+ 170
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNote.h View File

@@ -0,0 +1,170 @@
/* 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.
*/
#ifndef __SynthNote__
#define __SynthNote__

#include <Carbon/Carbon.h>
#include <AudioUnit/AudioUnit.h>
#include <CoreAudio/CoreAudio.h>
#include "MusicDeviceBase.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

enum {
kNoteState_Attacked = 0,
kNoteState_Sostenutoed = 1,
kNoteState_ReleasedButSostenutoed = 2,
kNoteState_ReleasedButSustained = 3,
kNoteState_Released = 4,
kNoteState_FastReleased = 5,
kNoteState_Free = 6,
kNumberOfActiveNoteStates = 5,
kNumberOfSoundingNoteStates = 6,
kNumberOfNoteStates = 7
};

/*
This table describes the state transitions for SynthNotes

EVENT CURRENT STATE NEW STATE
note on free attacked
note off attacked (and sustain on) released but sustained
note off attacked released
note off sostenutoed released but sostenutoed
sustain on -- no changes --
sustain off released but sustained released
sostenuto on attacked sostenutoed
sostenuto off sostenutoed attacked
sostenuto off released but sostenutoed (and sustain on) released but sustained
sostenuto off released but sostenutoed released
end of note any state free
soft voice stealing any state fast released
hard voice stealing any state free
soft voice stealing happens when there is a note on event and NumActiveNotes > MaxActiveNotes
hard voice stealing happens when there is a note on event and NumActiveNotes == NumNotes (no free notes)
voice stealing removes the quietest note in the highest numbered state that has sounding notes.
*/

class SynthGroupElement;
class SynthPartElement;
class AUInstrumentBase;

struct SynthNote
{
SynthNote() :
mPrev(0), mNext(0), mState(kNoteState_Free),
mRelativeStartFrame(0),
mRelativeReleaseFrame(-1),
mRelativeKillFrame(-1)
{
}
virtual ~SynthNote() {}
virtual void Reset();
virtual void AttackNote(
SynthPartElement * inPart,
SynthGroupElement * inGroup,
NoteInstanceID inNoteID,
SInt64 inAbsoluteSampleFrame,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams
);
virtual OSStatus Render(UInt32 inNumFrames, AudioBufferList& inBufferList)=0;
virtual void Attack(const MusicDeviceNoteParams &inParams) = 0;
virtual void Kill(UInt32 inFrame); // voice is being stolen.
virtual void Release(UInt32 inFrame);
virtual void FastRelease(UInt32 inFrame);
virtual Float32 Amplitude() = 0; // used for finding quietest note for voice stealing.

virtual void NoteEnded(UInt32 inFrame);

SynthGroupElement* GetGroup() const { return mGroup; }
SynthPartElement* GetPart() const { return mPart; }
AUInstrumentBase* GetAudioUnit() const;

Float32 GetGlobalParameter(AudioUnitParameterID inParamID) const;

NoteInstanceID GetNoteID() const { return mNoteID; }
UInt32 GetState() const { return mState; }
Boolean IsSounding() const { return mState < kNumberOfSoundingNoteStates; }
Boolean IsActive() const { return mState < kNumberOfActiveNoteStates; }
SInt64 GetAbsoluteStartFrame() const { return mAbsoluteStartFrame; }
SInt32 GetRelativeStartFrame() const { return mRelativeStartFrame; }
SInt32 GetRelativeReleaseFrame() const { return mRelativeReleaseFrame; }
SInt32 GetRelativeKillFrame() const { return mRelativeKillFrame; }

void ListRemove() { mPrev = mNext = 0; } // only use when lists will be reset.

float PitchBend() const;
double TuningA() const;
virtual double Frequency(); // returns the frequency of note + pitch bend.
double SampleRate();

//private:
// friend class NoteList;
// linked list pointers
SynthNote *mPrev;
SynthNote *mNext;
SynthPartElement* mPart;
SynthGroupElement* mGroup;
NoteInstanceID mNoteID;
UInt32 mState;
SInt64 mAbsoluteStartFrame;
SInt32 mRelativeStartFrame;
SInt32 mRelativeReleaseFrame;
SInt32 mRelativeKillFrame;
Float32 mPitch;
Float32 mVelocity;
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif


+ 87
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.cpp View File

@@ -0,0 +1,87 @@
/* 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 "SynthNoteList.h"
#include <stdexcept>

void SynthNoteList::SanityCheck() const
{
if (mState >= kNumberOfNoteStates) {
throw std::runtime_error("mState is bad");
}
if (mHead == NULL) {
if (mTail != NULL)
throw std::runtime_error("mHead is NULL but not mTail");
return;
}
if (mTail == NULL) {
throw std::runtime_error("mTail is NULL but not mHead");
}
if (mHead->mPrev) {
throw std::runtime_error("mHead has a mPrev");
}
if (mTail->mNext) {
throw std::runtime_error("mTail has a mNext");
}
SynthNote *note = mHead;
while (note)
{
if (note->mState != mState)
throw std::runtime_error("note in wrong state");
if (note->mNext) {
if (note->mNext->mPrev != note)
throw std::runtime_error("bad link 1");
} else {
if (mTail != note)
throw std::runtime_error("note->mNext is nil, but mTail != note");
}
if (note->mPrev) {
if (note->mPrev->mNext != note)
throw std::runtime_error("bad link 2");
} else {
if (mHead != note)
throw std::runtime_error("note->mPrev is nil, but mHead != note");
}
note = note->mNext;
}
}

+ 226
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUInstrumentBase/SynthNoteList.h View File

@@ -0,0 +1,226 @@
/* 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.
*/
#ifndef __SynthNoteList__
#define __SynthNoteList__

#include "SynthNote.h"

#if DEBUG
#ifndef DEBUG_PRINT
#define DEBUG_PRINT 0
#endif
#define SANITY_CHECK 0
#endif

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct SynthNoteList
{
SynthNoteList() : mState(0xFFFFFFFF), mHead(0), mTail(0) {}
bool NotEmpty() const { return mHead != NULL; }
bool IsEmpty() const { return mHead == NULL; }
void Empty() {
#if SANITY_CHECK
SanityCheck();
#endif
mHead = mTail = NULL;
}
UInt32 Length() const {
#if SANITY_CHECK
SanityCheck();
#endif
UInt32 length = 0;
for (SynthNote* note = mHead; note; note = note->mNext)
length++;
return length;
};
void AddNote(SynthNote *inNote)
{
#if DEBUG_PRINT
printf("AddNote %d %08X\n", mState, inNote);
#endif
#if SANITY_CHECK
SanityCheck();
#endif
inNote->mState = mState;
inNote->mNext = mHead;
inNote->mPrev = NULL;
if (mHead) { mHead->mPrev = inNote; mHead = inNote; }
else mHead = mTail = inNote;
#if SANITY_CHECK
SanityCheck();
#endif
}
void RemoveNote(SynthNote *inNote)
{
#if DEBUG_PRINT
printf("RemoveNote\n");
#endif
#if SANITY_CHECK
SanityCheck();
#endif
if (inNote->mPrev) inNote->mPrev->mNext = inNote->mNext;
else mHead = inNote->mNext;

if (inNote->mNext) inNote->mNext->mPrev = inNote->mPrev;
else mTail = inNote->mPrev;
inNote->mPrev = 0;
inNote->mNext = 0;
#if SANITY_CHECK
SanityCheck();
#endif
}

void TransferAllFrom(SynthNoteList *inNoteList, UInt32 inFrame)
{
#if DEBUG_PRINT
printf("TransferAllFrom\n");
#endif
#if SANITY_CHECK
SanityCheck();
inNoteList->SanityCheck();
#endif
if (!inNoteList->mTail) return;
if (mState == kNoteState_Released)
{
for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
{
#if DEBUG_PRINT
printf("TransferAllFrom release %08X\n", note);
#endif
note->mState = mState;
note->Release(inFrame);
}
}
else
{
for (SynthNote* note = inNoteList->mHead; note; note = note->mNext)
{
note->mState = mState;
}
}
inNoteList->mTail->mNext = mHead;
if (mHead) mHead->mPrev = inNoteList->mTail;
else mTail = inNoteList->mTail;
mHead = inNoteList->mHead;
inNoteList->mHead = NULL;
inNoteList->mTail = NULL;
#if SANITY_CHECK
SanityCheck();
inNoteList->SanityCheck();
#endif
}
SynthNote* FindOldestNote()
{
#if DEBUG_PRINT
printf("FindOldestNote\n");
#endif
#if SANITY_CHECK
SanityCheck();
#endif
SInt64 minStartFrame = -1;
SynthNote* oldestNote = NULL;
for (SynthNote* note = mHead; note; note = note->mNext)
{
if (note->mAbsoluteStartFrame < minStartFrame)
{
oldestNote = note;
minStartFrame = note->mAbsoluteStartFrame;
}
}
return oldestNote;
}
SynthNote* FindMostQuietNote()
{
#if DEBUG_PRINT
printf("FindMostQuietNote\n");
#endif
Float32 minAmplitude = 1e9;
SInt64 minStartFrame = -1;
SynthNote* mostQuietNote = NULL;
for (SynthNote* note = mHead; note; note = note->mNext)
{
Float32 amp = note->Amplitude();
#if DEBUG_PRINT
printf(" amp %g minAmplitude %g\n", amp, minAmplitude);
#endif
if (amp < minAmplitude)
{
mostQuietNote = note;
minAmplitude = amp;
minStartFrame = note->mAbsoluteStartFrame;
}
else if (amp == minAmplitude && note->mAbsoluteStartFrame < minStartFrame)
{
// use earliest start time as a tie breaker
mostQuietNote = note;
minStartFrame = note->mAbsoluteStartFrame;
}
}
#if SANITY_CHECK
SanityCheck();
#endif
return mostQuietNote;
}
void SanityCheck() const;
UInt32 mState;
SynthNote *mHead;
SynthNote *mTail;
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#endif

+ 82
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/AUViewBase/AUViewLocalizedStringKeys.h View File

@@ -0,0 +1,82 @@
/* 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.
*/
#ifndef __AUViewLocalizedStringKeys_h__
#define __AUViewLocalizedStringKeys_h__

// ACCESS POINT:
#define kLocalizedStringBundle_AUView CFSTR("com.apple.audio.units.Components")
#define kLocalizedStringTable_AUView CFSTR("CustomUI")

// UNLOCALIZED STRINGS:
#define kAUViewUnlocalizedString_TitleSeparator CFSTR(": ")
// Generic View:
#define kAUViewLocalizedStringKey_AudioUnit CFSTR("Audio Unit")
#define kAUViewLocalizedStringKey_Manufacturer CFSTR("Manufacturer")
#define kAUViewLocalizedStringKey_FactoryPreset CFSTR("Factory Preset")
#define kAUViewLocalizedStringKey_Properties CFSTR("Properties")
#define kAUViewLocalizedStringKey_Parameters CFSTR("Parameters")
#define kAUViewLocalizedStringKey_Standard CFSTR("Standard")
#define kAUViewLocalizedStringKey_Expert CFSTR("Expert")
// AULoadCPU:
#define kAUViewLocalizedStringKey_RestrictCPULoad CFSTR("Restrict CPU Load")
#define kAUViewLocalizedStringKey_PercentSymbol CFSTR("%")
#define kAUViewLocalizedStringKey_NotApplicable CFSTR("n/a")
// AUDiskStreamingCheckbox:
#define kAUViewLocalizedStringKey_StreamFromDisk CFSTR("Stream From Disk")
// AURenderQualityPopup:
#define kAUViewLocalizedStringKey_RenderQuality CFSTR("Render Quality")
#define kAUViewLocalizedStringKey_Maximum CFSTR("Maximum")
#define kAUViewLocalizedStringKey_High CFSTR("High")
#define kAUViewLocalizedStringKey_Medium CFSTR("Medium")
#define kAUViewLocalizedStringKey_Low CFSTR("Low")
#define kAUViewLocalizedStringKey_Minimum CFSTR("Minimum")

// AUChannelLayoutPopUp:
#define kAUViewLocalizedStringKey_AudioChannelLayout CFSTR("Audio Channel Layout")
#endif //__AUViewLocalizedStringKeys_h__

+ 483
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.cpp View File

@@ -0,0 +1,483 @@
/* 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 "AUEffectBase.h"

/*
This class does not deal as well as it should with N-M effects...
The problem areas are (if the channels don't match):
ProcessInPlace if the channels don't match - there will be problems if InputChan != OutputChan
Bypass - its just passing the buffers through when not processing them

This will be fixed in a future update...
*/

//_____________________________________________________________________________
//
AUEffectBase::AUEffectBase( AudioComponentInstance audioUnit,
bool inProcessesInPlace ) :
AUBase(audioUnit, 1, 1), // 1 in bus, 1 out bus
mBypassEffect(false),
mParamSRDep (false),
mProcessesInPlace(inProcessesInPlace)
{
}

//_____________________________________________________________________________
//
AUEffectBase::~AUEffectBase()
{
Cleanup();
}

//_____________________________________________________________________________
//
void AUEffectBase::Cleanup()
{
for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it)
delete *it;
mKernelList.clear();
}


//_____________________________________________________________________________
//
OSStatus AUEffectBase::Initialize()
{
// get our current numChannels for input and output
SInt16 auNumInputs = (SInt16) GetInput(0)->GetStreamFormat().mChannelsPerFrame;
SInt16 auNumOutputs = (SInt16) GetOutput(0)->GetStreamFormat().mChannelsPerFrame;

// does the unit publish specific information about channel configurations?
const AUChannelInfo *auChannelConfigs = NULL;
UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);

if ((numIOconfigs > 0) && (auChannelConfigs != NULL))
{
bool foundMatch = false;
for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i)
{
SInt16 configNumInputs = auChannelConfigs[i].inChannels;
SInt16 configNumOutputs = auChannelConfigs[i].outChannels;
if ((configNumInputs < 0) && (configNumOutputs < 0))
{
// unit accepts any number of channels on input and output
if (((configNumInputs == -1) && (configNumOutputs == -2))
|| ((configNumInputs == -2) && (configNumOutputs == -1)))
{
foundMatch = true;
// unit accepts any number of channels on input and output IFF they are the same number on both scopes
}
else if (((configNumInputs == -1) && (configNumOutputs == -1)) && (auNumInputs == auNumOutputs))
{
foundMatch = true;
// unit has specified a particular number of channels on both scopes
}
else
continue;
}
else
{
// the -1 case on either scope is saying that the unit doesn't care about the
// number of channels on that scope
bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1);
bool outputMatch = (auNumOutputs == configNumOutputs) || (configNumOutputs == -1);
if (inputMatch && outputMatch)
foundMatch = true;
}
}
if (!foundMatch)
return kAudioUnitErr_FormatNotSupported;
}
else
{
// there is no specifically published channel info
// so for those kinds of effects, the assumption is that the channels (whatever their number)
// should match on both scopes
if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0))
{
return kAudioUnitErr_FormatNotSupported;
}
}

MaintainKernels();
return noErr;
}

OSStatus AUEffectBase::Reset( AudioUnitScope inScope,
AudioUnitElement inElement)
{
for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it) {
AUKernelBase *kernel = *it;
if (kernel != NULL)
kernel->Reset();
}
return AUBase::Reset(inScope, inElement);
}

OSStatus AUEffectBase::GetPropertyInfo (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
if (inScope == kAudioUnitScope_Global) {
switch (inID) {
case kAudioUnitProperty_BypassEffect:
outWritable = true;
outDataSize = sizeof (UInt32);
return noErr;
case kAudioUnitProperty_InPlaceProcessing:
outWritable = true;
outDataSize = sizeof (UInt32);
return noErr;
}
}
return AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
}


OSStatus AUEffectBase::GetProperty (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
if (inScope == kAudioUnitScope_Global) {
switch (inID) {
case kAudioUnitProperty_BypassEffect:
*((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
return noErr;
case kAudioUnitProperty_InPlaceProcessing:
*((UInt32*)outData) = (mProcessesInPlace ? 1 : 0);
return noErr;
}
}
return AUBase::GetProperty (inID, inScope, inElement, outData);
}


OSStatus AUEffectBase::SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
if (inScope == kAudioUnitScope_Global) {
switch (inID) {
case kAudioUnitProperty_BypassEffect:
{
if (inDataSize < sizeof(UInt32))
return kAudioUnitErr_InvalidPropertyValue;
bool tempNewSetting = *((UInt32*)inData) != 0;
// we're changing the state of bypass
if (tempNewSetting != IsBypassEffect())
{
if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
Reset(0, 0);
SetBypassEffect (tempNewSetting);
}
return noErr;
}
case kAudioUnitProperty_InPlaceProcessing:
mProcessesInPlace = (*((UInt32*)inData) != 0);
return noErr;
}
}
return AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
}

void AUEffectBase::MaintainKernels()
{
UInt32 nChannels = GetNumberOfChannels();
if (mKernelList.size() < nChannels) {
mKernelList.reserve(nChannels);
for (UInt32 i = mKernelList.size(); i < nChannels; ++i)
mKernelList.push_back(NewKernel());
} else
while (mKernelList.size() > nChannels) {
AUKernelBase *kernel = mKernelList.back();
delete kernel;
mKernelList.pop_back();
}

for(unsigned int i = 0; i < nChannels; i++ )
{
if(mKernelList[i]) {
mKernelList[i]->SetChannelNum (i);
}
}
}

bool AUEffectBase::StreamFormatWritable( AudioUnitScope scope,
AudioUnitElement element)
{
return IsInitialized() ? false : true;
}

OSStatus AUEffectBase::ChangeStreamFormat( AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat)
{
OSStatus result = AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
if (result == noErr)
{
// for the moment this only dependency we know about
// where a parameter's range may change is with the sample rate
// and effects are only publishing parameters in the global scope!
if (GetParamHasSampleRateDependency() && fnotequal(inPrevFormat.mSampleRate, inNewFormat.mSampleRate))
PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0);
}

return result;
}


// ____________________________________________________________________________
//
// This method is called (potentially repeatedly) by ProcessForScheduledParams()
// in order to perform the actual DSP required for this portion of the entire buffer
// being processed. The entire buffer can be divided up into smaller "slices"
// according to the timestamps on the scheduled parameters...
//
OSStatus AUEffectBase::ProcessScheduledSlice( void *inUserData,
UInt32 inStartFrameInBuffer,
UInt32 inSliceFramesToProcess,
UInt32 inTotalBufferFrames )
{
ScheduledProcessParams &sliceParams = *((ScheduledProcessParams*)inUserData);
AudioUnitRenderActionFlags &actionFlags = *sliceParams.actionFlags;
AudioBufferList &inputBufferList = *sliceParams.inputBufferList;
AudioBufferList &outputBufferList = *sliceParams.outputBufferList;
// fix the size of the buffer we're operating on before we render this slice of time
for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
inputBufferList.mBuffers[i].mDataByteSize =
(inputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess * sizeof(AudioUnitSampleType));
}

for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
outputBufferList.mBuffers[i].mDataByteSize =
(outputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess * sizeof(AudioUnitSampleType));
}
// process the buffer
OSStatus result = ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess );

// we just partially processed the buffers, so increment the data pointers to the next part of the buffer to process
for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
inputBufferList.mBuffers[i].mData =
(AudioUnitSampleType *)inputBufferList.mBuffers[i].mData + inputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess;
}
for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
outputBufferList.mBuffers[i].mData =
(AudioUnitSampleType *)outputBufferList.mBuffers[i].mData + outputBufferList.mBuffers[i].mNumberChannels * inSliceFramesToProcess;
}
return result;
}

// ____________________________________________________________________________
//

OSStatus AUEffectBase::Render( AudioUnitRenderActionFlags &ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 nFrames)
{
if (!HasInput(0))
return kAudioUnitErr_NoConnection;

OSStatus result = noErr;
AUOutputElement *theOutput = GetOutput(0); // throws if error

AUInputElement *theInput = GetInput(0);
result = theInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames);
if (result == noErr)
{
if(ProcessesInPlace() && theOutput->WillAllocateBuffer())
{
theOutput->SetBufferList(theInput->GetBufferList() );
}

if (ShouldBypassEffect())
{
// leave silence bit alone
if(!ProcessesInPlace() )
{
theInput->CopyBufferContentsTo (theOutput->GetBufferList());
}
}
else
{
if(mParamList.size() == 0 )
{
// this will read/write silence bit
result = ProcessBufferLists(ioActionFlags, theInput->GetBufferList(), theOutput->GetBufferList(), nFrames);
}
else
{
// deal with scheduled parameters...
AudioBufferList &inputBufferList = theInput->GetBufferList();
AudioBufferList &outputBufferList = theOutput->GetBufferList();
ScheduledProcessParams processParams;
processParams.actionFlags = &ioActionFlags;
processParams.inputBufferList = &inputBufferList;
processParams.outputBufferList = &outputBufferList;
// divide up the buffer into slices according to scheduled params then
// do the DSP for each slice (ProcessScheduledSlice() called for each slice)
result = ProcessForScheduledParams( mParamList,
nFrames,
&processParams );
// fixup the buffer pointers to how they were before we started
for(unsigned int i = 0; i < inputBufferList.mNumberBuffers; i++ ) {
inputBufferList.mBuffers[i].mData =
(AudioUnitSampleType *)inputBufferList.mBuffers[i].mData - inputBufferList.mBuffers[i].mNumberChannels * nFrames;
inputBufferList.mBuffers[i].mDataByteSize =
(inputBufferList.mBuffers[i].mNumberChannels * nFrames * sizeof(AudioUnitSampleType));
}
for(unsigned int i = 0; i < outputBufferList.mNumberBuffers; i++ ) {
outputBufferList.mBuffers[i].mData =
(AudioUnitSampleType *)outputBufferList.mBuffers[i].mData - outputBufferList.mBuffers[i].mNumberChannels * nFrames;
outputBufferList.mBuffers[i].mDataByteSize =
(outputBufferList.mBuffers[i].mNumberChannels * nFrames * sizeof(AudioUnitSampleType));
}
}
}
if ( (ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) && !ProcessesInPlace() )
{
AUBufferList::ZeroBuffer(theOutput->GetBufferList() );
}
}
return result;
}

OSStatus AUEffectBase::ProcessBufferLists(
AudioUnitRenderActionFlags & ioActionFlags,
const AudioBufferList & inBuffer,
AudioBufferList & outBuffer,
UInt32 inFramesToProcess )
{
bool ioSilence;

bool silentInput = IsInputSilent (ioActionFlags, inFramesToProcess);
ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
// call the kernels to handle either interleaved or deinterleaved
if (inBuffer.mNumberBuffers == 1) {
// interleaved (or mono)
int channel = 0;
for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end(); ++it, ++channel) {
AUKernelBase *kernel = *it;
if (kernel != NULL) {
ioSilence = silentInput;
// process each interleaved channel individually
kernel->Process(
(const AudioUnitSampleType *)inBuffer.mBuffers[0].mData + channel,
(AudioUnitSampleType *)outBuffer.mBuffers[0].mData + channel,
inFramesToProcess,
inBuffer.mBuffers[0].mNumberChannels,
ioSilence);
if (!ioSilence)
ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
}
}
} else {
// deinterleaved
const AudioBuffer *srcBuffer = inBuffer.mBuffers;
AudioBuffer *destBuffer = outBuffer.mBuffers;
for (KernelList::iterator it = mKernelList.begin(); it != mKernelList.end();
++it, ++srcBuffer, ++destBuffer) {
AUKernelBase *kernel = *it;
if (kernel != NULL) {
ioSilence = silentInput;
kernel->Process(
(const AudioUnitSampleType *)srcBuffer->mData,
(AudioUnitSampleType *)destBuffer->mData,
inFramesToProcess,
1,
ioSilence);
if (!ioSilence)
ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
}
}
}
return noErr;
}

Float64 AUEffectBase::GetSampleRate()
{
return GetOutput(0)->GetStreamFormat().mSampleRate;
}

UInt32 AUEffectBase::GetNumberOfChannels()
{
return GetOutput(0)->GetStreamFormat().mChannelsPerFrame;
}


+ 269
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUEffectBase.h View File

@@ -0,0 +1,269 @@
/* 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.
*/
#ifndef __AUEffectBase_h__
#define __AUEffectBase_h__

#include "AUBase.h"
#include "AUSilentTimeout.h"

class AUKernelBase;

// Base class for an effect with one input stream, one output stream,
// any number of channels.
/*! @class AUEffectBase */
class AUEffectBase : public AUBase {
public:
/*! @ctor AUEffectBase */
AUEffectBase( AudioComponentInstance audioUnit,
bool inProcessesInPlace = true );
/*! @dtor ~AUEffectBase */
~AUEffectBase();
/*! @method Initialize */
virtual OSStatus Initialize();

/*! @method Cleanup */
virtual void Cleanup();


/*! @method Reset */
virtual OSStatus Reset( AudioUnitScope inScope,
AudioUnitElement inElement);

/*! @method GetPropertyInfo */
virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method GetProperty */
virtual OSStatus GetProperty (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);

/*! @method SetProperty */
virtual OSStatus SetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);

/*! @method StreamFormatWritable */
virtual bool StreamFormatWritable (AudioUnitScope scope,
AudioUnitElement element);

/*! @method ChangeStreamFormat */
virtual OSStatus ChangeStreamFormat (
AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat);

/*! @method Render */
virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames);

// our virtual methods
// If your unit processes N to N channels, and there are no interactions between channels,
// it can override NewKernel to create a mono processing object per channel. Otherwise,
// don't override NewKernel, and instead, override ProcessBufferLists.
/*! @method NewKernel */
virtual AUKernelBase * NewKernel() { return NULL; }

/*! @method ProcessBufferLists */
virtual OSStatus ProcessBufferLists(
AudioUnitRenderActionFlags & ioActionFlags,
const AudioBufferList & inBuffer,
AudioBufferList & outBuffer,
UInt32 inFramesToProcess );

// convenience format accessors (use output 0's format)
/*! @method GetSampleRate */
Float64 GetSampleRate();
/*! @method GetNumberOfChannels */
UInt32 GetNumberOfChannels();

// convenience wrappers for accessing parameters in the global scope
/*! @method SetParameter */
void SetParameter( AudioUnitParameterID paramID,
AudioUnitParameterValue value)
{
Globals()->SetParameter(paramID, value);
}
/*! @method GetParameter */
AudioUnitParameterValue GetParameter( AudioUnitParameterID paramID )
{
return Globals()->GetParameter(paramID );
}
/*! @method IsBypassEffect */
// This is used for the property value - to reflect to the UI if an effect is bypassed
bool IsBypassEffect () { return mBypassEffect; }
protected:
/*! @method MaintainKernels */
void MaintainKernels();

/*! @method ShouldBypassEffect */
// This is used in the render call to see if an effect is bypassed
// It can return a different status than IsBypassEffect (though it MUST take that into account)
virtual bool ShouldBypassEffect () { return IsBypassEffect(); }
public:
/*! @method SetBypassEffect */
virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }
/*! @method SetParamHasSampleRateDependency */
void SetParamHasSampleRateDependency (bool inFlag)
{
mParamSRDep = inFlag;
}
/*! @method GetParamHasSampleRateDependency */
bool GetParamHasSampleRateDependency () const { return mParamSRDep; }


struct ScheduledProcessParams // pointer passed in as void* userData param for ProcessScheduledSlice()
{
AudioUnitRenderActionFlags *actionFlags;
AudioBufferList *inputBufferList;
AudioBufferList *outputBufferList;
};

virtual OSStatus ProcessScheduledSlice( void *inUserData,
UInt32 inStartFrameInBuffer,
UInt32 inSliceFramesToProcess,
UInt32 inTotalBufferFrames );


bool ProcessesInPlace() const {return mProcessesInPlace;};
void SetProcessesInPlace(bool inProcessesInPlace) {mProcessesInPlace = inProcessesInPlace;};
typedef std::vector<AUKernelBase *> KernelList;

protected:
/*! @var mKernelList */
KernelList mKernelList;

AUKernelBase* GetKernel(UInt32 index) { return mKernelList[index]; }

/*! @method IsInputSilent */
bool IsInputSilent (AudioUnitRenderActionFlags inActionFlags, UInt32 inFramesToProcess)
{
bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0;
// take latency and tail time into account when propagating the silent bit
UInt32 silentTimeoutFrames = UInt32(GetSampleRate() * (GetLatency() + GetTailTime()));
mSilentTimeout.Process (inFramesToProcess, silentTimeoutFrames, inputSilent);
return inputSilent;
}
private:
/*! @var mBypassEffect */
bool mBypassEffect;
/*! @var mParamSRDep */
bool mParamSRDep;
/*! @var mProcessesInplace */
bool mProcessesInPlace;
/*! @var mSilentTimeout */
AUSilentTimeout mSilentTimeout;


};


// Base class for a "kernel", an object that performs DSP on one channel of an interleaved stream.
/*! @class AUKernelBase */
class AUKernelBase {
public:
/*! @ctor AUKernelBase */
AUKernelBase(AUEffectBase *inAudioUnit ) :
mAudioUnit(inAudioUnit) { }

/*! @dtor ~AUKernelBase */
virtual ~AUKernelBase() { }

/*! @method Reset */
virtual void Reset() { }

/*! @method Process */
virtual void Process( const AudioUnitSampleType * inSourceP,
AudioUnitSampleType * inDestP,
UInt32 inFramesToProcess,
UInt32 inNumChannels,
bool & ioSilence) = 0;

/*! @method GetSampleRate */
Float64 GetSampleRate()
{
return mAudioUnit->GetSampleRate();
}
/*! @method GetParameter */
AudioUnitParameterValue GetParameter (AudioUnitParameterID paramID)
{
return mAudioUnit->GetParameter(paramID);
}
void SetChannelNum (UInt32 inChan) { mChannelNum = inChan; }
UInt32 GetChannelNum () { return mChannelNum; }
protected:
/*! @var mAudioUnit */
AUEffectBase * mAudioUnit;
UInt32 mChannelNum;

};



#endif // __AUEffectBase_h__

+ 481
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.cpp View File

@@ -0,0 +1,481 @@
/* 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 "AUMIDIBase.h"
#include <CoreMIDI/CoreMIDI.h>
#include "CAXException.h"

//temporaray location
enum
{
kMidiMessage_NoteOff = 0x80,
kMidiMessage_NoteOn = 0x90,
kMidiMessage_PolyPressure = 0xA0,
kMidiMessage_ControlChange = 0xB0,
kMidiMessage_ProgramChange = 0xC0,
kMidiMessage_ChannelPressure = 0xD0,
kMidiMessage_PitchWheel = 0xE0,

kMidiController_AllSoundOff = 120,
kMidiController_ResetAllControllers = 121,
kMidiController_AllNotesOff = 123
};

AUMIDIBase::AUMIDIBase(AUBase* inBase)
: mAUBaseInstance (*inBase)
{
#if CA_AUTO_MIDI_MAP
mMapManager = new CAAUMIDIMapManager();
#endif
}

AUMIDIBase::~AUMIDIBase()
{
#if CA_AUTO_MIDI_MAP
if (mMapManager)
delete mMapManager;
#endif
}

#if TARGET_API_MAC_OSX
OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus result = noErr;
switch (inID) {
case kMusicDeviceProperty_MIDIXMLNames:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
if (GetXMLNames(NULL) == noErr) {
outDataSize = sizeof(CFURLRef);
outWritable = false;
} else
result = kAudioUnitErr_InvalidProperty;
break;
#if CA_AUTO_MIDI_MAP
case kAudioUnitProperty_AllParameterMIDIMappings:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping)*mMapManager->NumMaps();
result = noErr;
break;
case kAudioUnitProperty_HotMapParameterMIDIMapping:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping);
result = noErr;
break;
case kAudioUnitProperty_AddParameterMIDIMapping:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping);
result = noErr;
break;
case kAudioUnitProperty_RemoveParameterMIDIMapping:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping);
result = noErr;
break;
#endif

default:
result = kAudioUnitErr_InvalidProperty;
break;
}
return result;
InvalidScope:
return kAudioUnitErr_InvalidScope;
InvalidElement:
return kAudioUnitErr_InvalidElement;
}

OSStatus AUMIDIBase::DelegateGetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus result;
switch (inID) {
case kMusicDeviceProperty_MIDIXMLNames:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
result = GetXMLNames((CFURLRef *)outData);
break;
#if CA_AUTO_MIDI_MAP
case kAudioUnitProperty_AllParameterMIDIMappings:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping* maps = (static_cast<AUParameterMIDIMapping*>(outData));
mMapManager->GetMaps(maps);
// printf ("GETTING MAPS\n");
// mMapManager->Print();
result = noErr;
break;
}
case kAudioUnitProperty_HotMapParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * map = (static_cast<AUParameterMIDIMapping*>(outData));
mMapManager->GetHotParameterMap (*map);
result = noErr;
break;
}
#endif
default:
result = kAudioUnitErr_InvalidProperty;
break;
}
return result;
InvalidScope:
return kAudioUnitErr_InvalidScope;
InvalidElement:
return kAudioUnitErr_InvalidElement;
}

OSStatus AUMIDIBase::DelegateSetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
OSStatus result;
switch (inID) {
#if CA_AUTO_MIDI_MAP
case kAudioUnitProperty_AddParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
mMapManager->SortedInsertToParamaterMaps (maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
result = noErr;
break;
}
case kAudioUnitProperty_RemoveParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
bool didChange;
mMapManager->SortedRemoveFromParameterMaps(maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
if (didChange)
mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
result = noErr;
break;
}
case kAudioUnitProperty_HotMapParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping & map = *((AUParameterMIDIMapping*)inData);
mMapManager->SetHotMapping (map);
result = noErr;
break;
}
case kAudioUnitProperty_AllParameterMIDIMappings:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * mappings = (AUParameterMIDIMapping*)inData;
mMapManager->ReplaceAllMaps (mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
result = noErr;
break;
}
#endif
default:
result = kAudioUnitErr_InvalidProperty;
break;
}
return result;
#if CA_AUTO_MIDI_MAP
InvalidScope:
return kAudioUnitErr_InvalidScope;
InvalidElement:
return kAudioUnitErr_InvalidElement;
#endif
}



#endif //TARGET_API_MAC_OSX


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ____MidiDispatch


inline const Byte * NextMIDIEvent(const Byte *event, const Byte *end)
{
Byte c = *event;
switch (c >> 4) {
default: // data byte -- assume in sysex
while ((*++event & 0x80) == 0 && event < end)
;
break;
case 0x8:
case 0x9:
case 0xA:
case 0xB:
case 0xE:
event += 3;
break;
case 0xC:
case 0xD:
event += 2;
break;
case 0xF:
switch (c) {
case 0xF0:
while ((*++event & 0x80) == 0 && event < end)
;
break;
case 0xF1:
case 0xF3:
event += 2;
break;
case 0xF2:
event += 3;
break;
default:
++event;
break;
}
}
return (event >= end) ? end : event;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUMIDIBase::HandleMIDIPacketList
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus AUMIDIBase::HandleMIDIPacketList(const MIDIPacketList *pktlist)
{
if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
int nPackets = pktlist->numPackets;
const MIDIPacket *pkt = pktlist->packet;
while (nPackets-- > 0) {
const Byte *event = pkt->data, *packetEnd = event + pkt->length;
long startFrame = (long)pkt->timeStamp;
while (event < packetEnd) {
Byte status = event[0];
if (status & 0x80) {
// really a status byte (not sysex continuation)
HandleMidiEvent(status & 0xF0, status & 0x0F, event[1], event[2], startFrame);
// note that we're generating a bogus channel number for system messages (0xF0-FF)
}
event = NextMIDIEvent(event, packetEnd);
}
pkt = reinterpret_cast<const MIDIPacket *>(packetEnd);
}
return noErr;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUMIDIBase::HandleMidiEvent
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus AUMIDIBase::HandleMidiEvent(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
{
if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
#if CA_AUTO_MIDI_MAP
// you potentially have a choice to make here - if a param mapping matches, do you still want to process the
// MIDI event or not. The default behaviour is to continue on with the MIDI event.
if (mMapManager->HandleHotMapping (status, channel, data1, mAUBaseInstance)) {
mAUBaseInstance.PropertyChanged (kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
}
else {
mMapManager->FindParameterMapEventMatch(status, channel, data1, data2, inStartFrame, mAUBaseInstance);
}
#endif
OSStatus result = noErr;
switch(status)
{
case kMidiMessage_NoteOn:
if(data2)
{
result = HandleNoteOn(channel, data1, data2, inStartFrame);
}
else
{
// zero velocity translates to note off
result = HandleNoteOff(channel, data1, data2, inStartFrame);
}
break;
case kMidiMessage_NoteOff:
result = HandleNoteOff(channel, data1, data2, inStartFrame);
break;
default:
result = HandleNonNoteEvent (status, channel, data1, data2, inStartFrame);
break;
}
return result;
}

OSStatus AUMIDIBase::HandleNonNoteEvent (UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
{
OSStatus result = noErr;

switch (status)
{
case kMidiMessage_PitchWheel:
result = HandlePitchWheel(channel, data1, data2, inStartFrame);
break;
case kMidiMessage_ProgramChange:
result = HandleProgramChange(channel, data1);
break;
case kMidiMessage_ChannelPressure:
result = HandleChannelPressure(channel, data1, inStartFrame);
break;
case kMidiMessage_ControlChange:
{
switch (data1) {
case kMidiController_AllNotesOff:
result = HandleAllNotesOff(channel);
break;

case kMidiController_ResetAllControllers:
result = HandleResetAllControllers(channel);
break;

case kMidiController_AllSoundOff:
result = HandleAllSoundOff(channel);
break;
default:
result = HandleControlChange(channel, data1, data2, inStartFrame);
break;
}
break;
}
case kMidiMessage_PolyPressure:
result = HandlePolyPressure (channel, data1, data2, inStartFrame);
break;
}
return result;
}

OSStatus AUMIDIBase::SysEx (const UInt8 * inData,
UInt32 inLength)
{
if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;

return HandleSysEx(inData, inLength );
}



#if TARGET_OS_MAC
#if __LP64__
// comp instance, parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index + 1];
#else
// parameters in reverse order, then comp instance
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
#endif
#elif TARGET_OS_WIN32
// (no comp instance), parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index];
#endif


OSStatus AUMIDIBase::ComponentEntryDispatch( ComponentParameters * params,
AUMIDIBase * This)
{
if (This == NULL) return paramErr;

OSStatus result;
switch (params->what) {
case kMusicDeviceMIDIEventSelect:
{
PARAM(UInt32, pbinStatus, 0, 4);
PARAM(UInt32, pbinData1, 1, 4);
PARAM(UInt32, pbinData2, 2, 4);
PARAM(UInt32, pbinOffsetSampleFrame, 3, 4);
result = This->MIDIEvent(pbinStatus, pbinData1, pbinData2, pbinOffsetSampleFrame);
}
break;
case kMusicDeviceSysExSelect:
{
PARAM(const UInt8 *, pbinData, 0, 2);
PARAM(UInt32, pbinLength, 1, 2);
result = This->SysEx(pbinData, pbinLength);
}
break;

default:
result = badComponentSelector;
break;
}
return result;
}


+ 207
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIBase.h View File

@@ -0,0 +1,207 @@
/* 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.
*/
#ifndef __AUMIDIBase_h__
#define __AUMIDIBase_h__

#include "AUBase.h"

#if CA_AUTO_MIDI_MAP
#include "CAAUMIDIMapManager.h"
#endif

struct MIDIPacketList;

// ________________________________________________________________________
// MusicDeviceBase
//
/*! @class AUMIDIBase */
class AUMIDIBase {
public:
// this is NOT a copy constructor!
/*! @ctor AUMIDIBase */
AUMIDIBase(AUBase* inBase);
/*! @dtor ~AUMIDIBase */
virtual ~AUMIDIBase();
/*! @method MIDIEvent */
OSStatus MIDIEvent( UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame)
{
UInt32 strippedStatus = inStatus & 0xf0;
UInt32 channel = inStatus & 0x0f;
return HandleMidiEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame);
}
/*! @method HandleMIDIPacketList */
OSStatus HandleMIDIPacketList(const MIDIPacketList *pktlist);
/*! @method SysEx */
OSStatus SysEx( const UInt8 * inData,
UInt32 inLength);

#if TARGET_API_MAC_OSX
/*! @method DelegateGetPropertyInfo */
virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method DelegateGetProperty */
virtual OSStatus DelegateGetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
/*! @method DelegateSetProperty */
virtual OSStatus DelegateSetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
#endif

protected:
// MIDI dispatch
/*! @method HandleMidiEvent */
virtual OSStatus HandleMidiEvent( UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
UInt8 inData2,
UInt32 inStartFrame);

/*! @method HandleNonNoteEvent */
virtual OSStatus HandleNonNoteEvent ( UInt8 status,
UInt8 channel,
UInt8 data1,
UInt8 data2,
UInt32 inStartFrame);

#if TARGET_API_MAC_OSX
/*! @method GetXMLNames */
virtual OSStatus GetXMLNames(CFURLRef *outNameDocument)
{ return kAudioUnitErr_InvalidProperty; } // if not overridden, it's unsupported
#endif

// channel messages
/*! @method HandleNoteOn */
virtual OSStatus HandleNoteOn( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleNoteOff */
virtual OSStatus HandleNoteOff( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleControlChange */
virtual OSStatus HandleControlChange( UInt8 inChannel,
UInt8 inController,
UInt8 inValue,
UInt32 inStartFrame) { return noErr; }
/*! @method HandlePitchWheel */
virtual OSStatus HandlePitchWheel( UInt8 inChannel,
UInt8 inPitch1,
UInt8 inPitch2,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleChannelPressure */
virtual OSStatus HandleChannelPressure( UInt8 inChannel,
UInt8 inValue,
UInt32 inStartFrame) { return noErr; }

/*! @method HandleProgramChange */
virtual OSStatus HandleProgramChange( UInt8 inChannel,
UInt8 inValue) { return noErr; }

/*! @method HandlePolyPressure */
virtual OSStatus HandlePolyPressure( UInt8 inChannel,
UInt8 inKey,
UInt8 inValue,
UInt32 inStartFrame) { return noErr; }

/*! @method HandleResetAllControllers */
virtual OSStatus HandleResetAllControllers(UInt8 inChannel) { return noErr; }
/*! @method HandleAllNotesOff */
virtual OSStatus HandleAllNotesOff( UInt8 inChannel) { return noErr; }
/*! @method HandleAllSoundOff */
virtual OSStatus HandleAllSoundOff( UInt8 inChannel) { return noErr; }


//System messages
/*! @method HandleSysEx */
virtual OSStatus HandleSysEx( const UInt8 * inData,
UInt32 inLength ) { return noErr; }

#if CA_AUTO_MIDI_MAP
/* map manager */
CAAUMIDIMapManager *GetMIDIMapManager() {return mMapManager;};
#endif

private:
/*! @var mAUBaseInstance */
AUBase & mAUBaseInstance;
#if CA_AUTO_MIDI_MAP
/* map manager */
CAAUMIDIMapManager * mMapManager;
#endif
public:
#if !TARGET_OS_IPHONE
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters *params,
AUMIDIBase *This);
#endif
};

#endif // __AUMIDIBase_h__

+ 158
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.cpp View File

@@ -0,0 +1,158 @@
/* 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 "AUMIDIEffectBase.h"

// compatibility with older OS SDK releases
typedef OSStatus
(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);

static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);

AUMIDIEffectBase::AUMIDIEffectBase( AudioComponentInstance inInstance,
bool inProcessesInPlace )
: AUEffectBase(inInstance, inProcessesInPlace),
AUMIDIBase(this)
{
}

OSStatus AUMIDIEffectBase::GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus result;
result = AUEffectBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
return result;
}

OSStatus AUMIDIEffectBase::GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus result;

#if !CA_AU_IS_ONLY_PLUGIN
if (inID == kAudioUnitProperty_FastDispatch) {
if (inElement == kMusicDeviceMIDIEventSelect) {
*(TEMP_MusicDeviceMIDIEventProc *)outData = AUMIDIEffectBaseMIDIEvent;
return noErr;
}
return kAudioUnitErr_InvalidElement;
}
#endif
result = AUEffectBase::GetProperty (inID, inScope, inElement, outData);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
return result;
}

OSStatus AUMIDIEffectBase::SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{

OSStatus result = AUEffectBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
return result;
}


#if !TARGET_OS_IPHONE
OSStatus AUMIDIEffectBase::ComponentEntryDispatch(ComponentParameters * params,
AUMIDIEffectBase * This)
{
if (This == NULL) return paramErr;

OSStatus result;
switch (params->what) {
case kMusicDeviceMIDIEventSelect:
case kMusicDeviceSysExSelect:
result = AUMIDIBase::ComponentEntryDispatch (params, This);
break;
default:
result = AUEffectBase::ComponentEntryDispatch(params, This);
break;
}
return result;
}
#endif

// fast dispatch
static OSStatus AUMIDIEffectBaseMIDIEvent(void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
AUMIDIEffectBase *This = static_cast<AUMIDIEffectBase *>(inComponentStorage);
if (This == NULL) return paramErr;
result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}

+ 83
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUMIDIEffectBase.h View File

@@ -0,0 +1,83 @@
/* 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.
*/
#ifndef __AUMIDIEffectBase_h__
#define __AUMIDIEffectBase_h__

#include "AUMIDIBase.h"
#include "AUEffectBase.h"

// ________________________________________________________________________
// AUMIDIEffectBase
//
/*! @class AUMIDIEffectBase */
class AUMIDIEffectBase : public AUEffectBase, public AUMIDIBase {
public:
/*! @ctor AUMIDIEffectBase */
AUMIDIEffectBase( AudioComponentInstance inInstance,
bool inProcessesInPlace = false );

/*! @method GetPropertyInfo */
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method GetProperty */
virtual OSStatus GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
/*! @method SetProperty */
virtual OSStatus SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
#if !TARGET_OS_IPHONE
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
AUMIDIEffectBase * This);
#endif
};

#endif // __AUMIDIEffectBase_h__

+ 105
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.cpp View File

@@ -0,0 +1,105 @@
/* 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 "AUOutputBase.h"

#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif

#if TARGET_API_MAC_OS8 || TARGET_API_MAC_OSX
struct AudioOutputUnitStartStopGluePB {
unsigned char componentFlags;
unsigned char componentParamSize;
short componentWhat;
AudioUnit ci;
};
#elif TARGET_OS_WIN32
struct AudioOutputUnitStartStopGluePB {
unsigned char componentFlags;
unsigned char componentParamSize;
short componentWhat;
};
#else
#error Platform not supported
#endif

#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif

#if !TARGET_OS_IPHONE
OSStatus AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
{
if (This == NULL) return paramErr;

OSStatus result;
switch (params->what) {
case kAudioOutputUnitStartSelect:
{
//AudioOutputUnitStartStopGluePB *p = (AudioOutputUnitStartStopGluePB *)params;
result = This->Start();
}
break;

case kAudioOutputUnitStopSelect:
{
//AudioOutputUnitStartStopGluePB *p = (AudioOutputUnitStartStopGluePB *)params;
result = This->Stop();
}
break;

default:
result = badComponentSelector;
break;
}
return result;
}
#endif

+ 76
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUOutputBase.h View File

@@ -0,0 +1,76 @@
/* 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.
*/
#ifndef __AUOutputBase_h__
#define __AUOutputBase_h__

#include "AUBase.h"

// ________________________________________________________________________
// AUOutputBase
// this is now a mix-in rather than an AUBase subclass

/*! @class AUOutputBase */
class AUOutputBase {
public:
/*! @ctor AUOutputBase */
AUOutputBase(AUBase *inBase) : mAUBaseInstance(*inBase) { }
virtual ~AUOutputBase() { }

// additional component entry points
/*! @method Start */
virtual OSStatus Start() = 0;
/*! @method Stop */
virtual OSStatus Stop() = 0;

#if !TARGET_OS_IPHONE
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
AUOutputBase * This);
#endif

private:
/*! @var mAUBaseInstance */
AUBase & mAUBaseInstance;
};

#endif // __AUOutputBase_h__

+ 700
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.cpp View File

@@ -0,0 +1,700 @@
/* 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 "AUPannerBase.h"
#include "CABundleLocker.h"
#include <AudioToolbox/AudioToolbox.h>
#include <Accelerate/Accelerate.h>

static bool sLocalized = false;

static CFStringRef kPanner_Azimuth_Name = CFSTR("azimuth");
static CFStringRef kPanner_Elevation_Name = CFSTR("elevation");
static CFStringRef kPanner_Distance_Name = CFSTR("distance");

static CFStringRef kPanner_CoordScale_Name = CFSTR("coordinate scale");
static CFStringRef kPanner_RefDistance_Name = CFSTR("reference distance");
static CFStringRef kPanner_Gain_Name = CFSTR("gain");

static Float32 kPannerParamDefault_Azimuth = 0.;
static Float32 kPannerParamDefault_Elevation = 0.;
static Float32 kPannerParamDefault_Distance = 1.;

static Float32 kPannerParamDefault_CoordScale = 10.;
static Float32 kPannerParamDefault_RefDistance = 1.;
static Float32 kPannerParamDefault_Gain = 1.;

//_____________________________________________________________________________
//
AUPannerBase::AUPannerBase(AudioComponentInstance inAudioUnit)
: AUBase(inAudioUnit, 1, 1), mBypassEffect(false)
{
{
CABundleLocker lock;
if (!sLocalized)
{
CFBundleRef bundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.audio.units.Components") );
if (bundle != NULL)
{
kPanner_Azimuth_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Azimuth_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
kPanner_Elevation_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Elevation_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
kPanner_Distance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Distance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
kPanner_CoordScale_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_CoordScale_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
kPanner_RefDistance_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_RefDistance_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));
kPanner_Gain_Name = CFCopyLocalizedStringFromTableInBundle(kPanner_Gain_Name, CFSTR("AudioUnits"), bundle, CFSTR(""));

}
sLocalized = true;
}
}
CreateElements();
SetParameter(kPannerParam_Azimuth, kPannerParamDefault_Azimuth);
SetParameter(kPannerParam_Elevation, kPannerParamDefault_Elevation);
SetParameter(kPannerParam_Distance, kPannerParamDefault_Distance);
SetParameter(kPannerParam_CoordScale, kPannerParamDefault_CoordScale);
SetParameter(kPannerParam_RefDistance, kPannerParamDefault_RefDistance);
SetParameter(kPannerParam_Gain, kPannerParamDefault_Gain);
}

//_____________________________________________________________________________
//
AUPannerBase::~AUPannerBase()
{
Cleanup();
}

//_____________________________________________________________________________
//
/*! @method Initialize */
OSStatus AUPannerBase::Initialize()
{
OSStatus err = noErr;
AllocBypassMatrix();
err = UpdateBypassMatrix();
return err;
}

//_____________________________________________________________________________
//
/*! @method AllocBypassMatrix */
void AUPannerBase::AllocBypassMatrix()
{
UInt32 inChannels = GetNumberOfInputChannels();
UInt32 outChannels = GetNumberOfOutputChannels();
mBypassMatrix.alloc(inChannels * outChannels, true);
}

static AudioChannelLayoutTag DefaultTagForNumberOfChannels(UInt32 inNumberChannels)
{
switch (inNumberChannels) {
case 1: return kAudioChannelLayoutTag_Mono;
case 2: return kAudioChannelLayoutTag_Stereo;
case 4: return kAudioChannelLayoutTag_Quadraphonic;
case 5: return kAudioChannelLayoutTag_AudioUnit_5_0;
case 6: return kAudioChannelLayoutTag_AudioUnit_6_0;
case 7: return kAudioChannelLayoutTag_AudioUnit_7_0;
case 8: return kAudioChannelLayoutTag_AudioUnit_8;

default: return 0xFFFF0000 | inNumberChannels;
}
}

//_____________________________________________________________________________
//
/*! @method UpdateBypassMatrix */
OSStatus AUPannerBase::SetDefaultChannelLayoutsIfNone()
{
OSStatus err = noErr;
// if layout has not been set, then guess layout from number of channels
UInt32 inChannels = GetNumberOfInputChannels();
AudioChannelLayout inputLayoutSubstitute;
const AudioChannelLayout* inputLayout = &GetInputLayout();
if (inputLayout == NULL || inputLayout->mChannelLayoutTag == 0) {
inputLayout = &inputLayoutSubstitute;
inputLayoutSubstitute.mNumberChannelDescriptions = 0;
inputLayoutSubstitute.mChannelBitmap = 0;
inputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(inChannels);

mInputLayout = &inputLayoutSubstitute;
err = SetAudioChannelLayout(kAudioUnitScope_Input, 0, &GetInputLayout());
if (err) return err;
}
// if layout has not been set, then guess layout from number of channels
UInt32 outChannels = GetNumberOfOutputChannels();
AudioChannelLayout outputLayoutSubstitute;
const AudioChannelLayout* outputLayout = &GetOutputLayout();
if (outputLayout == NULL || outputLayout->mChannelLayoutTag == 0) {
outputLayout = &outputLayoutSubstitute;
outputLayoutSubstitute.mNumberChannelDescriptions = 0;
outputLayoutSubstitute.mChannelBitmap = 0;
outputLayoutSubstitute.mChannelLayoutTag = DefaultTagForNumberOfChannels(outChannels);

mOutputLayout = &outputLayoutSubstitute;
err = SetAudioChannelLayout(kAudioUnitScope_Output, 0, &GetOutputLayout());
if (err) return err;
}
return err;
}


OSStatus AUPannerBase::UpdateBypassMatrix()
{
OSStatus err = SetDefaultChannelLayoutsIfNone();
if (err) return err;
UInt32 inChannels = GetNumberOfInputChannels();
UInt32 outChannels = GetNumberOfOutputChannels();
const AudioChannelLayout* inoutACL[2];
inoutACL[0] = &GetInputLayout();
inoutACL[1] = &GetOutputLayout();

mBypassMatrix.alloc(inChannels * outChannels, true);
UInt32 propSize = inChannels * outChannels * sizeof(Float32);
err = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap, sizeof(inoutACL), inoutACL, &propSize, mBypassMatrix());
if (err) {
// if there is an error, use a diagonal matrix.
Float32* bypass = mBypassMatrix();
for (UInt32 chan = 0; chan < std::min(inChannels, outChannels); ++chan)
{
float *amp = bypass + (chan * outChannels + chan);
*amp = 1.;
}
}

return noErr;
}

//_____________________________________________________________________________
//
/*! @method Cleanup */
void AUPannerBase::Cleanup()
{
}


//_____________________________________________________________________________
//
/*! @method Reset */
OSStatus AUPannerBase::Reset( AudioUnitScope inScope,
AudioUnitElement inElement)
{
return AUBase::Reset(inScope, inElement);
}

//_____________________________________________________________________________
//
/*! @method GetParameterInfo */
OSStatus AUPannerBase::GetParameterInfo( AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo )
{
OSStatus result = noErr;

outParameterInfo.flags = kAudioUnitParameterFlag_IsWritable
+ kAudioUnitParameterFlag_IsReadable;
if (inScope == kAudioUnitScope_Global) {
switch(inParameterID)
{
case kPannerParam_Azimuth:
AUBase::FillInParameterName (outParameterInfo, kPanner_Azimuth_Name, false);
outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
outParameterInfo.minValue = -180.;
outParameterInfo.maxValue = 180;
outParameterInfo.defaultValue = kPannerParamDefault_Azimuth;
break;

case kPannerParam_Elevation:
AUBase::FillInParameterName (outParameterInfo, kPanner_Elevation_Name, false);
outParameterInfo.unit = kAudioUnitParameterUnit_Degrees;
outParameterInfo.minValue = -90.;
outParameterInfo.maxValue = 90;
outParameterInfo.defaultValue = kPannerParamDefault_Elevation;
break;

case kPannerParam_Distance:
AUBase::FillInParameterName (outParameterInfo, kPanner_Distance_Name, false);
outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
outParameterInfo.minValue = 0.0;
outParameterInfo.maxValue = 1.;
outParameterInfo.defaultValue = kPannerParamDefault_Distance;
outParameterInfo.flags += kAudioUnitParameterFlag_IsHighResolution;
//outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
break;
case kPannerParam_CoordScale:
AUBase::FillInParameterName (outParameterInfo, kPanner_CoordScale_Name, false);
outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
outParameterInfo.minValue = 0.01;
outParameterInfo.maxValue = 1000.;
outParameterInfo.defaultValue = kPannerParamDefault_CoordScale;
outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
break;

case kPannerParam_RefDistance:
AUBase::FillInParameterName (outParameterInfo, kPanner_RefDistance_Name, false);
outParameterInfo.unit = kAudioUnitParameterUnit_Meters;
outParameterInfo.minValue = 0.01;
outParameterInfo.maxValue = 1000.;
outParameterInfo.defaultValue = kPannerParamDefault_RefDistance;
outParameterInfo.flags += kAudioUnitParameterFlag_DisplayLogarithmic;
break;

case kPannerParam_Gain:
AUBase::FillInParameterName (outParameterInfo, kPanner_Gain_Name, false);
outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
outParameterInfo.minValue = 0.;
outParameterInfo.maxValue = 1.;
outParameterInfo.defaultValue = kPannerParamDefault_Gain;
break;

default:
result = kAudioUnitErr_InvalidParameter;
break;
}
} else {
result = kAudioUnitErr_InvalidParameter;
}
return result;
}

//_____________________________________________________________________________
//
OSStatus AUPannerBase::GetParameter( AudioUnitParameterID inParamID,
AudioUnitScope inScope,
AudioUnitElement inElement,
Float32 & outValue)
{
if (inScope != kAudioUnitScope_Global)
return kAudioUnitErr_InvalidScope;
outValue = Globals()->GetParameter(inParamID);

return noErr;
}

//_____________________________________________________________________________
//
OSStatus AUPannerBase::SetParameter( AudioUnitParameterID inParamID,
AudioUnitScope inScope,
AudioUnitElement inElement,
Float32 inValue,
UInt32 inBufferOffsetInFrames)
{
if (inScope != kAudioUnitScope_Global)
return kAudioUnitErr_InvalidScope;

Globals()->SetParameter(inParamID, inValue);
return noErr;
}



//_____________________________________________________________________________
//
/*! @method GetPropertyInfo */
OSStatus AUPannerBase::GetPropertyInfo (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus err = noErr;
switch (inID) {
case kAudioUnitProperty_BypassEffect:
if (inScope != kAudioUnitScope_Global)
return kAudioUnitErr_InvalidScope;
outWritable = true;
outDataSize = sizeof (UInt32);
break;
default:
err = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
}
return err;
}

//_____________________________________________________________________________
//
/*! @method GetProperty */
OSStatus AUPannerBase::GetProperty (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus err = noErr;
switch (inID)
{
case kAudioUnitProperty_BypassEffect:
if (inScope != kAudioUnitScope_Global)
return kAudioUnitErr_InvalidScope;

*((UInt32*)outData) = (IsBypassEffect() ? 1 : 0);
break;
default:
err = AUBase::GetProperty(inID, inScope, inElement, outData);
}
return err;
}

//_____________________________________________________________________________
//
/*! @method SetProperty */
OSStatus AUPannerBase::SetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
switch (inID)
{
case kAudioUnitProperty_BypassEffect:
if (inDataSize < sizeof(UInt32))
return kAudioUnitErr_InvalidPropertyValue;
bool tempNewSetting = *((UInt32*)inData) != 0;
// we're changing the state of bypass
if (tempNewSetting != IsBypassEffect())
{
if (!tempNewSetting && IsBypassEffect() && IsInitialized()) // turning bypass off and we're initialized
Reset(0, 0);
SetBypassEffect (tempNewSetting);
}
return noErr;
}
return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
}


//_____________________________________________________________________________
//
/*! @method StreamFormatWritable */
bool AUPannerBase::StreamFormatWritable (AudioUnitScope scope,
AudioUnitElement element)
{
return true;
}

//_____________________________________________________________________________
//
/*! @method ChangeStreamFormat */
OSStatus AUPannerBase::ChangeStreamFormat (
AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat)
{
if (inScope == kAudioUnitScope_Input && !InputChannelConfigIsSupported(inNewFormat.NumberChannels()))
return kAudioUnitErr_FormatNotSupported;
if (inScope == kAudioUnitScope_Output && !OutputChannelConfigIsSupported(inNewFormat.NumberChannels()))
return kAudioUnitErr_FormatNotSupported;
if (inNewFormat.NumberChannels() != inPrevFormat.NumberChannels())
RemoveAudioChannelLayout(inScope, inElement);
return AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
}

//_____________________________________________________________________________
//
/*! @method Render */
OSStatus AUPannerBase::Render(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
if (IsBypassEffect())
return BypassRender(ioActionFlags, inTimeStamp, inNumberFrames);
else
return PannerRender(ioActionFlags, inTimeStamp, inNumberFrames);
}

//_____________________________________________________________________________
//
/*! @method Render */
OSStatus AUPannerBase::BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames)
{
AudioUnitRenderActionFlags xflags = 0;
OSStatus result = PullInput(0, xflags, inTimeStamp, inNumberFrames);
if (result) return false;
bool isSilent = xflags & kAudioUnitRenderAction_OutputIsSilence;

AudioBufferList& outputBufferList = GetOutput(0)->GetBufferList();
AUBufferList::ZeroBuffer(outputBufferList);
if (!isSilent)
{
UInt32 inChannels = GetNumberOfInputChannels();
UInt32 outChannels = GetNumberOfOutputChannels();
Float32* bypass = mBypassMatrix();
for (UInt32 outChan = 0; outChan < outChannels; ++outChan)
{
float* outData = GetOutput(0)->GetChannelData(outChan);
for (UInt32 inChan = 0; inChan < inChannels; ++inChan)
{
float* inData = GetInput(0)->GetChannelData(inChan);
float *amp = bypass + (inChan * outChannels + outChan);
vDSP_vsma(inData, 1, amp, outData, 1, outData, 1, inNumberFrames);
}
}
}
return noErr;
}

//_____________________________________________________________________________
//
UInt32 AUPannerBase::GetAudioChannelLayout( AudioUnitScope inScope,
AudioUnitElement inElement,
AudioChannelLayout * outLayoutPtr,
Boolean & outWritable)
{
SetDefaultChannelLayoutsIfNone();
outWritable = true;
CAAudioChannelLayout* caacl = NULL;
switch (inScope)
{
case kAudioUnitScope_Input:
caacl = &mInputLayout;
break;
case kAudioUnitScope_Output:
caacl = &mOutputLayout;
break;
default:
COMPONENT_THROW(kAudioUnitErr_InvalidScope);
}
if (inElement != 0)
COMPONENT_THROW(kAudioUnitErr_InvalidElement);
UInt32 size = caacl->IsValid() ? caacl->Size() : 0;
if (size > 0 && outLayoutPtr)
memcpy(outLayoutPtr, &caacl->Layout(), size);
return size;
}

//_____________________________________________________________________________
//
OSStatus AUPannerBase::RemoveAudioChannelLayout( AudioUnitScope inScope,
AudioUnitElement inElement)
{
CAAudioChannelLayout* caacl = NULL;
switch (inScope)
{
case kAudioUnitScope_Input:
caacl = &mInputLayout;
break;
case kAudioUnitScope_Output:
caacl = &mOutputLayout;
break;
default:
return kAudioUnitErr_InvalidScope;
}
if (inElement != 0)
return kAudioUnitErr_InvalidElement;
*caacl = NULL;
return noErr;
}

//_____________________________________________________________________________
//
OSStatus AUPannerBase::SetAudioChannelLayout( AudioUnitScope inScope,
AudioUnitElement inElement,
const AudioChannelLayout * inLayout)
{
if (!inLayout)
return RemoveAudioChannelLayout(inScope, inElement);

if (!ChannelLayoutTagIsSupported(inScope, inElement, inLayout->mChannelLayoutTag))
return kAudioUnitErr_FormatNotSupported;
CAAudioChannelLayout* caacl = NULL;
UInt32 currentChannels;
switch (inScope)
{
case kAudioUnitScope_Input:
caacl = &mInputLayout;
currentChannels = GetNumberOfInputChannels();
break;
case kAudioUnitScope_Output:
caacl = &mOutputLayout;
currentChannels = GetNumberOfOutputChannels();
break;
default:
return kAudioUnitErr_InvalidScope;
}
if (inElement != 0)
return kAudioUnitErr_InvalidElement;

UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout);
if (currentChannels != numChannelsInLayout)
return kAudioUnitErr_InvalidPropertyValue;
*caacl = inLayout;
if (IsInitialized())
UpdateBypassMatrix();
return noErr;
}

//_____________________________________________________________________________
//
UInt32 AUPannerBase::GetChannelLayoutTags( AudioUnitScope inScope,
AudioUnitElement inElement,
AudioChannelLayoutTag* outTags)
{
switch (inScope)
{
case kAudioUnitScope_Input:
if (outTags) {
outTags[0] = kAudioChannelLayoutTag_Mono;
outTags[1] = kAudioChannelLayoutTag_Stereo;
outTags[2] = kAudioChannelLayoutTag_Ambisonic_B_Format;
}
return 3;
case kAudioUnitScope_Output:
if (outTags) {
outTags[0] = kAudioChannelLayoutTag_Stereo;
outTags[1] = kAudioChannelLayoutTag_Quadraphonic;
outTags[2] = kAudioChannelLayoutTag_AudioUnit_5_0;
outTags[3] = kAudioChannelLayoutTag_AudioUnit_6_0;
outTags[4] = kAudioChannelLayoutTag_AudioUnit_7_0;
outTags[5] = kAudioChannelLayoutTag_AudioUnit_7_0_Front;
outTags[6] = kAudioChannelLayoutTag_AudioUnit_8;
}
return 7;
default: {
OSStatus err = kAudioUnitErr_InvalidScope;
throw err;
}
}
}



//_____________________________________________________________________________
//
bool AUPannerBase::ChannelConfigIsSupported()
{
UInt32 inChannels = GetNumberOfInputChannels();
UInt32 outChannels = GetNumberOfOutputChannels();
const AUChannelInfo* cinfo = NULL;
UInt32 numConfigs = SupportedNumChannels(&cinfo);
for (UInt32 i = 0; i < numConfigs; ++i)
{
if (cinfo[i].inChannels == (SInt16)inChannels && cinfo[i].outChannels == (SInt16)outChannels)
return true;
}
return false;
}


//_____________________________________________________________________________
//
bool AUPannerBase::InputChannelConfigIsSupported(UInt32 inNumberChannels)
{
const AUChannelInfo* cinfo = NULL;
UInt32 numConfigs = SupportedNumChannels(&cinfo);
for (UInt32 i = 0; i < numConfigs; ++i)
{
if (cinfo[i].inChannels == (SInt16)inNumberChannels)
return true;
}
return false;
}

//_____________________________________________________________________________
//
bool AUPannerBase::OutputChannelConfigIsSupported(UInt32 inNumberChannels)
{
const AUChannelInfo* cinfo = NULL;
UInt32 numConfigs = SupportedNumChannels(&cinfo);
for (UInt32 i = 0; i < numConfigs; ++i)
{
if (cinfo[i].outChannels == (SInt16)inNumberChannels)
return true;
}
return false;
}

//_____________________________________________________________________________
//
bool AUPannerBase::ChannelLayoutTagIsSupported( AudioUnitScope inScope,
AudioUnitElement inElement,
AudioChannelLayoutTag inTag)
{
UInt32 numTags = GetChannelLayoutTags(inScope, inElement, NULL);
CAAutoFree<AudioChannelLayoutTag> tags(numTags);
GetChannelLayoutTags(inScope, inElement, tags());
for (UInt32 i = 0; i < numTags; ++i)
{
if (tags[i] == inTag)
return true;
}
return false;
}


+ 263
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/AUPannerBase.h View File

@@ -0,0 +1,263 @@
/* 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.
*/
#ifndef __AUPannerBase_h__
#define __AUPannerBase_h__

#include "AUBase.h"
#include <math.h>
#include "CAAutoDisposer.h"
#include "CAAudioChannelLayout.h"


/*! @class AUPannerBase */
class AUPannerBase : public AUBase
{
public:
/*! @ctor AUPannerBase */
AUPannerBase(AudioComponentInstance inAudioUnit);
/*! @dtor ~AUPannerBase */
virtual ~AUPannerBase();
/*! @method Initialize */
virtual OSStatus Initialize();

/*! @method Cleanup */
virtual void Cleanup();


/*! @method Reset */
virtual OSStatus Reset( AudioUnitScope inScope,
AudioUnitElement inElement);

/*! @method GetParameterInfo */
virtual OSStatus GetParameterInfo( AudioUnitScope inScope,
AudioUnitParameterID inParameterID,
AudioUnitParameterInfo &outParameterInfo );


/*! @method GetPropertyInfo */
virtual OSStatus GetPropertyInfo (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method GetProperty */
virtual OSStatus GetProperty (AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);

/*! @method SetProperty */
virtual OSStatus SetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);


/*! @method StreamFormatWritable */
virtual bool StreamFormatWritable (AudioUnitScope scope,
AudioUnitElement element);

/*! @method ChangeStreamFormat */
virtual OSStatus ChangeStreamFormat (
AudioUnitScope inScope,
AudioUnitElement inElement,
const CAStreamBasicDescription & inPrevFormat,
const CAStreamBasicDescription & inNewFormat);

/*! @method IsBypassEffect */
// This is used for the property value - to reflect to the UI if an effect is bypassed
bool IsBypassEffect () { return mBypassEffect; }
/*! @method SetBypassEffect */
virtual void SetBypassEffect (bool inFlag) { mBypassEffect = inFlag; }

/*! @method Render */
virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames);

/*! @method Render */
virtual OSStatus PannerRender(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames) = 0;

/*! @method BypassRender */
virtual OSStatus BypassRender(AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
UInt32 inNumberFrames);


/*! @method GetAudioChannelLayout */
virtual UInt32 GetAudioChannelLayout( AudioUnitScope inScope,
AudioUnitElement inElement,
AudioChannelLayout * outLayoutPtr,
Boolean & outWritable);

/*! @method SetAudioChannelLayout */
virtual OSStatus SetAudioChannelLayout( AudioUnitScope inScope,
AudioUnitElement inElement,
const AudioChannelLayout * inLayout);

/*! @method RemoveAudioChannelLayout */
virtual OSStatus RemoveAudioChannelLayout( AudioUnitScope inScope,
AudioUnitElement inElement);

/*! @method GetChannelLayoutTags */
virtual UInt32 GetChannelLayoutTags( AudioUnitScope inScope,
AudioUnitElement inElement,
AudioChannelLayoutTag* outTags);

/*! @method GetNumberOfInputChannels */
UInt32 GetNumberOfInputChannels() { return ((AUIOElement*)Inputs().SafeGetElement(0))->NumberChannels(); };
/*! @method GetNumberOfOutputChannels */
UInt32 GetNumberOfOutputChannels() { return ((AUIOElement*)Outputs().SafeGetElement(0))->NumberChannels(); }

/*! @method GetParameter */
virtual OSStatus GetParameter( AudioUnitParameterID inParamID,
AudioUnitScope inScope,
AudioUnitElement inElement,
Float32 & outValue);
/*! @method SetParameter */
virtual OSStatus SetParameter( AudioUnitParameterID inParamID,
AudioUnitScope inScope,
AudioUnitElement inElement,
Float32 inValue,
UInt32 inBufferOffsetInFrames);

// convenience wrappers for accessing parameters in the global scope
/*! @method SetParameter */
void SetParameter( UInt32 inParamID,
Float32 inValue)
{
OSStatus err = SetParameter(inParamID, kAudioUnitScope_Global, 0, inValue, 0);
if (err) throw err;
}
/*! @method GetParameter */
Float32 GetParameter( UInt32 inParamID )
{
Float32 outValue = 0.;
OSStatus err = GetParameter(inParamID, kAudioUnitScope_Global, 0, outValue);
if (err) throw err;
return outValue;
}

/*! @method InputChannelConfigIsSupported */
bool InputChannelConfigIsSupported(UInt32 inNumberChannels);
/*! @method OutputChannelConfigIsSupported */
bool OutputChannelConfigIsSupported(UInt32 inNumberChannels);
/*! @method ChannelConfigIsSupported */
bool ChannelConfigIsSupported();

/*! @method SupportsTail */
virtual bool SupportsTail () { return true; }
/*! @method GetTailTime */
virtual Float64 GetTailTime() { return 0; }


/*! @method GetGain */
Float32 GetGain() { return GetParameter(kPannerParam_Gain); }
/*! @method GetTailTime */
Float32 GetAzimuth() { return GetParameter(kPannerParam_Azimuth); }
/*! @method GetElevation */
Float32 GetElevation() { return GetParameter(kPannerParam_Elevation); }
/*! @method GetDistance */
Float32 GetDistance() { return GetParameter(kPannerParam_Distance); }
/*! @method GetCoordScale */
Float32 GetCoordScale() { return GetParameter(kPannerParam_CoordScale); }
/*! @method GetRefDistance */
Float32 GetRefDistance() { return GetParameter(kPannerParam_RefDistance); }
/*! @method SetGain */
void SetGain(Float32 inValue) { SetParameter(kPannerParam_Gain, inValue); }
/*! @method SetAzimuth */
void SetAzimuth(Float32 inValue) { SetParameter(kPannerParam_Azimuth, inValue); }
/*! @method SetElevation */
void SetElevation(Float32 inValue) { SetParameter(kPannerParam_Elevation, inValue); }
/*! @method SetDistance */
void SetDistance(Float32 inValue) { SetParameter(kPannerParam_Distance, inValue); }
/*! @method SetCoordScale */
void SetCoordScale(Float32 inValue) { SetParameter(kPannerParam_CoordScale, inValue); }
/*! @method SetRefDistance */
void SetRefDistance(Float32 inValue) { SetParameter(kPannerParam_RefDistance, inValue); }
protected:
/*! @method ShouldBypassEffect */
// This is used in the render call to see if an effect is bypassed
// It can return a different status than IsBypassEffect (though it MUST take that into account)
virtual bool ShouldBypassEffect () { return IsBypassEffect(); }

/*! @method AllocBypassMatrix */
void AllocBypassMatrix();

/*! @method UpdateBypassMatrix */
OSStatus UpdateBypassMatrix();

/*! @method SetDefaultChannelLayoutsIfNone */
OSStatus SetDefaultChannelLayoutsIfNone();
/*! @method ChannelLayoutTagIsSupported */
bool ChannelLayoutTagIsSupported( AudioUnitScope inScope,
AudioUnitElement inElement,
AudioChannelLayoutTag inTag);
const AudioChannelLayout& GetInputLayout() const { return mInputLayout.Layout(); }
const AudioChannelLayout& GetOutputLayout() const { return mOutputLayout.Layout(); }
private:
/*! @var UpdateBypassMatrix */
bool mBypassEffect;
/*! @var mBypassMatrix */
CAAutoFree<Float32> mBypassMatrix;
/*! @var mInputLayout */
CAAudioChannelLayout mInputLayout;
/*! @var mOutputLayout */
CAAudioChannelLayout mOutputLayout;
};

#endif /* __AUPannerBase_h__ */

+ 343
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.cpp View File

@@ -0,0 +1,343 @@
/* 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 "MusicDeviceBase.h"

// compatibility with older OS SDK releases
typedef OSStatus
(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);

typedef OSStatus
(*TEMP_MusicDeviceStartNoteProc)( void * inComponentStorage,
MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams);

typedef OSStatus
(*TEMP_MusicDeviceStopNoteProc)(void * inComponentStorage,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);


static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);

static OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams);

static OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);



MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups,
UInt32 numParts)
: AUBase(inInstance, numInputs, numOutputs, numGroups, numParts),
AUMIDIBase(this)
{
}

OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus result;
switch (inID)
{
case kMusicDeviceProperty_InstrumentCount:
if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
outDataSize = sizeof(UInt32);
outWritable = false;
result = noErr;
break;

default:
result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
break;
}
return result;
}

OSStatus MusicDeviceBase::GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus result;

switch (inID)
{
#if !CA_AU_IS_ONLY_PLUGIN
case kAudioUnitProperty_FastDispatch:
if (inElement == kMusicDeviceMIDIEventSelect) {
*(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
return noErr;
}
else if (inElement == kMusicDeviceStartNoteSelect) {
*(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
return noErr;
}
else if (inElement == kMusicDeviceStopNoteSelect) {
*(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
return noErr;
}
return kAudioUnitErr_InvalidElement;
#endif

case kMusicDeviceProperty_InstrumentCount:
if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
return GetInstrumentCount (*(UInt32*)outData);

default:
result = AUBase::GetProperty (inID, inScope, inElement, outData);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
}
return result;
}


OSStatus MusicDeviceBase::SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)

{

OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
return result;
}

// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
// then this call should return an instrument count of zero and noErr
OSStatus MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
{
outInstCount = 0;
return noErr;
}

OSStatus MusicDeviceBase::HandleNoteOn( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame)
{
MusicDeviceNoteParams params;
params.argCount = 2;
params.mPitch = inNoteNumber;
params.mVelocity = inVelocity;
return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
}
OSStatus MusicDeviceBase::HandleNoteOff( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame)
{
return StopNote (inChannel, inNoteNumber, inStartFrame);
}

OSStatus
MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams)
{
if (inParams == NULL || outNoteInstanceID == NULL) return paramErr;

if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}

#if TARGET_OS_MAC
#if __LP64__
// comp instance, parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index + 1];
#else
// parameters in reverse order, then comp instance
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
#endif
#elif TARGET_OS_WIN32
// (no comp instance), parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index];
#endif

#if !TARGET_OS_IPHONE
OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
MusicDeviceBase * This)
{
if (This == NULL) return paramErr;

OSStatus result;
switch (params->what) {
case kMusicDeviceMIDIEventSelect:
case kMusicDeviceSysExSelect:
{
result = AUMIDIBase::ComponentEntryDispatch (params, This);
}
break;
case kMusicDevicePrepareInstrumentSelect:
{
PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
result = This->PrepareInstrument(inInstrument);
}
break;
case kMusicDeviceReleaseInstrumentSelect:
{
PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
result = This->ReleaseInstrument(inInstrument);
}
break;
case kMusicDeviceStartNoteSelect:
{
PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
}
break;
case kMusicDeviceStopNoteSelect:
{
PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
}
break;

default:
result = AUBase::ComponentEntryDispatch(params, This);
break;
}
return result;
}
#endif


// fast dispatch
static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
if (This == NULL) return paramErr;
result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}

OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams)
{
OSStatus result = noErr;
try {
if (inParams == NULL || outNoteInstanceID == NULL) return paramErr;
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
if (This == NULL) return paramErr;
result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}
COMPONENT_CATCH
return result;
}

OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
if (This == NULL) return paramErr;
result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}


+ 123
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/OtherBases/MusicDeviceBase.h View File

@@ -0,0 +1,123 @@
/* 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.
*/
#ifndef __MusicDeviceBase_h__
#define __MusicDeviceBase_h__

#include "AUMIDIBase.h"

// ________________________________________________________________________
// MusicDeviceBase
//

/*! @class MusicDeviceBase */
class MusicDeviceBase : public AUBase, public AUMIDIBase {
public:
/*! @ctor MusicDeviceBase */
MusicDeviceBase( AudioComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups = 0,
UInt32 numParts = 0);

/*! @method PrepareInstrument */
virtual OSStatus PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return noErr; }

/*! @method ReleaseInstrument */
virtual OSStatus ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return noErr; }

/*! @method StartNote */
virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams &inParams) = 0;

/*! @method StopNote */
virtual OSStatus StopNote( MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame) = 0;

/*! @method GetPropertyInfo */
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);

/*! @method GetProperty */
virtual OSStatus GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
/*! @method SetProperty */
virtual OSStatus SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);

/*! @method HandleNoteOn */
virtual OSStatus HandleNoteOn( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame);
/*! @method HandleNoteOff */
virtual OSStatus HandleNoteOff( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame);

/*! @method GetInstrumentCount */
virtual OSStatus GetInstrumentCount ( UInt32 &outInstCount) const;

#if !TARGET_OS_IPHONE
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
MusicDeviceBase * This);
#endif
private:
OSStatus HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams);
};

#endif // __MusicDeviceBase_h__

+ 128
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.cpp View File

@@ -0,0 +1,128 @@
/* 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 "AUBaseHelper.h"

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioUnitProperties.h>
#else
#include <AudioUnitProperties.h>
#endif

OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath)
{
static CFStringRef kFRString = CFSTR (kAUPresetExternalFileRefs);
const void* frVal = CFDictionaryGetValue(parent, kFRString);
if (!frVal) return kAudioUnitErr_InvalidPropertyValue;

const void* frString = CFDictionaryGetValue ((CFDictionaryRef)frVal, frKey);
if (!frString) return kAudioUnitErr_InvalidPropertyValue;
if (fPath)
*fPath = (CFStringRef)frString;
return noErr;
}

// write valid samples check, with bool for zapping

UInt32 FindInvalidSamples(Float32 *inSource, UInt32 inFramesToProcess, bool &outHasNonZero, bool zapInvalidSamples)
{
float *sourceP = inSource;
UInt32 badSamplesDetected = 0;
bool hasNonZero = false;
for (UInt32 i=0; i < inFramesToProcess; i++)
{
float input = *(sourceP++);
if(input > 0)
hasNonZero = true;

float absx = fabs(input);
// a bad number!
if (!(absx < 1e15))
{
if (!(absx == 0))
{
//printf("\tbad sample: %f\n", input);
badSamplesDetected++;
if (zapInvalidSamples)
input = 0;
}
}
}
return badSamplesDetected;
}


CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict)
{
if (!fileRefDict)
fileRefDict = CFDictionaryCreateMutable (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

CFDictionarySetValue (fileRefDict, fKey, fPath);
return fileRefDict;
}

#if DEBUG
//_____________________________________________________________________________
//
void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f)
{
bool isRamp = event.eventType == kParameterEvent_Ramped;
fprintf (f, "\tParamID=%ld,Scope=%ld,Element=%ld\n", (long)event.parameter, (long)event.scope, (long)event.element);
fprintf (f, "\tEvent Type:%s,", (isRamp ? "ramp" : "immediate"));
if (isRamp)
fprintf (f, "start=%ld,dur=%ld,startValue=%f,endValue=%f\n",
(long)event.eventValues.ramp.startBufferOffset, (long)event.eventValues.ramp.durationInFrames,
event.eventValues.ramp.startValue, event.eventValues.ramp.endValue);
else
fprintf (f, "start=%ld,value=%f\n",
(long)event.eventValues.immediate.bufferOffset,
event.eventValues.immediate.value);
fprintf (f, "- - - - - - - - - - - - - - - -\n");
}
#endif


+ 74
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBaseHelper.h View File

@@ -0,0 +1,74 @@
/* 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.
*/
#ifndef __AUBaseHelper_h__
#define __AUBaseHelper_h__

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#include <AudioUnit/AUComponent.h>
#else
#include <CoreFoundation.h>
#include <AUComponent.h>
#endif

#include "AUBase.h"


UInt32 FindInvalidSamples(Float32 *inSource, UInt32 inFramesToProcess, bool &hasNonZero, bool zapInvalidSamples);


// helpers for dealing with the file-references dictionary in an AUPreset

extern "C" OSStatus
GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath);

// if fileRefDict is NULL, this call creates one
// if not NULL, then the key value is added to it
extern "C" CFMutableDictionaryRef
CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);

#if DEBUG
void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
#endif



#endif // __AUBaseHelper_h__

+ 203
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.cpp View File

@@ -0,0 +1,203 @@
/* 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 "AUBuffer.h"
#include <stdlib.h>

AUBufferList::~AUBufferList()
{
Deallocate();
if (mPtrs)
free(mPtrs);
}

void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
{
UInt32 nStreams;
UInt32 channelsPerStream;
if (format.IsInterleaved()) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
}

// careful -- the I/O thread could be running!
if (nStreams > mAllocatedStreams) {
mPtrs = (AudioBufferList *)CA_realloc(mPtrs, offsetof(AudioBufferList, mBuffers) + nStreams * sizeof(AudioBuffer));
mAllocatedStreams = nStreams;
}
UInt32 bytesPerStream = (nFrames * format.mBytesPerFrame + 0xF) & ~0xF;
UInt32 nBytes = nStreams * bytesPerStream;
if (nBytes > mAllocatedBytes) {
if (mExternalMemory) {
mExternalMemory = false;
mMemory = NULL;
}
mMemory = (Byte *)CA_realloc(mMemory, nBytes);
mAllocatedBytes = nBytes;
}
mAllocatedFrames = nFrames;
mPtrState = kPtrsInvalid;
}

void AUBufferList::Deallocate()
{
mAllocatedStreams = 0;
mAllocatedFrames = 0;
mAllocatedBytes = 0;
// this causes a world of hurt if someone upstream disconnects during I/O (SysSoundGraph)
/* if (mPtrs) {
printf("deallocating bufferlist %08X\n", int(mPtrs));
free(mPtrs);
mPtrs = NULL;
} */
if (mMemory) {
if (mExternalMemory)
mExternalMemory = false;
else
free(mMemory);
mMemory = NULL;
}
mPtrState = kPtrsInvalid;
}

AudioBufferList & AUBufferList::PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
{
if (nFrames > mAllocatedFrames)
COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);

UInt32 nStreams;
UInt32 channelsPerStream;
if (format.IsInterleaved()) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
if (nStreams > mAllocatedStreams)
COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
}
AudioBufferList *abl = mPtrs;
abl->mNumberBuffers = nStreams;
AudioBuffer *buf = abl->mBuffers;
Byte *mem = mMemory;
UInt32 streamInterval = (mAllocatedFrames * format.mBytesPerFrame + 0xF) & ~0xF;
UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
for ( ; nStreams--; ++buf) {
buf->mNumberChannels = channelsPerStream;
buf->mData = mem;
buf->mDataByteSize = bytesPerBuffer;
mem += streamInterval;
}
if (UInt32(mem - mMemory) > mAllocatedBytes)
COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
mPtrState = kPtrsToMyMemory;
return *mPtrs;
}

AudioBufferList & AUBufferList::PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
{
UInt32 nStreams;
UInt32 channelsPerStream;
if (format.IsInterleaved()) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
if (nStreams > mAllocatedStreams)
COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
}
AudioBufferList *abl = mPtrs;
abl->mNumberBuffers = nStreams;
AudioBuffer *buf = abl->mBuffers;
UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
for ( ; nStreams--; ++buf) {
buf->mNumberChannels = channelsPerStream;
buf->mData = NULL;
buf->mDataByteSize = bytesPerBuffer;
}
mPtrState = kPtrsToExternalMemory;
return *mPtrs;
}

// this should NOT be called while I/O is in process
void AUBufferList::UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf)
{
UInt32 alignedSize = buf.size & ~0xF;
if (mMemory != NULL && alignedSize >= mAllocatedBytes) {
// don't accept the buffer if we already have one and it's big enough
// if we don't already have one, we don't need one
Byte *oldMemory = mMemory;
mMemory = buf.buffer;
mAllocatedBytes = alignedSize;
// from Allocate(): nBytes = nStreams * nFrames * format.mBytesPerFrame;
// thus: nFrames = nBytes / (nStreams * format.mBytesPerFrame)
mAllocatedFrames = mAllocatedBytes / (format.NumberChannelStreams() * format.mBytesPerFrame);
mExternalMemory = true;
free(oldMemory);
}
}

#if DEBUG
void AUBufferList::PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames, bool asFloats)
{
printf(" %s [%d] 0x%08lX:\n", label, subscript, long(&abl));
const AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = 0; i < abl.mNumberBuffers; ++buf, ++i) {
printf(" [%2d] %5dbytes %dch @ %p: ", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
if (buf->mData != NULL) {
UInt32 nSamples = nFrames * buf->mNumberChannels;
for (UInt32 j = 0; j < nSamples; ++j) {
if (nSamples > 16 && (j % 16) == 0)
printf("\n\t");
if (asFloats)
printf(" %6.3f", ((float *)buf->mData)[j]);
else
printf(" %08X", (unsigned)((UInt32 *)buf->mData)[j]);
}
}
printf("\n");
}
}
#endif

+ 261
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUBuffer.h View File

@@ -0,0 +1,261 @@
/* 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.
*/
#ifndef __AUBuffer_h__
#define __AUBuffer_h__

#include <TargetConditionals.h>
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioUnit.h>
#else
#include <AudioUnit.h>
#endif

#include <string.h>
#include "CAStreamBasicDescription.h"
#include "CAAutoDisposer.h"
#include "CADebugMacros.h"

// make this usable outside the stricter context of AudiUnits
#ifndef COMPONENT_THROW
#define COMPONENT_THROW(err) \
do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
#endif


/*! @class AUBufferList */
class AUBufferList {
enum EPtrState {
kPtrsInvalid,
kPtrsToMyMemory,
kPtrsToExternalMemory
};
public:
/*! @ctor AUBufferList */
AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL),
mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
/*! @dtor ~AUBufferList */
~AUBufferList();

/*! @method PrepareBuffer */
AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
/*! @method PrepareNullBuffer */
AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);

/*! @method SetBufferList */
AudioBufferList & SetBufferList(const AudioBufferList &abl) {
if (mAllocatedStreams < abl.mNumberBuffers)
COMPONENT_THROW(-1);
mPtrState = kPtrsToExternalMemory;
memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
return *mPtrs;
}
/*! @method SetBuffer */
void SetBuffer(UInt32 index, const AudioBuffer &ab) {
if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
COMPONENT_THROW(-1);
mPtrState = kPtrsToExternalMemory;
mPtrs->mBuffers[index] = ab;
}

/*! @method InvalidateBufferList */
void InvalidateBufferList() { mPtrState = kPtrsInvalid; }

/*! @method GetBufferList */
AudioBufferList & GetBufferList() const {
if (mPtrState == kPtrsInvalid)
COMPONENT_THROW(-1);
return *mPtrs;
}

/*! @method CopyBufferListTo */
void CopyBufferListTo(AudioBufferList &abl) const {
if (mPtrState == kPtrsInvalid)
COMPONENT_THROW(-1);
memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
}
/*! @method CopyBufferContentsTo */
void CopyBufferContentsTo(AudioBufferList &abl) const {
if (mPtrState == kPtrsInvalid)
COMPONENT_THROW(-1);
const AudioBuffer *srcbuf = mPtrs->mBuffers;
AudioBuffer *destbuf = abl.mBuffers;

for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
--srcbuf;
if (destbuf->mData != srcbuf->mData)
memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
destbuf->mDataByteSize = srcbuf->mDataByteSize;
}
}
/*! @method Allocate */
void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
/*! @method Deallocate */
void Deallocate();
/*! @method UseExternalBuffer */
void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);

// AudioBufferList utilities
/*! @method ZeroBuffer */
static void ZeroBuffer(AudioBufferList &abl) {
AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
memset(buf->mData, 0, buf->mDataByteSize);
}
#if DEBUG
/*! @method PrintBuffer */
static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
#endif

/*! @method GetAllocatedFrames */
UInt32 GetAllocatedFrames() const { return mAllocatedFrames; }
private:
/*! @ctor AUBufferList */
AUBufferList(AUBufferList &) { } // prohibit copy constructor

/*! @var mPtrState */
EPtrState mPtrState;
/*! @var mExternalMemory */
bool mExternalMemory;
/*! @var mPtrs */
AudioBufferList * mPtrs;
/*! @var mMemory */
Byte * mMemory;
/*! @var mAllocatedStreams */
UInt32 mAllocatedStreams;
/*! @var mAllocatedFrames */
UInt32 mAllocatedFrames;
/*! @var mAllocatedBytes */
UInt32 mAllocatedBytes;
};


// Allocates an array of samples (type T), to be optimally aligned for the processor
/*! @class TAUBuffer */
template <class T>
class TAUBuffer {
public:
enum {
kAlignInterval = 0x10,
kAlignMask = kAlignInterval - 1
};
/*! @ctor TAUBuffer.0 */
TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
{
}
/*! @ctor TAUBuffer.1 */
TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL),
mBufferSizeBytes(0)
{
Allocate(numElems, numChannels);
}
/*! @dtor ~TAUBuffer */
~TAUBuffer()
{
Deallocate();
}
/*! @method Allocate */
void Allocate(UInt32 numElems) // can also re-allocate
{
UInt32 reqSize = numElems * sizeof(T);
if (mMemObject != NULL && reqSize == mBufferSizeBytes)
return; // already allocated

mBufferSizeBytes = reqSize;
mMemObject = CA_realloc(mMemObject, reqSize);
UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
if (misalign) {
mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
} else
mAlignedBuffer = (T *)mMemObject;
}

/*! @method Deallocate */
void Deallocate()
{
if (mMemObject == NULL) return; // so this method has no effect if we're using
// an external buffer
free(mMemObject);
mMemObject = NULL;
mAlignedBuffer = NULL;
mBufferSizeBytes = 0;
}
/*! @method AllocateClear */
void AllocateClear(UInt32 numElems) // can also re-allocate
{
Allocate(numElems);
Clear();
}
/*! @method Clear */
void Clear()
{
memset(mAlignedBuffer, 0, mBufferSizeBytes);
}
// accessors
/*! @method operator T *()@ */
operator T *() { return mAlignedBuffer; }

private:
/*! @var mMemObject */
void * mMemObject; // null when using an external buffer
/*! @var mAlignedBuffer */
T * mAlignedBuffer; // always valid once allocated
/*! @var mBufferSizeBytes */
UInt32 mBufferSizeBytes;
};

#endif // __AUBuffer_h__

+ 423
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.cpp View File

@@ -0,0 +1,423 @@
/* 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.
*/
/*=============================================================================
* AUDebugDispatcher.h
* CAServices

=============================================================================*/

#if AU_DEBUG_DISPATCHER

#warning "This should * * NOT * * be seen on a Release Version"


#include "AUDebugDispatcher.h"

static char* AUErrorStr (OSStatus result);

class AUDD_Locker {
public:
AUDD_Locker (CAMutex &guard) :mGuard (guard) { didLock = mGuard.Lock(); }
~AUDD_Locker () { if (didLock) mGuard.Unlock(); }

private:
bool didLock;
CAMutex &mGuard;
};
AUDebugDispatcher::AUDebugDispatcher (AUBase *au, FILE* file)
: mAUBase (au),
mFile (file),
mHaveDoneProperty (false),
mPrintMutex ("AU Debug Dispatcher Printer"),
mHostCB1_Result (0),
mHostCB2_Result (0),
mHostCB3_Result (0),
mHostCB_WhenToPrint (0),
mHostCB_WasPlaying (0)
{
// lets gather some info about this instance...
AudioComponentDescription desc = mAUBase->GetComponentDescription();
fprintf (mFile, "\nAUBase=0x%X, Type=%4.4s, SubType=%4.4s, Manu=%4.4s\n\n", AU(),
(char*)&desc.componentType,
(char*)&desc.componentSubType,
(char*)&desc.componentManufacturer);
mFirstTime = CAHostTimeBase::GetCurrentTime();
}


AUDebugDispatcher::~AUDebugDispatcher()
{
PrintHeaderString (CAHostTimeBase::GetCurrentTime(), (unsigned int)pthread_self(), "Close");
fprintf (mFile, "\n");
}

void AUDebugDispatcher::PrintHeaderString (UInt64 inNowTime, unsigned int inThread, const char* inMethod)
{
double secsSinceStart = SecsSinceStart(inNowTime);
fprintf (mFile, "[AUDisp:AUBase = 0x%X, Time = %.6lf secs, Thread = 0x%X, IsInitialized = '%c'] %s()\n",
AU(), secsSinceStart, inThread, (mAUBase->IsInitialized() ? 'T' : 'F'), inMethod);
}

unsigned int AUDebugDispatcher::RecordDispatch (UInt64 inStartTime, OSStatus result, const char* inMethod)
{
UInt64 nowTime = CAHostTimeBase::GetCurrentTime();
unsigned int theThread = (unsigned int)pthread_self();
PrintHeaderString (nowTime, theThread, inMethod);
UInt64 nanos = CAHostTimeBase::ConvertToNanos(nowTime - inStartTime);

fprintf (mFile, "\t[Time To execute = %.6lf secs", (nanos * 1.0e-9));

if (result)
fprintf (mFile, ", * * * result = %ld, %s * * * ", result, AUErrorStr(result));

fprintf (mFile, "]\n");

return theThread;
}

#pragma mark -
#pragma mark __AU Dispatch
#pragma mark -

void AUDebugDispatcher::Initialize (UInt64 nowTime, OSStatus result)
{
AUDD_Locker lock (mPrintMutex);
RecordDispatch (nowTime, result, "Initialize");
}

void AUDebugDispatcher::Uninitialize (UInt64 nowTime, OSStatus result)
{
AUDD_Locker lock (mPrintMutex);
RecordDispatch (nowTime, result, "Uninitialize");
}

void AUDebugDispatcher::GetPropertyInfo (UInt64 nowTime,
OSStatus result,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 *outDataSize,
Boolean *outWritable)
{
AUDD_Locker lock (mPrintMutex);
RecordDispatch (nowTime, result, "GetPropertyInfo");
PrintProperty (inID, inScope, inElement);
}

void AUDebugDispatcher::GetProperty (UInt64 nowTime,
OSStatus result,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 *ioDataSize,
void *outData)
{
//err -> ioDataSize == NULL or 0
//outData == NULL -> Dispatches to GetPropertyInfo
// still should log these as calls to GetProperty...
AUDD_Locker lock (mPrintMutex);
const char *dispStr = outData != NULL ? "GetProperty" : "GetProperty - Info";
RecordDispatch (nowTime, result, dispStr);
PrintProperty (inID, inScope, inElement);
}

void AUDebugDispatcher::SetProperty (UInt64 nowTime,
OSStatus result,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
// inData could be NULL to remove property value...
AUDD_Locker lock (mPrintMutex);
RecordDispatch (nowTime, result, "SetProperty");
PrintProperty (inID, inScope, inElement);
}

void AUDebugDispatcher::Render ( UInt64 nowTime,
OSStatus result,
AudioUnitRenderActionFlags * inRenderFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inOutputBusNumber,
UInt32 inNumFrames,
AudioBufferList * inIOData)
{
if (mHaveDoneProperty) {
AUDD_Locker lock (mPrintMutex);
RecordDispatch (nowTime, result, "Render");
fprintf (mFile, "\t\t[Sample Time = %.0lf, NumFrames = %ld]\n", inTimeStamp->mSampleTime, inNumFrames);
mHaveDoneProperty = false;
}
RenderActions_HostCallbacks ();
}

#define kBeginLine " "

void AUDebugDispatcher::RenderActions_HostCallbacks ()
{
bool doPrint = !(mHostCB_WhenToPrint++ % 5000);
// (3) Host Transport State callback
// - this is printed below, but we use the transStateChange to see if we have something to print
Boolean isPlaying, transStateChange, isCycling;
Float64 currentSample, cycleStartBeat, cycleEndBeat;
OSStatus result = mAUBase->CallHostTransportState (&isPlaying, &transStateChange, &currentSample,
&isCycling, &cycleStartBeat, &cycleEndBeat);
bool newCB3Result = false;
if (result != mHostCB3_Result) {
mHostCB3_Result = result;
newCB3Result = true;
}

if (transStateChange) mHostCB_WhenToPrint = 1;
// Code to test the Host Callbacks
Float64 currentBeat, currentTempo;
// (1) Beat and Tempo callback
result = mAUBase->CallHostBeatAndTempo (&currentBeat, &currentTempo);
if (result) {
if (result != mHostCB1_Result) {
printf ("_HCback_ Error Calling HostBeatAndTempo:%ld\n", result);
mHostCB1_Result = result;
}
} else {
if (doPrint || currentBeat < 0 || transStateChange)
printf ("_HCback_ Beat and Tempo: Current Beat:%f, Current Tempo:%f\n", currentBeat, currentTempo);
}
// (2) Musical Time callback
UInt32 deltaSampleOffset, timeSig_Denom;
Float32 timeSig_Num;
Float64 currentMeasureDownBeat;
result = mAUBase->CallHostMusicalTimeLocation (&deltaSampleOffset, &timeSig_Num, &timeSig_Denom, &currentMeasureDownBeat);

if (result) {
if (result != mHostCB2_Result) {
printf ("%sError Calling CallHostMusicalTimeLocation:%ld\n", kBeginLine, result);
mHostCB2_Result = result;
}
} else {
if (doPrint || currentMeasureDownBeat < 0 || deltaSampleOffset < 0 || transStateChange) {
printf ("%sMusical Time: Delta Sample Offset:%ld, Time Sig:Num:%.1f, Time Sig:Denom:%ld, DownBeat:%f\n",
kBeginLine, deltaSampleOffset, timeSig_Num, timeSig_Denom, currentMeasureDownBeat);
}
}
if (mHostCB3_Result) {
if (newCB3Result) {
printf ("%sError Calling CallHostTransportState:%ld\n", kBeginLine, mHostCB3_Result);
}
} else {
if (doPrint || (mHostCB_WasPlaying != isPlaying) || transStateChange || currentSample < 0)
{
printf ("%sTransport State: Was Playing:%d, ", kBeginLine, mHostCB_WasPlaying);
mHostCB_WasPlaying = isPlaying;
printf ("Is Playing:%d, Transport State Changed:%d", isPlaying, transStateChange);
if (isPlaying) {
printf (", Current Sample:%.1f", currentSample);
if (isCycling)
printf (", Is Cycling [Start Beat:%.2f, End Beat:%.2f]", cycleStartBeat, cycleEndBeat);
}
printf ("\n");
}
}
}

#pragma mark -
#pragma mark __Utilities
#pragma mark -

static char* AUScopeStr (AudioUnitScope inScope)
{
switch (inScope) {
case kAudioUnitScope_Global: return "Global";
case kAudioUnitScope_Output: return "Output";
case kAudioUnitScope_Input: return "Input";
case kAudioUnitScope_Group: return "Group";
}
return NULL;
}

static char* AUErrorStr (OSStatus result)
{
switch (result) {
case kAudioUnitErr_InvalidProperty: return "Invalid Property";
case kAudioUnitErr_InvalidParameter: return "Invalid Parameter";
case kAudioUnitErr_InvalidElement: return "Invalid Element";
case kAudioUnitErr_NoConnection: return "Invalid Connection";
case kAudioUnitErr_FailedInitialization: return "Failed Initialization";
case kAudioUnitErr_TooManyFramesToProcess: return "Too Many Frames";
case kAudioUnitErr_IllegalInstrument: return "Illegal Instrument";
case kAudioUnitErr_InstrumentTypeNotFound: return "Instrument Type Not Found";
case kAudioUnitErr_InvalidFile: return "Invalid File";
case kAudioUnitErr_UnknownFileType: return "Unknown File Type";
case kAudioUnitErr_FileNotSpecified: return "File Not Specified";
case kAudioUnitErr_FormatNotSupported: return "Format Not Supported";
case kAudioUnitErr_Uninitialized: return "Un Initialized";
case kAudioUnitErr_InvalidScope: return "Invalid Scope";
case kAudioUnitErr_PropertyNotWritable: return "Property Not Writable";
case kAudioUnitErr_InvalidPropertyValue: return "Invalid Property Value";
case kAudioUnitErr_PropertyNotInUse: return "Property Not In Use";
case kAudioUnitErr_Initialized: return "Initialized";

// some common system errors
case badComponentSelector: return "Bad Component Selector";
case paramErr: return "Parameter Error";
case badComponentInstance: return "Bad Component Instance";
}
return "Unknown Error";
}

static char* AUPropertyStr (AudioUnitPropertyID inID)
{
switch (inID) {
case kAudioUnitProperty_ClassInfo: return "Class Info";
case kAudioUnitProperty_MakeConnection: return "Connection";
case kAudioUnitProperty_SampleRate: return "Sample Rate";
case kAudioUnitProperty_ParameterList: return "Parameter List";
case kAudioUnitProperty_ParameterInfo: return "Parameter Info";
case kAudioUnitProperty_FastDispatch: return "Fast Dispatch";
case kAudioUnitProperty_CPULoad: return "CPU Load";
case kAudioUnitProperty_StreamFormat: return "Format";
case kAudioUnitProperty_ReverbRoomType: return "Reverb Room Type";
case kAudioUnitProperty_ElementCount: return "Element Count";
case kAudioUnitProperty_Latency: return "Latency";
case kAudioUnitProperty_SupportedNumChannels: return "Supported Num Channels";
case kAudioUnitProperty_MaximumFramesPerSlice: return "Max Frames Per Slice";
case kAudioUnitProperty_SetExternalBuffer: return "Set External Buffer";
case kAudioUnitProperty_ParameterValueStrings: return "Parameter Value Strings";
case kAudioUnitProperty_GetUIComponentList: return "Carbon UI";
case kAudioUnitProperty_AudioChannelLayout: return "Audio Channel Layout";
case kAudioUnitProperty_TailTime: return "Tail Time";
case kAudioUnitProperty_BypassEffect: return "Bypass Effect";
case kAudioUnitProperty_LastRenderError: return "Last Render Error";
case kAudioUnitProperty_SetRenderCallback: return "Render Callback";
case kAudioUnitProperty_FactoryPresets: return "Factory Preset";
case kAudioUnitProperty_ContextName: return "Context Name";
case kAudioUnitProperty_RenderQuality: return "Render Quality";
case kAudioUnitProperty_HostCallbacks: return "Host Callbacks";
case kAudioUnitProperty_InPlaceProcessing: return "In Place Processing";
case kAudioUnitProperty_ElementName: return "Element Name";
case kAudioUnitProperty_CocoaUI: return "Cocoa UI";
case kAudioUnitProperty_SupportedChannelLayoutTags: return "Supported Channel Layout Tags";
case kAudioUnitProperty_ParameterStringFromValue: return "Parameter Value Name";
case kAudioUnitProperty_UsesInternalReverb: return "Use Internal Reverb";
case kAudioUnitProperty_ParameterIDName: return "Parameter ID Name";
case kAudioUnitProperty_ParameterClumpName: return "Clump Name";
case kAudioUnitProperty_PresentPreset: return "Present Preset";

case kMusicDeviceProperty_InstrumentCount: return "Instrument Count";
case kMusicDeviceProperty_InstrumentName: return "Instrument Name";
case kMusicDeviceProperty_SoundBankFSRef: return "Sound Bank - File";
case kMusicDeviceProperty_InstrumentNumber: return "Instrument Number";
case kMusicDeviceProperty_MIDIXMLNames: return "MIDI XML Names";
case kMusicDeviceProperty_BankName: return "Bank Name";
case kMusicDeviceProperty_SoundBankData: return "Sound Bank - Data";
case kAudioOutputUnitProperty_CurrentDevice: return "Current AudioDevice";
case kAudioOutputUnitProperty_IsRunning: return "Is Running";
case kAudioOutputUnitProperty_ChannelMap: return "Channel Map";
case kAudioOutputUnitProperty_EnableIO: return "Enable I/O";
case kAudioOutputUnitProperty_StartTime: return "Start Time";
case kAudioOutputUnitProperty_SetInputCallback: return "I/O Input Callback";
}
return "Unknown";
}

void AUDebugDispatcher::PrintProperty ( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement)
{
char* scopeStr = AUScopeStr(inScope);
char* propStr = AUPropertyStr (inID);
if (scopeStr != NULL)
fprintf (mFile, "\t\t[ID = %ld, %s, Scope = %s, El = %ld]\n", inID, propStr, scopeStr, inElement);
else
fprintf (mFile, "\t\t[ID = %ld, %s, Scope = %ld, El = %ld]\n", inID, propStr, inScope , inElement);
bool iscback = false;
bool isInput = false;
switch (inID)
{
case kAudioUnitProperty_SetRenderCallback:
iscback = true;
case kAudioUnitProperty_MakeConnection:
{
AUInputElement *el = mAUBase->GetInput (inElement);
if (el) {
bool hasInput = false;
if (iscback)
hasInput = el->IsCallback();
else
hasInput = el->HasConnection();
fprintf (mFile, "\t\tHas Input=%c, ", (hasInput ? 'T' : 'F'));
isInput = true;
}
}
case kAudioUnitProperty_SampleRate:
case kAudioUnitProperty_StreamFormat:
{
CAStreamBasicDescription desc = mAUBase->GetStreamFormat (inScope, inElement);
if (!isInput)
fprintf (mFile, "\t\t");
desc.Print (mFile);
break;
}
default:
break;
}
mHaveDoneProperty = true;
}

#endif //AU_DEBUG_DISPATCHER

+ 131
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUDebugDispatcher.h View File

@@ -0,0 +1,131 @@
/* 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.
*/
/*=============================================================================
* AUDebugDispatcher.h
* CAServices

=============================================================================*/

#ifndef __AUDebugDispatcher_h__
#define __AUDebugDispatcher_h__

#if AU_DEBUG_DISPATCHER

#include "CAHostTimeBase.h"
#include "CAMutex.h"
#include "AUBase.h"


class AUDebugDispatcher {
public:
AUDebugDispatcher (AUBase *au, FILE* file = stdout);
~AUDebugDispatcher();

// these are the AU API calls
void Initialize (UInt64 nowTime, OSStatus result);

void Uninitialize (UInt64 nowTime, OSStatus result);

void GetPropertyInfo (UInt64 nowTime,
OSStatus result,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 *outDataSize,
Boolean *outWritable);

void GetProperty ( UInt64 nowTime,
OSStatus result,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 *ioDataSize,
void *outData);
void SetProperty ( UInt64 nowTime,
OSStatus result,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
void Render ( UInt64 nowTime,
OSStatus result,
AudioUnitRenderActionFlags * inRenderFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inOutputBusNumber,
UInt32 inNumFrames,
AudioBufferList * inIOData);
private:
AUBase* mAUBase;
UInt64 mFirstTime;
FILE* mFile;
bool mHaveDoneProperty;
CAMutex mPrintMutex;


OSStatus mHostCB1_Result;
OSStatus mHostCB2_Result;
OSStatus mHostCB3_Result;
int mHostCB_WhenToPrint;
int mHostCB_WasPlaying;
double SecsSinceStart(UInt64 inNowTime)
{
UInt64 nanos = CAHostTimeBase::ConvertToNanos(inNowTime - mFirstTime);
return nanos * 1.0e-9;
}

unsigned int RecordDispatch (UInt64 inStartTime, OSStatus result, const char* inMethod);

void PrintHeaderString (UInt64 inNowTime, unsigned int inThread, const char* inMethod);
unsigned int AU() const { return (unsigned int)mAUBase->GetComponentInstance(); }
void PrintProperty (AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement);

void RenderActions_HostCallbacks ();
};

#endif // AU_DEBUG_DISPATCHER
#endif //__AUDebugDispatcher_h__

+ 149
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUInputFormatConverter.h View File

@@ -0,0 +1,149 @@
/* 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.
*/
#ifndef __AUInputFormatConverter_h__
#define __AUInputFormatConverter_h__

#include "FormatConverterClient.h"
#include "AUTimestampGenerator.h"

// ____________________________________________________________________________
// AUInputFormatConverter
//
// Subclass of FormatConverterClient that applies a format conversion
// to an input of an AudioUnit.
/*! @class AUInputFormatConverter */
class AUInputFormatConverter : public FormatConverterClient {
public:
/*! @ctor AUInputFormatConverter */
AUInputFormatConverter(AUBase *hostAU, int inputBus) :
mHost(hostAU),
mHostBus(inputBus),
mPreviousSilentFrames(0x1000)
{
#if DEBUG
mTimestampGenerator.mVerbosity = 0;
strcpy(mTimestampGenerator.mDebugName, "AUConverter");
#endif
}
// need to subsequently call Initialize, with the desired formats
/*! @dtor ~AUInputFormatConverter */
~AUInputFormatConverter()
{
}
virtual OSStatus Initialize(const AudioStreamBasicDescription &src, const AudioStreamBasicDescription &dest)
{
OSStatus err = FormatConverterClient::Initialize(src, dest);
if (err) return err;
mIsPCMToPCM = (src.mFormatID == kAudioFormatLinearPCM) && (dest.mFormatID == kAudioFormatLinearPCM);
mHasSRC = (fnonzero(src.mSampleRate) && fnonzero(dest.mSampleRate) && fnotequal(src.mSampleRate, dest.mSampleRate));
return ca_noErr;
}

virtual OSStatus Reset()
{
mPreviousSilentFrames = 0x1000;
mTimestampGenerator.Reset();
return FormatConverterClient::Reset();
}
void SetStartInputTimeAtZero(bool b)
{
mTimestampGenerator.SetStartInputAtZero(b);
}

/*! @method FillComplexBuffer */
OSStatus AUFillComplexBuffer(const AudioTimeStamp & inTimeStamp,
UInt32 & ioOutputDataPacketSize,
AudioBufferList & outOutputData,
AudioStreamPacketDescription* outPacketDescription,
bool& outSilence)
{
mTimestampGenerator.AddOutputTime(inTimeStamp, ioOutputDataPacketSize, mOutputFormat.mSampleRate);
mSilentOutput = true;
OSStatus err = FillComplexBuffer(ioOutputDataPacketSize, outOutputData, outPacketDescription);
if (mSilentOutput) {
if (!mIsPCMToPCM || (mHasSRC && mPreviousSilentFrames < 32))
mSilentOutput = false;
mPreviousSilentFrames += ioOutputDataPacketSize;
} else
mPreviousSilentFrames = 0;
outSilence = mSilentOutput;
return err;
}

/*! @method FormatConverterInputProc */
virtual OSStatus FormatConverterInputProc(
UInt32 & ioNumberDataPackets,
AudioBufferList & ioData,
AudioStreamPacketDescription** outDataPacketDescription)
{
OSStatus err = ca_noErr;
AudioUnitRenderActionFlags actionFlags = 0;
AUInputElement *input = mHost->GetInput(mHostBus);
*ioNumberDataPackets = std::min(*ioNumberDataPackets, This->mHost->GetMaxFramesPerSlice());
const AudioTimeStamp &inputTime = mTimestampGenerator.GenerateInputTime(ioNumberDataPackets, mInputFormat.mSampleRate);
err = input->PullInput(actionFlags, inputTime, mHostBus, ioNumberDataPackets);
if (!err) {
input->CopyBufferListTo(ioData);
if (!(actionFlags & kAudioUnitRenderAction_OutputIsSilence))
mSilentOutput = false;
}
return err;
}

protected:
/*! @var mHost */
AUBase * mHost;
/*! @var mHostBus */
int mHostBus;
AUTimestampGenerator mTimestampGenerator;
bool mIsPCMToPCM;
bool mHasSRC;
bool mSilentOutput;
UInt32 mPreviousSilentFrames;
};

#endif // __AUInputFormatConverter_h__

+ 87
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUSilentTimeout.h View File

@@ -0,0 +1,87 @@
/* 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.
*/
#ifndef __AUSilentTimeout
#define __AUSilentTimeout

class AUSilentTimeout
{
public:
AUSilentTimeout()
: mTimeoutCounter(0),
mResetTimer(true)
{};

void Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool &ioSilence )
{
if(ioSilence )
{
if(mResetTimer )
{
mTimeoutCounter = inTimeoutLimit;
mResetTimer = false;
}
if(mTimeoutCounter > 0 )
{
mTimeoutCounter -= inFramesToProcess;
ioSilence = false;
}
}
else
{
// signal to reset the next time we receive silence
mResetTimer = true;
}
}

void Reset()
{
mResetTimer = true;
};



private:
SInt32 mTimeoutCounter;
bool mResetTimer;
};

#endif // __AUSilentTimeout

+ 185
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.cpp View File

@@ -0,0 +1,185 @@
/* 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 "AUTimestampGenerator.h"
#include "CAMath.h"

#if DEBUG
static double DebugHostTime(const AudioTimeStamp &ts)
{
static UInt64 baseHostTime = 0;
if (!(ts.mFlags & kAudioTimeStampHostTimeValid))
return -1.;
if (baseHostTime == 0)
baseHostTime = ts.mHostTime;
return double(SInt64(ts.mHostTime) - SInt64(baseHostTime)) * CAHostTimeBase::GetInverseFrequency();
}
#endif

void AUTimestampGenerator::AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj)
{
mRateScalarAdj = rateScalarAdj;
mLastOutputTime = mCurrentOutputTime;
mCurrentOutputTime = inTimeStamp;
if (mBypassed)
return;
if (mHostTimeDiscontinuityCorrection && !(mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) && (mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
// no host time here but we had one last time, interpolate one
double rateScalar = (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) ? mCurrentOutputTime.mRateScalar : 1.0;
Float64 deltaSamples = mCurrentOutputTime.mSampleTime - mLastOutputTime.mSampleTime;
mCurrentOutputTime.mHostTime = mLastOutputTime.mHostTime +
UInt64(CAHostTimeBase::GetFrequency() * deltaSamples * rateScalar / outputSampleRate);
mCurrentOutputTime.mFlags |= kAudioTimeStampHostTimeValid;
#if DEBUG
if (mVerbosity > 1)
printf("synthesized host time: %.3f (%.3f + %.f smp @ %.f Hz, rs %.3f\n", DebugHostTime(mCurrentOutputTime), DebugHostTime(mLastOutputTime), deltaSamples, outputSampleRate, rateScalar);
#endif
}
// copy rate scalar
if (rateScalarAdj != 1.0) {
if (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid)
mCurrentOutputTime.mRateScalar *= rateScalarAdj;
else {
mCurrentOutputTime.mRateScalar = rateScalarAdj;
mCurrentOutputTime.mFlags |= kAudioTimeStampRateScalarValid;
}
}
if (mFirstTime) {
mFirstTime = false;
mDiscontinuous = false;
mDiscontinuityDeltaSamples = 0.;
if (!mStartInputAtZero)
mNextInputSampleTime = mCurrentOutputTime.mSampleTime;
} else {
mDiscontinuous = fnotequal(mCurrentOutputTime.mSampleTime, mNextOutputSampleTime);
mDiscontinuityDeltaSamples = mCurrentOutputTime.mSampleTime - mNextOutputSampleTime;
// time should never go backwards...
if (mDiscontinuityDeltaSamples < 0.)
mDiscontinuityDeltaSamples = 0.;
#if DEBUG
if (mVerbosity > 1)
if (mDiscontinuous)
printf("%-20.20s: *** DISCONTINUOUS, got "TSGFMT", expected "TSGFMT"\n", mDebugName, (SInt64)mCurrentOutputTime.mSampleTime, (SInt64)mNextOutputSampleTime);
#endif
}
mNextOutputSampleTime = mCurrentOutputTime.mSampleTime + expectedDeltaFrames;
}

const AudioTimeStamp & AUTimestampGenerator::GenerateInputTime(Float64 framesToAdvance, double inputSampleRate)
{
if (mBypassed)
return mCurrentOutputTime;

double inputSampleTime;
mCurrentInputTime.mFlags = kAudioTimeStampSampleTimeValid;
double rateScalar = 1.0;
// propagate rate scalar
if (mCurrentOutputTime.mFlags & kAudioTimeStampRateScalarValid) {
mCurrentInputTime.mFlags |= kAudioTimeStampRateScalarValid;
mCurrentInputTime.mRateScalar = rateScalar = mCurrentOutputTime.mRateScalar;
}
// propagate host time and sample time
if (mCurrentOutputTime.mFlags & kAudioTimeStampHostTimeValid) {
mCurrentInputTime.mFlags |= kAudioTimeStampHostTimeValid;
mCurrentInputTime.mHostTime = mCurrentOutputTime.mHostTime;
if (mHostTimeDiscontinuityCorrection && mDiscontinuous && (mLastOutputTime.mFlags & kAudioTimeStampHostTimeValid)) {
// we had a discontinuous output time, need to resync by interpolating
// a sample time that is appropriate to the host time
UInt64 deltaHostTime = mCurrentOutputTime.mHostTime - mLastOutputTime.mHostTime;
double deltaSeconds = double(deltaHostTime) * CAHostTimeBase::GetInverseFrequency();
// samples/second * seconds = samples
double deltaSamples = floor(inputSampleRate / rateScalar * deltaSeconds + 0.5);
double lastInputSampleTime = mCurrentInputTime.mSampleTime;
inputSampleTime = lastInputSampleTime + deltaSamples;
#if DEBUG
if (mVerbosity > 1)
printf("%-20.20s: adjusted input time: "TSGFMT" -> "TSGFMT" (SR=%.3f, rs=%.3f)\n", mDebugName, (SInt64)lastInputSampleTime, (SInt64)inputSampleTime, inputSampleRate, rateScalar);
#endif
mDiscontinuous = false;
} else {
inputSampleTime = mNextInputSampleTime;
}
} else {
// we don't know the host time, so we can't do much
inputSampleTime = mNextInputSampleTime;
}

if (!mHostTimeDiscontinuityCorrection && fnonzero(mDiscontinuityDeltaSamples))
{
// we had a discontinuous output time, need to resync by propagating the
// detected discontinuity, taking the rate scalar adjustment into account
inputSampleTime += floor(mDiscontinuityDeltaSamples / mRateScalarAdj + 0.5);
#if DEBUG
if (mVerbosity > 1)
printf("%-20.20s: adjusted input time: %.0f -> %.0f (SR=%.3f, rs=%.3f, delta=%.0f)\n", mDebugName, mNextInputSampleTime, inputSampleTime, inputSampleRate, mRateScalarAdj, mDiscontinuityDeltaSamples);
#endif
mDiscontinuityDeltaSamples = 0.;
}
// propagate word clock
if (mCurrentOutputTime.mFlags & kAudioTimeStampWordClockTimeValid) {
mCurrentInputTime.mFlags |= kAudioTimeStampWordClockTimeValid;
mCurrentInputTime.mWordClockTime = mCurrentOutputTime.mWordClockTime;
}
// propagate SMPTE time
if (mCurrentOutputTime.mFlags & kAudioTimeStampSMPTETimeValid) {
mCurrentInputTime.mFlags |= kAudioTimeStampSMPTETimeValid;
mCurrentInputTime.mSMPTETime = mCurrentOutputTime.mSMPTETime;
}
// store the input sample time and expected next input time
mCurrentInputTime.mSampleTime = inputSampleTime;
mNextInputSampleTime = inputSampleTime + framesToAdvance;

#if DEBUG
if (mVerbosity > 0) {
printf("%-20.20s: out = "TSGFMT" (%10.3fs) in = "TSGFMT" (%10.3fs) delta = "TSGFMT" advance = "TSGFMT"\n", mDebugName, (SInt64)mCurrentOutputTime.mSampleTime, DebugHostTime(mCurrentOutputTime), (SInt64)inputSampleTime, DebugHostTime(mCurrentInputTime), (SInt64)(mCurrentOutputTime.mSampleTime - inputSampleTime), (SInt64)framesToAdvance);
}
#endif
return mCurrentInputTime;
}

+ 148
- 0
distrho/src/CoreAudio106/AudioUnits/AUPublic/Utility/AUTimestampGenerator.h View File

@@ -0,0 +1,148 @@
/* 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.
*/
#ifndef __AUTimestampGenerator_h__
#define __AUTimestampGenerator_h__

#include <math.h>
#include "CAHostTimeBase.h"
#include <stdio.h>

#define TSGFMT "0x%10qx"
//#define TSGFMT "%10qd"

// This class generates a continuously increasing series of timestamps based
// on a series of potentially discontinuous timestamps (as can be delivered from
// CoreAudio in the event of an overload or major engine change).
// N.B.: "output" = downstream (source) timestamp
// "input" = upstream (derived) timestamp
class AUTimestampGenerator {
public:
AUTimestampGenerator(bool hostTimeDiscontinuityCorrection = false) :
mStartInputAtZero(true),
mBypassed(false),
mHostTimeDiscontinuityCorrection(hostTimeDiscontinuityCorrection)
{
#if DEBUG
mVerbosity = 0;
sprintf(mDebugName, "tsg @ %p", this);
#endif
// CAHostTimeBase should be used instead of the calls in <CoreAudio/HostTime.h>
// we make this call here to ensure that this is initialized, otherwise the first time
// you do actually call CAHostTimeBase to do work, can be on the render thread, and lead to unwanted VM faults
CAHostTimeBase::GetFrequency();
Reset();
}
void SetStartInputAtZero(bool b) { mStartInputAtZero = b; }
bool GetStartInputAtZero() const { return mStartInputAtZero; }
// bypassing is intended for a narrow special case. the upstream sample time will always be the same as the downstream time.
void SetBypassed(bool b) { mBypassed = b; }
bool GetBypassed() const { return mBypassed; }
// Call this to reset the timeline.
void Reset()
{
mCurrentInputTime.mSampleTime = 0.;
mNextInputSampleTime = 0.;
mCurrentOutputTime.mSampleTime = 0.;
mNextOutputSampleTime = 0.;
mLastOutputTime.mFlags = 0;
mRateScalarAdj = 1.;
mFirstTime = true;
#if DEBUG
if (mVerbosity)
printf("%-20.20s: Reset\n", mDebugName);
#endif
}
// Call this once per render cycle with the downstream timestamp.
// expectedDeltaFrames is the expected difference between the current and NEXT
// downstream timestamps.
// sampleRate is the OUTPUT sample rate.
void AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj=1.0);
// Call this once per render cycle to obtain the upstream timestamp.
// framesToAdvance is the number of frames the input timeline is to be
// advanced during this render cycle.
// sampleRate is the INPUT sample rate.
const AudioTimeStamp & GenerateInputTime(Float64 framesToAdvance, double inputSampleRate);
// this can be called to override the setting of the next input sample time in GenerateInputTime
void Advance(Float64 framesToAdvance)
{
#if DEBUG
if (mVerbosity > 1)
printf("%-20.20s: ADVANCE in = "TSGFMT" advance = "TSGFMT"\n", mDebugName, (SInt64)mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
#endif
mNextInputSampleTime = mCurrentInputTime.mSampleTime + framesToAdvance;
}
private:
AudioTimeStamp mCurrentInputTime;
Float64 mNextInputSampleTime;
Float64 mNextOutputSampleTime;

AudioTimeStamp mLastOutputTime;
AudioTimeStamp mCurrentOutputTime;

bool mFirstTime;
bool mStartInputAtZero; // if true, input timeline starts at 0, else it starts
// synced with the output timeline
bool mDiscontinuous;
bool mBypassed;
Float64 mDiscontinuityDeltaSamples;
double mRateScalarAdj;
bool mHostTimeDiscontinuityCorrection; // If true, propagate timestamp discontinuities using host time.

#if DEBUG
public:
int mVerbosity;
char mDebugName[64];
#endif
};


#endif // __AUTimestampGenerator_h__

+ 163
- 0
distrho/src/CoreAudio106/PublicUtility/AUOutputBL.cpp View File

@@ -0,0 +1,163 @@
/* 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 "AUOutputBL.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AUComponent.h>
#else
#include <AUComponent.h>
#endif
/*
struct AudioBufferList
{
UInt32 mNumberBuffers;
AudioBuffer mBuffers[1];
};
struct AudioBuffer
{
UInt32 mNumberChannels; // number of interleaved channels in the buffer
UInt32 mDataByteSize; // the size of the buffer pointed to by mData
void* mData; // the pointer to the buffer
};
*/

AUOutputBL::AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames)
: mFormat (inDesc),
mBufferMemory(NULL),
mBufferList (NULL),
mNumberBuffers (0), // keep this here, so can ensure integrity of ABL
mBufferSize (0),
mFrames(inDefaultNumFrames)
{
mNumberBuffers = mFormat.IsInterleaved() ? 1 : mFormat.NumberChannels();
mBufferList = reinterpret_cast<AudioBufferList*>(new Byte[offsetof(AudioBufferList, mBuffers) + (mNumberBuffers * sizeof(AudioBuffer))]);
}

AUOutputBL::~AUOutputBL()
{
if (mBufferMemory)
delete[] mBufferMemory;

if (mBufferList)
delete [] (Byte *)mBufferList;
}

void AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated)
{
UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1;
if (mBufferMemory == NULL || inWantNullBufferIfAllocated)
{
mBufferList->mNumberBuffers = mNumberBuffers;
AudioBuffer *buf = &mBufferList->mBuffers[0];
for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
buf->mNumberChannels = channelsPerBuffer;
buf->mDataByteSize = mFormat.FramesToBytes (inNumFrames);
buf->mData = NULL;
}
}
else
{
UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
if ((nBytes * mNumberBuffers) > AllocatedBytes())
throw OSStatus(kAudioUnitErr_TooManyFramesToProcess);
mBufferList->mNumberBuffers = mNumberBuffers;
AudioBuffer *buf = &mBufferList->mBuffers[0];
Byte* p = mBufferMemory;
for (UInt32 i = 0; i < mNumberBuffers; ++i, ++buf) {
buf->mNumberChannels = channelsPerBuffer;
buf->mDataByteSize = nBytes;
buf->mData = p;
p += mBufferSize;
}
}
}


void AUOutputBL::Allocate (UInt32 inNumFrames)
{
if (inNumFrames)
{
UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
if (nBytes <= AllocatedBytes())
return;
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
if (mNumberBuffers > 1)
nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
mBufferSize = nBytes;
UInt32 memorySize = mBufferSize * mNumberBuffers;
Byte *newMemory = new Byte[memorySize];
memset(newMemory, 0, memorySize); // make buffer "hot"
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
delete[] oldMemory;
mFrames = inNumFrames;
}
else
{
if (mBufferMemory) {
delete [] mBufferMemory;
mBufferMemory = NULL;
}
mBufferSize = 0;
mFrames = 0;
}
}

#if DEBUG
void AUOutputBL::Print()
{
printf ("AUOutputBL::Print\n");
mFormat.Print();
printf ("Num Buffers:%d, mFrames:%d, allocatedMemory:%c\n", (int)mBufferList->mNumberBuffers, (int)mFrames, (mBufferMemory != NULL ? 'T' : 'F'));
AudioBuffer *buf = &mBufferList->mBuffers[0];
for (UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i, ++buf)
printf ("\tBuffer:%d, Size:%d, Chans:%d, Buffer:%p\n", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
}
#endif


+ 112
- 0
distrho/src/CoreAudio106/PublicUtility/AUOutputBL.h View File

@@ -0,0 +1,112 @@
/* 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.
*/
#ifndef __AUOutputBL_h__
#define __AUOutputBL_h__

#include "CAStreamBasicDescription.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#else
#endif

// ____________________________________________________________________________
//
// AUOutputBL - Simple Buffer List wrapper targetted to use with retrieving AU output
// Works in one of two ways (both adjustable)... Can use it with NULL pointers, or allocate
// memory to receive the data in.

// Before using this with any call to AudioUnitRender, it needs to be Prepared
// as some calls to AudioUnitRender can reset the ABL

class AUOutputBL {
public:
// you CANNOT use one of these - it will crash!
// AUOutputBL ();
// this is the constructor that you use
// it can't be reset once you've constructed it
AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames = 512);
~AUOutputBL();

void Prepare ()
{
Prepare (mFrames);
}
// this version can throw if this is an allocted ABL and inNumFrames is > AllocatedFrames()
// you can set the bool to true if you want a NULL buffer list even if allocated
// inNumFrames must be a valid number (will throw if inNumFrames is 0)
void Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated = false);
AudioBufferList* ABL() { return mBufferList; }
// You only need to call this if you want to allocate a buffer list
// if you want an empty buffer list, just call Prepare()
// if you want to dispose previously allocted memory, pass in 0
// then you either have an empty buffer list, or you can re-allocate
// Memory is kept around if an Allocation request is less than what is currently allocated
void Allocate (UInt32 inNumberFrames);
UInt32 AllocatedFrames() const { return mFrames; }
const CAStreamBasicDescription& GetFormat() const { return mFormat; }

#if DEBUG
void Print();
#endif
private:
UInt32 AllocatedBytes () const { return (mBufferSize * mNumberBuffers); }

CAStreamBasicDescription mFormat;
Byte* mBufferMemory;
AudioBufferList* mBufferList;
UInt32 mNumberBuffers;
UInt32 mBufferSize;
UInt32 mFrames;

// don't want to copy these.. can if you want, but more code to write!
AUOutputBL () {}
AUOutputBL (const AUOutputBL &c) {}
AUOutputBL& operator= (const AUOutputBL& c) { return *this; }
};

#endif // __AUOutputBL_h__

+ 133
- 0
distrho/src/CoreAudio106/PublicUtility/AUParamInfo.cpp View File

@@ -0,0 +1,133 @@
/* 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 "AUParamInfo.h"
#include "CAXException.h"

AUParamInfo::AUParamInfo (AudioUnit inAU,
bool inIncludeExpert,
bool inIncludeReadOnly,
AudioUnitScope inScope,
AudioUnitElement inElement)
: mAU (inAU),
mNumParams (0),
mParamListID(NULL),
mScope (inScope),
mElement (inElement)
{
UInt32 size;
OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL);
if (size == 0 || result) return;
int nparams = size / sizeof(AudioUnitPropertyID);
mParamListID = new AudioUnitParameterID[nparams];

memset (mParamListID, 0xFF, size);

AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams];
result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size);
if (result) {
delete [] mParamListID;
delete [] paramList;
mParamListID = NULL;
return;
}
ParameterMap params;
for (int i = 0; i < nparams; ++i)
{
CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation
const AudioUnitParameterInfo &paramInfo = auvp.ParamInfo();
// don't include if parameter can't be read or written
if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
&& !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
continue;

// only include if expert params wanted
if (!inIncludeExpert && auvp.IsExpert())
continue;
// only include if read only params are wanted
if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
&& (paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
{
if (!inIncludeReadOnly)
continue;
}
mParamListID[mNumParams] = paramList[i];
mNumParams++;
// ok - if we're here, then we have a parameter we are going to display.
UInt32 clump = 0;
auvp.GetClumpID (clump);
mParams[clump].push_back (auvp);
}

delete [] paramList;
}

AUParamInfo::~AUParamInfo()
{
delete [] mParamListID;
}

UInt32 AUParamInfo::NumParamsForClump (UInt32 inClump) const
{
ParameterMap::const_iterator it = mParams.find(inClump);
if (it != mParams.end())
return (*it).second.size();
return 0;
}

const CAAUParameter* AUParamInfo::GetParamInfo (AudioUnitParameterID inParamID) const
{
for (ParameterMap::const_iterator it = mParams.begin(); it != mParams.end(); ++it) {
const ParameterList &list = (*it).second;
for (ParameterList::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
if (inParamID == (*iter).mParameterID) {
return &(*iter);
}
}
}
return NULL;
}

+ 106
- 0
distrho/src/CoreAudio106/PublicUtility/AUParamInfo.h View File

@@ -0,0 +1,106 @@
/* 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 <map>
#include <vector>
#include <AudioUnit/AudioUnit.h>
#include "CAAUParameter.h"

/*
The ParameterMap returned by the Map() method is a map where
- the key is the clumpID
- the value is a ParameterList (vector<CAAUParameter>)
If you have parameters on multiple scopes (or elements within a scope), then you should create one of these
for each scope-element pair
*/

class AUParamInfo {

public:
typedef std::vector <CAAUParameter> ParameterList;
typedef std::map <UInt32, ParameterList, std::less<UInt32> > ParameterMap;



AUParamInfo (AudioUnit inAU,
bool inIncludeExpert,
bool inIncludeReadOnly,
AudioUnitScope inScope = kAudioUnitScope_Global,
AudioUnitElement inElement = 0);
~AUParamInfo();
const ParameterMap& Map () const { return mParams; }
// some convenience methods
UInt32 NumParams () const { return mNumParams; }
AudioUnitParameterID ParamID (UInt32 inIndex) const
{
if (inIndex < mNumParams) return mParamListID[inIndex];
return 0xFFFFFFFF;
}
UInt32 NumClumps () const { return mParams.size(); }

UInt32 NumParamsForClump (UInt32 inClump) const;
// returns NULL if there's no info for the parameter
const CAAUParameter* GetParamInfo (AudioUnitParameterID inParamID) const;
AudioUnitScope GetScope () const { return mScope; }
AudioUnitElement GetElement () const { return mElement; }
private:

AudioUnit mAU;
UInt32 mNumParams;
AudioUnitParameterID * mParamListID;
ParameterMap mParams;
AudioUnitScope mScope;
AudioUnitElement mElement;
// disallow
AUParamInfo () {}
AUParamInfo (const AUParamInfo &c) {}
AUParamInfo& operator= (const AUParamInfo& c) { return *this; }
};

+ 194
- 0
distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.cpp View File

@@ -0,0 +1,194 @@
/* 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 "CAAUMIDIMap.h"


static MIDILinearTransformer linearTrans;
static MIDILogTransformer logTrans;
static MIDIExpTransformer expTrans;
static MIDISqrtTransformer sqrtTrans;
static MIDISquareTransformer squareTrans;
static MIDICubeRtTransformer cubeRtTrans;
static MIDICubeTransformer cubeTrans;

MIDIValueTransformer * CAAUMIDIMap::GetTransformer (UInt32 inFlags)
{
if (AudioUnitDisplayTypeIsLogarithmic(inFlags))
return &logTrans;
else if (AudioUnitDisplayTypeIsExponential(inFlags))
return &expTrans;
else if (AudioUnitDisplayTypeIsSquareRoot(inFlags))
return &sqrtTrans;
else if (AudioUnitDisplayTypeIsSquared(inFlags))
return &squareTrans;
else if (AudioUnitDisplayTypeIsCubed(inFlags))
return &cubeTrans;
else if (AudioUnitDisplayTypeIsCubeRoot(inFlags))
return &cubeRtTrans;
else
return &linearTrans;
}

// The CALLER of this method must ensure that the status byte's MIDI Command matches!!!
bool CAAUMIDIMap::MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const
{
// see if the channels match first
SInt8 chan = Channel();
// channel matches (if chan is less than zero, "Any Channel" flag is set)
if (chan >= 0 && chan != inChannel)
return false;

// match the special cases first
if (IsKeyEvent()) {
// we're using this key event as an on/off type switch
if (IsBipolar()) {
if (IsKeyPressure()){
if (IsBipolar_OnValue()) {
if (inData2 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData2 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
else {
if (IsBipolar_OnValue()) {
if (inData1 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData1 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
}
if (IsAnyNote()) {
// not quite sure how to interpret this...
if (IsKeyPressure())
outLinear = inData2 / 127.0;
else
outLinear = inData1 / 127.0;
return true;
}
if (mData1 == inData1) {
if (IsKeyPressure())
outLinear = inData2 / 127.0;
else
outLinear = 1;
return true;
}
return false;
}
else if (IsControlChange()) {
// controller ID matches
if (mData1 == inData1) {
if (IsBipolar()) {
if (IsBipolar_OnValue()) {
if (inData2 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData2 < 64) {
outLinear = 0;
return true;
}
}
return false;
}
//printf("this in midi matches %X with ", this);
outLinear = inData2 / 127.;
return true;
}
return false;
}
// this just matches on the patch change value itself...
if (IsPatchChange()) {
if (mData1 == inData1) {
outLinear = 1;
return true;
}
return false;
}

// finally, for the other two, just check the bi-polar matching conditions
// pitch bend and after touch
if (IsBipolar()) {
if (IsBipolar_OnValue()) {
if (inData1 > 63) {
outLinear = 1;
return true;
}
} else {
if (inData1 < 64) {
outLinear = 0;
return true;
}
}
return false;
}

if (IsPitchBend()) {
UInt16 value = (inData2 << 7) | inData1;
outLinear = value / 16383.;
}
else if (IsChannelPressure()) {
outLinear = inData1 / 127.0;
}

return true;
}


void CAAUMIDIMap::Print () const
{
printf ("CAAUMIDIMap:%p, (%u/%u), mParamID %d, IsValid:%c, Status:0x%X, mData1 %d, Flags:0x%X\n", this, (unsigned int)mScope, (unsigned int)mElement, (int)mParameterID, (IsValid() ? 'T' : 'F'), mStatus, mData1, (int)mFlags);
}

+ 535
- 0
distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMap.h View File

@@ -0,0 +1,535 @@
/* 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.
*/
#ifndef __CAAUMIDIMap_h_
#define __CAAUMIDIMap_h_

#include <AudioUnit/AudioUnitProperties.h>
#include <algorithm>

/*
enum {
kAUParameterMIDIMapping_AnyChannelFlag = (1L << 0),
// If this flag is set and mStatus is a MIDI channel message, then the MIDI channel number
// in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.

kAUParameterMIDIMapping_AnyNoteFlag = (1L << 1),
// If this flag is set and mStatus is a Note On, Note Off, or Polyphonic Pressure message,
// the message's note number is ignored; the mapping is from ANY note number.

kAUParameterMIDIMapping_SubRange = (1L << 2),
// set this flag if the midi control should map only to a sub-range of the parameter's value
// then specify that range in the mSubRangeMin and mSubRangeMax members

kAUParameterMIDIMapping_Toggle = (1L << 3),
// this is only useful for boolean typed parameters. When set, it means that the parameter's
// value should be toggled (if true, become false and vice versa) when the represented MIDI message
// is received
kAUParameterMIDIMapping_Bipolar = (1L << 4),
// this can be set to when mapping a MIDI Controller to indicate that the parameter (typically a boolean
// style parameter) will only have its value changed to either the on or off state of a MIDI controller message
// (0 < 64 is off, 64 < 127 is on) such as the sustain pedal. The seeting of the next flag
// (kAUParameterMIDIMapping_Bipolar_On) determine whether the parameter is mapped to the on or off
// state of the controller
kAUParameterMIDIMapping_Bipolar_On = (1L << 5)
// only a valid flag if kAUParameterMIDIMapping_Bipolar is set
};

// The reserved fields here are being used to reserve space (as well as align to 64 bit size) for future use
// When/If these fields are used, the names of the fields will be changed to reflect their functionality
// so, apps should NOT refer to these reserved fields directly by name
typedef struct AUParameterMIDIMapping
{
AudioUnitScope mScope;
AudioUnitElement mElement;
AudioUnitParameterID mParameterID;
UInt32 mFlags;
Float32 mSubRangeMin;
Float32 mSubRangeMax;
UInt8 mStatus;
UInt8 mData1;
UInt8 reserved1; // MUST be set to zero
UInt8 reserved2; // MUST be set to zero
UInt32 reserved3; // MUST be set to zero
} AUParameterMIDIMapping;
*/

/*
Parameter To MIDI Mapping Properties
These properties are used to:
Describe a current set of mappings between MIDI messages and Parameter value setting
Create a mapping between a parameter and a MIDI message through either:
- explicitly adding (or removing) the mapping
- telling the AU to hot-map the next MIDI message to a specified Parameter
The same MIDI Message can map to one or more parameters
One Parameter can be mapped from multiple MIDI messages

In general usage, these properties only apply to AU's that implement the MIDI API
AU Instruments (type=='aumu') and Music Effects (type == 'aumf')

These properties are used in the Global scope. The scope and element members of the structure describe
the scope and element of the parameter. In all usages, mScope, mElement and mParameterID must be
correctly specified.


* The AUParameterMIDIMapping Structure

Command mStatus mData1
Note Off 0x8n Note Num
Note On 0x9n Note Num
Key Pressure 0xAn Note Num
Control Change 0xBn ControllerID
Patch Change 0xCn Patch Num
Channel Pressure DxDn 0 (Unused)
Pitch Bend 0xEn 0 (Unused)

(where n is 0-0xF to correspond to MIDI channels 1-16)

Details:

In general MIDI Commands can be mapped to either a specific channel as specified in the mStatus bit.
If the kAUParameterMIDIMapping_AnyChannelFlag bit is set mStatus is a MIDI channel message, then the
MIDI channel number in the status byte is ignored; the mapping is from the specified MIDI message on ANY channel.

For note commands (note on, note off, key pressure), the MIDI message can trigger either with just a specific
note number, or any note number if the kAUParameterMIDIMapping_AnyNoteFlag bit is set. In these instances, the
note number is used as the trigger value (for instance, a note message could be used to set the
cut off frequency of a filter).

The Properties:

kAudioUnitProperty_AllParameterMIDIMappings array of AUParameterMIDIMapping (read/write)
This property is used to both retreive and set the current mapping state between (some/many/all of) its parameters
and MIDI messages. When set, it should replace any previous mapped settings the AU had.

If this property is implemented by a non-MIDI capable AU (such as an 'aufx' type), then the property is
read only, and recommends a suggested set of mappings for the host to perform. In this case, it is the
host's responsibility to map MIDI message to the AU parameters. As described previously, there are a set
of default mappings (see AudioToolbox/AUMIDIController.h) that the host can recommend to the user
in this circumstance.

This property's size will be very dynamic, depending on the number of mappings currently in affect, so the
caller should always get the size of the property first before retrieving it. The AU should return an error
if the caller doesn't provide enough space to return all of the current mappings.

kAudioUnitProperty_AddParameterMIDIMapping array of AUParameterMIDIMapping (write only)
This property is used to Add mappings to the existing set of mappings the AU possesses. It does NOT replace
any existing mappings.

kAudioUnitProperty_RemoveParameterMIDIMapping array of AUParameterMIDIMapping (write only)
This property is used to remove the specified mappings from the AU. If a mapping is specified that does not
currently exist in the AU, then it should just be ignored.

kAudioUnitProperty_HotMapParameterMIDIMapping AUParameterMIDIMapping (read/write)
This property is used in two ways, determined by the value supplied by the caller.
(1) If a mapping struct is provided, then that struct provides *all* of the information that the AU should
use to map the parameter, *except* for the MIDI message. The AU should then listen for the next MIDI message
and associate that MIDI message with the supplied AUParameter mapping. When this MIDI message is received and
the mapping made, the AU should also issue a notification on this property
(kAudioUnitProperty_HotMapParameterMIDIMapping) to indicate to the host that the mapping has been made. The host
can then retrieve the mapping that was made by getting the value of this property.

To avoid possible confusion, it is recommended that once the host has retrieved this mapping (if it is
presenting a UI to describe the mappings for example), that it then clears the mapping state as described next.

Thus, the only time this property will return a valid value is when the AU has made a mapping. If the AU's mapping
state has been cleared (or it has not been asked to make a mapping), then the AU should return
kAudioUnitErr_InvalidPropertyValue if the host tries to read this value.

(2) If the value passed in is NULL, then if the AU had a parameter that it was in the process of mapping, it
should disregard that (stop listening to the MIDI messages to create a mapping) and discard the partially
mapped struct. If the value is NULL and the AU is not in the process of mapping, the AU can ignore the request.

At all times, the _AllMappings property will completely describe the current known state of the AU's mappings
of MIDI messages to parameters.
*/


/*
When mapping, it is recommended that LSB controllers are in general not mapped (ie. the controller range of 32 < 64)
as many host parsers will map 14 bit control values. If you know (or can present an option) that the host deals with
7 bit controllers only, then these controller ID's can be mapped of course.
*/


struct MIDIValueTransformer {
virtual double tolinear(double) = 0;
virtual double fromlinear(double) = 0;
#if DEBUG
// suppress warning
virtual ~MIDIValueTransformer() { }
#endif
};

struct MIDILinearTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x; }
virtual double fromlinear(double x) { return x; }
};

struct MIDILogTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return log(std::max(x, .00001)); }
virtual double fromlinear(double x) { return exp(x); }
};

struct MIDIExpTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return exp(x); }
virtual double fromlinear(double x) { return log(std::max(x, .00001)); }
};

struct MIDISqrtTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
virtual double fromlinear(double x) { return x < 0. ? -(x * x) : x * x; }
};

struct MIDISquareTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x < 0. ? -(x * x) : x * x; }
virtual double fromlinear(double x) { return x < 0. ? -(sqrt(-x)) : sqrt(x); }
};

struct MIDICubeRtTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
virtual double fromlinear(double x) { return x * x * x; }
};

struct MIDICubeTransformer : public MIDIValueTransformer {
virtual double tolinear(double x) { return x * x * x; }
virtual double fromlinear(double x) { return x < 0. ? -(pow(-x, 1./3.)) : pow(x, 1./3.); }
};


class CAAUMIDIMap : public AUParameterMIDIMapping {
public:
// variables for more efficient parsing of MIDI to Param value
Float32 mMinValue;
Float32 mMaxValue;
MIDIValueTransformer *mTransType;

// methods
static MIDIValueTransformer *GetTransformer (UInt32 inFlags);
CAAUMIDIMap() { memset(this, 0, sizeof(CAAUMIDIMap)); }
CAAUMIDIMap (const AUParameterMIDIMapping& inMap)
{
memset(this, 0, sizeof(CAAUMIDIMap));
memcpy (this, &inMap, sizeof(inMap));
}
CAAUMIDIMap (AudioUnitScope inScope, AudioUnitElement inElement, AudioUnitParameterID inParam)
{
memset(this, 0, sizeof(CAAUMIDIMap));
mScope = inScope;
mElement = inElement;
mParameterID = inParam;
}


bool IsValid () const { return mStatus != 0; }

// returns -1 if any channel bit is set
SInt32 Channel () const { return IsAnyChannel() ? -1 : (mStatus & 0xF); }
bool IsAnyChannel () const {
return mFlags & kAUParameterMIDIMapping_AnyChannelFlag;
}
// preserves the existing channel info in the status byte
// preserves any previously set mFlags value
void SetAnyChannel (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_AnyChannelFlag;
else
mFlags &= ~kAUParameterMIDIMapping_AnyChannelFlag;
}

bool IsAnyNote () const {
return (mFlags & kAUParameterMIDIMapping_AnyNoteFlag) != 0;
}
// preserves the existing key num in the mData1 byte
// preserves any previously set mFlags value
void SetAnyNote (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_AnyNoteFlag;
else
mFlags &= ~kAUParameterMIDIMapping_AnyNoteFlag;
}
bool IsToggle() const { return (mFlags & kAUParameterMIDIMapping_Toggle) != 0; }
void SetToggle (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_Toggle;
else
mFlags &= ~kAUParameterMIDIMapping_Toggle;
}
bool IsBipolar() const { return (mFlags & kAUParameterMIDIMapping_Bipolar) != 0; }
// inUseOnValue is valid ONLY if inFlag is true
void SetBipolar (bool inFlag, bool inUseOnValue = false)
{
if (inFlag) {
mFlags |= kAUParameterMIDIMapping_Bipolar;
if (inUseOnValue)
mFlags |= kAUParameterMIDIMapping_Bipolar_On;
else
mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
} else {
mFlags &= ~kAUParameterMIDIMapping_Bipolar;
mFlags &= ~kAUParameterMIDIMapping_Bipolar_On;
}
}
bool IsBipolar_OnValue () const { return (mFlags & kAUParameterMIDIMapping_Bipolar_On) != 0; }

bool IsSubRange () const { return (mFlags & kAUParameterMIDIMapping_SubRange) != 0; }
void SetSubRange (Float32 inStartValue, Float32 inStopValue)
{
mFlags |= kAUParameterMIDIMapping_SubRange;
mSubRangeMin = inStartValue;
mSubRangeMax = inStopValue;
}
void SetParamRange(Float32 minValue, Float32 maxValue)
{
mMinValue = minValue;
mMaxValue = maxValue;
}
// this will retain the subrange values previously set.
void SetSubRange (bool inFlag)
{
if (inFlag)
mFlags |= kAUParameterMIDIMapping_SubRange;
else
mFlags &= ~kAUParameterMIDIMapping_SubRange;
}
bool IsAnyValue() const{return !IsBipolar();}
bool IsOnValue() const{return IsBipolar_OnValue();}
bool IsOffValue() const{return IsBipolar();}
bool IsNoteOff () const { return ((mStatus & 0xF0) == 0x80); }
bool IsNoteOn () const { return ((mStatus & 0xF0) == 0x90); }
bool IsKeyPressure () const { return ((mStatus & 0xF0) == 0xA0); }
bool IsKeyEvent () const { return (mStatus > 0x7F) && (mStatus < 0xB0); }
bool IsPatchChange () const { return ((mStatus & 0xF0) == 0xC0); }
bool IsChannelPressure () const { return ((mStatus & 0xF0) == 0xD0); }
bool IsPitchBend () const { return ((mStatus & 0xF0) == 0xE0); }
bool IsControlChange () const { return ((mStatus & 0xF0) == 0xB0); }
void SetControllerOnValue(){SetBipolar(true,true);}
void SetControllerOffValue(){SetBipolar(true,false);}
void SetControllerAnyValue(){SetBipolar(false,false);}
// All of these Set calls will reset the mFlags field based on the
// anyChannel param value
void SetNoteOff (UInt8 key, SInt8 channel, bool anyChannel = false)
{
mStatus = 0x80 | (channel & 0xF);
mData1 = key;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}

void SetNoteOn (UInt8 key, SInt8 channel, bool anyChannel = false)
{
mStatus = 0x90 | (channel & 0xF);
mData1 = key;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}

void SetPolyKey (UInt8 key, SInt8 channel, bool anyChannel = false)
{
mStatus = 0xA0 | (channel & 0xF);
mData1 = key;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}

void SetControlChange (UInt8 controllerID, SInt8 channel, bool anyChannel = false)
{
mStatus = 0xB0 | (channel & 0xF);
mData1 = controllerID;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
void SetPatchChange (UInt8 patchChange, SInt8 channel, bool anyChannel = false)
{
mStatus = 0xC0 | (channel & 0xF);
mData1 = patchChange;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}

void SetChannelPressure (SInt8 channel, bool anyChannel = false)
{
mStatus = 0xD0 | (channel & 0xF);
mData1 = 0;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}

void SetPitchBend (SInt8 channel, bool anyChannel = false)
{
mStatus = 0xE0 | (channel & 0xF);
mData1 = 0;
mFlags = (anyChannel ? kAUParameterMIDIMapping_AnyChannelFlag : 0);
}
Float32 ParamValueFromMIDILinear (Float32 inLinearValue) const
{
Float32 low, high;
if (IsSubRange()){
low = mSubRangeMin;
high = mSubRangeMax;
}
else {
low = mMinValue;
high = mMaxValue;
}
// WE ARE ASSUMING YOU HAVE SET THIS UP PROPERLY!!!!! (or this will crash cause it will be NULL)
return mTransType->fromlinear((inLinearValue * (high - low)) + low);
}

// The CALLER of this method must ensure that the status byte's MIDI Command (ignoring the channel) matches!!!
bool MIDI_Matches (UInt8 inChannel, UInt8 inData1, UInt8 inData2, Float32 &outLinear) const;
void Print () const;
void Save (CFPropertyListRef &outData) const;
void Restore (CFDictionaryRef inData);
static void SaveAsMapPList (AudioUnit inUnit,
const AUParameterMIDIMapping * inMappings,
UInt32 inNumMappings,
CFPropertyListRef &outData,
CFStringRef inName = NULL);

// inNumMappings describes how much memory is allocated in outMappings
static void RestoreFromMapPList (const CFDictionaryRef inData,
AUParameterMIDIMapping * outMappings,
UInt32 inNumMappings);
static UInt32 NumberOfMaps (const CFDictionaryRef inData);
};


// these sorting operations sort for run-time efficiency based on the MIDI messages
inline bool operator== (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
{
// ignore channel first
return (((a.mStatus & 0xF0) == (b.mStatus & 0xF0))
&& (a.mData1 == b.mData1)
&& ((a.mStatus & 0xF) == (b.mStatus & 0xf)) // now compare the channel
&& (a.mParameterID == b.mParameterID)
&& (a.mElement == b.mElement)
&& (a.mScope == b.mScope));
// reserved field comparisons - ignored until/if they are used
}

inline bool operator< (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
{
if ((a.mStatus & 0xF0) != (b.mStatus & 0xF0))
return ((a.mStatus & 0xF0) < (b.mStatus & 0xF0));
if (a.mData1 != b.mData1)
return (a.mData1 < b.mData1);

if ((a.mStatus & 0xF) != (b.mStatus & 0xf)) // now compare the channel
return ((a.mStatus & 0xF) < (b.mStatus & 0xf));

// reserved field comparisons - ignored until/if they are used
// we're sorting this by MIDI, so we don't really care how the rest is sorted
return ((a.mParameterID < b.mParameterID)
&& (a.mElement < b.mElement)
&& (a.mScope < b.mScope));
}



class CompareMIDIMap {
int compare (const CAAUMIDIMap &a, const CAAUMIDIMap &b)
{
if ((a.mStatus & 0xF0) < (b.mStatus & 0xF0))
return -1;
if ((a.mStatus & 0xF0) > (b.mStatus & 0xF0))
return 1;

// note event
if (a.mStatus < 0xB0 || a.mStatus >= 0xD0)
return 0;
if (a.mData1 > b.mData1) return 1;
if (a.mData1 < b.mData1) return -1;
return 0;
}
public:
bool operator() (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
return compare (a, b) < 0;
}
bool Finish (const CAAUMIDIMap &a, const CAAUMIDIMap &b) {
return compare (a, b) != 0;
}
};


/*
usage: To find potential mapped events for a given status byte, where mMMapEvents is a sorted vec
CompareMIDIMap comparObj;
sortVecIter lower_iter = std::lower_bound(mMMapEvents.begin(), mMMapEvents.end(), inStatusByte, compareObj);
for (;lower_iter < mMMapEvents.end(); ++lower_iter) {
// then, see if we go out of the status byte range, using the Finish method
if (compareObj.Finish(map, tempMap)) // tempMap is a CAAUMIDIMap object with the status/dataByte 1 set
break;
// ...
}
in the for loop you call the MIDI_Matches call, to see if the MIDI event matches a given AUMIDIParam mapping
special note: you HAVE to transform note on (with vel zero) events to the note off status byte
*/

#endif

+ 227
- 0
distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.cpp View File

@@ -0,0 +1,227 @@
/* 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 "CAAUMIDIMapManager.h"
#include <AudioToolbox/AudioUnitUtilities.h>

CAAUMIDIMapManager::CAAUMIDIMapManager()
{
hotMapping = false;
}

static void FillInMap (CAAUMIDIMap &map, AUBase &That)
{
AudioUnitParameterInfo info;
That.GetParameterInfo (map.mScope, map.mParameterID, info);
if (map.IsSubRange()) {
map.mMinValue = map.mSubRangeMin;
map.mMaxValue = map.mSubRangeMax;
} else {
map.mMinValue = info.minValue;
map.mMaxValue = info.maxValue;
}
map.mTransType = CAAUMIDIMap::GetTransformer(info.flags);
}

OSStatus CAAUMIDIMapManager::SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That)
{
for (unsigned int i = 0; i < inNumMaps; ++i)
{
CAAUMIDIMap map(maps[i]);

FillInMap (map, That);
int idx = FindParameterIndex (maps[i]);
if (idx > -1)
mParameterMaps.erase(mParameterMaps.begin() + idx);

// least disruptive place to put this is at the end
mParameterMaps.push_back(map);
}
std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap());
return noErr;
}

void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap )
{
outMap = mHotMap;
}

void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange)
{
if (hotMapping) {
hotMapping = false;
}

outMapDidChange = false;
for (unsigned int i = 0; i < inNumMaps; ++i) {
int idx = FindParameterIndex (maps[i]);
if (idx > -1) {
//mParameterMaps[idx].Print();
mParameterMaps.erase(mParameterMaps.begin() + idx);
outMapDidChange = true;
}
}
}

void CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That)
{
mParameterMaps.clear();

for (unsigned int i = 0; i < inNumMaps; ++i) {
CAAUMIDIMap mapping(inMappings[i]);

FillInMap (mapping, That);
mParameterMaps.push_back (mapping);
}

std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap());
}

bool CAAUMIDIMapManager::HandleHotMapping(UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
AUBase &That)
{ //used to set the hot map info

if (inStatus == 0xf0) return false;
if (!hotMapping) return false;
hotMapping = false;

mHotMap.mStatus = inStatus | inChannel;
mHotMap.mData1 = inData1;
SortedInsertToParamaterMaps (&mHotMap, 1, That);
return true;
}

#if DEBUG

void CAAUMIDIMapManager::Print()
{
for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
CAAUMIDIMap* listmap = &(*i);
listmap->Print();
}
}

#endif // DEBUG

void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps)
{
int i = 0;
for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) {
AUParameterMIDIMapping &listmap = (*iter);
maps[i] = listmap;
}
}

int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap)
{
//used to get back hot mapping and one at a time maps, for ui
int idx = 0;
for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
CAAUMIDIMap & listmap = (*i);
if ( (listmap.mParameterID == inMap.mParameterID) &&
(listmap.mScope == inMap.mScope) &&
(listmap.mElement == inMap.mElement) )
{
return idx;
}
idx++;
}
return -1;
}

bool CAAUMIDIMapManager::FindParameterMapEventMatch( UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
UInt8 inData2,
UInt32 inBufferOffset,
AUBase& inAUBase)
{
bool ret_value = false;

if (inStatus == 0x90 && !inData2)
inStatus = 0x80 | inChannel;
//used to test for midi matches once map is made
CAAUMIDIMap tempMap;
tempMap.mStatus = inStatus | inChannel;
tempMap.mData1 = inData1;
CompareMIDIMap compareObj;

AudioUnitEvent event;
event.mEventType = kAudioUnitEvent_ParameterValueChange;
event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance();
ParameterMaps::iterator lower_iter =
std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj);
while (lower_iter < mParameterMaps.end())
{
CAAUMIDIMap & map = (*lower_iter);
if (compareObj.Finish(map, tempMap))
break;
Float32 value;
if (map.MIDI_Matches(inChannel, inData1, inData2, value))
{
inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement,
map.ParamValueFromMIDILinear(value), inBufferOffset);

event.mArgument.mParameter.mParameterID = map.mParameterID;
event.mArgument.mParameter.mScope = map.mScope;
event.mArgument.mParameter.mElement = map.mElement;
AUEventListenerNotify(NULL, NULL, &event);
ret_value = true;
}
++lower_iter;
}
return ret_value;
}

+ 96
- 0
distrho/src/CoreAudio106/PublicUtility/CAAUMIDIMapManager.h View File

@@ -0,0 +1,96 @@
/* 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.
*/
#ifndef __CAAUMIDIMapManager_h_
#define __CAAUMIDIMapManager_h_

#include <AUBase.h>
#include <CAAUMIDIMap.h>
#include <vector>
#include <AudioToolbox/AudioUnitUtilities.h>

class CAAUMIDIMapManager {
protected:
typedef std::vector<CAAUMIDIMap> ParameterMaps;
ParameterMaps mParameterMaps;
bool hotMapping;
AUParameterMIDIMapping mHotMap;
public:
CAAUMIDIMapManager();
UInt32 NumMaps(){return mParameterMaps.size();}
void GetMaps(AUParameterMIDIMapping* maps);
int FindParameterIndex(AUParameterMIDIMapping &map);
void GetHotParameterMap(AUParameterMIDIMapping &outMap);
void SortedRemoveFromParameterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange);
OSStatus SortedInsertToParamaterMaps (AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That);
void ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That);
bool IsHotMapping(){return hotMapping;}
void SetHotMapping (AUParameterMIDIMapping &inMap){hotMapping = true; mHotMap = inMap; }
bool HandleHotMapping( UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
AUBase &That);
bool FindParameterMapEventMatch(UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
UInt8 inData2,
UInt32 inBufferOffset,
AUBase& inAUBase);
#if DEBUG
void Print();
#endif
};


#endif

+ 394
- 0
distrho/src/CoreAudio106/PublicUtility/CAAUParameter.cpp View File

@@ -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

+ 185
- 0
distrho/src/CoreAudio106/PublicUtility/CAAUParameter.h View File

@@ -0,0 +1,185 @@
/* 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.
*/
#ifndef __CAAUParameter_h__
#define __CAAUParameter_h__

#include <AudioToolbox/AudioUnitUtilities.h>

// ____________________________________________________________________________
// CAAUParameter
// complete parameter specification
/*! @class CAAUParameter */
class CAAUParameter : public AudioUnitParameter {
public:
/*! @ctor CAAUParameter.0 */
CAAUParameter();
/*! @ctor CAAUParameter.1 */
CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
/*! @ctor CAAUParameter.2 */
CAAUParameter(AudioUnitParameter &inParam);
/*! @ctor CAAUParameter.3 */
CAAUParameter(const CAAUParameter &a);
/*! @dtor ~CAAUParameter */
~CAAUParameter();
/*! @method operator <@ */
bool operator < (const CAAUParameter &a) const
{
return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0;
}

/*! @method operator ==@ */
bool operator == (const CAAUParameter &a) const
{
return !memcmp(this, &a, sizeof(AudioUnitParameter));
}
/*! @method operator =@ */
CAAUParameter & operator = (const CAAUParameter &a);
/*! @method GetValue */
Float32 GetValue() const;
/*! @method SetValue */
void SetValue( AUParameterListenerRef inListener,
void * inObject,
Float32 inValue) const;
/*! @method GetName */
CFStringRef GetName() const { return mParamName; }
// borrowed reference!

/*! @method GetStringFromValueCopy */
CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
// returns a copy of the name of the current parameter value
// or null if there is no name associated
// caller must release
/*! @method ValuesHaveStrings */
bool ValuesHaveStrings () const
{
return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
}
/*! @method GetValueFromString */
Float32 GetValueFromString (CFStringRef str) const;
// caller must release

/*! @method ParamInfo */
const AudioUnitParameterInfo &
ParamInfo() const { return mParamInfo; }

/*! @method GetParamTag */
CFStringRef GetParamTag() const { return mParamTag; }
// this may return null! -
// in which case there is no descriptive tag for the parameter

/*! @method GetParamName */
CFStringRef GetParamName (int inIndex) const
// this can return null if there is no name for the parameter
{
return (mNamedParams && inIndex < mNumIndexedParams)
? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
: 0;
}
/*! @method GetNumIndexedParams */
int GetNumIndexedParams () const { return mNumIndexedParams; }
/*! @method IsIndexedParam */
bool IsIndexedParam () const { return mNumIndexedParams != 0; }
/*! @method HasNamedParams */
bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
/*! @method GetClumpID */
bool GetClumpID (UInt32 &outClumpID) const
{
if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) {
outClumpID = mParamInfo.clumpID;
return true;
}
return false;
}
/*! @method HasDisplayTransformation */
bool HasDisplayTransformation () const
{
return GetAudioUnitParameterDisplayType (mParamInfo.flags);
}

/*! @method IsExpert */
bool IsExpert () const
{
return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode;
}
#if DEBUG
void Print () const;
#endif
// these methods are defined in CAPersistence.cpp
// they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
// however, this is sufficient to be able to save/restore a CAAUParameter object
void Save (CFPropertyListRef &outData) const;
static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam);

protected:
// cached parameter info
/*! @var mParamInfo */
AudioUnitParameterInfo mParamInfo;
/*! @var mParamName */
CFStringRef mParamName;
/*! @var mParamTag */
CFStringRef mParamTag;
/*! @var mNumIndexedParams */
short mNumIndexedParams;
/*! @var mNamedParams */
CFArrayRef mNamedParams;
private:
void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);

};



#endif // __CAAUParameter_h__

+ 288
- 0
distrho/src/CoreAudio106/PublicUtility/CAAtomic.h View File

@@ -0,0 +1,288 @@
/* 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.
*/
/*
This file implements all Atomic operations using Interlocked functions specified in
Winbase.h
NOTE: According to Microsoft documentation, all Interlocked functions generates a
full barrier.
On Windows:
As the Interlocked functions returns the Old value, Extra checks and operations
are made after the atomic operation to return value consistent with OSX counterparts.
*/
#ifndef __CAAtomic_h__
#define __CAAtomic_h__

#if TARGET_OS_WIN32
#include <windows.h>
#include <intrin.h>
#else
#include <CoreFoundation/CFBase.h>
#include <libkern/OSAtomic.h>
#endif

inline void CAMemoryBarrier()
{
#if TARGET_OS_WIN32
MemoryBarrier();
#else
OSMemoryBarrier();
#endif
}

inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt);
// InterlockedExchangeAdd returns the original value which differs from OSX version.
// At this point the addition would have occured and hence returning the new value
// to keep it sync with OSX.
return lRetVal + theAmt;
#else
return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue);
#endif
}

inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue)
{
#if TARGET_OS_WIN32
// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
// function instead.
long j = _InterlockedOr((volatile long*)theValue, theMask);
// _InterlockedOr returns the original value which differs from OSX version.
// Returning the new value similar to OSX
return (SInt32)(j | theMask);
#else
return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue);
#endif
}

inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue)
{
#if TARGET_OS_WIN32
// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
// function instead.
long j = _InterlockedAnd((volatile long*)theValue, theMask);
// _InterlockedAnd returns the original value which differs from OSX version.
// Returning the new value similar to OSX
return (SInt32)(j & theMask);
#else
return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue);
#endif
}

inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue)
{
#if TARGET_OS_WIN32
// InterlockedCompareExchange returns the old value. But we need to return bool value.
long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue);
// Hence we check if the new value is set and if it is we return true else false.
// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen.
return (oldValue == lRetVal);
#else
return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue);
#endif
}


inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return (SInt32)InterlockedIncrement((volatile long*)theValue);
#else
return OSAtomicIncrement32((volatile int32_t *)theValue);
#endif
}

inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return (SInt32)InterlockedDecrement((volatile long*)theValue);
#else
return OSAtomicDecrement32((volatile int32_t *)theValue);
#endif
}

inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return CAAtomicIncrement32(theValue);
#else
return OSAtomicIncrement32Barrier((volatile int32_t *)theValue);
#endif
}

inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return CAAtomicDecrement32(theValue);
#else
return OSAtomicDecrement32Barrier((volatile int32_t *)theValue);
#endif
}

inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress);
#endif
}

inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress);
#endif
}

inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
#endif
}

// int32_t flavors -- for C++ only since we can't overload in C
// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
// SInt32 is defined as signed long so this would work there.
// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included.
#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__
inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue)
{
return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue);
}

inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue)
{
return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue);
}

inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue)
{
return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue);
}

inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue)
{
return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue);
}

inline int32_t CAAtomicIncrement32(volatile int32_t* theValue)
{
return CAAtomicIncrement32((volatile SInt32 *)theValue);
}

inline int32_t CAAtomicDecrement32(volatile int32_t* theValue)
{
return CAAtomicDecrement32((volatile SInt32 *)theValue);
}

inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue)
{
return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue);
}

inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
{
return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue);
}
#endif // __cplusplus && !__LP64__

#if __LP64__
inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
{
return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue );
}
#endif

/* Spinlocks. These use memory barriers as required to synchronize access to shared
* memory protected by the lock. The lock operation spins, but employs various strategies
* to back off if the lock is held, making it immune to most priority-inversion livelocks.
* The try operation immediately returns false if the lock was held, true if it took the
* lock. The convention is that unlocked is zero, locked is nonzero.
*/
#define CA_SPINLOCK_INIT 0

typedef int32_t CASpinLock;

bool CASpinLockTry( volatile CASpinLock *__lock );
void CASpinLockLock( volatile CASpinLock *__lock );
void CASpinLockUnlock( volatile CASpinLock *__lock );

inline void CASpinLockLock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
OSSpinLockLock(__lock);
#else
while (CAAtomicTestAndSetBarrier(0, (void*)__lock))
usleep(1000); // ???
#endif
}

inline void CASpinLockUnlock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
OSSpinLockUnlock(__lock);
#else
CAAtomicTestAndClearBarrier(0, (void*)__lock);
#endif
}

inline bool CASpinLockTry( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
return OSSpinLockTry(__lock);
#else
return (CAAtomicTestAndSetBarrier(0, (void*)__lock) == 0);
#endif
}


#endif // __CAAtomic_h__

+ 209
- 0
distrho/src/CoreAudio106/PublicUtility/CAAtomicStack.h View File

@@ -0,0 +1,209 @@
/* 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.
*/
#ifndef __TStack_h__
#define __TStack_h__

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <libkern/OSAtomic.h>
#else
// #include <DriverSynchronization.h>
#include <CAAtomic.h>
#endif

#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
#include <CoreServices/CoreServices.h>
#endif

// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
// class T must implement set_next() and get_next()
template <class T>
class TAtomicStack {
public:
TAtomicStack() : mHead(NULL) { }
// non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
void push_NA(T *item)
{
item->set_next(mHead);
mHead = item;
}
T * pop_NA()
{
T *result = mHead;
if (result)
mHead = result->get_next();
return result;
}
bool empty() { return mHead == NULL; }
T * head() { return mHead; }
// atomic routines
void push_atomic(T *item)
{
T *head;
do {
head = mHead;
item->set_next(head);
} while (!compare_and_swap(head, item, &mHead));
}
void push_multiple_atomic(T *item)
// pushes entire linked list headed by item
{
T *head, *p = item, *tail;
// find the last one -- when done, it will be linked to head
do {
tail = p;
p = p->get_next();
} while (p);
do {
head = mHead;
tail->set_next(head);
} while (!compare_and_swap(head, item, &mHead));
}
T * pop_atomic_single_reader()
// this may only be used when only one thread may potentially pop from the stack.
// if multiple threads may pop, this suffers from the ABA problem.
// <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
{
T *result;
do {
if ((result = mHead) == NULL)
break;
} while (!compare_and_swap(result, result->get_next(), &mHead));
return result;
}
T * pop_atomic()
// This is inefficient for large linked lists.
// prefer pop_all() to a series of calls to pop_atomic.
// push_multiple_atomic has to traverse the entire list.
{
T *result = pop_all();
if (result) {
T *next = result->get_next();
if (next)
// push all the remaining items back onto the stack
push_multiple_atomic(next);
}
return result;
}
T * pop_all()
{
T *result;
do {
if ((result = mHead) == NULL)
break;
} while (!compare_and_swap(result, NULL, &mHead));
return result;
}
T* pop_all_reversed()
{
TAtomicStack<T> reversed;
T *p = pop_all(), *next;
while (p != NULL) {
next = p->get_next();
reversed.push_NA(p);
p = next;
}
return reversed.mHead;
}
static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
{
#if TARGET_OS_MAC
#if __LP64__
return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
#else
return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
#endif
#else
//return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
#endif
}
protected:
T * mHead;
};

#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
#include <libkern/OSAtomic.h>

class CAAtomicStack {
public:
CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) { /*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/ mHead.opaque1 = 0; mHead.opaque2 = 0;
}
// a subset of the above
void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
void push_NA(void *p) { push_atomic(p); }

void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
void * pop_atomic_single_reader() { return pop_atomic(); }
void * pop_NA() { return pop_atomic(); }
private:
OSQueueHead mHead;
size_t mNextPtrOffset;
};

// syntactic sugar
template <class T>
class TAtomicStack2 : public CAAtomicStack {
public:
TAtomicStack2(size_t nextPtrOffset) : CAAtomicStack(nextPtrOffset) { }
T * pop_atomic() { return (T *)CAAtomicStack::pop_atomic(); }
T * pop_atomic_single_reader() { return pop_atomic(); }
T * pop_NA() { return pop_atomic(); }
};

#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32

#endif // __TStack_h__

+ 225
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.cpp View File

@@ -0,0 +1,225 @@
/* 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
//=============================================================================

#include "CAAudioBufferList.h"
#include "CADebugMacros.h"
#include "CALogMacros.h"
#include <stdlib.h>
#include <string.h>

//=============================================================================
// CAAudioBufferList
//=============================================================================

AudioBufferList* CAAudioBufferList::Create(UInt32 inNumberBuffers)
{
UInt32 theSize = CalculateByteSize(inNumberBuffers);
AudioBufferList* theAnswer = static_cast<AudioBufferList*>(calloc(1, theSize));
if(theAnswer != NULL)
{
theAnswer->mNumberBuffers = inNumberBuffers;
}
return theAnswer;
}

void CAAudioBufferList::Destroy(AudioBufferList* inBufferList)
{
free(inBufferList);
}

UInt32 CAAudioBufferList::CalculateByteSize(UInt32 inNumberBuffers)
{
UInt32 theSize = SizeOf32(AudioBufferList) - SizeOf32(AudioBuffer);
theSize += inNumberBuffers * SizeOf32(AudioBuffer);
return theSize;
}

UInt32 CAAudioBufferList::GetTotalNumberChannels(const AudioBufferList& inBufferList)
{
UInt32 theAnswer = 0;
for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
{
theAnswer += inBufferList.mBuffers[theIndex].mNumberChannels;
}
return theAnswer;
}

bool CAAudioBufferList::GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel)
{
bool theAnswer = false;
UInt32 theIndex = 0;
while((theIndex < inBufferList.mNumberBuffers) && (inChannel >= inBufferList.mBuffers[theIndex].mNumberChannels))
{
inChannel -= inBufferList.mBuffers[theIndex].mNumberChannels;
++theIndex;
}
if(theIndex < inBufferList.mNumberBuffers)
{
outBufferNumber = theIndex;
outBufferChannel = inChannel;
theAnswer = true;
}
return theAnswer;
}

void CAAudioBufferList::Clear(AudioBufferList& outBufferList)
{
// assumes that "0" is actually the 0 value for this stream format
for(UInt32 theBufferIndex = 0; theBufferIndex < outBufferList.mNumberBuffers; ++theBufferIndex)
{
if(outBufferList.mBuffers[theBufferIndex].mData != NULL)
{
memset(outBufferList.mBuffers[theBufferIndex].mData, 0, outBufferList.mBuffers[theBufferIndex].mDataByteSize);
}
}
}

void CAAudioBufferList::Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel)
{
// This is a brute force copy method that can handle ABL's that have different buffer layouts
// This means that this method is probably not the fastest way to do this for all cases.
// This method also assumes that both the source and destination sample formats are Float32

UInt32 theInputChannel = inStartingSourceChannel;
UInt32 theNumberInputChannels = GetTotalNumberChannels(inSource);
UInt32 theOutputChannel = inStartingDestinationChannel;
UInt32 theNumberOutputChannels = GetTotalNumberChannels(outDestination);
UInt32 theInputBufferIndex = 0;
UInt32 theInputBufferChannel = 0;
UInt32 theOutputBufferIndex = 0;
UInt32 theOutputBufferChannel = 0;
while((theInputChannel < theNumberInputChannels) && (theOutputChannel < theNumberOutputChannels))
{
GetBufferForChannel(inSource, theInputChannel, theInputBufferIndex, theInputBufferChannel);
GetBufferForChannel(inSource, theOutputChannel, theOutputBufferIndex, theOutputBufferChannel);
CopyChannel(inSource.mBuffers[theInputBufferIndex], theInputBufferChannel, outDestination.mBuffers[theOutputBufferIndex], theOutputBufferChannel);
++theInputChannel;
++theOutputChannel;
}
}

void CAAudioBufferList::CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel)
{
// set up the stuff for the loop
UInt32 theNumberFramesToCopy = outDestination.mDataByteSize / (outDestination.mNumberChannels * SizeOf32(Float32));
const Float32* theSource = static_cast<const Float32*>(inSource.mData);
Float32* theDestination = static_cast<Float32*>(outDestination.mData);
// loop through the data and copy the samples
while(theNumberFramesToCopy > 0)
{
// copy the data
theDestination[inDestinationChannel] = theSource[inSourceChannel];
// adjust the pointers
--theNumberFramesToCopy;
theSource += inSource.mNumberChannels;
theDestination += outDestination.mNumberChannels;
}
}

void CAAudioBufferList::Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList)
{
// assumes that the buffers are Float32 samples and the listst have the same layout
// this is a lame algorithm, by the way. it could at least be unrolled a couple of times
for(UInt32 theBufferIndex = 0; theBufferIndex < ioSummedBufferList.mNumberBuffers; ++theBufferIndex)
{
Float32* theSourceBuffer = static_cast<Float32*>(inSourceBufferList.mBuffers[theBufferIndex].mData);
Float32* theSummedBuffer = static_cast<Float32*>(ioSummedBufferList.mBuffers[theBufferIndex].mData);
UInt32 theNumberSamplesToMix = ioSummedBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(Float32);
if((theSourceBuffer != NULL) && (theSummedBuffer != NULL) && (theNumberSamplesToMix > 0))
{
while(theNumberSamplesToMix > 0)
{
*theSummedBuffer += *theSourceBuffer;
++theSummedBuffer;
++theSourceBuffer;
--theNumberSamplesToMix;
}
}
}
}

bool CAAudioBufferList::HasData(AudioBufferList& inBufferList)
{
bool hasData = false;
for(UInt32 theBufferIndex = 0; !hasData && (theBufferIndex < inBufferList.mNumberBuffers); ++theBufferIndex)
{
if(inBufferList.mBuffers[theBufferIndex].mData != NULL)
{
UInt32* theBuffer = (UInt32*)inBufferList.mBuffers[theBufferIndex].mData;
UInt32 theNumberSamples = inBufferList.mBuffers[theBufferIndex].mDataByteSize / SizeOf32(UInt32);
for(UInt32 theSampleIndex = 0; !hasData && (theSampleIndex < theNumberSamples); ++theSampleIndex)
{
hasData = theBuffer[theSampleIndex] != 0;
}
}
}
return hasData;
}

#if CoreAudio_Debug
void CAAudioBufferList::PrintToLog(const AudioBufferList& inBufferList)
{
PrintInt(" Number streams: ", inBufferList.mNumberBuffers);
for(UInt32 theIndex = 0; theIndex < inBufferList.mNumberBuffers; ++theIndex)
{
PrintIndexedInt(" Channels in stream", theIndex + 1, inBufferList.mBuffers[theIndex].mNumberChannels);
PrintIndexedInt(" Buffer size of stream", theIndex + 1, inBufferList.mBuffers[theIndex].mDataByteSize);
}
}
#endif

AudioBufferList CAAudioBufferList::sEmptyBufferList = { 0, { { 0, 0, NULL } } };

+ 93
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioBufferList.h View File

@@ -0,0 +1,93 @@
/* 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.
*/
#if !defined(__CAAudioBufferList_h__)
#define __CAAudioBufferList_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif

//=============================================================================
// Types
//=============================================================================

typedef AudioBufferList* AudioBufferListPtr;

//=============================================================================
// CAAudioBufferList
//=============================================================================

struct CAAudioBufferList
{

// Construction/Destruction
public:
static AudioBufferList* Create(UInt32 inNumberBuffers);
static void Destroy(AudioBufferList* inBufferList);
static UInt32 CalculateByteSize(UInt32 inNumberBuffers);

// Operations
public:
static UInt32 GetTotalNumberChannels(const AudioBufferList& inBufferList);
static bool GetBufferForChannel(const AudioBufferList& inBufferList, UInt32 inChannel, UInt32& outBufferNumber, UInt32& outBufferChannel);
static void Clear(AudioBufferList& outBufferList);
static void Copy(const AudioBufferList& inSource, UInt32 inStartingSourceChannel, AudioBufferList& outDestination, UInt32 inStartingDestinationChannel);
static void CopyChannel(const AudioBuffer& inSource, UInt32 inSourceChannel, AudioBuffer& outDestination, UInt32 inDestinationChannel);
static void Sum(const AudioBufferList& inSourceBufferList, AudioBufferList& ioSummedBufferList);
static bool HasData(AudioBufferList& inBufferList);
#if CoreAudio_Debug
static void PrintToLog(const AudioBufferList& inBufferList);
#endif

// Constants
public:
static AudioBufferList sEmptyBufferList;

};

#endif

+ 142
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.cpp View File

@@ -0,0 +1,142 @@
/* 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 "CAAudioChannelLayout.h"
#include "CAAutoDisposer.h"
#include <stdlib.h>
#include <string.h>

//=============================================================================
// CAAudioChannelLayout
//=============================================================================

AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
{
UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize));
if(theAnswer != NULL)
{
SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
}
return theAnswer;
}

void CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout)
{
free(inChannelLayout);
}

void CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions)
{
outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
outChannelLayout.mChannelBitmap = 0;
outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions;
for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex)
{
outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown;
outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0;
}
}

bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
{
// compare based on the number of channel descriptions present
// (this may be too strict a comparison if all you care about are matching layout tags)
UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
if (theSize1 != theSize2)
return false;
return !memcmp (&x, &y, theSize1);
}

// counting the one bits in a word
inline UInt32 CountOnes(UInt32 x)
{
// secret magic algorithm for counting bits in a word.
UInt32 t;
x = x - ((x >> 1) & 0x55555555);
t = ((x >> 2) & 0x33333333);
x = (x & 0x33333333) + t;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x << 8);
x = x + (x << 16);
return x >> 24;
}

UInt32 CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
{
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
return inLayout.mNumberChannelDescriptions;
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
return CountOnes (inLayout.mChannelBitmap);

return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
}

void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout)
{
if (layout == NULL)
{
fprintf (file, "\tNULL layout\n");
return;
}
fprintf (file, "\tTag=0x%X, ", (int)layout->mChannelLayoutTag);
if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
fprintf (file, "Using Bitmap:0x%X\n", (int)layout->mChannelBitmap);
else {
fprintf (file, "Num Chan Descs=%d\n", (int)layout->mNumberChannelDescriptions);
const AudioChannelDescription *desc = layout->mChannelDescriptions;
for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) {
fprintf (file, "\t\tLabel=%d, Flags=0x%X, ", (int)desc->mChannelLabel, (int)desc->mChannelFlags);
fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]);
}
}
}

+ 191
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayout.h View File

@@ -0,0 +1,191 @@
/* 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.
*/
#if !defined(__CAAudioChannelLayout_h__)
#define __CAAudioChannelLayout_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#else
#include <CoreAudioTypes.h>
#include <CoreFoundation.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "CADebugMacros.h"
#include "CAAutoDisposer.h"

#if !HAL_Build
#include "CAReferenceCounted.h"
#endif

//=============================================================================
// CAAudioChannelLayout
//=============================================================================

bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);

extern "C" void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout);

class CAAudioChannelLayout
{
// static Construction/Destruction
public:
static AudioChannelLayout* Create(UInt32 inNumberChannelDescriptions);
static void Destroy(AudioChannelLayout* inChannelLayout);
static UInt32 CalculateByteSize(UInt32 inNumberChannelDescriptions) {
return OffsetOf32(AudioChannelLayout, mChannelDescriptions) + inNumberChannelDescriptions * SizeOf32(AudioChannelDescription);
}
static void SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
static UInt32 NumberChannels(const AudioChannelLayout& inLayout);
#if !HAL_Build
// object methods
public:
CAAudioChannelLayout ();

CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
// if inChooseSurround is false, then symmetrical speaker arrangements
// are chosen in place of surround layouts if there is a choice
// This call chooses layouts based on the expected defaults in
// AudioUnit usage
CAAudioChannelLayout (AudioChannelLayoutTag inTag);
CAAudioChannelLayout (const CAAudioChannelLayout &c);
CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
~CAAudioChannelLayout();
CAAudioChannelLayout& operator= (const AudioChannelLayout* inChannelLayout);
CAAudioChannelLayout& operator= (const CAAudioChannelLayout& c);
bool operator== (const CAAudioChannelLayout &c) const;

void SetWithTag(AudioChannelLayoutTag inTag);

bool IsValid() const { return NumberChannels() > 0; }
UInt32 Size() const { return mLayout ? mLayout->Size() : 0; }
UInt32 NumberChannels() const { return mLayout ? mLayout->NumberChannels() : 0; }
AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; }
const AudioChannelLayout& Layout() const { return mLayout->Layout(); }
operator const AudioChannelLayout *() const { return &Layout(); }
void Print () const { Print (stdout); }
void Print (FILE* file) const;

OSStatus Save (CFPropertyListRef *outData) const;
OSStatus Restore (CFPropertyListRef &inData);
private:
class RefCountedLayout : public CAReferenceCounted {
void * operator new(size_t size, size_t aclSize)
{
return CA_malloc(sizeof(RefCountedLayout) - sizeof(AudioChannelLayout) + aclSize);
}
void operator delete(void *mem)
{
free(mem);
}
RefCountedLayout(UInt32 inDataSize) :
mByteSize(inDataSize)
{
memset(&mACL, 0, inDataSize);
}
public:
static RefCountedLayout *CreateWithNumberChannelDescriptions(unsigned nChannels) {
size_t size = CAAudioChannelLayout::CalculateByteSize(nChannels);
return new(size) RefCountedLayout(size);
}

static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
RefCountedLayout *acl = new(size) RefCountedLayout(size);
memcpy(&acl->mACL, layout, size);
return acl;
}
static RefCountedLayout *CreateWithLayoutTag(AudioChannelLayoutTag layoutTag) {
RefCountedLayout *acl = CreateWithNumberChannelDescriptions(0);
acl->mACL.mChannelLayoutTag = layoutTag;
return acl;
}
const AudioChannelLayout & Layout() const { return mACL; }
UInt32 Size () const { return mByteSize; }
UInt32 NumberChannels() { return CAAudioChannelLayout::NumberChannels(Layout()); }
private:
const UInt32 mByteSize;
AudioChannelLayout mACL;
// * * * mACL is variable length and thus must be last * * *
// only the constructors can change the actual state of the layout
friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
AudioChannelLayout * GetLayout() { return &mACL; }
private:
// prohibited methods: private and unimplemented.
RefCountedLayout();
RefCountedLayout(const RefCountedLayout& c);
RefCountedLayout& operator=(const RefCountedLayout& c);
};
RefCountedLayout *mLayout;
#endif // HAL_Build

};

#endif

+ 193
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioChannelLayoutObject.cpp View File

@@ -0,0 +1,193 @@
/* 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 "CAAudioChannelLayout.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioToolbox/AudioFormat.h>
#else
#include <AudioFormat.h>
#endif

CAAudioChannelLayout::CAAudioChannelLayout ()
{
mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
}

//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
{
// this chooses default layouts based on the number of channels...
AudioChannelLayoutTag tag;
switch (inNumberChannels)
{
default:
// here we have a "broken" layout, in the sense that we haven't any idea how to lay this out
mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(inNumberChannels);
SetAllToUnknown(*mLayout->GetLayout(), inNumberChannels);
return; // don't fall into the tag case
case 1:
tag = kAudioChannelLayoutTag_Mono;
break;
case 2:
tag = inChooseSurround ? kAudioChannelLayoutTag_Binaural : kAudioChannelLayoutTag_Stereo;
break;
case 4:
tag = inChooseSurround ? kAudioChannelLayoutTag_Ambisonic_B_Format : kAudioChannelLayoutTag_AudioUnit_4;
break;
case 5:
tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_5_0 : kAudioChannelLayoutTag_AudioUnit_5;
break;
case 6:
tag = inChooseSurround ? kAudioChannelLayoutTag_AudioUnit_6_0 : kAudioChannelLayoutTag_AudioUnit_6;
break;
case 7:
tag = kAudioChannelLayoutTag_AudioUnit_7_0;
break;
case 8:
tag = kAudioChannelLayoutTag_AudioUnit_8;
break;
}
mLayout = RefCountedLayout::CreateWithLayoutTag(tag);
}

//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (AudioChannelLayoutTag inLayoutTag)
: mLayout(NULL)
{
SetWithTag(inLayoutTag);
}

//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (const CAAudioChannelLayout &c)
: mLayout(NULL)
{
*this = c;
}


//=============================================================================
// CAAudioChannelLayout::AudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout)
: mLayout(NULL)
{
*this = inChannelLayout;
}

//=============================================================================
// CAAudioChannelLayout::~CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::~CAAudioChannelLayout ()
{
if (mLayout) {
mLayout->release();
mLayout = NULL;
}
}

//=============================================================================
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout& CAAudioChannelLayout::operator= (const CAAudioChannelLayout &c)
{
if (mLayout != c.mLayout) {
if (mLayout)
mLayout->release();
if ((mLayout = c.mLayout) != NULL)
mLayout->retain();
}
return *this;
}

CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout)
{
if (mLayout && &mLayout->Layout() == inChannelLayout)
return *this;
if (mLayout)
mLayout->release();

if (inChannelLayout == NULL)
{
mLayout = RefCountedLayout::CreateWithNumberChannelDescriptions(0);
}
else
{
mLayout = RefCountedLayout::CreateWithLayout(inChannelLayout);
}
return *this;
}

void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag)
{
if (mLayout)
mLayout->release();
mLayout = RefCountedLayout::CreateWithLayoutTag(inTag);
}

//=============================================================================
// CAAudioChannelLayout::operator==
//=============================================================================
bool CAAudioChannelLayout::operator== (const CAAudioChannelLayout &c) const
{
if (mLayout == c.mLayout)
return true;
return Layout() == c.Layout();
}

//=============================================================================
// CAAudioChannelLayout::Print
//=============================================================================
void CAAudioChannelLayout::Print (FILE* file) const
{
CAShowAudioChannelLayout (file, &Layout());
}


+ 415
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.cpp View File

@@ -0,0 +1,415 @@
/* 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 "CAAudioFileFormats.h"
#include <algorithm>
#include <ctype.h>

CAAudioFileFormats *CAAudioFileFormats::sInstance = NULL;

CAAudioFileFormats *CAAudioFileFormats::Instance(bool loadDataFormats)
{
if (sInstance == NULL)
sInstance = new CAAudioFileFormats(loadDataFormats);
return sInstance;
}

/*
class CompareFileFormatNames {
public:
bool operator() (const CAAudioFileFormats::FileFormatInfo &a, const CAAudioFileFormats::FileFormatInfo &b)
{
return CFStringCompare(a.mFileTypeName, b.mFileTypeName,
kCFCompareCaseInsensitive | kCFCompareLocalized) == kCFCompareLessThan;
}
};*/

static int CompareFileFormatNames(const void *va, const void *vb)
{
CAAudioFileFormats::FileFormatInfo *a = (CAAudioFileFormats::FileFormatInfo *)va,
*b = (CAAudioFileFormats::FileFormatInfo *)vb;
return CFStringCompare(a->mFileTypeName, b->mFileTypeName,
kCFCompareCaseInsensitive | kCFCompareLocalized);
}

CAAudioFileFormats::CAAudioFileFormats(bool loadDataFormats) :
mNumFileFormats(0), mFileFormats(NULL)
{
OSStatus err;
UInt32 size;
UInt32 *fileTypes = NULL;
// get all file types
err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size);
if (err != noErr) goto bail;
mNumFileFormats = size / sizeof(UInt32);
mFileFormats = new FileFormatInfo[mNumFileFormats];
fileTypes = new UInt32[mNumFileFormats];
err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_WritableTypes, 0, NULL, &size, fileTypes);
if (err != noErr) goto bail;
// get info for each file type
for (int i = 0; i < mNumFileFormats; ++i) {
FileFormatInfo *ffi = &mFileFormats[i];
OSType filetype = fileTypes[i];

ffi->mFileTypeID = filetype;
// file type name
ffi->mFileTypeName = NULL;
size = sizeof(CFStringRef);
err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_FileTypeName, sizeof(UInt32), &filetype, &size, &ffi->mFileTypeName);
if (ffi->mFileTypeName)
CFRetain(ffi->mFileTypeName);
// file extensions
size = sizeof(CFArrayRef);
err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_ExtensionsForType,
sizeof(OSType), &filetype, &size, &ffi->mExtensions);
if (err)
ffi->mExtensions = NULL;
// file data formats
ffi->mNumDataFormats = 0;
ffi->mDataFormats = NULL;
if (loadDataFormats)
ffi->LoadDataFormats();
}

// sort file formats by name
qsort(mFileFormats, mNumFileFormats, sizeof(FileFormatInfo), CompareFileFormatNames);
bail:
delete[] fileTypes;
}

void CAAudioFileFormats::FileFormatInfo::LoadDataFormats()
{
if (mDataFormats != NULL) return;
UInt32 *writableFormats = NULL, *readableFormats = NULL;
int nWritableFormats, nReadableFormats;
// get all writable formats
UInt32 size;
OSStatus err = AudioFormatGetPropertyInfo(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size);
if (err != noErr) goto bail;
nWritableFormats = size / sizeof(UInt32);
writableFormats = new UInt32[nWritableFormats];
err = AudioFormatGetProperty(kAudioFormatProperty_EncodeFormatIDs, 0, NULL, &size, writableFormats);
if (err != noErr) goto bail;
// get all readable formats
err = AudioFormatGetPropertyInfo(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size);
if (err != noErr) goto bail;
nReadableFormats = size / sizeof(UInt32);
readableFormats = new UInt32[nReadableFormats];
err = AudioFormatGetProperty(kAudioFormatProperty_DecodeFormatIDs, 0, NULL, &size, readableFormats);
if (err != noErr) goto bail;
err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableFormatIDs, sizeof(UInt32), &mFileTypeID, &size);
if (err == noErr) {
mNumDataFormats = size / sizeof(OSType);
OSType *formatIDs = new OSType[mNumDataFormats];
err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableFormatIDs,
sizeof(UInt32), &mFileTypeID, &size, formatIDs);
if (err == noErr) {
mDataFormats = new DataFormatInfo[mNumDataFormats];
for (int j = 0; j < mNumDataFormats; ++j) {
int k;
bool anyBigEndian = false, anyLittleEndian = false;
DataFormatInfo *dfi = &mDataFormats[j];
dfi->mFormatID = formatIDs[j];
dfi->mReadable = (dfi->mFormatID == kAudioFormatLinearPCM);
dfi->mWritable = (dfi->mFormatID == kAudioFormatLinearPCM);
for (k = 0; k < nReadableFormats; ++k)
if (readableFormats[k] == dfi->mFormatID) {
dfi->mReadable = true;
break;
}
for (k = 0; k < nWritableFormats; ++k)
if (writableFormats[k] == dfi->mFormatID) {
dfi->mWritable = true;
break;
}
dfi->mNumVariants = 0;
AudioFileTypeAndFormatID tf = { mFileTypeID, dfi->mFormatID };
err = AudioFileGetGlobalInfoSize(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat,
sizeof(AudioFileTypeAndFormatID), &tf, &size);
if (err == noErr) {
dfi->mNumVariants = size / sizeof(AudioStreamBasicDescription);
dfi->mVariants = new AudioStreamBasicDescription[dfi->mNumVariants];
err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat,
sizeof(AudioFileTypeAndFormatID), &tf, &size, dfi->mVariants);
if (err) {
dfi->mNumVariants = 0;
delete[] dfi->mVariants;
dfi->mVariants = NULL;
} else {
for (k = 0; k < dfi->mNumVariants; ++k) {
AudioStreamBasicDescription *desc = &dfi->mVariants[k];
if (desc->mBitsPerChannel > 8) {
if (desc->mFormatFlags & kAudioFormatFlagIsBigEndian)
anyBigEndian = true;
else
anyLittleEndian = true;
}
}
}
}
dfi->mEitherEndianPCM = (anyBigEndian && anyLittleEndian);
}
}
delete[] formatIDs;
}
bail:
delete[] readableFormats;
delete[] writableFormats;
}

// note that the outgoing format will have zero for the sample rate, channels per frame, bytesPerPacket, bytesPerFrame
bool CAAudioFileFormats::InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt)
{
// if the file format only supports one data format
for (int i = 0; i < mNumFileFormats; ++i) {
FileFormatInfo *ffi = &mFileFormats[i];
ffi->LoadDataFormats();
if (ffi->mFileTypeID == filetype && ffi->mNumDataFormats > 0) {
DataFormatInfo *dfi = &ffi->mDataFormats[0];
if (ffi->mNumDataFormats > 1) {
// file can contain multiple data formats. Take PCM if it's there.
for (int j = 0; j < ffi->mNumDataFormats; ++j) {
if (ffi->mDataFormats[j].mFormatID == kAudioFormatLinearPCM) {
dfi = &ffi->mDataFormats[j];
break;
}
}
}
memset(&fmt, 0, sizeof(fmt));
fmt.mFormatID = dfi->mFormatID;
if (dfi->mNumVariants > 0) {
// take the first variant as a default
fmt = dfi->mVariants[0];
if (dfi->mNumVariants > 1 && dfi->mFormatID == kAudioFormatLinearPCM) {
// look for a 16-bit variant as a better default
for (int j = 0; j < dfi->mNumVariants; ++j) {
AudioStreamBasicDescription *desc = &dfi->mVariants[j];
if (desc->mBitsPerChannel == 16) {
fmt = *desc;
break;
}
}
}
}
return true;
}
}
return false;
}

bool CAAudioFileFormats::InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype)
{
bool result = false;
CFRange range = CFStringFind(filename, CFSTR("."), kCFCompareBackwards);
if (range.location == kCFNotFound) return false;
range.location += 1;
range.length = CFStringGetLength(filename) - range.location;
CFStringRef ext = CFStringCreateWithSubstring(NULL, filename, range);
for (int i = 0; i < mNumFileFormats; ++i) {
FileFormatInfo *ffi = &mFileFormats[i];
if (ffi->MatchExtension(ext)) {
filetype = ffi->mFileTypeID;
result = true;
break;
}
}
CFRelease(ext);
return result;
}

bool CAAudioFileFormats::InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype)
{
if (filename == NULL) return false;
CFStringRef cfname = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8);
bool result = InferFileFormatFromFilename(cfname, filetype);
CFRelease(cfname);
return result;
}

bool CAAudioFileFormats::InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt,
AudioFileTypeID &filetype)
{
// if there's exactly one file format that supports this data format
FileFormatInfo *theFileFormat = NULL;
for (int i = 0; i < mNumFileFormats; ++i) {
FileFormatInfo *ffi = &mFileFormats[i];
ffi->LoadDataFormats();
DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats;
for ( ; dfi < dfiend; ++dfi)
if (dfi->mFormatID == fmt.mFormatID) {
if (theFileFormat != NULL)
return false; // ambiguous
theFileFormat = ffi; // got a candidate
}
}
if (theFileFormat == NULL)
return false;
filetype = theFileFormat->mFileTypeID;
return true;
}

bool CAAudioFileFormats::IsKnownDataFormat(OSType dataFormat)
{
for (int i = 0; i < mNumFileFormats; ++i) {
FileFormatInfo *ffi = &mFileFormats[i];
ffi->LoadDataFormats();
DataFormatInfo *dfi = ffi->mDataFormats, *dfiend = dfi + ffi->mNumDataFormats;
for ( ; dfi < dfiend; ++dfi)
if (dfi->mFormatID == dataFormat)
return true;
}
return false;
}

CAAudioFileFormats::FileFormatInfo * CAAudioFileFormats::FindFileFormat(UInt32 formatID)
{
for (int i = 0; i < mNumFileFormats; ++i) {
FileFormatInfo *ffi = &mFileFormats[i];
if (ffi->mFileTypeID == formatID)
return ffi;
}
return NULL;
}

bool CAAudioFileFormats::FileFormatInfo::AnyWritableFormats()
{
LoadDataFormats();
DataFormatInfo *dfi = mDataFormats, *dfiend = dfi + mNumDataFormats;
for ( ; dfi < dfiend; ++dfi)
if (dfi->mWritable)
return true;
return false;
}

char *OSTypeToStr(char *buf, OSType t)
{
char *p = buf;
char str[4], *q = str;
*(UInt32 *)str = CFSwapInt32HostToBig(t);
for (int i = 0; i < 4; ++i) {
if (isprint(*q) && *q != '\\')
*p++ = *q++;
else {
sprintf(p, "\\x%02x", *q++);
p += 4;
}
}
*p = '\0';
return buf;
}

int StrToOSType(const char *str, OSType &t)
{
char buf[4];
const char *p = str;
int x;
for (int i = 0; i < 4; ++i) {
if (*p != '\\') {
if ((buf[i] = *p++) == '\0') {
// special-case for 'aac ': if we only got three characters, assume the last was a space
if (i == 3) {
--p;
buf[i] = ' ';
break;
}
goto fail;
}
} else {
if (*++p != 'x') goto fail;
if (sscanf(++p, "%02X", &x) != 1) goto fail;
buf[i] = x;
p += 2;
}
}
t = CFSwapInt32BigToHost(*(UInt32 *)buf);
return p - str;
fail:
return 0;
}

#if DEBUG

void CAAudioFileFormats::DebugPrint()
{
for (int i = 0; i < mNumFileFormats; ++i)
mFileFormats[i].DebugPrint();
}

void CAAudioFileFormats::FileFormatInfo::DebugPrint()
{
char ftype[20];
char ftypename[64];
CFStringGetCString(mFileTypeName, ftypename, sizeof(ftypename), kCFStringEncodingUTF8);
printf("File type: '%s' = %s\n Extensions:", OSTypeToStr(ftype, mFileTypeID), ftypename);
int i, n = NumberOfExtensions();
for (i = 0; i < n; ++i) {
GetExtension(i, ftype, sizeof(ftype));
printf(" .%s", ftype);
}
LoadDataFormats();
printf("\n Formats:\n");
for (i = 0; i < mNumDataFormats; ++i)
mDataFormats[i].DebugPrint();
}

void CAAudioFileFormats::DataFormatInfo::DebugPrint()
{
char buf[20];
static const char *ny[] = { "not ", "" };
printf(" '%s': %sreadable %swritable\n", OSTypeToStr(buf, mFormatID), ny[mReadable], ny[mWritable]);
for (int i = 0; i < mNumVariants; ++i) {
CAStreamBasicDescription desc(mVariants[i]);
desc.PrintFormat(stdout, " ", "");
//printf(" %d bytes/frame\n", desc.mBytesPerFrame);
}
}
#endif


+ 143
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioFileFormats.h View File

@@ -0,0 +1,143 @@
/* 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.
*/
#ifndef __CAAudioFileFormats_h__
#define __CAAudioFileFormats_h__

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioToolbox/AudioToolbox.h>
#else
#include <AudioToolbox.h>
#endif
#include "CAStreamBasicDescription.h"

class CAAudioFileFormats {
public:
enum { noErr = 0 };

struct DataFormatInfo {
DataFormatInfo() : mVariants(NULL) { }
~DataFormatInfo() { delete[] mVariants; }
UInt32 mFormatID;
int mNumVariants;
AudioStreamBasicDescription * mVariants;
bool mReadable;
bool mWritable;
bool mEitherEndianPCM;

#if DEBUG
void DebugPrint();
#endif
};
struct FileFormatInfo {
FileFormatInfo() : mFileTypeName(NULL), mExtensions(NULL), mDataFormats(NULL) { }
~FileFormatInfo() {
delete[] mDataFormats;
if (mFileTypeName)
CFRelease(mFileTypeName);
if (mExtensions)
CFRelease(mExtensions);
}
AudioFileTypeID mFileTypeID;
CFStringRef mFileTypeName;
CFArrayRef mExtensions;
int mNumDataFormats;
DataFormatInfo * mDataFormats; // NULL until loaded!
int NumberOfExtensions() { return mExtensions ? CFArrayGetCount(mExtensions) : 0; }
char * GetExtension(int index, char *buf, int buflen) {
CFStringRef cfext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, index);
CFStringGetCString(cfext, buf, buflen, kCFStringEncodingUTF8);
return buf;
}
bool MatchExtension(CFStringRef testExt) { // testExt should not include "."
CFIndex n = NumberOfExtensions();
for (CFIndex i = 0; i < n; ++i) {
CFStringRef ext = (CFStringRef)CFArrayGetValueAtIndex(mExtensions, i);
if (CFStringCompare(ext, testExt, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
return true;
}
return false;
}
bool AnyWritableFormats();
void LoadDataFormats();
#if DEBUG
void DebugPrint();
#endif
};
private: // use Instance()
CAAudioFileFormats(bool loadDataFormats);
~CAAudioFileFormats();
public:
bool InferDataFormatFromFileFormat(AudioFileTypeID filetype, CAStreamBasicDescription &fmt);
bool InferFileFormatFromFilename(const char *filename, AudioFileTypeID &filetype);

bool InferFileFormatFromFilename(CFStringRef filename, AudioFileTypeID &filetype);

bool InferFileFormatFromDataFormat(const CAStreamBasicDescription &fmt, AudioFileTypeID &filetype);

bool IsKnownDataFormat(UInt32 dataFormat);
#if DEBUG
void DebugPrint();
#endif

int mNumFileFormats;
FileFormatInfo * mFileFormats;
FileFormatInfo * FindFileFormat(UInt32 formatID);

static CAAudioFileFormats * Instance(bool loadDataFormats=true);

private:
static CAAudioFileFormats * sInstance;
};

char * OSTypeToStr(char *buf, UInt32 t);
int StrToOSType(const char *str, UInt32 &t);

#endif // __CAAudioFileFormats_h__

+ 127
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.cpp View File

@@ -0,0 +1,127 @@
/* 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
//=============================================================================

#include "CAAudioTimeStamp.h"

//=============================================================================
// CAAudioTimeStamp
//=============================================================================

const AudioTimeStamp CAAudioTimeStamp::kZero = { 0.0, 0, 0.0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0 };

bool operator<(const AudioTimeStamp& x, const AudioTimeStamp& y)
{
bool isLessThan = false;
bool isDone = false;
// check the sample time
if(!isDone)
{
if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid))
{
isLessThan = x.mSampleTime < y.mSampleTime;
isDone = true;
}
}
// check the host time
if(!isDone)
{
if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid))
{
isLessThan = x.mHostTime < y.mHostTime;
isDone = true;
}
}
// check the word clock time
if(!isDone)
{
if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid))
{
isLessThan = x.mWordClockTime < y.mWordClockTime;
isDone = true;
}
}
return isLessThan;
}

bool operator==(const AudioTimeStamp& x, const AudioTimeStamp& y)
{
bool isEqual = false;
bool isDone = false;
// check the sample time
if(!isDone)
{
if((x.mFlags & kAudioTimeStampSampleTimeValid) && (y.mFlags & kAudioTimeStampSampleTimeValid))
{
isEqual = x.mSampleTime == y.mSampleTime;
isDone = true;
}
}
// check the host time
if(!isDone)
{
if((x.mFlags & kAudioTimeStampHostTimeValid) && (y.mFlags & kAudioTimeStampHostTimeValid))
{
isEqual = x.mHostTime == y.mHostTime;
isDone = true;
}
}
// check the word clock time
if(!isDone)
{
if((x.mFlags & kAudioTimeStampWordClockTimeValid) && (y.mFlags & kAudioTimeStampWordClockTimeValid))
{
isEqual = x.mWordClockTime == y.mWordClockTime;
isDone = true;
}
}
return isEqual;
}

+ 90
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioTimeStamp.h View File

@@ -0,0 +1,90 @@
/* 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.
*/
#if !defined(__CAAudioTimeStamp_h__)
#define __CAAudioTimeStamp_h__

//=============================================================================
// Includes
//=============================================================================

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif

#include <string.h>

//=============================================================================
// CAAudioTimeStamp
//=============================================================================

struct CAAudioTimeStamp
:
public AudioTimeStamp
{

// Construction/Destruction
public:
CAAudioTimeStamp() { memset(this, 0, sizeof(AudioTimeStamp)); }
CAAudioTimeStamp(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); }
CAAudioTimeStamp(Float64 inSampleTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mFlags = kAudioTimeStampSampleTimeValid; }
CAAudioTimeStamp(UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mHostTime = inHostTime; mFlags = kAudioTimeStampHostTimeValid; }
CAAudioTimeStamp(Float64 inSampleTime, UInt64 inHostTime) { memset(this, 0, sizeof(AudioTimeStamp)); mSampleTime = inSampleTime; mHostTime = inHostTime; mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; }

// Assignment
public:
CAAudioTimeStamp& operator=(const AudioTimeStamp& v) { memcpy(this, &v, sizeof(AudioTimeStamp)); return *this; }

// Constants
public:
static const AudioTimeStamp kZero;

};

bool operator<(const AudioTimeStamp& x, const AudioTimeStamp& y);
bool operator==(const AudioTimeStamp& x, const AudioTimeStamp& y);
inline bool operator!=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x == y); }
inline bool operator<=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return (x < y) || (x == y); }
inline bool operator>=(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !(x < y); }
inline bool operator>(const AudioTimeStamp& x, const AudioTimeStamp& y) { return !((x < y) || (x == y)); }

#endif

+ 1257
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.cpp
File diff suppressed because it is too large
View File


+ 417
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioUnit.h View File

@@ -0,0 +1,417 @@
/* 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.
*/
#ifndef __CAAudioUnit_h__
#define __CAAudioUnit_h__

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#if !TARGET_OS_IPHONE
#include <AudioUnit/MusicDevice.h>
#endif
#include <AudioToolbox/AUGraph.h>
#else
#include <ConditionalMacros.h>
#include <CoreAudioTypes.h>
#include <AudioUnit.h>
#include <MusicDevice.h>
#include <AUGraph.h>
#include <MusicDevice.h>
#endif

#include <vector>
#include "CAStreamBasicDescription.h"
#include "CAComponent.h"
#include "CAAudioChannelLayout.h"

// defined below
class CAAUChanHelper;

// These constructors will NOT throw exceptions - so "check" after creation if AU IsValid()
// The destructor will NOT automatically close the AU down
// This state should be managed by the Caller
// once closed, the unit represented by this object is no longer valid
// it is up to the user of this object to ensure its validity is in sync
// if it is removed from a graph

// methods that can significantly change the state of the AU (like its format) are
// NOT const whereas those that don't change the externally related state of the AU are not const

class CAAudioUnit {
enum {
paramErr = -50,
badComponentSelector = (long)0x80008002
};
public:
typedef std::vector<AudioChannelLayoutTag> ChannelTagVector;
typedef ChannelTagVector::iterator ChannelTagVectorIter;

public:
CAAudioUnit ()
: mDataPtr(0) {}

CAAudioUnit (const AudioUnit& inUnit);

CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit);

CAAudioUnit (const CAAudioUnit& y)
: mDataPtr(0) { *this = y; }

static OSStatus Open (const CAComponent& inComp, CAAudioUnit &outUnit);

~CAAudioUnit ();

void Close ();

CAAudioUnit& operator= (const CAAudioUnit& y);

bool operator== (const CAAudioUnit& y) const;

bool operator== (const AudioUnit& y) const;

#pragma mark __State Management
bool IsValid () const;
AudioUnit AU() const;
operator AudioUnit () const { return AU(); }

const CAComponent& Comp() const { return mComp; }
bool FromAUGraph () const { return GetAUNode() != 0 && GetAUNode() != kCAAU_DoNotKnowIfAUNode; }
AUNode GetAUNode () const;
operator AUNode () const { return GetAUNode(); }
#pragma mark __API Wrapper
OSStatus Initialize() const {
return AudioUnitInitialize(AU());
}
OSStatus Uninitialize() const {
return AudioUnitUninitialize(AU());
}
OSStatus GetPropertyInfo(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
UInt32 *outDataSize, Boolean *outWritable) const
{
return AudioUnitGetPropertyInfo(AU(), propID, scope, element, outDataSize, outWritable);
}
OSStatus GetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
void *outData, UInt32 *ioDataSize) const
{
return AudioUnitGetProperty(AU(), propID, scope, element, outData, ioDataSize);
}
OSStatus SetProperty(AudioUnitPropertyID propID, AudioUnitScope scope, AudioUnitElement element,
const void *inData, UInt32 inDataSize)
{
return AudioUnitSetProperty(AU(), propID, scope, element, inData, inDataSize);
}
OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
Float32 value, UInt32 bufferOffsetFrames=0);
OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
Float32 &outValue) const;

OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inOutputBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);
OSStatus Reset (AudioUnitScope scope, AudioUnitElement element)
{
return AudioUnitReset (AU(), scope, element);
}
OSStatus GlobalReset ()
{
return AudioUnitReset (AU(), kAudioUnitScope_Global, 0);
}

OSStatus AddRenderNotify (AURenderCallback inProc, void *inProcRefCon)
{
return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon);
}
OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon)
{
return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon);
}

OSStatus AddPropertyListener (AudioUnitPropertyID inID,
AudioUnitPropertyListenerProc inProc,
void * inProcRefCon)
{
return AudioUnitAddPropertyListener (AU(), inID, inProc, inProcRefCon);
}
OSStatus RemovePropertyListener (AudioUnitPropertyID inID,
AudioUnitPropertyListenerProc inProc,
void * inProcUserData);
#if !TARGET_OS_IPHONE
// Fast dispatch support for MIDI Effects or Music Devices
OSStatus MIDIEvent (UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);
// uses the default VoiceForGroup value - this is the normal case
OSStatus StartNote (MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams)
{
return StartNote (kMusicNoteEvent_UseGroupInstrument,
inGroupID, outNoteInstanceID,
inOffsetSampleFrame, inParams);
}

OSStatus StartNote (MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams);

OSStatus StopNote (MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);
#endif

#pragma mark __Format Utilities
// typically you ask this about an AU
// These Questions are asking about Input and Output...

// These ones just say whether an AU can do a single combination of channels
// and is fine if the AU has a single output (and if an input, a single input)
bool CanDo (int inChannelsInOut) const
{
return CanDo (inChannelsInOut, inChannelsInOut);
}
bool CanDo ( int inChannelsIn,
int inChannelsOut) const;
// This version does a more thorough test for ANY AU with ANY ins/outs
// you pass in the channel helper (for the current element count on that scope)
bool CanDo ( const CAAUChanHelper &input,
const CAAUChanHelper &output) const;
bool SupportsNumChannels () const;

bool HasChannelLayouts (AudioUnitScope inScope,
AudioUnitElement inEl) const;
OSStatus GetChannelLayoutTags (AudioUnitScope inScope,
AudioUnitElement inEl,
ChannelTagVector &outChannelVector) const;
bool HasChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl) const;
OSStatus GetChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl,
CAAudioChannelLayout &outLayout) const;

OSStatus SetChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl,
const CAAudioChannelLayout &inLayout);

OSStatus SetChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl,
const AudioChannelLayout &inLayout,
UInt32 inSize);
OSStatus ClearChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl);
OSStatus GetFormat (AudioUnitScope inScope,
AudioUnitElement inEl,
AudioStreamBasicDescription &outFormat) const;
// if an AudioChannelLayout is either required or set, this call can fail
// and the SetChannelLayout call should be used to set the format
OSStatus SetFormat (AudioUnitScope inScope,
AudioUnitElement inEl,
const AudioStreamBasicDescription &inFormat);

OSStatus GetSampleRate (AudioUnitScope inScope,
AudioUnitElement inEl,
Float64 &outRate) const;
OSStatus SetSampleRate (AudioUnitScope inScope,
AudioUnitElement inEl,
Float64 inRate);

// this sets the sample rate on all in/out buses of the AU
OSStatus SetSampleRate (Float64 inSampleRate);
OSStatus NumberChannels (AudioUnitScope inScope,
AudioUnitElement inEl,
UInt32 &outChans) const;

OSStatus GetNumberChannels (AudioUnitScope inScope,
AudioUnitElement inEl,
UInt32 &outChans) const
{
return NumberChannels (inScope, inEl, outChans);
}

OSStatus SetNumberChannels (AudioUnitScope inScope,
AudioUnitElement inEl,
UInt32 inChans);

OSStatus IsElementCountWritable (AudioUnitScope inScope, bool &outWritable) const;

OSStatus GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const;

OSStatus SetElementCount (AudioUnitScope inScope, UInt32 inCount);
// value of -1 for outTotalNumChannels indicates no restriction on num channels
// for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to
// any number of channels.
// outTotalNumChannels is only valid if method returns true...
bool HasDynamicInputs (SInt32 &outTotalNumChannels) const
{
return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels);
}
bool HasDynamicOutputs (SInt32 &outTotalNumChannels) const
{
return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels);
}
// here, if the in (or out) elements are dynamic, then you supply the number of elements
// you want on in (or out) scope, and the number of channels on each consecutive element
OSStatus ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
{
return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate);
}
OSStatus ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
{
return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate);
}

bool CanBypass () const;

bool GetBypass () const;

OSStatus SetBypass (bool inBypass) const;
Float64 Latency () const;
// these calls just deal with the global preset state
// you could rescope them to deal with presets on the part scope
OSStatus GetAUPreset (CFPropertyListRef &outData) const;

OSStatus SetAUPreset (CFPropertyListRef &inData);
OSStatus SetAUPresetFromDocument (CFPropertyListRef &inData);

OSStatus GetPresentPreset (AUPreset &outData) const;
OSStatus SetPresentPreset (AUPreset &inData);
bool HasCustomView () const;
#pragma mark __Print
void Print () const { Print (stdout); }
void Print (FILE* file) const;
private:
CAComponent mComp;
class AUState;
AUState* mDataPtr;
// this can throw - so wrap this up in a static that returns a result code...
CAAudioUnit (const CAComponent& inComp);

bool HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const;
OSStatus ConfigureDynamicScope (AudioUnitScope inScope,
UInt32 inNumElements,
UInt32 *inChannelsPerElement,
Float64 inSampleRate);
bool ValidateChannelPair (int inChannelsIn,
int inChannelsOut,
const AUChannelInfo * info,
UInt32 numChanInfo) const;
bool ValidateDynamicScope (AudioUnitScope inScope,
SInt32 &outTotalNumChannels,
const AUChannelInfo * info,
UInt32 numInfo) const;
bool CheckOneSide (const CAAUChanHelper &inHelper,
bool checkOutput,
const AUChannelInfo *info,
UInt32 numInfo) const;
enum {
kCAAU_DoNotKnowIfAUNode = -1
};
};

class CAAUChanHelper {
public:
CAAUChanHelper()
: mChans(mStaticChans), mNumEls(0), mDidAllocate(false)
{
memset (mChans, 0, sizeof(UInt32) * kStaticElCount);
}
CAAUChanHelper(UInt32 inMaxElems);
CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope);
CAAUChanHelper (const CAAUChanHelper &c)
: mChans(mStaticChans), mNumEls(0), mDidAllocate(false)
{ *this = c; }
~CAAUChanHelper();

CAAUChanHelper& operator= (const CAAUChanHelper &c);

UInt32 * mChans;
UInt32 mNumEls;
private:
enum {
kStaticElCount = 8
};
UInt32 mStaticChans[kStaticElCount];
bool mDidAllocate;
};

#endif

+ 137
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioUnitOutputCapturer.h View File

@@ -0,0 +1,137 @@
/* 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.
*/
#ifndef __CAAudioUnitOutputCapturer_h__
#define __CAAudioUnitOutputCapturer_h__

#include <AudioToolbox/ExtendedAudioFile.h>

/*
Class to capture output from an AudioUnit for analysis.

example:

CFURL fileurl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/recording.caf"), kCFURLPOSIXPathStyle, false);

CAAudioUnitOutputCapturer captor(someAU, fileurl, 'caff', anASBD);

{
captor.Start();
...
captor.Stop();
} // can repeat

captor.Close(); // can be omitted; happens automatically from destructor
*/

class CAAudioUnitOutputCapturer {
public:
enum { noErr = 0 };

CAAudioUnitOutputCapturer(AudioUnit au, CFURLRef outputFileURL, AudioFileTypeID fileType, const AudioStreamBasicDescription &format, UInt32 busNumber = 0) :
mFileOpen(false),
mClientFormatSet(false),
mAudioUnit(au),
mExtAudioFile(NULL),
mBusNumber (busNumber)
{
CFShow(outputFileURL);
OSStatus err = ExtAudioFileCreateWithURL(outputFileURL, fileType, &format, NULL, kAudioFileFlags_EraseFile, &mExtAudioFile);
if (!err)
mFileOpen = true;
}
void Start() {
if (mFileOpen) {
if (!mClientFormatSet) {
AudioStreamBasicDescription clientFormat;
UInt32 size = sizeof(clientFormat);
AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, mBusNumber, &clientFormat, &size);
ExtAudioFileSetProperty(mExtAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
mClientFormatSet = true;
}
ExtAudioFileWriteAsync(mExtAudioFile, 0, NULL); // initialize async writes
AudioUnitAddRenderNotify(mAudioUnit, RenderCallback, this);
}
}
void Stop() {
if (mFileOpen)
AudioUnitRemoveRenderNotify(mAudioUnit, RenderCallback, this);
}
void Close() {
if (mExtAudioFile) {
ExtAudioFileDispose(mExtAudioFile);
mExtAudioFile = NULL;
}
}
~CAAudioUnitOutputCapturer() {
Close();
}

private:
static OSStatus RenderCallback( void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
if (*ioActionFlags & kAudioUnitRenderAction_PostRender) {
CAAudioUnitOutputCapturer *This = (CAAudioUnitOutputCapturer *)inRefCon;
static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
if (This->mBusNumber == inBusNumber && !(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError)) {
OSStatus result = ExtAudioFileWrite(This->mExtAudioFile, inNumberFrames, ioData);
if (result) DebugMessageN1("ERROR WRITING FRAMES: %d\n", result);
}
}
return noErr;
}
bool mFileOpen;
bool mClientFormatSet;
AudioUnit mAudioUnit;
ExtAudioFileRef mExtAudioFile;
UInt32 mBusNumber;
};

#endif // __CAAudioUnitOutputCapturer_h__

+ 244
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.cpp View File

@@ -0,0 +1,244 @@
/* 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 "CAAudioValueRange.h"

// Standard Library
#include <algorithm>

//==================================================================================================
// CAAudioValueRange
//==================================================================================================

Float64 CAAudioValueRange::PickCommonSampleRate(const AudioValueRange& inRange)
{
// This routine will pick a "common" sample rate from the give range of rates or the maximum
// if no common rates can be found. It assumes that inRange contains a continuous range of
// sample rates.
Float64 theAnswer = inRange.mMaximum;
if(ContainsValue(inRange, 44100.0))
{
theAnswer = 44100.0;
}
else if(ContainsValue(inRange, 48000.0))
{
theAnswer = 48000.0;
}
else if(ContainsValue(inRange, 96000.0))
{
theAnswer = 96000.0;
}
else if(ContainsValue(inRange, 88200.0))
{
theAnswer = 88200.0;
}
else if(ContainsValue(inRange, 64000.0))
{
theAnswer = 64000.0;
}
else if(ContainsValue(inRange, 32000.0))
{
theAnswer = 32000.0;
}
else if(ContainsValue(inRange, 24000.0))
{
theAnswer = 24000.0;
}
else if(ContainsValue(inRange, 22050.0))
{
theAnswer = 22050.0;
}
else if(ContainsValue(inRange, 16000.0))
{
theAnswer = 16000.0;
}
else if(ContainsValue(inRange, 12000.0))
{
theAnswer = 12000.0;
}
else if(ContainsValue(inRange, 11025.0))
{
theAnswer = 11025.0;
}
else if(ContainsValue(inRange, 8000.0))
{
theAnswer = 8000.0;
}
return theAnswer;
}

bool CAAudioValueRange::Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange)
{
bool isNonEmpty;
if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y))
{
outRange.mMinimum = std::max(x.mMinimum, y.mMinimum);
outRange.mMaximum = std::min(x.mMaximum, y.mMaximum);
isNonEmpty = true;
}
else
{
outRange.mMinimum = 0;
outRange.mMaximum = 0;
isNonEmpty = false;
}
return isNonEmpty;
}

bool CAAudioValueRange::Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange)
{
bool isDisjoint;
if(!IsStrictlyLessThan(x, y) && !IsStrictlyGreaterThan(x, y))
{
outRange.mMinimum = std::min(x.mMinimum, y.mMinimum);
outRange.mMaximum = std::max(x.mMaximum, y.mMaximum);
isDisjoint = false;
}
else
{
outRange.mMinimum = 0;
outRange.mMaximum = 0;
isDisjoint = true;
}
return isDisjoint;
}

void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion)
{
// this method assumes that the ranges in inRangeList are disjoint and that they are sorted from low to high and
outUnion.clear();
// start at the beginning of inRangeList
CAAudioValueRangeList::const_iterator theIterator = inRangeList.begin();
// iterate through inRangeList and add all the ranges that are strictly less than inRange
while((theIterator != inRangeList.end()) && CAAudioValueRange::IsStrictlyLessThan(*theIterator, inRange))
{
// put this range in the union
outUnion.push_back(*theIterator);
// go to the next one
std::advance(theIterator, 1);
}
if(theIterator != inRangeList.end())
{
if(!CAAudioValueRange::IsStrictlyGreaterThan(*theIterator, inRange))
{
// inRange intersects the range that theIterator points at, but might actually intersect several contiguous ranges
// initialize the starting point, noting that we can skip the current one since we already know it's in the intersection
CAAudioValueRangeList::const_iterator theGreaterIterator = theIterator;
std::advance(theGreaterIterator, 1);
// iterate until we find a range that is strictly greater than inRange
while((theGreaterIterator != inRangeList.end()) && !CAAudioValueRange::IsStrictlyGreaterThan(*theGreaterIterator, inRange))
{
// go to the next one
std::advance(theGreaterIterator, 1);
}
// theGreaterIterator now points at either one past the highest range in the intersection or the end of the vector
// Either way, we have to adjust it to point at the true highest range in the intersection
std::advance(theGreaterIterator, -1);
// now theIterator points at the lowest range in the intersection and theGreaterIterator points at the highest
// so we can compute the coagulated range
AudioValueRange theCoagulation;
theCoagulation.mMinimum = std::min(theIterator->mMinimum, inRange.mMinimum);
theCoagulation.mMaximum = std::max(theGreaterIterator->mMaximum, inRange.mMaximum);
// add the coagulation to the union
outUnion.push_back(theCoagulation);
// adjust theIterator to point at the next range for processing
theIterator = theGreaterIterator;
std::advance(theIterator, 1);
}
else
{
// the range theIterator points at is strictly greater than inRange, so insert inRange in front of it and we're done
outUnion.push_back(inRange);
}
// we need to now copy the remaining higher ranges in inRangeList into the union
while(theIterator != inRangeList.end())
{
// put this range in the union
outUnion.push_back(*theIterator);
// go to the next one
std::advance(theIterator, 1);
}
}
else
{
// inRange is larger than all of the ranges in inRangeList, so just add it onto the end of the union and we're done
// This is also the case if inRangeList is empty
outUnion.push_back(inRange);
}
}

void CAAudioValueRange_ComputeIntersection(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outIntersections)
{
outIntersections.clear();
// iterate through the list and compute the intersections
CAAudioValueRangeList::const_iterator theIterator = inRangeList.begin();
while(theIterator != inRangeList.end())
{
// figure out if the range intersects
AudioValueRange theIntersection;
if(CAAudioValueRange::Intersection(inRange, *theIterator, theIntersection))
{
// it does, so add the intersection to the return list
outIntersections.push_back(theIntersection);
}
// go to the next one
std::advance(theIterator, 1);
}
}

+ 114
- 0
distrho/src/CoreAudio106/PublicUtility/CAAudioValueRange.h View File

@@ -0,0 +1,114 @@
/* 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.
*/
#if !defined(__CAAudioValueRange_h__)
#define __CAAudioValueRange_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
// Standard Library Includes
#include <functional>
#include <vector>

//=============================================================================
// CAAudioValueRange
//=============================================================================

struct CAAudioValueRange
:
public AudioValueRange
{

// Construction/Destruction
public:
CAAudioValueRange() { mMinimum = 0.0; mMaximum = 0.0; }
CAAudioValueRange(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; }
CAAudioValueRange(Float64 inMinimum, Float64 inMaximum) { mMinimum = inMinimum; mMaximum = inMaximum; }

// Assignment
public:
CAAudioValueRange& operator=(const AudioValueRange& v) { mMinimum = v.mMinimum; mMaximum = v.mMaximum; return *this; }

// Operations
public:
static bool ContainsValue(const AudioValueRange& inRange, Float64 inValue) { return (inValue >= inRange.mMinimum) && (inValue <= inRange.mMaximum); }
static Float64 PickCommonSampleRate(const AudioValueRange& inRange);
static bool IsStrictlyLessThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMaximum < y.mMinimum; }
static bool IsStrictlyGreaterThan(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum > y.mMaximum; }
static bool IsStrictlyContainedBy(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
static bool OverlapsLow(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum < y.mMinimum) && (x.mMaximum >= y.mMinimum) && (x.mMaximum <= y.mMaximum); }
static bool OverlapsHigh(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum >= y.mMinimum) && (x.mMinimum <= y.mMaximum) && (x.mMaximum > y.mMaximum); }
static bool Intersection(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);
static bool Union(const AudioValueRange& x, const AudioValueRange& y, AudioValueRange& outRange);

// STL Helpers
public:
struct LessThan
:
public std::binary_function<AudioValueRange, AudioValueRange, bool>
{
bool operator()(const AudioValueRange& x, const AudioValueRange& y) const
{
return x.mMinimum < y.mMinimum;
}
};
};

inline bool operator<(const AudioValueRange& x, const AudioValueRange& y) { return x.mMinimum < y.mMinimum; }
inline bool operator==(const AudioValueRange& x, const AudioValueRange& y) { return (x.mMinimum == y.mMinimum) && (x.mMaximum == y.mMaximum); }
inline bool operator!=(const AudioValueRange& x, const AudioValueRange& y) { return !(x == y); }
inline bool operator<=(const AudioValueRange& x, const AudioValueRange& y) { return (x < y) || (x == y); }
inline bool operator>=(const AudioValueRange& x, const AudioValueRange& y) { return !(x < y); }
inline bool operator>(const AudioValueRange& x, const AudioValueRange& y) { return !((x < y) || (x == y)); }

typedef std::vector<CAAudioValueRange> CAAudioValueRangeList;
void CAAudioValueRange_ComputeUnion(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outUnion);
void CAAudioValueRange_ComputeIntersection(const AudioValueRange& inRange, const CAAudioValueRangeList& inRangeList, CAAudioValueRangeList& outIntersections);

#endif

+ 502
- 0
distrho/src/CoreAudio106/PublicUtility/CAAutoDisposer.h View File

@@ -0,0 +1,502 @@
/* 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.
*/
#if !defined(__CAPtr_h__)
#define __CAPtr_h__

#include <stdlib.h> // for malloc
#include <new> // for bad_alloc
#include <string.h> // for memset

inline void* CA_malloc(size_t size)
{
void* p = malloc(size);
if (!p && size) throw std::bad_alloc();
return p;
}

inline void* CA_realloc(void* old, size_t size)
{
#if TARGET_OS_WIN32
void* p = realloc(old, size);
#else
void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL).
#endif
if (!p && size) throw std::bad_alloc();
return p;
}

#ifndef UINTPTR_MAX
#if __LP64__
#define UINTPTR_MAX 18446744073709551615ULL
#else
#define UINTPTR_MAX 4294967295U
#endif
#endif

inline void* CA_calloc(size_t n, size_t size)
{
// ensure that multiplication will not overflow
if (n && UINTPTR_MAX / n < size) throw std::bad_alloc();
size_t nsize = n*size;
void* p = malloc(nsize);
if (!p && nsize) throw std::bad_alloc();

memset(p, 0, nsize);
return p;
}


// helper class for automatic conversions
template <typename T>
struct CAPtrRef
{
T* ptr_;

explicit CAPtrRef(T* ptr) : ptr_(ptr) {}
};

template <typename T>
class CAAutoFree
{
private:
T* ptr_;

public:
CAAutoFree() : ptr_(0) {}
explicit CAAutoFree(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership

// C++ std says: a template constructor is never a copy constructor
CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership

CAAutoFree(size_t n, bool clear = false)
// this becomes an ambiguous call if n == 0
: ptr_(0)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (n > maxItems)
throw std::bad_alloc();

ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T)));
}
~CAAutoFree() { free(); }
void alloc(size_t numItems, bool clear = false)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (numItems > maxItems) throw std::bad_alloc();
free();
ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T)));
}
void allocBytes(size_t numBytes, bool clear = false)
{
free();
ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes));
}
void reallocBytes(size_t numBytes)
{
ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes));
}

void reallocItems(size_t numItems)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (numItems > maxItems) throw std::bad_alloc();
ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T)));
}
template <typename U>
CAAutoFree& operator=(CAAutoFree<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoFree& operator=(CAAutoFree& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoFree& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoFree& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }

bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
::free(ptr_);
ptr_ = ptr;
}
}
void free()
{
set(0);
}


// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }

CAAutoFree& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}

template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }

template<typename U>
operator CAAutoFree<U>()
{ return CAAutoFree<U>(release()); }
};


template <typename T>
class CAAutoDelete
{
private:
T* ptr_;

public:
CAAutoDelete() : ptr_(0) {}

explicit CAAutoDelete(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership

// C++ std says: a template constructor is never a copy constructor
CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership
~CAAutoDelete() { free(); }
template <typename U>
CAAutoDelete& operator=(CAAutoDelete<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoDelete& operator=(CAAutoDelete& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoDelete& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoDelete& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
delete ptr_;
ptr_ = ptr;
}
}
void free()
{
set(0);
}


// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }

CAAutoDelete& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}

template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }

template<typename U>
operator CAAutoFree<U>()
{ return CAAutoFree<U>(release()); }
};


template <typename T>
class CAAutoArrayDelete
{
private:
T* ptr_;

public:
CAAutoArrayDelete() : ptr_(0) {}

explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership

// C++ std says: a template constructor is never a copy constructor
CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership
// this becomes an ambiguous call if n == 0
CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {}
~CAAutoArrayDelete() { free(); }
void alloc(size_t numItems)
{
free();
ptr_ = new T [numItems];
}
template <typename U>
CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoArrayDelete& operator=(CAAutoArrayDelete& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoArrayDelete& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoArrayDelete& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }

bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
delete [] ptr_;
ptr_ = ptr;
}
}
void free()
{
set(0);
}


// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }

CAAutoArrayDelete& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}

template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }

template<typename U>
operator CAAutoArrayDelete<U>()
{ return CAAutoFree<U>(release()); }
};





// convenience function
template <typename T>
void free(CAAutoFree<T>& p)
{
p.free();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////

#if 0
// example program showing ownership transfer

CAAutoFree<char> source()
{
// source allocates and returns ownership to the caller.
const char* str = "this is a test";
size_t size = strlen(str) + 1;
CAAutoFree<char> captr(size, false);
strlcpy(captr(), str, size);
printf("source %08X %08X '%s'\n", &captr, captr(), captr());
return captr;
}

void user(CAAutoFree<char> const& captr)
{
// passed by const reference. user can access the pointer but does not take ownership.
printf("user: %08X %08X '%s'\n", &captr, captr(), captr());
}

void sink(CAAutoFree<char> captr)
{
// passed by value. sink takes ownership and frees the pointer on return.
printf("sink: %08X %08X '%s'\n", &captr, captr(), captr());
}


int main (int argc, char * const argv[])
{

CAAutoFree<char> captr(source());
printf("main captr A %08X %08X\n", &captr, captr());
user(captr);
sink(captr);
printf("main captr B %08X %08X\n", &captr, captr());
return 0;
}
#endif

#endif

+ 192
- 0
distrho/src/CoreAudio106/PublicUtility/CABitOperations.h View File

@@ -0,0 +1,192 @@
/* 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.
*/
#ifndef _CABitOperations_h_
#define _CABitOperations_h_

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
//#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
#include <CoreFoundation/CFBase.h>
#else
// #include <MacTypes.h>
#include "CFBase.h"
#endif
#include <TargetConditionals.h>

// return whether a number is a power of two
inline UInt32 IsPowerOfTwo(UInt32 x)
{
return (x & (x-1)) == 0;
}

// count the leading zeroes in a word
#ifdef __MWERKS__

// Metrowerks Codewarrior. powerpc native count leading zeroes instruction:
#define CountLeadingZeroes(x) ((int)__cntlzw((unsigned int)x))

#elif TARGET_OS_WIN32

static int CountLeadingZeroes( int arg )
{
__asm{
bsr eax, arg
mov ecx, 63
cmovz eax, ecx
xor eax, 31
}
return arg;
}

#else

static __inline__ int CountLeadingZeroes(int arg) {
#if TARGET_CPU_PPC || TARGET_CPU_PPC64
__asm__ volatile("cntlzw %0, %1" : "=r" (arg) : "r" (arg));
return arg;
#elif TARGET_CPU_X86 || TARGET_CPU_X86_64
__asm__ volatile(
"bsrl %0, %0\n\t"
"movl $63, %%ecx\n\t"
"cmove %%ecx, %0\n\t"
"xorl $31, %0"
: "=r" (arg)
: "0" (arg) : "%ecx"
);
return arg;
#else
if (arg == 0) return 32;
return __builtin_clz(arg);
#endif
}

#endif

// count trailing zeroes
inline UInt32 CountTrailingZeroes(UInt32 x)
{
return 32 - CountLeadingZeroes(~x & (x-1));
}

// count leading ones
inline UInt32 CountLeadingOnes(UInt32 x)
{
return CountLeadingZeroes(~x);
}

// count trailing ones
inline UInt32 CountTrailingOnes(UInt32 x)
{
return 32 - CountLeadingZeroes(x & (~x-1));
}

// number of bits required to represent x.
inline UInt32 NumBits(UInt32 x)
{
return 32 - CountLeadingZeroes(x);
}

// base 2 log of next power of two greater or equal to x
inline UInt32 Log2Ceil(UInt32 x)
{
return 32 - CountLeadingZeroes(x - 1);
}

// next power of two greater or equal to x
inline UInt32 NextPowerOfTwo(UInt32 x)
{
return 1L << Log2Ceil(x);
}

// counting the one bits in a word
inline UInt32 CountOnes(UInt32 x)
{
// secret magic algorithm for counting bits in a word.
UInt32 t;
x = x - ((x >> 1) & 0x55555555);
t = ((x >> 2) & 0x33333333);
x = (x & 0x33333333) + t;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x << 8);
x = x + (x << 16);
return x >> 24;
}

// counting the zero bits in a word
inline UInt32 CountZeroes(UInt32 x)
{
return CountOnes(~x);
}

// return the bit position (0..31) of the least significant bit
inline UInt32 LSBitPos(UInt32 x)
{
return CountTrailingZeroes(x & -(SInt32)x);
}

// isolate the least significant bit
inline UInt32 LSBit(UInt32 x)
{
return x & -(SInt32)x;
}

// return the bit position (0..31) of the most significant bit
inline UInt32 MSBitPos(UInt32 x)
{
return 31 - CountLeadingZeroes(x);
}

// isolate the most significant bit
inline UInt32 MSBit(UInt32 x)
{
return 1UL << MSBitPos(x);
}

// Division optimized for power of 2 denominators
inline UInt32 DivInt(UInt32 numerator, UInt32 denominator)
{
if(IsPowerOfTwo(denominator))
return numerator >> (31 - CountLeadingZeroes(denominator));
else
return numerator/denominator;
}

#endif


+ 82
- 0
distrho/src/CoreAudio106/PublicUtility/CABool.h View File

@@ -0,0 +1,82 @@
/* 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.
*/
#if !defined(__CABool_h__)
#define __CABool_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#include "CADebugMacros.h"
#include "CAException.h"

//=============================================================================
// CABool
//
// This class implements a boolean value that has a third state that marks
// it as uninitialized. Accessing the value of an instance of this class that
// is uninitialized will throw an exception.
//=============================================================================

class CABool
{

// Construction/Destruction
public:
CABool() : mValue(-1) {}
CABool(bool inValue) : mValue(inValue ? 1 : 0) {}
CABool(const CABool& inValue) : mValue(inValue.mValue) {}
~CABool() {}
CABool& operator=(bool inValue) { mValue = inValue; return *this; }
CABool& operator=(const CABool& inValue) { mValue = inValue.mValue; return *this; }
operator bool() const { ThrowIf(mValue == -1, CAException('nope'), "CABool: uninitialized"); return mValue != 0; }
bool IsInitialized() const { return mValue != -1; }
void Uninitialize() { mValue = -1; }

private:
SInt32 mValue;

};

#endif

+ 252
- 0
distrho/src/CoreAudio106/PublicUtility/CABufferList.cpp View File

@@ -0,0 +1,252 @@
/* 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 "CABufferList.h"
#include "CAByteOrder.h"

void CABufferList::AllocateBuffers(UInt32 nBytes)
{
if (nBytes <= GetNumBytes()) return;
if (mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
nBytes = ((nBytes + 15) & ~15) | 16;
UInt32 memorySize = nBytes * mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // get page faults now, not later
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
if (buf->mData != NULL && buf->mDataByteSize > 0)
// preserve existing buffer contents
memcpy(p, buf->mData, buf->mDataByteSize);
buf->mDataByteSize = nBytes;
buf->mData = p;
p += nBytes;
}
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
delete[] oldMemory;
}

void CABufferList::AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inSrcList, CABufferList *inSetPtrList)
{
if (mNumberBuffers != inSrcList->mNumberBuffers) return;
if (mNumberBuffers != inSetPtrList->mNumberBuffers) return;
if (nBytes <= GetNumBytes()) {
CopyAllFrom(inSrcList, inSetPtrList);
return;
}
inSetPtrList->VerifyNotTrashingOwnedBuffer();
UInt32 fromByteSize = inSrcList->GetNumBytes();
if (mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
nBytes = ((nBytes + 15) & ~15) | 16;
UInt32 memorySize = nBytes * mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // make buffer "hot"
AudioBuffer *buf = mBuffers;
AudioBuffer *ptrBuf = inSetPtrList->mBuffers;
AudioBuffer *srcBuf = inSrcList->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf, ++ptrBuf, ++srcBuf) {
if (srcBuf->mData != NULL && srcBuf->mDataByteSize > 0)
// preserve existing buffer contents
memmove(p, srcBuf->mData, srcBuf->mDataByteSize);
buf->mDataByteSize = nBytes;
buf->mData = p;
ptrBuf->mDataByteSize = srcBuf->mDataByteSize;
ptrBuf->mData = p;
p += nBytes;
}
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
if (inSrcList != inSetPtrList)
inSrcList->BytesConsumed(fromByteSize);
delete[] oldMemory;
}

void CABufferList::DeallocateBuffers()
{
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
buf->mData = NULL;
buf->mDataByteSize = 0;
}
if (mBufferMemory != NULL) {
delete[] mBufferMemory;
mBufferMemory = NULL;
}
}

static void show(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label, const char *fmtstr=NULL)
{
printf("%s %p (%d fr%s):\n", label ? label : "AudioBufferList", &abl, framesToPrint, fmtstr ? fmtstr : "");
const AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) {
printf(" [%2d] %5dbytes %dch @ %p", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
if (framesToPrint && buf->mData != NULL) {
printf(":");
Byte *p = (Byte *)buf->mData;
for (int j = framesToPrint * buf->mNumberChannels; --j >= 0; )
switch (wordSize) {
case 0: // native float
printf(" %6.3f", *(Float32 *)p);
p += sizeof(Float32);
break;
// positive: big endian
case 1:
case -1:
printf(" %02X", *p);
p += 1;
break;
case 2:
printf(" %04X", CFSwapInt16BigToHost(*(UInt16 *)p));
p += 2;
break;
case 3:
printf(" %06X", (p[0] << 16) | (p[1] << 8) | p[2]);
p += 3;
break;
case 4:
printf(" %08X", (unsigned int)CFSwapInt32BigToHost(*(UInt32 *)p));
p += 4;
break;
case 10:
printf(" %6.3f", CASwapFloat32BigToHost(*(Float32 *)p));
p += sizeof(Float32);
break;
case -2:
printf(" %04X", CFSwapInt16LittleToHost(*(UInt16 *)p));
p += 2;
break;
case -3:
printf(" %06X", (p[2] << 16) | (p[1] << 8) | p[0]);
p += 3;
break;
case -4:
printf(" %08X", (unsigned int)CFSwapInt32LittleToHost(*(UInt32 *)p));
p += 4;
break;
case -10:
printf(" %6.3f", CASwapFloat32LittleToHost(*(Float32 *)p));
p += sizeof(Float32);
break;
}
}
printf("\n");
}
}

void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &asbd, const char *label)
{
CAStreamBasicDescription fmt(asbd);
int wordSize = 1;
char fmtstr[80] = { 0 };
if (fmt.mFormatID == kAudioFormatLinearPCM) {
if (fmt.mFormatFlags & kLinearPCMFormatFlagIsFloat) {
if (fmt.mBitsPerChannel == 32) {
if (fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) {
wordSize = 10;
strcpy(fmtstr, ", BEF");
} else {
wordSize = -10;
strcpy(fmtstr, ", LEF");
}
}
} else {
wordSize = fmt.SampleWordSize();
if (wordSize > 0) {
#if CA_PREFER_FIXED_POINT
int fracbits = (asbd.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
if (fracbits > 0)
sprintf(fmtstr, ", %d.%d-bit", (int)asbd.mBitsPerChannel - fracbits, fracbits);
else
#endif
sprintf(fmtstr, ", %d-bit", (int)asbd.mBitsPerChannel);

if (!(fmt.mFormatFlags & kLinearPCMFormatFlagIsBigEndian)) {
wordSize = -wordSize;
strcat(fmtstr, " LEI");
} else {
strcat(fmtstr, " BEI");
}
}
}
}
show(abl, framesToPrint, wordSize, label, fmtstr);
}

void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label)
{
show(abl, framesToPrint, wordSize, label);
}

extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize)
{
show(*abl, framesToPrint, wordSize, NULL);
}

// if the return result is odd, there was a null buffer.
extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullok)
{
const AudioBuffer *buf = abl->mBuffers, *bufend = buf + abl->mNumberBuffers;
int sum = 0; // defeat attempts by the compiler to optimize away the code that touches the buffers
int anyNull = 0;
for ( ; buf < bufend; ++buf) {
const int *p = (const int *)buf->mData;
if (p == NULL) {
anyNull = 1;
if (nullok) continue;
}
unsigned datasize = buf->mDataByteSize;
if (datasize >= sizeof(int)) {
sum += p[0];
sum += p[datasize / sizeof(int) - 1];
}
}
return anyNull | (sum & ~1);
}


+ 298
- 0
distrho/src/CoreAudio106/PublicUtility/CABufferList.h View File

@@ -0,0 +1,298 @@
/* 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.
*/
#ifndef __CABufferList_h__
#define __CABufferList_h__

#include <stddef.h>
#include "CAStreamBasicDescription.h"
#include "CAXException.h"

void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, const AudioStreamBasicDescription &fmt, const char *label=NULL);
void CAShowAudioBufferList(const AudioBufferList &abl, int framesToPrint, int wordSize, const char *label=NULL);
extern "C" void CAShowAudioBufferList(const AudioBufferList *abl, int framesToPrint, int wordSize);
extern "C" int CrashIfClientProvidedBogusAudioBufferList(const AudioBufferList *abl, bool nullOK=false);

/* ____________________________________________________________________________
// CABufferList - variable length buffer list

This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
is preferred.
CABufferList can be used in one of two ways:
- as mutable pointers into non-owned memory
- as an immutable array of buffers (owns its own memory).

All buffers are assumed to have the same format (number of channels, word size), so that
we can assume their mDataByteSizes are all the same.
____________________________________________________________________________ */
class CABufferList {
public:
void * operator new(size_t /*size*/, int nBuffers) {
return ::operator new(sizeof(CABufferList) + (nBuffers-1) * sizeof(AudioBuffer));
}
static CABufferList * New(const char *name, const CAStreamBasicDescription &format)
{
UInt32 numBuffers = format.NumberChannelStreams(), channelsPerBuffer = format.NumberInterleavedChannels();
return new(numBuffers) CABufferList(name, numBuffers, channelsPerBuffer);
}

protected:
CABufferList(const char *name, UInt32 numBuffers, UInt32 channelsPerBuffer) :
mName(name),
mBufferMemory(NULL)
{
//XAssert(numBuffers > 0 /*&& channelsPerBuffer > 0*/);
mNumberBuffers = numBuffers;
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
buf->mNumberChannels = channelsPerBuffer;
buf->mDataByteSize = 0;
buf->mData = NULL;
}
}

public:
~CABufferList()
{
if (mBufferMemory)
delete[] mBufferMemory;
}
const char * Name() { return mName; }
const AudioBufferList & GetBufferList() const { return *(AudioBufferList *)&mNumberBuffers; }
AudioBufferList & GetModifiableBufferList()
{
VerifyNotTrashingOwnedBuffer();
return _GetBufferList();
}
UInt32 GetNumberBuffers() const { return mNumberBuffers; }
UInt32 GetNumBytes() const
{
return mBuffers[0].mDataByteSize;
}
void SetBytes(UInt32 nBytes, void *data)
{
VerifyNotTrashingOwnedBuffer();
XAssert(mNumberBuffers == 1);
mBuffers[0].mDataByteSize = nBytes;
mBuffers[0].mData = data;
}
void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
// copies bytes from srcbl
// make ptrbl reflect the length copied
// note that srcbl may be same as ptrbl!
{
// Note that this buffer *can* own memory and its pointers/lengths are not
// altered; only its buffer contents, which are copied from srcbl.
// The pointers/lengths in ptrbl are updated to reflect the addresses/lengths
// of the copied data, and srcbl's contents are consumed.
ptrbl->VerifyNotTrashingOwnedBuffer();
UInt32 nBytes = srcbl->GetNumBytes();
AudioBuffer *mybuf = mBuffers, *srcbuf = srcbl->mBuffers,
*ptrbuf = ptrbl->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf, ++ptrbuf) {
memmove(mybuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
ptrbuf->mData = mybuf->mData;
ptrbuf->mDataByteSize = srcbuf->mDataByteSize;
}
if (srcbl != ptrbl)
srcbl->BytesConsumed(nBytes);
}
void AppendFrom(CABufferList *blp, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *mybuf = mBuffers, *srcbuf = blp->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) {
XAssert(nBytes <= srcbuf->mDataByteSize);
memcpy((Byte *)mybuf->mData + mybuf->mDataByteSize, srcbuf->mData, nBytes);
mybuf->mDataByteSize += nBytes;
}
blp->BytesConsumed(nBytes);
}
void PadWithZeroes(UInt32 desiredBufferSize)
// for cases where an algorithm (e.g. SRC) requires some
// padding to create silence following end-of-file
{
VerifyNotTrashingOwnedBuffer();
if (GetNumBytes() > desiredBufferSize) return;
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
memset((Byte *)buf->mData + buf->mDataByteSize, 0, desiredBufferSize - buf->mDataByteSize);
buf->mDataByteSize = desiredBufferSize;
}
}
void SetToZeroes(UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
memset((Byte *)buf->mData, 0, nBytes);
buf->mDataByteSize = nBytes;
}
}
void Reset()
{
DeallocateBuffers();
}
Boolean SameDataAs(const CABufferList* anotherBufferList)
{
// check to see if two buffer lists point to the same memory.
if (mNumberBuffers != anotherBufferList->mNumberBuffers) return false;
for (UInt32 i = 0; i < mNumberBuffers; ++i) {
if (mBuffers[i].mData != anotherBufferList->mBuffers[i].mData) return false;
}
return true;
}
void BytesConsumed(UInt32 nBytes)
// advance buffer pointers, decrease buffer sizes
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
XAssert(nBytes <= buf->mDataByteSize);
buf->mData = (Byte *)buf->mData + nBytes;
buf->mDataByteSize -= nBytes;
}
}
void SetFrom(const AudioBufferList *abl)
{
VerifyNotTrashingOwnedBuffer();
memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
}
void SetFrom(const CABufferList *blp)
{
SetFrom(&blp->GetBufferList());
}
void SetFrom(const AudioBufferList *abl, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *mybuf = mBuffers;
const AudioBuffer *srcbuf = abl->mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++mybuf, ++srcbuf) {
mybuf->mNumberChannels = srcbuf->mNumberChannels;
mybuf->mDataByteSize = nBytes;
mybuf->mData = srcbuf->mData;
}
}
void SetFrom(const CABufferList *blp, UInt32 nBytes)
{
SetFrom(&blp->GetBufferList(), nBytes);
}
AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const
{
memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mNumberBuffers] - (char *)abl);
return abl;
}
void AllocateBuffers(UInt32 nBytes);
void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
void DeallocateBuffers();
void UseExternalBuffer(Byte *ptr, UInt32 nBytes);
void AdvanceBufferPointers(UInt32 nBytes)
// this is for bufferlists that function simply as
// an array of pointers into another bufferlist, being advanced,
// as in RenderOutput implementations
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
buf->mData = (Byte *)buf->mData + nBytes;
buf->mDataByteSize -= nBytes;
}
}
void SetNumBytes(UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf)
buf->mDataByteSize = nBytes;
}

void Print(const char *label=NULL, int nframes=0, int wordSize=0) const
{
if (label == NULL)
label = mName;
printf("%s - ", label);
CAShowAudioBufferList(&GetBufferList(), nframes, wordSize);
if (mBufferMemory)
printf(" owned memory @ 0x%p:\n", mBufferMemory);
}

protected:
AudioBufferList & _GetBufferList() { return *(AudioBufferList *)&mNumberBuffers; } // use with care
// if we make this public, then we lose ability to call VerifyNotTrashingOwnedBuffer
void VerifyNotTrashingOwnedBuffer()
{
// This needs to be called from places where we are modifying the buffer list.
// It's an error to modify the buffer pointers or lengths if we own the buffer memory.
XAssert(mBufferMemory == NULL);
}

const char * mName; // for debugging
Byte * mBufferMemory;
// the rest must exactly mirror the structure of AudioBufferList
UInt32 mNumberBuffers;
AudioBuffer mBuffers[1];
};

#endif // __CABufferList_h__

+ 78
- 0
distrho/src/CoreAudio106/PublicUtility/CABundleLocker.cpp View File

@@ -0,0 +1,78 @@
/* 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 "CABundleLocker.h"
#include <pthread.h>

/*
some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
*/

static pthread_mutex_t sCABundleLocker = PTHREAD_MUTEX_INITIALIZER;

#define RECURSIVE_LOCK 0

#if RECURSIVE_LOCK
static pthread_once_t sOnce = PTHREAD_ONCE_INIT;

static void InitCABundleLocker()
{
// have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&sCABundleLocker, &attr);
pthread_mutexattr_destroy(&attr);
}
#endif

CABundleLocker::CABundleLocker()
{
#if RECURSIVE_LOCK
pthread_once(&sOnce, InitCABundleLocker);
#endif
pthread_mutex_lock(&sCABundleLocker);
}

CABundleLocker::~CABundleLocker()
{
pthread_mutex_unlock(&sCABundleLocker);
}


+ 61
- 0
distrho/src/CoreAudio106/PublicUtility/CABundleLocker.h View File

@@ -0,0 +1,61 @@
/* 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.
*/
#ifndef _CABundleLocker_h_
#define _CABundleLocker_h_

/*
some bundle operations are not thread safe, notably CFCopyLocalizedStringFromTableInBundle
*/

class CABundleLocker
{
public:

#if TARGET_OS_MAC
CABundleLocker();
~CABundleLocker();
#else
CABundleLocker() {}
~CABundleLocker() {}
#endif
};

#endif

+ 155
- 0
distrho/src/CoreAudio106/PublicUtility/CAByteOrder.h View File

@@ -0,0 +1,155 @@
/* 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.
*/
#if !defined(__CAByteOrder_h__)
#define __CAByteOrder_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#else
#include "CoreFoundation.h"
#endif


#if defined(__cplusplus)
extern "C" {
#endif

CF_INLINE Float32 CASwapFloat32 (Float32 arg) {
union {
Float32 f;
UInt32 i;
} flip;

flip.f = arg;
flip.i = CFSwapInt32 (flip.i);
return flip.f;
}

CF_INLINE Float64 CASwapFloat64 (Float64 arg) {
union {
Float64 f;
UInt64 i;
} flip;

flip.f = arg;
flip.i = CFSwapInt64 (flip.i);
return flip.f;
}

#pragma mark -Flippers

CF_INLINE Float32 CASwapFloat32BigToHost(Float32 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}

CF_INLINE Float64 CASwapFloat64BigToHost(Float64 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}

CF_INLINE Float32 CASwapFloat32HostToBig(Float32 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}

CF_INLINE Float64 CASwapFloat64HostToBig(Float64 arg) {
#if defined(__BIG_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}

CF_INLINE Float32 CASwapFloat32LittleToHost(Float32 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}

CF_INLINE Float64 CASwapFloat64LittleToHost(Float64 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}

CF_INLINE Float32 CASwapFloat32HostToLittle(Float32 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat32(arg);
#endif
}

CF_INLINE Float64 CASwapFloat64HostToLittle(Float64 arg) {
#if defined(__LITTLE_ENDIAN__)
return arg;
#else
return CASwapFloat64(arg);
#endif
}


#if defined(__cplusplus)
}
#endif

#endif

+ 788
- 0
distrho/src/CoreAudio106/PublicUtility/CACFArray.cpp View File

@@ -0,0 +1,788 @@
/* 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 "CACFArray.h"

// PublicUtility Includes
#include "CACFDictionary.h"
#include "CACFNumber.h"
#include "CACFString.h"

//=============================================================================
// CACFArray
//=============================================================================

bool CACFArray::HasItem(const void* inItem) const
{
bool theAnswer = false;
if(mCFArray != NULL)
{
CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
theAnswer = CFArrayContainsValue(mCFArray, theRange, inItem);
}
return theAnswer;
}

bool CACFArray::GetIndexOfItem(const void* inItem, UInt32& outIndex) const
{
bool theAnswer = false;
outIndex = 0;
if(mCFArray != NULL)
{
CFRange theRange = { 0, CFArrayGetCount(mCFArray)};
CFIndex theIndex = CFArrayGetFirstIndexOfValue(mCFArray, theRange, inItem);
if(theIndex != -1)
{
theAnswer = true;
outIndex = ToUInt32(theIndex);
}
}
return theAnswer;
}

bool CACFArray::GetBool(UInt32 inIndex, bool& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inIndex, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
{
outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
theAnswer = true;
}
else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
SInt32 theNumericValue = 0;
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
outValue = theNumericValue != 0;
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetSInt32(UInt32 inIndex, SInt32& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetUInt32(UInt32 inIndex, UInt32& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt32Type, &outItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetSInt64(UInt32 inIndex, SInt64& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetUInt64(UInt32 inIndex, UInt64& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberSInt64Type, &outItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetFloat32(UInt32 inIndex, Float32& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat32Type, &outItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetFloat64(UInt32 inIndex, Float64& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theItem), kCFNumberFloat64Type, &outItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetString(UInt32 inIndex, CFStringRef& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
{
outItem = static_cast<CFStringRef>(theItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetArray(UInt32 inIndex, CFArrayRef& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
{
outItem = static_cast<CFArrayRef>(theItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
{
outItem = static_cast<CFDictionaryRef>(theItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetData(UInt32 inIndex, CFDataRef& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFDataGetTypeID()))
{
outItem = static_cast<CFDataRef>(theItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const
{
bool theAnswer = false;
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFUUIDGetTypeID()))
{
outItem = static_cast<CFUUIDRef>(theItem);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFArray::GetCFType(UInt32 inIndex, CFTypeRef& outItem) const
{
bool theAnswer = false;
if((mCFArray != NULL) && (inIndex < GetNumberItems()))
{
outItem = CFArrayGetValueAtIndex(mCFArray, inIndex);
theAnswer = outItem != NULL;
}
return theAnswer;
}

void CACFArray::GetCACFString(UInt32 inIndex, CACFString& outItem) const
{
outItem = static_cast<CFStringRef>(NULL);
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFStringGetTypeID()))
{
outItem = static_cast<CFStringRef>(theItem);
}
}
}

void CACFArray::GetCACFArray(UInt32 inIndex, CACFArray& outItem) const
{
outItem = static_cast<CFArrayRef>(NULL);
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFArrayGetTypeID()))
{
outItem = static_cast<CFArrayRef>(theItem);
}
}
}

void CACFArray::GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const
{
outItem = static_cast<CFDictionaryRef>(NULL);
CFTypeRef theItem = NULL;
if(GetCFType(inIndex, theItem))
{
if((theItem != NULL) && (CFGetTypeID(theItem) == CFDictionaryGetTypeID()))
{
outItem = static_cast<CFDictionaryRef>(theItem);
}
}
}

bool CACFArray::AppendBool(bool inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFBoolean theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFBoolean());
}
}
return theAnswer;
}

bool CACFArray::AppendSInt32(SInt32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::AppendUInt32(UInt32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::AppendSInt64(SInt64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::AppendUInt64(UInt64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::AppendFloat32(Float32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::AppendFloat64(Float64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = AppendCFType(theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::AppendString(const CFStringRef inItem)
{
return AppendCFType(inItem);
}

bool CACFArray::AppendArray(const CFArrayRef inItem)
{
return AppendCFType(inItem);
}

bool CACFArray::AppendDictionary(const CFDictionaryRef inItem)
{
return AppendCFType(inItem);
}

bool CACFArray::AppendData(const CFDataRef inItem)
{
return AppendCFType(inItem);
}

bool CACFArray::AppendCFType(const CFTypeRef inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CFArrayAppendValue(mCFArray, inItem);
theAnswer = true;
}
return theAnswer;
}

bool CACFArray::InsertBool(UInt32 inIndex, bool inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFBoolean theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFBoolean());
}
}
return theAnswer;
}

bool CACFArray::InsertSInt32(UInt32 inIndex, SInt32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::InsertUInt32(UInt32 inIndex, UInt32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::InsertSInt64(UInt32 inIndex, SInt64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::InsertUInt64(UInt32 inIndex, UInt64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::InsertFloat32(UInt32 inIndex, Float32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::InsertFloat64(UInt32 inIndex, Float64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = InsertCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::InsertString(UInt32 inIndex, const CFStringRef inItem)
{
return InsertCFType(inIndex, inItem);
}

bool CACFArray::InsertArray(UInt32 inIndex, const CFArrayRef inItem)
{
return InsertCFType(inIndex, inItem);
}

bool CACFArray::InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
{
return InsertCFType(inIndex, inItem);
}

bool CACFArray::InsertData(UInt32 inIndex, const CFDataRef inItem)
{
return InsertCFType(inIndex, inItem);
}

bool CACFArray::InsertCFType(UInt32 inIndex, const CFTypeRef inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable)
{
if(inIndex < GetNumberItems())
{
CFArrayInsertValueAtIndex(mCFArray, inIndex, inItem);
}
else
{
CFArrayAppendValue(mCFArray, inItem);
}
theAnswer = true;
}
return theAnswer;
}

bool CACFArray::SetBool(UInt32 inIndex, bool inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFBoolean theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFBoolean());
}
}
return theAnswer;
}

bool CACFArray::SetSInt32(UInt32 inIndex, SInt32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::SetUInt32(UInt32 inIndex, UInt32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::SetSInt64(UInt32 inIndex, SInt64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::SetUInt64(UInt32 inIndex, UInt64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::SetFloat32(UInt32 inIndex, Float32 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::SetFloat64(UInt32 inIndex, Float64 inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CACFNumber theItem(inItem);
if(theItem.IsValid())
{
theAnswer = SetCFType(inIndex, theItem.GetCFNumber());
}
}
return theAnswer;
}

bool CACFArray::SetString(UInt32 inIndex, const CFStringRef inItem)
{
return SetCFType(inIndex, inItem);
}

bool CACFArray::SetArray(UInt32 inIndex, const CFArrayRef inItem)
{
return SetCFType(inIndex, inItem);
}

bool CACFArray::SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem)
{
return SetCFType(inIndex, inItem);
}

bool CACFArray::SetData(UInt32 inIndex, const CFDataRef inItem)
{
return SetCFType(inIndex, inItem);
}

bool CACFArray::SetCFType(UInt32 inIndex, const CFTypeRef inItem)
{
bool theAnswer = false;
if((mCFArray != NULL) && mMutable && (inIndex <= GetNumberItems()))
{
CFArraySetValueAtIndex(mCFArray, inIndex, inItem);
theAnswer = true;
}
return theAnswer;
}

+ 186
- 0
distrho/src/CoreAudio106/PublicUtility/CACFArray.h View File

@@ -0,0 +1,186 @@
/* 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.
*/
#if !defined(__CACFArray_h__)
#define __CACFArray_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#else
#include <CoreAudioTypes.h>
#include <CoreFoundation.h>
#endif

#include "CADebugMacros.h"

//=============================================================================
// Types
//=============================================================================

class CACFDictionary;
class CACFString;

//=============================================================================
// CACFArray
//=============================================================================

class CACFArray
{

// Construction/Destruction
public:
CACFArray(bool inRelease = true) : mCFArray(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
CACFArray(UInt32 inMaxNumberItems, bool inRelease) : mCFArray(CFArrayCreateMutable(NULL, inMaxNumberItems, &kCFTypeArrayCallBacks)), mRelease(inRelease), mMutable(true) {}
CACFArray(CFArrayRef inCFArray, bool inRelease) : mCFArray(const_cast<CFMutableArrayRef>(inCFArray)), mRelease(inRelease), mMutable(false) {}
CACFArray(CFMutableArrayRef inCFArray, bool inRelease) : mCFArray(inCFArray), mRelease(inRelease), mMutable(true) {}
CACFArray(const CACFArray& inArray) : mCFArray(inArray.mCFArray), mRelease(inArray.mRelease), mMutable(inArray.mMutable) { Retain(); }
CACFArray& operator=(const CACFArray& inArray) { Release(); mCFArray = inArray.mCFArray; mRelease = inArray.mRelease; mMutable = inArray.mMutable; Retain(); return *this; }
CACFArray& operator=(CFArrayRef inCFArray) { Release(); mCFArray = const_cast<CFMutableArrayRef>(inCFArray); mMutable = false; Retain(); return *this; }
CACFArray& operator=(CFMutableArrayRef inCFArray) { Release(); mCFArray = inCFArray; mMutable = true; Retain(); return *this; }
~CACFArray() { Release(); }

private:
void Retain() { if(mRelease && (mCFArray != NULL)) { CFRetain(mCFArray); } }
void Release() { if(mRelease && (mCFArray != NULL)) { CFRelease(mCFArray); } }
// Attributes
public:
bool IsValid() const { return mCFArray != NULL; }
bool IsMutable() const { return mMutable; }
bool CanModify() const { return mMutable && (mCFArray != NULL); }
bool WillRelease() const { return mRelease; }
void ShouldRelease(bool inRelease) { mRelease = inRelease; }
CFTypeID GetTypeID() const { return CFGetTypeID(mCFArray); }
CFArrayRef GetCFArray() const { return mCFArray; }
CFArrayRef CopyCFArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
CFMutableArrayRef GetCFMutableArray() const { return mCFArray; }
CFMutableArrayRef CopyCFMutableArray() const { if(mCFArray != NULL) { CFRetain(mCFArray); } return mCFArray; }
CFPropertyListRef AsPropertyList() const { return mCFArray; }

void SetCFMutableArrayFromCopy(CFArrayRef inArray, bool inRelease = true) { Release(); mCFArray = CFArrayCreateMutableCopy(NULL, 0, inArray); mMutable = true; mRelease = inRelease; }

// Item Operations
public:
UInt32 GetNumberItems() const { UInt32 theAnswer = 0; if(mCFArray != NULL) { theAnswer = ToUInt32(CFArrayGetCount(mCFArray)); } return theAnswer; }
bool HasItem(const void* inItem) const;
void RemoveItem(const void* inItem) { UInt32 theIndex; if(CanModify() && GetIndexOfItem(inItem, theIndex)) { RemoveItemAtIndex(theIndex); } }
bool GetIndexOfItem(const void* inItem, UInt32& outIndex) const;
void RemoveItemAtIndex(UInt32 inIndex) { if(CanModify()) { CFArrayRemoveValueAtIndex(mCFArray, inIndex); } }
void Clear() { if(CanModify()) { CFArrayRemoveAllValues(mCFArray); } }
void Sort(CFComparatorFunction inCompareFunction) { if(CanModify()) { CFRange theRange = { 0, CFArrayGetCount(mCFArray) }; CFArraySortValues(mCFArray, theRange, inCompareFunction, NULL); } }
void SortNumbers() { Sort((CFComparatorFunction)CFNumberCompare); }
void SortStrings() { Sort((CFComparatorFunction)CFStringCompare); }
bool GetBool(UInt32 inIndex, bool& outValue) const;
bool GetSInt32(UInt32 inIndex, SInt32& outItem) const;
bool GetUInt32(UInt32 inIndex, UInt32& outItem) const;
bool GetSInt64(UInt32 inIndex, SInt64& outItem) const;
bool GetUInt64(UInt32 inIndex, UInt64& outItem) const;
bool GetFloat32(UInt32 inIndex, Float32& outItem) const;
bool GetFloat64(UInt32 inIndex, Float64& outItem) const;
bool GetString(UInt32 inIndex, CFStringRef& outItem) const;
bool GetArray(UInt32 inIndex, CFArrayRef& outItem) const;
bool GetDictionary(UInt32 inIndex, CFDictionaryRef& outItem) const;
bool GetData(UInt32 inIndex, CFDataRef& outItem) const;
bool GetUUID(UInt32 inIndex, CFUUIDRef& outItem) const;
bool GetCFType(UInt32 inIndex, CFTypeRef& outItem) const;
void GetCACFString(UInt32 inIndex, CACFString& outItem) const;
void GetCACFArray(UInt32 inIndex, CACFArray& outItem) const;
void GetCACFDictionary(UInt32 inIndex, CACFDictionary& outItem) const;
bool AppendBool(bool inItem);
bool AppendSInt32(SInt32 inItem);
bool AppendUInt32(UInt32 inItem);
bool AppendSInt64(SInt64 inItem);
bool AppendUInt64(UInt64 inItem);
bool AppendFloat32(Float32 inItem);
bool AppendFloat64(Float64 inItem);
bool AppendString(const CFStringRef inItem);
bool AppendArray(const CFArrayRef inItem);
bool AppendDictionary(const CFDictionaryRef inItem);
bool AppendData(const CFDataRef inItem);
bool AppendCFType(const CFTypeRef inItem);
bool InsertBool(UInt32 inIndex, bool inItem);
bool InsertSInt32(UInt32 inIndex, SInt32 inItem);
bool InsertUInt32(UInt32 inIndex, UInt32 inItem);
bool InsertSInt64(UInt32 inIndex, SInt64 inItem);
bool InsertUInt64(UInt32 inIndex, UInt64 inItem);
bool InsertFloat32(UInt32 inIndex, Float32 inItem);
bool InsertFloat64(UInt32 inIndex, Float64 inItem);
bool InsertString(UInt32 inIndex, const CFStringRef inItem);
bool InsertArray(UInt32 inIndex, const CFArrayRef inItem);
bool InsertDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
bool InsertData(UInt32 inIndex, const CFDataRef inItem);
bool InsertCFType(UInt32 inIndex, const CFTypeRef inItem);
bool SetBool(UInt32 inIndex, bool inItem);
bool SetSInt32(UInt32 inIndex, SInt32 inItem);
bool SetUInt32(UInt32 inIndex, UInt32 inItem);
bool SetSInt64(UInt32 inIndex, SInt64 inItem);
bool SetUInt64(UInt32 inIndex, UInt64 inItem);
bool SetFloat32(UInt32 inIndex, Float32 inItem);
bool SetFloat64(UInt32 inIndex, Float64 inItem);
bool SetString(UInt32 inIndex, const CFStringRef inItem);
bool SetArray(UInt32 inIndex, const CFArrayRef inItem);
bool SetDictionary(UInt32 inIndex, const CFDictionaryRef inItem);
bool SetData(UInt32 inIndex, const CFDataRef inItem);
bool SetCFType(UInt32 inIndex, const CFTypeRef inItem);

// Implementation
private:
CFMutableArrayRef mCFArray;
bool mRelease;
bool mMutable;
};

#endif

+ 101
- 0
distrho/src/CoreAudio106/PublicUtility/CACFData.h View File

@@ -0,0 +1,101 @@
/* 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.
*/
#if !defined(__CACFData_h__)
#define __CACFData_h__

//=============================================================================
// Includes
//=============================================================================

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CFData.h>
#else
#include <CoreAudioTypes.h>
#include <CFData.h>
#endif

#include "CADebugMacros.h"

//=============================================================================
// CACFData
//=============================================================================

class CACFData
{

// Construction/Destruction
public:
CACFData(CFDataRef inCFData, bool inWillRelease = true) : mCFData(inCFData), mWillRelease(inWillRelease) {}
CACFData(const void* inData, UInt32 inDataSize) : mCFData(NULL), mWillRelease(true) { mCFData = CFDataCreate(NULL, static_cast<const UInt8*>(inData), inDataSize); }
~CACFData() { Release(); }
CACFData(const CACFData& inNumber) : mCFData(inNumber.mCFData), mWillRelease(inNumber.mWillRelease) { Retain(); }
CACFData& operator=(const CACFData& inNumber) { Release(); mCFData = inNumber.mCFData; mWillRelease = inNumber.mWillRelease; Retain(); return *this; }
CACFData& operator=(CFDataRef inCFData) { Release(); mCFData = inCFData; mWillRelease = true; return *this; }

private:
void Retain() { if(mWillRelease && (mCFData != NULL)) { CFRetain(mCFData); } }
void Release() { if(mWillRelease && (mCFData != NULL)) { CFRelease(mCFData); } }
CFDataRef mCFData;
bool mWillRelease;

// Operations
public:
void AllowRelease() { mWillRelease = true; }
void DontAllowRelease() { mWillRelease = false; }
bool IsValid() { return mCFData != NULL; }

// Value Access
public:
CFDataRef GetCFData() const { return mCFData; }
CFDataRef CopyCFData() const { if(mCFData != NULL) { CFRetain(mCFData); } return mCFData; }
UInt32 GetSize() const { return ToUInt32(CFDataGetLength(mCFData)); }
const void* GetDataPtr() const { return CFDataGetBytePtr(mCFData); }
void CopyData(UInt32 inStartOffset, void* outData, UInt32 inDataSize) const { CFRange theRange = { inStartOffset, inDataSize }; CFDataGetBytes(mCFData, theRange, static_cast<UInt8*>(outData)); }
SInt32 GetSInt32() const { SInt32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(SInt32)); return theAnswer; }
Float32 GetFloat32() const { Float32 theAnswer = 0; CopyData(0, &theAnswer, SizeOf32(Float32)); return theAnswer; }

};

#endif

+ 561
- 0
distrho/src/CoreAudio106/PublicUtility/CACFDictionary.cpp View File

@@ -0,0 +1,561 @@
/* 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 "CACFDictionary.h"

// PublicUtility Includes
#include "CACFArray.h"
#include "CACFNumber.h"
#include "CACFString.h"

//=============================================================================
// CACFDictionary
//=============================================================================

bool CACFDictionary::HasKey(const CFStringRef inKey) const
{
return CFDictionaryContainsKey(mCFDictionary, inKey) != 0;
}

UInt32 CACFDictionary::Size () const
{
return ToUInt32(CFDictionaryGetCount(mCFDictionary));
}

void CACFDictionary::GetKeys (const void **keys) const
{
CFDictionaryGetKeysAndValues(mCFDictionary, keys, NULL);
}

bool CACFDictionary::GetBool(const CFStringRef inKey, bool& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFBooleanGetTypeID()))
{
outValue = CFBooleanGetValue(static_cast<CFBooleanRef>(theValue));
theAnswer = true;
}
else if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
SInt32 theNumericValue = 0;
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &theNumericValue);
outValue = theNumericValue != 0;
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt32Type, &outValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &outValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat32Type, &outValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberFloat64Type, &outValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetFixed64(const CFStringRef inKey, Float64& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFNumberGetTypeID()))
{
SInt64 theFixed64 = 0;
CFNumberGetValue(static_cast<CFNumberRef>(theValue), kCFNumberSInt64Type, &theFixed64);
outValue = static_cast<Float64>(theFixed64 >> 32);
outValue += static_cast<Float64>(theFixed64 & 0x00000000FFFFFFFFLL) / static_cast<Float64>(0x0000000100000000LL);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
{
outValue = static_cast<CFStringRef>(theValue);
theAnswer = true;
}
}
return theAnswer;
}
bool CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
{
outValue = static_cast<CFArrayRef>(theValue);
theAnswer = true;
}
}
return theAnswer;
}
bool CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
{
outValue = static_cast<CFDictionaryRef>(theValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const
{
bool theAnswer = false;
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFDataGetTypeID()))
{
outValue = static_cast<CFDataRef>(theValue);
theAnswer = true;
}
}
return theAnswer;
}

bool CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const
{
bool theAnswer = false;
if(mCFDictionary != NULL)
{
outValue = CFDictionaryGetValue(mCFDictionary, inKey);
theAnswer = (outValue != NULL);
}
return theAnswer;
}

bool CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const
{
bool theAnswer = false;
if(mCFDictionary != NULL)
{
CACFString theKey(inKey);
if(theKey.IsValid())
{
theAnswer = GetCFType(theKey.GetCFString(), outValue);
}
}
return theAnswer;
}

void CACFDictionary::GetCACFString(const CFStringRef inKey, CACFString& outValue) const
{
outValue = static_cast<CFStringRef>(NULL);
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFStringGetTypeID()))
{
outValue = static_cast<CFStringRef>(theValue);
}
}
}
void CACFDictionary::GetCACFArray(const CFStringRef inKey, CACFArray& outValue) const
{
outValue = static_cast<CFArrayRef>(NULL);
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFArrayGetTypeID()))
{
outValue = static_cast<CFArrayRef>(theValue);
}
}
}
void CACFDictionary::GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outValue) const
{
outValue = static_cast<CFDictionaryRef>(NULL);
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
if((theValue != NULL) && (CFGetTypeID(theValue) == CFDictionaryGetTypeID()))
{
outValue = static_cast<CFDictionaryRef>(theValue);
}
}
}

bool CACFDictionary::AddBool(const CFStringRef inKey, bool inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFBoolean theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFBoolean());
}
return theAnswer;
}

bool CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
return theAnswer;
}

bool CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
return theAnswer;
}

bool CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
return theAnswer;
}

bool CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
return theAnswer;
}

bool CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
return theAnswer;
}

bool CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
return theAnswer;
}

bool CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
return theAnswer;
}

bool CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
return theAnswer;
}

bool CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
return theAnswer;
}

bool CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
return theAnswer;
}

bool CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
return theAnswer;
}

bool CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CFDictionarySetValue(mCFDictionary, inKey, inValue);
theAnswer = true;
}
return theAnswer;
}

bool CACFDictionary::AddURL(const CFStringRef inKey, const CFURLRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CFDictionarySetValue(mCFDictionary, inKey, inValue);
theAnswer = true;
}
return theAnswer;
}

bool CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFString theKey(inKey);
if(theKey.IsValid())
{
theAnswer = AddCFType(theKey.GetCFString(), inValue);
}
}
return theAnswer;
}

bool CACFDictionary::AddCString(const CFStringRef inKey, const char* inValue)
{
bool theAnswer = false;
if(mMutable && (mCFDictionary != NULL))
{
CACFString theValue(inValue);
if(theValue.IsValid())
{
theAnswer = AddCFType(inKey, theValue.GetCFString());
}
}
return theAnswer;
}

+ 162
- 0
distrho/src/CoreAudio106/PublicUtility/CACFDictionary.h View File

@@ -0,0 +1,162 @@
/* 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.
*/
#if !defined(__CACFDictionary_h__)
#define __CACFDictionary_h__

//=============================================================================
// Includes
//=============================================================================

// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#else
#include <CoreFoundation.h>
#endif

//=============================================================================
// Types
//=============================================================================

class CACFArray;
class CACFString;

//=============================================================================
// CACFDictionary
//=============================================================================

class CACFDictionary
{

// Construction/Destruction
public:
CACFDictionary(bool inRelease = true) : mCFDictionary(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)), mRelease(inRelease), mMutable(true) {}
CACFDictionary(CFDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(const_cast<CFMutableDictionaryRef>(inCFDictionary)), mRelease(inRelease), mMutable(false) {}
CACFDictionary(CFMutableDictionaryRef inCFDictionary, bool inRelease) : mCFDictionary(inCFDictionary), mRelease(inRelease), mMutable(true) {}
CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { Retain(); }
CACFDictionary& operator=(const CACFDictionary& inDictionary) { Release(); mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; Retain(); return *this; }
CACFDictionary& operator=(CFDictionaryRef inDictionary) { Release(); mCFDictionary = const_cast<CFMutableDictionaryRef>(inDictionary); mMutable = false; Retain(); return *this; }
CACFDictionary& operator=(CFMutableDictionaryRef inDictionary) { Release(); mCFDictionary = inDictionary; mMutable = true; Retain(); return *this; }
~CACFDictionary() { Release(); }

private:
void Retain() { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } }
void Release() { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } }
// Attributes
public:
bool IsValid() const { return mCFDictionary != NULL; }
bool IsMutable() const { return mMutable;}
bool CanModify() const { return mMutable && (mCFDictionary != NULL); }
bool WillRelease() const { return mRelease; }
void ShouldRelease(bool inRelease) { mRelease = inRelease; }
CFDictionaryRef GetDict() const { return mCFDictionary; }
CFDictionaryRef GetCFDictionary() const { return mCFDictionary; }
CFDictionaryRef CopyCFDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }

CFMutableDictionaryRef GetMutableDict() { return mCFDictionary; }
CFMutableDictionaryRef GetCFMutableDictionary() const { return mCFDictionary; }
CFMutableDictionaryRef CopyCFMutableDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
void SetCFMutableDictionaryFromCopy(CFDictionaryRef inDictionary, bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutableCopy(NULL, 0, inDictionary); mMutable = true; mRelease = inRelease; }
void SetCFMutableDictionaryToEmpty(bool inRelease = true) { Release(); mCFDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); mMutable = true; mRelease = inRelease; }

CFPropertyListRef AsPropertyList() const { return mCFDictionary; }
OSStatus GetDictIfMutable(CFMutableDictionaryRef& outDict) const { OSStatus theAnswer = -1; if(mMutable) { outDict = mCFDictionary; theAnswer = 0; } return theAnswer; }

// Item Operations
public:
bool HasKey(const CFStringRef inKey) const;
UInt32 Size() const;
void GetKeys(const void** keys) const;
bool GetBool(const CFStringRef inKey, bool& outValue) const;
bool GetSInt32(const CFStringRef inKey, SInt32& outValue) const;
bool GetUInt32(const CFStringRef inKey, UInt32& outValue) const;
bool GetSInt64(const CFStringRef inKey, SInt64& outValue) const;
bool GetUInt64(const CFStringRef inKey, UInt64& outValue) const;
bool GetFloat32(const CFStringRef inKey, Float32& outValue) const;
bool GetFloat64(const CFStringRef inKey, Float64& outValue) const;
bool GetFixed64(const CFStringRef inKey, Float64& outValue) const;
bool GetString(const CFStringRef inKey, CFStringRef& outValue) const;
bool GetArray(const CFStringRef inKey, CFArrayRef& outValue) const;
bool GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const;
bool GetData(const CFStringRef inKey, CFDataRef& outValue) const;
bool GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const;
bool GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const;

void GetCACFString(const CFStringRef inKey, CACFString& outItem) const;
void GetCACFArray(const CFStringRef inKey, CACFArray& outItem) const;
void GetCACFDictionary(const CFStringRef inKey, CACFDictionary& outItem) const;
bool AddBool(const CFStringRef inKey, bool inValue);
bool AddSInt32(const CFStringRef inKey, SInt32 inValue);
bool AddUInt32(const CFStringRef inKey, UInt32 inValue);
bool AddSInt64(const CFStringRef inKey, SInt64 inValue);
bool AddUInt64(const CFStringRef inKey, UInt64 inValue);
bool AddFloat32(const CFStringRef inKey, Float32 inValue);
bool AddFloat64(const CFStringRef inKey, Float64 inValue);
bool AddNumber(const CFStringRef inKey, const CFNumberRef inValue);
bool AddString(const CFStringRef inKey, const CFStringRef inValue);
bool AddArray(const CFStringRef inKey, const CFArrayRef inValue);
bool AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue);
bool AddData(const CFStringRef inKey, const CFDataRef inValue);
bool AddCFType(const CFStringRef inKey, const CFTypeRef inValue);
bool AddURL(const CFStringRef inKey, const CFURLRef inValue);
bool AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue);
bool AddCString(const CFStringRef inKey, const char* inValue);

void RemoveKey(const CFStringRef inKey) { if(CanModify()) { CFDictionaryRemoveValue(mCFDictionary, inKey); } }
void Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } }
void Show() { CFShow(mCFDictionary); }
// Implementation
private:
CFMutableDictionaryRef mCFDictionary;
bool mRelease;
bool mMutable;
};

#endif //__CACFDictionary_h__

+ 100
- 0
distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.cpp View File

@@ -0,0 +1,100 @@
/* 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 "CACFDistributedNotification.h"

// PublicUtility Includes
#include "CADebugMacros.h"

//==================================================================================================
// CACFDistributedNotification
//==================================================================================================

void CACFDistributedNotification::AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior)
{
#if !TARGET_OS_IPHONE
CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
CFNotificationSuspensionBehavior theSuspensionBehavior = inSuspensionBehavior;
#else
CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationSuspensionBehavior theSuspensionBehavior = 0;
#endif
CFNotificationCenterAddObserver(theCenter, inObserver, inCallback, inName, NULL, theSuspensionBehavior);
}

void CACFDistributedNotification::RemoveObserver(const void* inObserver, CFStringRef inName)
{
#if !TARGET_OS_IPHONE
CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
#else
CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
#endif
CFNotificationCenterRemoveObserver(theCenter, inObserver, inName, NULL);
}

void CACFDistributedNotification::PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions)
{
#if !TARGET_OS_IPHONE
CFNotificationCenterRef theCenter = CFNotificationCenterGetDistributedCenter();
CFDictionaryRef theUserInfo = inUserInfo;
CFOptionFlags theFlags = kCFNotificationDeliverImmediately;
if(inPostToAllSessions)
{
theFlags += kCFNotificationPostToAllSessions;
}
#else
// flag unsupported features
Assert(inUserInfo == NULL, "CACFDistributedNotification::PostNotification: distributed notifications do not support a payload");
Assert(inPostToAllSessions, "CACFDistributedNotification::PostNotification: distributed notifications do not support per-session delivery");
CFNotificationCenterRef theCenter = CFNotificationCenterGetDarwinNotifyCenter();
CFDictionaryRef theUserInfo = NULL;
CFOptionFlags theFlags = 0;
#endif
CFNotificationCenterPostNotificationWithOptions(theCenter, inName, NULL, theUserInfo, theFlags);
}

+ 67
- 0
distrho/src/CoreAudio106/PublicUtility/CACFDistributedNotification.h View File

@@ -0,0 +1,67 @@
/* 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.
*/
#if !defined(__CACFDistributedNotification_h__)
#define __CACFDistributedNotification_h__

//==================================================================================================
// Includes
//==================================================================================================

// System Includes
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>

//==================================================================================================
// CACFDistributedNotification
//==================================================================================================

class CACFDistributedNotification
{

// Operations
public:
static void AddObserver(const void* inObserver, CFNotificationCallback inCallback, CFStringRef inName, CFNotificationSuspensionBehavior inSuspensionBehavior = CFNotificationSuspensionBehaviorCoalesce);
static void RemoveObserver(const void* inObserver, CFStringRef inName);
static void PostNotification(CFStringRef inName, CFDictionaryRef inUserInfo, bool inPostToAllSessions);

};

#endif

+ 138
- 0
distrho/src/CoreAudio106/PublicUtility/CACFMachPort.cpp View File

@@ -0,0 +1,138 @@
/* 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
//==================================================================================================

#include "CACFMachPort.h"
#include "CAException.h"
#include "CADebugMacros.h"

//==================================================================================================
// CACFMachPort
//==================================================================================================

// This constructor is the short form. The CFMachPort will own the send and receive rights.
CACFMachPort::CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData)
:
mMachPort(NULL),
mRunLoopSource(NULL),
mOwnsPort(true)
{
CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort(s): couldn't create the CFMachPort");

mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
if(mRunLoopSource == NULL)
{
CFMachPortInvalidate(mMachPort);
CFRelease(mMachPort);
mMachPort = NULL;
DebugMessage("CACFMachPort::CACFMachPort(s): couldn't create the CFRunLoopSource");
throw CAException('what');
}
}

// This constructor is the general form:
// - If inMachPort is MACH_PORT_NULL, the CFMachPort will allocate the port and own the send and
// receive rights. Otherwise, the caller owns the rights and is resposible for cleaning them
// up.
// - If inCallBack is NULL, then received messages will just get swallowed by the CFMachPort.
// This is useful if you are only using the CFMachPort to track port death (aka invalidation).
// - If inInvalidationCallBack is non-NULL, then it will be installed as the invalidation
// callback on the CFMachPort.
CACFMachPort::CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData)
:
mMachPort(NULL),
mRunLoopSource(NULL),
mOwnsPort(false)
{
CFMachPortContext theContext = { 1, inUserData, NULL, NULL, NULL };
if(inMachPort == MACH_PORT_NULL)
{
mMachPort = CFMachPortCreate(NULL, inCallBack, &theContext, NULL);
ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort");
mOwnsPort = true;
}
else
{
mMachPort = CFMachPortCreateWithPort(NULL, inMachPort, inCallBack, &theContext, NULL);
ThrowIfNULL(mMachPort, CAException('what'), "CACFMachPort::CACFMachPort: couldn't create the CFMachPort with a port");
mOwnsPort = false;
}

mRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mMachPort, 0);
if(mRunLoopSource == NULL)
{
if(mOwnsPort)
{
CFMachPortInvalidate(mMachPort);
}
CFRelease(mMachPort);
mMachPort = NULL;
DebugMessage("CACFMachPort::CACFMachPort: couldn't create the CFRunLoopSource");
throw CAException('what');
}
if(inInvalidationCallBack != NULL)
{
CFMachPortSetInvalidationCallBack(mMachPort, inInvalidationCallBack);
}
}

CACFMachPort::~CACFMachPort()
{
if(mRunLoopSource != NULL)
{
CFRelease(mRunLoopSource);
}
if(mMachPort != NULL)
{
if(mOwnsPort)
{
CFMachPortInvalidate(mMachPort);
}
CFRelease(mMachPort);
}
}

+ 83
- 0
distrho/src/CoreAudio106/PublicUtility/CACFMachPort.h View File

@@ -0,0 +1,83 @@
/* 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.
*/
#if !defined(__CACFMachPort_h__)
#define __CACFMachPort_h__

//==================================================================================================
// Includes
//==================================================================================================

#include <CoreFoundation/CFMachPort.h>

//==================================================================================================
// CACFMachPort
//
// This class wraps a CFMachPort.
//
// Note that when you create a CFMachPort object, CF will attach the run loop source for the the
// Mach Port that handles Port Death notifications (aka the Invalidation Callback) to the current
// thread's run loop. This is something over which there is no control, so be sure to create the
// CFMachPort on the thread on which you want to handle Port Death notificaitons on.
//==================================================================================================

class CACFMachPort
{

// Construction/Destruction
public:
CACFMachPort(CFMachPortCallBack inCallBack, void* inUserData = NULL);
CACFMachPort(mach_port_t inMachPort, CFMachPortCallBack inCallBack, CFMachPortInvalidationCallBack inInvalidationCallBack, void* inUserData);
virtual ~CACFMachPort();

// Attributes
public:
CFMachPortRef GetMachPortRef() const { return mMachPort; }
mach_port_t GetMachPort() const { return CFMachPortGetPort(mMachPort); }
CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; }

// Implementation
protected:
CFMachPortRef mMachPort;
CFRunLoopSourceRef mRunLoopSource;
bool mOwnsPort;
};

#endif

+ 129
- 0
distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.cpp View File

@@ -0,0 +1,129 @@
/* 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
//=============================================================================

#include "CACFMessagePort.h"
#include "CADebugMacros.h"
#include "CAException.h"

//=============================================================================
// CACFLocalMessagePort
//=============================================================================

CACFLocalMessagePort::CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData)
:
mMessagePort(NULL),
mRunLoopSource(NULL)
{
// create the CFMessagePort
CFMessagePortContext theContext = { 0, inUserData, NULL, NULL, NULL };
mMessagePort = CFMessagePortCreateLocal(NULL, inName, inPortCallBack, &theContext, NULL);
if(mMessagePort != NULL)
{
// add the invalidation callback, if any
if(inInvalidationCallBack != NULL)
{
CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack);
}
// get the run loop source
mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
}
}

CACFLocalMessagePort::~CACFLocalMessagePort()
{
if(mMessagePort != NULL)
{
CFMessagePortInvalidate(mMessagePort);
CFRelease(mMessagePort);
}
if(mRunLoopSource != NULL)
{
CFRelease(mRunLoopSource);
}
}

//=============================================================================
// CACFRemoteMessagePort
//=============================================================================

CACFRemoteMessagePort::CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack)
:
mMessagePort(NULL),
mRunLoopSource(NULL)
{
// create the CFMessagePort
mMessagePort = CFMessagePortCreateRemote(NULL, inName);
if(mMessagePort != NULL)
{
// failure to create a remote port does not need to throw an exception
// because it isn't really an error since the port in question may not
// exist and this fact requires a more complex response than an excpeption
// provides for.
// add the invalidation callback, if any
if(inInvalidationCallBack != NULL)
{
CFMessagePortSetInvalidationCallBack(mMessagePort, inInvalidationCallBack);
}
// get the run loop source
mRunLoopSource = CFMessagePortCreateRunLoopSource(NULL, mMessagePort, 0);
}
}

CACFRemoteMessagePort::~CACFRemoteMessagePort()
{
if(mMessagePort != NULL)
{
//CFMessagePortInvalidate(mMessagePort);
CFRelease(mMessagePort);
}
if(mRunLoopSource != NULL)
{
CFRelease(mRunLoopSource);
}
}

+ 109
- 0
distrho/src/CoreAudio106/PublicUtility/CACFMessagePort.h View File

@@ -0,0 +1,109 @@
/* 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.
*/
#if !defined(__CACFMessagePort_h__)
#define __CACFMessagePort_h__

//=============================================================================
// Includes
//=============================================================================

#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CFMessagePort.h>
#else
#include <CFMessagePort.h>
#endif

//=============================================================================
// CACFLocalMessagePort
//=============================================================================

class CACFLocalMessagePort
{

// Construction/Destruction
public:
CACFLocalMessagePort(CFStringRef inName, CFMessagePortCallBack inPortCallBack, CFMessagePortInvalidationCallBack inInvalidationCallBack, void* inUserData = NULL);
virtual ~CACFLocalMessagePort();

// Attributes
public:
bool IsValid() const { return mMessagePort != NULL; }
CFMessagePortRef GetMessagePortRef() const { return mMessagePort; }
CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; }

// Implementation
protected:
CFMessagePortRef mMessagePort;
CFRunLoopSourceRef mRunLoopSource;

};

//=============================================================================
// CACFRemoteMessagePort
//=============================================================================

class CACFRemoteMessagePort
{

// Construction/Destruction
public:
CACFRemoteMessagePort(CFStringRef inName, CFMessagePortInvalidationCallBack inInvalidationCallBack);
virtual ~CACFRemoteMessagePort();

// Attributes
public:
bool IsValid() const { return mMessagePort != NULL; }
CFMessagePortRef GetMessagePortRef() const { return mMessagePort; }
CFRunLoopSourceRef GetRunLoopSource() const { return mRunLoopSource; }

// Operations
public:
SInt32 SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, NULL, NULL); }
SInt32 SendRequest(SInt32 inMessageID, CFDataRef inData, CFTimeInterval inSendTimeout, CFTimeInterval inReceiveTimout, CFStringRef inReplyMode, CFDataRef& outReturnData) const { return CFMessagePortSendRequest(mMessagePort, inMessageID, inData, inSendTimeout, inReceiveTimout, inReplyMode, &outReturnData); }

// Implementation
protected:
CFMessagePortRef mMessagePort;
CFRunLoopSourceRef mRunLoopSource;

};

#endif

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save