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