fix macOS build (following Projucer changes made in Windows, which removed /Applications/JUCE/modules from its headers). move JUCE headers under source control, so that Windows and macOS can both build against same version of JUCE. remove AUv3 target (I think it's an iOS thing, so it will never work with this macOS fluidsynth dylib).
This commit is contained in:
@ -0,0 +1,47 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
struct ModifierKeyProvider
|
||||
{
|
||||
virtual ~ModifierKeyProvider() {}
|
||||
virtual int getWin32Modifiers() const = 0;
|
||||
};
|
||||
|
||||
struct ModifierKeyReceiver
|
||||
{
|
||||
virtual ~ModifierKeyReceiver() {}
|
||||
virtual void setModifierKeyProvider (ModifierKeyProvider*) = 0;
|
||||
virtual void removeModifierKeyProvider() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
2166
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
Normal file
2166
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
140
modules/juce_audio_plugin_client/AU/AUResources.r
Normal file
140
modules/juce_audio_plugin_client/AU/AUResources.r
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
File: AUResources.r
|
||||
Abstract: AUResources.r
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// 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
|
File diff suppressed because it is too large
Load Diff
1055
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h
Normal file
1055
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,75 @@
|
||||
/*
|
||||
File: AUBaseHelper.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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"
|
||||
|
||||
// helpers for dealing with the file-references dictionary in an AUPreset
|
||||
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
|
||||
CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);
|
||||
|
||||
int AccessURLAsset(const CFURLRef inURL, int mode);
|
||||
|
||||
#if DEBUG
|
||||
void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // __AUBaseHelper_h__
|
@ -0,0 +1,219 @@
|
||||
/*
|
||||
File: AUBuffer.cpp
|
||||
Abstract: AUBuffer.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "AUBuffer.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
AUBufferList::~AUBufferList()
|
||||
{
|
||||
Deallocate();
|
||||
if (mPtrs)
|
||||
free(mPtrs);
|
||||
}
|
||||
|
||||
// a * b + c
|
||||
static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c)
|
||||
{
|
||||
if (a == 0 || b == 0) return c; // prevent zero divide
|
||||
|
||||
if (a > (0xFFFFFFFF - c) / b)
|
||||
throw std::bad_alloc();
|
||||
|
||||
return a * b + c;
|
||||
}
|
||||
|
||||
void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
|
||||
{
|
||||
UInt32 nStreams;
|
||||
if (format.IsInterleaved()) {
|
||||
nStreams = 1;
|
||||
} else {
|
||||
nStreams = format.mChannelsPerFrame;
|
||||
}
|
||||
|
||||
// careful -- the I/O thread could be running!
|
||||
if (nStreams > mAllocatedStreams) {
|
||||
size_t theHeaderSize = sizeof(AudioBufferList) - sizeof(AudioBuffer);
|
||||
mPtrs = (AudioBufferList *)CA_realloc(mPtrs,
|
||||
SafeMultiplyAddUInt32(nStreams, sizeof(AudioBuffer), theHeaderSize));
|
||||
mAllocatedStreams = nStreams;
|
||||
}
|
||||
UInt32 bytesPerStream = SafeMultiplyAddUInt32(nFrames, format.mBytesPerFrame, 0xF) & ~0xF;
|
||||
UInt32 nBytes = SafeMultiplyAddUInt32(nStreams, bytesPerStream, 0);
|
||||
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
|
@ -0,0 +1,269 @@
|
||||
/*
|
||||
File: AUBuffer.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __AUBuffer_h__
|
||||
#define __AUBuffer_h__
|
||||
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.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__
|
@ -0,0 +1,403 @@
|
||||
/*
|
||||
File: AUCarbonViewBase.cpp
|
||||
Abstract: AUCarbonViewBase.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "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 !__LP64__
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
#if !__LP64__
|
||||
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;
|
||||
#else
|
||||
return noErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus AUCarbonViewBase::CreateUI(Float32 inXOffset, Float32 inYOffset)
|
||||
{
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus AUCarbonViewBase::EmbedControl(ControlRef ctl)
|
||||
{
|
||||
#if !__LP64__
|
||||
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);
|
||||
#else
|
||||
return noErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUCarbonViewBase::AddCarbonControl(AUCarbonViewControl::ControlType type, const CAAUParameter ¶m, 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)
|
||||
{
|
||||
#if !__LP64__
|
||||
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 = { static_cast<CGFloat>(mBottomRight.h), static_cast<CGFloat>(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<65>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<65>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<65>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<65>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;
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
File: AUCarbonViewBase.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __AUCarbonViewBase_h__
|
||||
#define __AUCarbonViewBase_h__
|
||||
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.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__
|
@ -0,0 +1,710 @@
|
||||
/*
|
||||
File: AUCarbonViewControl.cpp
|
||||
Abstract: AUCarbonViewControl.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "AUCarbonViewControl.h"
|
||||
#include "AUCarbonViewBase.h"
|
||||
#include "AUViewLocalizedStringKeys.h"
|
||||
|
||||
AUCarbonViewControl::AUCarbonViewControl(AUCarbonViewBase *ownerView, AUParameterListenerRef listener, ControlType type, const CAAUParameter ¶m, ControlRef control) :
|
||||
mOwnerView(ownerView),
|
||||
mListener(listener),
|
||||
mType(type),
|
||||
mParam(param),
|
||||
mControl(control),
|
||||
mInControlInitialization(0)
|
||||
{
|
||||
#if !__LP64__
|
||||
SetControlReference(control, SRefCon(this));
|
||||
#endif
|
||||
}
|
||||
|
||||
AUCarbonViewControl::~AUCarbonViewControl()
|
||||
{
|
||||
AUListenerRemoveParameter(mListener, this, &mParam);
|
||||
}
|
||||
|
||||
AUCarbonViewControl* AUCarbonViewControl::mLastControl = NULL;
|
||||
|
||||
void AUCarbonViewControl::Bind()
|
||||
{
|
||||
#if !__LP64__
|
||||
mInControlInitialization = 1; // true
|
||||
AUListenerAddParameter(mListener, this, &mParam);
|
||||
// will cause an almost-immediate callback
|
||||
|
||||
EventTypeSpec events[] = {
|
||||
{ kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
|
||||
};
|
||||
|
||||
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
|
||||
|
||||
if (mType == kTypeContinuous || mType == kTypeText || mType == kTypeDiscrete) {
|
||||
EventTypeSpec controlEvents[] = {
|
||||
{ kEventClassControl, kEventControlHit },
|
||||
{ kEventClassControl, kEventControlClick },
|
||||
{ kEventClassControl, kEventControlTrack }
|
||||
};
|
||||
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(controlEvents), controlEvents);
|
||||
}
|
||||
|
||||
if (mType == kTypeText) {
|
||||
EventTypeSpec controlFocusEvents[] = {
|
||||
{ kEventClassControl, kEventControlSetFocusPart }
|
||||
};
|
||||
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(controlFocusEvents), controlFocusEvents);
|
||||
ControlKeyFilterUPP proc = mParam.ValuesHaveStrings() ? StdKeyFilterCallback : NumericKeyFilterCallback;
|
||||
// this will fail for a static text field
|
||||
SetControlData(mControl, 0, kControlEditTextKeyFilterTag, sizeof(proc), &proc);
|
||||
}
|
||||
|
||||
Update(true);
|
||||
mInControlInitialization = 0; // false
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUCarbonViewControl::ParameterToControl(Float32 paramValue)
|
||||
{
|
||||
#if !__LP64__
|
||||
++mInControlInitialization;
|
||||
switch (mType) {
|
||||
case kTypeContinuous:
|
||||
SetValueFract(AUParameterValueToLinear(paramValue, &mParam));
|
||||
break;
|
||||
case kTypeDiscrete:
|
||||
{
|
||||
long value = long(paramValue);
|
||||
|
||||
// special case [1] -- menu parameters
|
||||
if (mParam.HasNamedParams()) {
|
||||
// if we're dealing with menus they behave differently!
|
||||
// becaue setting min and max doesn't work correctly for the control value
|
||||
// first menu item always reports a control value of 1
|
||||
ControlKind ctrlKind;
|
||||
if (GetControlKind(mControl, &ctrlKind) == noErr) {
|
||||
if ((ctrlKind.kind == kControlKindPopupArrow)
|
||||
|| (ctrlKind.kind == kControlKindPopupButton))
|
||||
{
|
||||
value = value - long(mParam.ParamInfo().minValue) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// special case [2] -- Write-only boolean parameters
|
||||
AudioUnitParameterInfo AUPI = mParam.ParamInfo();
|
||||
|
||||
bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
|
||||
(AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
|
||||
!(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
|
||||
if (!isWriteOnlyBoolParameter) {
|
||||
SetValue (value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kTypeText:
|
||||
{
|
||||
CFStringRef cfstr = mParam.GetStringFromValueCopy(¶mValue);
|
||||
|
||||
if ( !(mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsWritable) //READ ONLY PARAMS
|
||||
&& (mParam.ParamInfo().flags & kAudioUnitParameterFlag_IsReadable))
|
||||
{
|
||||
if (mParam.GetParamTag()) {
|
||||
CFMutableStringRef str = CFStringCreateMutableCopy(NULL, 256, cfstr);
|
||||
CFRelease (cfstr);
|
||||
CFStringAppend (str, CFSTR(" "));
|
||||
CFStringAppend (str, mParam.GetParamTag());
|
||||
cfstr = str;
|
||||
}
|
||||
}
|
||||
SetTextValue(cfstr);
|
||||
CFRelease (cfstr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
--mInControlInitialization;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUCarbonViewControl::ControlToParameter()
|
||||
{
|
||||
#if !__LP64__
|
||||
if (mInControlInitialization)
|
||||
return;
|
||||
|
||||
switch (mType) {
|
||||
case kTypeContinuous:
|
||||
{
|
||||
double controlValue = GetValueFract();
|
||||
Float32 paramValue = AUParameterValueFromLinear(controlValue, &mParam);
|
||||
mParam.SetValue(mListener, this, paramValue);
|
||||
}
|
||||
break;
|
||||
case kTypeDiscrete:
|
||||
{
|
||||
long value = GetValue();
|
||||
|
||||
// special case [1] -- Menus
|
||||
if (mParam.HasNamedParams()) {
|
||||
// if we're dealing with menus they behave differently!
|
||||
// becaue setting min and max doesn't work correctly for the control value
|
||||
// first menu item always reports a control value of 1
|
||||
ControlKind ctrlKind;
|
||||
if (GetControlKind(mControl, &ctrlKind) == noErr) {
|
||||
if ((ctrlKind.kind == kControlKindPopupArrow)
|
||||
|| (ctrlKind.kind == kControlKindPopupButton))
|
||||
{
|
||||
value = value + long(mParam.ParamInfo().minValue) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// special case [2] -- Write-only boolean parameters
|
||||
AudioUnitParameterInfo AUPI = mParam.ParamInfo();
|
||||
|
||||
bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
|
||||
(AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
|
||||
!(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
|
||||
if (isWriteOnlyBoolParameter) {
|
||||
value = 1;
|
||||
}
|
||||
|
||||
mParam.SetValue (mListener, this, value);
|
||||
}
|
||||
break;
|
||||
case kTypeText:
|
||||
{
|
||||
Float32 val = mParam.GetValueFromString (GetTextValue());
|
||||
mParam.SetValue(mListener, this, (mParam.IsIndexedParam() ? (int)val : val));
|
||||
if (mParam.ValuesHaveStrings())
|
||||
ParameterToControl(val); //make sure we display the correct text (from the AU)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUCarbonViewControl::SetValueFract(double value)
|
||||
{
|
||||
#if !__LP64__
|
||||
SInt32 minimum = GetControl32BitMinimum(mControl);
|
||||
SInt32 maximum = GetControl32BitMaximum(mControl);
|
||||
SInt32 cval = SInt32(value * (maximum - minimum) + minimum + 0.5);
|
||||
SetControl32BitValue(mControl, cval);
|
||||
// printf("set: value=%lf, min=%ld, max=%ld, ctl value=%ld\n", value, minimum, maximum, cval);
|
||||
#endif
|
||||
}
|
||||
|
||||
double AUCarbonViewControl::GetValueFract()
|
||||
{
|
||||
#if !__LP64__
|
||||
SInt32 minimum = GetControl32BitMinimum(mControl);
|
||||
SInt32 maximum = GetControl32BitMaximum(mControl);
|
||||
SInt32 cval = GetControl32BitValue(mControl);
|
||||
double result = double(cval - minimum) / double(maximum - minimum);
|
||||
// printf("get: min=%ld, max=%ld, value=%ld, result=%f\n", minimum, maximum, cval, result);
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUCarbonViewControl::SetTextValue(CFStringRef cfstr)
|
||||
{
|
||||
#if !__LP64__
|
||||
verify_noerr(SetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr));
|
||||
#endif
|
||||
}
|
||||
|
||||
CFStringRef AUCarbonViewControl::GetTextValue()
|
||||
{
|
||||
#if !__LP64__
|
||||
CFStringRef cfstr;
|
||||
verify_noerr(GetControlData(mControl, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &cfstr, NULL));
|
||||
return cfstr;
|
||||
#else
|
||||
return CFSTR("");
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUCarbonViewControl::SetValue(long value)
|
||||
{
|
||||
#if !__LP64__
|
||||
SetControl32BitValue(mControl, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
long AUCarbonViewControl::GetValue()
|
||||
{
|
||||
#if !__LP64__
|
||||
return GetControl32BitValue(mControl);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Notes on event handling
|
||||
|
||||
Button (Click and release on button)
|
||||
kEventControlClick received
|
||||
kEventControlTrack received
|
||||
kEventControlValueFieldChanged received
|
||||
kEventControlHit received
|
||||
|
||||
Button (Click and release outside of button bounds)
|
||||
kEventControlClick received
|
||||
kEventControlTrack received
|
||||
|
||||
Slider (Click, drag, and release)
|
||||
kEventControlClick received
|
||||
kEventControlTrack received
|
||||
kEventControlValueFieldChanged received
|
||||
kEventControlValueFieldChanged received
|
||||
kEventControlHit received
|
||||
|
||||
Slider (Click, release without changing value)
|
||||
kEventControlClick received
|
||||
kEventControlTrack received
|
||||
*/
|
||||
bool AUCarbonViewControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
|
||||
{
|
||||
UInt32 eclass = GetEventClass(event);
|
||||
UInt32 ekind = GetEventKind(event);
|
||||
ControlRef control;
|
||||
bool handled = true;
|
||||
|
||||
switch (eclass) {
|
||||
case kEventClassControl:
|
||||
{
|
||||
AudioUnitParameterInfo AUPI = mParam.ParamInfo();
|
||||
|
||||
bool isWriteOnlyBoolParameter = ( (AUPI.unit == kAudioUnitParameterUnit_Boolean) &&
|
||||
(AUPI.flags & kAudioUnitParameterFlag_IsWritable) &&
|
||||
!(AUPI.flags & kAudioUnitParameterFlag_IsReadable) );
|
||||
|
||||
switch (ekind) {
|
||||
case kEventControlSetFocusPart: // tab
|
||||
handled = !handled; // fall through to next case
|
||||
mLastControl = this;
|
||||
case kEventControlValueFieldChanged:
|
||||
GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
|
||||
verify(control == mControl);
|
||||
ControlToParameter();
|
||||
return handled;
|
||||
case kEventControlClick:
|
||||
if (isWriteOnlyBoolParameter) {
|
||||
GetEventParameter(event, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
|
||||
verify(control == mControl);
|
||||
ControlToParameter();
|
||||
} else if (mLastControl != this) {
|
||||
if (mLastControl != NULL) {
|
||||
mLastControl->Update(false);
|
||||
}
|
||||
mLastControl = this;
|
||||
}
|
||||
mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseDownInControl, NULL);
|
||||
break; // don't return true, continue normal processing
|
||||
case kEventControlHit:
|
||||
if (mLastControl != this) {
|
||||
if (mLastControl != NULL)
|
||||
mLastControl->Update(false);
|
||||
mLastControl = this;
|
||||
}
|
||||
mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
|
||||
break; // don't return true, continue normal processing
|
||||
case kEventControlTrack:
|
||||
if (mLastControl != this) {
|
||||
if (mLastControl != NULL)
|
||||
mLastControl->Update(false);
|
||||
mLastControl = this;
|
||||
}
|
||||
|
||||
CallNextEventHandler(inHandlerRef, event);
|
||||
ControlToParameter(); // new code
|
||||
mOwnerView->TellListener(mParam, kAudioUnitCarbonViewEvent_MouseUpInControl, NULL);
|
||||
// old code:
|
||||
// break; // don't return true, continue normal processing
|
||||
|
||||
return handled; // don't return true, continue normal processing
|
||||
}
|
||||
}
|
||||
}
|
||||
return !handled;
|
||||
}
|
||||
|
||||
pascal void AUCarbonViewControl::SliderTrackProc(ControlRef theControl, ControlPartCode partCode)
|
||||
{
|
||||
// this doesn't need to actually do anything
|
||||
// AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
|
||||
}
|
||||
|
||||
pascal ControlKeyFilterResult AUCarbonViewControl::StdKeyFilterCallback(ControlRef theControl,
|
||||
SInt16 *keyCode, SInt16 *charCode,
|
||||
EventModifiers *modifiers)
|
||||
{
|
||||
#if !__LP64__
|
||||
SInt16 c = *charCode;
|
||||
if (c >= ' ' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f) || c == '\t')
|
||||
return kControlKeyFilterPassKey;
|
||||
if (c == '\r' || c == 3) { // return or Enter
|
||||
AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
|
||||
ControlEditTextSelectionRec sel = { 0, 32767 };
|
||||
SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
|
||||
This->ControlToParameter();
|
||||
}
|
||||
#endif
|
||||
return kControlKeyFilterBlockKey;
|
||||
}
|
||||
|
||||
pascal ControlKeyFilterResult AUCarbonViewControl::NumericKeyFilterCallback(ControlRef theControl,
|
||||
SInt16 *keyCode, SInt16 *charCode,
|
||||
EventModifiers *modifiers)
|
||||
{
|
||||
#if !__LP64__
|
||||
SInt16 c = *charCode;
|
||||
if (isdigit(c) || c == '+' || c == '-' || c == '.' || c == '\b' || c == 0x7F || (c >= 0x1c && c <= 0x1f)
|
||||
|| c == '\t')
|
||||
return kControlKeyFilterPassKey;
|
||||
if (c == '\r' || c == 3) { // return or Enter
|
||||
AUCarbonViewControl *This = (AUCarbonViewControl *)GetControlReference(theControl);
|
||||
ControlEditTextSelectionRec sel = { 0, 32767 };
|
||||
SetControlData(This->mControl, 0, kControlEditTextSelectionTag, sizeof(sel), &sel);
|
||||
This->ControlToParameter();
|
||||
}
|
||||
#endif
|
||||
return kControlKeyFilterBlockKey;
|
||||
}
|
||||
|
||||
Boolean AUCarbonViewControl::SizeControlToFit(ControlRef inControl, SInt16 *outWidth, SInt16 *outHeight)
|
||||
{
|
||||
#if !__LP64__
|
||||
if (inControl == 0) return false;
|
||||
|
||||
Boolean bValue = false;
|
||||
// this only works on text controls -- returns an error for other controls, but doesn't do anything,
|
||||
// so the error is irrelevant
|
||||
SetControlData(inControl, kControlEntireControl, 'stim' /* kControlStaticTextIsMultilineTag */, sizeof(Boolean), &bValue);
|
||||
|
||||
SInt16 baseLineOffset;
|
||||
Rect bestRect;
|
||||
OSErr err = GetBestControlRect(inControl, &bestRect, &baseLineOffset);
|
||||
if (err != noErr) return false;
|
||||
|
||||
int width = (bestRect.right - bestRect.left) + 1;
|
||||
int height = (bestRect.bottom - bestRect.top) + 1;
|
||||
|
||||
Rect boundsRect;
|
||||
GetControlBounds (inControl, &boundsRect);
|
||||
|
||||
Rect newRect;
|
||||
newRect.top = boundsRect.top;
|
||||
newRect.bottom = newRect.top + height;
|
||||
newRect.left = boundsRect.left;
|
||||
newRect.right = newRect.left + width;
|
||||
|
||||
SetControlBounds (inControl, &newRect);
|
||||
|
||||
if (outWidth)
|
||||
*outWidth = width;
|
||||
|
||||
if (outHeight)
|
||||
*outHeight = height;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark ___AUPropertyControl
|
||||
bool AUPropertyControl::HandleEvent(EventHandlerCallRef inHandlerRef, EventRef event)
|
||||
{
|
||||
UInt32 eclass = GetEventClass(event);
|
||||
UInt32 ekind = GetEventKind(event);
|
||||
switch (eclass) {
|
||||
case kEventClassControl:
|
||||
switch (ekind) {
|
||||
case kEventControlValueFieldChanged:
|
||||
HandleControlChange();
|
||||
return true; // handled
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AUPropertyControl::RegisterEvents ()
|
||||
{
|
||||
#if !__LP64__
|
||||
EventTypeSpec events[] = {
|
||||
{ kEventClassControl, kEventControlValueFieldChanged } // N.B. OS X only
|
||||
};
|
||||
|
||||
WantEventTypes(GetControlEventTarget(mControl), GetEventTypeCount(events), events);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUPropertyControl::EmbedControl (ControlRef theControl)
|
||||
{
|
||||
mView->EmbedControl (theControl);
|
||||
}
|
||||
|
||||
WindowRef AUPropertyControl::GetCarbonWindow()
|
||||
{
|
||||
return mView->GetCarbonWindow();
|
||||
}
|
||||
|
||||
#pragma mark ___AUVPreset
|
||||
#if !__LP64__
|
||||
static CFStringRef kStringFactoryPreset = kAUViewLocalizedStringKey_FactoryPreset;
|
||||
static bool sAUVPresetLocalized = false;
|
||||
#endif
|
||||
|
||||
AUVPresets::AUVPresets (AUCarbonViewBase* inParentView,
|
||||
CFArrayRef& inPresets,
|
||||
Point inLocation,
|
||||
int nameWidth,
|
||||
int controlWidth,
|
||||
ControlFontStyleRec & inFontStyle)
|
||||
: AUPropertyControl (inParentView),
|
||||
mPresets (inPresets),
|
||||
mView (inParentView)
|
||||
{
|
||||
#if !__LP64__
|
||||
Rect r;
|
||||
|
||||
// ok we now have an array of factory presets
|
||||
// get their strings and display them
|
||||
|
||||
r.top = inLocation.v; r.bottom = r.top;
|
||||
r.left = inLocation.h; r.right = r.left;
|
||||
|
||||
// localize as necessary
|
||||
if (!sAUVPresetLocalized) {
|
||||
CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
|
||||
if (mainBundle) {
|
||||
kStringFactoryPreset = CFCopyLocalizedStringFromTableInBundle(
|
||||
kAUViewLocalizedStringKey_FactoryPreset, kLocalizedStringTable_AUView,
|
||||
mainBundle, CFSTR("FactoryPreset title string"));
|
||||
sAUVPresetLocalized = true;
|
||||
}
|
||||
}
|
||||
|
||||
// create localized title string
|
||||
CFMutableStringRef factoryPresetsTitle = CFStringCreateMutable(NULL, 0);
|
||||
CFStringAppend(factoryPresetsTitle, kStringFactoryPreset);
|
||||
CFStringAppend(factoryPresetsTitle, kAUViewUnlocalizedString_TitleSeparator);
|
||||
|
||||
ControlRef theControl;
|
||||
verify_noerr(CreateStaticTextControl(mView->GetCarbonWindow(), &r, factoryPresetsTitle, &inFontStyle, &theControl));
|
||||
SInt16 width = 0;
|
||||
AUCarbonViewControl::SizeControlToFit(theControl, &width, &mHeight);
|
||||
CFRelease(factoryPresetsTitle);
|
||||
EmbedControl(theControl);
|
||||
|
||||
r.top -= 2;
|
||||
r.left += width + 10;
|
||||
r.right = r.left;
|
||||
r.bottom = r.top;
|
||||
|
||||
verify_noerr(CreatePopupButtonControl ( mView->GetCarbonWindow(), &r, NULL,
|
||||
-12345, // DON'T GET MENU FROM RESOURCE mMenuID,!!!
|
||||
FALSE, // variableWidth,
|
||||
0, // titleWidth,
|
||||
0, // titleJustification,
|
||||
0, // titleStyle,
|
||||
&mControl));
|
||||
|
||||
MenuRef menuRef;
|
||||
verify_noerr(CreateNewMenu(1, 0, &menuRef));
|
||||
|
||||
int numPresets = CFArrayGetCount(mPresets);
|
||||
|
||||
for (int i = 0; i < numPresets; ++i)
|
||||
{
|
||||
AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
|
||||
verify_noerr(AppendMenuItemTextWithCFString (menuRef, preset->presetName, 0, 0, 0));
|
||||
}
|
||||
|
||||
verify_noerr(SetControlData(mControl, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
|
||||
verify_noerr (SetControlFontStyle (mControl, &inFontStyle));
|
||||
|
||||
SetControl32BitMaximum (mControl, numPresets);
|
||||
|
||||
// size popup
|
||||
SInt16 height = 0;
|
||||
|
||||
AUCarbonViewControl::SizeControlToFit(mControl, &width, &height);
|
||||
|
||||
if (height > mHeight) mHeight = height;
|
||||
if (mHeight < 0) mHeight = 0;
|
||||
|
||||
// find which menu item is the Default preset
|
||||
UInt32 propertySize = sizeof(AUPreset);
|
||||
AUPreset defaultPreset;
|
||||
OSStatus result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
|
||||
kAudioUnitProperty_PresentPreset,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
&defaultPreset,
|
||||
&propertySize);
|
||||
|
||||
mPropertyID = kAudioUnitProperty_PresentPreset;
|
||||
#endif
|
||||
#ifndef __LP64__
|
||||
if (result != noErr) { // if the PresentPreset property is not implemented, fall back to the CurrentPreset property
|
||||
result = AudioUnitGetProperty (mView->GetEditAudioUnit(),
|
||||
kAudioUnitProperty_CurrentPreset,
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
&defaultPreset,
|
||||
&propertySize);
|
||||
mPropertyID = kAudioUnitProperty_CurrentPreset;
|
||||
if (result == noErr)
|
||||
CFRetain (defaultPreset.presetName);
|
||||
}
|
||||
#endif
|
||||
#if !__LP64__
|
||||
EmbedControl (mControl);
|
||||
|
||||
HandlePropertyChange(defaultPreset);
|
||||
|
||||
RegisterEvents();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUVPresets::AddInterest (AUEventListenerRef inListener,
|
||||
void * inObject)
|
||||
{
|
||||
AudioUnitEvent e;
|
||||
e.mEventType = kAudioUnitEvent_PropertyChange;
|
||||
e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
|
||||
e.mArgument.mProperty.mPropertyID = mPropertyID;
|
||||
e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
|
||||
e.mArgument.mProperty.mElement = 0;
|
||||
|
||||
AUEventListenerAddEventType(inListener, inObject, &e);
|
||||
}
|
||||
|
||||
void AUVPresets::RemoveInterest (AUEventListenerRef inListener,
|
||||
void * inObject)
|
||||
{
|
||||
AudioUnitEvent e;
|
||||
e.mEventType = kAudioUnitEvent_PropertyChange;
|
||||
e.mArgument.mProperty.mAudioUnit = mView->GetEditAudioUnit();
|
||||
e.mArgument.mProperty.mPropertyID = mPropertyID;
|
||||
e.mArgument.mProperty.mScope = kAudioUnitScope_Global;
|
||||
e.mArgument.mProperty.mElement = 0;
|
||||
|
||||
AUEventListenerRemoveEventType(inListener, inObject, &e);
|
||||
}
|
||||
|
||||
void AUVPresets::HandleControlChange ()
|
||||
{
|
||||
#if !__LP64__
|
||||
SInt32 i = GetControl32BitValue(mControl);
|
||||
if (i > 0)
|
||||
{
|
||||
AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i-1);
|
||||
|
||||
verify_noerr(AudioUnitSetProperty (mView->GetEditAudioUnit(),
|
||||
mPropertyID, // either currentPreset or PresentPreset depending on which is supported
|
||||
kAudioUnitScope_Global,
|
||||
0,
|
||||
preset,
|
||||
sizeof(AUPreset)));
|
||||
|
||||
// when we change a preset we can't expect the AU to update its state
|
||||
// as it isn't meant to know that its being viewed!
|
||||
// so we broadcast a notification to all listeners that all parameters on this AU have changed
|
||||
AudioUnitParameter changedUnit;
|
||||
changedUnit.mAudioUnit = mView->GetEditAudioUnit();
|
||||
changedUnit.mParameterID = kAUParameterListener_AnyParameter;
|
||||
verify_noerr (AUParameterListenerNotify (NULL, NULL, &changedUnit) );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUVPresets::HandlePropertyChange(AUPreset &preset)
|
||||
{
|
||||
#if !__LP64__
|
||||
// check to see if the preset is in our menu
|
||||
int numPresets = CFArrayGetCount(mPresets);
|
||||
if (preset.presetNumber < 0) {
|
||||
SetControl32BitValue (mControl, 0); //controls are one-based
|
||||
} else {
|
||||
for (SInt32 i = 0; i < numPresets; ++i) {
|
||||
AUPreset* currPreset = (AUPreset*) CFArrayGetValueAtIndex (mPresets, i);
|
||||
if (preset.presetNumber == currPreset->presetNumber) {
|
||||
SetControl32BitValue (mControl, ++i); //controls are one-based
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.presetName)
|
||||
CFRelease (preset.presetName);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool AUVPresets::HandlePropertyChange (const AudioUnitProperty &inProp)
|
||||
{
|
||||
if (inProp.mPropertyID == mPropertyID)
|
||||
{
|
||||
UInt32 theSize = sizeof(AUPreset);
|
||||
AUPreset currentPreset;
|
||||
|
||||
OSStatus result = AudioUnitGetProperty(inProp.mAudioUnit,
|
||||
inProp.mPropertyID,
|
||||
inProp.mScope,
|
||||
inProp.mElement, ¤tPreset, &theSize);
|
||||
|
||||
if (result == noErr) {
|
||||
#ifndef __LP64__
|
||||
if (inProp.mPropertyID == kAudioUnitProperty_CurrentPreset && currentPreset.presetName)
|
||||
CFRetain (currentPreset.presetName);
|
||||
#endif
|
||||
HandlePropertyChange(currentPreset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@ -0,0 +1,231 @@
|
||||
/*
|
||||
File: AUCarbonViewControl.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __AUCarbonViewControl_h__
|
||||
#define __AUCarbonViewControl_h__
|
||||
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.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 ¶m, 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__
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
File: AUCarbonViewDispatch.cpp
|
||||
Abstract: AUCarbonViewDispatch.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "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;
|
||||
}
|
@ -0,0 +1,438 @@
|
||||
/*
|
||||
File: AUDispatch.cpp
|
||||
Abstract: AUDispatch.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "AUBase.h"
|
||||
#include "CAXException.h"
|
||||
#include "AUDispatch.h"
|
||||
|
||||
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
#if __LP64__
|
||||
// comp instance, parameters in forward order
|
||||
#define PARAM(_typ, _name, _index, _nparams) \
|
||||
_typ _name = *(_typ *)¶ms->params[_index + 1];
|
||||
#else
|
||||
// parameters in reverse order, then comp instance
|
||||
#define PARAM(_typ, _name, _index, _nparams) \
|
||||
_typ _name = *(_typ *)¶ms->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 *)¶ms->params[_index];
|
||||
#endif
|
||||
|
||||
|
||||
OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
|
||||
{
|
||||
if (This == NULL) return kAudio_ParamError;
|
||||
|
||||
OSStatus result = noErr;
|
||||
|
||||
switch (params->what) {
|
||||
case kComponentCanDoSelect:
|
||||
switch (GetSelectorForCanDo(params)) {
|
||||
// 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:
|
||||
{
|
||||
CAMutex::Locker lock2(This->GetMutex());
|
||||
result = This->DoInitialize();
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitUninitializeSelect:
|
||||
{
|
||||
CAMutex::Locker lock2(This->GetMutex());
|
||||
This->DoCleanup();
|
||||
result = noErr;
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitGetPropertyInfoSelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitGetPropertySelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
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 = kAudio_ParamError;
|
||||
goto finishGetProperty;
|
||||
}
|
||||
if (poutData == NULL) {
|
||||
UInt32 dataSize;
|
||||
|
||||
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 = kAudio_ParamError;
|
||||
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 && tempBuffer != NULL)
|
||||
{
|
||||
memcpy(poutData, tempBuffer, clientBufferSize);
|
||||
delete[] tempBuffer;
|
||||
// pioDataSize remains correct, the number of bytes we wrote
|
||||
} else
|
||||
*pioDataSize = actualPropertySize;
|
||||
} else
|
||||
*pioDataSize = 0;
|
||||
|
||||
finishGetProperty:
|
||||
;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitSetPropertySelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
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 = kAudio_ParamError;
|
||||
goto finishSetProperty;
|
||||
}
|
||||
|
||||
if (pinDataSize == 0) {
|
||||
ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
|
||||
result = kAudio_ParamError;
|
||||
goto finishSetProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
finishSetProperty:
|
||||
;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitAddPropertyListenerSelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
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:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
PARAM(AudioUnitPropertyID, pinID, 0, 2);
|
||||
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
|
||||
result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
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:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
PARAM(AURenderCallback, pinProc, 0, 2);
|
||||
PARAM(void *, pinProcRefCon, 1, 2);
|
||||
result = This->SetRenderNotification (pinProc, pinProcRefCon);
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitRemoveRenderNotifySelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
PARAM(AURenderCallback, pinProc, 0, 2);
|
||||
PARAM(void *, pinProcRefCon, 1, 2);
|
||||
result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitGetParameterSelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
PARAM(AudioUnitParameterID, pinID, 0, 4);
|
||||
PARAM(AudioUnitScope, pinScope, 1, 4);
|
||||
PARAM(AudioUnitElement, pinElement, 2, 4);
|
||||
PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
|
||||
result = (poutValue == NULL ? kAudio_ParamError : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitSetParameterSelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
|
||||
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:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
|
||||
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:
|
||||
{
|
||||
// realtime; no lock
|
||||
{
|
||||
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 = kAudio_ParamError;
|
||||
else {
|
||||
if (pinActionFlags == NULL) {
|
||||
tempFlags = 0;
|
||||
pinActionFlags = &tempFlags;
|
||||
}
|
||||
result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioUnitResetSelect:
|
||||
{
|
||||
CAMutex::Locker lock(This->GetMutex());
|
||||
PARAM(AudioUnitScope, pinScope, 0, 2);
|
||||
PARAM(AudioUnitElement, pinElement, 1, 2);
|
||||
This->ResetRenderTime();
|
||||
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 CMgr_AudioUnitBaseGetParameter( AUBase * This,
|
||||
AudioUnitParameterID inID,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement,
|
||||
float *outValue)
|
||||
{
|
||||
OSStatus result = AUBase::noErr;
|
||||
|
||||
try {
|
||||
if (This == NULL || outValue == NULL) return kAudio_ParamError;
|
||||
result = This->GetParameter(inID, inScope, inElement, *outValue);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
|
||||
AudioUnitParameterID inID,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement,
|
||||
float inValue,
|
||||
UInt32 inBufferOffset)
|
||||
{
|
||||
OSStatus result = AUBase::noErr;
|
||||
|
||||
try {
|
||||
if (This == NULL) return kAudio_ParamError;
|
||||
result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList * ioData)
|
||||
{
|
||||
if (inTimeStamp == NULL || ioData == NULL) return kAudio_ParamError;
|
||||
|
||||
OSStatus result = AUBase::noErr;
|
||||
AudioUnitRenderActionFlags tempFlags;
|
||||
|
||||
try {
|
||||
if (ioActionFlags == NULL) {
|
||||
tempFlags = 0;
|
||||
ioActionFlags = &tempFlags;
|
||||
}
|
||||
result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
File: AUDispatch.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __AUDispatch_h__
|
||||
#define __AUDispatch_h__
|
||||
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#else
|
||||
#include "AudioUnit.h"
|
||||
#endif
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
/*! @function AudioUnitBaseGetParameter */
|
||||
OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
|
||||
AudioUnitParameterID inID,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement,
|
||||
float * outValue);
|
||||
|
||||
/*! @function AudioUnitBaseSetParameter */
|
||||
OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
|
||||
AudioUnitParameterID inID,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement,
|
||||
float inValue,
|
||||
UInt32 inBufferOffset);
|
||||
|
||||
/*! @function AudioUnitBaseRender */
|
||||
OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList * ioData);
|
||||
#endif
|
||||
|
||||
#endif // __AUDispatch_h__
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
File: AUInputElement.cpp
|
||||
Abstract: AUInputElement.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "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;
|
||||
AllocateBuffer();
|
||||
|
||||
mConnInstanceStorage = NULL;
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
mConnRenderProc = NULL;
|
||||
UInt32 size = sizeof(AudioUnitRenderProc);
|
||||
OSStatus result = AudioUnitGetProperty( conn.sourceAudioUnit,
|
||||
kAudioUnitProperty_FastDispatch,
|
||||
kAudioUnitScope_Global,
|
||||
kAudioUnitRenderSelect,
|
||||
&mConnRenderProc,
|
||||
&size);
|
||||
if (result == noErr)
|
||||
mConnInstanceStorage = CMgr_GetComponentInstanceStorage (conn.sourceAudioUnit);
|
||||
else
|
||||
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);
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
File: AUInputElement.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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;
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
/*! @var mConnRenderProc */
|
||||
AudioUnitRenderProc mConnRenderProc;
|
||||
#endif
|
||||
/*! @var mConnInstanceStorage */
|
||||
void * mConnInstanceStorage; // for the input component
|
||||
};
|
||||
|
||||
|
||||
#endif // __AUInput_h__
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
File: AUInputFormatConverter.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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__
|
@ -0,0 +1,495 @@
|
||||
/*
|
||||
File: AUMIDIBase.cpp
|
||||
Abstract: AUMIDIBase.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "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) {
|
||||
#if !TARGET_OS_IPHONE
|
||||
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;
|
||||
#endif
|
||||
#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;
|
||||
|
||||
#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
|
||||
InvalidScope:
|
||||
return kAudioUnitErr_InvalidScope;
|
||||
InvalidElement:
|
||||
return kAudioUnitErr_InvalidElement;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSStatus AUMIDIBase::DelegateGetProperty( AudioUnitPropertyID inID,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement,
|
||||
void * outData)
|
||||
{
|
||||
OSStatus result;
|
||||
|
||||
switch (inID) {
|
||||
#if !TARGET_OS_IPHONE
|
||||
case kMusicDeviceProperty_MIDIXMLNames:
|
||||
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
|
||||
ca_require(inElement == 0, InvalidElement);
|
||||
result = GetXMLNames((CFURLRef *)outData);
|
||||
break;
|
||||
#endif
|
||||
#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;
|
||||
|
||||
#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
|
||||
InvalidScope:
|
||||
return kAudioUnitErr_InvalidScope;
|
||||
InvalidElement:
|
||||
return kAudioUnitErr_InvalidElement;
|
||||
#endif
|
||||
}
|
||||
|
||||
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], static_cast<UInt32>(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 *)¶ms->params[_index + 1];
|
||||
#else
|
||||
// parameters in reverse order, then comp instance
|
||||
#define PARAM(_typ, _name, _index, _nparams) \
|
||||
_typ _name = *(_typ *)¶ms->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 *)¶ms->params[_index];
|
||||
#endif
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
OSStatus AUMIDIBase::ComponentEntryDispatch( ComponentParameters * params,
|
||||
AUMIDIBase * This)
|
||||
{
|
||||
if (This == NULL) return kAudio_ParamError;
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
File: AUMIDIBase.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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 */
|
||||
virtual 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 */
|
||||
virtual 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 !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
// component dispatcher
|
||||
/*! @method ComponentEntryDispatch */
|
||||
static OSStatus ComponentEntryDispatch( ComponentParameters *params,
|
||||
AUMIDIBase *This);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // __AUMIDIBase_h__
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
File: AUOutputBase.cpp
|
||||
Abstract: AUOutputBase.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
#include "AUOutputBase.h"
|
||||
|
||||
OSStatus AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
|
||||
{
|
||||
if (This == NULL) return paramErr;
|
||||
|
||||
OSStatus result;
|
||||
|
||||
switch (params->what) {
|
||||
case kAudioOutputUnitStartSelect:
|
||||
{
|
||||
result = This->Start();
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioOutputUnitStopSelect:
|
||||
{
|
||||
result = This->Stop();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
result = badComponentSelector;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
File: AUOutputBase.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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 !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
// component dispatcher
|
||||
/*! @method ComponentEntryDispatch */
|
||||
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
|
||||
AUOutputBase * This);
|
||||
#endif
|
||||
|
||||
private:
|
||||
/*! @var mAUBaseInstance */
|
||||
AUBase & mAUBaseInstance;
|
||||
};
|
||||
|
||||
#endif // __AUOutputBase_h__
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
File: AUOutputElement.cpp
|
||||
Abstract: AUOutputElement.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.h"
|
||||
#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;
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
File: AUOutputElement.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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__
|
@ -0,0 +1,668 @@
|
||||
/*
|
||||
File: AUPlugInDispatch.cpp
|
||||
Abstract: AUPlugInDispatch.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "AUPlugInDispatch.h"
|
||||
#include "CAXException.h"
|
||||
#include "ComponentBase.h"
|
||||
#include "AUBase.h"
|
||||
|
||||
#define ACPI ((AudioComponentPlugInInstance *)self)
|
||||
#define AUI ((AUBase *)&ACPI->mInstanceStorage)
|
||||
|
||||
#define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex());
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static OSStatus AUMethodInitialize(void *self)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->DoInitialize();
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodUninitialize(void *self)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
AUI->DoCleanup();
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval.
|
||||
Boolean writable = false;
|
||||
|
||||
AUI_LOCK
|
||||
result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
|
||||
if (outDataSize != NULL)
|
||||
*outDataSize = dataSize;
|
||||
if (outWritable != NULL)
|
||||
*outWritable = writable;
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
UInt32 actualPropertySize, clientBufferSize;
|
||||
Boolean writable;
|
||||
char *tempBuffer;
|
||||
void *destBuffer;
|
||||
|
||||
AUI_LOCK
|
||||
if (ioDataSize == NULL) {
|
||||
ca_debug_string("AudioUnitGetProperty: null size pointer");
|
||||
result = kAudio_ParamError;
|
||||
goto finishGetProperty;
|
||||
}
|
||||
if (outData == NULL) {
|
||||
UInt32 dataSize;
|
||||
|
||||
result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable);
|
||||
*ioDataSize = dataSize;
|
||||
goto finishGetProperty;
|
||||
}
|
||||
|
||||
clientBufferSize = *ioDataSize;
|
||||
if (clientBufferSize == 0)
|
||||
{
|
||||
ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
|
||||
// $$$ or should we allow this as a shortcut for finding the size?
|
||||
result = kAudio_ParamError;
|
||||
goto finishGetProperty;
|
||||
}
|
||||
|
||||
result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable);
|
||||
if (result != noErr)
|
||||
goto finishGetProperty;
|
||||
|
||||
if (clientBufferSize < actualPropertySize)
|
||||
{
|
||||
tempBuffer = new char[actualPropertySize];
|
||||
destBuffer = tempBuffer;
|
||||
} else {
|
||||
tempBuffer = NULL;
|
||||
destBuffer = outData;
|
||||
}
|
||||
|
||||
result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer);
|
||||
|
||||
if (result == noErr) {
|
||||
if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
|
||||
{
|
||||
memcpy(outData, tempBuffer, clientBufferSize);
|
||||
delete[] tempBuffer;
|
||||
// ioDataSize remains correct, the number of bytes we wrote
|
||||
} else
|
||||
*ioDataSize = actualPropertySize;
|
||||
} else
|
||||
*ioDataSize = 0;
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
finishGetProperty:
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
if (inData && inDataSize)
|
||||
result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
|
||||
else {
|
||||
if (inData == NULL && inDataSize == 0) {
|
||||
result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement);
|
||||
} else {
|
||||
if (inData == NULL) {
|
||||
ca_debug_string("AudioUnitSetProperty: inData == NULL");
|
||||
result = kAudio_ParamError;
|
||||
goto finishSetProperty;
|
||||
}
|
||||
|
||||
if (inDataSize == 0) {
|
||||
ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
|
||||
result = kAudio_ParamError;
|
||||
goto finishSetProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
finishSetProperty:
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->AddPropertyListener(prop, proc, userData);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->RemovePropertyListener(prop, proc, NULL, false);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->RemovePropertyListener(prop, proc, userData, true);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->SetRenderNotification(proc, userData);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->RemoveRenderNotification(proc, userData);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value));
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a (potentially) realtime method; no lock
|
||||
result = AUI->SetParameter(param, scope, elem, value, bufferOffset);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a (potentially) realtime method; no lock
|
||||
result = AUI->ScheduleParameter(events, numEvents);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
try {
|
||||
#endif
|
||||
// this is a processing method; no lock
|
||||
AudioUnitRenderActionFlags tempFlags;
|
||||
|
||||
if (inTimeStamp == NULL || ioData == NULL)
|
||||
result = kAudio_ParamError;
|
||||
else {
|
||||
if (ioActionFlags == NULL) {
|
||||
tempFlags = 0;
|
||||
ioActionFlags = &tempFlags;
|
||||
}
|
||||
result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
try {
|
||||
#endif
|
||||
// this is a processing method; no lock
|
||||
AudioUnitRenderActionFlags tempFlags;
|
||||
|
||||
if (inTimeStamp == NULL || ioData == NULL)
|
||||
result = kAudio_ParamError;
|
||||
else {
|
||||
if (ioActionFlags == NULL) {
|
||||
tempFlags = 0;
|
||||
ioActionFlags = &tempFlags;
|
||||
}
|
||||
result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->Reset(scope, elem);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
try {
|
||||
#endif
|
||||
// this is a processing method; no lock
|
||||
bool doParamCheck = true;
|
||||
|
||||
AudioUnitRenderActionFlags tempFlags;
|
||||
|
||||
if (ioActionFlags == NULL) {
|
||||
tempFlags = 0;
|
||||
ioActionFlags = &tempFlags;
|
||||
} else {
|
||||
if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
|
||||
doParamCheck = false;
|
||||
}
|
||||
|
||||
if (doParamCheck && (inTimeStamp == NULL || ioData == NULL))
|
||||
result = kAudio_ParamError;
|
||||
else {
|
||||
result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
try {
|
||||
#endif
|
||||
// this is a processing method; no lock
|
||||
bool doParamCheck = true;
|
||||
|
||||
AudioUnitRenderActionFlags tempFlags;
|
||||
|
||||
if (ioActionFlags == NULL) {
|
||||
tempFlags = 0;
|
||||
ioActionFlags = &tempFlags;
|
||||
} else {
|
||||
if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
|
||||
doParamCheck = false;
|
||||
}
|
||||
|
||||
if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL))
|
||||
result = kAudio_ParamError;
|
||||
else {
|
||||
result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
static OSStatus AUMethodStart(void *self)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->Start();
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodStop(void *self)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
AUI_LOCK
|
||||
result = AUI->Stop();
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
#if !CA_BASIC_AU_FEATURES
|
||||
// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
|
||||
static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a potential render-time method; no lock
|
||||
result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a potential render-time method; no lock
|
||||
result = AUI->SysEx(inData, inLength);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a potential render-time method; no lock
|
||||
if (inParams == NULL || outNoteInstanceID == NULL)
|
||||
result = kAudio_ParamError;
|
||||
else
|
||||
result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a potential render-time method; no lock
|
||||
result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a potential render-time method; no lock
|
||||
result = AUI->PrepareInstrument(inInstrument);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
// this is a potential render-time method; no lock
|
||||
result = AUI->ReleaseInstrument(inInstrument);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
#endif // TARGET_OS_IPHONE
|
||||
#endif // CA_BASIC_AU_FEATURES
|
||||
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
#pragma mark -
|
||||
#pragma mark Lookup Methods
|
||||
|
||||
AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
switch (selector) {
|
||||
case kAudioUnitInitializeSelect: return (AudioComponentMethod)AUMethodInitialize;
|
||||
case kAudioUnitUninitializeSelect: return (AudioComponentMethod)AUMethodUninitialize;
|
||||
case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
|
||||
case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
|
||||
case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
|
||||
case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener;
|
||||
case kAudioUnitRemovePropertyListenerSelect:
|
||||
return (AudioComponentMethod)AUMethodRemovePropertyListener;
|
||||
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
|
||||
return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData;
|
||||
case kAudioUnitAddRenderNotifySelect: return (AudioComponentMethod)AUMethodAddRenderNotify;
|
||||
case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify;
|
||||
case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
|
||||
case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
|
||||
case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters;
|
||||
case kAudioUnitRenderSelect: return (AudioComponentMethod)AUMethodRender;
|
||||
case kAudioUnitResetSelect: return (AudioComponentMethod)AUMethodReset;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
switch (selector) {
|
||||
case kAudioOutputUnitStartSelect: return (AudioComponentMethod)AUMethodStart;
|
||||
case kAudioOutputUnitStopSelect: return (AudioComponentMethod)AUMethodStop;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
method = AUOutputLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
if (selector == kAudioUnitComplexRenderSelect)
|
||||
return (AudioComponentMethod)AUMethodComplexRender;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
if (selector == kAudioUnitProcessSelect)
|
||||
return (AudioComponentMethod)AUMethodProcess;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
if (selector == kAudioUnitProcessMultipleSelect)
|
||||
return (AudioComponentMethod)AUMethodProcessMultiple;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
method = AUBaseProcessMultipleLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
method = AUBaseProcessLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !CA_BASIC_AU_FEATURES
|
||||
inline AudioComponentMethod MIDI_Lookup (SInt16 selector)
|
||||
{
|
||||
switch (selector) {
|
||||
case kMusicDeviceMIDIEventSelect: return (AudioComponentMethod)AUMethodMIDIEvent;
|
||||
case kMusicDeviceSysExSelect: return (AudioComponentMethod)AUMethodSysEx;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
return MIDI_Lookup(selector);
|
||||
}
|
||||
|
||||
AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
return MIDI_Lookup(selector);
|
||||
}
|
||||
|
||||
AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
|
||||
if (method) return method;
|
||||
|
||||
switch (selector) {
|
||||
case kMusicDeviceStartNoteSelect: return (AudioComponentMethod)AUMethodStartNote;
|
||||
case kMusicDeviceStopNoteSelect: return (AudioComponentMethod)AUMethodStopNote;
|
||||
#if !TARGET_OS_IPHONE
|
||||
case kMusicDevicePrepareInstrumentSelect: return (AudioComponentMethod)AUMethodPrepareInstrument;
|
||||
case kMusicDeviceReleaseInstrumentSelect: return (AudioComponentMethod)AUMethodReleaseInstrument;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return MIDI_Lookup (selector);
|
||||
}
|
||||
|
||||
AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector)
|
||||
{
|
||||
switch (selector) {
|
||||
case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
|
||||
case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
|
||||
case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
|
||||
|
||||
case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
|
||||
case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
File: AUPlugInDispatch.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __AUPlugInBase_h__
|
||||
#define __AUPlugInBase_h__
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <AudioUnit/AudioComponent.h>
|
||||
#if !CA_BASIC_AU_FEATURES
|
||||
#include <AudioUnit/MusicDevice.h>
|
||||
#endif
|
||||
#else
|
||||
#include "AudioComponent.h"
|
||||
#include "MusicDevice.h"
|
||||
#endif
|
||||
|
||||
#include "ComponentBase.h"
|
||||
|
||||
struct AUBaseLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUBaseFactory : public APFactory<AUBaseLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUOutputLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUOutputBaseFactory : public APFactory<AUOutputLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUComplexOutputLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUOutputComplexBaseFactory : public APFactory<AUComplexOutputLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUBaseProcessLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUBaseProcessFactory : public APFactory<AUBaseProcessLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUBaseProcessMultipleLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUBaseProcessMultipleFactory : public APFactory<AUBaseProcessMultipleLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUBaseProcessAndMultipleLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUBaseProcessAndMultipleFactory : public APFactory<AUBaseProcessAndMultipleLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
#if !CA_BASIC_AU_FEATURES
|
||||
struct AUMIDILookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUMIDIEffectFactory : public APFactory<AUMIDILookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUMIDIProcessLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUMIDIProcessFactory : public APFactory<AUMIDIProcessLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUMusicLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUMusicDeviceFactory : public APFactory<AUMusicLookup, Implementor>
|
||||
{
|
||||
};
|
||||
|
||||
struct AUAuxBaseLookup {
|
||||
static AudioComponentMethod Lookup (SInt16 selector);
|
||||
};
|
||||
template <class Implementor>
|
||||
class AUAuxBaseFactory : public APFactory<AUAuxBaseLookup, Implementor>
|
||||
{
|
||||
};
|
||||
#endif // CA_BASIC_AU_FEATURES
|
||||
|
||||
#endif // __AUPlugInBase_h__
|
@ -0,0 +1,567 @@
|
||||
/*
|
||||
File: AUScopeElement.cpp
|
||||
Abstract: AUScopeElement.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.h"
|
||||
#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;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//
|
||||
// Helper method.
|
||||
// returns whether the specified paramID is known to the element
|
||||
//
|
||||
bool AUElement::HasParameterID (AudioUnitParameterID paramID) const
|
||||
{
|
||||
if(mUseIndexedParameters)
|
||||
{
|
||||
if(paramID >= mIndexedParameters.size() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ParameterMap::const_iterator i = mParameters.find(paramID);
|
||||
if (i == mParameters.end())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
//
|
||||
// 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 = static_cast<UInt32>(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 = static_cast<UInt32>(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(static_cast<uint32_t>(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 = mCreator->CreateElement(GetScope(), static_cast<UInt32>(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
|
||||
bool didAddElements = false;
|
||||
unsigned int maxElNum = GetNumberOfElements();
|
||||
|
||||
int dictSize = static_cast<int>(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 = 0;
|
||||
CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
|
||||
int result = sscanf (string, "%u", &intKey);
|
||||
// check if sscanf succeeded and element index is less than max elements.
|
||||
if (result && UInt32(intKey) < maxElNum)
|
||||
{
|
||||
CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict, keys[i]));
|
||||
AUElement* element = GetElement (intKey);
|
||||
if (element)
|
||||
element->SetName (elName);
|
||||
}
|
||||
}
|
||||
free (keys);
|
||||
|
||||
return didAddElements;
|
||||
}
|
||||
|
||||
void AUScope::SaveState(CFMutableDataRef data)
|
||||
{
|
||||
AudioUnitElement nElems = GetNumberOfElements();
|
||||
for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
|
||||
AUElement *element = GetElement(ielem);
|
||||
UInt32 nparams = element->GetNumberOfParameters();
|
||||
if (nparams > 0) {
|
||||
struct {
|
||||
UInt32 scope;
|
||||
UInt32 element;
|
||||
} hdr;
|
||||
|
||||
hdr.scope = CFSwapInt32HostToBig(GetScope());
|
||||
hdr.element = CFSwapInt32HostToBig(ielem);
|
||||
CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
|
||||
|
||||
element->SaveState(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const UInt8 * AUScope::RestoreState(const UInt8 *state)
|
||||
{
|
||||
const UInt8 *p = state;
|
||||
UInt32 elementIdx = CFSwapInt32BigToHost(*(UInt32 *)p); p += sizeof(UInt32);
|
||||
AUElement *element = GetElement(elementIdx);
|
||||
if (!element) {
|
||||
struct {
|
||||
AudioUnitParameterID paramID;
|
||||
AudioUnitParameterValue value;
|
||||
} entry;
|
||||
UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
|
||||
p += sizeof(UInt32);
|
||||
|
||||
p += nparams * sizeof(entry);
|
||||
} else
|
||||
p = element->RestoreState(p);
|
||||
|
||||
return p;
|
||||
}
|
@ -0,0 +1,553 @@
|
||||
/*
|
||||
File: AUScopeElement.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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.0f), mValue2(0.0f), 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 AUIOElement;
|
||||
|
||||
/*! @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 */
|
||||
virtual UInt32 GetNumberOfParameters()
|
||||
{
|
||||
if(mUseIndexedParameters) return static_cast<UInt32>(mIndexedParameters.size()); else return static_cast<UInt32>(mParameters.size());
|
||||
}
|
||||
/*! @method GetParameterList */
|
||||
virtual void GetParameterList(AudioUnitParameterID *outList);
|
||||
/*! @method HasParameterID */
|
||||
bool HasParameterID (AudioUnitParameterID paramID) const;
|
||||
|
||||
/*! @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);
|
||||
|
||||
/*! @method AsIOElement*/
|
||||
virtual AUIOElement* AsIOElement () { return NULL; }
|
||||
|
||||
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 SetWillAllocateBuffer */
|
||||
void SetWillAllocateBuffer(bool inFlag) {
|
||||
mWillAllocate = inFlag;
|
||||
}
|
||||
/*! @method WillAllocateBuffer */
|
||||
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);
|
||||
}
|
||||
Float32 * GetFloat32ChannelData(int ch) const {
|
||||
if (mStreamFormat.IsInterleaved())
|
||||
return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
|
||||
else
|
||||
return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
|
||||
}
|
||||
SInt32 * GetSInt32ChannelData(int ch) const {
|
||||
if (mStreamFormat.IsInterleaved())
|
||||
return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
|
||||
else
|
||||
return static_cast<SInt32 *>(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 ();
|
||||
|
||||
/*! @method AsIOElement*/
|
||||
virtual AUIOElement* AsIOElement () { return this; }
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// ____________________________________________________________________________
|
||||
//
|
||||
// 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 */
|
||||
void Initialize( AUBase *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;
|
||||
|
||||
AUBase * GetCreator() const { return mCreator; }
|
||||
AudioUnitScope GetScope() const { return mScope; }
|
||||
|
||||
|
||||
private:
|
||||
/*! @var mCreator */
|
||||
AUBase * 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(AUBase *creator,
|
||||
AudioUnitScope scope,
|
||||
UInt32 numElements)
|
||||
{
|
||||
mCreator = creator;
|
||||
mScope = scope;
|
||||
|
||||
if (mDelegate)
|
||||
return mDelegate->Initialize(creator, scope, numElements);
|
||||
|
||||
SetNumberOfElements(numElements);
|
||||
}
|
||||
|
||||
/*! @method SetNumberOfElements */
|
||||
void SetNumberOfElements(UInt32 numElements);
|
||||
|
||||
/*! @method GetNumberOfElements */
|
||||
UInt32 GetNumberOfElements() const
|
||||
{
|
||||
if (mDelegate)
|
||||
return mDelegate->GetNumberOfElements();
|
||||
|
||||
return static_cast<UInt32>(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 = element ? element->AsIOElement () : NULL;
|
||||
if (!ioel)
|
||||
COMPONENT_THROW (kAudioUnitErr_InvalidElement);
|
||||
return ioel;
|
||||
}
|
||||
|
||||
/*! @method HasElementWithName */
|
||||
bool HasElementWithName () const;
|
||||
|
||||
/*! @method AddElementNamesToDict */
|
||||
void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
|
||||
|
||||
bool RestoreElementNames (CFDictionaryRef& inNameDict);
|
||||
|
||||
AudioUnitScope GetScope() const { return mScope; }
|
||||
|
||||
void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
|
||||
|
||||
/*! @method SaveState */
|
||||
void SaveState(CFMutableDataRef data);
|
||||
|
||||
/*! @method RestoreState */
|
||||
const UInt8 * RestoreState(const UInt8 *state);
|
||||
|
||||
private:
|
||||
typedef std::vector<AUElement *> ElementVector;
|
||||
/*! @var mCreator */
|
||||
AUBase * mCreator;
|
||||
/*! @var mScope */
|
||||
AudioUnitScope mScope;
|
||||
/*! @var mElements */
|
||||
ElementVector mElements;
|
||||
/*! @var mDelegate */
|
||||
AUScopeDelegate * mDelegate;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __AUScopeElement_h__
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
File: AUSilentTimeout.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
File: AUTimestampGenerator.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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)
|
||||
{
|
||||
mState.mStartInputAtZero = true;
|
||||
mState.mBypassed = false;
|
||||
mState.mHostTimeDiscontinuityCorrection = hostTimeDiscontinuityCorrection;
|
||||
#if DEBUG
|
||||
mVerbosity = 0;
|
||||
snprintf(mDebugName, sizeof(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) { mState.mStartInputAtZero = b; }
|
||||
bool GetStartInputAtZero() const { return mState.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) { mState.mBypassed = b; }
|
||||
bool GetBypassed() const { return mState.mBypassed; }
|
||||
|
||||
// Call this to reset the timeline.
|
||||
void Reset()
|
||||
{
|
||||
mState.mCurrentInputTime.mSampleTime = 0.;
|
||||
mState.mNextInputSampleTime = 0.;
|
||||
mState.mCurrentOutputTime.mSampleTime = 0.;
|
||||
mState.mNextOutputSampleTime = 0.;
|
||||
mState.mLastOutputTime.mFlags = 0;
|
||||
mState.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, bool advanceHostTime = false);
|
||||
|
||||
// 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)mState.mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
|
||||
#endif
|
||||
mState.mNextInputSampleTime = mState.mCurrentInputTime.mSampleTime + framesToAdvance;
|
||||
}
|
||||
|
||||
struct State {
|
||||
AudioTimeStamp mCurrentInputTime;
|
||||
Float64 mNextInputSampleTime;
|
||||
Float64 mNextOutputSampleTime;
|
||||
Float64 mInputSampleTimeForOutputPull;
|
||||
|
||||
AudioTimeStamp mLastOutputTime;
|
||||
AudioTimeStamp mCurrentOutputTime;
|
||||
|
||||
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.
|
||||
};
|
||||
|
||||
void GetState(State& outState) const { outState = mState; }
|
||||
void SetState(State const& inState) { mState = inState; mFirstTime = false; }
|
||||
|
||||
private:
|
||||
|
||||
struct State mState;
|
||||
|
||||
bool mFirstTime;
|
||||
|
||||
#if DEBUG
|
||||
public:
|
||||
int mVerbosity;
|
||||
char mDebugName[64];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif // __AUTimestampGenerator_h__
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
File: AUViewLocalizedStringKeys.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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__
|
@ -0,0 +1,402 @@
|
||||
/*
|
||||
File: CAAUParameter.cpp
|
||||
Abstract: CAAUParameter.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.h"
|
||||
#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,
|
||||
0,
|
||||
&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,
|
||||
0,
|
||||
&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 = static_cast<UInt32>(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
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
File: CAAUParameter.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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__
|
@ -0,0 +1,305 @@
|
||||
/*
|
||||
File: CAAtomic.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
/*
|
||||
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>
|
||||
#pragma intrinsic(_InterlockedOr)
|
||||
#pragma intrinsic(_InterlockedAnd)
|
||||
#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
|
||||
|
||||
inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, volatile void ** __theValue)
|
||||
{
|
||||
#if __LP64__
|
||||
return CAAtomicCompareAndSwap64Barrier((int64_t)__oldValue, (int64_t)__newValue, (int64_t *)__theValue);
|
||||
#else
|
||||
return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__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__
|
@ -0,0 +1,239 @@
|
||||
/*
|
||||
File: CAAtomicStack.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAAtomicStack_h__
|
||||
#define __CAAtomicStack_h__
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <libkern/OSAtomic.h>
|
||||
#else
|
||||
#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 T *& 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->next() = mHead;
|
||||
mHead = item;
|
||||
}
|
||||
|
||||
T * pop_NA()
|
||||
{
|
||||
T *result = mHead;
|
||||
if (result)
|
||||
mHead = result->next();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool empty() const { return mHead == NULL; }
|
||||
|
||||
T * head() { return mHead; }
|
||||
|
||||
// atomic routines
|
||||
void push_atomic(T *item)
|
||||
{
|
||||
T *head_;
|
||||
do {
|
||||
head_ = mHead;
|
||||
item->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->next();
|
||||
} while (p);
|
||||
do {
|
||||
head_ = mHead;
|
||||
tail->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->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->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->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;
|
||||
};
|
||||
|
||||
// a more efficient subset of TAtomicStack using OSQueue.
|
||||
template <class T>
|
||||
class TAtomicStack2 {
|
||||
public:
|
||||
TAtomicStack2() {
|
||||
/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
|
||||
mHead.opaque1 = 0; mHead.opaque2 = 0;
|
||||
mNextPtrOffset = -1;
|
||||
}
|
||||
void push_atomic(T *item) {
|
||||
if (mNextPtrOffset < 0) {
|
||||
T **pnext = &item->next(); // hack around offsetof not working with C++
|
||||
mNextPtrOffset = (Byte *)pnext - (Byte *)item;
|
||||
}
|
||||
OSAtomicEnqueue(&mHead, item, mNextPtrOffset);
|
||||
}
|
||||
void push_NA(T *item) { push_atomic(item); }
|
||||
|
||||
T * pop_atomic() { return (T *)OSAtomicDequeue(&mHead, mNextPtrOffset); }
|
||||
T * pop_atomic_single_reader() { return pop_atomic(); }
|
||||
T * pop_NA() { return pop_atomic(); }
|
||||
|
||||
// caution: do not try to implement pop_all_reversed here. the writer could add new elements
|
||||
// while the reader is trying to pop old ones!
|
||||
|
||||
private:
|
||||
OSQueueHead mHead;
|
||||
ssize_t mNextPtrOffset;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define TAtomicStack2 TAtomicStack
|
||||
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
|
||||
|
||||
#endif // __CAAtomicStack_h__
|
@ -0,0 +1,153 @@
|
||||
/*
|
||||
File: CAAudioChannelLayout.cpp
|
||||
Abstract: CAAudioChannelLayout.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
//=============================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
File: CAAudioChannelLayout.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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);
|
||||
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 SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription) + (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;
|
||||
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((UInt32)size);
|
||||
}
|
||||
|
||||
static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
|
||||
size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
|
||||
RefCountedLayout *acl = new(size) RefCountedLayout((UInt32)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
|
@ -0,0 +1,508 @@
|
||||
/*
|
||||
File: CAAutoDisposer.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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
|
@ -0,0 +1,585 @@
|
||||
/*
|
||||
File: CADebugMacros.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#if !defined(__CADebugMacros_h__)
|
||||
#define __CADebugMacros_h__
|
||||
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.h"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// Includes
|
||||
//=============================================================================
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#else
|
||||
#include "CoreAudioTypes.h"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// CADebugMacros
|
||||
//=============================================================================
|
||||
|
||||
//#define CoreAudio_StopOnFailure 1
|
||||
//#define CoreAudio_TimeStampMessages 1
|
||||
//#define CoreAudio_ThreadStampMessages 1
|
||||
//#define CoreAudio_FlushDebugMessages 1
|
||||
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
#define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
|
||||
#define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; }
|
||||
#else
|
||||
#define CA4CCToCString(the4CC) { ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 }
|
||||
#define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; }
|
||||
#endif
|
||||
|
||||
// This is a macro that does a sizeof and casts the result to a UInt32. This is useful for all the
|
||||
// places where -wshorten64-32 catches assigning a sizeof expression to a UInt32.
|
||||
// For want of a better place to park this, we'll park it here.
|
||||
#define SizeOf32(X) ((UInt32)sizeof(X))
|
||||
|
||||
// This is a macro that does a offsetof and casts the result to a UInt32. This is useful for all the
|
||||
// places where -wshorten64-32 catches assigning an offsetof expression to a UInt32.
|
||||
// For want of a better place to park this, we'll park it here.
|
||||
#define OffsetOf32(X, Y) ((UInt32)offsetof(X, Y))
|
||||
|
||||
// This macro casts the expression to a UInt32. It is called out specially to allow us to track casts
|
||||
// that have been added purely to avert -wshorten64-32 warnings on 64 bit platforms.
|
||||
// For want of a better place to park this, we'll park it here.
|
||||
#define ToUInt32(X) ((UInt32)(X))
|
||||
#define ToSInt32(X) ((SInt32)(X))
|
||||
|
||||
#pragma mark Basic Definitions
|
||||
|
||||
#if DEBUG || CoreAudio_Debug
|
||||
// can be used to break into debugger immediately, also see CADebugger
|
||||
#define BusError() { long* p=NULL; *p=0; }
|
||||
|
||||
// basic debugging print routines
|
||||
#if TARGET_OS_MAC && !TARGET_API_MAC_CARBON
|
||||
extern void DebugStr(const unsigned char* debuggerMsg);
|
||||
#define DebugMessage(msg) DebugStr("\p"msg)
|
||||
#define DebugMessageN1(msg, N1)
|
||||
#define DebugMessageN2(msg, N1, N2)
|
||||
#define DebugMessageN3(msg, N1, N2, N3)
|
||||
#else
|
||||
#include "CADebugPrintf.h"
|
||||
|
||||
#if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
|
||||
#define FlushRtn ,fflush(DebugPrintfFile)
|
||||
#else
|
||||
#define FlushRtn
|
||||
#endif
|
||||
|
||||
#if CoreAudio_ThreadStampMessages
|
||||
#include <pthread.h>
|
||||
#include "CAHostTimeBase.h"
|
||||
#if TARGET_RT_64_BIT
|
||||
#define DebugPrintfThreadIDFormat "%16p"
|
||||
#else
|
||||
#define DebugPrintfThreadIDFormat "%8p"
|
||||
#endif
|
||||
#define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " DebugPrintfThreadIDFormat " " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), pthread_self(), ## __VA_ARGS__) FlushRtn
|
||||
#elif CoreAudio_TimeStampMessages
|
||||
#include "CAHostTimeBase.h"
|
||||
#define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), ## __VA_ARGS__) FlushRtn
|
||||
#else
|
||||
#define DebugMsg(inFormat, ...) DebugPrintf(inFormat, ## __VA_ARGS__) FlushRtn
|
||||
#endif
|
||||
#endif
|
||||
void DebugPrint(const char *fmt, ...); // can be used like printf
|
||||
#ifndef DEBUGPRINT
|
||||
#define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h)
|
||||
#endif
|
||||
#if VERBOSE
|
||||
#define vprint(msg) DEBUGPRINT(msg)
|
||||
#else
|
||||
#define vprint(msg)
|
||||
#endif
|
||||
|
||||
// Original macro keeps its function of turning on and off use of CADebuggerStop() for both asserts and throws.
|
||||
// For backwards compat, it overrides any setting of the two sub-macros.
|
||||
#if CoreAudio_StopOnFailure
|
||||
#include "CADebugger.h"
|
||||
#undef CoreAudio_StopOnAssert
|
||||
#define CoreAudio_StopOnAssert 1
|
||||
#undef CoreAudio_StopOnThrow
|
||||
#define CoreAudio_StopOnThrow 1
|
||||
#define STOP CADebuggerStop()
|
||||
#else
|
||||
#define STOP
|
||||
#endif
|
||||
|
||||
#if CoreAudio_StopOnAssert
|
||||
#if !CoreAudio_StopOnFailure
|
||||
#include "CADebugger.h"
|
||||
#define STOP
|
||||
#endif
|
||||
#define __ASSERT_STOP CADebuggerStop()
|
||||
#else
|
||||
#define __ASSERT_STOP
|
||||
#endif
|
||||
|
||||
#if CoreAudio_StopOnThrow
|
||||
#if !CoreAudio_StopOnFailure
|
||||
#include "CADebugger.h"
|
||||
#define STOP
|
||||
#endif
|
||||
#define __THROW_STOP CADebuggerStop()
|
||||
#else
|
||||
#define __THROW_STOP
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define DebugMsg(inFormat, ...)
|
||||
#ifndef DEBUGPRINT
|
||||
#define DEBUGPRINT(msg)
|
||||
#endif
|
||||
#define vprint(msg)
|
||||
#define STOP
|
||||
#define __ASSERT_STOP
|
||||
#define __THROW_STOP
|
||||
#endif
|
||||
|
||||
// Old-style numbered DebugMessage calls are implemented in terms of DebugMsg() now
|
||||
#define DebugMessage(msg) DebugMsg(msg)
|
||||
#define DebugMessageN1(msg, N1) DebugMsg(msg, N1)
|
||||
#define DebugMessageN2(msg, N1, N2) DebugMsg(msg, N1, N2)
|
||||
#define DebugMessageN3(msg, N1, N2, N3) DebugMsg(msg, N1, N2, N3)
|
||||
#define DebugMessageN4(msg, N1, N2, N3, N4) DebugMsg(msg, N1, N2, N3, N4)
|
||||
#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugMsg(msg, N1, N2, N3, N4, N5)
|
||||
#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugMsg(msg, N1, N2, N3, N4, N5, N6)
|
||||
#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7)
|
||||
#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8)
|
||||
#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)
|
||||
|
||||
void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging)
|
||||
void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging)
|
||||
|
||||
#define NO_ACTION (void)0
|
||||
|
||||
#if DEBUG || CoreAudio_Debug
|
||||
|
||||
#pragma mark Debug Macros
|
||||
|
||||
#define Assert(inCondition, inMessage) \
|
||||
if(!(inCondition)) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
__ASSERT_STOP; \
|
||||
}
|
||||
|
||||
#define AssertFileLine(inCondition, inMessage) \
|
||||
if(!(inCondition)) \
|
||||
{ \
|
||||
DebugMessageN3("%s, line %d: %s", __FILE__, __LINE__, inMessage); \
|
||||
__ASSERT_STOP; \
|
||||
}
|
||||
|
||||
#define AssertNoError(inError, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
char __4CC[5] = CA4CCToCString(__Err); \
|
||||
DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertNoKernelError(inError, inMessage) \
|
||||
{ \
|
||||
unsigned int __Err = (unsigned int)(inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertNotNULL(inPtr, inMessage) \
|
||||
{ \
|
||||
if((inPtr) == NULL) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FailIf(inCondition, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
STOP; \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
|
||||
if((inPointer) == NULL) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \
|
||||
{ \
|
||||
unsigned int __Err = (inKernelError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FailIfError(inError, inAction, inHandler, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
char __4CC[5] = CA4CCToCString(__Err); \
|
||||
DebugMessageN2(inMessage ", Error: %ld (%s)", (long int)__Err, __4CC); \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FailIfNoMessage(inCondition, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
STOP; \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \
|
||||
if((inPointer) == NULL) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \
|
||||
{ \
|
||||
unsigned int __Err = (inKernelError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
} \
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#define Throw(inException) __THROW_STOP; throw (inException)
|
||||
|
||||
#define ThrowIf(inCondition, inException, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
Throw(inException); \
|
||||
}
|
||||
|
||||
#define ThrowIfNULL(inPointer, inException, inMessage) \
|
||||
if((inPointer) == NULL) \
|
||||
{ \
|
||||
DebugMessage(inMessage); \
|
||||
Throw(inException); \
|
||||
}
|
||||
|
||||
#define ThrowIfKernelError(inKernelError, inException, inMessage) \
|
||||
{ \
|
||||
int __Err = (inKernelError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
|
||||
Throw(inException); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ThrowIfError(inError, inException, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
char __4CC[5] = CA4CCToCString(__Err); \
|
||||
DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
|
||||
Throw(inException); \
|
||||
} \
|
||||
}
|
||||
|
||||
#if TARGET_OS_WIN32
|
||||
#define ThrowIfWinError(inError, inException, inMessage) \
|
||||
{ \
|
||||
HRESULT __Err = (inError); \
|
||||
if(FAILED(__Err)) \
|
||||
{ \
|
||||
DebugMessageN2(inMessage ", Code: %d, Facility: 0x%X", HRESULT_CODE(__Err), HRESULT_FACILITY(__Err)); \
|
||||
Throw(inException); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SubclassResponsibility(inMethodName, inException) \
|
||||
{ \
|
||||
DebugMessage(inMethodName": Subclasses must implement this method"); \
|
||||
Throw(inException); \
|
||||
}
|
||||
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#else
|
||||
|
||||
#pragma mark Release Macros
|
||||
|
||||
#define Assert(inCondition, inMessage) \
|
||||
if(!(inCondition)) \
|
||||
{ \
|
||||
__ASSERT_STOP; \
|
||||
}
|
||||
|
||||
#define AssertFileLine(inCondition, inMessage) Assert(inCondition, inMessage)
|
||||
|
||||
#define AssertNoError(inError, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertNoKernelError(inError, inMessage) \
|
||||
{ \
|
||||
unsigned int __Err = (unsigned int)(inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define AssertNotNULL(inPtr, inMessage) \
|
||||
{ \
|
||||
if((inPtr) == NULL) \
|
||||
{ \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FailIf(inCondition, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
STOP; \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
|
||||
if((inPointer) == NULL) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \
|
||||
if((inKernelError) != 0) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfError(inError, inAction, inHandler, inMessage) \
|
||||
if((inError) != 0) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfNoMessage(inCondition, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
STOP; \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \
|
||||
if((inPointer) == NULL) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
}
|
||||
|
||||
#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \
|
||||
{ \
|
||||
unsigned int __Err = (inKernelError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
STOP; \
|
||||
{ inAction; } \
|
||||
goto inHandler; \
|
||||
} \
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#define Throw(inException) __THROW_STOP; throw (inException)
|
||||
|
||||
#define ThrowIf(inCondition, inException, inMessage) \
|
||||
if(inCondition) \
|
||||
{ \
|
||||
Throw(inException); \
|
||||
}
|
||||
|
||||
#define ThrowIfNULL(inPointer, inException, inMessage) \
|
||||
if((inPointer) == NULL) \
|
||||
{ \
|
||||
Throw(inException); \
|
||||
}
|
||||
|
||||
#define ThrowIfKernelError(inKernelError, inException, inMessage) \
|
||||
{ \
|
||||
int __Err = (inKernelError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
Throw(inException); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ThrowIfError(inError, inException, inMessage) \
|
||||
{ \
|
||||
SInt32 __Err = (inError); \
|
||||
if(__Err != 0) \
|
||||
{ \
|
||||
Throw(inException); \
|
||||
} \
|
||||
}
|
||||
|
||||
#if TARGET_OS_WIN32
|
||||
#define ThrowIfWinError(inError, inException, inMessage) \
|
||||
{ \
|
||||
HRESULT __Err = (inError); \
|
||||
if(FAILED(__Err)) \
|
||||
{ \
|
||||
Throw(inException); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SubclassResponsibility(inMethodName, inException) \
|
||||
{ \
|
||||
Throw(inException); \
|
||||
}
|
||||
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#endif // DEBUG || CoreAudio_Debug
|
||||
|
||||
#endif
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
File: CADebugPrintf.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#if !defined(__CADebugPrintf_h__)
|
||||
#define __CADebugPrintf_h__
|
||||
|
||||
//=============================================================================
|
||||
// Includes
|
||||
//=============================================================================
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#else
|
||||
#include "CoreAudioTypes.h"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// Macros to redirect debugging output to various logging services
|
||||
//=============================================================================
|
||||
|
||||
//#define CoreAudio_UseSysLog 1
|
||||
//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt"
|
||||
|
||||
#if DEBUG || CoreAudio_Debug
|
||||
|
||||
#if TARGET_OS_WIN32
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
#endif
|
||||
extern int CAWin32DebugPrintf(char* inFormat, ...);
|
||||
#define DebugPrintfRtn CAWin32DebugPrintf
|
||||
#define DebugPrintfFile
|
||||
#define DebugPrintfLineEnding "\n"
|
||||
#define DebugPrintfFileComma
|
||||
#else
|
||||
#if CoreAudio_UseSysLog
|
||||
#include <sys/syslog.h>
|
||||
#define DebugPrintfRtn syslog
|
||||
#define DebugPrintfFile LOG_NOTICE
|
||||
#define DebugPrintfLineEnding ""
|
||||
#define DebugPrintfFileComma DebugPrintfFile,
|
||||
#elif defined(CoreAudio_UseSideFile)
|
||||
#include <stdio.h>
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
#endif
|
||||
void OpenDebugPrintfSideFile();
|
||||
extern FILE* sDebugPrintfSideFile;
|
||||
#define DebugPrintfRtn fprintf
|
||||
#define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
|
||||
#define DebugPrintfLineEnding "\n"
|
||||
#define DebugPrintfFileComma DebugPrintfFile,
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define DebugPrintfRtn fprintf
|
||||
#define DebugPrintfFile stderr
|
||||
#define DebugPrintfLineEnding "\n"
|
||||
#define DebugPrintfFileComma DebugPrintfFile,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DebugPrintfRtn
|
||||
#define DebugPrintfFile
|
||||
#define DebugPrintfLineEnding
|
||||
#define DebugPrintfFileComma
|
||||
#define DebugPrintf(inFormat, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
File: CAException.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#if !defined(__CAException_h__)
|
||||
#define __CAException_h__
|
||||
|
||||
//=============================================================================
|
||||
// Includes
|
||||
//=============================================================================
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#else
|
||||
#include "CoreAudioTypes.h"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// CAException
|
||||
//=============================================================================
|
||||
|
||||
class CAException
|
||||
{
|
||||
|
||||
public:
|
||||
CAException(OSStatus inError) : mError(inError) {}
|
||||
CAException(const CAException& inException) : mError(inException.mError) {}
|
||||
CAException& operator=(const CAException& inException) { mError = inException.mError; return *this; }
|
||||
~CAException() {}
|
||||
|
||||
OSStatus GetError() const { return mError; }
|
||||
|
||||
protected:
|
||||
OSStatus mError;
|
||||
};
|
||||
|
||||
#define CATry try{
|
||||
#define CACatch } catch(...) {}
|
||||
#define CASwallowException(inExpression) try { inExpression; } catch(...) {}
|
||||
|
||||
#endif
|
@ -0,0 +1,234 @@
|
||||
/*
|
||||
File: CAHostTimeBase.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#if !defined(__CAHostTimeBase_h__)
|
||||
#define __CAHostTimeBase_h__
|
||||
|
||||
//=============================================================================
|
||||
// Includes
|
||||
//=============================================================================
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#else
|
||||
#include <CoreAudioTypes.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
#include <mach/mach_time.h>
|
||||
#include <pthread.h>
|
||||
#elif TARGET_OS_WIN32
|
||||
#include <windows.h>
|
||||
#include "WinPThreadDefs.h"
|
||||
#else
|
||||
#error Unsupported operating system
|
||||
#endif
|
||||
|
||||
#include "CADebugPrintf.h"
|
||||
|
||||
//=============================================================================
|
||||
// CAHostTimeBase
|
||||
//
|
||||
// This class provides platform independent access to the host's time base.
|
||||
//=============================================================================
|
||||
|
||||
#if CoreAudio_Debug
|
||||
// #define Log_Host_Time_Base_Parameters 1
|
||||
// #define Track_Host_TimeBase 1
|
||||
#endif
|
||||
|
||||
class CAHostTimeBase
|
||||
{
|
||||
|
||||
public:
|
||||
static UInt64 ConvertToNanos(UInt64 inHostTime);
|
||||
static UInt64 ConvertFromNanos(UInt64 inNanos);
|
||||
|
||||
static UInt64 GetTheCurrentTime();
|
||||
#if TARGET_OS_MAC
|
||||
static UInt64 GetCurrentTime() { return GetTheCurrentTime(); }
|
||||
#endif
|
||||
static UInt64 GetCurrentTimeInNanos();
|
||||
|
||||
static Float64 GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; }
|
||||
static Float64 GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; }
|
||||
static UInt32 GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; }
|
||||
|
||||
static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
|
||||
static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
|
||||
|
||||
static UInt64 MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator);
|
||||
|
||||
private:
|
||||
static void Initialize();
|
||||
|
||||
static pthread_once_t sIsInited;
|
||||
|
||||
static Float64 sFrequency;
|
||||
static Float64 sInverseFrequency;
|
||||
static UInt32 sMinDelta;
|
||||
static UInt32 sToNanosNumerator;
|
||||
static UInt32 sToNanosDenominator;
|
||||
#if Track_Host_TimeBase
|
||||
static UInt64 sLastTime;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline UInt64 CAHostTimeBase::GetTheCurrentTime()
|
||||
{
|
||||
UInt64 theTime = 0;
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
theTime = mach_absolute_time();
|
||||
#elif TARGET_OS_WIN32
|
||||
LARGE_INTEGER theValue;
|
||||
QueryPerformanceCounter(&theValue);
|
||||
theTime = *((UInt64*)&theValue);
|
||||
#endif
|
||||
|
||||
#if Track_Host_TimeBase
|
||||
if(sLastTime != 0)
|
||||
{
|
||||
if(theTime <= sLastTime)
|
||||
{
|
||||
DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime);
|
||||
}
|
||||
sLastTime = theTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLastTime = theTime;
|
||||
}
|
||||
#endif
|
||||
|
||||
return theTime;
|
||||
}
|
||||
|
||||
inline UInt64 CAHostTimeBase::ConvertToNanos(UInt64 inHostTime)
|
||||
{
|
||||
pthread_once(&sIsInited, Initialize);
|
||||
|
||||
UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator);
|
||||
#if CoreAudio_Debug
|
||||
if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime)))
|
||||
{
|
||||
DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped");
|
||||
}
|
||||
#endif
|
||||
|
||||
return theAnswer;
|
||||
}
|
||||
|
||||
inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
|
||||
{
|
||||
pthread_once(&sIsInited, Initialize);
|
||||
|
||||
UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator);
|
||||
#if CoreAudio_Debug
|
||||
if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos)))
|
||||
{
|
||||
DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped");
|
||||
}
|
||||
#endif
|
||||
|
||||
return theAnswer;
|
||||
}
|
||||
|
||||
inline UInt64 CAHostTimeBase::GetCurrentTimeInNanos()
|
||||
{
|
||||
return ConvertToNanos(GetTheCurrentTime());
|
||||
}
|
||||
|
||||
inline UInt64 CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
|
||||
{
|
||||
UInt64 theAnswer;
|
||||
|
||||
if(inStartTime <= inEndTime)
|
||||
{
|
||||
theAnswer = inEndTime - inStartTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
theAnswer = inStartTime - inEndTime;
|
||||
}
|
||||
|
||||
return ConvertToNanos(theAnswer);
|
||||
}
|
||||
|
||||
inline SInt64 CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
|
||||
{
|
||||
SInt64 theAnswer;
|
||||
SInt64 theSign = 1;
|
||||
|
||||
if(inStartTime <= inEndTime)
|
||||
{
|
||||
theAnswer = static_cast<SInt64>(inEndTime - inStartTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
theAnswer = static_cast<SInt64>(inStartTime - inEndTime);
|
||||
theSign = -1;
|
||||
}
|
||||
|
||||
return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer)));
|
||||
}
|
||||
|
||||
inline UInt64 CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator)
|
||||
{
|
||||
#if TARGET_OS_MAC && TARGET_RT_64_BIT
|
||||
__uint128_t theAnswer = inMuliplicand;
|
||||
#else
|
||||
long double theAnswer = inMuliplicand;
|
||||
#endif
|
||||
if(inNumerator != inDenominator)
|
||||
{
|
||||
theAnswer *= inNumerator;
|
||||
theAnswer /= inDenominator;
|
||||
}
|
||||
return static_cast<UInt64>(theAnswer);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
File: CAMath.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAMath_h__
|
||||
#define __CAMath_h__
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#else
|
||||
#include <CoreAudioTypes.h>
|
||||
#endif
|
||||
|
||||
inline bool fiszero(Float64 f) { return (f == 0.); }
|
||||
inline bool fiszero(Float32 f) { return (f == 0.f); }
|
||||
|
||||
inline bool fnonzero(Float64 f) { return !fiszero(f); }
|
||||
inline bool fnonzero(Float32 f) { return !fiszero(f); }
|
||||
|
||||
inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
|
||||
inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
|
||||
|
||||
inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
|
||||
inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
|
||||
|
||||
#endif // __CAMath_h__
|
@ -0,0 +1,345 @@
|
||||
/*
|
||||
File: CAMutex.cpp
|
||||
Abstract: CAMutex.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
//==================================================================================================
|
||||
// Includes
|
||||
//==================================================================================================
|
||||
|
||||
// Self Include
|
||||
#include "CAMutex.h"
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
// PublicUtility Includes
|
||||
#include "CADebugMacros.h"
|
||||
#include "CAException.h"
|
||||
#include "CAHostTimeBase.h"
|
||||
|
||||
//==================================================================================================
|
||||
// Logging
|
||||
//==================================================================================================
|
||||
|
||||
#if CoreAudio_Debug
|
||||
// #define Log_Ownership 1
|
||||
// #define Log_Errors 1
|
||||
// #define Log_LongLatencies 1
|
||||
// #define LongLatencyThreshholdNS 1000000ULL // nanoseconds
|
||||
#endif
|
||||
|
||||
//==================================================================================================
|
||||
// CAMutex
|
||||
//==================================================================================================
|
||||
|
||||
CAMutex::CAMutex(const char* inName)
|
||||
:
|
||||
mName(inName),
|
||||
mOwner(0)
|
||||
{
|
||||
#if TARGET_OS_MAC
|
||||
OSStatus theError = pthread_mutex_init(&mMutex, NULL);
|
||||
ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex");
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
|
||||
#endif
|
||||
#elif TARGET_OS_WIN32
|
||||
mMutex = CreateMutex(NULL, false, NULL);
|
||||
ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex.");
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
CAMutex::~CAMutex()
|
||||
{
|
||||
#if TARGET_OS_MAC
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
|
||||
#endif
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
#elif TARGET_OS_WIN32
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
|
||||
#endif
|
||||
if(mMutex != NULL)
|
||||
{
|
||||
CloseHandle(mMutex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CAMutex::Lock()
|
||||
{
|
||||
bool theAnswer = false;
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
pthread_t theCurrentThread = pthread_self();
|
||||
if(!pthread_equal(theCurrentThread, mOwner))
|
||||
{
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
|
||||
#endif
|
||||
|
||||
#if Log_LongLatencies
|
||||
UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos();
|
||||
#endif
|
||||
|
||||
OSStatus theError = pthread_mutex_lock(&mMutex);
|
||||
ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex");
|
||||
mOwner = theCurrentThread;
|
||||
theAnswer = true;
|
||||
|
||||
#if Log_LongLatencies
|
||||
UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos();
|
||||
if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS)
|
||||
DebugPrintfRtn(DebugPrintfFileComma "Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName);
|
||||
#endif
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
#elif TARGET_OS_WIN32
|
||||
if(mOwner != GetCurrentThreadId())
|
||||
{
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
|
||||
OSStatus theError = WaitForSingleObject(mMutex, INFINITE);
|
||||
ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex");
|
||||
mOwner = GetCurrentThreadId();
|
||||
theAnswer = true;
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return theAnswer;
|
||||
}
|
||||
|
||||
void CAMutex::Unlock()
|
||||
{
|
||||
#if TARGET_OS_MAC
|
||||
if(pthread_equal(pthread_self(), mOwner))
|
||||
{
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
|
||||
#endif
|
||||
|
||||
mOwner = 0;
|
||||
OSStatus theError = pthread_mutex_unlock(&mMutex);
|
||||
ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex");
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
|
||||
}
|
||||
#elif TARGET_OS_WIN32
|
||||
if(mOwner == GetCurrentThreadId())
|
||||
{
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
|
||||
mOwner = 0;
|
||||
bool wasReleased = ReleaseMutex(mMutex);
|
||||
ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex");
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CAMutex::Try(bool& outWasLocked)
|
||||
{
|
||||
bool theAnswer = false;
|
||||
outWasLocked = false;
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
pthread_t theCurrentThread = pthread_self();
|
||||
if(!pthread_equal(theCurrentThread, mOwner))
|
||||
{
|
||||
// this means the current thread doesn't already own the lock
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
|
||||
#endif
|
||||
|
||||
// go ahead and call trylock to see if we can lock it.
|
||||
int theError = pthread_mutex_trylock(&mMutex);
|
||||
if(theError == 0)
|
||||
{
|
||||
// return value of 0 means we successfully locked the lock
|
||||
mOwner = theCurrentThread;
|
||||
theAnswer = true;
|
||||
outWasLocked = true;
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
else if(theError == EBUSY)
|
||||
{
|
||||
// return value of EBUSY means that the lock was already locked by another thread
|
||||
theAnswer = false;
|
||||
outWasLocked = false;
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// any other return value means something really bad happenned
|
||||
ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this means the current thread already owns the lock
|
||||
theAnswer = true;
|
||||
outWasLocked = false;
|
||||
}
|
||||
#elif TARGET_OS_WIN32
|
||||
if(mOwner != GetCurrentThreadId())
|
||||
{
|
||||
// this means the current thread doesn't own the lock
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
|
||||
// try to acquire the mutex
|
||||
OSStatus theError = WaitForSingleObject(mMutex, 0);
|
||||
if(theError == WAIT_OBJECT_0)
|
||||
{
|
||||
// this means we successfully locked the lock
|
||||
mOwner = GetCurrentThreadId();
|
||||
theAnswer = true;
|
||||
outWasLocked = true;
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
else if(theError == WAIT_TIMEOUT)
|
||||
{
|
||||
// this means that the lock was already locked by another thread
|
||||
theAnswer = false;
|
||||
outWasLocked = false;
|
||||
|
||||
#if Log_Ownership
|
||||
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// any other return value means something really bad happenned
|
||||
ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this means the current thread already owns the lock
|
||||
theAnswer = true;
|
||||
outWasLocked = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return theAnswer;
|
||||
}
|
||||
|
||||
bool CAMutex::IsFree() const
|
||||
{
|
||||
return mOwner == 0;
|
||||
}
|
||||
|
||||
bool CAMutex::IsOwnedByCurrentThread() const
|
||||
{
|
||||
bool theAnswer = true;
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
theAnswer = pthread_equal(pthread_self(), mOwner);
|
||||
#elif TARGET_OS_WIN32
|
||||
theAnswer = (mOwner == GetCurrentThreadId());
|
||||
#endif
|
||||
|
||||
return theAnswer;
|
||||
}
|
||||
|
||||
|
||||
CAMutex::Unlocker::Unlocker(CAMutex& inMutex)
|
||||
: mMutex(inMutex),
|
||||
mNeedsLock(false)
|
||||
{
|
||||
Assert(mMutex.IsOwnedByCurrentThread(), "Major problem: Unlocker attempted to unlock a mutex not owned by the current thread!");
|
||||
|
||||
mMutex.Unlock();
|
||||
mNeedsLock = true;
|
||||
}
|
||||
|
||||
CAMutex::Unlocker::~Unlocker()
|
||||
{
|
||||
if(mNeedsLock)
|
||||
{
|
||||
mMutex.Lock();
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
File: CAMutex.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAMutex_h__
|
||||
#define __CAMutex_h__
|
||||
|
||||
//==================================================================================================
|
||||
// Includes
|
||||
//==================================================================================================
|
||||
|
||||
// System Includes
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#else
|
||||
#include <CoreAudioTypes.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
#include <pthread.h>
|
||||
#elif TARGET_OS_WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#error Unsupported operating system
|
||||
#endif
|
||||
|
||||
//==================================================================================================
|
||||
// A recursive mutex.
|
||||
//==================================================================================================
|
||||
|
||||
class CAMutex
|
||||
{
|
||||
// Construction/Destruction
|
||||
public:
|
||||
CAMutex(const char* inName);
|
||||
virtual ~CAMutex();
|
||||
|
||||
// Actions
|
||||
public:
|
||||
virtual bool Lock();
|
||||
virtual void Unlock();
|
||||
virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not
|
||||
|
||||
virtual bool IsFree() const;
|
||||
virtual bool IsOwnedByCurrentThread() const;
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
const char* mName;
|
||||
#if TARGET_OS_MAC
|
||||
pthread_t mOwner;
|
||||
pthread_mutex_t mMutex;
|
||||
#elif TARGET_OS_WIN32
|
||||
UInt32 mOwner;
|
||||
HANDLE mMutex;
|
||||
#endif
|
||||
|
||||
// Helper class to manage taking and releasing recursively
|
||||
public:
|
||||
class Locker
|
||||
{
|
||||
|
||||
// Construction/Destruction
|
||||
public:
|
||||
Locker(CAMutex& inMutex) : mMutex(&inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex->Lock(); }
|
||||
Locker(CAMutex* inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = (mMutex != NULL && mMutex->Lock()); }
|
||||
// in this case the mutex can be null
|
||||
~Locker() { if(mNeedsRelease) { mMutex->Unlock(); } }
|
||||
|
||||
|
||||
private:
|
||||
Locker(const Locker&);
|
||||
Locker& operator=(const Locker&);
|
||||
|
||||
// Implementation
|
||||
private:
|
||||
CAMutex* mMutex;
|
||||
bool mNeedsRelease;
|
||||
|
||||
};
|
||||
|
||||
// Unlocker
|
||||
class Unlocker
|
||||
{
|
||||
public:
|
||||
Unlocker(CAMutex& inMutex);
|
||||
~Unlocker();
|
||||
|
||||
private:
|
||||
CAMutex& mMutex;
|
||||
bool mNeedsLock;
|
||||
|
||||
// Hidden definitions of copy ctor, assignment operator
|
||||
Unlocker(const Unlocker& copy); // Not implemented
|
||||
Unlocker& operator=(const Unlocker& copy); // Not implemented
|
||||
};
|
||||
|
||||
// you can use this with Try - if you take the lock in try, pass in the outWasLocked var
|
||||
class Tryer {
|
||||
|
||||
// Construction/Destruction
|
||||
public:
|
||||
Tryer (CAMutex &mutex) : mMutex(mutex), mNeedsRelease(false), mHasLock(false) { mHasLock = mMutex.Try (mNeedsRelease); }
|
||||
~Tryer () { if (mNeedsRelease) mMutex.Unlock(); }
|
||||
|
||||
bool HasLock () const { return mHasLock; }
|
||||
|
||||
private:
|
||||
Tryer(const Tryer&);
|
||||
Tryer& operator=(const Tryer&);
|
||||
|
||||
// Implementation
|
||||
private:
|
||||
CAMutex & mMutex;
|
||||
bool mNeedsRelease;
|
||||
bool mHasLock;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif // __CAMutex_h__
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
File: CAReferenceCounted.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAReferenceCounted_h__
|
||||
#define __CAReferenceCounted_h__
|
||||
|
||||
#include "CAAtomic.h"
|
||||
|
||||
// base class for reference-counted objects
|
||||
class CAReferenceCounted {
|
||||
public:
|
||||
CAReferenceCounted() : mRefCount(1) {}
|
||||
|
||||
void retain() { CAAtomicIncrement32(&mRefCount); }
|
||||
|
||||
void release()
|
||||
{
|
||||
SInt32 rc = CAAtomicDecrement32(&mRefCount);
|
||||
if (rc == 0) {
|
||||
releaseObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Retainer {
|
||||
public:
|
||||
Retainer(CAReferenceCounted *obj) : mObject(obj) { mObject->retain(); }
|
||||
~Retainer() { mObject->release(); }
|
||||
|
||||
private:
|
||||
CAReferenceCounted * mObject;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual ~CAReferenceCounted() { }
|
||||
|
||||
virtual void releaseObject ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public:
|
||||
#endif
|
||||
SInt32 GetReferenceCount() const { return mRefCount; }
|
||||
private:
|
||||
SInt32 mRefCount;
|
||||
|
||||
CAReferenceCounted(const CAReferenceCounted &a);
|
||||
CAReferenceCounted &operator=(const CAReferenceCounted &a);
|
||||
};
|
||||
|
||||
|
||||
#endif // __CAReferenceCounted_h__
|
@ -0,0 +1,879 @@
|
||||
/*
|
||||
File: CAStreamBasicDescription.cpp
|
||||
Abstract: CAStreamBasicDescription.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "CAStreamBasicDescription.h"
|
||||
#include "CAMath.h"
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreFoundation/CFByteOrder.h>
|
||||
#else
|
||||
#include <CFByteOrder.h>
|
||||
#endif
|
||||
|
||||
#pragma mark This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it
|
||||
|
||||
char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize)
|
||||
{
|
||||
if (bufsize > 0) {
|
||||
char *p = writeLocation, *pend = writeLocation + bufsize;
|
||||
union { UInt32 i; unsigned char str[4]; } u;
|
||||
unsigned char *q = u.str;
|
||||
u.i = CFSwapInt32HostToBig(t);
|
||||
|
||||
bool hasNonPrint = false;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (!(isprint(*q) && *q != '\\')) {
|
||||
hasNonPrint = true;
|
||||
break;
|
||||
}
|
||||
q++;
|
||||
}
|
||||
q = u.str;
|
||||
|
||||
if (hasNonPrint)
|
||||
p += snprintf (p, pend - p, "0x");
|
||||
else if (p < pend)
|
||||
*p++ = '\'';
|
||||
|
||||
for (int i = 0; i < 4 && p < pend; ++i) {
|
||||
if (hasNonPrint) {
|
||||
p += snprintf(p, pend - p, "%02X", *q++);
|
||||
} else {
|
||||
*p++ = *q++;
|
||||
}
|
||||
}
|
||||
if (!hasNonPrint && p < pend)
|
||||
*p++ = '\'';
|
||||
if (p >= pend) p -= 1;
|
||||
*p = '\0';
|
||||
}
|
||||
return writeLocation;
|
||||
}
|
||||
|
||||
|
||||
const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
CAStreamBasicDescription::CAStreamBasicDescription()
|
||||
{
|
||||
memset (this, 0, sizeof(AudioStreamBasicDescription));
|
||||
}
|
||||
|
||||
CAStreamBasicDescription::CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
|
||||
{
|
||||
SetFrom(desc);
|
||||
}
|
||||
|
||||
|
||||
CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate, UInt32 inFormatID,
|
||||
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
|
||||
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
|
||||
UInt32 inBitsPerChannel, UInt32 inFormatFlags)
|
||||
{
|
||||
mSampleRate = inSampleRate;
|
||||
mFormatID = inFormatID;
|
||||
mBytesPerPacket = inBytesPerPacket;
|
||||
mFramesPerPacket = inFramesPerPacket;
|
||||
mBytesPerFrame = inBytesPerFrame;
|
||||
mChannelsPerFrame = inChannelsPerFrame;
|
||||
mBitsPerChannel = inBitsPerChannel;
|
||||
mFormatFlags = inFormatFlags;
|
||||
mReserved = 0;
|
||||
}
|
||||
|
||||
char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize, bool brief /*=false*/) const
|
||||
{
|
||||
int bufsize = (int)_bufsize; // must be signed to protect against overflow
|
||||
char *theBuffer = buf;
|
||||
int nc;
|
||||
char formatID[24];
|
||||
CAStringForOSType(mFormatID, formatID, sizeof(formatID));
|
||||
if (brief) {
|
||||
CommonPCMFormat com;
|
||||
bool interleaved;
|
||||
if (IdentifyCommonPCMFormat(com, &interleaved) && com != kPCMFormatOther) {
|
||||
const char *desc;
|
||||
switch (com) {
|
||||
case kPCMFormatInt16:
|
||||
desc = "Int16";
|
||||
break;
|
||||
case kPCMFormatFixed824:
|
||||
desc = "Int8.24";
|
||||
break;
|
||||
case kPCMFormatFloat32:
|
||||
desc = "Float32";
|
||||
break;
|
||||
case kPCMFormatFloat64:
|
||||
desc = "Float64";
|
||||
break;
|
||||
default:
|
||||
desc = NULL;
|
||||
break;
|
||||
}
|
||||
if (desc) {
|
||||
const char *inter ="";
|
||||
if (mChannelsPerFrame > 1)
|
||||
inter = !interleaved ? ", non-inter" : ", inter";
|
||||
snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s%s", (int)mChannelsPerFrame, mSampleRate, desc, inter);
|
||||
return theBuffer;
|
||||
}
|
||||
}
|
||||
if (mChannelsPerFrame == 0 && mSampleRate == 0.0 && mFormatID == 0) {
|
||||
snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate);
|
||||
return theBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
nc = snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags);
|
||||
buf += nc; if ((bufsize -= nc) <= 0) goto exit;
|
||||
if (mFormatID == kAudioFormatLinearPCM) {
|
||||
bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
|
||||
int wordSize = static_cast<int>(SampleWordSize());
|
||||
const char *endian = (wordSize > 1) ?
|
||||
((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
|
||||
const char *sign = isInt ?
|
||||
((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
|
||||
const char *floatInt = isInt ? "integer" : "float";
|
||||
char packed[32];
|
||||
if (wordSize > 0 && PackednessIsSignificant()) {
|
||||
if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
|
||||
snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize);
|
||||
else
|
||||
snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize);
|
||||
} else
|
||||
packed[0] = '\0';
|
||||
const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
|
||||
((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
|
||||
const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
|
||||
const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
|
||||
char bitdepth[20];
|
||||
|
||||
int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
|
||||
if (fracbits > 0)
|
||||
snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits);
|
||||
else
|
||||
snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel);
|
||||
|
||||
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%s-bit%s%s %s%s%s%s%s",
|
||||
bitdepth, endian, sign, floatInt,
|
||||
commaSpace, packed, align, deinter);
|
||||
// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
|
||||
} else if (mFormatID == kAudioFormatAppleLossless) {
|
||||
int sourceBits = 0;
|
||||
switch (mFormatFlags)
|
||||
{
|
||||
case 1: // kAppleLosslessFormatFlag_16BitSourceData
|
||||
sourceBits = 16;
|
||||
break;
|
||||
case 2: // kAppleLosslessFormatFlag_20BitSourceData
|
||||
sourceBits = 20;
|
||||
break;
|
||||
case 3: // kAppleLosslessFormatFlag_24BitSourceData
|
||||
sourceBits = 24;
|
||||
break;
|
||||
case 4: // kAppleLosslessFormatFlag_32BitSourceData
|
||||
sourceBits = 32;
|
||||
break;
|
||||
}
|
||||
if (sourceBits)
|
||||
nc = snprintf(buf, static_cast<size_t>(bufsize), "from %d-bit source, ", sourceBits);
|
||||
else
|
||||
nc = snprintf(buf, static_cast<size_t>(bufsize), "from UNKNOWN source bit depth, ");
|
||||
buf += nc; if ((bufsize -= nc) <= 0) goto exit;
|
||||
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d frames/packet", (int)mFramesPerPacket);
|
||||
// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
|
||||
}
|
||||
else
|
||||
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame",
|
||||
(int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame);
|
||||
exit:
|
||||
return theBuffer;
|
||||
}
|
||||
|
||||
void CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
|
||||
{
|
||||
// the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
|
||||
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
|
||||
{
|
||||
// the canonical linear PCM format
|
||||
ioDescription.mFormatFlags = kAudioFormatFlagsCanonical;
|
||||
ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
|
||||
ioDescription.mFramesPerPacket = 1;
|
||||
ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
|
||||
ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
|
||||
}
|
||||
}
|
||||
|
||||
void CAStreamBasicDescription::NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription)
|
||||
{
|
||||
// the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
|
||||
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
|
||||
{
|
||||
// the canonical linear PCM format
|
||||
ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
|
||||
if(inNativeEndian)
|
||||
{
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if TARGET_RT_LITTLE_ENDIAN
|
||||
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
|
||||
#endif
|
||||
}
|
||||
ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
|
||||
ioDescription.mFramesPerPacket = 1;
|
||||
ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
|
||||
ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
|
||||
}
|
||||
}
|
||||
|
||||
void CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
|
||||
{
|
||||
ioDescription.mSampleRate = 0;
|
||||
ioDescription.mFormatID = 0;
|
||||
ioDescription.mBytesPerPacket = 0;
|
||||
ioDescription.mFramesPerPacket = 0;
|
||||
ioDescription.mBytesPerFrame = 0;
|
||||
ioDescription.mChannelsPerFrame = 0;
|
||||
ioDescription.mBitsPerChannel = 0;
|
||||
ioDescription.mFormatFlags = 0;
|
||||
}
|
||||
|
||||
void CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
|
||||
{
|
||||
if(fiszero(ioDescription.mSampleRate))
|
||||
{
|
||||
ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
|
||||
}
|
||||
if(ioDescription.mFormatID == 0)
|
||||
{
|
||||
ioDescription.mFormatID = inTemplateDescription.mFormatID;
|
||||
}
|
||||
if(ioDescription.mFormatFlags == 0)
|
||||
{
|
||||
ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
|
||||
}
|
||||
if(ioDescription.mBytesPerPacket == 0)
|
||||
{
|
||||
ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
|
||||
}
|
||||
if(ioDescription.mFramesPerPacket == 0)
|
||||
{
|
||||
ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
|
||||
}
|
||||
if(ioDescription.mBytesPerFrame == 0)
|
||||
{
|
||||
ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
|
||||
}
|
||||
if(ioDescription.mChannelsPerFrame == 0)
|
||||
{
|
||||
ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
|
||||
}
|
||||
if(ioDescription.mBitsPerChannel == 0)
|
||||
{
|
||||
ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
|
||||
}
|
||||
}
|
||||
|
||||
void CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate)
|
||||
{
|
||||
if(inIncludeSampleRate)
|
||||
{
|
||||
int theCharactersWritten = snprintf(outName, inMaxNameLength, "%.0f ", inDescription.mSampleRate);
|
||||
outName += theCharactersWritten;
|
||||
inMaxNameLength -= static_cast<UInt32>(theCharactersWritten);
|
||||
}
|
||||
|
||||
switch(inDescription.mFormatID)
|
||||
{
|
||||
case kAudioFormatLinearPCM:
|
||||
{
|
||||
const char* theEndianString = NULL;
|
||||
if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
|
||||
{
|
||||
#if TARGET_RT_LITTLE_ENDIAN
|
||||
theEndianString = "Big Endian";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
theEndianString = "Little Endian";
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* theKindString = NULL;
|
||||
if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
|
||||
{
|
||||
theKindString = (inAbbreviate ? "Float" : "Floating Point");
|
||||
}
|
||||
else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
|
||||
{
|
||||
theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
|
||||
}
|
||||
else
|
||||
{
|
||||
theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
|
||||
}
|
||||
|
||||
const char* thePackingString = NULL;
|
||||
if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
|
||||
{
|
||||
if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
|
||||
{
|
||||
thePackingString = "High";
|
||||
}
|
||||
else
|
||||
{
|
||||
thePackingString = "Low";
|
||||
}
|
||||
}
|
||||
|
||||
const char* theMixabilityString = NULL;
|
||||
if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
|
||||
{
|
||||
theMixabilityString = "Mixable";
|
||||
}
|
||||
else
|
||||
{
|
||||
theMixabilityString = "Unmixable";
|
||||
}
|
||||
|
||||
if(inAbbreviate)
|
||||
{
|
||||
if(theEndianString != NULL)
|
||||
{
|
||||
if(thePackingString != NULL)
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(thePackingString != NULL)
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(theEndianString != NULL)
|
||||
{
|
||||
if(thePackingString != NULL)
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(thePackingString != NULL)
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioFormatAC3:
|
||||
strlcpy(outName, "AC-3", sizeof(outName));
|
||||
break;
|
||||
|
||||
case kAudioFormat60958AC3:
|
||||
strlcpy(outName, "AC-3 for SPDIF", sizeof(outName));
|
||||
break;
|
||||
|
||||
default:
|
||||
CACopy4CCToCString(outName, inDescription.mFormatID);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
#if CoreAudio_Debug
|
||||
#include "CALogMacros.h"
|
||||
|
||||
void CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
|
||||
{
|
||||
PrintFloat (" Sample Rate: ", inDesc.mSampleRate);
|
||||
Print4CharCode (" Format ID: ", inDesc.mFormatID);
|
||||
PrintHex (" Format Flags: ", inDesc.mFormatFlags);
|
||||
PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket);
|
||||
PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket);
|
||||
PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame);
|
||||
PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame);
|
||||
PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
|
||||
{
|
||||
bool theAnswer = false;
|
||||
bool isDone = false;
|
||||
|
||||
// note that if either side is 0, that field is skipped
|
||||
|
||||
// format ID is the first order sort
|
||||
if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
|
||||
{
|
||||
if(x.mFormatID != y.mFormatID)
|
||||
{
|
||||
// formats are sorted numerically except that linear
|
||||
// PCM is always first
|
||||
if(x.mFormatID == kAudioFormatLinearPCM)
|
||||
{
|
||||
theAnswer = true;
|
||||
}
|
||||
else if(y.mFormatID == kAudioFormatLinearPCM)
|
||||
{
|
||||
theAnswer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
theAnswer = x.mFormatID < y.mFormatID;
|
||||
}
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mixable is always better than non-mixable for linear PCM and should be the second order sort item
|
||||
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
|
||||
{
|
||||
if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
|
||||
{
|
||||
theAnswer = true;
|
||||
isDone = true;
|
||||
}
|
||||
else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
|
||||
{
|
||||
theAnswer = false;
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
// floating point vs integer for linear PCM only
|
||||
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
|
||||
{
|
||||
if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
|
||||
{
|
||||
// floating point is better than integer
|
||||
theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
// bit depth
|
||||
if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
|
||||
{
|
||||
if(x.mBitsPerChannel != y.mBitsPerChannel)
|
||||
{
|
||||
// deeper bit depths are higher quality
|
||||
theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
// sample rate
|
||||
if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
|
||||
{
|
||||
if(fnotequal(x.mSampleRate, y.mSampleRate))
|
||||
{
|
||||
// higher sample rates are higher quality
|
||||
theAnswer = x.mSampleRate < y.mSampleRate;
|
||||
isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
// number of channels
|
||||
if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
|
||||
{
|
||||
if(x.mChannelsPerFrame != y.mChannelsPerFrame)
|
||||
{
|
||||
// more channels is higher quality
|
||||
theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
|
||||
//isDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
return theAnswer;
|
||||
}
|
||||
|
||||
void CAStreamBasicDescription::ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly )
|
||||
{
|
||||
// match wildcards
|
||||
if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0)
|
||||
{
|
||||
// Obliterate all flags.
|
||||
xFlags = yFlags = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x.mFormatID == kAudioFormatLinearPCM) {
|
||||
// knock off the all clear flag
|
||||
xFlags = xFlags & ~kAudioFormatFlagsAreAllClear;
|
||||
yFlags = yFlags & ~kAudioFormatFlagsAreAllClear;
|
||||
|
||||
// if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit.
|
||||
if (xFlags & yFlags & kAudioFormatFlagIsPacked) {
|
||||
xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
|
||||
yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
|
||||
}
|
||||
|
||||
// if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit.
|
||||
if (xFlags & yFlags & kAudioFormatFlagIsFloat) {
|
||||
xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
|
||||
yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
|
||||
}
|
||||
|
||||
// if the bit depth is 8 bits or less and the format is packed, we don't care about endianness
|
||||
if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
|
||||
{
|
||||
xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
|
||||
}
|
||||
if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
|
||||
{
|
||||
yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
|
||||
}
|
||||
|
||||
// if the number of channels is 1, we don't care about non-interleavedness
|
||||
if (x.mChannelsPerFrame == 1 && y.mChannelsPerFrame == 1) {
|
||||
xFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
|
||||
yFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
|
||||
}
|
||||
|
||||
if (converterOnly) {
|
||||
CAStreamBasicDescription cas_x = CAStreamBasicDescription(x);
|
||||
CAStreamBasicDescription cas_y = CAStreamBasicDescription(y);
|
||||
if (!cas_x.PackednessIsSignificant() && !cas_y.PackednessIsSignificant()) {
|
||||
xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
|
||||
yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
|
||||
}
|
||||
if (!cas_x.AlignmentIsSignificant() && !cas_y.AlignmentIsSignificant()) {
|
||||
xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
|
||||
yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
|
||||
}
|
||||
// We don't care about whether the streams are mixable in this case
|
||||
xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
|
||||
yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
|
||||
{
|
||||
UInt32 xFlags = x.mFormatFlags;
|
||||
UInt32 yFlags = y.mFormatFlags;
|
||||
|
||||
CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, false);
|
||||
return xFlags == yFlags;
|
||||
}
|
||||
|
||||
bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
|
||||
{
|
||||
// the semantics for equality are:
|
||||
// 1) Values must match exactly -- except for PCM format flags, see above.
|
||||
// 2) wildcard's are ignored in the comparison
|
||||
|
||||
#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
|
||||
|
||||
return
|
||||
// check all but the format flags
|
||||
CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
|
||||
// check the format flags
|
||||
&& MatchFormatFlags(x, y);
|
||||
}
|
||||
|
||||
bool CAStreamBasicDescription::FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
|
||||
{
|
||||
return
|
||||
// check the sample rate
|
||||
(fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
|
||||
|
||||
// check the format ids
|
||||
&& MATCH(mFormatID)
|
||||
|
||||
// check the bytes per packet
|
||||
&& MATCH(mBytesPerPacket)
|
||||
|
||||
// check the frames per packet
|
||||
&& MATCH(mFramesPerPacket)
|
||||
|
||||
// check the bytes per frame
|
||||
&& MATCH(mBytesPerFrame)
|
||||
|
||||
// check the channels per frame
|
||||
&& MATCH(mChannelsPerFrame)
|
||||
|
||||
// check the channels per frame
|
||||
&& MATCH(mBitsPerChannel) ;
|
||||
}
|
||||
|
||||
bool CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const
|
||||
{
|
||||
if (interpretingWildcards)
|
||||
return *this == other;
|
||||
return memcmp(this, &other, offsetof(AudioStreamBasicDescription, mReserved)) == 0;
|
||||
}
|
||||
|
||||
bool CAStreamBasicDescription::IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
|
||||
{
|
||||
UInt32 xFlags = x.mFormatFlags, yFlags = y.mFormatFlags;
|
||||
CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, true);
|
||||
|
||||
return
|
||||
// check all but the format flags
|
||||
CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
|
||||
// check the format flags with converter focus
|
||||
&& (xFlags == yFlags);
|
||||
|
||||
}
|
||||
|
||||
bool SanityCheck(const AudioStreamBasicDescription& x)
|
||||
{
|
||||
// This function returns false if there are sufficiently insane values in any field.
|
||||
// It is very conservative so even some very unlikely values will pass.
|
||||
// This is just meant to catch the case where the data from a file is corrupted.
|
||||
|
||||
return
|
||||
(x.mSampleRate >= 0.)
|
||||
&& (x.mSampleRate < 3e6) // SACD sample rate is 2.8224 MHz
|
||||
&& (x.mBytesPerPacket < 1000000)
|
||||
&& (x.mFramesPerPacket < 1000000)
|
||||
&& (x.mBytesPerFrame < 1000000)
|
||||
&& (x.mChannelsPerFrame <= 1024)
|
||||
&& (x.mBitsPerChannel <= 1024)
|
||||
&& (x.mFormatID != 0)
|
||||
&& !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
|
||||
}
|
||||
|
||||
bool CAStreamBasicDescription::FromText(const char *inTextDesc, AudioStreamBasicDescription &fmt)
|
||||
{
|
||||
const char *p = inTextDesc;
|
||||
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
|
||||
bool isPCM = true; // until proven otherwise
|
||||
UInt32 pcmFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
|
||||
|
||||
if (p[0] == '-') // previously we required a leading dash on PCM formats
|
||||
++p;
|
||||
|
||||
if (p[0] == 'B' && p[1] == 'E') {
|
||||
pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
|
||||
p += 2;
|
||||
} else if (p[0] == 'L' && p[1] == 'E') {
|
||||
p += 2;
|
||||
} else {
|
||||
// default is native-endian
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
|
||||
#endif
|
||||
}
|
||||
if (p[0] == 'F') {
|
||||
pcmFlags = (pcmFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat;
|
||||
++p;
|
||||
} else {
|
||||
if (p[0] == 'U') {
|
||||
pcmFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
|
||||
++p;
|
||||
}
|
||||
if (p[0] == 'I')
|
||||
++p;
|
||||
else {
|
||||
// it's not PCM; presumably some other format (NOT VALIDATED; use AudioFormat for that)
|
||||
isPCM = false;
|
||||
p = inTextDesc; // go back to the beginning
|
||||
char buf[4] = { ' ',' ',' ',' ' };
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (*p != '\\') {
|
||||
if ((buf[i] = *p++) == '\0') {
|
||||
// special-case for 'aac'
|
||||
if (i != 3) return false;
|
||||
--p; // keep pointing at the terminating null
|
||||
buf[i] = ' ';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// "\xNN" is a hex byte
|
||||
if (*++p != 'x') return false;
|
||||
int x;
|
||||
if (sscanf(++p, "%02X", &x) != 1) return false;
|
||||
buf[i] = static_cast<char>(x);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (strchr("-@/#", buf[3])) {
|
||||
// further special-casing for 'aac'
|
||||
buf[3] = ' ';
|
||||
--p;
|
||||
}
|
||||
|
||||
memcpy(&fmt.mFormatID, buf, 4);
|
||||
fmt.mFormatID = CFSwapInt32BigToHost(fmt.mFormatID);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPCM) {
|
||||
fmt.mFormatID = kAudioFormatLinearPCM;
|
||||
fmt.mFormatFlags = pcmFlags;
|
||||
fmt.mFramesPerPacket = 1;
|
||||
fmt.mChannelsPerFrame = 1;
|
||||
UInt32 bitdepth = 0, fracbits = 0;
|
||||
while (isdigit(*p))
|
||||
bitdepth = 10 * bitdepth + static_cast<UInt32>(*p++ - '0');
|
||||
if (*p == '.') {
|
||||
++p;
|
||||
if (!isdigit(*p)) {
|
||||
fprintf(stderr, "Expected fractional bits following '.'\n");
|
||||
goto Bail;
|
||||
}
|
||||
while (isdigit(*p))
|
||||
fracbits = 10 * fracbits + static_cast<UInt32>(*p++ - '0');
|
||||
bitdepth += fracbits;
|
||||
fmt.mFormatFlags |= (fracbits << kLinearPCMFormatFlagsSampleFractionShift);
|
||||
}
|
||||
fmt.mBitsPerChannel = bitdepth;
|
||||
fmt.mBytesPerPacket = fmt.mBytesPerFrame = (bitdepth + 7) / 8;
|
||||
if (bitdepth & 7) {
|
||||
// assume unpacked. (packed odd bit depths are describable but not supported in AudioConverter.)
|
||||
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
|
||||
// alignment matters; default to high-aligned. use ':L_' for low.
|
||||
fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
|
||||
}
|
||||
}
|
||||
if (*p == '@') {
|
||||
++p;
|
||||
while (isdigit(*p))
|
||||
fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0');
|
||||
}
|
||||
if (*p == '/') {
|
||||
UInt32 flags = 0;
|
||||
while (true) {
|
||||
char c = *++p;
|
||||
if (c >= '0' && c <= '9')
|
||||
flags = (flags << 4) | static_cast<UInt32>(c - '0');
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
flags = (flags << 4) | static_cast<UInt32>(c - 'A' + 10);
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
flags = (flags << 4) | static_cast<UInt32>(c - 'a' + 10);
|
||||
else break;
|
||||
}
|
||||
fmt.mFormatFlags = flags;
|
||||
}
|
||||
if (*p == '#') {
|
||||
++p;
|
||||
while (isdigit(*p))
|
||||
fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast<UInt32>(*p++ - '0');
|
||||
}
|
||||
if (*p == ':') {
|
||||
++p;
|
||||
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
|
||||
if (*p == 'L')
|
||||
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsAlignedHigh);
|
||||
else if (*p == 'H')
|
||||
fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
|
||||
else
|
||||
goto Bail;
|
||||
++p;
|
||||
UInt32 bytesPerFrame = 0;
|
||||
while (isdigit(*p))
|
||||
bytesPerFrame = 10 * bytesPerFrame + static_cast<UInt32>(*p++ - '0');
|
||||
fmt.mBytesPerFrame = fmt.mBytesPerPacket = bytesPerFrame;
|
||||
}
|
||||
if (*p == ',') {
|
||||
++p;
|
||||
int ch = 0;
|
||||
while (isdigit(*p))
|
||||
ch = 10 * ch + (*p++ - '0');
|
||||
fmt.mChannelsPerFrame = static_cast<UInt32>(ch);
|
||||
if (*p == 'D') {
|
||||
++p;
|
||||
if (fmt.mFormatID != kAudioFormatLinearPCM) {
|
||||
fprintf(stderr, "non-interleaved flag invalid for non-PCM formats\n");
|
||||
goto Bail;
|
||||
}
|
||||
fmt.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
|
||||
} else {
|
||||
if (*p == 'I') ++p; // default
|
||||
if (fmt.mFormatID == kAudioFormatLinearPCM)
|
||||
fmt.mBytesPerPacket = fmt.mBytesPerFrame *= static_cast<UInt32>(ch);
|
||||
}
|
||||
}
|
||||
if (*p != '\0') {
|
||||
fprintf(stderr, "extra characters at end of format string: %s\n", p);
|
||||
goto Bail;
|
||||
}
|
||||
return true;
|
||||
|
||||
Bail:
|
||||
fprintf(stderr, "Invalid format string: %s\n", inTextDesc);
|
||||
fprintf(stderr, "Syntax of format strings is: \n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *CAStreamBasicDescription::sTextParsingUsageString =
|
||||
"format[@sample_rate_hz][/format_flags][#frames_per_packet][:LHbytesPerFrame][,channelsDI].\n"
|
||||
"Format for PCM is [-][BE|LE]{F|I|UI}{bitdepth}; else a 4-char format code (e.g. aac, alac).\n";
|
@ -0,0 +1,424 @@
|
||||
/*
|
||||
File: CAStreamBasicDescription.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAStreamBasicDescription_h__
|
||||
#define __CAStreamBasicDescription_h__
|
||||
|
||||
#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"
|
||||
#include <string.h> // for memset, memcpy
|
||||
#include <stdio.h> // for FILE *
|
||||
|
||||
#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
|
||||
|
||||
extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize);
|
||||
|
||||
// define Leopard specific symbols for backward compatibility if applicable
|
||||
#if COREAUDIOTYPES_VERSION < 1050
|
||||
typedef Float32 AudioSampleType;
|
||||
enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
|
||||
#endif
|
||||
#if COREAUDIOTYPES_VERSION < 1051
|
||||
typedef Float32 AudioUnitSampleType;
|
||||
enum {
|
||||
kLinearPCMFormatFlagsSampleFractionShift = 7,
|
||||
kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
|
||||
};
|
||||
#endif
|
||||
|
||||
// define the IsMixable format flag for all versions of the system
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
|
||||
enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
|
||||
#else
|
||||
enum { kIsNonMixableFlag = (1L << 6) };
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// CAStreamBasicDescription
|
||||
//
|
||||
// This is a wrapper class for the AudioStreamBasicDescription struct.
|
||||
// It adds a number of convenience routines, but otherwise adds nothing
|
||||
// to the footprint of the original struct.
|
||||
//=============================================================================
|
||||
class CAStreamBasicDescription :
|
||||
public AudioStreamBasicDescription
|
||||
{
|
||||
|
||||
// Constants
|
||||
public:
|
||||
static const AudioStreamBasicDescription sEmpty;
|
||||
|
||||
enum CommonPCMFormat {
|
||||
kPCMFormatOther = 0,
|
||||
kPCMFormatFloat32 = 1,
|
||||
kPCMFormatInt16 = 2,
|
||||
kPCMFormatFixed824 = 3,
|
||||
kPCMFormatFloat64 = 4
|
||||
};
|
||||
|
||||
// Construction/Destruction
|
||||
public:
|
||||
CAStreamBasicDescription();
|
||||
|
||||
CAStreamBasicDescription(const AudioStreamBasicDescription &desc);
|
||||
|
||||
CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID,
|
||||
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
|
||||
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
|
||||
UInt32 inBitsPerChannel, UInt32 inFormatFlags);
|
||||
|
||||
CAStreamBasicDescription( double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) {
|
||||
unsigned wordsize;
|
||||
|
||||
mSampleRate = inSampleRate;
|
||||
mFormatID = kAudioFormatLinearPCM;
|
||||
mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||
mFramesPerPacket = 1;
|
||||
mChannelsPerFrame = inNumChannels;
|
||||
mBytesPerFrame = mBytesPerPacket = 0;
|
||||
mReserved = 0;
|
||||
|
||||
switch (pcmf) {
|
||||
default:
|
||||
return;
|
||||
case kPCMFormatFloat32:
|
||||
wordsize = 4;
|
||||
mFormatFlags |= kAudioFormatFlagIsFloat;
|
||||
break;
|
||||
case kPCMFormatFloat64:
|
||||
wordsize = 8;
|
||||
mFormatFlags |= kAudioFormatFlagIsFloat;
|
||||
break;
|
||||
case kPCMFormatInt16:
|
||||
wordsize = 2;
|
||||
mFormatFlags |= kAudioFormatFlagIsSignedInteger;
|
||||
break;
|
||||
case kPCMFormatFixed824:
|
||||
wordsize = 4;
|
||||
mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift);
|
||||
break;
|
||||
}
|
||||
mBitsPerChannel = wordsize * 8;
|
||||
if (inIsInterleaved)
|
||||
mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels;
|
||||
else {
|
||||
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
|
||||
mBytesPerFrame = mBytesPerPacket = wordsize;
|
||||
}
|
||||
}
|
||||
|
||||
// Assignment
|
||||
CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
|
||||
|
||||
void SetFrom(const AudioStreamBasicDescription &desc)
|
||||
{
|
||||
memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
|
||||
}
|
||||
|
||||
bool FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); }
|
||||
static bool FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc);
|
||||
// return true if parsing was successful
|
||||
|
||||
static const char *sTextParsingUsageString;
|
||||
|
||||
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
//
|
||||
// interrogation
|
||||
|
||||
bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
|
||||
|
||||
bool PackednessIsSignificant() const
|
||||
{
|
||||
Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
|
||||
return (SampleWordSize() << 3) != mBitsPerChannel;
|
||||
}
|
||||
|
||||
bool AlignmentIsSignificant() const
|
||||
{
|
||||
return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
|
||||
}
|
||||
|
||||
bool IsInterleaved() const
|
||||
{
|
||||
return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
|
||||
}
|
||||
|
||||
bool IsSignedInteger() const
|
||||
{
|
||||
return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger);
|
||||
}
|
||||
|
||||
bool IsFloat() const
|
||||
{
|
||||
return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat);
|
||||
}
|
||||
|
||||
bool IsNativeEndian() const
|
||||
{
|
||||
return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
|
||||
}
|
||||
|
||||
// for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
|
||||
UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
|
||||
UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
|
||||
UInt32 NumberChannels() const { return mChannelsPerFrame; }
|
||||
UInt32 SampleWordSize() const {
|
||||
return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0;
|
||||
}
|
||||
|
||||
UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; }
|
||||
UInt32 BytesToFrames(UInt32 nbytes) const {
|
||||
Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
|
||||
return nbytes / mBytesPerFrame;
|
||||
}
|
||||
|
||||
bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
|
||||
{
|
||||
return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
|
||||
}
|
||||
|
||||
bool IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const
|
||||
{ // return true if it's a valid PCM format.
|
||||
|
||||
outFormat = kPCMFormatOther;
|
||||
// trap out patently invalid formats.
|
||||
if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0)
|
||||
return false;
|
||||
bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
|
||||
if (outIsInterleaved != NULL) *outIsInterleaved = interleaved;
|
||||
unsigned wordsize = mBytesPerFrame;
|
||||
if (interleaved) {
|
||||
if (wordsize % mChannelsPerFrame != 0) return false;
|
||||
wordsize /= mChannelsPerFrame;
|
||||
}
|
||||
|
||||
if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian
|
||||
&& wordsize * 8 == mBitsPerChannel) {
|
||||
// packed and native endian, good
|
||||
if (mFormatFlags & kLinearPCMFormatFlagIsFloat) {
|
||||
// float: reject nonsense bits
|
||||
if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask))
|
||||
return false;
|
||||
if (wordsize == 4)
|
||||
outFormat = kPCMFormatFloat32;
|
||||
if (wordsize == 8)
|
||||
outFormat = kPCMFormatFloat64;
|
||||
} else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) {
|
||||
// signed int
|
||||
unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
|
||||
if (wordsize == 4 && fracbits == 24)
|
||||
outFormat = kPCMFormatFixed824;
|
||||
else if (wordsize == 2 && fracbits == 0)
|
||||
outFormat = kPCMFormatInt16;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsCommonFloat32(bool *outIsInterleaved=NULL) const {
|
||||
CommonPCMFormat fmt;
|
||||
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32;
|
||||
}
|
||||
bool IsCommonFloat64(bool *outIsInterleaved=NULL) const {
|
||||
CommonPCMFormat fmt;
|
||||
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64;
|
||||
}
|
||||
bool IsCommonFixed824(bool *outIsInterleaved=NULL) const {
|
||||
CommonPCMFormat fmt;
|
||||
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824;
|
||||
}
|
||||
bool IsCommonInt16(bool *outIsInterleaved=NULL) const {
|
||||
CommonPCMFormat fmt;
|
||||
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16;
|
||||
}
|
||||
|
||||
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
//
|
||||
// manipulation
|
||||
|
||||
void SetCanonical(UInt32 nChannels, bool interleaved)
|
||||
// note: leaves sample rate untouched
|
||||
{
|
||||
mFormatID = kAudioFormatLinearPCM;
|
||||
UInt32 sampleSize = SizeOf32(AudioSampleType);
|
||||
mFormatFlags = kAudioFormatFlagsCanonical;
|
||||
mBitsPerChannel = 8 * sampleSize;
|
||||
mChannelsPerFrame = nChannels;
|
||||
mFramesPerPacket = 1;
|
||||
if (interleaved)
|
||||
mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
|
||||
else {
|
||||
mBytesPerPacket = mBytesPerFrame = sampleSize;
|
||||
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCanonical() const
|
||||
{
|
||||
if (mFormatID != kAudioFormatLinearPCM) return false;
|
||||
UInt32 reqFormatFlags;
|
||||
UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask);
|
||||
bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
|
||||
unsigned sampleSize = SizeOf32(AudioSampleType);
|
||||
reqFormatFlags = kAudioFormatFlagsCanonical;
|
||||
UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
|
||||
|
||||
return ((mFormatFlags & flagsMask) == reqFormatFlags
|
||||
&& mBitsPerChannel == 8 * sampleSize
|
||||
&& mFramesPerPacket == 1
|
||||
&& mBytesPerFrame == reqFrameSize
|
||||
&& mBytesPerPacket == reqFrameSize);
|
||||
}
|
||||
|
||||
void SetAUCanonical(UInt32 nChannels, bool interleaved)
|
||||
{
|
||||
mFormatID = kAudioFormatLinearPCM;
|
||||
#if CA_PREFER_FIXED_POINT
|
||||
mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
|
||||
#else
|
||||
mFormatFlags = kAudioFormatFlagsCanonical;
|
||||
#endif
|
||||
mChannelsPerFrame = nChannels;
|
||||
mFramesPerPacket = 1;
|
||||
mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
|
||||
if (interleaved)
|
||||
mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
|
||||
else {
|
||||
mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
|
||||
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
|
||||
// alter an existing format
|
||||
{
|
||||
Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
|
||||
UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
|
||||
if (wordSize == 0)
|
||||
wordSize = (mBitsPerChannel + 7) / 8;
|
||||
mChannelsPerFrame = nChannels;
|
||||
mFramesPerPacket = 1;
|
||||
if (interleaved) {
|
||||
mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
|
||||
mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved);
|
||||
} else {
|
||||
mBytesPerPacket = mBytesPerFrame = wordSize;
|
||||
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
|
||||
}
|
||||
}
|
||||
|
||||
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
//
|
||||
// other
|
||||
|
||||
bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const;
|
||||
static bool FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
|
||||
static bool IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
|
||||
|
||||
void Print() const {
|
||||
Print (stdout);
|
||||
}
|
||||
|
||||
void Print(FILE* file) const {
|
||||
PrintFormat (file, "", "AudioStreamBasicDescription:");
|
||||
}
|
||||
|
||||
void PrintFormat(FILE *f, const char *indent, const char *name) const {
|
||||
char buf[256];
|
||||
fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
|
||||
char buf[256];
|
||||
fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
char * AsString(char *buf, size_t bufsize, bool brief=false) const;
|
||||
|
||||
static void Print (const AudioStreamBasicDescription &inDesc)
|
||||
{
|
||||
CAStreamBasicDescription desc(inDesc);
|
||||
desc.Print ();
|
||||
}
|
||||
|
||||
OSStatus Save(CFPropertyListRef *outData) const;
|
||||
|
||||
OSStatus Restore(CFPropertyListRef &inData);
|
||||
|
||||
// Operations
|
||||
static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
|
||||
static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
|
||||
static void NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
|
||||
static void ResetFormat(AudioStreamBasicDescription& ioDescription);
|
||||
static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
|
||||
static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false);
|
||||
static void ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly);
|
||||
|
||||
#if CoreAudio_Debug
|
||||
static void PrintToLog(const AudioStreamBasicDescription& inDesc);
|
||||
#endif
|
||||
};
|
||||
|
||||
bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
|
||||
bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
|
||||
#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
|
||||
inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
|
||||
inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
|
||||
inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
|
||||
inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
|
||||
#endif
|
||||
|
||||
bool SanityCheck(const AudioStreamBasicDescription& x);
|
||||
|
||||
|
||||
#endif // __CAStreamBasicDescription_h__
|
@ -0,0 +1,233 @@
|
||||
/*
|
||||
File: CAThreadSafeList.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAThreadSafeList_h__
|
||||
#define __CAThreadSafeList_h__
|
||||
|
||||
#include "CAAtomicStack.h"
|
||||
|
||||
// linked list of T's
|
||||
// T must define operator ==
|
||||
template <class T>
|
||||
class TThreadSafeList {
|
||||
private:
|
||||
enum EEventType { kAdd, kRemove, kClear };
|
||||
class Node {
|
||||
public:
|
||||
Node * mNext;
|
||||
EEventType mEventType;
|
||||
T mObject;
|
||||
|
||||
Node *& next() { return mNext; }
|
||||
};
|
||||
|
||||
public:
|
||||
class iterator {
|
||||
public:
|
||||
iterator() { }
|
||||
iterator(Node *n) : mNode(n) { }
|
||||
|
||||
bool operator == (const iterator &other) const { return this->mNode == other.mNode; }
|
||||
bool operator != (const iterator &other) const { return this->mNode != other.mNode; }
|
||||
|
||||
T & operator * () const { return mNode->mObject; }
|
||||
|
||||
iterator & operator ++ () { mNode = mNode->next(); return *this; } // preincrement
|
||||
iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->next(); return tmp; } // postincrement
|
||||
|
||||
private:
|
||||
Node * mNode;
|
||||
};
|
||||
|
||||
TThreadSafeList() { }
|
||||
~TThreadSafeList()
|
||||
{
|
||||
mActiveList.free_all();
|
||||
mPendingList.free_all();
|
||||
mFreeList.free_all();
|
||||
}
|
||||
|
||||
// These may be called on any thread
|
||||
|
||||
void deferred_add(const T &obj) // can be called on any thread
|
||||
{
|
||||
Node *node = AllocNode();
|
||||
node->mEventType = kAdd;
|
||||
node->mObject = obj;
|
||||
mPendingList.push_atomic(node);
|
||||
//mPendingList.dump("pending after add");
|
||||
}
|
||||
|
||||
void deferred_remove(const T &obj) // can be called on any thread
|
||||
{
|
||||
Node *node = AllocNode();
|
||||
node->mEventType = kRemove;
|
||||
node->mObject = obj;
|
||||
mPendingList.push_atomic(node);
|
||||
//mPendingList.dump("pending after remove");
|
||||
}
|
||||
|
||||
void deferred_clear() // can be called on any thread
|
||||
{
|
||||
Node *node = AllocNode();
|
||||
node->mEventType = kClear;
|
||||
mPendingList.push_atomic(node);
|
||||
}
|
||||
|
||||
// These must be called from only one thread
|
||||
|
||||
void update() // must only be called from one thread
|
||||
{
|
||||
NodeStack reversed;
|
||||
Node *event, *node, *next;
|
||||
bool workDone = false;
|
||||
|
||||
// reverse the events so they are in order
|
||||
event = mPendingList.pop_all();
|
||||
while (event != NULL) {
|
||||
next = event->mNext;
|
||||
reversed.push_NA(event);
|
||||
event = next;
|
||||
workDone = true;
|
||||
}
|
||||
if (workDone) {
|
||||
//reversed.dump("pending popped");
|
||||
//mActiveList.dump("active before update");
|
||||
|
||||
// now process them
|
||||
while ((event = reversed.pop_NA()) != NULL) {
|
||||
switch (event->mEventType) {
|
||||
case kAdd:
|
||||
{
|
||||
Node **pnode;
|
||||
bool needToInsert = true;
|
||||
for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) {
|
||||
node = *pnode;
|
||||
if (node->mObject == event->mObject) {
|
||||
//printf("already active!!!\n");
|
||||
FreeNode(event);
|
||||
needToInsert = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needToInsert) {
|
||||
// link the new event in at the end of the active list
|
||||
*pnode = event;
|
||||
event->mNext = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kRemove:
|
||||
// find matching node in the active list, remove it
|
||||
for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) {
|
||||
node = *pnode;
|
||||
if (node->mObject == event->mObject) {
|
||||
*pnode = node->mNext; // remove from linked list
|
||||
FreeNode(node);
|
||||
break;
|
||||
}
|
||||
pnode = &node->mNext;
|
||||
}
|
||||
// dispose the request node
|
||||
FreeNode(event);
|
||||
break;
|
||||
case kClear:
|
||||
for (node = mActiveList.head(); node != NULL; ) {
|
||||
next = node->mNext;
|
||||
FreeNode(node);
|
||||
node = next;
|
||||
}
|
||||
FreeNode(event);
|
||||
break;
|
||||
default:
|
||||
//printf("invalid node type %d!\n", event->mEventType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//mActiveList.dump("active after update");
|
||||
}
|
||||
}
|
||||
|
||||
iterator begin() const {
|
||||
//mActiveList.dump("active at begin");
|
||||
return iterator(mActiveList.head());
|
||||
}
|
||||
iterator end() const { return iterator(NULL); }
|
||||
|
||||
|
||||
private:
|
||||
Node * AllocNode()
|
||||
{
|
||||
Node *node = mFreeList.pop_atomic();
|
||||
if (node == NULL)
|
||||
node = (Node *)CA_malloc(sizeof(Node));
|
||||
return node;
|
||||
}
|
||||
|
||||
void FreeNode(Node *node)
|
||||
{
|
||||
mFreeList.push_atomic(node);
|
||||
}
|
||||
|
||||
private:
|
||||
class NodeStack : public TAtomicStack<Node> {
|
||||
public:
|
||||
void free_all() {
|
||||
Node *node;
|
||||
while ((node = this->pop_NA()) != NULL)
|
||||
free(node);
|
||||
}
|
||||
|
||||
Node ** phead() { return &this->mHead; }
|
||||
Node * head() const { return this->mHead; }
|
||||
};
|
||||
|
||||
NodeStack mActiveList; // what's actually in the container - only accessed on one thread
|
||||
NodeStack mPendingList; // add or remove requests - threadsafe
|
||||
NodeStack mFreeList; // free nodes for reuse - threadsafe
|
||||
};
|
||||
|
||||
#endif // __CAThreadSafeList_h__
|
@ -0,0 +1,194 @@
|
||||
/*
|
||||
File: CAVectorUnit.cpp
|
||||
Abstract: CAVectorUnit.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "CAVectorUnit.h"
|
||||
|
||||
#if !TARGET_OS_WIN32
|
||||
#include <sys/sysctl.h>
|
||||
#elif HAS_IPP
|
||||
#include "ippdefs.h"
|
||||
#include "ippcore.h"
|
||||
#endif
|
||||
|
||||
int gCAVectorUnitType = kVecUninitialized;
|
||||
|
||||
#if TARGET_OS_WIN32
|
||||
// Use cpuid to check if SSE2 is available.
|
||||
// Before calling this function make sure cpuid is available
|
||||
static SInt32 IsSSE2Available()
|
||||
{
|
||||
int return_value;
|
||||
|
||||
{
|
||||
int r_edx;
|
||||
_asm
|
||||
{
|
||||
mov eax, 0x01
|
||||
cpuid
|
||||
mov r_edx, edx
|
||||
}
|
||||
return_value = (r_edx >> 26) & 0x1;
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
// Use cpuid to check if SSE3 is available.
|
||||
// Before calling this function make sure cpuid is available
|
||||
static SInt32 IsSSE3Available()
|
||||
{
|
||||
SInt32 return_value;
|
||||
|
||||
{
|
||||
SInt32 r_ecx;
|
||||
_asm
|
||||
{
|
||||
mov eax, 0x01
|
||||
cpuid
|
||||
mov r_ecx, ecx
|
||||
}
|
||||
return_value = r_ecx & 0x1;
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
// Return true if the cpuid instruction is available.
|
||||
// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed
|
||||
// This function may not work on Intel CPUs prior to Pentium (didn't test)
|
||||
static bool IsCpuidAvailable()
|
||||
{
|
||||
SInt32 return_value = 0x0;
|
||||
_asm{
|
||||
pushfd ; //push original EFLAGS
|
||||
pop eax ; //get original EFLAGS
|
||||
mov ecx, eax ; //save original EFLAGS
|
||||
xor eax, 200000h ; //flip ID bit in EFLAGS
|
||||
push eax ; //save new EFLAGS value on stack
|
||||
popfd ; //replace current EFLAGS value
|
||||
pushfd ; //get new EFLAGS
|
||||
pop eax ; //store new EFLAGS in EAX
|
||||
xor eax, ecx ;
|
||||
je end_cpuid_identify ; //can't toggle ID bit
|
||||
mov return_value, 0x1;
|
||||
end_cpuid_identify:
|
||||
nop;
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SInt32 CAVectorUnit_Examine()
|
||||
{
|
||||
int result = kVecNone;
|
||||
|
||||
#if TARGET_OS_WIN32
|
||||
#if HAS_IPP
|
||||
// Initialize the static IPP library! This needs to be done before
|
||||
// any IPP function calls, otherwise we may have a performance penalty
|
||||
int status = ippStaticInit();
|
||||
if ( status == ippStsNonIntelCpu )
|
||||
{
|
||||
IppCpuType cpuType = ippGetCpuType();
|
||||
if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 )
|
||||
ippStaticInitCpu( cpuType );
|
||||
}
|
||||
#endif
|
||||
{
|
||||
// On Windows we use cpuid to detect the vector unit because it works on Intel and AMD.
|
||||
// The IPP library does not detect SSE on AMD processors.
|
||||
if (IsCpuidAvailable())
|
||||
{
|
||||
if(IsSSE3Available())
|
||||
{
|
||||
result = kVecSSE3;
|
||||
}
|
||||
else if(IsSSE2Available())
|
||||
{
|
||||
result = kVecSSE2;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif TARGET_OS_MAC
|
||||
#if DEBUG
|
||||
if (getenv("CA_NoVector")) {
|
||||
fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n");
|
||||
return result;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if (TARGET_CPU_PPC || TARGET_CPU_PPC64)
|
||||
int sels[2] = { CTL_HW, HW_VECTORUNIT };
|
||||
int vType = 0; //0 == scalar only
|
||||
size_t length = sizeof(vType);
|
||||
int error = sysctl(sels, 2, &vType, &length, NULL, 0);
|
||||
if (!error && vType > 0)
|
||||
result = kVecAltivec;
|
||||
#elif (TARGET_CPU_X86 || TARGET_CPU_X86_64)
|
||||
static const struct { const char* kName; const int kVectype; } kStringVectypes[] = {
|
||||
{ "hw.optional.avx1_0", kVecAVX1 }, { "hw.optional.sse3", kVecSSE3 }, { "hw.optional.sse2", kVecSSE2 }
|
||||
};
|
||||
static const size_t kNumStringVectypes = sizeof(kStringVectypes)/sizeof(kStringVectypes[0]);
|
||||
int i = 0, answer = 0;
|
||||
while(i != kNumStringVectypes)
|
||||
{
|
||||
size_t length = sizeof(answer);
|
||||
int error = sysctlbyname(kStringVectypes[i].kName, &answer, &length, NULL, 0);
|
||||
if (!error && answer)
|
||||
{
|
||||
result = kStringVectypes[i].kVectype;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
};
|
||||
#elif CA_ARM_NEON
|
||||
result = kVecNeon;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
gCAVectorUnitType = result;
|
||||
return result;
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
File: CAVectorUnit.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAVectorUnit_h__
|
||||
#define __CAVectorUnit_h__
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
#include "CAVectorUnitTypes.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreFoundation/CFBase.h>
|
||||
#else
|
||||
#include "CFBase.h"
|
||||
#endif
|
||||
|
||||
// Unify checks for vector units.
|
||||
// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing).
|
||||
|
||||
extern int gCAVectorUnitType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern SInt32 CAVectorUnit_Examine(); // expensive. use GetType() for lazy initialization and caching.
|
||||
|
||||
static inline SInt32 CAVectorUnit_GetType()
|
||||
{
|
||||
int x = gCAVectorUnitType;
|
||||
return (x != kVecUninitialized) ? x : CAVectorUnit_Examine();
|
||||
}
|
||||
|
||||
static inline Boolean CAVectorUnit_HasVectorUnit()
|
||||
{
|
||||
return CAVectorUnit_GetType() > kVecNone;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
class CAVectorUnit {
|
||||
public:
|
||||
static SInt32 GetVectorUnitType() { return CAVectorUnit_GetType(); }
|
||||
static bool HasVectorUnit() { return GetVectorUnitType() > kVecNone; }
|
||||
static bool HasAltivec() { return GetVectorUnitType() == kVecAltivec; }
|
||||
static bool HasSSE2() { return GetVectorUnitType() >= kVecSSE2; }
|
||||
static bool HasSSE3() { return GetVectorUnitType() >= kVecSSE3; }
|
||||
static bool HasAVX1() { return GetVectorUnitType() >= kVecAVX1; }
|
||||
static bool HasNeon() { return GetVectorUnitType() == kVecNeon; }
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // __CAVectorUnit_h__
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
File: CAVectorUnitTypes.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAVectorUnitTypes_h__
|
||||
#define __CAVectorUnitTypes_h__
|
||||
|
||||
enum {
|
||||
kVecUninitialized = -1,
|
||||
kVecNone = 0,
|
||||
kVecAltivec = 1,
|
||||
kVecSSE2 = 100,
|
||||
kVecSSE3 = 101,
|
||||
kVecAVX1 = 110,
|
||||
kVecNeon = 200
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,361 @@
|
||||
/*
|
||||
File: CAXException.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __CAXException_h__
|
||||
#define __CAXException_h__
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#else
|
||||
#include <ConditionalMacros.h>
|
||||
#include <CoreFoundation.h>
|
||||
#endif
|
||||
#include "CADebugMacros.h"
|
||||
#include <ctype.h>
|
||||
//#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
class CAX4CCString {
|
||||
public:
|
||||
CAX4CCString(OSStatus error) {
|
||||
// see if it appears to be a 4-char-code
|
||||
UInt32 beErr = CFSwapInt32HostToBig(error);
|
||||
char *str = mStr;
|
||||
memcpy(str + 1, &beErr, 4);
|
||||
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
|
||||
str[0] = str[5] = '\'';
|
||||
str[6] = '\0';
|
||||
} else if (error > -200000 && error < 200000)
|
||||
// no, format it as an integer
|
||||
snprintf(str, sizeof(mStr), "%d", (int)error);
|
||||
else
|
||||
snprintf(str, sizeof(mStr), "0x%x", (int)error);
|
||||
}
|
||||
const char *get() const { return mStr; }
|
||||
operator const char *() const { return mStr; }
|
||||
private:
|
||||
char mStr[16];
|
||||
};
|
||||
|
||||
class CAX4CCStringNoQuote {
|
||||
public:
|
||||
CAX4CCStringNoQuote(OSStatus error) {
|
||||
// see if it appears to be a 4-char-code
|
||||
UInt32 beErr = CFSwapInt32HostToBig(error);
|
||||
char *str = mStr;
|
||||
memcpy(str, &beErr, 4);
|
||||
if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
|
||||
str[4] = '\0';
|
||||
} else if (error > -200000 && error < 200000)
|
||||
// no, format it as an integer
|
||||
snprintf(str, sizeof(mStr), "%d", (int)error);
|
||||
else
|
||||
snprintf(str, sizeof(mStr), "0x%x", (int)error);
|
||||
}
|
||||
const char *get() const { return mStr; }
|
||||
operator const char *() const { return mStr; }
|
||||
private:
|
||||
char mStr[16];
|
||||
};
|
||||
|
||||
|
||||
// An extended exception class that includes the name of the failed operation
|
||||
class CAXException {
|
||||
public:
|
||||
CAXException(const char *operation, OSStatus err) :
|
||||
mError(err)
|
||||
{
|
||||
if (operation == NULL)
|
||||
mOperation[0] = '\0';
|
||||
else if (strlen(operation) >= sizeof(mOperation)) {
|
||||
memcpy(mOperation, operation, sizeof(mOperation) - 1);
|
||||
mOperation[sizeof(mOperation) - 1] = '\0';
|
||||
} else
|
||||
|
||||
strlcpy(mOperation, operation, sizeof(mOperation));
|
||||
}
|
||||
|
||||
char *FormatError(char *str, size_t strsize) const
|
||||
{
|
||||
return FormatError(str, strsize, mError);
|
||||
}
|
||||
|
||||
char mOperation[256];
|
||||
const OSStatus mError;
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
typedef void (*WarningHandler)(const char *msg, OSStatus err);
|
||||
|
||||
static char *FormatError(char *str, size_t strsize, OSStatus error)
|
||||
{
|
||||
strlcpy(str, CAX4CCString(error), strsize);
|
||||
return str;
|
||||
}
|
||||
|
||||
static void Warning(const char *s, OSStatus error)
|
||||
{
|
||||
if (sWarningHandler)
|
||||
(*sWarningHandler)(s, error);
|
||||
}
|
||||
|
||||
static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
|
||||
private:
|
||||
static WarningHandler sWarningHandler;
|
||||
};
|
||||
|
||||
#if DEBUG || CoreAudio_Debug
|
||||
#define XThrowIfError(error, operation) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
|
||||
__THROW_STOP; \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XThrowIf(condition, error, operation) \
|
||||
do { \
|
||||
if (condition) { \
|
||||
OSStatus __err = error; \
|
||||
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
|
||||
__THROW_STOP; \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XRequireNoError(error, label) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
|
||||
STOP; \
|
||||
goto label; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XAssert(assertion) \
|
||||
do { \
|
||||
if (!(assertion)) { \
|
||||
DebugMessageN3("%s:%d: error: failed assertion: %s", __FILE__, __LINE__, #assertion); \
|
||||
__ASSERT_STOP; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XAssertNoError(error) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
DebugMessageN4("%s:%d: error %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
|
||||
STOP; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ca_require_noerr(errorCode, exceptionLabel) \
|
||||
do \
|
||||
{ \
|
||||
int evalOnceErrorCode = (errorCode); \
|
||||
if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
|
||||
{ \
|
||||
DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d", \
|
||||
#errorCode, evalOnceErrorCode, \
|
||||
#exceptionLabel, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
goto exceptionLabel; \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_verify_noerr(errorCode) \
|
||||
do \
|
||||
{ \
|
||||
int evalOnceErrorCode = (errorCode); \
|
||||
if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
|
||||
{ \
|
||||
DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d", \
|
||||
#errorCode, evalOnceErrorCode, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_debug_string(message) \
|
||||
do \
|
||||
{ \
|
||||
DebugMessageN3("ca_debug_string: %s %s:%d", \
|
||||
message, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
} while ( 0 )
|
||||
|
||||
|
||||
#define ca_verify(assertion) \
|
||||
do \
|
||||
{ \
|
||||
if ( __builtin_expect(!(assertion), 0) ) \
|
||||
{ \
|
||||
DebugMessageN3("ca_verify: %s %s:%d", \
|
||||
#assertion, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_require(assertion, exceptionLabel) \
|
||||
do \
|
||||
{ \
|
||||
if ( __builtin_expect(!(assertion), 0) ) \
|
||||
{ \
|
||||
DebugMessageN4("ca_require: %s %s %s:%d", \
|
||||
#assertion, \
|
||||
#exceptionLabel, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
goto exceptionLabel; \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_check(assertion) \
|
||||
do \
|
||||
{ \
|
||||
if ( __builtin_expect(!(assertion), 0) ) \
|
||||
{ \
|
||||
DebugMessageN3("ca_check: %s %s:%d", \
|
||||
#assertion, \
|
||||
__FILE__, \
|
||||
__LINE__); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#else
|
||||
#define XThrowIfError(error, operation) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XThrowIf(condition, error, operation) \
|
||||
do { \
|
||||
if (condition) { \
|
||||
OSStatus __err = error; \
|
||||
throw CAXException(operation, __err); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XRequireNoError(error, label) \
|
||||
do { \
|
||||
OSStatus __err = error; \
|
||||
if (__err) { \
|
||||
goto label; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XAssert(assertion) \
|
||||
do { \
|
||||
if (!(assertion)) { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define XAssertNoError(error) \
|
||||
do { \
|
||||
/*OSStatus __err =*/ error; \
|
||||
} while (0)
|
||||
|
||||
#define ca_require_noerr(errorCode, exceptionLabel) \
|
||||
do \
|
||||
{ \
|
||||
if ( __builtin_expect(0 != (errorCode), 0) ) \
|
||||
{ \
|
||||
goto exceptionLabel; \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_verify_noerr(errorCode) \
|
||||
do \
|
||||
{ \
|
||||
if ( 0 != (errorCode) ) \
|
||||
{ \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_debug_string(message)
|
||||
|
||||
#define ca_verify(assertion) \
|
||||
do \
|
||||
{ \
|
||||
if ( !(assertion) ) \
|
||||
{ \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_require(assertion, exceptionLabel) \
|
||||
do \
|
||||
{ \
|
||||
if ( __builtin_expect(!(assertion), 0) ) \
|
||||
{ \
|
||||
goto exceptionLabel; \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
#define ca_check(assertion) \
|
||||
do \
|
||||
{ \
|
||||
if ( !(assertion) ) \
|
||||
{ \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#define XThrow(error, operation) XThrowIf(true, error, operation)
|
||||
#define XThrowIfErr(error) XThrowIfError(error, #error)
|
||||
|
||||
#endif // __CAXException_h__
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
File: CarbonEventHandler.cpp
|
||||
Abstract: CarbonEventHandler.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../../juce_core/native/juce_mac_ClangBugWorkaround.h"
|
||||
#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 = static_cast<int>(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);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
File: CarbonEventHandler.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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__
|
@ -0,0 +1,369 @@
|
||||
/*
|
||||
File: ComponentBase.cpp
|
||||
Abstract: ComponentBase.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "ComponentBase.h"
|
||||
#include "CAXException.h"
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_once_t ComponentInitLocker::sOnce = PTHREAD_ONCE_INIT;
|
||||
|
||||
void ComponentInitLocker::InitComponentInitLocker()
|
||||
{
|
||||
// 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(&sComponentOpenMutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
#elif TARGET_OS_WIN32
|
||||
CAGuard ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
|
||||
#endif
|
||||
|
||||
ComponentBase::EInstanceType ComponentBase::sNewInstanceType;
|
||||
|
||||
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_WIN32
|
||||
static OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
|
||||
#endif
|
||||
|
||||
ComponentBase::ComponentBase(AudioComponentInstance inInstance)
|
||||
: mComponentInstance(inInstance),
|
||||
mInstanceType(sNewInstanceType)
|
||||
{
|
||||
GetComponentDescription();
|
||||
}
|
||||
|
||||
ComponentBase::~ComponentBase()
|
||||
{
|
||||
}
|
||||
|
||||
void ComponentBase::PostConstructor()
|
||||
{
|
||||
}
|
||||
|
||||
void ComponentBase::PreDestructor()
|
||||
{
|
||||
}
|
||||
|
||||
#define ACPI ((AudioComponentPlugInInstance *)self)
|
||||
#define ACImp ((ComponentBase *)&ACPI->mInstanceStorage)
|
||||
|
||||
OSStatus ComponentBase::AP_Open(void *self, AudioUnit compInstance)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
ComponentInitLocker lock;
|
||||
|
||||
ComponentBase::sNewInstanceType = ComponentBase::kAudioComponentInstance;
|
||||
ComponentBase *cb = (ComponentBase *)(*ACPI->mConstruct)(&ACPI->mInstanceStorage, compInstance);
|
||||
cb->PostConstructor(); // allows base class to do additional initialization
|
||||
// once the derived class is fully constructed
|
||||
result = noErr;
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
if (result)
|
||||
delete ACPI;
|
||||
return result;
|
||||
}
|
||||
|
||||
OSStatus ComponentBase::AP_Close(void *self)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
try {
|
||||
if (ACImp) {
|
||||
ACImp->PreDestructor();
|
||||
(*ACPI->mDestruct)(&ACPI->mInstanceStorage);
|
||||
free(self);
|
||||
}
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
OSStatus ComponentBase::Version()
|
||||
{
|
||||
return 0x00000001;
|
||||
}
|
||||
|
||||
OSStatus ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
|
||||
{
|
||||
if (This == NULL) return kAudio_ParamError;
|
||||
|
||||
OSStatus result = noErr;
|
||||
|
||||
switch (p->what) {
|
||||
case kComponentCloseSelect:
|
||||
This->PreDestructor();
|
||||
delete This;
|
||||
break;
|
||||
|
||||
case kComponentVersionSelect:
|
||||
result = This->Version();
|
||||
break;
|
||||
|
||||
case kComponentCanDoSelect:
|
||||
switch (GetSelectorForCanDo(p)) {
|
||||
case kComponentOpenSelect:
|
||||
case kComponentCloseSelect:
|
||||
case kComponentVersionSelect:
|
||||
case kComponentCanDoSelect:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
result = badComponentSelector;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
SInt16 ComponentBase::GetSelectorForCanDo(ComponentParameters *params)
|
||||
{
|
||||
if (params->what != kComponentCanDoSelect) return 0;
|
||||
|
||||
#if TARGET_CPU_X86
|
||||
SInt16 sel = params->params[0];
|
||||
#elif TARGET_CPU_X86_64
|
||||
SInt16 sel = params->params[1];
|
||||
#elif TARGET_CPU_PPC
|
||||
SInt16 sel = (params->params[0] >> 16);
|
||||
#else
|
||||
SInt16 sel = params->params[0];
|
||||
#endif
|
||||
|
||||
return sel;
|
||||
/*
|
||||
printf ("flags:%d, paramSize: %d, what: %d\n\t", params->flags, params->paramSize, params->what);
|
||||
for (int i = 0; i < params->paramSize; ++i) {
|
||||
printf ("[%d]:%d(0x%x), ", i, params->params[i], params->params[i]);
|
||||
}
|
||||
printf("\n\tsel:%d\n", sel);
|
||||
*/
|
||||
}
|
||||
|
||||
#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 = 1;
|
||||
|
||||
if (IsPluginObject()) {
|
||||
ca_require_noerr(result = CB_GetComponentDescription (mComponentInstance, &desc), home);
|
||||
}
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
else {
|
||||
ca_require_noerr(result = CMgr_GetComponentDescription (mComponentInstance, &desc), home);
|
||||
}
|
||||
#endif
|
||||
|
||||
home:
|
||||
if (result)
|
||||
memset (&desc, 0, sizeof(AudioComponentDescription));
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
#if CA_USE_AUDIO_PLUGIN_ONLY
|
||||
// everything we need is there and we should be linking against it
|
||||
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
|
||||
{
|
||||
AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
|
||||
if (comp)
|
||||
return AudioComponentGetDescription(comp, outDesc);
|
||||
|
||||
return kAudio_ParamError;
|
||||
}
|
||||
|
||||
#elif !TARGET_OS_WIN32
|
||||
// these are the direct dependencies on ComponentMgr calls that an AU
|
||||
// that is a component mgr is dependent on
|
||||
|
||||
// these are dynamically loaded so that these calls will work on Leopard
|
||||
#include <dlfcn.h>
|
||||
|
||||
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
|
||||
{
|
||||
typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
|
||||
static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
|
||||
|
||||
typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
|
||||
static AudioComponentGetDescriptionProc acGDProc = NULL;
|
||||
|
||||
static int doneInit = 0;
|
||||
if (doneInit == 0) {
|
||||
doneInit = 1;
|
||||
void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
|
||||
if (theImage != NULL)
|
||||
{
|
||||
aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
|
||||
if (aciGCProc) {
|
||||
acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus result = kAudio_UnimplementedError;
|
||||
if (acGDProc && aciGCProc) {
|
||||
AudioComponent comp = (*aciGCProc)(inInstance);
|
||||
if (comp)
|
||||
result = (*acGDProc)(comp, outDesc);
|
||||
}
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
else {
|
||||
result = CMgr_GetComponentDescription (inInstance, outDesc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
// these are the direct dependencies on ComponentMgr calls that an AU
|
||||
// that is a component mgr is dependent on
|
||||
|
||||
// these are dynamically loaded
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include "CAXException.h"
|
||||
#include "ComponentBase.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Component Manager
|
||||
// Used for fast dispatch with audio units
|
||||
typedef Handle (*GetComponentInstanceStorageProc)(ComponentInstance aComponentInstance);
|
||||
static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
|
||||
|
||||
typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
|
||||
static GetComponentInfoProc sGetComponentInfoProc = NULL;
|
||||
|
||||
typedef void (*SetComponentInstanceStorageProc)(ComponentInstance, Handle);
|
||||
static SetComponentInstanceStorageProc sSetComponentInstanceStorageProc = NULL;
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
static void CSInitOnce(void* /*unused*/)
|
||||
{
|
||||
void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
|
||||
if (!theImage) return;
|
||||
|
||||
sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
|
||||
sGetComponentInfoProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
|
||||
sSetComponentInstanceStorageProc = (SetComponentInstanceStorageProc) dlsym(theImage, "SetComponentInstanceStorage");
|
||||
}
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
|
||||
static dispatch_once_t sCSInitOnce = 0;
|
||||
|
||||
static void CSInit ()
|
||||
{
|
||||
dispatch_once_f(&sCSInitOnce, NULL, CSInitOnce);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void CSInit ()
|
||||
{
|
||||
static int sDoCSLoad = 1;
|
||||
if (sDoCSLoad) {
|
||||
sDoCSLoad = 0;
|
||||
CSInitOnce(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
|
||||
{
|
||||
CSInit();
|
||||
if (sGetComponentInfoProc)
|
||||
return (*sGetComponentInfoProc)((Component)inInstance, (ComponentDescription*)outDesc, NULL, NULL, NULL);
|
||||
return kAudio_UnimplementedError;
|
||||
}
|
||||
|
||||
Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)
|
||||
{
|
||||
CSInit();
|
||||
if (sGetComponentInstanceStorageProc)
|
||||
return (*sGetComponentInstanceStorageProc)(aComponentInstance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage)
|
||||
{
|
||||
CSInit();
|
||||
if (sSetComponentInstanceStorageProc)
|
||||
(*sSetComponentInstanceStorageProc)(aComponentInstance, theStorage);
|
||||
}
|
||||
#endif // !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
|
||||
#else
|
||||
//#include "ComponentManagerDependenciesWin.h"
|
||||
// everything we need is there and we should be linking against it
|
||||
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
|
||||
{
|
||||
AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
|
||||
if (comp)
|
||||
return AudioComponentGetDescription(comp, outDesc);
|
||||
|
||||
return kAudio_ParamError;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,353 @@
|
||||
/*
|
||||
File: ComponentBase.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#ifndef __ComponentBase_h__
|
||||
#define __ComponentBase_h__
|
||||
|
||||
#include <new>
|
||||
#include "CADebugMacros.h"
|
||||
#include "CAXException.h"
|
||||
|
||||
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
#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
|
||||
#endif
|
||||
Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance);
|
||||
void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage);
|
||||
#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
|
||||
|
||||
#if !TARGET_OS_WIN32
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_WIN32
|
||||
#include "CAGuard.h"
|
||||
#endif
|
||||
#else
|
||||
#include "CoreAudioTypes.h"
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
#include "ComponentManagerDependenciesWin.h"
|
||||
#endif
|
||||
#include "AudioUnit.h"
|
||||
#include "CAGuard.h"
|
||||
#endif
|
||||
|
||||
#ifndef COMPONENT_THROW
|
||||
#if VERBOSE_COMPONENT_THROW
|
||||
#define COMPONENT_THROW(throw_err) \
|
||||
do { DebugMessage(#throw_err); throw static_cast<OSStatus>(throw_err); } while (0)
|
||||
#else
|
||||
#define COMPONENT_THROW(throw_err) \
|
||||
throw static_cast<OSStatus>(throw_err)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define COMPONENT_CATCH \
|
||||
catch (const CAXException &ex) { result = ex.mError; } \
|
||||
catch (std::bad_alloc &) { result = kAudio_MemFullError; } \
|
||||
catch (OSStatus catch_err) { result = catch_err; } \
|
||||
catch (OSErr catch_err) { result = catch_err; } \
|
||||
catch (...) { result = -1; }
|
||||
|
||||
/*! @class ComponentBase */
|
||||
class ComponentBase {
|
||||
public:
|
||||
// classic MacErrors
|
||||
enum { noErr = 0};
|
||||
|
||||
/*! @ctor ComponentBase */
|
||||
ComponentBase(AudioComponentInstance inInstance);
|
||||
|
||||
/*! @dtor ~ComponentBase */
|
||||
virtual ~ComponentBase();
|
||||
|
||||
/*! @method PostConstructor */
|
||||
virtual void PostConstructor();
|
||||
|
||||
/*! @method PreDestructor */
|
||||
virtual void PreDestructor();
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
/*! @method Version */
|
||||
virtual OSStatus Version();
|
||||
|
||||
/*! @method ComponentEntryDispatch */
|
||||
static OSStatus ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
|
||||
|
||||
/*! GetSelectorForCanDo */
|
||||
static SInt16 GetSelectorForCanDo(ComponentParameters *params);
|
||||
#endif
|
||||
|
||||
/*! @method GetComponentInstance */
|
||||
AudioComponentInstance GetComponentInstance() const { return mComponentInstance; }
|
||||
|
||||
/*! @method GetComponentDescription */
|
||||
AudioComponentDescription GetComponentDescription() const;
|
||||
|
||||
// This global variable is so that new instances know how they were instantiated: via the Component Manager,
|
||||
// or as AudioComponents. It's ugly, but preferable to altering the constructor of every class in the hierarchy.
|
||||
// It's safe because construction is protected by ComponentInitLocker.
|
||||
enum EInstanceType { kComponentMgrInstance, kAudioComponentInstance };
|
||||
static EInstanceType sNewInstanceType;
|
||||
|
||||
/*! @method IsPluginObject */
|
||||
bool IsPluginObject () const { return mInstanceType == kAudioComponentInstance; }
|
||||
/*! @method IsCMgrObject */
|
||||
bool IsCMgrObject () const { return mInstanceType == kComponentMgrInstance; }
|
||||
|
||||
/*! @method AP_Open */
|
||||
static OSStatus AP_Open(void *self, AudioUnit compInstance);
|
||||
|
||||
/*! @method AP_Close */
|
||||
static OSStatus AP_Close(void *self);
|
||||
|
||||
protected:
|
||||
/*! @var mComponentInstance */
|
||||
AudioComponentInstance mComponentInstance;
|
||||
EInstanceType mInstanceType;
|
||||
};
|
||||
|
||||
class ComponentInitLocker
|
||||
{
|
||||
#if TARGET_OS_MAC
|
||||
public:
|
||||
ComponentInitLocker()
|
||||
{
|
||||
pthread_once(&sOnce, InitComponentInitLocker);
|
||||
pthread_mutex_lock(&sComponentOpenMutex);
|
||||
mPreviousNewInstanceType = ComponentBase::sNewInstanceType;
|
||||
}
|
||||
~ComponentInitLocker()
|
||||
{
|
||||
ComponentBase::sNewInstanceType = mPreviousNewInstanceType;
|
||||
pthread_mutex_unlock(&sComponentOpenMutex);
|
||||
}
|
||||
|
||||
// There are situations (11844772) where we need to be able to release the lock early.
|
||||
class Unlocker {
|
||||
public:
|
||||
Unlocker()
|
||||
{
|
||||
pthread_mutex_unlock(&sComponentOpenMutex);
|
||||
}
|
||||
~Unlocker()
|
||||
{
|
||||
pthread_mutex_lock(&sComponentOpenMutex);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
static pthread_mutex_t sComponentOpenMutex;
|
||||
static pthread_once_t sOnce;
|
||||
static void InitComponentInitLocker();
|
||||
|
||||
#elif TARGET_OS_WIN32
|
||||
public:
|
||||
bool sNeedsUnlocking;
|
||||
ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
|
||||
~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
|
||||
private:
|
||||
static CAGuard sComponentOpenGuard;
|
||||
#endif
|
||||
|
||||
private:
|
||||
ComponentBase::EInstanceType mPreviousNewInstanceType;
|
||||
};
|
||||
|
||||
/*! @class AudioComponentPlugInInstance */
|
||||
struct AudioComponentPlugInInstance {
|
||||
AudioComponentPlugInInterface mPlugInInterface;
|
||||
void * (*mConstruct)(void *memory, AudioComponentInstance ci);
|
||||
void (*mDestruct)(void *memory);
|
||||
void * mPad[2]; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
|
||||
UInt32 mInstanceStorage; // the ACI implementation object is constructed into this memory
|
||||
// this member is just a placeholder. it is aligned to a 16byte boundary
|
||||
};
|
||||
|
||||
/*! @class APFactory */
|
||||
template <class APMethodLookup, class Implementor>
|
||||
class APFactory {
|
||||
public:
|
||||
static void *Construct(void *memory, AudioComponentInstance compInstance)
|
||||
{
|
||||
return new(memory) Implementor(compInstance);
|
||||
}
|
||||
|
||||
static void Destruct(void *memory)
|
||||
{
|
||||
((Implementor *)memory)->~Implementor();
|
||||
}
|
||||
|
||||
// This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
|
||||
// The actual implementation object is not created until Open().
|
||||
static AudioComponentPlugInInterface *Factory(const AudioComponentDescription * /* inDesc */)
|
||||
{
|
||||
AudioComponentPlugInInstance *acpi =
|
||||
(AudioComponentPlugInInstance *)malloc( offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor) );
|
||||
acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
|
||||
acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
|
||||
acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
|
||||
acpi->mPlugInInterface.reserved = NULL;
|
||||
acpi->mConstruct = Construct;
|
||||
acpi->mDestruct = Destruct;
|
||||
acpi->mPad[0] = NULL;
|
||||
acpi->mPad[1] = NULL;
|
||||
return (AudioComponentPlugInInterface*)acpi;
|
||||
}
|
||||
|
||||
// This is for runtime registration (not for plug-ins loaded from bundles).
|
||||
static AudioComponent Register(UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags=0)
|
||||
{
|
||||
AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
|
||||
return AudioComponentRegister(&desc, name, vers, Factory);
|
||||
}
|
||||
};
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
/*! @class ComponentEntryPoint
|
||||
* @discussion This is only used for a component manager version
|
||||
*/
|
||||
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;
|
||||
|
||||
ComponentBase::sNewInstanceType = ComponentBase::kComponentMgrInstance;
|
||||
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
|
||||
|
||||
CMgr_SetComponentInstanceStorage(ci, (Handle)This);
|
||||
} 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;
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: Component Mgr is deprecated in ML.
|
||||
// this macro should not be used with new audio components
|
||||
// it is only for backwards compatibility with Lion and SL.
|
||||
// this macro registers both a plugin and a component mgr version.
|
||||
#define AUDIOCOMPONENT_ENTRY(FactoryType, 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); \
|
||||
} \
|
||||
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
|
||||
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
|
||||
return FactoryType<Class>::Factory(inDesc); \
|
||||
}
|
||||
// the only component we still support are the carbon based view components
|
||||
// you should be using this macro now to exclusively register those types
|
||||
#define VIEW_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); \
|
||||
}
|
||||
|
||||
/*! @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)
|
||||
// this macro is used to generate the Entry Point for a given Audio Plugin
|
||||
// you should be using this macro now with audio components
|
||||
#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
|
||||
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
|
||||
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
|
||||
return FactoryType<Class>::Factory(inDesc); \
|
||||
}
|
||||
|
||||
#endif // !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
|
||||
|
||||
#endif // __ComponentBase_h__
|
@ -0,0 +1,354 @@
|
||||
/*
|
||||
File: MusicDeviceBase.cpp
|
||||
Abstract: MusicDeviceBase.h
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#include "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);
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
|
||||
UInt32 numInputs,
|
||||
UInt32 numOutputs,
|
||||
UInt32 numGroups)
|
||||
: AUBase(inInstance, numInputs, numOutputs, numGroups),
|
||||
AUMIDIBase(this)
|
||||
{
|
||||
}
|
||||
|
||||
OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
|
||||
AudioUnitScope inScope,
|
||||
AudioUnitElement inElement,
|
||||
UInt32 & outDataSize,
|
||||
Boolean & outWritable)
|
||||
{
|
||||
OSStatus result;
|
||||
|
||||
switch (inID)
|
||||
{
|
||||
#if !TARGET_OS_IPHONE
|
||||
case kMusicDeviceProperty_InstrumentCount:
|
||||
if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
|
||||
outDataSize = sizeof(UInt32);
|
||||
outWritable = false;
|
||||
result = noErr;
|
||||
break;
|
||||
#endif
|
||||
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_USE_AUDIO_PLUGIN_ONLY
|
||||
case kAudioUnitProperty_FastDispatch:
|
||||
if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
|
||||
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
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
case kMusicDeviceProperty_InstrumentCount:
|
||||
if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
|
||||
return GetInstrumentCount (*(UInt32*)outData);
|
||||
#endif
|
||||
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 kAudio_ParamError;
|
||||
|
||||
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 *)¶ms->params[_index + 1];
|
||||
#else
|
||||
// parameters in reverse order, then comp instance
|
||||
#define PARAM(_typ, _name, _index, _nparams) \
|
||||
_typ _name = *(_typ *)¶ms->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 *)¶ms->params[_index];
|
||||
#endif
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
|
||||
MusicDeviceBase * This)
|
||||
{
|
||||
if (This == NULL) return kAudio_ParamError;
|
||||
|
||||
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
|
||||
|
||||
#if !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
|
||||
// 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 kAudio_ParamError;
|
||||
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 kAudio_ParamError;
|
||||
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
|
||||
if (This == NULL) return kAudio_ParamError;
|
||||
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 kAudio_ParamError;
|
||||
result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
|
||||
}
|
||||
COMPONENT_CATCH
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
File: MusicDeviceBase.h
|
||||
Abstract: Part of CoreAudio Utility Classes
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
#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);
|
||||
|
||||
|
||||
virtual OSStatus MIDIEvent( UInt32 inStatus,
|
||||
UInt32 inData1,
|
||||
UInt32 inData2,
|
||||
UInt32 inOffsetSampleFrame)
|
||||
{
|
||||
return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
|
||||
}
|
||||
|
||||
/*! @method SysEx */
|
||||
virtual OSStatus SysEx( const UInt8 * inData,
|
||||
UInt32 inLength)
|
||||
{
|
||||
return AUMIDIBase::SysEx (inData, inLength);
|
||||
}
|
||||
|
||||
/*! @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 !CA_USE_AUDIO_PLUGIN_ONLY
|
||||
// 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__
|
2428
modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
Normal file
2428
modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
Normal file
File diff suppressed because it is too large
Load Diff
1860
modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
Normal file
1860
modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
Normal file
File diff suppressed because it is too large
Load Diff
140
modules/juce_audio_plugin_client/AUResources.r
Normal file
140
modules/juce_audio_plugin_client/AUResources.r
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
File: AUResources.r
|
||||
Abstract: AUResources.r
|
||||
Version: 1.1
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
|
||||
Inc. ("Apple") in consideration of your agreement to the following
|
||||
terms, and your use, installation, modification or redistribution of
|
||||
this Apple software constitutes acceptance of these terms. If you do
|
||||
not agree with these terms, please do not use, install, modify or
|
||||
redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and
|
||||
subject to these terms, Apple grants you a personal, non-exclusive
|
||||
license, under Apple's copyrights in this original Apple software (the
|
||||
"Apple Software"), to use, reproduce, modify and redistribute the Apple
|
||||
Software, with or without modifications, in source and/or binary forms;
|
||||
provided that if you redistribute the Apple Software in its entirety and
|
||||
without modifications, you must retain this notice and the following
|
||||
text and disclaimers in all such redistributions of the Apple Software.
|
||||
Neither the name, trademarks, service marks or logos of Apple Inc. may
|
||||
be used to endorse or promote products derived from the Apple Software
|
||||
without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or
|
||||
implied, are granted by Apple herein, including but not limited to any
|
||||
patent rights that may be infringed by your derivative works or by other
|
||||
works in which the Apple Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
|
||||
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
|
||||
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
|
||||
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
|
||||
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
|
||||
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
|
||||
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Copyright (C) 2014 Apple Inc. All Rights Reserved.
|
||||
|
||||
*/
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// 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
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
/*
|
||||
This file is used to include and build the required digidesign CPP files without your project
|
||||
needing to reference the files directly. Because these files will be found via your include path,
|
||||
this means that the project doesn't have to change to cope with people's SDKs being in different
|
||||
locations.
|
||||
|
||||
Important note on Windows: In your project settings for the three juce_RTAS_DigiCode.cpp files and
|
||||
the juce_RTAS_Wrapper.cpp file, you need to set the calling convention to "__stdcall".
|
||||
If you don't do this, you'll get some unresolved externals and will spend a long time wondering what's
|
||||
going on... All the other files in your project can be set to use the normal __cdecl convention.
|
||||
|
||||
If you get an error building the includes statements below, check your paths - there's a full
|
||||
list of the necessary Digidesign paths in juce_RTAS_Wrapper.cpp
|
||||
*/
|
||||
|
||||
#if WINDOWS_VERSION
|
||||
#undef _UNICODE
|
||||
#undef UNICODE
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#pragma clang diagnostic ignored "-Wcomment"
|
||||
#pragma clang diagnostic ignored "-Wreorder"
|
||||
#pragma clang diagnostic ignored "-Wextra-tokens"
|
||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
#endif
|
||||
|
||||
#include <CEffectGroup.cpp>
|
||||
#include <CEffectGroupMIDI.cpp>
|
||||
#include <CEffectMIDIUtils.cpp>
|
||||
#include <CEffectProcess.cpp>
|
||||
#include <CEffectProcessAS.cpp>
|
||||
#include <CEffectType.cpp>
|
||||
#include <CEffectTypeRTAS.cpp>
|
||||
#include <ChunkDataParser.cpp>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wcomment"
|
||||
#pragma clang diagnostic ignored "-Wextra-tokens"
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#pragma clang diagnostic ignored "-Wreorder"
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
#endif
|
||||
|
||||
/*
|
||||
This file is used to include and build the required digidesign CPP files without your project
|
||||
needing to reference the files directly. Because these files will be found via your include path,
|
||||
this means that the project doesn't have to change to cope with people's SDKs being in different
|
||||
locations.
|
||||
|
||||
Important note on Windows: In your project settings for the three juce_RTAS_DigiCode.cpp files and
|
||||
the juce_RTAS_Wrapper.cpp file, you need to set the calling convention to "__stdcall".
|
||||
If you don't do this, you'll get some unresolved externals and will spend a long time wondering what's
|
||||
going on... All the other files in your project can be set to use the normal __cdecl convention.
|
||||
|
||||
If you get an error building the includes statements below, check your paths - there's a full
|
||||
list of the necessary Digidesign paths in juce_RTAS_Wrapper.cpp
|
||||
*/
|
||||
|
||||
#include <CEffectProcessMIDI.cpp>
|
||||
#include <PlugInUtils.cpp>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#pragma clang diagnostic ignored "-Wextra-tokens"
|
||||
#pragma clang diagnostic ignored "-Wreorder"
|
||||
#endif
|
||||
|
||||
/*
|
||||
This file is used to include and build the required digidesign CPP files without your project
|
||||
needing to reference the files directly. Because these files will be found via your include path,
|
||||
this means that the project doesn't have to change to cope with people's SDKs being in different
|
||||
locations.
|
||||
|
||||
Important note on Windows: In your project settings for the three juce_RTAS_DigiCode.cpp files and
|
||||
the juce_RTAS_Wrapper.cpp file, you need to set the calling convention to "__stdcall".
|
||||
If you don't do this, you'll get some unresolved externals and will spend a long time wondering what's
|
||||
going on... All the other files in your project can be set to use the normal __cdecl convention.
|
||||
|
||||
If you get an error building the includes statements below, check your paths - there's a full
|
||||
list of the necessary Digidesign paths in juce_RTAS_Wrapper.cpp
|
||||
*/
|
||||
|
||||
#if WINDOWS_VERSION
|
||||
#undef _UNICODE
|
||||
#undef UNICODE
|
||||
#define DllMain DllMainRTAS
|
||||
#include <DLLMain.cpp>
|
||||
#undef DllMain
|
||||
#include <DefaultSwap.cpp>
|
||||
#else
|
||||
#include <PlugInInitialize.cpp>
|
||||
#include <Dispatcher.cpp>
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if _MSC_VER
|
||||
short __stdcall NewPlugIn (void*) { return 0; }
|
||||
short __stdcall _PI_GetRoutineDescriptor (long, void*) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define kCompileAsCodeResource 0
|
||||
#define kBuildStandAlone 0
|
||||
#define kNoDSP 0
|
||||
#define kNoDAE 0
|
||||
#define kNoSDS 0
|
||||
#define kNoViews 0
|
||||
#define kUseDSPCodeDecode 0
|
||||
|
||||
#define WIN32 1
|
||||
#define WINDOWS_VERSION 1
|
||||
#define PLUGIN_SDK_BUILD 1
|
||||
#define PLUGIN_SDK_DIRECTMIDI 1
|
||||
#define _STDINT_H 1
|
||||
|
||||
// the Digidesign projects all use a struct alignment of 2..
|
||||
#pragma pack (2)
|
||||
#pragma warning (disable: 4267 4996 4311 4312 4103 4121 4100 4127 4189 4245 4389 4512 4701 4703)
|
||||
|
||||
#include <ForcedInclude.h>
|
||||
|
||||
#else
|
||||
|
||||
#define kCompileAsCodeResource 0
|
||||
#define kNoDSP 1
|
||||
#define kNoDAE 0
|
||||
#define kNoSDS 0
|
||||
#define kNoViews 0
|
||||
#define kUseDSPCodeDecode 0
|
||||
|
||||
#define MAC_VERSION 1
|
||||
#define PLUGIN_SDK_BUILD 1
|
||||
#define PLUGIN_SDK_DIRECTMIDI 1
|
||||
#define DIGI_PASCAL
|
||||
|
||||
#include <MacAlwaysInclude.h>
|
||||
|
||||
#endif
|
||||
#endif
|
175
modules/juce_audio_plugin_client/RTAS/juce_RTAS_MacUtilities.mm
Normal file
175
modules/juce_audio_plugin_client/RTAS/juce_RTAS_MacUtilities.mm
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
// Horrible carbon-based fix for a cocoa bug, where an NSWindow that wraps a carbon
|
||||
// window fails to keep its position updated when the user drags the window around..
|
||||
#define WINDOWPOSITION_BODGE 1
|
||||
#define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
using namespace juce;
|
||||
|
||||
//==============================================================================
|
||||
void initialiseMacRTAS();
|
||||
void initialiseMacRTAS()
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
NSApplicationLoad();
|
||||
#endif
|
||||
}
|
||||
|
||||
void* attachSubWindow (void*, Component*);
|
||||
void* attachSubWindow (void* hostWindowRef, Component* comp)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if 0
|
||||
// This was suggested as a way to improve passing keypresses to the host, but
|
||||
// a side-effect seems to be occasional rendering artifacts.
|
||||
HIWindowChangeClass ((WindowRef) hostWindowRef, kFloatingWindowClass);
|
||||
#endif
|
||||
|
||||
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: hostWindowRef];
|
||||
[hostWindow retain];
|
||||
[hostWindow setCanHide: YES];
|
||||
[hostWindow setReleasedWhenClosed: YES];
|
||||
NSRect oldWindowFrame = [hostWindow frame];
|
||||
|
||||
NSView* content = [hostWindow contentView];
|
||||
NSRect f = [content frame];
|
||||
f.size.width = comp->getWidth();
|
||||
f.size.height = comp->getHeight();
|
||||
[content setFrame: f];
|
||||
|
||||
const CGFloat mainScreenHeight = [[[NSScreen screens] objectAtIndex: 0] frame].size.height;
|
||||
|
||||
#if WINDOWPOSITION_BODGE
|
||||
{
|
||||
Rect winBounds;
|
||||
GetWindowBounds ((WindowRef) hostWindowRef, kWindowContentRgn, &winBounds);
|
||||
NSRect w = [hostWindow frame];
|
||||
w.origin.x = winBounds.left;
|
||||
w.origin.y = mainScreenHeight - winBounds.bottom;
|
||||
[hostWindow setFrame: w display: NO animate: NO];
|
||||
}
|
||||
#endif
|
||||
|
||||
NSPoint windowPos = [hostWindow convertBaseToScreen: f.origin];
|
||||
windowPos.x = windowPos.x + jmax (0.0f, (oldWindowFrame.size.width - f.size.width) / 2.0f);
|
||||
windowPos.y = mainScreenHeight - (windowPos.y + f.size.height);
|
||||
|
||||
comp->setTopLeftPosition ((int) windowPos.x, (int) windowPos.y);
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary);
|
||||
#endif
|
||||
|
||||
comp->setVisible (true);
|
||||
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
[hostWindow addChildWindow: pluginWindow
|
||||
ordered: NSWindowAbove];
|
||||
[hostWindow orderFront: nil];
|
||||
[pluginWindow orderFront: nil];
|
||||
|
||||
attachWindowHidingHooks (comp, (WindowRef) hostWindowRef, hostWindow);
|
||||
|
||||
return hostWindow;
|
||||
}
|
||||
}
|
||||
|
||||
void removeSubWindow (void*, Component*);
|
||||
void removeSubWindow (void* nsWindow, Component* comp)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* hostWindow = (NSWindow*) nsWindow;
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
removeWindowHidingHooks (comp);
|
||||
[hostWindow removeChildWindow: pluginWindow];
|
||||
comp->removeFromDesktop();
|
||||
[hostWindow release];
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isJuceWindow (WindowRef w)
|
||||
{
|
||||
for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
|
||||
{
|
||||
ComponentPeer* peer = ComponentPeer::getPeer(i);
|
||||
NSView* view = (NSView*) peer->getNativeHandle();
|
||||
|
||||
if ([[view window] windowRef] == w)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void forwardCurrentKeyEventToHostWindow();
|
||||
void forwardCurrentKeyEventToHostWindow()
|
||||
{
|
||||
WindowRef w = FrontNonFloatingWindow();
|
||||
WindowRef original = w;
|
||||
|
||||
while (IsValidWindowPtr (w) && isJuceWindow (w))
|
||||
{
|
||||
w = GetNextWindowOfClass (w, kDocumentWindowClass, true);
|
||||
|
||||
if (w == original)
|
||||
break;
|
||||
}
|
||||
|
||||
if (! isJuceWindow (w))
|
||||
{
|
||||
ActivateWindow (w, true);
|
||||
repostCurrentNSEvent();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#endif
|
@ -0,0 +1,4 @@
|
||||
EXPORTS
|
||||
NewPlugIn @1
|
||||
_PI_GetRoutineDescriptor @2
|
||||
|
BIN
modules/juce_audio_plugin_client/RTAS/juce_RTAS_WinResources.rsr
Normal file
BIN
modules/juce_audio_plugin_client/RTAS/juce_RTAS_WinResources.rsr
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
159
modules/juce_audio_plugin_client/RTAS/juce_RTAS_WinUtilities.cpp
Normal file
159
modules/juce_audio_plugin_client/RTAS/juce_RTAS_WinUtilities.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
// (these functions are in their own file because of problems including windows.h
|
||||
// at the same time as the Digi headers)
|
||||
|
||||
#define _DO_NOT_DECLARE_INTERLOCKED_INTRINSICS_IN_MEMORY // (workaround for a VC build problem)
|
||||
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#undef STRICT
|
||||
#define STRICT
|
||||
#include <intrin.h>
|
||||
#include <windows.h>
|
||||
|
||||
#pragma pack (push, 8)
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#pragma pack (pop)
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
void JUCE_CALLTYPE attachSubWindow (void* hostWindow,
|
||||
int& titleW, int& titleH,
|
||||
Component* comp)
|
||||
{
|
||||
RECT clientRect;
|
||||
GetClientRect ((HWND) hostWindow, &clientRect);
|
||||
|
||||
titleW = clientRect.right - clientRect.left;
|
||||
titleH = jmax (0, (int) (clientRect.bottom - clientRect.top) - comp->getHeight());
|
||||
comp->setTopLeftPosition (0, titleH);
|
||||
|
||||
comp->addToDesktop (0);
|
||||
|
||||
HWND plugWnd = (HWND) comp->getWindowHandle();
|
||||
SetParent (plugWnd, (HWND) hostWindow);
|
||||
|
||||
DWORD val = GetWindowLong (plugWnd, GWL_STYLE);
|
||||
val = (val & ~WS_POPUP) | WS_CHILD;
|
||||
SetWindowLong (plugWnd, GWL_STYLE, val);
|
||||
|
||||
val = GetWindowLong ((HWND) hostWindow, GWL_STYLE);
|
||||
SetWindowLong ((HWND) hostWindow, GWL_STYLE, val | WS_CLIPCHILDREN);
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE resizeHostWindow (void* hostWindow,
|
||||
int& titleW, int& titleH,
|
||||
Component* comp)
|
||||
{
|
||||
RECT clientRect, windowRect;
|
||||
GetClientRect ((HWND) hostWindow, &clientRect);
|
||||
GetWindowRect ((HWND) hostWindow, &windowRect);
|
||||
const int borderW = (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left);
|
||||
const int borderH = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
|
||||
|
||||
SetWindowPos ((HWND) hostWindow, 0, 0, 0,
|
||||
borderW + jmax (titleW, comp->getWidth()),
|
||||
borderH + comp->getHeight() + titleH,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI DllMainRTAS (HINSTANCE, DWORD, LPVOID);
|
||||
|
||||
extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD reason, LPVOID reserved)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH)
|
||||
Process::setCurrentModuleInstanceHandle (instance);
|
||||
|
||||
if (GetModuleHandleA ("DAE.DLL") != 0)
|
||||
return DllMainRTAS (instance, reason, reserved);
|
||||
|
||||
ignoreUnused (reserved);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
|
||||
namespace
|
||||
{
|
||||
HWND findMDIParentOf (HWND w)
|
||||
{
|
||||
const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME);
|
||||
|
||||
while (w != 0)
|
||||
{
|
||||
HWND parent = GetParent (w);
|
||||
|
||||
if (parent == 0)
|
||||
break;
|
||||
|
||||
TCHAR windowType [32] = { 0 };
|
||||
GetClassName (parent, windowType, 31);
|
||||
|
||||
if (String (windowType).equalsIgnoreCase ("MDIClient"))
|
||||
{
|
||||
w = parent;
|
||||
break;
|
||||
}
|
||||
|
||||
RECT windowPos, parentPos;
|
||||
GetWindowRect (w, &windowPos);
|
||||
GetWindowRect (parent, &parentPos);
|
||||
|
||||
int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left);
|
||||
int dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top);
|
||||
|
||||
if (dw > 100 || dh > 100)
|
||||
break;
|
||||
|
||||
w = parent;
|
||||
|
||||
if (dw == 2 * frameThickness)
|
||||
break;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE passFocusToHostWindow (void* hostWindow)
|
||||
{
|
||||
SetFocus (findMDIParentOf ((HWND) hostWindow));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#endif
|
1067
modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
Normal file
1067
modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,170 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
|
||||
#include <juce_audio_devices/juce_audio_devices.h>
|
||||
#include <juce_gui_extra/juce_gui_extra.h>
|
||||
#include <juce_audio_utils/juce_audio_utils.h>
|
||||
|
||||
// You can set this flag in your build if you need to specify a different
|
||||
// standalone JUCEApplication class for your app to use. If you don't
|
||||
// set it then by default we'll just create a simple one as below.
|
||||
#if ! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP
|
||||
|
||||
extern juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter();
|
||||
|
||||
#include "juce_StandaloneFilterWindow.h"
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
class StandaloneFilterApp : public JUCEApplication
|
||||
{
|
||||
public:
|
||||
StandaloneFilterApp()
|
||||
{
|
||||
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Standalone;
|
||||
|
||||
PropertiesFile::Options options;
|
||||
|
||||
options.applicationName = getApplicationName();
|
||||
options.filenameSuffix = ".settings";
|
||||
options.osxLibrarySubFolder = "Application Support";
|
||||
#if JUCE_LINUX
|
||||
options.folderName = "~/.config";
|
||||
#else
|
||||
options.folderName = "";
|
||||
#endif
|
||||
|
||||
appProperties.setStorageParameters (options);
|
||||
}
|
||||
|
||||
const String getApplicationName() override { return JucePlugin_Name; }
|
||||
const String getApplicationVersion() override { return JucePlugin_VersionString; }
|
||||
bool moreThanOneInstanceAllowed() override { return true; }
|
||||
void anotherInstanceStarted (const String&) override {}
|
||||
|
||||
virtual StandaloneFilterWindow* createWindow()
|
||||
{
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
StandalonePluginHolder::PluginInOuts channels[] = { JucePlugin_PreferredChannelConfigurations };
|
||||
#endif
|
||||
|
||||
return new StandaloneFilterWindow (getApplicationName(),
|
||||
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
|
||||
appProperties.getUserSettings(),
|
||||
false, {}, nullptr
|
||||
#ifdef JucePlugin_PreferredChannelConfigurations
|
||||
, juce::Array<StandalonePluginHolder::PluginInOuts> (channels, juce::numElementsInArray (channels))
|
||||
#else
|
||||
, {}
|
||||
#endif
|
||||
#if JUCE_DONT_AUTO_OPEN_MIDI_DEVICES_ON_MOBILE
|
||||
, false
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void initialise (const String&) override
|
||||
{
|
||||
mainWindow.reset (createWindow());
|
||||
|
||||
#if JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
|
||||
Desktop::getInstance().setKioskModeComponent (mainWindow.get(), false);
|
||||
#endif
|
||||
|
||||
mainWindow->setVisible (true);
|
||||
}
|
||||
|
||||
void shutdown() override
|
||||
{
|
||||
mainWindow = nullptr;
|
||||
appProperties.saveIfNeeded();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void systemRequestedQuit() override
|
||||
{
|
||||
if (ModalComponentManager::getInstance()->cancelAllModalComponents())
|
||||
{
|
||||
Timer::callAfterDelay (100, []()
|
||||
{
|
||||
if (auto app = JUCEApplicationBase::getInstance())
|
||||
app->systemRequestedQuit();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ApplicationProperties appProperties;
|
||||
std::unique_ptr<StandaloneFilterWindow> mainWindow;
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#if JucePlugin_Build_Standalone && JUCE_IOS
|
||||
|
||||
using namespace juce;
|
||||
|
||||
bool JUCE_CALLTYPE juce_isInterAppAudioConnected()
|
||||
{
|
||||
if (auto holder = StandalonePluginHolder::getInstance())
|
||||
return holder->isInterAppAudioConnected();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE juce_switchToHostApplication()
|
||||
{
|
||||
if (auto holder = StandalonePluginHolder::getInstance())
|
||||
holder->switchToHostApplication();
|
||||
}
|
||||
|
||||
#if JUCE_MODULE_AVAILABLE_juce_gui_basics
|
||||
Image JUCE_CALLTYPE juce_getIAAHostIcon (int size)
|
||||
{
|
||||
if (auto holder = StandalonePluginHolder::getInstance())
|
||||
return holder->getIAAHostIcon (size);
|
||||
|
||||
return Image();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,883 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
|
||||
extern juce::AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (juce::AudioProcessor::WrapperType type);
|
||||
#endif
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An object that creates and plays a standalone instance of an AudioProcessor.
|
||||
|
||||
The object will create your processor using the same createPluginFilter()
|
||||
function that the other plugin wrappers use, and will run it through the
|
||||
computer's audio/MIDI devices using AudioDeviceManager and AudioProcessorPlayer.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class StandalonePluginHolder : private AudioIODeviceCallback,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Structure used for the number of inputs and outputs. */
|
||||
struct PluginInOuts { short numIns, numOuts; };
|
||||
|
||||
//==============================================================================
|
||||
/** Creates an instance of the default plugin.
|
||||
|
||||
The settings object can be a PropertySet that the class should use to store its
|
||||
settings - the takeOwnershipOfSettings indicates whether this object will delete
|
||||
the settings automatically when no longer needed. The settings can also be nullptr.
|
||||
|
||||
A default device name can be passed in.
|
||||
|
||||
Preferably a complete setup options object can be used, which takes precedence over
|
||||
the preferredDefaultDeviceName and allows you to select the input & output device names,
|
||||
sample rate, buffer size etc.
|
||||
|
||||
In all instances, the settingsToUse will take precedence over the "preferred" options if not null.
|
||||
*/
|
||||
StandalonePluginHolder (PropertySet* settingsToUse,
|
||||
bool takeOwnershipOfSettings = true,
|
||||
const String& preferredDefaultDeviceName = String(),
|
||||
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions = nullptr,
|
||||
const Array<PluginInOuts>& channels = Array<PluginInOuts>(),
|
||||
#if JUCE_ANDROID || JUCE_IOS
|
||||
bool shouldAutoOpenMidiDevices = true
|
||||
#else
|
||||
bool shouldAutoOpenMidiDevices = false
|
||||
#endif
|
||||
)
|
||||
|
||||
: settings (settingsToUse, takeOwnershipOfSettings),
|
||||
channelConfiguration (channels),
|
||||
shouldMuteInput (! isInterAppAudioConnected()),
|
||||
autoOpenMidiDevices (shouldAutoOpenMidiDevices)
|
||||
{
|
||||
createPlugin();
|
||||
|
||||
auto inChannels = (channelConfiguration.size() > 0 ? channelConfiguration[0].numIns
|
||||
: processor->getMainBusNumInputChannels());
|
||||
|
||||
if (preferredSetupOptions != nullptr)
|
||||
options.reset (new AudioDeviceManager::AudioDeviceSetup (*preferredSetupOptions));
|
||||
|
||||
if (inChannels > 0 && RuntimePermissions::isRequired (RuntimePermissions::recordAudio)
|
||||
&& ! RuntimePermissions::isGranted (RuntimePermissions::recordAudio))
|
||||
RuntimePermissions::request (RuntimePermissions::recordAudio,
|
||||
[this, preferredDefaultDeviceName] (bool granted) { init (granted, preferredDefaultDeviceName); });
|
||||
else
|
||||
init (true, preferredDefaultDeviceName);
|
||||
}
|
||||
|
||||
void init (bool enableAudioInput, const String& preferredDefaultDeviceName)
|
||||
{
|
||||
setupAudioDevices (enableAudioInput, preferredDefaultDeviceName, options.get());
|
||||
reloadPluginState();
|
||||
startPlaying();
|
||||
|
||||
if (autoOpenMidiDevices)
|
||||
startTimer (500);
|
||||
}
|
||||
|
||||
virtual ~StandalonePluginHolder()
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
deletePlugin();
|
||||
shutDownAudioDevices();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
virtual void createPlugin()
|
||||
{
|
||||
|
||||
#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client
|
||||
processor.reset (::createPluginFilterOfType (AudioProcessor::wrapperType_Standalone));
|
||||
#else
|
||||
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Standalone);
|
||||
processor.reset (createPluginFilter());
|
||||
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined);
|
||||
#endif
|
||||
jassert (processor != nullptr); // Your createPluginFilter() function must return a valid object!
|
||||
|
||||
processor->disableNonMainBuses();
|
||||
processor->setRateAndBufferSizeDetails (44100, 512);
|
||||
|
||||
int inChannels = (channelConfiguration.size() > 0 ? channelConfiguration[0].numIns
|
||||
: processor->getMainBusNumInputChannels());
|
||||
|
||||
int outChannels = (channelConfiguration.size() > 0 ? channelConfiguration[0].numOuts
|
||||
: processor->getMainBusNumOutputChannels());
|
||||
|
||||
processorHasPotentialFeedbackLoop = (inChannels > 0 && outChannels > 0);
|
||||
}
|
||||
|
||||
virtual void deletePlugin()
|
||||
{
|
||||
stopPlaying();
|
||||
processor = nullptr;
|
||||
}
|
||||
|
||||
static String getFilePatterns (const String& fileSuffix)
|
||||
{
|
||||
if (fileSuffix.isEmpty())
|
||||
return {};
|
||||
|
||||
return (fileSuffix.startsWithChar ('.') ? "*" : "*.") + fileSuffix;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Value& getMuteInputValue() { return shouldMuteInput; }
|
||||
bool getProcessorHasPotentialFeedbackLoop() const { return processorHasPotentialFeedbackLoop; }
|
||||
|
||||
//==============================================================================
|
||||
File getLastFile() const
|
||||
{
|
||||
File f;
|
||||
|
||||
if (settings != nullptr)
|
||||
f = File (settings->getValue ("lastStateFile"));
|
||||
|
||||
if (f == File())
|
||||
f = File::getSpecialLocation (File::userDocumentsDirectory);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void setLastFile (const FileChooser& fc)
|
||||
{
|
||||
if (settings != nullptr)
|
||||
settings->setValue ("lastStateFile", fc.getResult().getFullPathName());
|
||||
}
|
||||
|
||||
/** Pops up a dialog letting the user save the processor's state to a file. */
|
||||
void askUserToSaveState (const String& fileSuffix = String())
|
||||
{
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
FileChooser fc (TRANS("Save current state"), getLastFile(), getFilePatterns (fileSuffix));
|
||||
|
||||
if (fc.browseForFileToSave (true))
|
||||
{
|
||||
setLastFile (fc);
|
||||
|
||||
MemoryBlock data;
|
||||
processor->getStateInformation (data);
|
||||
|
||||
if (! fc.getResult().replaceWithData (data.getData(), data.getSize()))
|
||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
|
||||
TRANS("Error whilst saving"),
|
||||
TRANS("Couldn't write to the specified file!"));
|
||||
}
|
||||
#else
|
||||
ignoreUnused (fileSuffix);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Pops up a dialog letting the user re-load the processor's state from a file. */
|
||||
void askUserToLoadState (const String& fileSuffix = String())
|
||||
{
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
FileChooser fc (TRANS("Load a saved state"), getLastFile(), getFilePatterns (fileSuffix));
|
||||
|
||||
if (fc.browseForFileToOpen())
|
||||
{
|
||||
setLastFile (fc);
|
||||
|
||||
MemoryBlock data;
|
||||
|
||||
if (fc.getResult().loadFileAsData (data))
|
||||
processor->setStateInformation (data.getData(), (int) data.getSize());
|
||||
else
|
||||
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
|
||||
TRANS("Error whilst loading"),
|
||||
TRANS("Couldn't read from the specified file!"));
|
||||
}
|
||||
#else
|
||||
ignoreUnused (fileSuffix);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void startPlaying()
|
||||
{
|
||||
player.setProcessor (processor.get());
|
||||
|
||||
#if JucePlugin_Enable_IAA && JUCE_IOS
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
{
|
||||
processor->setPlayHead (device->getAudioPlayHead());
|
||||
device->setMidiMessageCollector (&player.getMidiMessageCollector());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void stopPlaying()
|
||||
{
|
||||
player.setProcessor (nullptr);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Shows an audio properties dialog box modally. */
|
||||
void showAudioSettingsDialog()
|
||||
{
|
||||
DialogWindow::LaunchOptions o;
|
||||
|
||||
int minNumInputs = std::numeric_limits<int>::max(), maxNumInputs = 0,
|
||||
minNumOutputs = std::numeric_limits<int>::max(), maxNumOutputs = 0;
|
||||
|
||||
auto updateMinAndMax = [] (int newValue, int& minValue, int& maxValue)
|
||||
{
|
||||
minValue = jmin (minValue, newValue);
|
||||
maxValue = jmax (maxValue, newValue);
|
||||
};
|
||||
|
||||
if (channelConfiguration.size() > 0)
|
||||
{
|
||||
auto defaultConfig = channelConfiguration.getReference (0);
|
||||
updateMinAndMax ((int) defaultConfig.numIns, minNumInputs, maxNumInputs);
|
||||
updateMinAndMax ((int) defaultConfig.numOuts, minNumOutputs, maxNumOutputs);
|
||||
}
|
||||
|
||||
if (auto* bus = processor->getBus (true, 0))
|
||||
updateMinAndMax (bus->getDefaultLayout().size(), minNumInputs, maxNumInputs);
|
||||
|
||||
if (auto* bus = processor->getBus (false, 0))
|
||||
updateMinAndMax (bus->getDefaultLayout().size(), minNumOutputs, maxNumOutputs);
|
||||
|
||||
minNumInputs = jmin (minNumInputs, maxNumInputs);
|
||||
minNumOutputs = jmin (minNumOutputs, maxNumOutputs);
|
||||
|
||||
o.content.setOwned (new SettingsComponent (*this, deviceManager,
|
||||
minNumInputs,
|
||||
maxNumInputs,
|
||||
minNumOutputs,
|
||||
maxNumOutputs));
|
||||
o.content->setSize (500, 550);
|
||||
|
||||
o.dialogTitle = TRANS("Audio/MIDI Settings");
|
||||
o.dialogBackgroundColour = o.content->getLookAndFeel().findColour (ResizableWindow::backgroundColourId);
|
||||
o.escapeKeyTriggersCloseButton = true;
|
||||
o.useNativeTitleBar = true;
|
||||
o.resizable = false;
|
||||
|
||||
o.launchAsync();
|
||||
}
|
||||
|
||||
void saveAudioDeviceState()
|
||||
{
|
||||
if (settings != nullptr)
|
||||
{
|
||||
std::unique_ptr<XmlElement> xml (deviceManager.createStateXml());
|
||||
|
||||
settings->setValue ("audioSetup", xml.get());
|
||||
|
||||
#if ! (JUCE_IOS || JUCE_ANDROID)
|
||||
settings->setValue ("shouldMuteInput", (bool) shouldMuteInput.getValue());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void reloadAudioDeviceState (bool enableAudioInput,
|
||||
const String& preferredDefaultDeviceName,
|
||||
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions)
|
||||
{
|
||||
std::unique_ptr<XmlElement> savedState;
|
||||
|
||||
if (settings != nullptr)
|
||||
{
|
||||
savedState.reset (settings->getXmlValue ("audioSetup"));
|
||||
|
||||
#if ! (JUCE_IOS || JUCE_ANDROID)
|
||||
shouldMuteInput.setValue (settings->getBoolValue ("shouldMuteInput", true));
|
||||
#endif
|
||||
}
|
||||
|
||||
auto totalInChannels = processor->getMainBusNumInputChannels();
|
||||
auto totalOutChannels = processor->getMainBusNumOutputChannels();
|
||||
|
||||
if (channelConfiguration.size() > 0)
|
||||
{
|
||||
auto defaultConfig = channelConfiguration.getReference (0);
|
||||
totalInChannels = defaultConfig.numIns;
|
||||
totalOutChannels = defaultConfig.numOuts;
|
||||
}
|
||||
|
||||
deviceManager.initialise (enableAudioInput ? totalInChannels : 0,
|
||||
totalOutChannels,
|
||||
savedState.get(),
|
||||
true,
|
||||
preferredDefaultDeviceName,
|
||||
preferredSetupOptions);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void savePluginState()
|
||||
{
|
||||
if (settings != nullptr && processor != nullptr)
|
||||
{
|
||||
MemoryBlock data;
|
||||
processor->getStateInformation (data);
|
||||
|
||||
settings->setValue ("filterState", data.toBase64Encoding());
|
||||
}
|
||||
}
|
||||
|
||||
void reloadPluginState()
|
||||
{
|
||||
if (settings != nullptr)
|
||||
{
|
||||
MemoryBlock data;
|
||||
|
||||
if (data.fromBase64Encoding (settings->getValue ("filterState")) && data.getSize() > 0)
|
||||
processor->setStateInformation (data.getData(), (int) data.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void switchToHostApplication()
|
||||
{
|
||||
#if JUCE_IOS
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
device->switchApplication();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isInterAppAudioConnected()
|
||||
{
|
||||
#if JUCE_IOS
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
return device->isInterAppAudioConnected();
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if JUCE_MODULE_AVAILABLE_juce_gui_basics
|
||||
Image getIAAHostIcon (int size)
|
||||
{
|
||||
#if JUCE_IOS && JucePlugin_Enable_IAA
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
return device->getIcon (size);
|
||||
#else
|
||||
ignoreUnused (size);
|
||||
#endif
|
||||
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
static StandalonePluginHolder* getInstance();
|
||||
|
||||
//==============================================================================
|
||||
OptionalScopedPointer<PropertySet> settings;
|
||||
std::unique_ptr<AudioProcessor> processor;
|
||||
AudioDeviceManager deviceManager;
|
||||
AudioProcessorPlayer player;
|
||||
Array<PluginInOuts> channelConfiguration;
|
||||
|
||||
// avoid feedback loop by default
|
||||
bool processorHasPotentialFeedbackLoop = true;
|
||||
Value shouldMuteInput;
|
||||
AudioBuffer<float> emptyBuffer;
|
||||
bool autoOpenMidiDevices;
|
||||
|
||||
std::unique_ptr<AudioDeviceManager::AudioDeviceSetup> options;
|
||||
StringArray lastMidiDevices;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class SettingsComponent : public Component
|
||||
{
|
||||
public:
|
||||
SettingsComponent (StandalonePluginHolder& pluginHolder,
|
||||
AudioDeviceManager& deviceManagerToUse,
|
||||
int minAudioInputChannels,
|
||||
int maxAudioInputChannels,
|
||||
int minAudioOutputChannels,
|
||||
int maxAudioOutputChannels)
|
||||
: owner (pluginHolder),
|
||||
deviceSelector (deviceManagerToUse,
|
||||
minAudioInputChannels, maxAudioInputChannels,
|
||||
minAudioOutputChannels, maxAudioOutputChannels,
|
||||
true, false,
|
||||
true, false),
|
||||
shouldMuteLabel ("Feedback Loop:", "Feedback Loop:"),
|
||||
shouldMuteButton ("Mute audio input")
|
||||
{
|
||||
setOpaque (true);
|
||||
|
||||
shouldMuteButton.setClickingTogglesState (true);
|
||||
shouldMuteButton.getToggleStateValue().referTo (owner.shouldMuteInput);
|
||||
|
||||
addAndMakeVisible (deviceSelector);
|
||||
|
||||
if (owner.getProcessorHasPotentialFeedbackLoop())
|
||||
{
|
||||
addAndMakeVisible (shouldMuteButton);
|
||||
addAndMakeVisible (shouldMuteLabel);
|
||||
|
||||
shouldMuteLabel.attachToComponent (&shouldMuteButton, true);
|
||||
}
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto r = getLocalBounds();
|
||||
|
||||
if (owner.getProcessorHasPotentialFeedbackLoop())
|
||||
{
|
||||
auto itemHeight = deviceSelector.getItemHeight();
|
||||
auto extra = r.removeFromTop (itemHeight);
|
||||
|
||||
auto seperatorHeight = (itemHeight >> 1);
|
||||
shouldMuteButton.setBounds (Rectangle<int> (extra.proportionOfWidth (0.35f), seperatorHeight,
|
||||
extra.proportionOfWidth (0.60f), deviceSelector.getItemHeight()));
|
||||
|
||||
r.removeFromTop (seperatorHeight);
|
||||
}
|
||||
|
||||
deviceSelector.setBounds (r);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
StandalonePluginHolder& owner;
|
||||
AudioDeviceSelectorComponent deviceSelector;
|
||||
Label shouldMuteLabel;
|
||||
ToggleButton shouldMuteButton;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SettingsComponent)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void audioDeviceIOCallback (const float** inputChannelData,
|
||||
int numInputChannels,
|
||||
float** outputChannelData,
|
||||
int numOutputChannels,
|
||||
int numSamples) override
|
||||
{
|
||||
const bool inputMuted = shouldMuteInput.getValue();
|
||||
|
||||
if (inputMuted)
|
||||
{
|
||||
emptyBuffer.clear();
|
||||
inputChannelData = emptyBuffer.getArrayOfReadPointers();
|
||||
}
|
||||
|
||||
player.audioDeviceIOCallback (inputChannelData, numInputChannels,
|
||||
outputChannelData, numOutputChannels, numSamples);
|
||||
}
|
||||
|
||||
void audioDeviceAboutToStart (AudioIODevice* device) override
|
||||
{
|
||||
emptyBuffer.setSize (device->getActiveInputChannels().countNumberOfSetBits(), device->getCurrentBufferSizeSamples());
|
||||
emptyBuffer.clear();
|
||||
|
||||
player.audioDeviceAboutToStart (device);
|
||||
}
|
||||
|
||||
void audioDeviceStopped() override
|
||||
{
|
||||
player.audioDeviceStopped();
|
||||
emptyBuffer.setSize (0, 0);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void setupAudioDevices (bool enableAudioInput,
|
||||
const String& preferredDefaultDeviceName,
|
||||
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions)
|
||||
{
|
||||
deviceManager.addAudioCallback (this);
|
||||
deviceManager.addMidiInputCallback ({}, &player);
|
||||
|
||||
reloadAudioDeviceState (enableAudioInput, preferredDefaultDeviceName, preferredSetupOptions);
|
||||
}
|
||||
|
||||
void shutDownAudioDevices()
|
||||
{
|
||||
saveAudioDeviceState();
|
||||
|
||||
deviceManager.removeMidiInputCallback ({}, &player);
|
||||
deviceManager.removeAudioCallback (this);
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
auto newMidiDevices = MidiInput::getDevices();
|
||||
|
||||
if (newMidiDevices != lastMidiDevices)
|
||||
{
|
||||
for (auto& oldDevice : lastMidiDevices)
|
||||
if (! newMidiDevices.contains (oldDevice))
|
||||
deviceManager.setMidiInputEnabled (oldDevice, false);
|
||||
|
||||
for (auto& newDevice : newMidiDevices)
|
||||
if (! lastMidiDevices.contains (newDevice))
|
||||
deviceManager.setMidiInputEnabled (newDevice, true);
|
||||
}
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandalonePluginHolder)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class that can be used to run a simple standalone application containing your filter.
|
||||
|
||||
Just create one of these objects in your JUCEApplicationBase::initialise() method, and
|
||||
let it do its work. It will create your filter object using the same createPluginFilter() function
|
||||
that the other plugin wrappers use.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class StandaloneFilterWindow : public DocumentWindow,
|
||||
public Button::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
typedef StandalonePluginHolder::PluginInOuts PluginInOuts;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a window with a given title and colour.
|
||||
The settings object can be a PropertySet that the class should use to
|
||||
store its settings (it can also be null). If takeOwnershipOfSettings is
|
||||
true, then the settings object will be owned and deleted by this object.
|
||||
*/
|
||||
StandaloneFilterWindow (const String& title,
|
||||
Colour backgroundColour,
|
||||
PropertySet* settingsToUse,
|
||||
bool takeOwnershipOfSettings,
|
||||
const String& preferredDefaultDeviceName = String(),
|
||||
const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions = nullptr,
|
||||
const Array<PluginInOuts>& constrainToConfiguration = {},
|
||||
#if JUCE_ANDROID || JUCE_IOS
|
||||
bool autoOpenMidiDevices = true
|
||||
#else
|
||||
bool autoOpenMidiDevices = false
|
||||
#endif
|
||||
)
|
||||
: DocumentWindow (title, backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton),
|
||||
optionsButton ("Options")
|
||||
{
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
setTitleBarHeight (0);
|
||||
#else
|
||||
setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false);
|
||||
|
||||
Component::addAndMakeVisible (optionsButton);
|
||||
optionsButton.addListener (this);
|
||||
optionsButton.setTriggeredOnMouseDown (true);
|
||||
#endif
|
||||
|
||||
pluginHolder.reset (new StandalonePluginHolder (settingsToUse, takeOwnershipOfSettings,
|
||||
preferredDefaultDeviceName, preferredSetupOptions,
|
||||
constrainToConfiguration, autoOpenMidiDevices));
|
||||
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
setFullScreen (true);
|
||||
setContentOwned (new MainContentComponent (*this), false);
|
||||
#else
|
||||
setContentOwned (new MainContentComponent (*this), true);
|
||||
|
||||
if (auto* props = pluginHolder->settings.get())
|
||||
{
|
||||
const int x = props->getIntValue ("windowX", -100);
|
||||
const int y = props->getIntValue ("windowY", -100);
|
||||
|
||||
if (x != -100 && y != -100)
|
||||
setBoundsConstrained ({ x, y, getWidth(), getHeight() });
|
||||
else
|
||||
centreWithSize (getWidth(), getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
centreWithSize (getWidth(), getHeight());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
~StandaloneFilterWindow()
|
||||
{
|
||||
#if (! JUCE_IOS) && (! JUCE_ANDROID)
|
||||
if (auto* props = pluginHolder->settings.get())
|
||||
{
|
||||
props->setValue ("windowX", getX());
|
||||
props->setValue ("windowY", getY());
|
||||
}
|
||||
#endif
|
||||
|
||||
pluginHolder->stopPlaying();
|
||||
clearContentComponent();
|
||||
pluginHolder = nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessor* getAudioProcessor() const noexcept { return pluginHolder->processor.get(); }
|
||||
AudioDeviceManager& getDeviceManager() const noexcept { return pluginHolder->deviceManager; }
|
||||
|
||||
/** Deletes and re-creates the plugin, resetting it to its default state. */
|
||||
void resetToDefaultState()
|
||||
{
|
||||
pluginHolder->stopPlaying();
|
||||
clearContentComponent();
|
||||
pluginHolder->deletePlugin();
|
||||
|
||||
if (auto* props = pluginHolder->settings.get())
|
||||
props->removeValue ("filterState");
|
||||
|
||||
pluginHolder->createPlugin();
|
||||
setContentOwned (new MainContentComponent (*this), true);
|
||||
pluginHolder->startPlaying();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void closeButtonPressed() override
|
||||
{
|
||||
pluginHolder->savePluginState();
|
||||
|
||||
JUCEApplicationBase::quit();
|
||||
}
|
||||
|
||||
void buttonClicked (Button*) override
|
||||
{
|
||||
PopupMenu m;
|
||||
m.addItem (1, TRANS("Audio/MIDI Settings..."));
|
||||
m.addSeparator();
|
||||
m.addItem (2, TRANS("Save current state..."));
|
||||
m.addItem (3, TRANS("Load a saved state..."));
|
||||
m.addSeparator();
|
||||
m.addItem (4, TRANS("Reset to default state"));
|
||||
|
||||
m.showMenuAsync (PopupMenu::Options(),
|
||||
ModalCallbackFunction::forComponent (menuCallback, this));
|
||||
}
|
||||
|
||||
void handleMenuResult (int result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case 1: pluginHolder->showAudioSettingsDialog(); break;
|
||||
case 2: pluginHolder->askUserToSaveState(); break;
|
||||
case 3: pluginHolder->askUserToLoadState(); break;
|
||||
case 4: resetToDefaultState(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void menuCallback (int result, StandaloneFilterWindow* button)
|
||||
{
|
||||
if (button != nullptr && result != 0)
|
||||
button->handleMenuResult (result);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
DocumentWindow::resized();
|
||||
optionsButton.setBounds (8, 6, 60, getTitleBarHeight() - 8);
|
||||
}
|
||||
|
||||
virtual StandalonePluginHolder* getPluginHolder() { return pluginHolder.get(); }
|
||||
|
||||
std::unique_ptr<StandalonePluginHolder> pluginHolder;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class MainContentComponent : public Component,
|
||||
private Value::Listener,
|
||||
private Button::Listener,
|
||||
private ComponentListener
|
||||
{
|
||||
public:
|
||||
MainContentComponent (StandaloneFilterWindow& filterWindow)
|
||||
: owner (filterWindow), notification (this),
|
||||
editor (owner.getAudioProcessor()->createEditorIfNeeded())
|
||||
{
|
||||
Value& inputMutedValue = owner.pluginHolder->getMuteInputValue();
|
||||
|
||||
if (editor != nullptr)
|
||||
{
|
||||
editor->addComponentListener (this);
|
||||
componentMovedOrResized (*editor, false, true);
|
||||
|
||||
addAndMakeVisible (editor.get());
|
||||
}
|
||||
|
||||
addChildComponent (notification);
|
||||
|
||||
if (owner.pluginHolder->getProcessorHasPotentialFeedbackLoop())
|
||||
{
|
||||
inputMutedValue.addListener (this);
|
||||
shouldShowNotification = inputMutedValue.getValue();
|
||||
}
|
||||
|
||||
inputMutedChanged (shouldShowNotification);
|
||||
}
|
||||
|
||||
~MainContentComponent()
|
||||
{
|
||||
if (editor != nullptr)
|
||||
{
|
||||
editor->removeComponentListener (this);
|
||||
owner.pluginHolder->processor->editorBeingDeleted (editor.get());
|
||||
editor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto r = getLocalBounds();
|
||||
|
||||
if (shouldShowNotification)
|
||||
notification.setBounds (r.removeFromTop (NotificationArea::height));
|
||||
|
||||
editor->setBounds (r);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class NotificationArea : public Component
|
||||
{
|
||||
public:
|
||||
enum { height = 30 };
|
||||
|
||||
NotificationArea (Button::Listener* settingsButtonListener)
|
||||
: notification ("notification", "Audio input is muted to avoid feedback loop"),
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
settingsButton ("Unmute Input")
|
||||
#else
|
||||
settingsButton ("Settings...")
|
||||
#endif
|
||||
{
|
||||
setOpaque (true);
|
||||
|
||||
notification.setColour (Label::textColourId, Colours::black);
|
||||
|
||||
settingsButton.addListener (settingsButtonListener);
|
||||
|
||||
addAndMakeVisible (notification);
|
||||
addAndMakeVisible (settingsButton);
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
auto r = getLocalBounds();
|
||||
|
||||
g.setColour (Colours::darkgoldenrod);
|
||||
g.fillRect (r.removeFromBottom (1));
|
||||
|
||||
g.setColour (Colours::lightgoldenrodyellow);
|
||||
g.fillRect (r);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto r = getLocalBounds().reduced (5);
|
||||
|
||||
settingsButton.setBounds (r.removeFromRight (70));
|
||||
notification.setBounds (r);
|
||||
}
|
||||
private:
|
||||
Label notification;
|
||||
TextButton settingsButton;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void inputMutedChanged (bool newInputMutedValue)
|
||||
{
|
||||
shouldShowNotification = newInputMutedValue;
|
||||
notification.setVisible (shouldShowNotification);
|
||||
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
resized();
|
||||
#else
|
||||
setSize (editor->getWidth(),
|
||||
editor->getHeight()
|
||||
+ (shouldShowNotification ? NotificationArea::height : 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
void valueChanged (Value& value) override { inputMutedChanged (value.getValue()); }
|
||||
void buttonClicked (Button*) override
|
||||
{
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
owner.pluginHolder->getMuteInputValue().setValue (false);
|
||||
#else
|
||||
owner.pluginHolder->showAudioSettingsDialog();
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void componentMovedOrResized (Component&, bool, bool wasResized) override
|
||||
{
|
||||
if (wasResized && editor != nullptr)
|
||||
setSize (editor->getWidth(),
|
||||
editor->getHeight() + (shouldShowNotification ? NotificationArea::height : 0));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
StandaloneFilterWindow& owner;
|
||||
NotificationArea notification;
|
||||
std::unique_ptr<AudioProcessorEditor> editor;
|
||||
bool shouldShowNotification = false;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
TextButton optionsButton;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandaloneFilterWindow)
|
||||
};
|
||||
|
||||
inline StandalonePluginHolder* StandalonePluginHolder::getInstance()
|
||||
{
|
||||
#if JucePlugin_Enable_IAA || JucePlugin_Build_Standalone
|
||||
if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone)
|
||||
{
|
||||
auto& desktop = Desktop::getInstance();
|
||||
const int numTopLevelWindows = desktop.getNumComponents();
|
||||
|
||||
for (int i = 0; i < numTopLevelWindows; ++i)
|
||||
if (auto window = dynamic_cast<StandaloneFilterWindow*> (desktop.getComponent (i)))
|
||||
return window->getPluginHolder();
|
||||
}
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace juce
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/** An interface to allow an AudioProcessor to receive VST specific calls from
|
||||
the host.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
struct VSTCallbackHandler
|
||||
{
|
||||
virtual ~VSTCallbackHandler() {}
|
||||
|
||||
/** This is called by the VST plug-in wrapper when it receives unhandled
|
||||
plug-in "can do" calls from the host.
|
||||
*/
|
||||
virtual pointer_sized_int handleVstPluginCanDo (int32 index,
|
||||
pointer_sized_int value,
|
||||
void* ptr,
|
||||
float opt)
|
||||
{
|
||||
ignoreUnused (index, value, ptr, opt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** This is called by the VST plug-in wrapper when it receives unhandled
|
||||
vendor specific calls from the host.
|
||||
*/
|
||||
virtual pointer_sized_int handleVstManufacturerSpecific (int32 index,
|
||||
pointer_sized_int value,
|
||||
void* ptr,
|
||||
float opt) = 0;
|
||||
};
|
||||
|
||||
} // namespace juce
|
2292
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
Normal file
2292
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
319
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
Normal file
319
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../juce_core/system/juce_TargetPlatform.h"
|
||||
|
||||
#if JUCE_MAC
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_VST || JucePlugin_Build_VST3
|
||||
|
||||
#define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
//==============================================================================
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if ! JUCE_64BIT
|
||||
JUCE_API void updateEditorCompBoundsVST (Component*);
|
||||
void updateEditorCompBoundsVST (Component* comp)
|
||||
{
|
||||
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
|
||||
|
||||
HIRect r;
|
||||
HIViewGetFrame (dummyView, &r);
|
||||
HIViewRef root;
|
||||
HIViewFindByID (HIViewGetRoot (HIViewGetWindow (dummyView)), kHIViewWindowContentID, &root);
|
||||
HIViewConvertRect (&r, HIViewGetSuperview (dummyView), root);
|
||||
|
||||
Rect windowPos;
|
||||
GetWindowBounds (HIViewGetWindow (dummyView), kWindowContentRgn, &windowPos);
|
||||
|
||||
comp->setTopLeftPosition ((int) (windowPos.left + r.origin.x),
|
||||
(int) (windowPos.top + r.origin.y));
|
||||
}
|
||||
|
||||
static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
|
||||
{
|
||||
updateEditorCompBoundsVST ((Component*) user);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static bool shouldManuallyCloseHostWindow()
|
||||
{
|
||||
return getHostType().isCubase7orLater() || getHostType().isRenoise() || ((SystemStats::getOperatingSystemType() & 0xff) >= 12);
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
JUCE_API void initialiseMacVST();
|
||||
void initialiseMacVST()
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
NSApplicationLoad();
|
||||
#endif
|
||||
}
|
||||
|
||||
JUCE_API void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView);
|
||||
void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: parentWindowOrView];
|
||||
|
||||
if (shouldManuallyCloseHostWindow())
|
||||
{
|
||||
[hostWindow setReleasedWhenClosed: NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
[hostWindow retain];
|
||||
[hostWindow setReleasedWhenClosed: YES];
|
||||
}
|
||||
|
||||
[hostWindow setCanHide: YES];
|
||||
|
||||
HIViewRef parentView = 0;
|
||||
|
||||
WindowAttributes attributes;
|
||||
GetWindowAttributes ((WindowRef) parentWindowOrView, &attributes);
|
||||
|
||||
if ((attributes & kWindowCompositingAttribute) != 0)
|
||||
{
|
||||
HIViewRef root = HIViewGetRoot ((WindowRef) parentWindowOrView);
|
||||
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
|
||||
|
||||
if (parentView == 0)
|
||||
parentView = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
|
||||
|
||||
if (parentView == 0)
|
||||
CreateRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
|
||||
}
|
||||
|
||||
// It seems that the only way to successfully position our overlaid window is by putting a dummy
|
||||
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
|
||||
HIViewRef dummyView = 0;
|
||||
HIImageViewCreate (0, &dummyView);
|
||||
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
|
||||
HIViewSetFrame (dummyView, &r);
|
||||
HIViewAddSubview (parentView, dummyView);
|
||||
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
|
||||
|
||||
EventHandlerRef ref;
|
||||
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
|
||||
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
|
||||
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
|
||||
|
||||
updateEditorCompBoundsVST (comp);
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary);
|
||||
#endif
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
[pluginWindow setExcludedFromWindowsMenu: YES];
|
||||
[pluginWindow setCanHide: YES];
|
||||
|
||||
[hostWindow addChildWindow: pluginWindow
|
||||
ordered: NSWindowAbove];
|
||||
[hostWindow orderFront: nil];
|
||||
[pluginWindow orderFront: nil];
|
||||
|
||||
attachWindowHidingHooks (comp, (WindowRef) parentWindowOrView, hostWindow);
|
||||
|
||||
return hostWindow;
|
||||
}
|
||||
#endif
|
||||
|
||||
ignoreUnused (isNSView);
|
||||
NSView* parentView = [(NSView*) parentWindowOrView retain];
|
||||
|
||||
#if JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (0, parentView);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
|
||||
#endif
|
||||
|
||||
// (this workaround is because Wavelab provides a zero-size parent view..)
|
||||
if ([parentView frame].size.height == 0)
|
||||
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
[[parentView window] setAcceptsMouseMovedEvents: YES];
|
||||
return parentView;
|
||||
}
|
||||
}
|
||||
|
||||
JUCE_API void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView);
|
||||
void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["boundsEventRef"].toString().getHexValue64();
|
||||
RemoveEventHandler (ref);
|
||||
|
||||
removeWindowHidingHooks (comp);
|
||||
|
||||
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
|
||||
|
||||
if (HIViewIsValid (dummyView))
|
||||
CFRelease (dummyView);
|
||||
|
||||
NSWindow* hostWindow = (NSWindow*) window;
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
[pluginView retain];
|
||||
[hostWindow removeChildWindow: pluginWindow];
|
||||
[pluginWindow close];
|
||||
comp->removeFromDesktop();
|
||||
[pluginView release];
|
||||
|
||||
if (shouldManuallyCloseHostWindow())
|
||||
[hostWindow close];
|
||||
else
|
||||
[hostWindow release];
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
static bool needToRunMessageLoop = ! getHostType().isReaper();
|
||||
|
||||
// The event loop needs to be run between closing the window and deleting the plugin,
|
||||
// presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
|
||||
// in Live when you delete the plugin with its window open.
|
||||
// (Doing it this way rather than using a single longer timout means that we can guarantee
|
||||
// how many messages will be dispatched, which seems to be vital in Reaper)
|
||||
if (needToRunMessageLoop)
|
||||
for (int i = 20; --i >= 0;)
|
||||
MessageManager::getInstance()->runDispatchLoopUntil (1);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ignoreUnused (isNSView);
|
||||
comp->removeFromDesktop();
|
||||
[(id) window release];
|
||||
}
|
||||
}
|
||||
|
||||
JUCE_API void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
|
||||
void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
if (HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
component->getProperties() ["dummyViewRef"].toString().getHexValue64())
|
||||
{
|
||||
HIRect frameRect;
|
||||
HIViewGetFrame (dummyView, &frameRect);
|
||||
frameRect.size.width = newWidth;
|
||||
frameRect.size.height = newHeight;
|
||||
HIViewSetFrame (dummyView, &frameRect);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ignoreUnused (isNSView);
|
||||
|
||||
if (NSView* hostView = (NSView*) window)
|
||||
{
|
||||
const int dx = newWidth - component->getWidth();
|
||||
const int dy = newHeight - component->getHeight();
|
||||
|
||||
NSRect r = [hostView frame];
|
||||
r.size.width += dx;
|
||||
r.size.height += dy;
|
||||
r.origin.y -= dy;
|
||||
[hostView setFrame: r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JUCE_API void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView);
|
||||
void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView)
|
||||
{
|
||||
ignoreUnused (window, comp, isNSView);
|
||||
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
comp->setVisible ([((NSWindow*) window) isVisible]);
|
||||
#endif
|
||||
}
|
||||
|
||||
JUCE_API bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView);
|
||||
bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView)
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
NSWindow* win = [(NSView*) comp->getWindowHandle() window];
|
||||
[[win parentWindow] makeKeyWindow];
|
||||
repostCurrentNSEvent();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
ignoreUnused (comp, isNSView);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // (juce namespace)
|
||||
|
||||
#endif
|
||||
#endif
|
2817
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
Normal file
2817
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
105
modules/juce_audio_plugin_client/juce_audio_plugin_client.h
Normal file
105
modules/juce_audio_plugin_client/juce_audio_plugin_client.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
The block below describes the properties of this module, and is read by
|
||||
the Projucer to automatically generate project code that uses it.
|
||||
For details about the syntax and how to create or use a module, see the
|
||||
JUCE Module Format.txt file.
|
||||
|
||||
|
||||
BEGIN_JUCE_MODULE_DECLARATION
|
||||
|
||||
ID: juce_audio_plugin_client
|
||||
vendor: juce
|
||||
version: 5.3.2
|
||||
name: JUCE audio plugin wrapper classes
|
||||
description: Classes for building VST, VST3, AudioUnit, AAX and RTAS plugins.
|
||||
website: http://www.juce.com/juce
|
||||
license: GPL/Commercial
|
||||
|
||||
dependencies: juce_gui_basics, juce_audio_basics, juce_audio_processors
|
||||
|
||||
END_JUCE_MODULE_DECLARATION
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <juce_gui_basics/juce_gui_basics.h>
|
||||
#include <juce_audio_basics/juce_audio_basics.h>
|
||||
#include <juce_audio_processors/juce_audio_processors.h>
|
||||
|
||||
/** Config: JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
|
||||
Enable this if you want to force JUCE to use a continuous parameter
|
||||
index to identify a parameter in a DAW (this was the default in old
|
||||
versions of JUCE). This is index is usually used by the DAW to save
|
||||
automation data and enabling this may mess up user's DAW projects.
|
||||
*/
|
||||
#ifndef JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
#define JUCE_FORCE_USE_LEGACY_PARAM_IDS 0
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
|
||||
Enable this if you want to force JUCE to use a legacy scheme for
|
||||
identifying plug-in parameters as either continuous or discrete.
|
||||
DAW projects with automation data written by an AudioUnit, VST3 or
|
||||
AAX plug-in built with JUCE version 5.1.1 or earlier may load
|
||||
incorrectly when opened by an AudioUnit, VST3 or AAX plug-in built
|
||||
with JUCE version 5.2.0 and later.
|
||||
*/
|
||||
#ifndef JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
#define JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE 0
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS
|
||||
|
||||
Enable this if you want JUCE to use parameter ids which are compatible
|
||||
with Studio One. Studio One ignores any parameter ids which are negative.
|
||||
Enabling this option will make JUCE generate only positive parameter ids.
|
||||
Note that if you have already released a plug-in prior to JUCE 4.3.0 then
|
||||
enabling this will change your parameter ids making your plug-in
|
||||
incompatible to old automation data.
|
||||
*/
|
||||
#ifndef JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS
|
||||
#define JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS 1
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
|
||||
|
||||
Enable this if you want your standalone plugin window to use kiosk mode.
|
||||
By default, kiosk mode is enabled on iOS and Android.
|
||||
*/
|
||||
|
||||
#ifndef JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE
|
||||
#define JUCE_STANDALONE_FILTER_WINDOW_USE_KIOSK_MODE (JUCE_IOS || JUCE_ANDROID)
|
||||
#endif
|
||||
|
||||
#include "utility/juce_PluginHostType.h"
|
||||
#include "VST/juce_VSTCallbackHandler.h"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "AAX/juce_AAX_Wrapper.cpp"
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define JUCE_INCLUDED_AAX_IN_MM 1
|
||||
#include "AAX/juce_AAX_Wrapper.cpp"
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define UseExtendedThingResource 1
|
||||
#include <AudioUnit/AudioUnit.r>
|
||||
|
||||
//==============================================================================
|
||||
/* The AppConfig.h file should be a file in your project, containing info to describe the
|
||||
plugin's name, type, etc. The introjucer will generate this file automatically for you.
|
||||
|
||||
You may need to adjust the include path of your project to make sure it can be
|
||||
found by this include statement. (Don't hack this file to change the include path)
|
||||
*/
|
||||
#include "AppConfig.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// component resources for Audio Unit
|
||||
#define RES_ID 1000
|
||||
#define COMP_TYPE JucePlugin_AUMainType
|
||||
#define COMP_SUBTYPE JucePlugin_AUSubType
|
||||
#define COMP_MANUF JucePlugin_AUManufacturerCode
|
||||
#define VERSION JucePlugin_VersionCode
|
||||
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name
|
||||
#define DESCRIPTION JucePlugin_Desc
|
||||
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "Entry"
|
||||
|
||||
#include "AUResources.r"
|
||||
|
||||
//==============================================================================
|
||||
// component resources for Audio Unit Carbon View
|
||||
|
||||
#ifndef BUILD_AU_CARBON_UI
|
||||
#define BUILD_AU_CARBON_UI 1
|
||||
#endif
|
||||
|
||||
#if BUILD_AU_CARBON_UI
|
||||
#define RES_ID 2000
|
||||
#define COMP_TYPE kAudioUnitCarbonViewComponentType
|
||||
#define COMP_SUBTYPE JucePlugin_AUSubType
|
||||
#define COMP_MANUF JucePlugin_AUManufacturerCode
|
||||
#define VERSION JucePlugin_VersionCode
|
||||
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name " View"
|
||||
#define DESCRIPTION NAME
|
||||
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "ViewEntry"
|
||||
|
||||
#include "AUResources.r"
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "AU/juce_AU_Wrapper.mm"
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wparentheses"
|
||||
#pragma clang diagnostic ignored "-Wextra-tokens"
|
||||
#pragma clang diagnostic ignored "-Wcomment"
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
#pragma clang diagnostic ignored "-Wunused"
|
||||
#pragma clang diagnostic ignored "-Wextra-semi"
|
||||
#pragma clang diagnostic ignored "-Wformat-pedantic"
|
||||
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
#endif
|
||||
|
||||
// From MacOS 10.13 and iOS 11 Apple has (sensibly!) stopped defining a whole
|
||||
// set of functions with rather generic names. However, we still need a couple
|
||||
// of them to compile the files below.
|
||||
#ifndef verify
|
||||
#define verify(assertion) __Verify(assertion)
|
||||
#endif
|
||||
#ifndef verify_noerr
|
||||
#define verify_noerr(errorCode) __Verify_noErr(errorCode)
|
||||
#endif
|
||||
|
||||
#include "AU/CoreAudioUtilityClasses/AUBase.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUBuffer.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUCarbonViewBase.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUCarbonViewControl.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUCarbonViewDispatch.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUDispatch.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUInputElement.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUMIDIBase.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUOutputBase.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUOutputElement.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/AUScopeElement.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/CAAUParameter.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/CAMutex.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/CAVectorUnit.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/CarbonEventHandler.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/ComponentBase.cpp"
|
||||
#include "AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp"
|
||||
|
||||
#undef verify
|
||||
#undef verify_noerr
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "AU/juce_AUv3_Wrapper.mm"
|
@ -0,0 +1,7 @@
|
||||
|
||||
/*
|
||||
This dummy file is added to the resources section of the project to
|
||||
force Xcode to create some resources for the dpm. If there aren't any
|
||||
resources, PT will refuse to load the plugin..
|
||||
*/
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "RTAS/juce_RTAS_Wrapper.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "RTAS/juce_RTAS_DigiCode1.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "RTAS/juce_RTAS_DigiCode2.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "RTAS/juce_RTAS_DigiCode3.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "RTAS/juce_RTAS_WinUtilities.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "RTAS/juce_RTAS_MacUtilities.mm"
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if ! JUCE_MODULE_AVAILABLE_juce_audio_utils
|
||||
#error To compile AudioUnitv3 and/or Standalone plug-ins, you need to add the juce_audio_utils and juce_audio_devices modules!
|
||||
#endif
|
||||
|
||||
#include "Standalone/juce_StandaloneFilterApp.cpp"
|
||||
|
||||
#if JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP
|
||||
extern juce::JUCEApplicationBase* juce_CreateApplication();
|
||||
|
||||
#if JUCE_IOS
|
||||
extern void* juce_GetIOSCustomDelegateClass();
|
||||
#endif
|
||||
|
||||
#else
|
||||
JUCE_CREATE_APPLICATION_DEFINE(juce::StandaloneFilterApp)
|
||||
#endif
|
||||
|
||||
JUCE_MAIN_FUNCTION_DEFINITION
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "VST/juce_VST_Wrapper.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "VST3/juce_VST3_Wrapper.cpp"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "VST/juce_VST_Wrapper.mm"
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "utility/juce_PluginUtilities.cpp"
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_SUPPORT_CARBON && JUCE_MAC_WINDOW_VISIBITY_BODGE
|
||||
|
||||
/* When you wrap a WindowRef as an NSWindow, it seems to bugger up the HideWindow
|
||||
function, so when the host tries (and fails) to hide the window, this stuff catches
|
||||
the event and forces it to update.
|
||||
*/
|
||||
static pascal OSStatus windowVisibilityBodge (EventHandlerCallRef, EventRef e, void* user)
|
||||
{
|
||||
NSWindow* hostWindow = (NSWindow*) user;
|
||||
|
||||
switch (GetEventKind (e))
|
||||
{
|
||||
case kEventWindowInit: [hostWindow display]; break;
|
||||
case kEventWindowShown: [hostWindow orderFront: nil]; break;
|
||||
case kEventWindowHidden: [hostWindow orderOut: nil]; break;
|
||||
}
|
||||
|
||||
return eventNotHandledErr;
|
||||
}
|
||||
|
||||
inline void attachWindowHidingHooks (Component* comp, void* hostWindowRef, NSWindow* nsWindow)
|
||||
{
|
||||
const EventTypeSpec eventsToCatch[] =
|
||||
{
|
||||
{ kEventClassWindow, kEventWindowInit },
|
||||
{ kEventClassWindow, kEventWindowShown },
|
||||
{ kEventClassWindow, kEventWindowHidden }
|
||||
};
|
||||
|
||||
EventHandlerRef ref;
|
||||
InstallWindowEventHandler ((WindowRef) hostWindowRef,
|
||||
NewEventHandlerUPP (windowVisibilityBodge),
|
||||
GetEventTypeCount (eventsToCatch), eventsToCatch,
|
||||
(void*) nsWindow, &ref);
|
||||
|
||||
comp->getProperties().set ("carbonEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
|
||||
}
|
||||
|
||||
inline void removeWindowHidingHooks (Component* comp)
|
||||
{
|
||||
if (comp != nullptr)
|
||||
RemoveEventHandler ((EventHandlerRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["carbonEventRef"].toString().getHexValue64());
|
||||
}
|
||||
|
||||
#elif JUCE_MAC
|
||||
inline void attachWindowHidingHooks (void*, void*, void*) {}
|
||||
inline void removeWindowHidingHooks (void*) {}
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// The following checks should cause a compile error if you've forgotten to
|
||||
// define all your plugin settings properly..
|
||||
|
||||
#if ! (JucePlugin_Build_VST || JucePlugin_Build_VST3 \
|
||||
|| JucePlugin_Build_AU || JucePlugin_Build_AUv3 \
|
||||
||JucePlugin_Build_RTAS || JucePlugin_Build_AAX \
|
||||
|| JucePlugin_Build_Standalone || JucePlugin_Build_LV2)
|
||||
#error "You need to enable at least one plugin format!"
|
||||
#endif
|
||||
|
||||
#ifdef JUCE_CHECKSETTINGMACROS_H
|
||||
#error "This header should never be included twice! Otherwise something is wrong."
|
||||
#endif
|
||||
#define JUCE_CHECKSETTINGMACROS_H
|
||||
|
||||
#ifndef JucePlugin_IsSynth
|
||||
#error "You need to define the JucePlugin_IsSynth value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_ManufacturerCode
|
||||
#error "You need to define the JucePlugin_ManufacturerCode value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_PluginCode
|
||||
#error "You need to define the JucePlugin_PluginCode value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_ProducesMidiOutput
|
||||
#error "You need to define the JucePlugin_ProducesMidiOutput value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_WantsMidiInput
|
||||
#error "You need to define the JucePlugin_WantsMidiInput value!"
|
||||
#endif
|
||||
|
||||
#ifdef JucePlugin_Latency
|
||||
#error "JucePlugin_Latency is now deprecated - instead, call the AudioProcessor::setLatencySamples() method if your plugin has a non-zero delay"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_EditorRequiresKeyboardFocus
|
||||
#error "You need to define the JucePlugin_EditorRequiresKeyboardFocus value!"
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if _WIN64 || (__LP64__ && (defined (__APPLE_CPP__) || defined (__APPLE_CC__)))
|
||||
#undef JucePlugin_Build_RTAS
|
||||
#define JucePlugin_Build_RTAS 0
|
||||
#endif
|
||||
|
||||
#if ! (defined (_MSC_VER) || defined (__APPLE_CPP__) || defined (__APPLE_CC__))
|
||||
#undef JucePlugin_Build_VST3
|
||||
#define JucePlugin_Build_VST3 0
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JucePlugin_Build_LV2 && ! defined (JucePlugin_LV2URI)
|
||||
#error "You need to define the JucePlugin_LV2URI value!"
|
||||
#endif
|
||||
|
||||
#if JucePlugin_Build_AAX && ! defined (JucePlugin_AAXIdentifier)
|
||||
#error "You need to define the JucePlugin_AAXIdentifier value!"
|
||||
#endif
|
||||
|
||||
#if defined (__ppc__)
|
||||
#undef JucePlugin_Build_AAX
|
||||
#define JucePlugin_Build_AAX 0
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JucePlugin_Build_VST
|
||||
|
||||
#if JucePlugin_VersionCode < 0x010000 // Major < 0
|
||||
|
||||
#if (JucePlugin_VersionCode & 0x00FF00) > (9 * 0x100) // check if Minor number exceeeds 9
|
||||
#warning When version has "major" = 0, VST2 has trouble displaying "minor" exceeding 9
|
||||
#endif
|
||||
|
||||
#if (JucePlugin_VersionCode & 0xFF) > 9 // check if Bugfix number exceeeds 9
|
||||
#warning When version has "major" = 0, VST2 has trouble displaying "bugfix" exceeding 9
|
||||
#endif
|
||||
|
||||
#elif JucePlugin_VersionCode >= 0x650000 // Major >= 101
|
||||
|
||||
#if (JucePlugin_VersionCode & 0x00FF00) > (99 * 0x100) // check if Minor number exceeeds 99
|
||||
#warning When version has "major" > 100, VST2 has trouble displaying "minor" exceeding 99
|
||||
#endif
|
||||
|
||||
#if (JucePlugin_VersionCode & 0xFF) > 99 // check if Bugfix number exceeeds 99
|
||||
#warning When version has "major" > 100, VST2 has trouble displaying "bugfix" exceeding 99
|
||||
#endif
|
||||
|
||||
#endif // JucePlugin_VersionCode
|
||||
|
||||
#endif // JucePlugin_Build_VST
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN
|
||||
|
||||
#if JUCE_MAC
|
||||
|
||||
//==============================================================================
|
||||
// Helper class to workaround windows not getting mouse-moves...
|
||||
class FakeMouseMoveGenerator : private Timer
|
||||
{
|
||||
public:
|
||||
FakeMouseMoveGenerator()
|
||||
{
|
||||
startTimer (1000 / 30);
|
||||
}
|
||||
|
||||
static bool componentContainsAudioProcessorEditor (Component* comp) noexcept
|
||||
{
|
||||
if (dynamic_cast<AudioProcessorEditor*> (comp) != nullptr)
|
||||
return true;
|
||||
|
||||
for (auto* child : comp->getChildren())
|
||||
if (componentContainsAudioProcessorEditor (child))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
// Workaround for windows not getting mouse-moves...
|
||||
auto screenPos = Desktop::getInstance().getMainMouseSource().getScreenPosition();
|
||||
|
||||
if (screenPos != lastScreenPos)
|
||||
{
|
||||
lastScreenPos = screenPos;
|
||||
auto mods = ModifierKeys::currentModifiers;
|
||||
|
||||
if (! mods.isAnyMouseButtonDown())
|
||||
{
|
||||
if (auto* comp = Desktop::getInstance().findComponentAt (screenPos.roundToInt()))
|
||||
{
|
||||
if (componentContainsAudioProcessorEditor (comp->getTopLevelComponent()))
|
||||
{
|
||||
safeOldComponent = comp;
|
||||
|
||||
if (auto* peer = comp->getPeer())
|
||||
{
|
||||
if (! peer->isFocused())
|
||||
{
|
||||
peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse, peer->globalToLocal (screenPos), mods,
|
||||
MouseInputSource::invalidPressure, MouseInputSource::invalidOrientation, Time::currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (safeOldComponent != nullptr)
|
||||
{
|
||||
if (auto* peer = safeOldComponent->getPeer())
|
||||
{
|
||||
peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse, { -1.0f, -1.0f }, mods,
|
||||
MouseInputSource::invalidPressure, MouseInputSource::invalidOrientation, Time::currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
safeOldComponent = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Point<float> lastScreenPos;
|
||||
WeakReference<Component> safeOldComponent;
|
||||
};
|
||||
|
||||
#else
|
||||
struct FakeMouseMoveGenerator {};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../juce_audio_plugin_client.h"
|
||||
|
||||
namespace juce
|
||||
{
|
||||
#define Component juce::Component
|
||||
|
||||
#if JUCE_MAC
|
||||
#define Point juce::Point
|
||||
void repostCurrentNSEvent();
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
inline const PluginHostType& getHostType()
|
||||
{
|
||||
static PluginHostType hostType;
|
||||
return hostType;
|
||||
}
|
||||
}
|
||||
|
||||
extern juce::AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (juce::AudioProcessor::WrapperType);
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user