diff --git a/BREAKING-CHANGES.txt b/BREAKING-CHANGES.txt index fe2fa0e518..fcb5395e7a 100644 --- a/BREAKING-CHANGES.txt +++ b/BREAKING-CHANGES.txt @@ -4,6 +4,28 @@ JUCE breaking changes develop ======= +Change +------ +Resource forks are no longer generated for Audio Unit plug-ins. + +Possible Issues +--------------- +New builds of JUCE Audio Units may no longer load in old hosts that use the +Component Manager to discover plug-ins. + +Workaround +---------- +No workaround is available. + +Rationale +--------- +The Component Manager is deprecated in macOS 10.8 and later, so the majority of +hosts have now implemented support for the new plist-based discovery mechanism. +The new AudioUnitSDK (https://github.com/apple/AudioUnitSDK) provided by Apple +to replace the old Core Audio Utility Classes no longer includes the files +required to generate resource forks. + + Change ------ Previously, the AudioProcessorGraph would call processBlockBypassed on any diff --git a/README.md b/README.md index 5024834cd2..09d2af21dc 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ The JUCE framework contains the following dependencies: - [Oboe](modules/juce_audio_devices/native/oboe/) ([Apache 2.0](modules/juce_audio_devices/native/oboe/LICENSE)) - [FLAC](modules/juce_audio_formats/codecs/flac/) ([BSD](modules/juce_audio_formats/codecs/flac/Flac%20Licence.txt)) - [Ogg Vorbis](modules/juce_audio_formats/codecs/oggvorbis/) ([BSD](modules/juce_audio_formats/codecs/oggvorbis/Ogg%20Vorbis%20Licence.txt)) -- [CoreAudioUtilityClasses](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/) ([Apple](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp)) +- [AudioUnitSDK](modules/juce_audio_plugin_client/AU/AudioUnitSDK/) ([Apache 2.0](modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt)) - [AUResources.r](modules/juce_audio_plugin_client/AUResources.r) ([Apple](modules/juce_audio_plugin_client/AUResources.r)) - [LV2](modules/juce_audio_processors/format_types/LV2_SDK/) ([ISC](modules/juce_audio_processors/format_types/LV2_SDK/lv2/COPYING)) - [pslextensions](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h) ([Public domain](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h)) diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 15ec9ea487..bd662d2577 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -849,7 +849,7 @@ EXCLUDE = build/juce_graphics/image_formats \ build/juce_audio_formats/codecs/flac \ build/juce_audio_formats/codecs/oggvorbis \ build/juce_audio_devices/native \ - build/juce_audio_plugin_client/AU/CoreAudioUtilityClasses \ + build/juce_audio_plugin_client/AU/AudioUnitSDK \ build/juce_browser_plugin_client/juce_browser_plugin.h \ build/juce_core/native \ build/juce_events/native \ diff --git a/extras/Build/CMake/JUCEModuleSupport.cmake b/extras/Build/CMake/JUCEModuleSupport.cmake index 555a72c476..1109a29033 100644 --- a/extras/Build/CMake/JUCEModuleSupport.cmake +++ b/extras/Build/CMake/JUCEModuleSupport.cmake @@ -327,6 +327,8 @@ function(_juce_add_plugin_wrapper_target format path out_path) _juce_link_frameworks("${target_name}" INTERFACE AudioUnit) endif() elseif(format STREQUAL "AU") + target_compile_features("${target_name}" INTERFACE cxx_std_17) + target_include_directories("${target_name}" INTERFACE "${out_path}/juce_audio_plugin_client/AU") _juce_link_frameworks("${target_name}" INTERFACE AudioUnit CoreAudioKit) endif() endfunction() diff --git a/extras/Build/CMake/JUCEUtils.cmake b/extras/Build/CMake/JUCEUtils.cmake index 29edd9b778..378b7e78b8 100644 --- a/extras/Build/CMake/JUCEUtils.cmake +++ b/extras/Build/CMake/JUCEUtils.cmake @@ -87,12 +87,6 @@ set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD FALSE) if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD")) _juce_create_pkgconfig_target(JUCE_CURL_LINUX_DEPS libcurl) _juce_create_pkgconfig_target(JUCE_BROWSER_LINUX_DEPS webkit2gtk-4.0 gtk+-x11-3.0) -elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - find_program(JUCE_XCRUN xcrun) - - if(NOT JUCE_XCRUN) - message(WARNING "failed to find xcrun; older resource-based AU plug-ins may not work correctly") - endif() endif() # We set up default/fallback copy dirs here. If you need different copy dirs, use @@ -153,67 +147,6 @@ endfunction() # ================================================================================================== -function(_juce_add_au_resource_fork shared_code_target au_target) - if(NOT JUCE_XCRUN) - return() - endif() - - get_target_property(product_name ${shared_code_target} JUCE_PRODUCT_NAME) - get_target_property(module_sources juce::juce_audio_plugin_client_AU INTERFACE_SOURCES) - - list(FILTER module_sources INCLUDE REGEX "/juce_audio_plugin_client_AU.r$") - - if(NOT module_sources) - message(FATAL_ERROR "Failed to find AU resource file input") - endif() - - list(GET module_sources 0 au_rez_sources) - - get_target_property(juce_library_code ${shared_code_target} JUCE_GENERATED_SOURCES_DIRECTORY) - # We don't want our AU AppConfig.h to end up on peoples' include paths if we can help it - set(secret_au_resource_dir "${juce_library_code}/${au_target}/secret") - set(secret_au_plugindefines "${secret_au_resource_dir}/JucePluginDefines.h") - - set(au_rez_output "${secret_au_resource_dir}/${product_name}.rsrc") - - target_sources(${au_target} PRIVATE "${au_rez_output}") - set_source_files_properties("${au_rez_output}" PROPERTIES - GENERATED TRUE - MACOSX_PACKAGE_LOCATION Resources) - - set(defs_file $>) - - # Passing all our compile definitions using generator expressions is really painful - # because some of the definitions have pipes and quotes and dollars and goodness-knows - # what else that the shell would very much like to claim for itself, thank you very much. - # CMake definitely knows how to escape all these things, because it's perfectly happy to pass - # them to compiler invocations, but I have no idea how to get it to escape them - # in a custom command. - # In the end, it's simplest to generate a special single-purpose appconfig just for the - # resource compiler. - add_custom_command(OUTPUT "${secret_au_plugindefines}" - COMMAND juce::juceaide auplugindefines "${defs_file}" "${secret_au_plugindefines}" - DEPENDS "${defs_file}" - VERBATIM) - - add_custom_command(OUTPUT "${au_rez_output}" - COMMAND "${JUCE_XCRUN}" Rez - -d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64" -d "arm64_$arm64" - -I "${secret_au_resource_dir}" - -I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers" - -I "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/AudioUnit.framework/Headers" - -isysroot "${CMAKE_OSX_SYSROOT}" - "${au_rez_sources}" - -useDF - -o "${au_rez_output}" - DEPENDS "${secret_au_plugindefines}" - VERBATIM) - - set(au_resource_directory "$/Contents/Resources") -endfunction() - -# ================================================================================================== - # Ideally, we'd check the preprocessor defs on the target to see whether # JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off, # and then link libraries as appropriate. @@ -1285,10 +1218,6 @@ function(_juce_configure_plugin_targets target) _juce_configure_app_bundle(${target} ${target}_Standalone) endif() - if(TARGET ${target}_AU) - _juce_add_au_resource_fork(${target} ${target}_AU) - endif() - if(TARGET ${target}_AAX) target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk) endif() diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h index 9e9e60bd79..b8a25bb14f 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h @@ -1048,7 +1048,7 @@ public: struct XcodeTarget : build_tools::ProjectType::Target { //============================================================================== - XcodeTarget (build_tools::ProjectType::Target::Type targetType, const XcodeProjectExporter& exporter) + XcodeTarget (Type targetType, const XcodeProjectExporter& exporter) : Target (targetType), owner (exporter) { @@ -1699,10 +1699,17 @@ public: s.set ("CODE_SIGN_ENTITLEMENTS", getEntitlementsFilename().quoted()); { - auto cppStandard = owner.project.getCppStandardString(); + const auto cppStandard = [&]() -> String + { + if (owner.project.getCppStandardString() == "latest") + return owner.project.getLatestNumberedCppStandardString(); + + // The AudioUnitSDK requires C++17 + if (type == AudioUnitPlugIn) + return "17"; - if (cppStandard == "latest") - cppStandard = owner.project.getLatestNumberedCppStandardString(); + return owner.project.getCppStandardString(); + }(); s.set ("CLANG_CXX_LANGUAGE_STANDARD", (String (owner.shouldUseGNUExtensions() ? "gnu++" : "c++") + cppStandard).quoted()); @@ -1970,10 +1977,15 @@ public: if (owner.project.getEnabledModules().isModuleEnabled ("juce_audio_plugin_client")) { - // Needed to compile .r files - paths.add (owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client") - .rebased (owner.projectFolder, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder) - .toUnixStyle()); + const auto pluginClientModule = owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client"); + for (const auto& path : { pluginClientModule, // For AU resource fork + pluginClientModule.getChildFile ("AU") }) // For AudioUnitSDK includes + { + paths.add (path.rebased (owner.projectFolder, + owner.getTargetFolder(), + build_tools::RelativePath::buildTargetFolder) + .toUnixStyle()); + } } sanitiseAndEscapeSearchPaths (config, paths); diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.cpp new file mode 100644 index 0000000000..9b58f8e7da --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.cpp @@ -0,0 +1,2061 @@ +/*! + @file AudioUnitSDK/AUBase.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace ausdk { + +#if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64) + +class DenormalDisabler { +public: + DenormalDisabler() : mSavedMXCSR(GetCSR()) { SetCSR(mSavedMXCSR | 0x8040); } + + DenormalDisabler(const DenormalDisabler&) = delete; + DenormalDisabler(DenormalDisabler&&) = delete; + DenormalDisabler& operator=(const DenormalDisabler&) = delete; + DenormalDisabler& operator=(DenormalDisabler&&) = delete; + + ~DenormalDisabler() { SetCSR(mSavedMXCSR); } + +private: +#if 0 // not sure if this is right: // #if __has_include() + static unsigned GetCSR() { return _mm_getcsr(); } + static void SetCSR(unsigned x) { _mm_setcsr(x); } +#else + // our compiler does ALL floating point with SSE + static unsigned GetCSR() + { + unsigned result{}; + asm volatile("stmxcsr %0" : "=m"(*&result)); // NOLINT asm + return result; + } + static void SetCSR(unsigned a) + { + unsigned temp = a; + asm volatile("ldmxcsr %0" : : "m"(*&temp)); // NOLINT asm + } +#endif + + unsigned const mSavedMXCSR; +}; + +#else +// while denormals can be flushed to zero on ARM processors, there is no performance benefit +class DenormalDisabler { +public: + DenormalDisabler() = default; +}; +#endif + +static std::once_flag sAUBaseCFStringsInitialized{}; // NOLINT non-const global +// this is used for the presets +static CFStringRef kUntitledString = nullptr; // NOLINT non-const global +// these are the current keys for the class info document +static CFStringRef kVersionString = nullptr; // NOLINT non-const global +static CFStringRef kTypeString = nullptr; // NOLINT non-const global +static CFStringRef kSubtypeString = nullptr; // NOLINT non-const global +static CFStringRef kManufacturerString = nullptr; // NOLINT non-const global +static CFStringRef kDataString = nullptr; // NOLINT non-const global +static CFStringRef kNameString = nullptr; // NOLINT non-const global +static CFStringRef kRenderQualityString = nullptr; // NOLINT non-const global +static CFStringRef kElementNameString = nullptr; // NOLINT non-const global +static CFStringRef kPartString = nullptr; // NOLINT non-const global + +static constexpr auto kNoLastRenderedSampleTime = std::numeric_limits::lowest(); + +//_____________________________________________________________________________ +// +AUBase::AUBase(AudioComponentInstance inInstance, UInt32 numInputElements, UInt32 numOutputElements, + UInt32 numGroupElements) + : ComponentBase(inInstance), mInitNumInputEls(numInputElements), + mInitNumOutputEls(numOutputElements), mInitNumGroupEls(numGroupElements), + mLogString(CreateLoggingString()) +{ + ResetRenderTime(); + + std::call_once(sAUBaseCFStringsInitialized, []() { + kUntitledString = CFSTR("Untitled"); // NOLINT + kVersionString = CFSTR(kAUPresetVersionKey); // NOLINT + kTypeString = CFSTR(kAUPresetTypeKey); // NOLINT + kSubtypeString = CFSTR(kAUPresetSubtypeKey); // NOLINT + kManufacturerString = CFSTR(kAUPresetManufacturerKey); // NOLINT + kDataString = CFSTR(kAUPresetDataKey); // NOLINT + kNameString = CFSTR(kAUPresetNameKey); // NOLINT + kRenderQualityString = CFSTR(kAUPresetRenderQualityKey); // NOLINT + kElementNameString = CFSTR(kAUPresetElementNameKey); // NOLINT + kPartString = CFSTR(kAUPresetPartKey); // NOLINT + }); + + GlobalScope().Initialize(this, kAudioUnitScope_Global, 1); + + mCurrentPreset.presetNumber = -1; + CFRetain(mCurrentPreset.presetName = kUntitledString); +} + +//_____________________________________________________________________________ +// +AUBase::~AUBase() +{ + if (mCurrentPreset.presetName != nullptr) { + CFRelease(mCurrentPreset.presetName); + } +} + +//_____________________________________________________________________________ +// +void AUBase::PostConstructorInternal() +{ + // invoked after construction because they are virtual methods and/or call virtual methods + if (mMaxFramesPerSlice == 0) { + SetMaxFramesPerSlice(kAUDefaultMaxFramesPerSlice); + } + CreateElements(); +} + +//_____________________________________________________________________________ +// +void AUBase::PreDestructorInternal() +{ + // this is called from the ComponentBase dispatcher, which doesn't know anything about our + // (optional) lock + const AUEntryGuard guard(mAUMutex); + DoCleanup(); +} + +//_____________________________________________________________________________ +// +void AUBase::CreateElements() +{ + if (!mElementsCreated) { + Inputs().Initialize(this, kAudioUnitScope_Input, mInitNumInputEls); + Outputs().Initialize(this, kAudioUnitScope_Output, mInitNumOutputEls); + Groups().Initialize(this, kAudioUnitScope_Group, mInitNumGroupEls); + CreateExtendedElements(); + + mElementsCreated = true; + } +} + +//_____________________________________________________________________________ +// +void AUBase::SetMaxFramesPerSlice(UInt32 nFrames) +{ + if (nFrames == mMaxFramesPerSlice) { + return; + } + + mMaxFramesPerSlice = nFrames; + if (mBuffersAllocated) { + ReallocateBuffers(); + } + PropertyChanged(kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0); +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::CanSetMaxFrames() const +{ + return IsInitialized() ? kAudioUnitErr_Initialized : OSStatus(noErr); +} + +//_____________________________________________________________________________ +// +void AUBase::ReallocateBuffers() +{ + CreateElements(); + + const UInt32 nOutputs = Outputs().GetNumberOfElements(); + for (UInt32 i = 0; i < nOutputs; ++i) { + Output(i).AllocateBuffer(); // does no work if already allocated + } + const UInt32 nInputs = Inputs().GetNumberOfElements(); + for (UInt32 i = 0; i < nInputs; ++i) { + Input(i).AllocateBuffer(); // does no work if already allocated + } + mBuffersAllocated = true; +} + +//_____________________________________________________________________________ +// +void AUBase::DeallocateIOBuffers() +{ + if (!mBuffersAllocated) { + return; + } + + const UInt32 nOutputs = Outputs().GetNumberOfElements(); + for (UInt32 i = 0; i < nOutputs; ++i) { + Output(i).DeallocateBuffer(); + } + const UInt32 nInputs = Inputs().GetNumberOfElements(); + for (UInt32 i = 0; i < nInputs; ++i) { + Input(i).DeallocateBuffer(); + } + mBuffersAllocated = false; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::DoInitialize() +{ + OSStatus result = noErr; + + if (!mInitialized) { + result = Initialize(); + if (result == noErr) { + if (CanScheduleParameters()) { + mParamEventList.reserve(24); // NOLINT magic # + } + mHasBegunInitializing = true; + ReallocateBuffers(); // calls CreateElements() + mInitialized = true; // signal that it's okay to render + std::atomic_thread_fence(std::memory_order_seq_cst); + } + } + + return result; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::Initialize() { return noErr; } + +//_____________________________________________________________________________ +// +void AUBase::DoCleanup() +{ + if (mInitialized) { + Cleanup(); + } + + DeallocateIOBuffers(); + ResetRenderTime(); + + mInitialized = false; + mHasBegunInitializing = false; +} + +//_____________________________________________________________________________ +// +void AUBase::Cleanup() {} + +//_____________________________________________________________________________ +// +OSStatus AUBase::Reset(AudioUnitScope /*inScope*/, AudioUnitElement /*inElement*/) +{ + ResetRenderTime(); + return noErr; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) +{ + OSStatus result = noErr; + bool validateElement = true; + + switch (inID) { + case kAudioUnitProperty_MakeConnection: + AUSDK_Require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, + kAudioUnitErr_InvalidScope); + outDataSize = sizeof(AudioUnitConnection); + outWritable = true; + break; + + case kAudioUnitProperty_SetRenderCallback: + AUSDK_Require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, + kAudioUnitErr_InvalidScope); + outDataSize = sizeof(AURenderCallbackStruct); + outWritable = true; + break; + + case kAudioUnitProperty_StreamFormat: + outDataSize = sizeof(AudioStreamBasicDescription); + outWritable = IsStreamFormatWritable(inScope, inElement); + break; + + case kAudioUnitProperty_SampleRate: + outDataSize = sizeof(Float64); + outWritable = IsStreamFormatWritable(inScope, inElement); + break; + + case kAudioUnitProperty_ClassInfo: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(CFPropertyListRef); + outWritable = true; + break; + + case kAudioUnitProperty_FactoryPresets: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require_noerr(GetPresets(nullptr)); + outDataSize = sizeof(CFArrayRef); + outWritable = false; + break; + + case kAudioUnitProperty_PresentPreset: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(AUPreset); + outWritable = true; + break; + + case kAudioUnitProperty_ElementName: + outDataSize = sizeof(CFStringRef); + outWritable = true; + break; + + case kAudioUnitProperty_ParameterList: { + UInt32 nparams = 0; + AUSDK_Require_noerr(GetParameterList(inScope, nullptr, nparams)); + outDataSize = sizeof(AudioUnitParameterID) * nparams; + outWritable = false; + validateElement = false; + break; + } + + case kAudioUnitProperty_ParameterInfo: + outDataSize = sizeof(AudioUnitParameterInfo); + outWritable = false; + validateElement = false; + break; + + case kAudioUnitProperty_ParameterHistoryInfo: + outDataSize = sizeof(AudioUnitParameterHistoryInfo); + outWritable = false; + validateElement = false; + break; + + case kAudioUnitProperty_ElementCount: + outDataSize = sizeof(UInt32); + outWritable = BusCountWritable(inScope); + validateElement = false; + break; + + case kAudioUnitProperty_Latency: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(Float64); + outWritable = false; + break; + + case kAudioUnitProperty_TailTime: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(SupportsTail(), kAudioUnitErr_InvalidProperty); + outDataSize = sizeof(Float64); + outWritable = false; + break; + + case kAudioUnitProperty_MaximumFramesPerSlice: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(UInt32); + outWritable = true; + break; + + case kAudioUnitProperty_LastRenderError: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(OSStatus); + outWritable = false; + break; + + case kAudioUnitProperty_SupportedNumChannels: { + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + const UInt32 num = SupportedNumChannels(nullptr); + AUSDK_Require(num != 0u, kAudioUnitErr_InvalidProperty); + outDataSize = sizeof(AUChannelInfo) * num; + outWritable = false; + break; + } + + case kAudioUnitProperty_SupportedChannelLayoutTags: { + const auto tags = GetChannelLayoutTags(inScope, inElement); + AUSDK_Require(!tags.empty(), kAudioUnitErr_InvalidProperty); + outDataSize = static_cast(tags.size() * sizeof(AudioChannelLayoutTag)); + outWritable = false; + validateElement = false; // already done it + break; + } + + case kAudioUnitProperty_AudioChannelLayout: { + outWritable = false; + outDataSize = GetAudioChannelLayout(inScope, inElement, nullptr, outWritable); + if (outDataSize != 0u) { + result = noErr; + } else { + const auto tags = GetChannelLayoutTags(inScope, inElement); + return tags.empty() ? kAudioUnitErr_InvalidProperty + : kAudioUnitErr_InvalidPropertyValue; + } + validateElement = false; // already done it + break; + } + + case kAudioUnitProperty_ShouldAllocateBuffer: + AUSDK_Require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), + kAudioUnitErr_InvalidScope); + outWritable = true; + outDataSize = sizeof(UInt32); + break; + + case kAudioUnitProperty_ParameterValueStrings: + AUSDK_Require_noerr(GetParameterValueStrings(inScope, inElement, nullptr)); + outDataSize = sizeof(CFArrayRef); + outWritable = false; + validateElement = false; + break; + + case kAudioUnitProperty_HostCallbacks: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(mHostCallbackInfo); + outWritable = true; + break; + + case kAudioUnitProperty_ContextName: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(CFStringRef); + outWritable = true; + break; + +#if !TARGET_OS_IPHONE + case kAudioUnitProperty_IconLocation: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(HasIcon(), kAudioUnitErr_InvalidProperty); + outWritable = false; + outDataSize = sizeof(CFURLRef); + break; +#endif + + case kAudioUnitProperty_ParameterClumpName: + outDataSize = sizeof(AudioUnitParameterNameInfo); + outWritable = false; + break; + + case 61: // kAudioUnitProperty_LastRenderSampleTime + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(Float64); + outWritable = false; + break; + + case kAudioUnitProperty_NickName: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + outDataSize = sizeof(CFStringRef); + outWritable = true; + break; + + default: + result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); + validateElement = false; + break; + } + + if ((result == noErr) && validateElement) { + AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement); + } + + return result; +} + +//_____________________________________________________________________________ +// +// NOLINTNEXTLINE(misc-no-recursion) with SaveState +OSStatus AUBase::DispatchGetProperty( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData) +{ + // NOTE: We're currently only called from AUBase::ComponentEntryDispatch, which + // calls DispatchGetPropertyInfo first, which performs validation of the scope/element, + // and ensures that the outData buffer is non-null and large enough. + OSStatus result = noErr; + + switch (inID) { + case kAudioUnitProperty_StreamFormat: + *static_cast(outData) = GetStreamFormat(inScope, inElement); + break; + + case kAudioUnitProperty_SampleRate: + *static_cast(outData) = GetStreamFormat(inScope, inElement).mSampleRate; + break; + + case kAudioUnitProperty_ParameterList: { + UInt32 nparams = 0; + result = GetParameterList(inScope, static_cast(outData), nparams); + break; + } + + case kAudioUnitProperty_ParameterInfo: + *static_cast(outData) = {}; + result = + GetParameterInfo(inScope, inElement, *static_cast(outData)); + break; + + case kAudioUnitProperty_ParameterHistoryInfo: { + auto* const info = static_cast(outData); + result = GetParameterHistoryInfo( + inScope, inElement, info->updatesPerSecond, info->historyDurationInSeconds); + break; + } + + case kAudioUnitProperty_ClassInfo: { + *static_cast(outData) = nullptr; + result = SaveState(static_cast(outData)); + break; + } + + case kAudioUnitProperty_FactoryPresets: { + *static_cast(outData) = nullptr; + result = GetPresets(static_cast(outData)); + break; + } + + case kAudioUnitProperty_PresentPreset: { + *static_cast(outData) = mCurrentPreset; + + // retain current string (as client owns a reference to it and will release it) + if ((inID == kAudioUnitProperty_PresentPreset) && (mCurrentPreset.presetName != nullptr)) { + CFRetain(mCurrentPreset.presetName); + } + + result = noErr; + break; + } + + case kAudioUnitProperty_ElementName: { + const AUElement* const element = GetElement(inScope, inElement); + const CFStringRef name = *element->GetName(); + AUSDK_Require(name != nullptr, kAudioUnitErr_PropertyNotInUse); + CFRetain(name); // must return a +1 reference + *static_cast(outData) = name; + break; + } + + case kAudioUnitProperty_ElementCount: + *static_cast(outData) = GetScope(inScope).GetNumberOfElements(); + break; + + case kAudioUnitProperty_Latency: + *static_cast(outData) = GetLatency(); + break; + + case kAudioUnitProperty_TailTime: + AUSDK_Require(SupportsTail(), kAudioUnitErr_InvalidProperty); + *static_cast(outData) = GetTailTime(); + break; + + case kAudioUnitProperty_MaximumFramesPerSlice: + *static_cast(outData) = mMaxFramesPerSlice; + break; + + case kAudioUnitProperty_LastRenderError: + *static_cast(outData) = mLastRenderError; + mLastRenderError = 0; + break; + + case kAudioUnitProperty_SupportedNumChannels: { + const AUChannelInfo* infoPtr = nullptr; + const UInt32 num = SupportedNumChannels(&infoPtr); + if (num != 0 && infoPtr != nullptr) { + memcpy(outData, infoPtr, num * sizeof(AUChannelInfo)); + } + break; + } + + case kAudioUnitProperty_SupportedChannelLayoutTags: { + const auto tags = GetChannelLayoutTags(inScope, inElement); + AUSDK_Require(!tags.empty(), kAudioUnitErr_InvalidProperty); + AudioChannelLayoutTag* const ptr = + outData != nullptr ? static_cast(outData) : nullptr; + if (ptr != nullptr) { + memcpy(ptr, tags.data(), tags.size() * sizeof(AudioChannelLayoutTag)); + } + break; + } + + case kAudioUnitProperty_AudioChannelLayout: { + AudioChannelLayout* const ptr = + outData != nullptr ? static_cast(outData) : nullptr; + bool writable = false; + const UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable); + AUSDK_Require(dataSize != 0, kAudioUnitErr_InvalidProperty); + break; + } + + case kAudioUnitProperty_ShouldAllocateBuffer: { + const auto& element = IOElement(inScope, inElement); + *static_cast(outData) = static_cast(element.WillAllocateBuffer()); + break; + } + + case kAudioUnitProperty_ParameterValueStrings: + result = GetParameterValueStrings(inScope, inElement, static_cast(outData)); + break; + + case kAudioUnitProperty_HostCallbacks: + memcpy(outData, &mHostCallbackInfo, sizeof(mHostCallbackInfo)); + break; + + case kAudioUnitProperty_ContextName: + if (const CFStringRef name = *mContextName) { + CFRetain(name); // must return a +1 reference + *static_cast(outData) = name; + result = noErr; + } else { + *static_cast(outData) = nullptr; + result = kAudioUnitErr_PropertyNotInUse; + } + break; + +#if !TARGET_OS_IPHONE + case kAudioUnitProperty_IconLocation: { + const CFURLRef iconLocation = CopyIconLocation(); + AUSDK_Require(iconLocation != nullptr, kAudioUnitErr_InvalidProperty); + *static_cast(outData) = iconLocation; + break; + } +#endif + + case kAudioUnitProperty_ParameterClumpName: { + auto* const ioClumpInfo = static_cast(outData); + AUSDK_Require(ioClumpInfo->inID != kAudioUnitClumpID_System, + kAudioUnitErr_InvalidPropertyValue); // this ID value is reserved + result = CopyClumpName(inScope, ioClumpInfo->inID, + static_cast(std::max(ioClumpInfo->inDesiredLength, SInt32(0))), + &ioClumpInfo->outName); + + // this is provided for compatbility with existing implementations that don't know + // about this new mechanism + if (result == kAudioUnitErr_InvalidProperty) { + result = GetProperty(inID, inScope, inElement, outData); + } + break; + } + + case 61: // kAudioUnitProperty_LastRenderSampleTime + *static_cast(outData) = mCurrentRenderTime.mSampleTime; + break; + + case kAudioUnitProperty_NickName: + // Ownership follows Core Foundation's 'Copy Rule' + if (const auto* const name = *mNickName) { + CFRetain(name); + *static_cast(outData) = name; + } else { + *static_cast(outData) = nullptr; + } + break; + + default: + result = GetProperty(inID, inScope, inElement, outData); + break; + } + return result; +} + + +//_____________________________________________________________________________ +// +// Note: We can be sure inData is non-null; otherwise RemoveProperty would have been called. +// NOLINTNEXTLINE(misc-no-recursion) with RestoreState +OSStatus AUBase::DispatchSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) +{ + OSStatus result = noErr; + + switch (inID) { + case kAudioUnitProperty_MakeConnection: { + AUSDK_Require( + inDataSize >= sizeof(AudioUnitConnection), kAudioUnitErr_InvalidPropertyValue); + const auto& connection = *static_cast(inData); + result = SetConnection(connection); + break; + } + + case kAudioUnitProperty_SetRenderCallback: { + AUSDK_Require( + inDataSize >= sizeof(AURenderCallbackStruct), kAudioUnitErr_InvalidPropertyValue); + const auto& callback = *static_cast(inData); + result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, + callback.inputProc, callback.inputProcRefCon); + break; + } + + case kAudioUnitProperty_ElementCount: + AUSDK_Require(inDataSize == sizeof(UInt32), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(BusCountWritable(inScope), kAudioUnitErr_PropertyNotWritable); + result = SetBusCount(inScope, *static_cast(inData)); + if (result == noErr) { + PropertyChanged(inID, inScope, inElement); + } + break; + + case kAudioUnitProperty_MaximumFramesPerSlice: + AUSDK_Require(inDataSize == sizeof(UInt32), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require_noerr(CanSetMaxFrames()); + SetMaxFramesPerSlice(*static_cast(inData)); + break; + + case kAudioUnitProperty_StreamFormat: { + constexpr static UInt32 kMinimumValidASBDSize = 36; + AUSDK_Require(inDataSize >= kMinimumValidASBDSize, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement); + + AudioStreamBasicDescription newDesc = {}; + // now we're going to be ultra conservative! because of discrepancies between + // sizes of this struct based on aligment padding inconsistencies + memcpy(&newDesc, inData, kMinimumValidASBDSize); + + AUSDK_Require(ASBD::MinimalSafetyCheck(newDesc), kAudioUnitErr_FormatNotSupported); + + AUSDK_Require(ValidFormat(inScope, inElement, newDesc), kAudioUnitErr_FormatNotSupported); + + const AudioStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement); + + if (!ASBD::IsEqual(curDesc, newDesc)) { + AUSDK_Require( + IsStreamFormatWritable(inScope, inElement), kAudioUnitErr_PropertyNotWritable); + result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc); + } + break; + } + + case kAudioUnitProperty_SampleRate: { + AUSDK_Require(inDataSize == sizeof(Float64), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement); + + const AudioStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement); + AudioStreamBasicDescription newDesc = curDesc; + newDesc.mSampleRate = *static_cast(inData); + + AUSDK_Require(ValidFormat(inScope, inElement, newDesc), kAudioUnitErr_FormatNotSupported); + + if (!ASBD::IsEqual(curDesc, newDesc)) { + AUSDK_Require( + IsStreamFormatWritable(inScope, inElement), kAudioUnitErr_PropertyNotWritable); + result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc); + } + break; + } + + case kAudioUnitProperty_AudioChannelLayout: { + const auto& layout = *static_cast(inData); + constexpr size_t headerSize = sizeof(AudioChannelLayout) - sizeof(AudioChannelDescription); + + AUSDK_Require(inDataSize >= offsetof(AudioChannelLayout, mNumberChannelDescriptions) + + sizeof(AudioChannelLayout::mNumberChannelDescriptions), + kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(inDataSize >= headerSize + layout.mNumberChannelDescriptions * + sizeof(AudioChannelDescription), + kAudioUnitErr_InvalidPropertyValue); + result = SetAudioChannelLayout(inScope, inElement, &layout); + if (result == noErr) { + PropertyChanged(inID, inScope, inElement); + } + break; + } + + case kAudioUnitProperty_ClassInfo: + AUSDK_Require(inDataSize == sizeof(CFPropertyListRef*), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + result = RestoreState(*static_cast(inData)); + break; + + case kAudioUnitProperty_PresentPreset: { + AUSDK_Require(inDataSize == sizeof(AUPreset), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + const auto& newPreset = *static_cast(inData); + + if (newPreset.presetNumber >= 0) { + result = NewFactoryPresetSet(newPreset); + // NewFactoryPresetSet SHOULD call SetAFactoryPreset if the preset is valid + // from its own list of preset number->name + if (result == noErr) { + PropertyChanged(inID, inScope, inElement); + } + } else if (newPreset.presetName != nullptr) { + result = NewCustomPresetSet(newPreset); + if (result == noErr) { + PropertyChanged(inID, inScope, inElement); + } + } else { + result = kAudioUnitErr_InvalidPropertyValue; + } + break; + } + + case kAudioUnitProperty_ElementName: { + AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement); + AUSDK_Require(inDataSize == sizeof(CFStringRef), kAudioUnitErr_InvalidPropertyValue); + const auto element = GetScope(inScope).GetElement(inElement); + const CFStringRef inStr = *static_cast(inData); + element->SetName(inStr); + PropertyChanged(inID, inScope, inElement); + break; + } + + case kAudioUnitProperty_ShouldAllocateBuffer: { + AUSDK_Require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), + kAudioUnitErr_InvalidScope); + AUSDK_Require(GetElement(inScope, inElement) != nullptr, kAudioUnitErr_InvalidElement); + AUSDK_Require(inDataSize == sizeof(UInt32), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(!IsInitialized(), kAudioUnitErr_Initialized); + + auto& element = IOElement(inScope, inElement); + element.SetWillAllocateBuffer(*static_cast(inData) != 0); + break; + } + + case kAudioUnitProperty_HostCallbacks: { + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + const UInt32 availSize = + std::min(inDataSize, static_cast(sizeof(HostCallbackInfo))); + const bool hasChanged = memcmp(&mHostCallbackInfo, inData, availSize) == 0; + mHostCallbackInfo = {}; + memcpy(&mHostCallbackInfo, inData, availSize); + if (hasChanged) { + PropertyChanged(inID, inScope, inElement); + } + break; + } + + case kAudioUnitProperty_ContextName: { + AUSDK_Require(inDataSize == sizeof(CFStringRef), kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + const CFStringRef inStr = *static_cast(inData); + mContextName = inStr; + PropertyChanged(inID, inScope, inElement); + break; + } + + + case kAudioUnitProperty_NickName: { + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inDataSize == sizeof(CFStringRef), kAudioUnitErr_InvalidPropertyValue); + const CFStringRef inStr = *static_cast(inData); + mNickName = inStr; + PropertyChanged(inID, inScope, inElement); + break; + } + + default: + result = SetProperty(inID, inScope, inElement, inData, inDataSize); + if (result == noErr) { + PropertyChanged(inID, inScope, inElement); + } + + break; + } + return result; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::DispatchRemovePropertyValue( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement) +{ + OSStatus result = noErr; + switch (inID) { + case kAudioUnitProperty_AudioChannelLayout: { + result = RemoveAudioChannelLayout(inScope, inElement); + if (result == noErr) { + PropertyChanged(inID, inScope, inElement); + } + break; + } + + case kAudioUnitProperty_HostCallbacks: { + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + bool hasValue = false; + const void* const ptr = &mHostCallbackInfo; + for (size_t i = 0; i < sizeof(HostCallbackInfo); ++i) { + if (static_cast(ptr)[i] != 0) { // NOLINT + hasValue = true; + break; + } + } + if (hasValue) { + mHostCallbackInfo = {}; + PropertyChanged(inID, inScope, inElement); + } + break; + } + + case kAudioUnitProperty_ContextName: + mContextName = nullptr; + result = noErr; + break; + + case kAudioUnitProperty_NickName: { + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + mNickName = nullptr; + PropertyChanged(inID, inScope, inElement); + break; + } + + default: + result = RemovePropertyValue(inID, inScope, inElement); + break; + } + + return result; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetPropertyInfo(AudioUnitPropertyID /*inID*/, AudioUnitScope /*inScope*/, + AudioUnitElement /*inElement*/, UInt32& /*outDataSize*/, bool& /*outWritable*/) +{ + return kAudioUnitErr_InvalidProperty; +} + + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetProperty(AudioUnitPropertyID /*inID*/, AudioUnitScope /*inScope*/, + AudioUnitElement /*inElement*/, void* /*outData*/) +{ + return kAudioUnitErr_InvalidProperty; +} + + +//_____________________________________________________________________________ +// +OSStatus AUBase::SetProperty(AudioUnitPropertyID /*inID*/, AudioUnitScope /*inScope*/, + AudioUnitElement /*inElement*/, const void* /*inData*/, UInt32 /*inDataSize*/) +{ + return kAudioUnitErr_InvalidProperty; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::RemovePropertyValue( + AudioUnitPropertyID /*inID*/, AudioUnitScope /*inScope*/, AudioUnitElement /*inElement*/) +{ + return kAudioUnitErr_InvalidPropertyValue; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::AddPropertyListener( + AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc, void* inProcRefCon) +{ + const PropertyListener pl{ + .propertyID = inID, .listenerProc = inProc, .listenerRefCon = inProcRefCon + }; + + if (mPropertyListeners.empty()) { + mPropertyListeners.reserve(32); // NOLINT magic# + } + mPropertyListeners.push_back(pl); + + return noErr; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::RemovePropertyListener(AudioUnitPropertyID inID, + AudioUnitPropertyListenerProc inProc, void* inProcRefCon, bool refConSpecified) +{ + const auto iter = + std::remove_if(mPropertyListeners.begin(), mPropertyListeners.end(), [&](auto& item) { + return item.propertyID == inID && item.listenerProc == inProc && + (!refConSpecified || item.listenerRefCon == inProcRefCon); + }); + if (iter != mPropertyListeners.end()) { + mPropertyListeners.erase(iter, mPropertyListeners.end()); + } + return noErr; +} + +//_____________________________________________________________________________ +// +void AUBase::PropertyChanged( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement) +{ + for (const auto& pl : mPropertyListeners) { + if (pl.propertyID == inID) { + (pl.listenerProc)(pl.listenerRefCon, GetComponentInstance(), inID, inScope, inElement); + } + } +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::SetRenderNotification(AURenderCallback inProc, void* inRefCon) +{ + if (inProc == nullptr) { + return kAudio_ParamError; + } + + mRenderCallbacksTouched = true; + mRenderCallbacks.add(RenderCallback(inProc, inRefCon)); + // this will do nothing if it's already in the list + return noErr; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::RemoveRenderNotification(AURenderCallback inProc, void* inRefCon) +{ + mRenderCallbacks.remove(RenderCallback(inProc, inRefCon)); + return noErr; // error? +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetParameter(AudioUnitParameterID inID, AudioUnitScope inScope, + AudioUnitElement inElement, AudioUnitParameterValue& outValue) +{ + const auto& elem = Element(inScope, inElement); + outValue = elem.GetParameter(inID); + return noErr; +} + + +//_____________________________________________________________________________ +// +OSStatus AUBase::SetParameter(AudioUnitParameterID inID, AudioUnitScope inScope, + AudioUnitElement inElement, AudioUnitParameterValue inValue, UInt32 /*inBufferOffsetInFrames*/) +{ + auto& elem = Element(inScope, inElement); + elem.SetParameter(inID, inValue); + return noErr; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::ScheduleParameter( + const AudioUnitParameterEvent* inParameterEvent, UInt32 inNumEvents) +{ + const bool canScheduleParameters = CanScheduleParameters(); + + for (UInt32 i = 0; i < inNumEvents; ++i) { + const auto& pe = inParameterEvent[i]; // NOLINT subscript + if (pe.eventType == kParameterEvent_Immediate) { + SetParameter(pe.parameter, pe.scope, pe.element, + pe.eventValues.immediate.value, // NOLINT union + pe.eventValues.immediate.bufferOffset); // NOLINT union + } + if (canScheduleParameters) { + mParamEventList.push_back(pe); + } + } + + return noErr; +} + +// ____________________________________________________________________________ +// +constexpr bool ParameterEventListSortPredicate( + const AudioUnitParameterEvent& ev1, const AudioUnitParameterEvent& ev2) noexcept +{ + // ramp.startBufferOffset is signed + const SInt32 offset1 = + ev1.eventType == kParameterEvent_Immediate + ? static_cast(ev1.eventValues.immediate.bufferOffset) // NOLINT union + : ev1.eventValues.ramp.startBufferOffset; // NOLINT union + const SInt32 offset2 = + ev2.eventType == kParameterEvent_Immediate + ? static_cast(ev2.eventValues.immediate.bufferOffset) // NOLINT union + : ev2.eventValues.ramp.startBufferOffset; // NOLINT union + + return offset1 < offset2; +} + + +// ____________________________________________________________________________ +// +OSStatus AUBase::ProcessForScheduledParams( + ParameterEventList& inParamList, UInt32 inFramesToProcess, void* inUserData) +{ + OSStatus result = noErr; + + UInt32 framesRemaining = inFramesToProcess; + + UInt32 currentStartFrame = 0; // start of the whole buffer + + + // sort the ParameterEventList by startBufferOffset + std::sort(inParamList.begin(), inParamList.end(), ParameterEventListSortPredicate); + + while (framesRemaining > 0) { + // first of all, go through the ramped automation events and find out where the next + // division of our whole buffer will be + + UInt32 currentEndFrame = inFramesToProcess; // start out assuming we'll process all the way + // to the end of the buffer + + // find the next break point + for (const auto& event : inParamList) { + SInt32 offset = + event.eventType == kParameterEvent_Immediate + ? static_cast(event.eventValues.immediate.bufferOffset) // NOLINT + : event.eventValues.ramp.startBufferOffset; + + if (offset > static_cast(currentStartFrame) && + offset < static_cast(currentEndFrame)) { + currentEndFrame = static_cast(offset); + break; + } + + // consider ramp end to be a possible choice (there may be gaps in the supplied ramp + // events) + if (event.eventType == kParameterEvent_Ramped) { + offset = event.eventValues.ramp.startBufferOffset + + static_cast(event.eventValues.ramp.durationInFrames); // NOLINT + + if (offset > static_cast(currentStartFrame) && + offset < static_cast(currentEndFrame)) { + currentEndFrame = static_cast(offset); + } + } + } + + const UInt32 framesThisTime = currentEndFrame - currentStartFrame; + + // next, setup the parameter maps to be current for the ramp parameters active during + // this time segment... + + for (const auto& event : inParamList) { + bool eventFallsInSlice = false; + + if (event.eventType == kParameterEvent_Ramped) { + const auto& ramp = event.eventValues.ramp; + eventFallsInSlice = + ramp.startBufferOffset < static_cast(currentEndFrame) && + (ramp.startBufferOffset + static_cast(ramp.durationInFrames)) > + static_cast(currentStartFrame); + } else { /* kParameterEvent_Immediate */ + // actually, for the same parameter, there may be future immediate events which + // override this one, but it's OK since the event list is sorted in time order, + // we're guaranteed to end up with the current one + eventFallsInSlice = event.eventValues.immediate.bufferOffset <= currentStartFrame; + } + + if (eventFallsInSlice) { + AUElement* const element = GetElement(event.scope, event.element); + + if (element != nullptr) { + element->SetScheduledEvent(event.parameter, event, currentStartFrame, + currentEndFrame - currentStartFrame); + } + } + } + + + // Finally, actually do the processing for this slice..... + + result = + ProcessScheduledSlice(inUserData, currentStartFrame, framesThisTime, inFramesToProcess); + + if (result != noErr) { + break; + } + + framesRemaining -= std::min(framesThisTime, framesRemaining); + currentStartFrame = currentEndFrame; // now start from where we left off last time + } + + return result; +} + +//_____________________________________________________________________________ +// +void AUBase::ResetRenderTime() +{ + mCurrentRenderTime = {}; + mCurrentRenderTime.mSampleTime = kNoLastRenderedSampleTime; +} + +//_____________________________________________________________________________ +// +void AUBase::SetWantsRenderThreadID(bool inFlag) +{ + if (inFlag == mWantsRenderThreadID) { + return; + } + + mWantsRenderThreadID = inFlag; + if (!mWantsRenderThreadID) { + mRenderThreadID = {}; + }; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::DoRender(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 inBusNumber, UInt32 inFramesToProcess, + AudioBufferList& ioData) +{ + const auto errorExit = [this](OSStatus error) { + AUSDK_LogError(" from %s, render err: %d", GetLoggingString(), static_cast(error)); + SetRenderError(error); + return error; + }; + + OSStatus theError = noErr; + + [[maybe_unused]] const DenormalDisabler denormalDisabler; + + try { + AUSDK_Require(IsInitialized(), errorExit(kAudioUnitErr_Uninitialized)); + if (inFramesToProcess > mMaxFramesPerSlice) { +#ifndef AUSDK_NO_LOGGING + static UInt64 lastTimeMessagePrinted = 0; + const UInt64 now = HostTime::Current(); + if (static_cast(now - lastTimeMessagePrinted) > + mHostTimeFrequency) { // not more than once per second. + lastTimeMessagePrinted = now; + AUSDK_LogError("kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=%u, " + "mMaxFramesPerSlice=%u", + static_cast(inFramesToProcess), + static_cast(mMaxFramesPerSlice)); + } +#endif + return errorExit(kAudioUnitErr_TooManyFramesToProcess); + } + AUSDK_Require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), + errorExit(kAudio_ParamError)); + + auto& output = Output(inBusNumber); // will throw if non-existant + if (ASBD::NumberChannelStreams(output.GetStreamFormat()) != ioData.mNumberBuffers) { + AUSDK_LogError( + "ioData.mNumberBuffers=%u, " + "ASBD::NumberChannelStreams(output.GetStreamFormat())=%u; kAudio_ParamError", + static_cast(ioData.mNumberBuffers), + static_cast(ASBD::NumberChannelStreams(output.GetStreamFormat()))); + return errorExit(kAudio_ParamError); + } + + const unsigned expectedBufferByteSize = + inFramesToProcess * output.GetStreamFormat().mBytesPerFrame; + for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) { + AudioBuffer& buf = ioData.mBuffers[ibuf]; // NOLINT + if (buf.mData != nullptr) { + // only care about the size if the buffer is non-null + if (buf.mDataByteSize < expectedBufferByteSize) { + // if the buffer is too small, we cannot render safely. kAudio_ParamError. + AUSDK_LogError("%u frames, %u bytes/frame, expected %u-byte buffer; " + "ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError", + static_cast(inFramesToProcess), + static_cast(output.GetStreamFormat().mBytesPerFrame), + expectedBufferByteSize, ibuf, static_cast(buf.mDataByteSize)); + return errorExit(kAudio_ParamError); + } + // Some clients incorrectly pass bigger buffers than expectedBufferByteSize. + // We will generally set the buffer size at the end of rendering, before we return. + // However we should ensure that no one, DURING rendering, READS a + // potentially incorrect size. This can lead to doing too much work, or + // reading past the end of an input buffer into unmapped memory. + buf.mDataByteSize = expectedBufferByteSize; + } + } + + if (WantsRenderThreadID()) { + mRenderThreadID = std::this_thread::get_id(); + } + + if (mRenderCallbacksTouched) { + AudioUnitRenderActionFlags flags = ioActionFlags | kAudioUnitRenderAction_PreRender; + mRenderCallbacks.foreach ([&](const RenderCallback& rc) { + (*static_cast(rc.mRenderNotify))(rc.mRenderNotifyRefCon, &flags, + &inTimeStamp, inBusNumber, inFramesToProcess, &ioData); + }); + } + + theError = + DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData); + + SetRenderError(theError); + + if (mRenderCallbacksTouched) { + AudioUnitRenderActionFlags flags = ioActionFlags | kAudioUnitRenderAction_PostRender; + + if (theError != noErr) { + flags |= kAudioUnitRenderAction_PostRenderError; + } + + mRenderCallbacks.foreach ([&](const RenderCallback& rc) { + (*static_cast(rc.mRenderNotify))(rc.mRenderNotifyRefCon, &flags, + &inTimeStamp, inBusNumber, inFramesToProcess, &ioData); + }); + } + + // The vector's being emptied + // because these events should only apply to this Render cycle, so anything + // left over is from a preceding cycle and should be dumped. New scheduled + // parameters must be scheduled from the next pre-render callback. + if (!mParamEventList.empty()) { + mParamEventList.clear(); + } + } catch (const OSStatus& err) { + return errorExit(err); + } catch (...) { + return errorExit(-1); + } + return theError; +} + +inline bool CheckRenderArgs(AudioUnitRenderActionFlags flags) +{ + return (flags & kAudioUnitRenderAction_DoNotCheckRenderArgs) == 0u; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::DoProcess(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 inFramesToProcess, AudioBufferList& ioData) +{ + const auto errorExit = [this](OSStatus error) { + AUSDK_LogError(" from %s, process err: %d", GetLoggingString(), static_cast(error)); + SetRenderError(error); + return error; + }; + + OSStatus theError = noErr; + + [[maybe_unused]] const DenormalDisabler denormalDisabler; + + try { + if (CheckRenderArgs(ioActionFlags)) { + AUSDK_Require(IsInitialized(), errorExit(kAudioUnitErr_Uninitialized)); + AUSDK_Require(inFramesToProcess <= mMaxFramesPerSlice, + errorExit(kAudioUnitErr_TooManyFramesToProcess)); + AUSDK_Require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), + errorExit(kAudio_ParamError)); + + const auto& input = Input(0); // will throw if non-existant + if (ASBD::NumberChannelStreams(input.GetStreamFormat()) != ioData.mNumberBuffers) { + AUSDK_LogError( + "ioData.mNumberBuffers=%u, " + "ASBD::NumberChannelStreams(input->GetStreamFormat())=%u; kAudio_ParamError", + static_cast(ioData.mNumberBuffers), + static_cast(ASBD::NumberChannelStreams(input.GetStreamFormat()))); + return errorExit(kAudio_ParamError); + } + + const unsigned expectedBufferByteSize = + inFramesToProcess * input.GetStreamFormat().mBytesPerFrame; + for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) { + AudioBuffer& buf = ioData.mBuffers[ibuf]; // NOLINT + if (buf.mData != nullptr) { + // only care about the size if the buffer is non-null + if (buf.mDataByteSize < expectedBufferByteSize) { + // if the buffer is too small, we cannot render safely. kAudio_ParamError. + AUSDK_LogError("%u frames, %u bytes/frame, expected %u-byte buffer; " + "ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError", + static_cast(inFramesToProcess), + static_cast(input.GetStreamFormat().mBytesPerFrame), + expectedBufferByteSize, ibuf, static_cast(buf.mDataByteSize)); + return errorExit(kAudio_ParamError); + } + // Some clients incorrectly pass bigger buffers than expectedBufferByteSize. + // We will generally set the buffer size at the end of rendering, before we + // return. However we should ensure that no one, DURING rendering, READS a + // potentially incorrect size. This can lead to doing too much work, or + // reading past the end of an input buffer into unmapped memory. + buf.mDataByteSize = expectedBufferByteSize; + } + } + } + + if (WantsRenderThreadID()) { + mRenderThreadID = std::this_thread::get_id(); + } + + if (NeedsToRender(inTimeStamp)) { + theError = ProcessBufferLists(ioActionFlags, ioData, ioData, inFramesToProcess); + } else { + theError = noErr; + } + + } catch (const OSStatus& err) { + return errorExit(err); + } catch (...) { + return errorExit(-1); + } + return theError; +} + +OSStatus AUBase::DoProcessMultiple(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 inFramesToProcess, UInt32 inNumberInputBufferLists, + const AudioBufferList** inInputBufferLists, UInt32 inNumberOutputBufferLists, + AudioBufferList** ioOutputBufferLists) +{ + const auto errorExit = [this](OSStatus error) { + AUSDK_LogError( + " from %s, processmultiple err: %d", GetLoggingString(), static_cast(error)); + SetRenderError(error); + return error; + }; + + OSStatus theError = noErr; + + [[maybe_unused]] const DenormalDisabler denormalDisabler; + + try { + if (CheckRenderArgs(ioActionFlags)) { + AUSDK_Require(IsInitialized(), errorExit(kAudioUnitErr_Uninitialized)); + AUSDK_Require(inFramesToProcess <= mMaxFramesPerSlice, + errorExit(kAudioUnitErr_TooManyFramesToProcess)); + AUSDK_Require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), + errorExit(kAudio_ParamError)); + + for (unsigned ibl = 0; ibl < inNumberInputBufferLists; ++ibl) { + if (inInputBufferLists[ibl] != nullptr) { // NOLINT + const auto& input = Input(ibl); // will throw if non-existant + const unsigned expectedBufferByteSize = + inFramesToProcess * input.GetStreamFormat().mBytesPerFrame; + + if (ASBD::NumberChannelStreams(input.GetStreamFormat()) != + inInputBufferLists[ibl]->mNumberBuffers) { // NOLINT + AUSDK_LogError("inInputBufferLists[%u]->mNumberBuffers=%u, " + "ASBD::NumberChannelStreams(input.GetStreamFormat())=%u; " + "kAudio_ParamError", + ibl, static_cast(inInputBufferLists[ibl]->mNumberBuffers), + static_cast( + ASBD::NumberChannelStreams(input.GetStreamFormat()))); + return errorExit(kAudio_ParamError); + } + + for (unsigned ibuf = 0; + ibuf < inInputBufferLists[ibl]->mNumberBuffers; // NOLINT + ++ibuf) { + const AudioBuffer& buf = inInputBufferLists[ibl]->mBuffers[ibuf]; // NOLINT + if (buf.mData != nullptr) { + if (buf.mDataByteSize < expectedBufferByteSize) { + // the buffer is too small + AUSDK_LogError( + "%u frames, %u bytes/frame, expected %u-byte buffer; " + "inInputBufferLists[%u].mBuffers[%u].mDataByteSize=%u; " + "kAudio_ParamError", + static_cast(inFramesToProcess), + static_cast(input.GetStreamFormat().mBytesPerFrame), + expectedBufferByteSize, ibl, ibuf, + static_cast(buf.mDataByteSize)); + return errorExit(kAudio_ParamError); + } + } else { + // the buffer must exist + return errorExit(kAudio_ParamError); + } + } + } else { + // skip NULL input audio buffer list + } + } + + for (unsigned obl = 0; obl < inNumberOutputBufferLists; ++obl) { + if (ioOutputBufferLists[obl] != nullptr) { // NOLINT + const auto& output = Output(obl); // will throw if non-existant + const unsigned expectedBufferByteSize = + inFramesToProcess * output.GetStreamFormat().mBytesPerFrame; + + if (ASBD::NumberChannelStreams(output.GetStreamFormat()) != + ioOutputBufferLists[obl]->mNumberBuffers) { // NOLINT + AUSDK_LogError("ioOutputBufferLists[%u]->mNumberBuffers=%u, " + "ASBD::NumberChannelStreams(output.GetStreamFormat())=%u; " + "kAudio_ParamError", + obl, static_cast(ioOutputBufferLists[obl]->mNumberBuffers), + static_cast( + ASBD::NumberChannelStreams(output.GetStreamFormat()))); + return errorExit(kAudio_ParamError); + } + + for (unsigned obuf = 0; + obuf < ioOutputBufferLists[obl]->mNumberBuffers; // NOLINT + ++obuf) { + AudioBuffer& buf = ioOutputBufferLists[obl]->mBuffers[obuf]; // NOLINT + if (buf.mData != nullptr) { + // only care about the size if the buffer is non-null + if (buf.mDataByteSize < expectedBufferByteSize) { + // if the buffer is too small, we cannot render safely. + // kAudio_ParamError. + AUSDK_LogError( + "%u frames, %u bytes/frame, expected %u-byte buffer; " + "ioOutputBufferLists[%u]->mBuffers[%u].mDataByteSize=%u; " + "kAudio_ParamError", + static_cast(inFramesToProcess), + static_cast(output.GetStreamFormat().mBytesPerFrame), + expectedBufferByteSize, obl, obuf, + static_cast(buf.mDataByteSize)); + return errorExit(kAudio_ParamError); + } + // Some clients incorrectly pass bigger buffers than + // expectedBufferByteSize. We will generally set the buffer size at the + // end of rendering, before we return. However we should ensure that no + // one, DURING rendering, READS a potentially incorrect size. This can + // lead to doing too much work, or reading past the end of an input + // buffer into unmapped memory. + buf.mDataByteSize = expectedBufferByteSize; + } + } + } else { + // skip NULL output audio buffer list + } + } + } + + if (WantsRenderThreadID()) { + mRenderThreadID = std::this_thread::get_id(); + } + + if (NeedsToRender(inTimeStamp)) { + theError = ProcessMultipleBufferLists(ioActionFlags, inFramesToProcess, + inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, + ioOutputBufferLists); + } else { + theError = noErr; + } + } catch (const OSStatus& err) { + return errorExit(err); + } catch (...) { + return errorExit(-1); + } + return theError; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::SetInputCallback( + UInt32 inPropertyID, AudioUnitElement inElement, AURenderCallback inProc, void* inRefCon) +{ + auto& input = Input(inElement); // may throw + + input.SetInputCallback(inProc, inRefCon); + PropertyChanged(inPropertyID, kAudioUnitScope_Input, inElement); + + return noErr; +} + +//_____________________________________________________________________________ +// +// NOLINTNEXTLINE(misc-no-recursion) with DispatchSetProperty +OSStatus AUBase::SetConnection(const AudioUnitConnection& inConnection) +{ + auto& input = Input(inConnection.destInputNumber); // may throw + + if (inConnection.sourceAudioUnit != nullptr) { + // connecting, not disconnecting + AudioStreamBasicDescription sourceDesc; + UInt32 size = sizeof(AudioStreamBasicDescription); + AUSDK_Require_noerr( + AudioUnitGetProperty(inConnection.sourceAudioUnit, kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, inConnection.sourceOutputNumber, &sourceDesc, &size)); + AUSDK_Require_noerr( + DispatchSetProperty(kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, + inConnection.destInputNumber, &sourceDesc, sizeof(AudioStreamBasicDescription))); + } + input.SetConnection(inConnection); + + PropertyChanged( + kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inConnection.destInputNumber); + return noErr; +} + +//_____________________________________________________________________________ +// +UInt32 AUBase::SupportedNumChannels(const AUChannelInfo** /*outInfo*/) { return 0; } + +//_____________________________________________________________________________ +// +bool AUBase::ValidFormat(AudioUnitScope /*inScope*/, AudioUnitElement /*inElement*/, + const AudioStreamBasicDescription& inNewFormat) +{ + return ASBD::IsCommonFloat32(inNewFormat) && + (!ASBD::IsInterleaved(inNewFormat) || inNewFormat.mChannelsPerFrame == 1); +} + +//_____________________________________________________________________________ +// +bool AUBase::IsStreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) +{ + switch (scope) { + case kAudioUnitScope_Input: { + const auto& input = Input(element); + if (input.HasConnection()) { + return false; // can't write format when input comes from connection + } + [[fallthrough]]; + } + case kAudioUnitScope_Output: + return StreamFormatWritable(scope, element); + + //#warning "aliasing of global scope format should be pushed to subclasses" + case kAudioUnitScope_Global: + return StreamFormatWritable(kAudioUnitScope_Output, 0); + default: + break; + } + return false; +} + +//_____________________________________________________________________________ +// +AudioStreamBasicDescription AUBase::GetStreamFormat( + AudioUnitScope inScope, AudioUnitElement inElement) +{ + //#warning "aliasing of global scope format should be pushed to subclasses" + AUIOElement* element = nullptr; + + switch (inScope) { + case kAudioUnitScope_Input: + element = Inputs().GetIOElement(inElement); + break; + case kAudioUnitScope_Output: + element = Outputs().GetIOElement(inElement); + break; + case kAudioUnitScope_Global: // global stream description is an alias for that of output 0 + element = Outputs().GetIOElement(0); + break; + default: + Throw(kAudioUnitErr_InvalidScope); + } + return element->GetStreamFormat(); +} + +OSStatus AUBase::SetBusCount(AudioUnitScope inScope, UInt32 inCount) +{ + if (IsInitialized()) { + return kAudioUnitErr_Initialized; + } + + GetScope(inScope).SetNumberOfElements(inCount); + return noErr; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement, + const AudioStreamBasicDescription& inPrevFormat, const AudioStreamBasicDescription& inNewFormat) +{ + if (ASBD::IsEqual(inNewFormat, inPrevFormat)) { + return noErr; + } + + //#warning "aliasing of global scope format should be pushed to subclasses" + AUIOElement* element = nullptr; + + switch (inScope) { + case kAudioUnitScope_Input: + element = Inputs().GetIOElement(inElement); + break; + case kAudioUnitScope_Output: + element = Outputs().GetIOElement(inElement); + break; + case kAudioUnitScope_Global: + element = Outputs().GetIOElement(0); + break; + default: + Throw(kAudioUnitErr_InvalidScope); + } + element->SetStreamFormat(inNewFormat); + PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement); + return noErr; +} + +std::vector AUBase::GetChannelLayoutTags( + AudioUnitScope inScope, AudioUnitElement inElement) +{ + return IOElement(inScope, inElement).GetChannelLayoutTags(); +} + +UInt32 AUBase::GetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, + AudioChannelLayout* outLayoutPtr, bool& outWritable) +{ + auto& el = IOElement(scope, element); + return el.GetAudioChannelLayout(outLayoutPtr, outWritable); +} + +OSStatus AUBase::RemoveAudioChannelLayout(AudioUnitScope inScope, AudioUnitElement inElement) +{ + OSStatus result = noErr; + auto& el = IOElement(inScope, inElement); + bool writable = false; + if (el.GetAudioChannelLayout(nullptr, writable) > 0) { + result = el.RemoveAudioChannelLayout(); + } + return result; +} + +OSStatus AUBase::SetAudioChannelLayout( + AudioUnitScope inScope, AudioUnitElement inElement, const AudioChannelLayout* inLayout) +{ + auto& ioEl = IOElement(inScope, inElement); + + // the num channels of the layout HAS TO MATCH the current channels of the Element's stream + // format + const UInt32 currentChannels = ioEl.GetStreamFormat().mChannelsPerFrame; + const UInt32 numChannelsInLayout = AUChannelLayout::NumberChannels(*inLayout); + if (currentChannels != numChannelsInLayout) { + return kAudioUnitErr_InvalidPropertyValue; + } + + const auto tags = GetChannelLayoutTags(inScope, inElement); + if (tags.empty()) { + return kAudioUnitErr_InvalidProperty; + } + const auto inTag = inLayout->mChannelLayoutTag; + const auto iter = std::find_if(tags.begin(), tags.end(), [&inTag](auto& tag) { + return tag == inTag || tag == kAudioChannelLayoutTag_UseChannelDescriptions; + }); + + if (iter == tags.end()) { + return kAudioUnitErr_InvalidPropertyValue; + } + + return ioEl.SetAudioChannelLayout(*inLayout); +} + +constexpr int kCurrentSavedStateVersion = 0; + +static void AddNumToDictionary(CFMutableDictionaryRef dict, CFStringRef key, SInt32 value) +{ + const CFNumberRef num = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value); + CFDictionarySetValue(dict, key, num); + CFRelease(num); +} + +// NOLINTNEXTLINE(misc-no-recursion) with DispatchGetProperty +OSStatus AUBase::SaveState(CFPropertyListRef* outData) +{ + const AudioComponentDescription desc = GetComponentDescription(); + + auto dict = Owned::from_create(CFDictionaryCreateMutable( + nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + // first step -> save the version to the data ref + SInt32 value = kCurrentSavedStateVersion; + AddNumToDictionary(*dict, kVersionString, value); + + // second step -> save the component type, subtype, manu to the data ref + value = static_cast(desc.componentType); + AddNumToDictionary(*dict, kTypeString, value); + + value = static_cast(desc.componentSubType); + AddNumToDictionary(*dict, kSubtypeString, value); + + value = static_cast(desc.componentManufacturer); + AddNumToDictionary(*dict, kManufacturerString, value); + + // fourth step -> save the state of all parameters on all scopes and elements + auto data = Owned::from_create(CFDataCreateMutable(nullptr, 0)); + for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) { + const auto& scope = GetScope(iscope); + scope.SaveState(*data); + } + + SaveExtendedScopes(*data); + + // save all this in the data section of the dictionary + CFDictionarySetValue(*dict, kDataString, *data); + data = nullptr; // data can be large-ish, so destroy it now. + + // OK - now we're going to do some properties + // save the preset name... + CFDictionarySetValue(*dict, kNameString, mCurrentPreset.presetName); + + // Does the unit support the RenderQuality property - if so, save it... + OSStatus result = + DispatchGetProperty(kAudioUnitProperty_RenderQuality, kAudioUnitScope_Global, 0, &value); + + if (result == noErr) { + AddNumToDictionary(*dict, kRenderQualityString, value); + } + + // Do we have any element names for any of our scopes? + // first check to see if we have any names... + bool foundName = false; + for (AudioUnitScope i = 0; i < kNumScopes; ++i) { + foundName = GetScope(i).HasElementWithName(); + if (foundName) { + break; + } + } + // OK - we found a name away we go... + if (foundName) { + auto nameDict = Owned::from_create(CFDictionaryCreateMutable( + nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + for (AudioUnitScope i = 0; i < kNumScopes; ++i) { + GetScope(i).AddElementNamesToDict(*nameDict); + } + + CFDictionarySetValue(*dict, kElementNameString, *nameDict); + } + + // we're done!!! + *outData = static_cast(dict.release()); // transfer ownership + + return noErr; +} + +//_____________________________________________________________________________ +// +// NOLINTNEXTLINE(misc-no-recursion) with DispatchSetProperty +OSStatus AUBase::RestoreState(CFPropertyListRef plist) +{ + if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) { + return kAudioUnitErr_InvalidPropertyValue; + } + + const AudioComponentDescription desc = GetComponentDescription(); + + const auto* const dict = static_cast(plist); + + // zeroeth step - make sure the Part key is NOT present, as this method is used + // to restore the GLOBAL state of the dictionary + if (CFDictionaryContainsKey(dict, kPartString)) { + return kAudioUnitErr_InvalidPropertyValue; + } + + // first step -> check the saved version in the data ref + // at this point we're only dealing with version==0 + const auto* cfnum = static_cast(CFDictionaryGetValue(dict, kVersionString)); + AUSDK_Require(cfnum != nullptr, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(CFGetTypeID(cfnum) == CFNumberGetTypeID(), kAudioUnitErr_InvalidPropertyValue); + SInt32 value = 0; + CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); + if (value != kCurrentSavedStateVersion) { + return kAudioUnitErr_InvalidPropertyValue; + } + + // second step -> check that this data belongs to this kind of audio unit + // by checking the component subtype and manuID + // We're not checking the type, since there may be different versions (effect, format-converter, + // offline) of essentially the same AU + cfnum = static_cast(CFDictionaryGetValue(dict, kSubtypeString)); + AUSDK_Require(cfnum != nullptr, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(CFGetTypeID(cfnum) == CFNumberGetTypeID(), kAudioUnitErr_InvalidPropertyValue); + CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); + if (static_cast(value) != desc.componentSubType) { + return kAudioUnitErr_InvalidPropertyValue; + } + + cfnum = static_cast(CFDictionaryGetValue(dict, kManufacturerString)); + AUSDK_Require(cfnum != nullptr, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(CFGetTypeID(cfnum) == CFNumberGetTypeID(), kAudioUnitErr_InvalidPropertyValue); + CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); + if (static_cast(value) != desc.componentManufacturer) { + return kAudioUnitErr_InvalidPropertyValue; + } + + // fourth step -> restore the state of all of the parameters for each scope and element + const auto* const data = static_cast(CFDictionaryGetValue(dict, kDataString)); + if ((data != nullptr) && (CFGetTypeID(data) == CFDataGetTypeID())) { + const UInt8* p = CFDataGetBytePtr(data); + const UInt8* const pend = p + CFDataGetLength(data); // NOLINT + + // we have a zero length data, which may just mean there were no parameters to save! + // if (p >= pend) return noErr; + + while (p < pend) { + const UInt32 scopeIdx = + CFSwapInt32BigToHost(*reinterpret_cast(p)); // NOLINT + p += sizeof(UInt32); // NOLINT + + const auto& scope = GetScope(scopeIdx); + p = scope.RestoreState(p); + } + } + + // OK - now we're going to do some properties + // restore the preset name... + const auto* const name = static_cast(CFDictionaryGetValue(dict, kNameString)); + if (mCurrentPreset.presetName != nullptr) { + CFRelease(mCurrentPreset.presetName); + } + if ((name != nullptr) && (CFGetTypeID(name) == CFStringGetTypeID())) { + mCurrentPreset.presetName = name; + mCurrentPreset.presetNumber = -1; + } else { // no name entry make the default one + mCurrentPreset.presetName = kUntitledString; + mCurrentPreset.presetNumber = -1; + } + + CFRetain(mCurrentPreset.presetName); + PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0); + + // Does the dict contain render quality information? + cfnum = static_cast(CFDictionaryGetValue(dict, kRenderQualityString)); + if (cfnum && (CFGetTypeID(cfnum) == CFNumberGetTypeID())) { + CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); + DispatchSetProperty( + kAudioUnitProperty_RenderQuality, kAudioUnitScope_Global, 0, &value, sizeof(value)); + } + + // Do we have any element names for any of our scopes? + const auto nameDict = + static_cast(CFDictionaryGetValue(dict, kElementNameString)); + if (nameDict && (CFGetTypeID(nameDict) == CFDictionaryGetTypeID())) { + for (AudioUnitScope i = 0; i < kNumScopes; ++i) { + const CFStringRef key = CFStringCreateWithFormat( + nullptr, nullptr, CFSTR("%u"), static_cast(i)); // NOLINT + const auto elementDict = + static_cast(CFDictionaryGetValue(nameDict, key)); + if (elementDict && (CFGetTypeID(elementDict) == CFDictionaryGetTypeID())) { + const auto restoredElements = GetScope(i).RestoreElementNames(elementDict); + for (const auto& element : restoredElements) { + PropertyChanged(kAudioUnitProperty_ElementName, i, element); + } + } + CFRelease(key); + } + } + + return noErr; +} + +OSStatus AUBase::GetPresets(CFArrayRef* /*outData*/) const { return kAudioUnitErr_InvalidProperty; } + +OSStatus AUBase::NewFactoryPresetSet(const AUPreset& /*inNewFactoryPreset*/) +{ + return kAudioUnitErr_InvalidProperty; +} + +OSStatus AUBase::NewCustomPresetSet(const AUPreset& inNewCustomPreset) +{ + CFRelease(mCurrentPreset.presetName); + mCurrentPreset = inNewCustomPreset; + CFRetain(mCurrentPreset.presetName); + return noErr; +} + +// set the default preset for the unit -> the number of the preset MUST be >= 0 +// and the name should be valid, or the preset WON'T take +bool AUBase::SetAFactoryPresetAsCurrent(const AUPreset& inPreset) +{ + if (inPreset.presetNumber < 0 || inPreset.presetName == nullptr) { + return false; + } + CFRelease(mCurrentPreset.presetName); + mCurrentPreset = inPreset; + CFRetain(mCurrentPreset.presetName); + return true; +} + +bool AUBase::HasIcon() +{ + const CFURLRef url = CopyIconLocation(); + if (url != nullptr) { + CFRelease(url); + return true; + } + return false; +} + +CFURLRef AUBase::CopyIconLocation() { return nullptr; } + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetParameterList( + AudioUnitScope inScope, AudioUnitParameterID* outParameterList, UInt32& outNumParameters) +{ + const auto& scope = GetScope(inScope); + AUElement* elementWithMostParameters = nullptr; + UInt32 maxNumParams = 0; + + const UInt32 nElems = scope.GetNumberOfElements(); + for (UInt32 ielem = 0; ielem < nElems; ++ielem) { + AUElement* const element = scope.GetElement(ielem); + const UInt32 nParams = element->GetNumberOfParameters(); + if (nParams > maxNumParams) { + maxNumParams = nParams; + elementWithMostParameters = element; + } + } + + if (outParameterList != nullptr && elementWithMostParameters != nullptr) { + elementWithMostParameters->GetParameterList(outParameterList); + } + + outNumParameters = maxNumParams; + return noErr; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetParameterInfo(AudioUnitScope /*inScope*/, + AudioUnitParameterID /*inParameterID*/, AudioUnitParameterInfo& /*outParameterInfo*/) +{ + return kAudioUnitErr_InvalidParameter; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetParameterValueStrings( + AudioUnitScope /*inScope*/, AudioUnitParameterID /*inParameterID*/, CFArrayRef* /*outStrings*/) +{ + return kAudioUnitErr_InvalidProperty; +} + +//_____________________________________________________________________________ +// +OSStatus AUBase::GetParameterHistoryInfo(AudioUnitScope /*inScope*/, + AudioUnitParameterID /*inParameterID*/, Float32& /*outUpdatesPerSecond*/, + Float32& /*outHistoryDurationInSeconds*/) +{ + return kAudioUnitErr_InvalidProperty; +} + + +//_____________________________________________________________________________ +// +OSStatus AUBase::CopyClumpName(AudioUnitScope /*inScope*/, UInt32 /*inClumpID*/, + UInt32 /*inDesiredNameLength*/, CFStringRef* /*outClumpName*/) +{ + return kAudioUnitErr_InvalidProperty; +} + +//_____________________________________________________________________________ +// +void AUBase::SetNumberOfElements(AudioUnitScope inScope, UInt32 numElements) +{ + if (inScope == kAudioUnitScope_Global && numElements != 1) { + Throw(kAudioUnitErr_InvalidScope); + } + + GetScope(inScope).SetNumberOfElements(numElements); +} + +//_____________________________________________________________________________ +// +std::unique_ptr AUBase::CreateElement(AudioUnitScope scope, AudioUnitElement /*element*/) +{ + switch (scope) { + case kAudioUnitScope_Global: + return std::make_unique(*this); + case kAudioUnitScope_Input: + return std::make_unique(*this); + case kAudioUnitScope_Output: + return std::make_unique(*this); + case kAudioUnitScope_Group: + case kAudioUnitScope_Part: + return std::make_unique(*this); + default: + break; + } + Throw(kAudioUnitErr_InvalidScope); +} + +const char* AUBase::GetLoggingString() const noexcept { return mLogString.c_str(); } + +std::string AUBase::CreateLoggingString() const +{ + const auto desc = GetComponentDescription(); + std::array buf{}; + [[maybe_unused]] const int printCount = + snprintf(buf.data(), buf.size(), "AU (%p): ", GetComponentInstance()); // NOLINT +#if DEBUG + assert(printCount < static_cast(buf.size())); +#endif + return buf.data() + make_string_from_4cc(desc.componentType) + '/' + + make_string_from_4cc(desc.componentSubType) + '/' + + make_string_from_4cc(desc.componentManufacturer); +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.h new file mode 100644 index 0000000000..02f0d3d827 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.h @@ -0,0 +1,733 @@ +/*! + @file AudioUnitSDK/AUBase.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ + +#ifndef AudioUnitSDK_AUBase_h +#define AudioUnitSDK_AUBase_h + +// module +#include +#include +#include +#include +#include +#include +#include + +// OS +#include + +// std +#include +#include +#include +#include +#include +#include + +// ________________________________________________________________________ + +namespace ausdk { + +/*! + @class AUBase + @brief Abstract base class for an Audio Unit implementation. +*/ +class AUBase : public ComponentBase { +public: + constexpr static double kAUDefaultSampleRate = 44100.0; +#if !TARGET_OS_WIN32 + constexpr static UInt32 kAUDefaultMaxFramesPerSlice = 1156; + // this allows enough default frames for a 512 dest 44K and SRC from 96K + // add a padding of 4 frames for any vector rounding +#else + constexpr static UInt32 kAUDefaultMaxFramesPerSlice = 2048; +#endif + + AUBase(AudioComponentInstance inInstance, UInt32 numInputElements, UInt32 numOutputElements, + UInt32 numGroupElements = 0); + ~AUBase() override; + + AUBase(const AUBase&) = delete; + AUBase(AUBase&&) = delete; + AUBase& operator=(const AUBase&) = delete; + AUBase& operator=(AUBase&&) = delete; + + /// Called immediately after construction, when virtual methods work. Or, a subclass may call + /// this in order to have access to elements in its constructor. + void CreateElements(); + + virtual void CreateExtendedElements() {} + +#pragma mark - +#pragma mark AU dispatch + // ________________________________________________________________________ + // Virtual methods (mostly) directly corresponding to the entry points. Many of these + // have useful implementations here and will not need overriding. + + /// Implements the entry point and ensures that Initialize is called exactly once from an + /// uninitialized state. + OSStatus DoInitialize(); + + // Overrides to this method can assume that they will only be called exactly once + // when transitioning from an uninitialized state. + virtual OSStatus Initialize(); + + [[nodiscard]] bool IsInitialized() const noexcept { return mInitialized; } + [[nodiscard]] bool HasBegunInitializing() const noexcept { return mHasBegunInitializing; } + + /// Implements the entry point and ensures that Cleanup is called exactly once from an + /// initialized state. + void DoCleanup(); + + // Overrides to this method can assume that they will only be called exactly once + // when transitioning from an initialized state to an uninitialized state. + virtual void Cleanup(); + + virtual OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement); + + // Note about GetPropertyInfo, GetProperty, SetProperty: + // Certain properties are trapped out in these dispatch functions and handled with different + // virtual methods. (To discourage hacks and keep vtable size down, these are non-virtual) + + OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable); + OSStatus DispatchGetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData); + OSStatus DispatchSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize); + OSStatus DispatchRemovePropertyValue( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement); + + virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable); + virtual OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData); + virtual OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize); + virtual OSStatus RemovePropertyValue( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement); + + virtual OSStatus AddPropertyListener( + AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc, void* inProcRefCon); + virtual OSStatus RemovePropertyListener(AudioUnitPropertyID inID, + AudioUnitPropertyListenerProc inProc, void* inProcRefCon, bool refConSpecified); + + virtual OSStatus SetRenderNotification(AURenderCallback inProc, void* inRefCon); + virtual OSStatus RemoveRenderNotification(AURenderCallback inProc, void* inRefCon); + + virtual OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope inScope, + AudioUnitElement inElement, AudioUnitParameterValue& outValue); + virtual OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope inScope, + AudioUnitElement inElement, AudioUnitParameterValue inValue, UInt32 inBufferOffsetInFrames); + + [[nodiscard]] virtual bool CanScheduleParameters() const = 0; + virtual OSStatus ScheduleParameter( + const AudioUnitParameterEvent* inParameterEvent, UInt32 inNumEvents); + + OSStatus DoRender(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, + UInt32 inBusNumber, UInt32 inFramesToProcess, AudioBufferList& ioData); + OSStatus DoProcess(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, + UInt32 inFramesToProcess, AudioBufferList& ioData); + OSStatus DoProcessMultiple(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 inFramesToProcess, + UInt32 inNumberInputBufferLists, const AudioBufferList** inInputBufferLists, + UInt32 inNumberOutputBufferLists, AudioBufferList** ioOutputBufferLists); + + virtual OSStatus ProcessBufferLists(AudioUnitRenderActionFlags& /*ioActionFlags*/, + const AudioBufferList& /*inBuffer*/, AudioBufferList& /*outBuffer*/, + UInt32 /*inFramesToProcess*/) + { + return kAudio_UnimplementedError; + } + + virtual OSStatus ProcessMultipleBufferLists(AudioUnitRenderActionFlags& /*ioActionFlags*/, + UInt32 /*inFramesToProcess*/, UInt32 /*inNumberInputBufferLists*/, + const AudioBufferList** /*inInputBufferLists*/, UInt32 /*inNumberOutputBufferLists*/, + AudioBufferList** /*ioOutputBufferLists*/) + { + return kAudio_UnimplementedError; + } + + virtual OSStatus ComplexRender(AudioUnitRenderActionFlags& /*ioActionFlags*/, + const AudioTimeStamp& /*inTimeStamp*/, UInt32 /*inOutputBusNumber*/, + UInt32 /*inNumberOfPackets*/, UInt32* /*outNumberOfPackets*/, + AudioStreamPacketDescription* /*outPacketDescriptions*/, AudioBufferList& /*ioData*/, + void* /*outMetadata*/, UInt32* /*outMetadataByteSize*/) + { + return kAudio_UnimplementedError; + } + + // Override this method if your AU processes multiple output busses completely independently -- + // you'll want to just call Render without the NeedsToRender check. + // Otherwise, override Render(). + // + // N.B. Implementations of this method can assume that the output's buffer list has already been + // prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of + // GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a + // copy may occur after rendering. + virtual OSStatus RenderBus(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 /*inBusNumber*/, UInt32 inNumberFrames) + { + if (NeedsToRender(inTimeStamp)) { + return Render(ioActionFlags, inTimeStamp, inNumberFrames); + } + return noErr; // was presumably already rendered via another bus + } + + // N.B. For a unit with only one output bus, it can assume in its implementation of this + // method that the output's buffer list has already been prepared and access it with + // GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames) + // -- if PrepareBuffer is called, a copy may occur after rendering. + virtual OSStatus Render(AudioUnitRenderActionFlags& /*ioActionFlags*/, + const AudioTimeStamp& /*inTimeStamp*/, UInt32 /*inNumberFrames*/) + { + return noErr; + } + + +#pragma mark - +#pragma mark Property Dispatch + + // ________________________________________________________________________ + // These are called from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty + + virtual bool BusCountWritable(AudioUnitScope /*inScope*/) { return false; } + virtual OSStatus SetBusCount(AudioUnitScope inScope, UInt32 inCount); + virtual OSStatus SetConnection(const AudioUnitConnection& inConnection); + virtual OSStatus SetInputCallback( + UInt32 inPropertyID, AudioUnitElement inElement, AURenderCallback inProc, void* inRefCon); + + virtual OSStatus GetParameterList( + AudioUnitScope inScope, AudioUnitParameterID* outParameterList, UInt32& outNumParameters); + // outParameterList may be a null pointer + virtual OSStatus GetParameterInfo(AudioUnitScope inScope, AudioUnitParameterID inParameterID, + AudioUnitParameterInfo& outParameterInfo); + + virtual OSStatus GetParameterHistoryInfo(AudioUnitScope inScope, + AudioUnitParameterID inParameterID, Float32& outUpdatesPerSecond, + Float32& outHistoryDurationInSeconds); + virtual OSStatus SaveState(CFPropertyListRef* outData); + virtual void SaveExtendedScopes(CFMutableDataRef /*outData*/) {} + virtual OSStatus RestoreState(CFPropertyListRef plist); + virtual OSStatus GetParameterValueStrings( + AudioUnitScope inScope, AudioUnitParameterID inParameterID, CFArrayRef* outStrings); + virtual OSStatus CopyClumpName(AudioUnitScope inScope, UInt32 inClumpID, + UInt32 inDesiredNameLength, CFStringRef* outClumpName); + virtual OSStatus GetPresets(CFArrayRef* outData) const; + + /// Set the default preset for the unit. The number of the preset must be >= 0 and the name + /// should be valid, or the preset will be rejected. + bool SetAFactoryPresetAsCurrent(const AUPreset& inPreset); + + // Called when the host sets a new, valid preset. + // If this is a valid preset, then the subclass sets its state to that preset + // and returns noErr. + // If not a valid preset, return an error, and the pre-existing preset is restored. + virtual OSStatus NewFactoryPresetSet(const AUPreset& inNewFactoryPreset); + virtual OSStatus NewCustomPresetSet(const AUPreset& inNewCustomPreset); + virtual CFURLRef CopyIconLocation(); + + // default is no latency, and unimplemented tail time + virtual Float64 GetLatency() { return 0.0; } + virtual Float64 GetTailTime() { return 0.0; } + virtual bool SupportsTail() { return false; } + + // Stream formats: scope will always be input or output + bool IsStreamFormatWritable(AudioUnitScope scope, AudioUnitElement element); + + virtual bool StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) = 0; + + // pass in a pointer to get the struct, and num channel infos + // you can pass in NULL to just get the number + // a return value of 0 (the default in AUBase) means the property is not supported... + virtual UInt32 SupportedNumChannels(const AUChannelInfo** outInfo); + + /// Will only be called after StreamFormatWritable has succeeded. Default implementation + /// requires non-interleaved native-endian 32-bit float, any sample rate, any number of + /// channels; override when other formats are supported. A subclass's override can choose to + /// always return true and trap invalid formats in ChangeStreamFormat. + virtual bool ValidFormat(AudioUnitScope inScope, AudioUnitElement inElement, + const AudioStreamBasicDescription& inNewFormat); + + virtual AudioStreamBasicDescription GetStreamFormat( + AudioUnitScope inScope, AudioUnitElement inElement); + + // Will only be called after StreamFormatWritable + // and ValidFormat have succeeded. + virtual OSStatus ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement, + const AudioStreamBasicDescription& inPrevFormat, + const AudioStreamBasicDescription& inNewFormat); + + // ________________________________________________________________________ + // Methods useful for subclasses + AUScope& GetScope(AudioUnitScope inScope) + { + if (inScope >= kNumScopes) { + AUScope* const scope = GetScopeExtended(inScope); + + ThrowQuietIf(scope == nullptr, kAudioUnitErr_InvalidScope); + return *scope; + } + return mScopes[inScope]; // NOLINT + } + + virtual AUScope* GetScopeExtended(AudioUnitScope /*inScope*/) { return nullptr; } + + AUScope& GlobalScope() { return mScopes[kAudioUnitScope_Global]; } + AUScope& Inputs() { return mScopes[kAudioUnitScope_Input]; } + AUScope& Outputs() { return mScopes[kAudioUnitScope_Output]; } + AUScope& Groups() { return mScopes[kAudioUnitScope_Group]; } + AUElement* Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); } + + void SetNumberOfElements(AudioUnitScope inScope, UInt32 numElements); + virtual std::unique_ptr CreateElement( + AudioUnitScope scope, AudioUnitElement element); + + AUElement* GetElement(AudioUnitScope inScope, AudioUnitElement inElement) + { + return GetScope(inScope).GetElement(inElement); + } + + AUSDK_DEPRECATED("Use IOElement()") + AUIOElement* GetIOElement(AudioUnitScope inScope, AudioUnitElement inElement) + { + return &IOElement(inScope, inElement); + } + + AUIOElement& IOElement(AudioUnitScope inScope, AudioUnitElement inElement) + { + return *GetScope(inScope).GetIOElement(inElement); + } + + AUSDK_DEPRECATED("Use Element()") + AUElement* SafeGetElement(AudioUnitScope inScope, AudioUnitElement inElement) + { + return &Element(inScope, inElement); + } + + AUElement& Element(AudioUnitScope inScope, AudioUnitElement inElement) + { + return *GetScope(inScope).SafeGetElement(inElement); + } + + AUSDK_DEPRECATED("Use Input()") + AUInputElement* GetInput(AudioUnitElement inElement) { return &Input(inElement); } + AUInputElement& Input(AudioUnitElement inElement) + { + return static_cast(*Inputs().SafeGetElement(inElement)); // NOLINT downcast + } + + AUSDK_DEPRECATED("Use Output()") + AUOutputElement* GetOutput(AudioUnitElement inElement) { return &Output(inElement); } + AUOutputElement& Output(AudioUnitElement inElement) + { + return static_cast( // NOLINT downcast + *Outputs().SafeGetElement(inElement)); + } + + AUSDK_DEPRECATED("Use Group()") + AUElement* GetGroup(AudioUnitElement inElement) { return &Group(inElement); } + AUElement& Group(AudioUnitElement inElement) { return *Groups().SafeGetElement(inElement); } + + OSStatus PullInput(UInt32 inBusNumber, AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 inNumberFrames) + { + AUInputElement& input = Input(inBusNumber); // throws if error + return input.PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames); + } + + [[nodiscard]] UInt32 GetMaxFramesPerSlice() const noexcept { return mMaxFramesPerSlice; } + + [[nodiscard]] bool UsesFixedBlockSize() const noexcept { return mUsesFixedBlockSize; } + + void SetUsesFixedBlockSize(bool inUsesFixedBlockSize) noexcept + { + mUsesFixedBlockSize = inUsesFixedBlockSize; + } + + [[nodiscard]] virtual bool InRenderThread() const + { + return std::this_thread::get_id() == mRenderThreadID; + } + + /// Says whether an input is connected or has a callback. + bool HasInput(AudioUnitElement inElement) + { + auto* const in = + static_cast(Inputs().GetElement(inElement)); // NOLINT downcast + return in != nullptr && in->IsActive(); + } + + virtual void PropertyChanged( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement); + + // These calls can be used to call a Host's Callbacks. The method returns -1 if the host + // hasn't supplied the callback. Any other result is returned by the host. + // As in the API contract, for a parameter's value, you specify a pointer + // to that data type. Specify NULL for a parameter that you are not interested + // as this can save work in the host. + OSStatus CallHostBeatAndTempo(Float64* outCurrentBeat, Float64* outCurrentTempo) const + { + return (mHostCallbackInfo.beatAndTempoProc != nullptr + ? (*mHostCallbackInfo.beatAndTempoProc)( + mHostCallbackInfo.hostUserData, outCurrentBeat, outCurrentTempo) + : -1); + } + + OSStatus CallHostMusicalTimeLocation(UInt32* outDeltaSampleOffsetToNextBeat, + Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator, + Float64* outCurrentMeasureDownBeat) const + { + return (mHostCallbackInfo.musicalTimeLocationProc != nullptr + ? (*mHostCallbackInfo.musicalTimeLocationProc)(mHostCallbackInfo.hostUserData, + outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator, + outTimeSig_Denominator, outCurrentMeasureDownBeat) + : -1); + } + + OSStatus CallHostTransportState(Boolean* outIsPlaying, Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, Float64* outCycleStartBeat, + Float64* outCycleEndBeat) const + { + return (mHostCallbackInfo.transportStateProc != nullptr + ? (*mHostCallbackInfo.transportStateProc)(mHostCallbackInfo.hostUserData, + outIsPlaying, outTransportStateChanged, outCurrentSampleInTimeLine, + outIsCycling, outCycleStartBeat, outCycleEndBeat) + : -1); + } + + [[nodiscard]] const char* GetLoggingString() const noexcept; + + AUMutex* GetMutex() noexcept { return mAUMutex; } + // The caller of SetMutex is responsible for the managing the lifetime of the + // mutex object and, if deleted before the AUBase instance, is responsible + // for calling SetMutex(nullptr) + void SetMutex(AUMutex* mutex) noexcept { mAUMutex = mutex; } + +#pragma mark - +#pragma mark AU Output Base Dispatch + // ________________________________________________________________________ + // ________________________________________________________________________ + // ________________________________________________________________________ + // output unit methods + virtual OSStatus Start() { return kAudio_UnimplementedError; } + + virtual OSStatus Stop() { return kAudio_UnimplementedError; } + +#pragma mark - +#pragma mark AU Music Base Dispatch + // ________________________________________________________________________ + // ________________________________________________________________________ + // ________________________________________________________________________ + // music device/music effect methods + + virtual OSStatus MIDIEvent( + UInt32 /*inStatus*/, UInt32 /*inData1*/, UInt32 /*inData2*/, UInt32 /*inOffsetSampleFrame*/) + { + return kAudio_UnimplementedError; + } + + virtual OSStatus SysEx(const UInt8* /*inData*/, UInt32 /*inLength*/) + { + return kAudio_UnimplementedError; + } + +#if AUSDK_MIDI2_AVAILABLE + virtual OSStatus MIDIEventList( + UInt32 /*inOffsetSampleFrame*/, const MIDIEventList* /*eventList*/) + { + return kAudio_UnimplementedError; + } +#endif + + virtual OSStatus StartNote(MusicDeviceInstrumentID /*inInstrument*/, + MusicDeviceGroupID /*inGroupID*/, NoteInstanceID* /*outNoteInstanceID*/, + UInt32 /*inOffsetSampleFrame*/, const MusicDeviceNoteParams& /*inParams*/) + { + return kAudio_UnimplementedError; + } + + virtual OSStatus StopNote(MusicDeviceGroupID /*inGroupID*/, NoteInstanceID /*inNoteInstanceID*/, + UInt32 /*inOffsetSampleFrame*/) + { + return kAudio_UnimplementedError; + } + + /// Obsolete + static OSStatus PrepareInstrument(MusicDeviceInstrumentID /*inInstrument*/) + { + return kAudio_UnimplementedError; + } + + /// Obsolete + static OSStatus ReleaseInstrument(MusicDeviceInstrumentID /*inInstrument*/) + { + return kAudio_UnimplementedError; + } + + // ________________________________________________________________________ + // ________________________________________________________________________ + // ________________________________________________________________________ + +protected: +#pragma mark - +#pragma mark Implementation methods + void PostConstructorInternal() final; + void PreDestructorInternal() final; + + /// needs to be called when mMaxFramesPerSlice changes + virtual void ReallocateBuffers(); + + virtual void DeallocateIOBuffers(); + + static void FillInParameterName( + AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease) + { + ioInfo.cfNameString = inName; + ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString; + if (inShouldRelease) { + ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease; + } + CFStringGetCString(inName, &ioInfo.name[0], offsetof(AudioUnitParameterInfo, clumpID), + kCFStringEncodingUTF8); + } + + static void HasClump(AudioUnitParameterInfo& ioInfo, UInt32 inClumpID) noexcept + { + ioInfo.clumpID = inClumpID; + ioInfo.flags |= kAudioUnitParameterFlag_HasClump; + } + + virtual void SetMaxFramesPerSlice(UInt32 nFrames); + + [[nodiscard]] virtual OSStatus CanSetMaxFrames() const; + + [[nodiscard]] bool WantsRenderThreadID() const noexcept { return mWantsRenderThreadID; } + + void SetWantsRenderThreadID(bool inFlag); + + OSStatus SetRenderError(OSStatus inErr) + { + if (inErr != noErr && mLastRenderError == 0) { + mLastRenderError = inErr; + PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0); + } + return inErr; + } + + struct PropertyListener { + AudioUnitPropertyID propertyID{ 0 }; + AudioUnitPropertyListenerProc listenerProc{ nullptr }; + void* listenerRefCon{ nullptr }; + }; + using PropertyListeners = std::vector; + + [[nodiscard]] const PropertyListeners& GetPropertyListeners() const noexcept + { + return mPropertyListeners; + } + + HostCallbackInfo& GetHostCallbackInfo() noexcept { return mHostCallbackInfo; } + +private: + // shared between Render and RenderSlice, inlined to minimize function call overhead + OSStatus DoRenderBus(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, UInt32 inBusNumber, AUOutputElement& theOutput, + UInt32 inNumberFrames, AudioBufferList& ioData) + { + if (ioData.mBuffers[0].mData == nullptr || + (theOutput.WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1)) { + // will render into cache buffer + theOutput.PrepareBuffer(inNumberFrames); + } else { + // will render into caller's buffer + theOutput.SetBufferList(ioData); + } + const OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames); + if (result == noErr) { + if (ioData.mBuffers[0].mData == nullptr) { + theOutput.CopyBufferListTo(ioData); + } else { + theOutput.CopyBufferContentsTo(ioData); + theOutput.InvalidateBufferList(); + } + } + return result; + } + + bool HasIcon(); + + [[nodiscard]] std::string CreateLoggingString() const; + +protected: + //. Returns size. outLayoutPtr may be null if querying only for size. + virtual UInt32 GetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, + AudioChannelLayout* outLayoutPtr, bool& outWritable); + + /// Layout is non-null. + virtual OSStatus SetAudioChannelLayout( + AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout); + + virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element); + + virtual std::vector GetChannelLayoutTags( + AudioUnitScope scope, AudioUnitElement element); + + bool NeedsToRender(const AudioTimeStamp& inTimeStamp) + { + const bool needsToRender = (inTimeStamp.mSampleTime != mCurrentRenderTime.mSampleTime); + if (needsToRender) { // only copy this if we need to render + mCurrentRenderTime = inTimeStamp; + } + return needsToRender; + } + + // Scheduled parameter implementation: + + using ParameterEventList = std::vector; + + // Usually, you won't override this method. You only need to call this if your DSP code + // is prepared to handle scheduled immediate and ramped parameter changes. + // Before calling this method, it is assumed you have already called PullInput() on the input + // busses for which the DSP code depends. ProcessForScheduledParams() will call (potentially + // repeatedly) virtual method ProcessScheduledSlice() to perform the actual DSP for a given + // sub-division of the buffer. The job of ProcessForScheduledParams() is to sub-divide the + // buffer into smaller pieces according to the scheduled times found in the ParameterEventList + // (usually coming directly from a previous call to ScheduleParameter() ), setting the + // appropriate immediate or ramped parameter values for the corresponding scopes and elements, + // then calling ProcessScheduledSlice() to do the actual DSP for each of these divisions. + virtual OSStatus ProcessForScheduledParams( + ParameterEventList& inParamList, UInt32 inFramesToProcess, void* inUserData); + + // This method is called (potentially repeatedly) by ProcessForScheduledParams() + // in order to perform the actual DSP required for this portion of the entire buffer + // being processed. The entire buffer can be divided up into smaller "slices" + // according to the timestamps on the scheduled parameters... + // + // sub-classes wishing to handle scheduled parameter changes should override this method + // in order to do the appropriate DSP. AUEffectBase already overrides this for standard + // effect AudioUnits. + virtual OSStatus ProcessScheduledSlice(void* /*inUserData*/, UInt32 /*inStartFrameInBuffer*/, + UInt32 /*inSliceFramesToProcess*/, UInt32 /*inTotalBufferFrames*/) + { + // default implementation does nothing. + return noErr; + } + + [[nodiscard]] const AudioTimeStamp& CurrentRenderTime() const noexcept + { + return mCurrentRenderTime; + } + void ResetRenderTime(); + + // ________________________________________________________________________ + // Private data members to discourage hacking in subclasses +private: + struct RenderCallback { + RenderCallback() = default; + + RenderCallback(AURenderCallback proc, void* ref) + : mRenderNotify(proc), mRenderNotifyRefCon(ref) + { + } + + AURenderCallback mRenderNotify = nullptr; + void* mRenderNotifyRefCon = nullptr; + + bool operator==(const RenderCallback& other) const + { + return this->mRenderNotify == other.mRenderNotify && + this->mRenderNotifyRefCon == other.mRenderNotifyRefCon; + } + }; + + class RenderCallbackList { + public: + void add(const RenderCallback& rc) + { + const std::lock_guard guard{ mLock }; + const auto iter = std::find(mImpl.begin(), mImpl.end(), rc); + if (iter != mImpl.end()) { + return; + } + mImpl.emplace_back(rc); + } + + void remove(const RenderCallback& rc) + { + const std::lock_guard guard{ mLock }; + const auto iter = std::find(mImpl.begin(), mImpl.end(), rc); + if (iter != mImpl.end()) { + mImpl.erase(iter); + } + } + + template + void foreach (F&& func) + { + const std::lock_guard guard{ mLock }; + for (const auto& cb : mImpl) { + func(cb); + } + } + + private: + AUMutex mLock; + std::vector mImpl; + }; + +protected: + static constexpr AudioUnitScope kNumScopes = 4; + + ParameterEventList& GetParamEventList() noexcept { return mParamEventList; } + void SetBuffersAllocated(bool b) noexcept { mBuffersAllocated = b; } + + [[nodiscard]] CFStringRef GetContextName() const { return *mContextName; } + void SetContextName(CFStringRef str) { mContextName = str; } + + [[nodiscard]] CFStringRef GetNickName() const { return *mNickName; } + +private: + bool mElementsCreated{ false }; + bool mInitialized{ false }; + bool mHasBegunInitializing{ false }; + const UInt32 mInitNumInputEls; + const UInt32 mInitNumOutputEls; + const UInt32 mInitNumGroupEls; + std::array mScopes; + RenderCallbackList mRenderCallbacks; + bool mRenderCallbacksTouched{ false }; + std::thread::id mRenderThreadID{}; + bool mWantsRenderThreadID{ false }; + AudioTimeStamp mCurrentRenderTime{}; + UInt32 mMaxFramesPerSlice{ 0 }; + OSStatus mLastRenderError{ noErr }; +#ifndef AUSDK_NO_LOGGING + const double mHostTimeFrequency{ + HostTime::Frequency() + }; // cache because there is calculation cost +#endif + AUPreset mCurrentPreset{ -1, nullptr }; + bool mUsesFixedBlockSize{ false }; + + ParameterEventList mParamEventList; + PropertyListeners mPropertyListeners; + bool mBuffersAllocated{ false }; + const std::string mLogString; + Owned mNickName; + + /*! @var mAUMutex + If non-null, guards all non-realtime entry points into the AudioUnit. Most AudioUnits + do not need to use this. It's useful for the case of an AU which must synchronize + an external source of callbacks against entry from the host. + */ + AUMutex* mAUMutex{ nullptr }; + HostCallbackInfo mHostCallbackInfo{}; + Owned mContextName; +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUBase_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.cpp new file mode 100644 index 0000000000..b62dfbf491 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.cpp @@ -0,0 +1,188 @@ +/*! + @file AudioUnitSDK/AUBuffer.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include +#include + +namespace ausdk { + +inline void ThrowBadAlloc() +{ + AUSDK_LogError("AUBuffer throwing bad_alloc"); + throw std::bad_alloc(); +} + +// x: number to be rounded; y: the power of 2 to which to round +constexpr uint32_t RoundUpToMultipleOfPowerOf2(uint32_t x, uint32_t y) noexcept +{ + const auto mask = y - 1; +#if DEBUG + assert((mask & y) == 0u); // verifies that y is a power of 2 NOLINT +#endif + return (x + mask) & ~mask; +} + +// 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) { // NOLINT magic + ThrowBadAlloc(); + } + + return a * b + c; +} + +AllocatedBuffer* BufferAllocator::Allocate( + UInt32 numberBuffers, UInt32 maxBytesPerBuffer, UInt32 /*reservedFlags*/) +{ + constexpr size_t kAlignment = 16; + constexpr size_t kMaxBufferListSize = 65536; + + // Check for a reasonable number of buffers (obviate a more complicated check with offsetof). + if (numberBuffers > kMaxBufferListSize / sizeof(AudioBuffer)) { + throw std::out_of_range("AudioBuffers::Allocate: Too many buffers"); + } + + maxBytesPerBuffer = RoundUpToMultipleOfPowerOf2(maxBytesPerBuffer, kAlignment); + + const auto bufferDataSize = SafeMultiplyAddUInt32(numberBuffers, maxBytesPerBuffer, 0); + void* bufferData = nullptr; + if (bufferDataSize > 0) { + bufferData = malloc(bufferDataSize); + // don't use calloc(); it might not actually touch the memory and cause a VM fault later + memset(bufferData, 0, bufferDataSize); + } + + const auto implSize = static_cast( + offsetof(AllocatedBuffer, mAudioBufferList.mBuffers[std::max(UInt32(1), numberBuffers)])); + auto* const implMem = malloc(implSize); + auto* const allocatedBuffer = + new (implMem) AllocatedBuffer{ .mMaximumNumberBuffers = numberBuffers, + .mMaximumBytesPerBuffer = maxBytesPerBuffer, + .mHeaderSize = implSize, + .mBufferDataSize = bufferDataSize, + .mBufferData = bufferData }; + allocatedBuffer->mAudioBufferList.mNumberBuffers = numberBuffers; + return allocatedBuffer; +} + +void BufferAllocator::Deallocate(AllocatedBuffer* allocatedBuffer) +{ + if (allocatedBuffer->mBufferData != nullptr) { + free(allocatedBuffer->mBufferData); + } + allocatedBuffer->~AllocatedBuffer(); + free(allocatedBuffer); +} + + +AudioBufferList& AllocatedBuffer::Prepare(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer) +{ + if (mAudioBufferList.mNumberBuffers > mMaximumNumberBuffers) { + throw std::out_of_range("AllocatedBuffer::Prepare(): too many buffers"); + } + if (bytesPerBuffer > mMaximumBytesPerBuffer) { + throw std::out_of_range("AllocatedBuffer::Prepare(): insufficient capacity"); + } + + auto* ptr = static_cast(mBufferData); + auto* const ptrend = ptr + mBufferDataSize; + + for (UInt32 bufIdx = 0, nBufs = mAudioBufferList.mNumberBuffers; bufIdx < nBufs; ++bufIdx) { + auto& buf = mAudioBufferList.mBuffers[bufIdx]; // NOLINT + buf.mNumberChannels = channelsPerBuffer; + buf.mDataByteSize = bytesPerBuffer; + buf.mData = ptr; + ptr += mMaximumBytesPerBuffer; // NOLINT ptr math + } + if (ptr > ptrend) { + throw std::out_of_range("AllocatedBuffer::Prepare(): insufficient capacity"); + } + return mAudioBufferList; +} + +AudioBufferList& AllocatedBuffer::PrepareNull(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer) +{ + if (mAudioBufferList.mNumberBuffers > mMaximumNumberBuffers) { + throw std::out_of_range("AllocatedBuffer::PrepareNull(): too many buffers"); + } + for (UInt32 bufIdx = 0, nBufs = mAudioBufferList.mNumberBuffers; bufIdx < nBufs; ++bufIdx) { + auto& buf = mAudioBufferList.mBuffers[bufIdx]; // NOLINT + buf.mNumberChannels = channelsPerBuffer; + buf.mDataByteSize = bytesPerBuffer; + buf.mData = nullptr; + } + return mAudioBufferList; +} + +AudioBufferList& AUBufferList::PrepareBuffer( + const AudioStreamBasicDescription& format, UInt32 nFrames) +{ + ausdk::ThrowExceptionIf(nFrames > mAllocatedFrames, kAudioUnitErr_TooManyFramesToProcess); + + UInt32 nStreams = 0; + UInt32 channelsPerStream = 0; + if (ASBD::IsInterleaved(format)) { + nStreams = 1; + channelsPerStream = format.mChannelsPerFrame; + } else { + nStreams = format.mChannelsPerFrame; + channelsPerStream = 1; + } + + ausdk::ThrowExceptionIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported); + auto& abl = mBuffers->Prepare(channelsPerStream, nFrames * format.mBytesPerFrame); + mPtrState = EPtrState::ToMyMemory; + return abl; +} + +AudioBufferList& AUBufferList::PrepareNullBuffer( + const AudioStreamBasicDescription& format, UInt32 nFrames) +{ + UInt32 nStreams = 0; + UInt32 channelsPerStream = 0; + if (ASBD::IsInterleaved(format)) { + nStreams = 1; + channelsPerStream = format.mChannelsPerFrame; + } else { + nStreams = format.mChannelsPerFrame; + channelsPerStream = 1; + } + + ausdk::ThrowExceptionIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported); + auto& abl = mBuffers->PrepareNull(channelsPerStream, nFrames * format.mBytesPerFrame); + mPtrState = EPtrState::ToExternalMemory; + return abl; +} + +void AUBufferList::Allocate(const AudioStreamBasicDescription& format, UInt32 nFrames) +{ + auto& alloc = BufferAllocator::instance(); + if (mBuffers != nullptr) { + alloc.Deallocate(mBuffers); + } + const uint32_t nstreams = ASBD::IsInterleaved(format) ? 1 : format.mChannelsPerFrame; + mBuffers = alloc.Allocate(nstreams, nFrames * format.mBytesPerFrame, 0u); + mAllocatedFrames = nFrames; + mAllocatedStreams = nstreams; + mPtrState = EPtrState::Invalid; +} + +void AUBufferList::Deallocate() +{ + if (mBuffers != nullptr) { + BufferAllocator::instance().Deallocate(mBuffers); + mBuffers = nullptr; + } + + mAllocatedFrames = 0; + mAllocatedStreams = 0; + mPtrState = EPtrState::Invalid; +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.h new file mode 100644 index 0000000000..df882c9984 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.h @@ -0,0 +1,166 @@ +/*! + @file AudioUnitSDK/AUBuffer.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUBuffer_h +#define AudioUnitSDK_AUBuffer_h + +#include + +#include + +#include +#include + +namespace ausdk { + +/// struct created/destroyed by allocator. Do not attempt to manually create/destroy. +struct AllocatedBuffer { + const UInt32 mMaximumNumberBuffers; + const UInt32 mMaximumBytesPerBuffer; + const UInt32 mReservedA[2]; // NOLINT C-style array + const UInt32 mHeaderSize; + const UInt32 mBufferDataSize; + const UInt32 mReservedB[2]; // NOLINT C-style array + void* const mBufferData; + void* const mReservedC; + + AudioBufferList mAudioBufferList; + // opaque variable-length data may follow the AudioBufferList + + AudioBufferList& Prepare(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer); + AudioBufferList& PrepareNull(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer); +}; + +/*! + @class BufferAllocator + @brief Class which allocates memory for internal audio buffers. + + To customize, create a subclass and install an instance into the global via set_instance(). +*/ +class BufferAllocator { +public: + /// Obtain the global instance, creating it if necessary. + static BufferAllocator& instance(); + + /// A client may install a custom global instance via this method. Throws an exception if + /// a default instance has already been created. + static void set_instance(BufferAllocator& instance); + + BufferAllocator() = default; + virtual ~BufferAllocator() = default; + + // Rule of 5 + BufferAllocator(const BufferAllocator&) = delete; + BufferAllocator(BufferAllocator&&) = delete; + BufferAllocator& operator=(const BufferAllocator&) = delete; + BufferAllocator& operator=(BufferAllocator&&) = delete; + + // N.B. Must return zeroed memory aligned to at least 16 bytes. + virtual AllocatedBuffer* Allocate( + UInt32 numberBuffers, UInt32 maxBytesPerBuffer, UInt32 reservedFlags); + virtual void Deallocate(AllocatedBuffer* allocatedBuffer); +}; + +/*! + @class AUBufferList + @brief Manages an `AudioBufferList` backed by allocated memory buffers. +*/ +class AUBufferList { + enum class EPtrState { Invalid, ToMyMemory, ToExternalMemory }; + +public: + AUBufferList() = default; + ~AUBufferList() { Deallocate(); } + + AUBufferList(const AUBufferList&) = delete; + AUBufferList(AUBufferList&&) = delete; + AUBufferList& operator=(const AUBufferList&) = delete; + AUBufferList& operator=(AUBufferList&&) = delete; + + AudioBufferList& PrepareBuffer(const AudioStreamBasicDescription& format, UInt32 nFrames); + AudioBufferList& PrepareNullBuffer(const AudioStreamBasicDescription& format, UInt32 nFrames); + + AudioBufferList& SetBufferList(const AudioBufferList& abl) + { + ausdk::ThrowExceptionIf(mAllocatedStreams < abl.mNumberBuffers, -1); + mPtrState = EPtrState::ToExternalMemory; + auto& myabl = mBuffers->mAudioBufferList; + memcpy(&myabl, &abl, + static_cast( + reinterpret_cast(&abl.mBuffers[abl.mNumberBuffers]) - // NOLINT + reinterpret_cast(&abl))); // NOLINT + return myabl; + } + + void SetBuffer(UInt32 index, const AudioBuffer& ab) + { + auto& myabl = mBuffers->mAudioBufferList; + ausdk::ThrowExceptionIf( + mPtrState == EPtrState::Invalid || index >= myabl.mNumberBuffers, -1); + mPtrState = EPtrState::ToExternalMemory; + myabl.mBuffers[index] = ab; // NOLINT + } + + void InvalidateBufferList() noexcept { mPtrState = EPtrState::Invalid; } + + [[nodiscard]] AudioBufferList& GetBufferList() const + { + ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1); + return mBuffers->mAudioBufferList; + } + + void CopyBufferListTo(AudioBufferList& abl) const + { + ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1); + memcpy(&abl, &mBuffers->mAudioBufferList, + static_cast( + reinterpret_cast(&abl.mBuffers[abl.mNumberBuffers]) - // NOLINT + reinterpret_cast(&abl))); // NOLINT + } + + void CopyBufferContentsTo(AudioBufferList& destabl) const + { + ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1); + const auto& srcabl = mBuffers->mAudioBufferList; + const AudioBuffer* srcbuf = srcabl.mBuffers; // NOLINT + AudioBuffer* destbuf = destabl.mBuffers; // NOLINT + + for (UInt32 i = 0; i < destabl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) { // NOLINT + if (i >= + srcabl.mNumberBuffers) { // duplicate last source to additional outputs [4341137] + --srcbuf; // NOLINT + } + if (destbuf->mData != srcbuf->mData) { + memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize); + } + destbuf->mDataByteSize = srcbuf->mDataByteSize; + } + } + + void Allocate(const AudioStreamBasicDescription& format, UInt32 nFrames); + + void Deallocate(); + + // AudioBufferList utilities + static void ZeroBuffer(AudioBufferList& abl) + { + AudioBuffer* buf = abl.mBuffers; // NOLINT + for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) { // NOLINT + memset(buf->mData, 0, buf->mDataByteSize); + } + } + + [[nodiscard]] UInt32 GetAllocatedFrames() const noexcept { return mAllocatedFrames; } + +private: + EPtrState mPtrState{ EPtrState::Invalid }; + AllocatedBuffer* mBuffers = nullptr; // only valid between Allocate and Deallocate + + UInt32 mAllocatedStreams{ 0 }; + UInt32 mAllocatedFrames{ 0 }; +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUBuffer_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBufferAllocator.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBufferAllocator.cpp new file mode 100644 index 0000000000..577ccbf017 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBufferAllocator.cpp @@ -0,0 +1,15 @@ +/*! + @file AudioUnitSDK/AUBufferAllocator.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include + +namespace ausdk { + +BufferAllocator& BufferAllocator::instance() +{ + __attribute__((no_destroy)) static BufferAllocator global; + return global; +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.cpp new file mode 100644 index 0000000000..424883a17d --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.cpp @@ -0,0 +1,400 @@ +/*! + @file AudioUnitSDK/AUEffectBase.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include + +#include + +/* + This class does not deal as well as it should with N-M effects... + + The problem areas are (if the channels don't match): + ProcessInPlace if the channels don't match - there will be problems if InputChan != + OutputChan Bypass - its just passing the buffers through when not processing them +*/ + +namespace ausdk { + +//_____________________________________________________________________________ +// +AUEffectBase::AUEffectBase(AudioComponentInstance audioUnit, bool inProcessesInPlace) + : AUBase(audioUnit, 1, 1), // 1 in bus, 1 out bus + mProcessesInPlace(inProcessesInPlace) +#if TARGET_OS_IPHONE + , + mOnlyOneKernel(false) +#endif +{ +} + +//_____________________________________________________________________________ +// +void AUEffectBase::Cleanup() +{ + mKernelList.clear(); + mMainOutput = nullptr; + mMainInput = nullptr; +} + + +//_____________________________________________________________________________ +// +OSStatus AUEffectBase::Initialize() +{ + // get our current numChannels for input and output + const auto auNumInputs = static_cast(Input(0).GetStreamFormat().mChannelsPerFrame); + const auto auNumOutputs = static_cast(Output(0).GetStreamFormat().mChannelsPerFrame); + + // does the unit publish specific information about channel configurations? + const AUChannelInfo* auChannelConfigs = nullptr; + const UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs); + + if ((numIOconfigs > 0) && (auChannelConfigs != nullptr)) { + bool foundMatch = false; + for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i) { + const SInt16 configNumInputs = auChannelConfigs[i].inChannels; // NOLINT + const SInt16 configNumOutputs = auChannelConfigs[i].outChannels; // NOLINT + if ((configNumInputs < 0) && (configNumOutputs < 0)) { + // unit accepts any number of channels on input and output + if (((configNumInputs == -1) && (configNumOutputs == -2)) || + ((configNumInputs == -2) && + (configNumOutputs == -1))) { // NOLINT repeated branch below + foundMatch = true; + // unit accepts any number of channels on input and output IFF they are the same + // number on both scopes + } else if (((configNumInputs == -1) && (configNumOutputs == -1)) && + (auNumInputs == auNumOutputs)) { + foundMatch = true; + // unit has specified a particular number of channels on both scopes + } else { + continue; + } + } else { + // the -1 case on either scope is saying that the unit doesn't care about the + // number of channels on that scope + const bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1); + const bool outputMatch = + (auNumOutputs == configNumOutputs) || (configNumOutputs == -1); + if (inputMatch && outputMatch) { + foundMatch = true; + } + } + } + if (!foundMatch) { + return kAudioUnitErr_FormatNotSupported; + } + } else { + // there is no specifically published channel info + // so for those kinds of effects, the assumption is that the channels (whatever their + // number) should match on both scopes + if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0)) { + return kAudioUnitErr_FormatNotSupported; + } + } + MaintainKernels(); + + mMainOutput = &Output(0); + mMainInput = &Input(0); + + const AudioStreamBasicDescription format = GetStreamFormat(kAudioUnitScope_Output, 0); + mBytesPerFrame = format.mBytesPerFrame; + + return noErr; +} + +OSStatus AUEffectBase::Reset(AudioUnitScope inScope, AudioUnitElement inElement) +{ + for (auto& kernel : mKernelList) { + if (kernel) { + kernel->Reset(); + } + } + + return AUBase::Reset(inScope, inElement); +} + +OSStatus AUEffectBase::GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) +{ + if (inScope == kAudioUnitScope_Global) { + switch (inID) { + case kAudioUnitProperty_BypassEffect: + case kAudioUnitProperty_InPlaceProcessing: + outWritable = true; + outDataSize = sizeof(UInt32); + return noErr; + default: + break; + } + } + return AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); +} + + +OSStatus AUEffectBase::GetProperty( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData) +{ + if (inScope == kAudioUnitScope_Global) { + switch (inID) { + case kAudioUnitProperty_BypassEffect: + *static_cast(outData) = (IsBypassEffect() ? 1 : 0); // NOLINT + return noErr; + case kAudioUnitProperty_InPlaceProcessing: + *static_cast(outData) = (mProcessesInPlace ? 1 : 0); // NOLINT + return noErr; + default: + break; + } + } + return AUBase::GetProperty(inID, inScope, inElement, outData); +} + + +OSStatus AUEffectBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) +{ + if (inScope == kAudioUnitScope_Global) { + switch (inID) { + case kAudioUnitProperty_BypassEffect: { + if (inDataSize < sizeof(UInt32)) { + return kAudioUnitErr_InvalidPropertyValue; + } + + const bool tempNewSetting = *static_cast(inData) != 0; + // we're changing the state of bypass + if (tempNewSetting != IsBypassEffect()) { + if (!tempNewSetting && IsBypassEffect() && + IsInitialized()) { // turning bypass off and we're initialized + Reset(kAudioUnitScope_Global, 0); + } + SetBypassEffect(tempNewSetting); + } + return noErr; + } + case kAudioUnitProperty_InPlaceProcessing: + mProcessesInPlace = *static_cast(inData) != 0; + return noErr; + default: + break; + } + } + return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize); +} + + +void AUEffectBase::MaintainKernels() +{ +#if TARGET_OS_IPHONE + const UInt32 nKernels = mOnlyOneKernel ? 1 : GetNumberOfChannels(); +#else + const UInt32 nKernels = GetNumberOfChannels(); +#endif + + if (mKernelList.size() < nKernels) { + mKernelList.reserve(nKernels); + for (auto i = static_cast(mKernelList.size()); i < nKernels; ++i) { + mKernelList.push_back(NewKernel()); + } + } else { + while (mKernelList.size() > nKernels) { + mKernelList.pop_back(); + } + } + + for (UInt32 i = 0; i < nKernels; i++) { + if (mKernelList[i]) { + mKernelList[i]->SetChannelNum(i); + } + } +} + +bool AUEffectBase::StreamFormatWritable(AudioUnitScope /*scope*/, AudioUnitElement /*element*/) +{ + return !IsInitialized(); +} + +OSStatus AUEffectBase::ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement, + const AudioStreamBasicDescription& inPrevFormat, const AudioStreamBasicDescription& inNewFormat) +{ + const OSStatus result = + AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat); + if (result == noErr) { + // for the moment this only dependency we know about + // where a parameter's range may change is with the sample rate + // and effects are only publishing parameters in the global scope! + if (GetParamHasSampleRateDependency() && + inPrevFormat.mSampleRate != inNewFormat.mSampleRate) { + PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0); + } + } + + return result; +} + + +// ____________________________________________________________________________ +// +// This method is called (potentially repeatedly) by ProcessForScheduledParams() +// in order to perform the actual DSP required for this portion of the entire buffer +// being processed. The entire buffer can be divided up into smaller "slices" +// according to the timestamps on the scheduled parameters... +// +OSStatus AUEffectBase::ProcessScheduledSlice(void* inUserData, UInt32 /*inStartFrameInBuffer*/, + UInt32 inSliceFramesToProcess, UInt32 /*inTotalBufferFrames*/) +{ + const ScheduledProcessParams& sliceParams = *static_cast(inUserData); + + AudioUnitRenderActionFlags& actionFlags = *sliceParams.actionFlags; + AudioBufferList& inputBufferList = *sliceParams.inputBufferList; + AudioBufferList& outputBufferList = *sliceParams.outputBufferList; + + UInt32 channelSize = inSliceFramesToProcess * mBytesPerFrame; + // fix the size of the buffer we're operating on before we render this slice of time + for (UInt32 i = 0; i < inputBufferList.mNumberBuffers; i++) { + inputBufferList.mBuffers[i].mDataByteSize = // NOLINT + inputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT + } + + for (UInt32 i = 0; i < outputBufferList.mNumberBuffers; i++) { + outputBufferList.mBuffers[i].mDataByteSize = // NOLINT + outputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT + } + // process the buffer + const OSStatus result = + ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess); + + // we just partially processed the buffers, so increment the data pointers to the next part of + // the buffer to process + for (UInt32 i = 0; i < inputBufferList.mNumberBuffers; i++) { + inputBufferList.mBuffers[i].mData = // NOLINT + static_cast(inputBufferList.mBuffers[i].mData) + // NOLINT + inputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT + } + + for (UInt32 i = 0; i < outputBufferList.mNumberBuffers; i++) { + outputBufferList.mBuffers[i].mData = // NOLINT + static_cast(outputBufferList.mBuffers[i].mData) + // NOLINT + outputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT + } + + return result; +} + +// ____________________________________________________________________________ +// + +OSStatus AUEffectBase::Render( + AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, UInt32 nFrames) +{ + if (!HasInput(0)) { + return kAudioUnitErr_NoConnection; + } + + OSStatus result = noErr; + + result = mMainInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames); + + if (result == noErr) { + if (ProcessesInPlace() && mMainOutput->WillAllocateBuffer()) { + mMainOutput->SetBufferList(mMainInput->GetBufferList()); + } + + if (ShouldBypassEffect()) { + // leave silence bit alone + + if (!ProcessesInPlace()) { + mMainInput->CopyBufferContentsTo(mMainOutput->GetBufferList()); + } + } else { + auto& paramEventList = GetParamEventList(); + + if (paramEventList.empty()) { + // this will read/write silence bit + result = ProcessBufferLists(ioActionFlags, mMainInput->GetBufferList(), + mMainOutput->GetBufferList(), nFrames); + } else { + // deal with scheduled parameters... + + AudioBufferList& inputBufferList = mMainInput->GetBufferList(); + AudioBufferList& outputBufferList = mMainOutput->GetBufferList(); + + ScheduledProcessParams processParams{ .actionFlags = &ioActionFlags, + .inputBufferList = &inputBufferList, + .outputBufferList = &outputBufferList }; + + // divide up the buffer into slices according to scheduled params then + // do the DSP for each slice (ProcessScheduledSlice() called for each slice) + result = ProcessForScheduledParams(paramEventList, nFrames, &processParams); + + + // fixup the buffer pointers to how they were before we started + const UInt32 channelSize = nFrames * mBytesPerFrame; + for (UInt32 i = 0; i < inputBufferList.mNumberBuffers; i++) { + const UInt32 size = + inputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT + inputBufferList.mBuffers[i].mData = // NOLINT + static_cast(inputBufferList.mBuffers[i].mData) - size; // NOLINT + inputBufferList.mBuffers[i].mDataByteSize = size; // NOLINT + } + + for (UInt32 i = 0; i < outputBufferList.mNumberBuffers; i++) { + const UInt32 size = + outputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT + outputBufferList.mBuffers[i].mData = // NOLINT + static_cast(outputBufferList.mBuffers[i].mData) - + size; // NOLINT + outputBufferList.mBuffers[i].mDataByteSize = size; // NOLINT + } + } + } + + if (((ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0u) && + !ProcessesInPlace()) { + AUBufferList::ZeroBuffer(mMainOutput->GetBufferList()); + } + } + + return result; +} + + +OSStatus AUEffectBase::ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags, + const AudioBufferList& inBuffer, AudioBufferList& outBuffer, UInt32 inFramesToProcess) +{ + if (ShouldBypassEffect()) { + return noErr; + } + + bool ioSilence = false; + + const bool silentInput = IsInputSilent(ioActionFlags, inFramesToProcess); + ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence; + + for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) { + auto& kernel = mKernelList[channel]; + + if (!kernel) { + continue; + } + + ioSilence = silentInput; + const AudioBuffer* const srcBuffer = &inBuffer.mBuffers[channel]; // NOLINT subscript + AudioBuffer* const destBuffer = &outBuffer.mBuffers[channel]; // NOLINT subscript + + kernel->Process(static_cast(srcBuffer->mData), + static_cast(destBuffer->mData), inFramesToProcess, ioSilence); + + if (!ioSilence) { + ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence; + } + } + + return noErr; +} + +Float64 AUEffectBase::GetSampleRate() { return Output(0).GetStreamFormat().mSampleRate; } + +UInt32 AUEffectBase::GetNumberOfChannels() { return Output(0).GetStreamFormat().mChannelsPerFrame; } + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.h new file mode 100644 index 0000000000..55104b69ed --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.h @@ -0,0 +1,194 @@ +/*! + @file AudioUnitSDK/AUEffectBase.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUEffectBase_h +#define AudioUnitSDK_AUEffectBase_h + +#include +#include + +#include + +namespace ausdk { + +class AUKernelBase; + +/*! + @class AUEffectBase + @brief Base class for an effect with one input stream, one output stream, and any number of + channels. +*/ +class AUEffectBase : public AUBase { +public: + explicit AUEffectBase(AudioComponentInstance audioUnit, bool inProcessesInPlace = true); + + AUEffectBase(const AUEffectBase&) = delete; + AUEffectBase(AUEffectBase&&) = delete; + AUEffectBase& operator=(const AUEffectBase&) = delete; + AUEffectBase& operator=(AUEffectBase&&) = delete; + + ~AUEffectBase() override = default; + + OSStatus Initialize() override; + void Cleanup() override; + OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement) override; + OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) override; + OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData) override; + OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) override; + bool StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) override; + OSStatus ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement, + const AudioStreamBasicDescription& inPrevFormat, + const AudioStreamBasicDescription& inNewFormat) override; + OSStatus Render(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, + UInt32 nFrames) override; + + // our virtual methods + + // If your unit processes N to N channels, and there are no interactions between channels, + // it can override NewKernel to create a mono processing object per channel. Otherwise, + // don't override NewKernel, and instead, override ProcessBufferLists. + virtual std::unique_ptr NewKernel() { return {}; } + OSStatus ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags, + const AudioBufferList& inBuffer, AudioBufferList& outBuffer, + UInt32 inFramesToProcess) override; + + // convenience format accessors (use output 0's format) + Float64 GetSampleRate(); + UInt32 GetNumberOfChannels(); + + // convenience wrappers for accessing parameters in the global scope + using AUBase::SetParameter; + + void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value) + { + Globals()->SetParameter(paramID, value); + } + + using AUBase::GetParameter; + + AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID) + { + return Globals()->GetParameter(paramID); + } + + [[nodiscard]] bool CanScheduleParameters() const override { return true; } + + // This is used for the property value - to reflect to the UI if an effect is bypassed + [[nodiscard]] bool IsBypassEffect() const noexcept { return mBypassEffect; } + + virtual void SetBypassEffect(bool inFlag) { mBypassEffect = inFlag; } + + void SetParamHasSampleRateDependency(bool inFlag) noexcept { mParamSRDep = inFlag; } + [[nodiscard]] bool GetParamHasSampleRateDependency() const noexcept { return mParamSRDep; } + + /// Context, passed as `void* userData`, for `ProcessScheduledSlice()`. + struct ScheduledProcessParams { + AudioUnitRenderActionFlags* actionFlags = nullptr; + AudioBufferList* inputBufferList = nullptr; + AudioBufferList* outputBufferList = nullptr; + }; + + OSStatus ProcessScheduledSlice(void* inUserData, UInt32 inStartFrameInBuffer, + UInt32 inSliceFramesToProcess, UInt32 inTotalBufferFrames) override; + + [[nodiscard]] bool ProcessesInPlace() const noexcept { return mProcessesInPlace; } + void SetProcessesInPlace(bool inProcessesInPlace) noexcept + { + mProcessesInPlace = inProcessesInPlace; + } + + using KernelList = std::vector>; + +protected: + void MaintainKernels(); + + // This is used in the render call to see if an effect is bypassed + // It can return a different status than IsBypassEffect (though it MUST take that into account) + virtual bool ShouldBypassEffect() { return IsBypassEffect(); } + + [[nodiscard]] AUKernelBase* GetKernel(UInt32 index) const + { + return (index < mKernelList.size()) ? mKernelList[index].get() : nullptr; + } + [[nodiscard]] const KernelList& GetKernelList() const noexcept { return mKernelList; } + + bool IsInputSilent(AudioUnitRenderActionFlags inActionFlags, UInt32 inFramesToProcess) + { + bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0; + + // take latency and tail time into account when propagating the silent bit + const auto silentTimeoutFrames = + static_cast(GetSampleRate() * (GetLatency() + GetTailTime())); + mSilentTimeout.Process(inFramesToProcess, silentTimeoutFrames, inputSilent); + return inputSilent; + } + +#if TARGET_OS_IPHONE + void SetOnlyOneKernel(bool inUseOnlyOneKernel) noexcept + { + mOnlyOneKernel = inUseOnlyOneKernel; + } // set in ctor of subclass that wants it. +#endif + +private: + KernelList mKernelList; + bool mBypassEffect{ false }; + bool mParamSRDep{ false }; + bool mProcessesInPlace; + AUSilentTimeout mSilentTimeout; + AUOutputElement* mMainOutput{ nullptr }; + AUInputElement* mMainInput{ nullptr }; + +#if TARGET_OS_IPHONE + bool mOnlyOneKernel; +#endif + UInt32 mBytesPerFrame = 0; +}; + + +/*! + @class AUKernelBase + @brief Base class for a signal-processing "kernel", an object that performs DSP on one channel + of an audio stream. +*/ +class AUKernelBase { +public: + explicit AUKernelBase(AUEffectBase& inAudioUnit) : mAudioUnit(inAudioUnit) {} + + AUSDK_DEPRECATED("Construct with a reference") + explicit AUKernelBase(AUEffectBase* inAudioUnit) : mAudioUnit(*inAudioUnit) {} + + AUKernelBase(const AUKernelBase&) = delete; + AUKernelBase(AUKernelBase&&) = delete; + AUKernelBase& operator=(const AUKernelBase&) = delete; + AUKernelBase& operator=(AUKernelBase&&) = delete; + + virtual ~AUKernelBase() = default; + + virtual void Reset() {} + + virtual void Process(const Float32* /*inSourceP*/, Float32* /*inDestP*/, + UInt32 /*inFramesToProcess*/, bool& /*ioSilence*/) = 0; + + Float64 GetSampleRate() { return mAudioUnit.GetSampleRate(); } + + AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID) + { + return mAudioUnit.GetParameter(paramID); + } + + void SetChannelNum(UInt32 inChan) noexcept { mChannelNum = inChan; } + [[nodiscard]] UInt32 GetChannelNum() const noexcept { return mChannelNum; } + +protected: + AUEffectBase& mAudioUnit; // NOLINT protected + UInt32 mChannelNum = 0; // NOLINT protected +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUEffectBase_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.cpp new file mode 100644 index 0000000000..dafc8a380d --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.cpp @@ -0,0 +1,85 @@ +/*! + @file AudioUnitSDK/AUInputElement.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include + +namespace ausdk { + +constexpr bool HasGoodBufferPointers(const AudioBufferList& abl, UInt32 nBytes) noexcept +{ + const AudioBuffer* buf = abl.mBuffers; // NOLINT + for (UInt32 i = abl.mNumberBuffers; i-- > 0; ++buf) { // NOLINT + if (buf->mData == nullptr || buf->mDataByteSize < nBytes) { + return false; + } + } + return true; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AUInputElement::SetConnection +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AUInputElement::SetConnection(const AudioUnitConnection& conn) +{ + if (conn.sourceAudioUnit == nullptr) { + Disconnect(); + return; + } + + mInputType = EInputType::FromConnection; + mConnection = conn; + AllocateBuffer(); +} + +void AUInputElement::Disconnect() +{ + mInputType = EInputType::NoInput; + IOBuffer().Deallocate(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AUInputElement::SetInputCallback +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void AUInputElement::SetInputCallback(AURenderCallback proc, void* refCon) +{ + if (proc == nullptr) { + Disconnect(); + } else { + mInputType = EInputType::FromCallback; + mInputProc = proc; + mInputProcRefCon = refCon; + AllocateBuffer(); + } +} + +OSStatus AUInputElement::SetStreamFormat(const AudioStreamBasicDescription& fmt) +{ + const OSStatus err = AUIOElement::SetStreamFormat(fmt); + if (err == noErr) { + AllocateBuffer(); + } + return err; +} + +OSStatus AUInputElement::PullInput(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, AudioUnitElement inElement, UInt32 nFrames) +{ + if (!IsActive()) { + return kAudioUnitErr_NoConnection; + } + + auto& iob = IOBuffer(); + + AudioBufferList& pullBuffer = (HasConnection() || !WillAllocateBuffer()) + ? iob.PrepareNullBuffer(GetStreamFormat(), nFrames) + : iob.PrepareBuffer(GetStreamFormat(), nFrames); + + return PullInputWithBufferList(ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer); +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.h new file mode 100644 index 0000000000..d25cafab3d --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.h @@ -0,0 +1,91 @@ +/*! + @file AudioUnitSDK/AUInputElement.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUInputElement_h +#define AudioUnitSDK_AUInputElement_h + +#include +#include + +namespace ausdk { + +/*! + @class AUInputElement + @brief Implements an audio unit input element, managing the source of input from a callback + or connection. +*/ +class AUInputElement : public AUIOElement { +public: + using AUIOElement::AUIOElement; + + // AUElement override + OSStatus SetStreamFormat(const AudioStreamBasicDescription& fmt) override; + [[nodiscard]] bool NeedsBufferSpace() const override { return IsCallback(); } + void SetConnection(const AudioUnitConnection& conn); + void SetInputCallback(AURenderCallback proc, void* refCon); + [[nodiscard]] bool IsActive() const noexcept { return mInputType != EInputType::NoInput; } + [[nodiscard]] bool IsCallback() const noexcept + { + return mInputType == EInputType::FromCallback; + } + [[nodiscard]] bool HasConnection() const noexcept + { + return mInputType == EInputType::FromConnection; + } + OSStatus PullInput(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, + AudioUnitElement inElement, UInt32 nFrames); + OSStatus PullInputWithBufferList(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, AudioUnitElement inElement, UInt32 nFrames, + AudioBufferList& inBufferList); + +protected: + void Disconnect(); + +private: + enum class EInputType { NoInput, FromConnection, FromCallback }; + EInputType mInputType{ EInputType::NoInput }; + + // if from callback: + AURenderCallback mInputProc{ nullptr }; + void* mInputProcRefCon{ nullptr }; + + // if from connection: + AudioUnitConnection mConnection{}; +}; + +inline OSStatus AUInputElement::PullInputWithBufferList(AudioUnitRenderActionFlags& ioActionFlags, + const AudioTimeStamp& inTimeStamp, AudioUnitElement inElement, UInt32 nFrames, + AudioBufferList& inBufferList) +{ + OSStatus theResult = noErr; + + if (HasConnection()) { + // only support connections for V2 audio units + theResult = AudioUnitRender(mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, + mConnection.sourceOutputNumber, nFrames, &inBufferList); + } else { + // kFromCallback: + theResult = (mInputProc)(mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, + &inBufferList); + } + + if (mInputType == EInputType::NoInput) { // defense: the guy upstream could have disconnected + // it's a horrible thing to do, but may happen! + return kAudioUnitErr_NoConnection; + } + +#if !TARGET_OS_IPHONE || DEBUG + if (theResult == noErr) { // if there's already an error, there's no point (and maybe some harm) + // in validating. + if (ABL::IsBogusAudioBufferList(inBufferList) & 1) { + return kAudioUnitErr_InvalidPropertyValue; + } + } +#endif + return theResult; +} + +} // namespace ausdk + +#endif // AudioUnitSDK_AUInputElement_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.cpp new file mode 100644 index 0000000000..ea3fb7be88 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.cpp @@ -0,0 +1,251 @@ +/*! + @file AudioUnitSDK/AUMIDIBase.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include +#include + +namespace ausdk { + +// MIDI CC data bytes +constexpr uint8_t kMIDIController_AllSoundOff = 120u; +constexpr uint8_t kMIDIController_ResetAllControllers = 121u; +constexpr uint8_t kMIDIController_AllNotesOff = 123u; + +OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) +{ + (void)inScope; + (void)inElement; + (void)outDataSize; + (void)outWritable; + + switch (inID) { // NOLINT if/else?! +#if AUSDK_HAVE_XML_NAMES + case kMusicDeviceProperty_MIDIXMLNames: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + AUSDK_Require(GetXMLNames(nullptr) == noErr, kAudioUnitErr_InvalidProperty); + outDataSize = sizeof(CFURLRef); + outWritable = false; + return noErr; +#endif + +#if AUSDK_HAVE_MIDI_MAPPING + case kAudioUnitProperty_AllParameterMIDIMappings: + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + outWritable = true; + outDataSize = sizeof(AUParameterMIDIMapping) * mMIDIMapper->GetNumberMaps(); + return noErr; + + case kAudioUnitProperty_HotMapParameterMIDIMapping: + case kAudioUnitProperty_AddParameterMIDIMapping: + case kAudioUnitProperty_RemoveParameterMIDIMapping: + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + outWritable = true; + outDataSize = sizeof(AUParameterMIDIMapping); + return noErr; +#endif + + default: + return kAudioUnitErr_InvalidProperty; + } +} + +OSStatus AUMIDIBase::DelegateGetProperty( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData) +{ + (void)inScope; + (void)inElement; + (void)outData; + + switch (inID) { // NOLINT if/else?! +#if AUSDK_HAVE_XML_NAMES + case kMusicDeviceProperty_MIDIXMLNames: + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + return GetXMLNames(static_cast(outData)); +#endif + +#if AUSDK_HAVE_MIDI_MAPPING + case kAudioUnitProperty_AllParameterMIDIMappings: { + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + AUParameterMIDIMapping* const maps = (static_cast(outData)); + mMIDIMapper->GetMaps(maps); + return noErr; + } + + case kAudioUnitProperty_HotMapParameterMIDIMapping: { + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + AUParameterMIDIMapping* const map = (static_cast(outData)); + mMIDIMapper->GetHotParameterMap(*map); + return noErr; + } +#endif + + default: + return kAudioUnitErr_InvalidProperty; + } +} + +OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) +{ + (void)inScope; + (void)inElement; + (void)inData; + (void)inDataSize; + + switch (inID) { + +#if AUSDK_HAVE_MIDI_MAPPING + case kAudioUnitProperty_AddParameterMIDIMapping: { + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + const auto* const maps = static_cast(inData); + mMIDIMapper->AddParameterMapping( + maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance); + mAUBaseInstance.PropertyChanged( + kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0); + return noErr; + } + + case kAudioUnitProperty_RemoveParameterMIDIMapping: { + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + const auto* const maps = static_cast(inData); + bool didChange = false; + mMIDIMapper->RemoveParameterMapping( + maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange); + if (didChange) { + mAUBaseInstance.PropertyChanged( + kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0); + } + return noErr; + } + + case kAudioUnitProperty_HotMapParameterMIDIMapping: { + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + const auto& map = *static_cast(inData); + mMIDIMapper->SetHotMapping(map); + return noErr; + } + + case kAudioUnitProperty_AllParameterMIDIMappings: { + AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); + AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); + AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); + const auto* const mappings = static_cast(inData); + mMIDIMapper->ReplaceAllMaps( + mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance); + return noErr; + } +#endif + + default: + return kAudioUnitErr_InvalidProperty; + } +} + +constexpr uint8_t MIDIStatusNibbleValue(uint8_t status) noexcept { return (status & 0xF0U) >> 4u; } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AUMIDIBase::HandleMIDIEvent +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +OSStatus AUMIDIBase::HandleMIDIEvent( + UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame) +{ + if (!mAUBaseInstance.IsInitialized()) { + return kAudioUnitErr_Uninitialized; + } + +#if AUSDK_HAVE_MIDI_MAPPING + // 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 (mMIDIMapper) { + if (mMIDIMapper->HandleHotMapping(status, channel, data1, mAUBaseInstance)) { + mAUBaseInstance.PropertyChanged( + kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0); + } else { + mMIDIMapper->FindParameterMapEventMatch( + status, channel, data1, data2, inStartFrame, mAUBaseInstance); + } + } +#endif + switch (MIDIStatusNibbleValue(status)) { + case kMIDICVStatusNoteOn: + if (data2 != 0u) { + return HandleNoteOn(channel, data1, data2, inStartFrame); + } else { + // zero velocity translates to note off + return HandleNoteOff(channel, data1, data2, inStartFrame); + } + + case kMIDICVStatusNoteOff: + return HandleNoteOff(channel, data1, data2, inStartFrame); + + default: + return HandleNonNoteEvent(status, channel, data1, data2, inStartFrame); + } +} + +OSStatus AUMIDIBase::HandleNonNoteEvent( + UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame) +{ + switch (MIDIStatusNibbleValue(status)) { + case kMIDICVStatusPitchBend: + return HandlePitchWheel(channel, data1, data2, inStartFrame); + + case kMIDICVStatusProgramChange: + return HandleProgramChange(channel, data1); + + case kMIDICVStatusChannelPressure: + return HandleChannelPressure(channel, data1, inStartFrame); + + case kMIDICVStatusControlChange: { + switch (data1) { + case kMIDIController_AllNotesOff: + return HandleAllNotesOff(channel); + + case kMIDIController_ResetAllControllers: + return HandleResetAllControllers(channel); + + case kMIDIController_AllSoundOff: + return HandleAllSoundOff(channel); + + default: + return HandleControlChange(channel, data1, data2, inStartFrame); + } + } + + case kMIDICVStatusPolyPressure: + return HandlePolyPressure(channel, data1, data2, inStartFrame); + + default: + return noErr; + } +} + +OSStatus AUMIDIBase::SysEx(const UInt8* inData, UInt32 inLength) +{ + if (!mAUBaseInstance.IsInitialized()) { + return kAudioUnitErr_Uninitialized; + } + + return HandleSysEx(inData, inLength); +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.h new file mode 100644 index 0000000000..6a8923c4f3 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.h @@ -0,0 +1,169 @@ +/*! + @file AudioUnitSDK/AUMIDIBase.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUMIDIBase_h +#define AudioUnitSDK_AUMIDIBase_h + +#include + + +#ifndef AUSDK_HAVE_XML_NAMES +#define AUSDK_HAVE_XML_NAMES TARGET_OS_OSX // NOLINT(cppcoreguidelines-macro-usage) +#endif + +#ifndef AUSDK_HAVE_MIDI_MAPPING +#define AUSDK_HAVE_MIDI_MAPPING TARGET_OS_OSX // NOLINT(cppcoreguidelines-macro-usage) +#endif + +namespace ausdk { + +#if AUSDK_HAVE_MIDI_MAPPING +/// Abstract interface for parameter MIDI mapping +class AUMIDIMapper { +public: + AUMIDIMapper() = default; + virtual ~AUMIDIMapper() = default; + + AUMIDIMapper(const AUMIDIMapper&) = delete; + AUMIDIMapper(AUMIDIMapper&&) = delete; + AUMIDIMapper& operator=(const AUMIDIMapper&) = delete; + AUMIDIMapper& operator=(AUMIDIMapper&&) = delete; + + [[nodiscard]] virtual UInt32 GetNumberMaps() const = 0; + virtual void GetMaps(AUParameterMIDIMapping* outMapping) = 0; + virtual void GetHotParameterMap(AUParameterMIDIMapping& outMapping) = 0; + + virtual void AddParameterMapping( + const AUParameterMIDIMapping* maps, UInt32 count, AUBase& auBase) = 0; + virtual void RemoveParameterMapping( + const AUParameterMIDIMapping* maps, UInt32 count, bool& outDidChange) = 0; + virtual void SetHotMapping(const AUParameterMIDIMapping& mapping) = 0; + virtual void ReplaceAllMaps( + const AUParameterMIDIMapping* maps, UInt32 count, AUBase& auBase) = 0; + + virtual bool HandleHotMapping(UInt8 status, UInt8 channel, UInt8 data1, AUBase& auBase) = 0; + virtual bool FindParameterMapEventMatch(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, + UInt32 inStartFrame, AUBase& auBase) = 0; +}; +#endif + +// ________________________________________________________________________ +// AUMIDIBase +// +/*! + @class AUMIDIBase + @brief Auxiliary class supporting MIDI events. +*/ +class AUMIDIBase { +public: + explicit AUMIDIBase(AUBase& inBase) : mAUBaseInstance(inBase) {} + + virtual ~AUMIDIBase() = default; + + AUMIDIBase(const AUMIDIBase&) = delete; + AUMIDIBase(AUMIDIBase&&) = delete; + AUMIDIBase& operator=(const AUMIDIBase&) = delete; + AUMIDIBase& operator=(AUMIDIBase&&) = delete; + + virtual OSStatus MIDIEvent( + UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame) + { + const UInt32 strippedStatus = inStatus & 0xf0U; // NOLINT + const UInt32 channel = inStatus & 0x0fU; // NOLINT + + return HandleMIDIEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame); + } + +#if AUSDK_MIDI2_AVAILABLE + virtual OSStatus MIDIEventList( + UInt32 /*inOffsetSampleFrame*/, const MIDIEventList* /*eventList*/) + { + return kAudio_UnimplementedError; + } +#endif + + virtual OSStatus SysEx(const UInt8* inData, UInt32 inLength); + + virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable); + virtual OSStatus DelegateGetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData); + virtual OSStatus DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize); + +protected: + // MIDI dispatch + virtual OSStatus HandleMIDIEvent( + UInt8 inStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame); + virtual OSStatus HandleNonNoteEvent( + UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame); + + // Old name + AUSDK_DEPRECATED("HandleMIDIEvent") + OSStatus HandleMidiEvent( + UInt8 inStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame) + { + return HandleMIDIEvent(inStatus, inChannel, inData1, inData2, inStartFrame); + } + +#if AUSDK_HAVE_XML_NAMES + virtual OSStatus GetXMLNames(CFURLRef* /*outNameDocument*/) + { + return kAudioUnitErr_InvalidProperty; + } // if not overridden, it's unsupported +#endif + + // channel messages + virtual OSStatus HandleNoteOn( + UInt8 /*inChannel*/, UInt8 /*inNoteNumber*/, UInt8 /*inVelocity*/, UInt32 /*inStartFrame*/) + { + return noErr; + } + virtual OSStatus HandleNoteOff( + UInt8 /*inChannel*/, UInt8 /*inNoteNumber*/, UInt8 /*inVelocity*/, UInt32 /*inStartFrame*/) + { + return noErr; + } + virtual OSStatus HandleControlChange( + UInt8 /*inChannel*/, UInt8 /*inController*/, UInt8 /*inValue*/, UInt32 /*inStartFrame*/) + { + return noErr; + } + virtual OSStatus HandlePitchWheel( + UInt8 /*inChannel*/, UInt8 /*inPitch1*/, UInt8 /*inPitch2*/, UInt32 /*inStartFrame*/) + { + return noErr; + } + virtual OSStatus HandleChannelPressure( + UInt8 /*inChannel*/, UInt8 /*inValue*/, UInt32 /*inStartFrame*/) + { + return noErr; + } + virtual OSStatus HandleProgramChange(UInt8 /*inChannel*/, UInt8 /*inValue*/) { return noErr; } + virtual OSStatus HandlePolyPressure( + UInt8 /*inChannel*/, UInt8 /*inKey*/, UInt8 /*inValue*/, UInt32 /*inStartFrame*/) + { + return noErr; + } + virtual OSStatus HandleResetAllControllers(UInt8 /*inChannel*/) { return noErr; } + virtual OSStatus HandleAllNotesOff(UInt8 /*inChannel*/) { return noErr; } + virtual OSStatus HandleAllSoundOff(UInt8 /*inChannel*/) { return noErr; } + + // System messages + virtual OSStatus HandleSysEx(const UInt8* /*inData*/, UInt32 /*inLength*/) { return noErr; } + +#if AUSDK_HAVE_MIDI_MAPPING + void SetMIDIMapper(const std::shared_ptr& mapper) { mMIDIMapper = mapper; } +#endif + +private: + AUBase& mAUBaseInstance; +#if AUSDK_HAVE_MIDI_MAPPING + std::shared_ptr mMIDIMapper; +#endif +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUMIDIBase_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.cpp new file mode 100644 index 0000000000..6519bfe4c2 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.cpp @@ -0,0 +1,53 @@ +/*! + @file AudioUnitSDK/AUMIDIEffectBase.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include + +namespace ausdk { + +AUMIDIEffectBase::AUMIDIEffectBase(AudioComponentInstance inInstance, bool inProcessesInPlace) + : AUEffectBase(inInstance, inProcessesInPlace), AUMIDIBase(*static_cast(this)) +{ +} + +OSStatus AUMIDIEffectBase::GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) +{ + OSStatus result = + AUEffectBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); + + if (result == kAudioUnitErr_InvalidProperty) { + result = + AUMIDIBase::DelegateGetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); + } + + return result; +} + +OSStatus AUMIDIEffectBase::GetProperty( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData) +{ + OSStatus result = AUEffectBase::GetProperty(inID, inScope, inElement, outData); + + if (result == kAudioUnitErr_InvalidProperty) { + result = AUMIDIBase::DelegateGetProperty(inID, inScope, inElement, outData); + } + + return result; +} + +OSStatus AUMIDIEffectBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) +{ + + OSStatus result = AUEffectBase::SetProperty(inID, inScope, inElement, inData, inDataSize); + + if (result == kAudioUnitErr_InvalidProperty) { + result = AUMIDIBase::DelegateSetProperty(inID, inScope, inElement, inData, inDataSize); + } + + return result; +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.h new file mode 100644 index 0000000000..90e1f5b840 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.h @@ -0,0 +1,40 @@ +/*! + @file AudioUnitSDK/AUMIDIEffectBase.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUMIDIEffectBase_h +#define AudioUnitSDK_AUMIDIEffectBase_h + +#include +#include + +namespace ausdk { + +/*! + @class AUMIDIEffectBase + @brief Subclass of AUEffectBase and AUMIDIBase, providing an abstract base class for + music effects. +*/ +class AUMIDIEffectBase : public AUEffectBase, public AUMIDIBase { +public: + explicit AUMIDIEffectBase(AudioComponentInstance inInstance, bool inProcessesInPlace = false); + OSStatus MIDIEvent( + UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame) override + { + return AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame); + } + OSStatus SysEx(const UInt8* inData, UInt32 inLength) override + { + return AUMIDIBase::SysEx(inData, inLength); + } + OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) override; + OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData) override; + OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) override; +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUMIDIEffectBase_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIUtility.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIUtility.h new file mode 100644 index 0000000000..9dee84bf23 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIUtility.h @@ -0,0 +1,20 @@ +/*! + @file AudioUnitSDK/AUMIDIUtility.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUMIDIUtility_h +#define AudioUnitSDK_AUMIDIUtility_h + +// OS +#if defined __has_include && __has_include() +#include +#endif +#if defined(__MAC_12_0) || defined(__IPHONE_15_0) +#define AUSDK_MIDI2_AVAILABLE 1 +#endif + +#if AUSDK_MIDI2_AVAILABLE +#include +#endif + +#endif // AudioUnitSDK_AUMIDIUtility_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.cpp new file mode 100644 index 0000000000..6951f42bed --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.cpp @@ -0,0 +1,27 @@ +/*! + @file AudioUnitSDK/AUOutputElement.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include +#include + +namespace ausdk { + +AUOutputElement::AUOutputElement(AUBase& audioUnit) : AUIOElement(audioUnit) { AllocateBuffer(); } + +AUOutputElement::AUOutputElement(AUBase& audioUnit, const AudioStreamBasicDescription& format) + : AUIOElement{ audioUnit, format } +{ + AllocateBuffer(); +} + +OSStatus AUOutputElement::SetStreamFormat(const AudioStreamBasicDescription& desc) +{ + const OSStatus result = AUIOElement::SetStreamFormat(desc); // inherited + if (result == noErr) { + AllocateBuffer(); + } + return result; +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.h new file mode 100644 index 0000000000..6419d84f9d --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.h @@ -0,0 +1,33 @@ +/*! + @file AudioUnitSDK/AUOutputElement.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUOutputElement_h +#define AudioUnitSDK_AUOutputElement_h + +#include +#include + +namespace ausdk { + +/*! + @class AUOutputElement + @brief Implements an audio unit output element. +*/ +class AUOutputElement : public AUIOElement { +public: + explicit AUOutputElement(AUBase& audioUnit); + + AUOutputElement(AUBase& audioUnit, const AudioStreamBasicDescription& format); + + AUSDK_DEPRECATED("Construct with a reference") + explicit AUOutputElement(AUBase* audioUnit) : AUOutputElement(*audioUnit) {} + + // AUElement override + OSStatus SetStreamFormat(const AudioStreamBasicDescription& desc) override; + [[nodiscard]] bool NeedsBufferSpace() const override { return true; } +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUOutputElement_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.cpp new file mode 100644 index 0000000000..b06725d75f --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.cpp @@ -0,0 +1,773 @@ +/*! + @file AudioUnitSDK/AUPlugInDispatch.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include +#include +#include +#include + +#include +#include + +#define CATCH_EXCEPTIONS_IN_RENDER_METHODS TARGET_OS_OSX // NOLINT +#define HAVE_MUSICDEVICE_PREPARE_RELEASE TARGET_OS_OSX // NOLINT + +namespace ausdk { + +// ------------------------------------------------------------------------------------------------ +static auto AUInstance(void* self) +{ + return reinterpret_cast( // NOLINT reinterpret_cast + &(static_cast(self)->mInstanceStorage)); +} + +// ------------------------------------------------------------------------------------------------ +class AUInstanceGuard { +public: + explicit AUInstanceGuard(void* self) : mGuard(AUInstance(self)->GetMutex()) {} + +private: + const AUEntryGuard mGuard; +}; + +// ------------------------------------------------------------------------------------------------ +static bool IsValidParameterValue(AudioUnitParameterValue value) { return std::isfinite(value); } + +static bool AreValidParameterEvents(const AudioUnitParameterEvent* events, UInt32 numEvents) +{ + if (events == nullptr) { + return true; + } + + for (UInt32 i = 0; i < numEvents; ++i) { + const auto& event = events[i]; // NOLINT + switch (event.eventType) { + case kParameterEvent_Immediate: { + if (!IsValidParameterValue(event.eventValues.immediate.value)) { // NOLINT + return false; + } + break; + } + + case kParameterEvent_Ramped: { + if (!IsValidParameterValue(event.eventValues.ramp.startValue) || // NOLINT + !IsValidParameterValue(event.eventValues.ramp.endValue)) { // NOLINT + return false; + } + break; + } + + default: + break; + } + } + + return true; +} + +// ------------------------------------------------------------------------------------------------ +static OSStatus AUMethodInitialize(void* self) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->DoInitialize(); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodUninitialize(void* self) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + AUInstance(self)->DoCleanup(); + } + AUSDK_Catch(result) + 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. + bool writable = false; + + const AUInstanceGuard guard(self); + result = AUInstance(self)->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable); + if (outDataSize != nullptr) { + *outDataSize = dataSize; + } + if (outWritable != nullptr) { + *outWritable = static_cast(writable); + } + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodGetProperty(void* self, AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData, UInt32* ioDataSize) +{ + OSStatus result = noErr; + try { + bool writable = false; + + const AUInstanceGuard guard(self); + if (ioDataSize == nullptr) { + AUSDK_LogError("AudioUnitGetProperty: null size pointer"); + return kAudio_ParamError; + } + if (outData == nullptr) { + UInt32 dataSize = 0; + + result = AUInstance(self)->DispatchGetPropertyInfo( + inID, inScope, inElement, dataSize, writable); + *ioDataSize = dataSize; + return result; + } + + const auto clientBufferSize = *ioDataSize; + if (clientBufferSize == 0) { + AUSDK_LogError("AudioUnitGetProperty: *ioDataSize == 0 on entry"); + return kAudio_ParamError; + } + + UInt32 actualPropertySize = 0; + result = AUInstance(self)->DispatchGetPropertyInfo( + inID, inScope, inElement, actualPropertySize, writable); + if (result != noErr) { + return result; + } + + std::vector tempBuffer; + void* destBuffer = nullptr; + if (clientBufferSize < actualPropertySize) { + tempBuffer.resize(actualPropertySize); + destBuffer = tempBuffer.data(); + } else { + destBuffer = outData; + } + + result = AUInstance(self)->DispatchGetProperty(inID, inScope, inElement, destBuffer); + + if (result == noErr) { + if (clientBufferSize < actualPropertySize && !tempBuffer.empty()) { + memcpy(outData, tempBuffer.data(), clientBufferSize); + // ioDataSize remains correct, the number of bytes we wrote + } else { + *ioDataSize = actualPropertySize; + } + } else { + *ioDataSize = 0; + } + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodSetProperty(void* self, AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + if ((inData != nullptr) && (inDataSize != 0u)) { + result = + AUInstance(self)->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize); + } else { + if (inData == nullptr && inDataSize == 0) { + result = AUInstance(self)->DispatchRemovePropertyValue(inID, inScope, inElement); + } else { + if (inData == nullptr) { + AUSDK_LogError("AudioUnitSetProperty: inData == NULL"); + return kAudio_ParamError; + } + + if (inDataSize == 0) { + AUSDK_LogError("AudioUnitSetProperty: inDataSize == 0"); + return kAudio_ParamError; + } + } + } + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodAddPropertyListener( + void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void* userData) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->AddPropertyListener(prop, proc, userData); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodRemovePropertyListener( + void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->RemovePropertyListener(prop, proc, nullptr, false); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodRemovePropertyListenerWithUserData( + void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void* userData) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->RemovePropertyListener(prop, proc, userData, true); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodAddRenderNotify(void* self, AURenderCallback proc, void* userData) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->SetRenderNotification(proc, userData); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodRemoveRenderNotify(void* self, AURenderCallback proc, void* userData) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->RemoveRenderNotification(proc, userData); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodGetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope, + AudioUnitElement elem, AudioUnitParameterValue* value) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = (value == nullptr ? kAudio_ParamError + : AUInstance(self)->GetParameter(param, scope, elem, *value)); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodSetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope, + AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset) +{ + if (!IsValidParameterValue(value)) { + return kAudioUnitErr_InvalidParameterValue; + } + + OSStatus result = noErr; + try { + // this is a (potentially) realtime method; no lock + result = AUInstance(self)->SetParameter(param, scope, elem, value, bufferOffset); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodScheduleParameters( + void* self, const AudioUnitParameterEvent* events, UInt32 numEvents) +{ + if (!AreValidParameterEvents(events, numEvents)) { + return kAudioUnitErr_InvalidParameterValue; + } + + OSStatus result = noErr; + try { + // this is a (potentially) realtime method; no lock + result = AUInstance(self)->ScheduleParameter(events, numEvents); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodRender(void* self, AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, + AudioBufferList* ioData) +{ + OSStatus result = noErr; + +#if CATCH_EXCEPTIONS_IN_RENDER_METHODS + try { +#endif + // this is a processing method; no lock + AudioUnitRenderActionFlags tempFlags{}; + + if (inTimeStamp == nullptr || ioData == nullptr) { + result = kAudio_ParamError; + } else { + if (ioActionFlags == nullptr) { + tempFlags = 0; + ioActionFlags = &tempFlags; + } + result = AUInstance(self)->DoRender( + *ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData); + } + +#if CATCH_EXCEPTIONS_IN_RENDER_METHODS + } + AUSDK_Catch(result) +#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 CATCH_EXCEPTIONS_IN_RENDER_METHODS + try { +#endif + // this is a processing method; no lock + AudioUnitRenderActionFlags tempFlags{}; + + if (inTimeStamp == nullptr || ioData == nullptr) { + result = kAudio_ParamError; + } else { + if (ioActionFlags == nullptr) { + tempFlags = 0; + ioActionFlags = &tempFlags; + } + result = AUInstance(self)->ComplexRender(*ioActionFlags, *inTimeStamp, + inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, + *ioData, outMetadata, outMetadataByteSize); + } + +#if CATCH_EXCEPTIONS_IN_RENDER_METHODS + } + AUSDK_Catch(result) +#endif + + return result; +} + +static OSStatus AUMethodReset(void* self, AudioUnitScope scope, AudioUnitElement elem) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->Reset(scope, elem); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodProcess(void* self, AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, UInt32 inNumberFrames, AudioBufferList* ioData) +{ + OSStatus result = noErr; + +#if CATCH_EXCEPTIONS_IN_RENDER_METHODS + try { +#endif + // this is a processing method; no lock + bool doParamCheck = true; + + AudioUnitRenderActionFlags tempFlags{}; + + if (ioActionFlags == nullptr) { + tempFlags = 0; + ioActionFlags = &tempFlags; + } else { + if ((*ioActionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) != 0u) { + doParamCheck = false; + } + } + + if (doParamCheck && (inTimeStamp == nullptr || ioData == nullptr)) { + result = kAudio_ParamError; + } else { + result = + AUInstance(self)->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData); + } + +#if CATCH_EXCEPTIONS_IN_RENDER_METHODS + } + AUSDK_Catch(result) +#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 CATCH_EXCEPTIONS_IN_RENDER_METHODS + try { +#endif + // this is a processing method; no lock + bool doParamCheck = true; + + AudioUnitRenderActionFlags tempFlags{}; + + if (ioActionFlags == nullptr) { + tempFlags = 0; + ioActionFlags = &tempFlags; + } else { + if ((*ioActionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) != 0u) { + doParamCheck = false; + } + } + + if (doParamCheck && (inTimeStamp == nullptr || inInputBufferLists == nullptr || + ioOutputBufferLists == nullptr)) { + result = kAudio_ParamError; + } else { + result = AUInstance(self)->DoProcessMultiple(*ioActionFlags, *inTimeStamp, + inNumberFrames, inNumberInputBufferLists, inInputBufferLists, + inNumberOutputBufferLists, ioOutputBufferLists); + } + +#if CATCH_EXCEPTIONS_IN_RENDER_METHODS + } + AUSDK_Catch(result) +#endif + + return result; +} +// ------------------------------------------------------------------------------------------------ + +static OSStatus AUMethodStart(void* self) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->Start(); + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodStop(void* self) +{ + OSStatus result = noErr; + try { + const AUInstanceGuard guard(self); + result = AUInstance(self)->Stop(); + } + AUSDK_Catch(result) + return result; +} + +// ------------------------------------------------------------------------------------------------ + +// 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 = AUInstance(self)->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame); + } + AUSDK_Catch(result) + 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 = AUInstance(self)->SysEx(inData, inLength); + } + AUSDK_Catch(result) + return result; +} + +#if AUSDK_MIDI2_AVAILABLE +static OSStatus AUMethodMIDIEventList( + void* self, UInt32 inOffsetSampleFrame, const struct MIDIEventList* eventList) +{ + if (eventList == nullptr) { + return kAudio_ParamError; + } + + OSStatus result = noErr; + try { + // this is a potential render-time method; no lock + + // Note that a MIDIEventList is variably-sized and can be backed by less memory than + // required, so it is Undefined Behavior to form a reference to it; we must only use + // pointers. + result = AUInstance(self)->MIDIEventList(inOffsetSampleFrame, eventList); + } + AUSDK_Catch(result) + return result; +} +#endif + +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 == nullptr) { + result = kAudio_ParamError; + } else { + result = AUInstance(self)->StartNote( + inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams); + } + } + AUSDK_Catch(result) + 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 = AUInstance(self)->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame); + } + AUSDK_Catch(result) + return result; +} + +#if HAVE_MUSICDEVICE_PREPARE_RELEASE +static OSStatus AUMethodPrepareInstrument(void* self, MusicDeviceInstrumentID inInstrument) +{ + OSStatus result = noErr; + try { + // this is a potential render-time method; no lock + result = AUInstance(self)->PrepareInstrument(inInstrument); // NOLINT static via instance + } + AUSDK_Catch(result) + return result; +} + +static OSStatus AUMethodReleaseInstrument(void* self, MusicDeviceInstrumentID inInstrument) +{ + OSStatus result = noErr; + try { + // this is a potential render-time method; no lock + result = AUInstance(self)->ReleaseInstrument(inInstrument); // NOLINT static via instance + } + AUSDK_Catch(result) + return result; +} +#endif // HAVE_MUSICDEVICE_PREPARE_RELEASE + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#pragma mark - +#pragma mark Lookup Methods + +AudioComponentMethod AUBaseLookup::Lookup(SInt16 selector) +{ + switch (selector) { + case kAudioUnitInitializeSelect: + return (AudioComponentMethod)AUMethodInitialize; // NOLINT cast + case kAudioUnitUninitializeSelect: + return (AudioComponentMethod)AUMethodUninitialize; // NOLINT cast + case kAudioUnitGetPropertyInfoSelect: + return (AudioComponentMethod)AUMethodGetPropertyInfo; // NOLINT cast + case kAudioUnitGetPropertySelect: + return (AudioComponentMethod)AUMethodGetProperty; // NOLINT cast + case kAudioUnitSetPropertySelect: + return (AudioComponentMethod)AUMethodSetProperty; // NOLINT cast + case kAudioUnitAddPropertyListenerSelect: + return (AudioComponentMethod)AUMethodAddPropertyListener; // NOLINT cast + case kAudioUnitRemovePropertyListenerSelect: + return (AudioComponentMethod)AUMethodRemovePropertyListener; // NOLINT cast + case kAudioUnitRemovePropertyListenerWithUserDataSelect: + return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData; // NOLINT cast + case kAudioUnitAddRenderNotifySelect: + return (AudioComponentMethod)AUMethodAddRenderNotify; // NOLINT cast + case kAudioUnitRemoveRenderNotifySelect: + return (AudioComponentMethod)AUMethodRemoveRenderNotify; // NOLINT cast + case kAudioUnitGetParameterSelect: + return (AudioComponentMethod)AUMethodGetParameter; // NOLINT cast + case kAudioUnitSetParameterSelect: + return (AudioComponentMethod)AUMethodSetParameter; // NOLINT cast + case kAudioUnitScheduleParametersSelect: + return (AudioComponentMethod)AUMethodScheduleParameters; // NOLINT cast + case kAudioUnitRenderSelect: + return (AudioComponentMethod)AUMethodRender; // NOLINT cast + case kAudioUnitResetSelect: + return (AudioComponentMethod)AUMethodReset; // NOLINT cast + default: + break; + } + return nullptr; +} + +AudioComponentMethod AUOutputLookup::Lookup(SInt16 selector) +{ + const AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + switch (selector) { + case kAudioOutputUnitStartSelect: + return (AudioComponentMethod)AUMethodStart; // NOLINT cast + case kAudioOutputUnitStopSelect: + return (AudioComponentMethod)AUMethodStop; // NOLINT cast + default: + break; + } + return nullptr; +} + +AudioComponentMethod AUComplexOutputLookup::Lookup(SInt16 selector) +{ + AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + method = AUOutputLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + if (selector == kAudioUnitComplexRenderSelect) { + return (AudioComponentMethod)AUMethodComplexRender; // NOLINT cast + } + return nullptr; +} + +AudioComponentMethod AUBaseProcessLookup::Lookup(SInt16 selector) +{ + const AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + if (selector == kAudioUnitProcessSelect) { + return (AudioComponentMethod)AUMethodProcess; // NOLINT cast + } + + return nullptr; +} + +AudioComponentMethod AUBaseProcessMultipleLookup::Lookup(SInt16 selector) +{ + const AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + if (selector == kAudioUnitProcessMultipleSelect) { + return (AudioComponentMethod)AUMethodProcessMultiple; // NOLINT cast + } + + return nullptr; +} + +AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup(SInt16 selector) +{ + AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + method = AUBaseProcessMultipleLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + method = AUBaseProcessLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + return nullptr; +} + +inline AudioComponentMethod MIDI_Lookup(SInt16 selector) +{ + switch (selector) { + case kMusicDeviceMIDIEventSelect: + return (AudioComponentMethod)AUMethodMIDIEvent; // NOLINT cast + case kMusicDeviceSysExSelect: + return (AudioComponentMethod)AUMethodSysEx; // NOLINT cast +#if AUSDK_MIDI2_AVAILABLE + case kMusicDeviceMIDIEventListSelect: + return (AudioComponentMethod)AUMethodMIDIEventList; // NOLINT cast +#endif + default: + break; + } + return nullptr; +} + +AudioComponentMethod AUMIDILookup::Lookup(SInt16 selector) +{ + const AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + return MIDI_Lookup(selector); +} + +AudioComponentMethod AUMIDIProcessLookup::Lookup(SInt16 selector) +{ + const AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + return MIDI_Lookup(selector); +} + +AudioComponentMethod AUMusicLookup::Lookup(SInt16 selector) +{ + const AudioComponentMethod method = AUBaseLookup::Lookup(selector); + if (method != nullptr) { + return method; + } + + switch (selector) { + case kMusicDeviceStartNoteSelect: + return (AudioComponentMethod)AUMethodStartNote; // NOLINT cast + case kMusicDeviceStopNoteSelect: + return (AudioComponentMethod)AUMethodStopNote; // NOLINT cast +#if HAVE_MUSICDEVICE_PREPARE_RELEASE + case kMusicDevicePrepareInstrumentSelect: + return (AudioComponentMethod)AUMethodPrepareInstrument; // NOLINT cast + case kMusicDeviceReleaseInstrumentSelect: + return (AudioComponentMethod)AUMethodReleaseInstrument; // NOLINT cast +#endif + default: + break; + } + return MIDI_Lookup(selector); +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.h new file mode 100644 index 0000000000..3f9c69a1f7 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.h @@ -0,0 +1,110 @@ +/*! + @file AudioUnitSDK/AUPlugInDispatch.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUPlugInDispatch_h +#define AudioUnitSDK_AUPlugInDispatch_h + +#include + +namespace ausdk { + +/// Method lookup for a basic AUBase subclass. +struct AUBaseLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for a basic AUBase subclass. +template +class AUBaseFactory : public APFactory { +}; + +/// Method lookup for a AUBase subclass which implements I/O methods (Start, Stop). +struct AUOutputLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements I/O methods (Start, Stop). +template +class AUOutputBaseFactory : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements I/O methods (Start, Stop) and +/// ComplexRender. +struct AUComplexOutputLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements I/O methods (Start, Stop) and ComplexRender. +template +class AUOutputComplexBaseFactory : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements Process. +struct AUBaseProcessLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements Process. +template +class AUBaseProcessFactory : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements ProcessMultiple. +struct AUBaseProcessMultipleLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements ProcessMultiple. +template +class AUBaseProcessMultipleFactory : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements Process and ProcessMultiple. +struct AUBaseProcessAndMultipleLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements Process and ProcessMultiple. +template +class AUBaseProcessAndMultipleFactory + : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements MusicDevice methods (MIDIEvent and SysEx). +struct AUMIDILookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements MusicDevice methods (MIDIEvent and SysEx). +template +class AUMIDIEffectFactory : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements Process and MusicDevice methods (MIDIEvent +/// and SysEx). +struct AUMIDIProcessLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements Process and MusicDevice methods (MIDIEvent +/// and SysEx). +template +class AUMIDIProcessFactory : public APFactory { +}; + +/// Method lookup for an AUBase subclass which implements the full set of MusicDevice methods +/// (MIDIEvent, SysEx, StartNote, StopNote). +struct AUMusicLookup { + static AudioComponentMethod Lookup(SInt16 selector); +}; + +/// Factory for an AUBase subclass which implements the full set of MusicDevice methods +/// (MIDIEvent, SysEx, StartNote, StopNote). +template +class AUMusicDeviceFactory : public APFactory { +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUPlugInDispatch_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.cpp new file mode 100644 index 0000000000..571a24a759 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.cpp @@ -0,0 +1,442 @@ +/*! + @file AudioUnitSDK/AUScopeElement.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include +#include + +#include + +#include + +namespace ausdk { + +//_____________________________________________________________________________ +// +// By default, parameterIDs may be arbitrarily spaced, and a flat 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(UInt32 inNumberOfParameters) +{ + mIndexedParameters.resize(inNumberOfParameters); + mUseIndexedParameters = true; +} + +//_____________________________________________________________________________ +// +// Helper method. +// returns whether the specified paramID is known to the element +// +bool AUElement::HasParameterID(AudioUnitParameterID paramID) const +{ + if (mUseIndexedParameters) { + return paramID < mIndexedParameters.size(); + } + + return mParameters.find(paramID) != mParameters.end(); +} + +//_____________________________________________________________________________ +// +// caller assumes that this is actually an immediate parameter +// +AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID) const +{ + if (mUseIndexedParameters) { + ausdk::ThrowExceptionIf( + paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter); + return mIndexedParameters[paramID].load(std::memory_order_acquire); + } + const auto i = mParameters.find(paramID); + ausdk::ThrowExceptionIf(i == mParameters.end(), kAudioUnitErr_InvalidParameter); + return (*i).second.load(std::memory_order_acquire); +} + +//_____________________________________________________________________________ +// +void AUElement::SetParameter( + AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized) +{ + if (mUseIndexedParameters) { + ausdk::ThrowExceptionIf( + paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter); + mIndexedParameters[paramID].store(inValue, std::memory_order_release); + } else { + const auto 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. + // Throw(kAudioUnitErr_InvalidParameter); + AUSDK_LogError( + "Warning: %s SetParameter for undefined param ID %u while initialized. " + "Ignoring.", + mAudioUnit.GetLoggingString(), static_cast(paramID)); + } else { + // create new entry in map for the paramID (only happens first time) + mParameters[paramID] = ParameterValue{ inValue }; + } + } else { + // paramID already exists in map so simply change its value + (*i).second.store(inValue, std::memory_order_release); + } + } +} + +//_____________________________________________________________________________ +// +void AUElement::SetScheduledEvent(AudioUnitParameterID paramID, + const AudioUnitParameterEvent& inEvent, UInt32 /*inSliceOffsetInBuffer*/, + UInt32 /*inSliceDurationFrames*/, bool okWhenInitialized) +{ + if (inEvent.eventType != kParameterEvent_Immediate) { + AUSDK_LogError("Warning: %s was passed a ramped parameter event but does not implement " + "them. Ignoring.", + mAudioUnit.GetLoggingString()); + return; + } + SetParameter(paramID, inEvent.eventValues.immediate.value, okWhenInitialized); // NOLINT +} + +//_____________________________________________________________________________ +// +void AUElement::GetParameterList(AudioUnitParameterID* outList) +{ + if (mUseIndexedParameters) { + const auto nparams = static_cast(mIndexedParameters.size()); + for (UInt32 i = 0; i < nparams; i++) { + *outList++ = (AudioUnitParameterID)i; // NOLINT + } + } else { + for (const auto& param : mParameters) { + *outList++ = param.first; // NOLINT + } + } +} + +//_____________________________________________________________________________ +// +void AUElement::SaveState(AudioUnitScope scope, CFMutableDataRef data) +{ + AudioUnitParameterInfo paramInfo{}; + const CFIndex countOffset = CFDataGetLength(data); + uint32_t paramsWritten = 0; + + const auto appendBytes = [data](const void* bytes, CFIndex length) { + CFDataAppendBytes(data, static_cast(bytes), length); + }; + + const auto appendParameter = [&](AudioUnitParameterID paramID, AudioUnitParameterValue value) { + struct { + UInt32 paramID; + UInt32 value; // really a big-endian float + } entry{}; + static_assert(sizeof(entry) == (sizeof(entry.paramID) + sizeof(entry.value))); + + if (mAudioUnit.GetParameterInfo(scope, paramID, paramInfo) == noErr) { + if ((paramInfo.flags & kAudioUnitParameterFlag_CFNameRelease) != 0u) { + if (paramInfo.cfNameString != nullptr) { + CFRelease(paramInfo.cfNameString); + } + if (paramInfo.unit == kAudioUnitParameterUnit_CustomUnit && + paramInfo.unitName != nullptr) { + CFRelease(paramInfo.unitName); + } + } + if (((paramInfo.flags & kAudioUnitParameterFlag_OmitFromPresets) != 0u) || + ((paramInfo.flags & kAudioUnitParameterFlag_MeterReadOnly) != 0u)) { + return; + } + } + + entry.paramID = CFSwapInt32HostToBig(paramID); + entry.value = CFSwapInt32HostToBig(*reinterpret_cast(&value)); // NOLINT + + appendBytes(&entry, sizeof(entry)); + ++paramsWritten; + }; + + constexpr UInt32 placeholderCount = 0; + appendBytes(&placeholderCount, sizeof(placeholderCount)); + + if (mUseIndexedParameters) { + const auto nparams = static_cast(mIndexedParameters.size()); + for (UInt32 i = 0; i < nparams; i++) { + appendParameter(i, mIndexedParameters[i]); + } + } else { + for (const auto& item : mParameters) { + appendParameter(item.first, item.second); + } + } + + const auto count_BE = CFSwapInt32HostToBig(paramsWritten); + memcpy(CFDataGetMutableBytePtr(data) + countOffset, // NOLINT ptr math + &count_BE, sizeof(count_BE)); +} + +//_____________________________________________________________________________ +// +const UInt8* AUElement::RestoreState(const UInt8* state) +{ + union FloatInt32 { + UInt32 i; + AudioUnitParameterValue f; + }; + const UInt8* p = state; + const UInt32 nparams = CFSwapInt32BigToHost(*reinterpret_cast(p)); // NOLINT + p += sizeof(UInt32); // NOLINT + + for (UInt32 i = 0; i < nparams; ++i) { + struct { + AudioUnitParameterID paramID; + AudioUnitParameterValue value; + } entry{}; + static_assert(sizeof(entry) == (sizeof(entry.paramID) + sizeof(entry.value))); + + entry.paramID = CFSwapInt32BigToHost(*reinterpret_cast(p)); // NOLINT + p += sizeof(UInt32); // NOLINT + FloatInt32 temp{}; // NOLINT + temp.i = CFSwapInt32BigToHost(*reinterpret_cast(p)); // NOLINT + entry.value = temp.f; // NOLINT + p += sizeof(AudioUnitParameterValue); // NOLINT + + SetParameter(entry.paramID, entry.value); + } + return p; +} + +//_____________________________________________________________________________ +// +AUIOElement::AUIOElement(AUBase& audioUnit) : AUElement(audioUnit), mWillAllocate(true) +{ + mStreamFormat = AudioStreamBasicDescription{ .mSampleRate = AUBase::kAUDefaultSampleRate, + .mFormatID = kAudioFormatLinearPCM, + .mFormatFlags = AudioFormatFlags(kAudioFormatFlagsNativeFloatPacked) | + AudioFormatFlags(kAudioFormatFlagIsNonInterleaved), // NOLINT + .mBytesPerPacket = sizeof(float), + .mFramesPerPacket = 1, + .mBytesPerFrame = sizeof(float), + .mChannelsPerFrame = 2, + .mBitsPerChannel = 32, // NOLINT + .mReserved = 0 }; +} + +//_____________________________________________________________________________ +// +OSStatus AUIOElement::SetStreamFormat(const AudioStreamBasicDescription& format) +{ + mStreamFormat = format; + + // Clear the previous channel layout if it is inconsistent with the newly set format; + // preserve it if it is acceptable, in case the new format has no layout. + if (ChannelLayout().IsValid() && NumberChannels() != ChannelLayout().NumberChannels()) { + RemoveAudioChannelLayout(); + } + + return 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(); + + mIOBuffer.Allocate( + mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0); + } +} + +//_____________________________________________________________________________ +// +void AUIOElement::DeallocateBuffer() { mIOBuffer.Deallocate(); } + +//_____________________________________________________________________________ +// +// AudioChannelLayout support + +// return an empty vector (ie. NO channel layouts) if the AU doesn't require channel layout +// knowledge +std::vector AUIOElement::GetChannelLayoutTags() { return {}; } + +// outLayoutPtr WILL be NULL if called to determine layout size +UInt32 AUIOElement::GetAudioChannelLayout(AudioChannelLayout* outLayoutPtr, bool& outWritable) +{ + outWritable = true; + + UInt32 size = mChannelLayout.IsValid() ? mChannelLayout.Size() : 0; + if (size > 0 && outLayoutPtr != nullptr) { + memcpy(outLayoutPtr, &mChannelLayout.Layout(), size); + } + + return size; +} + +// 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& inLayout) +{ + if (NumberChannels() != AUChannelLayout::NumberChannels(inLayout)) { + return kAudioUnitErr_InvalidPropertyValue; + } + mChannelLayout = inLayout; + return noErr; +} + +// 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() +{ + mChannelLayout = {}; + return noErr; +} + +//_____________________________________________________________________________ +// +void AUScope::SetNumberOfElements(UInt32 numElements) +{ + if (mDelegate != nullptr) { + return mDelegate->SetNumberOfElements(numElements); + } + + if (numElements > mElements.size()) { + mElements.reserve(numElements); + while (numElements > mElements.size()) { + auto elem = mCreator->CreateElement(GetScope(), static_cast(mElements.size())); + mElements.push_back(std::move(elem)); + } + } else { + while (numElements < mElements.size()) { + mElements.pop_back(); + } + } +} + +//_____________________________________________________________________________ +// +bool AUScope::HasElementWithName() const +{ + for (UInt32 i = 0; i < GetNumberOfElements(); ++i) { + AUElement* const el = GetElement(i); + if ((el != nullptr) && el->HasName()) { + return true; + } + } + return false; +} + +//_____________________________________________________________________________ +// + +void AUScope::AddElementNamesToDict(CFMutableDictionaryRef inNameDict) const +{ + if (HasElementWithName()) { + const auto elementDict = + Owned::from_create(CFDictionaryCreateMutable( + nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + for (UInt32 i = 0; i < GetNumberOfElements(); ++i) { + AUElement* const el = GetElement(i); + if (el != nullptr && el->HasName()) { + const auto key = Owned::from_create(CFStringCreateWithFormat( + nullptr, nullptr, CFSTR("%u"), static_cast(i))); + CFDictionarySetValue(*elementDict, *key, *el->GetName()); + } + } + + const auto key = Owned::from_create( + CFStringCreateWithFormat(nullptr, nullptr, CFSTR("%u"), static_cast(mScope))); + CFDictionarySetValue(inNameDict, *key, *elementDict); + } +} + +//_____________________________________________________________________________ +// +std::vector AUScope::RestoreElementNames(CFDictionaryRef inNameDict) const +{ + // first we have to see if we have enough elements + std::vector restoredElements; + const auto maxElNum = GetNumberOfElements(); + + const auto dictSize = + static_cast(std::max(CFDictionaryGetCount(inNameDict), CFIndex(0))); + std::vector keys(dictSize); + CFDictionaryGetKeysAndValues( + inNameDict, reinterpret_cast(keys.data()), nullptr); // NOLINT + for (size_t i = 0; i < dictSize; i++) { + unsigned int intKey = 0; + std::array string{}; + CFStringGetCString(keys[i], string.data(), string.size(), kCFStringEncodingASCII); + const int result = sscanf(string.data(), "%u", &intKey); // NOLINT + // check if sscanf succeeded and element index is less than max elements. + if ((result != 0) && (static_cast(intKey) < maxElNum)) { + auto* const elName = + static_cast(CFDictionaryGetValue(inNameDict, keys[i])); + if ((elName != nullptr) && (CFGetTypeID(elName) == CFStringGetTypeID())) { + AUElement* const element = GetElement(intKey); + if (element != nullptr) { + element->SetName(elName); + restoredElements.push_back(intKey); + } + } + } + } + + return restoredElements; +} + +void AUScope::SaveState(CFMutableDataRef data) const +{ + const AudioUnitElement nElems = GetNumberOfElements(); + for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) { + AUElement* const element = GetElement(ielem); + const UInt32 nparams = element->GetNumberOfParameters(); + if (nparams > 0) { + struct { + const UInt32 scope; + const UInt32 element; + } hdr{ .scope = CFSwapInt32HostToBig(GetScope()), + .element = CFSwapInt32HostToBig(ielem) }; + static_assert(sizeof(hdr) == (sizeof(hdr.scope) + sizeof(hdr.element))); + CFDataAppendBytes(data, reinterpret_cast(&hdr), sizeof(hdr)); // NOLINT + + element->SaveState(mScope, data); + } + } +} + +const UInt8* AUScope::RestoreState(const UInt8* state) const +{ + const UInt8* p = state; + const UInt32 elementIdx = CFSwapInt32BigToHost(*reinterpret_cast(p)); // NOLINT + p += sizeof(UInt32); // NOLINT + AUElement* const element = GetElement(elementIdx); + if (element == nullptr) { + struct { + AudioUnitParameterID paramID; + AudioUnitParameterValue value; + } entry{}; + static_assert(sizeof(entry) == (sizeof(entry.paramID) + sizeof(entry.value))); + const UInt32 nparams = CFSwapInt32BigToHost(*reinterpret_cast(p)); // NOLINT + p += sizeof(UInt32); // NOLINT + + p += nparams * sizeof(entry); // NOLINT + } else { + p = element->RestoreState(p); + } + + return p; +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.h new file mode 100644 index 0000000000..0963110cb2 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.h @@ -0,0 +1,435 @@ +/*! + @file AudioUnitSDK/AUScopeElement.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUScopeElement_h +#define AudioUnitSDK_AUScopeElement_h + +// module +#include +#include +#include + +// OS +#include + +// std +#include +#include +#include +#include + +namespace ausdk { + +class AUBase; + +/// Wrap an atomic in a copy-constructible/assignable object. This allows storing atomic values in a +/// vector (not directly possible since atomics are not copy-constructible/assignable). +template +class AtomicValue { +public: + AtomicValue() = default; + explicit AtomicValue(T val) : mValue{ val } {} + ~AtomicValue() = default; + + AtomicValue(const AtomicValue& other) : mValue{ other.mValue.load() } {} + AtomicValue(AtomicValue&& other) noexcept : mValue{ other.mValue.load() } {} + + AtomicValue& operator=(const AtomicValue& other) + { + if (&other != this) { + mValue.store(other.mValue.load()); + } + return *this; + } + + AtomicValue& operator=(AtomicValue&& other) noexcept + { + mValue.store(other.mValue.load()); + return *this; + } + + T load(std::memory_order m = std::memory_order_seq_cst) const { return mValue.load(m); } + void store(T v, std::memory_order m = std::memory_order_seq_cst) { mValue.store(v, m); } + + operator T() const { return load(); } // NOLINT implicit conversions OK + + AtomicValue& operator=(T value) + { + store(value); + return *this; + } + +private: + std::atomic mValue{}; +}; + +/// A bare-bones reinvention of boost::flat_map, just enough to hold parameters in sorted vectors. +template +class flat_map { + using KVPair = std::pair; + using Impl = std::vector>; + + static bool keyless(const KVPair& item, Key k) { return k > item.first; } + + Impl mImpl; + +public: + using iterator = typename Impl::iterator; + using const_iterator = typename Impl::const_iterator; + + [[nodiscard]] bool empty() const { return mImpl.empty(); } + [[nodiscard]] size_t size() const { return mImpl.size(); } + [[nodiscard]] const_iterator begin() const { return mImpl.begin(); } + [[nodiscard]] const_iterator end() const { return mImpl.end(); } + iterator begin() { return mImpl.begin(); } + iterator end() { return mImpl.end(); } + const_iterator cbegin() { return mImpl.cbegin(); } + const_iterator cend() { return mImpl.cend(); } + + [[nodiscard]] const_iterator lower_bound(Key k) const + { + return std::lower_bound(mImpl.begin(), mImpl.end(), k, keyless); + } + + iterator lower_bound(Key k) { return std::lower_bound(mImpl.begin(), mImpl.end(), k, keyless); } + + [[nodiscard]] const_iterator find(Key k) const + { + auto iter = lower_bound(k); + if (iter != mImpl.end()) { + if ((*iter).first != k) { + iter = mImpl.end(); + } + } + return iter; + } + + iterator find(Key k) + { + auto iter = lower_bound(k); + if (iter != mImpl.end()) { + if ((*iter).first != k) { + iter = mImpl.end(); + } + } + return iter; + } + + class ItemProxy { + public: + ItemProxy(flat_map& map, Key k) : mMap{ map }, mKey{ k } {} + + operator Value() const // NOLINT implicit conversion is OK + { + const auto iter = mMap.find(mKey); + if (iter == mMap.end()) { + throw std::runtime_error("Invalid map key"); + } + return (*iter).second; + } + + ItemProxy& operator=(const Value& v) + { + const auto iter = mMap.lower_bound(mKey); + if (iter != mMap.end() && (*iter).first == mKey) { + (*iter).second = v; + } else { + mMap.mImpl.insert(iter, { mKey, v }); + } + return *this; + } + + private: + flat_map& mMap; + const Key mKey; + }; + + ItemProxy operator[](Key k) { return ItemProxy{ *this, k }; } +}; + +// ____________________________________________________________________________ +// +class AUIOElement; + +/// An organizational unit for parameters, with a name. +class AUElement { + using ParameterValue = AtomicValue; + using ParameterMap = flat_map; + +public: + explicit AUElement(AUBase& audioUnit) : mAudioUnit(audioUnit), mUseIndexedParameters(false) {} + + AUSDK_DEPRECATED("Construct with a reference") + explicit AUElement(AUBase* audioUnit) : AUElement(*audioUnit) {} + + AUElement(const AUElement&) = delete; + AUElement(AUElement&&) = delete; + AUElement& operator=(const AUElement&) = delete; + AUElement& operator=(AUElement&&) = delete; + + virtual ~AUElement() = default; + + virtual UInt32 GetNumberOfParameters() + { + return mUseIndexedParameters ? static_cast(mIndexedParameters.size()) + : static_cast(mParameters.size()); + } + virtual void GetParameterList(AudioUnitParameterID* outList); + [[nodiscard]] bool HasParameterID(AudioUnitParameterID paramID) const; + [[nodiscard]] AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID) const; + + // Only set okWhenInitialized to true when you know the outside world cannot access this + // element. Otherwise the parameter map could get corrupted. + 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. N.B. This only handles + // immediate parameters. Override to implement ramping. Called from + // AUBase::ProcessForScheduledParams. + virtual void SetScheduledEvent(AudioUnitParameterID paramID, + const AudioUnitParameterEvent& inEvent, UInt32 inSliceOffsetInBuffer, + UInt32 inSliceDurationFrames, bool okWhenInitialized = false); + + [[nodiscard]] AUBase& GetAudioUnit() const noexcept { return mAudioUnit; } + + void SaveState(AudioUnitScope scope, CFMutableDataRef data); + const UInt8* RestoreState(const UInt8* state); + + [[nodiscard]] Owned GetName() const { return mElementName; } + void SetName(CFStringRef inName) { mElementName = inName; } + + [[nodiscard]] bool HasName() const { return *mElementName != nil; } + + virtual void UseIndexedParameters(UInt32 inNumberOfParameters); + + virtual AUIOElement* AsIOElement() { return nullptr; } + +private: + // -- + AUBase& mAudioUnit; + ParameterMap mParameters; + bool mUseIndexedParameters; + std::vector mIndexedParameters; + Owned mElementName; +}; + + +// ____________________________________________________________________________ +// + +/// A subclass of AUElement which represents an input or output bus, and has an associated +/// audio format and buffers. +class AUIOElement : public AUElement { +public: + explicit AUIOElement(AUBase& audioUnit); + + AUIOElement(AUBase& audioUnit, const AudioStreamBasicDescription& format) + : AUIOElement{ audioUnit } + { + mStreamFormat = format; + } + + AUSDK_DEPRECATED("Construct with a reference") + explicit AUIOElement(AUBase* audioUnit) : AUIOElement(*audioUnit) {} + + [[nodiscard]] const AudioStreamBasicDescription& GetStreamFormat() const noexcept + { + return mStreamFormat; + } + + virtual OSStatus SetStreamFormat(const AudioStreamBasicDescription& format); + + virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0); + + void DeallocateBuffer(); + + /// Determines (via subclass override) whether the element's buffer list needs to be allocated. + [[nodiscard]] virtual bool NeedsBufferSpace() const = 0; + + void SetWillAllocateBuffer(bool inFlag) noexcept { mWillAllocate = inFlag; } + + [[nodiscard]] bool WillAllocateBuffer() const noexcept { return mWillAllocate; } + + AudioBufferList& PrepareBuffer(UInt32 nFrames) + { + if (mWillAllocate) { + return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames); + } + Throw(kAudioUnitErr_InvalidPropertyValue); + } + + AudioBufferList& PrepareNullBuffer(UInt32 nFrames) + { + return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames); + } + AudioBufferList& SetBufferList(AudioBufferList& abl) { return mIOBuffer.SetBufferList(abl); } + void SetBuffer(UInt32 index, AudioBuffer& ab) { mIOBuffer.SetBuffer(index, ab); } + void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); } + [[nodiscard]] AudioBufferList& GetBufferList() const { return mIOBuffer.GetBufferList(); } + + [[nodiscard]] float* GetFloat32ChannelData(UInt32 ch) + { + if (IsInterleaved()) { + return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; // NOLINT + } + return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); // NOLINT + } + + void CopyBufferListTo(AudioBufferList& abl) const { mIOBuffer.CopyBufferListTo(abl); } + void CopyBufferContentsTo(AudioBufferList& abl) const { mIOBuffer.CopyBufferContentsTo(abl); } + [[nodiscard]] bool IsInterleaved() const noexcept { return ASBD::IsInterleaved(mStreamFormat); } + [[nodiscard]] UInt32 NumberChannels() const noexcept { return mStreamFormat.mChannelsPerFrame; } + [[nodiscard]] UInt32 NumberInterleavedChannels() const noexcept + { + return ASBD::NumberInterleavedChannels(mStreamFormat); + } + virtual std::vector GetChannelLayoutTags(); + + [[nodiscard]] const AUChannelLayout& ChannelLayout() const { return mChannelLayout; } + + // Old layout methods + virtual OSStatus SetAudioChannelLayout(const AudioChannelLayout& inLayout); + virtual UInt32 GetAudioChannelLayout(AudioChannelLayout* outLayoutPtr, bool& outWritable); + + virtual OSStatus RemoveAudioChannelLayout(); + + /*! @fn AsIOElement*/ + AUIOElement* AsIOElement() override { return this; } + +protected: + AUBufferList& IOBuffer() noexcept { return mIOBuffer; } + void ForceSetAudioChannelLayout(const AudioChannelLayout& inLayout) + { + mChannelLayout = inLayout; + } + +private: + AudioStreamBasicDescription mStreamFormat{}; + AUChannelLayout mChannelLayout{}; + AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed + // for output: output cache, usually allocated early on + bool mWillAllocate{ false }; +}; + +// ____________________________________________________________________________ +// +/*! + @class AUScopeDelegate + @brief Provides a way to customize a scope, thereby obtaining virtual scopes. + + Can be used to implement scopes with variable numbers of elements. +*/ +class AUScopeDelegate { +public: + AUScopeDelegate() = default; + + virtual ~AUScopeDelegate() = default; + + AUScopeDelegate(const AUScopeDelegate&) = delete; + AUScopeDelegate(AUScopeDelegate&&) = delete; + AUScopeDelegate& operator=(const AUScopeDelegate&) = delete; + AUScopeDelegate& operator=(AUScopeDelegate&&) = delete; + + void Initialize(AUBase* creator, AudioUnitScope scope, UInt32 numElements) + { + mCreator = creator; + mScope = scope; + SetNumberOfElements(numElements); + } + virtual void SetNumberOfElements(UInt32 numElements) = 0; + virtual UInt32 GetNumberOfElements() = 0; + virtual AUElement* GetElement(UInt32 elementIndex) = 0; + + [[nodiscard]] AUBase* GetCreator() const noexcept { return mCreator; } + [[nodiscard]] AudioUnitScope GetScope() const noexcept { return mScope; } + + +private: + AUBase* mCreator{ nullptr }; + AudioUnitScope mScope{ 0 }; +}; + +// ____________________________________________________________________________ +// +/*! + @class AUScope + @brief Organizes one or more elements into an addressable group (e.g. global, input, output). +*/ +class AUScope { +public: + AUScope() = default; + + ~AUScope() = default; + + AUScope(const AUScope&) = delete; + AUScope(AUScope&&) = delete; + AUScope& operator=(const AUScope&) = delete; + AUScope& operator=(AUScope&&) = delete; + + void Initialize(AUBase* creator, AudioUnitScope scope, UInt32 numElements) + { + mCreator = creator; + mScope = scope; + + if (mDelegate != nullptr) { + return mDelegate->Initialize(creator, scope, numElements); + } + + SetNumberOfElements(numElements); + } + void SetNumberOfElements(UInt32 numElements); + [[nodiscard]] UInt32 GetNumberOfElements() const + { + if (mDelegate != nullptr) { + return mDelegate->GetNumberOfElements(); + } + + return static_cast(mElements.size()); + } + [[nodiscard]] AUElement* GetElement(UInt32 elementIndex) const + { + if (mDelegate != nullptr) { + return mDelegate->GetElement(elementIndex); + } + return elementIndex < mElements.size() ? mElements[elementIndex].get() : nullptr; + } + [[nodiscard]] AUElement* SafeGetElement(UInt32 elementIndex) const + { + AUElement* const element = GetElement(elementIndex); + ausdk::ThrowExceptionIf(element == nullptr, kAudioUnitErr_InvalidElement); + return element; + } + [[nodiscard]] AUIOElement* GetIOElement(UInt32 elementIndex) const + { + AUElement* const element = GetElement(elementIndex); + AUIOElement* const ioel = element != nullptr ? element->AsIOElement() : nullptr; + ausdk::ThrowExceptionIf(ioel == nullptr, kAudioUnitErr_InvalidElement); + return ioel; + } + + [[nodiscard]] bool HasElementWithName() const; + void AddElementNamesToDict(CFMutableDictionaryRef inNameDict) const; + + [[nodiscard]] std::vector RestoreElementNames( + CFDictionaryRef inNameDict) const; + + [[nodiscard]] AudioUnitScope GetScope() const noexcept { return mScope; } + + void SetDelegate(AUScopeDelegate* inDelegate) noexcept { mDelegate = inDelegate; } + void SaveState(CFMutableDataRef data) const; + const UInt8* RestoreState(const UInt8* state) const; + +private: + using ElementVector = std::vector>; + + AUBase* mCreator{ nullptr }; + AudioUnitScope mScope{ 0 }; + ElementVector mElements; + AUScopeDelegate* mDelegate{ nullptr }; +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUScopeElement_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUSilentTimeout.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUSilentTimeout.h new file mode 100644 index 0000000000..1e083039e9 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUSilentTimeout.h @@ -0,0 +1,49 @@ +/*! + @file AudioUnitSDK/AUSilentTimeout.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUSilentTimeout_h +#define AudioUnitSDK_AUSilentTimeout_h + +#include // for UInt32 +#include + +namespace ausdk { + +/*! + @class AUSilentTimeout + @brief Utility to assist in propagating a silence flag from signal-processing + input to output, factoring in a processing delay. +*/ +class AUSilentTimeout { +public: + AUSilentTimeout() = default; + + void Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool& ioSilence) + { + if (ioSilence) { + if (mResetTimer) { + mTimeoutCounter = inTimeoutLimit; + mResetTimer = false; + } + + if (mTimeoutCounter > 0) { + mTimeoutCounter -= std::min(inFramesToProcess, mTimeoutCounter); + ioSilence = false; + } + } else { + // signal to reset the next time we receive silence + mResetTimer = true; + } + } + + void Reset() { mResetTimer = true; } + +private: + UInt32 mTimeoutCounter{ 0 }; + bool mResetTimer{ false }; +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_AUSilentTimeout_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUUtility.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUUtility.h new file mode 100644 index 0000000000..2c8816fa81 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUUtility.h @@ -0,0 +1,524 @@ +/*! + @file AudioUnitSDK/AUUtility.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_AUUtility_h +#define AudioUnitSDK_AUUtility_h + +// OS +#if defined __has_include && __has_include() +#include +#else +#include +#endif +#include +#include +#include +#include + +// std +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark General + +#ifdef AUSDK_NO_DEPRECATIONS +#define AUSDK_DEPRECATED(msg) +#else +#define AUSDK_DEPRECATED(msg) [[deprecated(msg)]] // NOLINT macro +#endif + +#ifndef AUSDK_LOG_OBJECT +#define AUSDK_LOG_OBJECT OS_LOG_DEFAULT // NOLINT macro +#endif + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark Version + +#define AUSDK_VERSION_MAJOR 1 +#define AUSDK_VERSION_MINOR 1 +#define AUSDK_VERSION_PATCH 0 + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark Error-handling macros + +#ifdef AUSDK_NO_LOGGING +#define AUSDK_LogError(...) /* NOLINT macro */ +#else +#define AUSDK_LogError(...) /* NOLINT macro */ \ + if (__builtin_available(macOS 10.11, *)) { \ + os_log_error(AUSDK_LOG_OBJECT, __VA_ARGS__); \ + } else { \ + syslog(LOG_ERR, __VA_ARGS__); \ + } +#endif + +#define AUSDK_Catch(result) /* NOLINT(cppcoreguidelines-macro-usage) */ \ + catch (const ausdk::AUException& exc) { (result) = exc.mError; } \ + catch (const std::bad_alloc&) { (result) = kAudio_MemFullError; } \ + catch (const OSStatus& catch_err) { (result) = catch_err; } \ + catch (const std::system_error& exc) { (result) = exc.code().value(); } \ + catch (...) { (result) = -1; } + +#define AUSDK_Require(expr, error) /* NOLINT(cppcoreguidelines-macro-usage) */ \ + do { \ + if (!(expr)) { \ + return error; \ + } \ + } while (0) /* NOLINT */ + +#define AUSDK_Require_noerr(expr) /* NOLINT(cppcoreguidelines-macro-usage) */ \ + do { \ + if (const auto status_tmp_macro_detail_ = (expr); status_tmp_macro_detail_ != noErr) { \ + return status_tmp_macro_detail_; \ + } \ + } while (0) + +#pragma mark - + +// ------------------------------------------------------------------------------------------------- + +namespace ausdk { + +// ------------------------------------------------------------------------------------------------- + +/// A subclass of std::runtime_error that holds an OSStatus error. +class AUException : public std::runtime_error { +public: + explicit AUException(OSStatus err) + : std::runtime_error{ std::string("OSStatus ") + std::to_string(err) }, mError{ err } + { + } + + const OSStatus mError; +}; + +inline void ThrowExceptionIf(bool condition, OSStatus err) +{ + if (condition) { + AUSDK_LogError("throwing %d", static_cast(err)); + throw AUException{ err }; + } +} + +[[noreturn]] inline void Throw(OSStatus err) +{ + AUSDK_LogError("throwing %d", static_cast(err)); + throw AUException{ err }; +} + +inline void ThrowQuietIf(bool condition, OSStatus err) +{ + if (condition) { + throw AUException{ err }; + } +} + +[[noreturn]] inline void ThrowQuiet(OSStatus err) { throw AUException{ err }; } + +// ------------------------------------------------------------------------------------------------- + +/// Wrap a std::recursive_mutex in a C++ Mutex (named requirement). Methods are virtual to support +/// customization. +class AUMutex { +public: + AUMutex() = default; + virtual ~AUMutex() = default; + + AUMutex(const AUMutex&) = delete; + AUMutex(AUMutex&&) = delete; + AUMutex& operator=(const AUMutex&) = delete; + AUMutex& operator=(AUMutex&&) = delete; + + virtual void lock() { mImpl.lock(); } + virtual void unlock() { mImpl.unlock(); } + virtual bool try_lock() { return mImpl.try_lock(); } + +private: + std::recursive_mutex mImpl; +}; + +// ------------------------------------------------------------------------------------------------- + +/// Implement optional locking at AudioUnit non-realtime entry points (required only for a small +/// number of plug-ins which must synchronize against external entry points). +class AUEntryGuard { +public: + explicit AUEntryGuard(AUMutex* maybeMutex) : mMutex{ maybeMutex } + { + if (mMutex != nullptr) { + mMutex->lock(); + } + } + + ~AUEntryGuard() + { + if (mMutex != nullptr) { + mMutex->unlock(); + } + } + + AUEntryGuard(const AUEntryGuard&) = delete; + AUEntryGuard(AUEntryGuard&&) = delete; + AUEntryGuard& operator=(const AUEntryGuard&) = delete; + AUEntryGuard& operator=(AUEntryGuard&&) = delete; + +private: + AUMutex* mMutex; +}; + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark ASBD + +/// Utility functions relating to AudioStreamBasicDescription. +namespace ASBD { + +constexpr bool IsInterleaved(const AudioStreamBasicDescription& format) noexcept +{ + return (format.mFormatFlags & kLinearPCMFormatFlagIsNonInterleaved) == 0u; +} + +constexpr UInt32 NumberInterleavedChannels(const AudioStreamBasicDescription& format) noexcept +{ + return IsInterleaved(format) ? format.mChannelsPerFrame : 1; +} + +constexpr UInt32 NumberChannelStreams(const AudioStreamBasicDescription& format) noexcept +{ + return IsInterleaved(format) ? 1 : format.mChannelsPerFrame; +} + +constexpr bool IsCommonFloat32(const AudioStreamBasicDescription& format) noexcept +{ + return ( + format.mFormatID == kAudioFormatLinearPCM && format.mFramesPerPacket == 1 && + format.mBytesPerPacket == format.mBytesPerFrame + // so far, it's a valid PCM format + && (format.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0 && + (format.mChannelsPerFrame == 1 || + (format.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) && + ((format.mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian) && + format.mBitsPerChannel == 32 // NOLINT + && format.mBytesPerFrame == NumberInterleavedChannels(format) * sizeof(float)); +} + +constexpr AudioStreamBasicDescription CreateCommonFloat32( + Float64 sampleRate, UInt32 numChannels, bool interleaved = false) noexcept +{ + constexpr auto sampleSize = sizeof(Float32); + + AudioStreamBasicDescription asbd{}; + asbd.mFormatID = kAudioFormatLinearPCM; + asbd.mFormatFlags = kAudioFormatFlagIsFloat | + static_cast(kAudioFormatFlagsNativeEndian) | + kAudioFormatFlagIsPacked; + asbd.mBitsPerChannel = 8 * sampleSize; // NOLINT magic number + asbd.mChannelsPerFrame = numChannels; + asbd.mFramesPerPacket = 1; + asbd.mSampleRate = sampleRate; + if (interleaved) { + asbd.mBytesPerPacket = asbd.mBytesPerFrame = numChannels * sampleSize; + } else { + asbd.mBytesPerPacket = asbd.mBytesPerFrame = sampleSize; + asbd.mFormatFlags |= kAudioFormatFlagIsNonInterleaved; + } + return asbd; +} + +constexpr bool MinimalSafetyCheck(const AudioStreamBasicDescription& x) noexcept +{ + // This function returns false if there are sufficiently unreasonable 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) // NOLINT SACD sample rate is 2.8224 MHz + && (x.mBytesPerPacket < 1000000) // NOLINT + && (x.mFramesPerPacket < 1000000) // NOLINT + && (x.mBytesPerFrame < 1000000) // NOLINT + && (x.mChannelsPerFrame > 0) && (x.mChannelsPerFrame <= 1024) // NOLINT + && (x.mBitsPerChannel <= 1024) // NOLINT + && (x.mFormatID != 0) && + !(x.mFormatID == kAudioFormatLinearPCM && + (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame)); +} + +inline bool IsEqual( + const AudioStreamBasicDescription& lhs, const AudioStreamBasicDescription& rhs) noexcept +{ + return memcmp(&lhs, &rhs, sizeof(AudioStreamBasicDescription)) == 0; +} + +} // namespace ASBD + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark ACL + +/// Utility functions relating to AudioChannelLayout. +namespace ACL { + +constexpr bool operator==(const AudioChannelLayout& lhs, const AudioChannelLayout& rhs) noexcept +{ + if (lhs.mChannelLayoutTag != rhs.mChannelLayoutTag) { + return false; + } + if (lhs.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) { + return lhs.mChannelBitmap == rhs.mChannelBitmap; + } + if (lhs.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) { + if (lhs.mNumberChannelDescriptions != rhs.mNumberChannelDescriptions) { + return false; + } + for (auto i = 0u; i < lhs.mNumberChannelDescriptions; ++i) { + const auto& lhdesc = lhs.mChannelDescriptions[i]; // NOLINT array subscript + const auto& rhdesc = rhs.mChannelDescriptions[i]; // NOLINT array subscript + + if (lhdesc.mChannelLabel != rhdesc.mChannelLabel) { + return false; + } + if (lhdesc.mChannelLabel == kAudioChannelLabel_UseCoordinates) { + if (memcmp(&lhdesc, &rhdesc, sizeof(AudioChannelDescription)) != 0) { + return false; + } + } + } + } + return true; +} + +} // namespace ACL + +// ------------------------------------------------------------------------------------------------- + +/// Utility wrapper for the variably-sized AudioChannelLayout struct. +class AUChannelLayout { +public: + AUChannelLayout() : AUChannelLayout(0, kAudioChannelLayoutTag_UseChannelDescriptions, 0) {} + + /// Can construct from a layout tag. + explicit AUChannelLayout(AudioChannelLayoutTag inTag) : AUChannelLayout(0, inTag, 0) {} + + AUChannelLayout(uint32_t inNumberChannelDescriptions, AudioChannelLayoutTag inChannelLayoutTag, + AudioChannelBitmap inChannelBitMap) + : mStorage( + kHeaderSize + (inNumberChannelDescriptions * sizeof(AudioChannelDescription)), {}) + { + auto* const acl = reinterpret_cast(mStorage.data()); // NOLINT + + acl->mChannelLayoutTag = inChannelLayoutTag; + acl->mChannelBitmap = inChannelBitMap; + acl->mNumberChannelDescriptions = inNumberChannelDescriptions; + } + + /// Implicit conversion from AudioChannelLayout& is allowed. + AUChannelLayout(const AudioChannelLayout& acl) // NOLINT + : mStorage(kHeaderSize + (acl.mNumberChannelDescriptions * sizeof(AudioChannelDescription))) + { + memcpy(mStorage.data(), &acl, mStorage.size()); + } + + bool operator==(const AUChannelLayout& other) const noexcept + { + return ACL::operator==(Layout(), other.Layout()); + } + + bool operator!=(const AUChannelLayout& y) const noexcept { return !(*this == y); } + + [[nodiscard]] bool IsValid() const noexcept { return NumberChannels() > 0; } + + [[nodiscard]] const AudioChannelLayout& Layout() const noexcept { return *LayoutPtr(); } + + [[nodiscard]] const AudioChannelLayout* LayoutPtr() const noexcept + { + return reinterpret_cast(mStorage.data()); // NOLINT + } + + /// After default construction, this method will return + /// kAudioChannelLayoutTag_UseChannelDescriptions with 0 channel descriptions. + [[nodiscard]] AudioChannelLayoutTag Tag() const noexcept { return Layout().mChannelLayoutTag; } + + [[nodiscard]] uint32_t NumberChannels() const noexcept { return NumberChannels(*LayoutPtr()); } + + [[nodiscard]] uint32_t Size() const noexcept { return static_cast(mStorage.size()); } + + static uint32_t NumberChannels(const AudioChannelLayout& inLayout) noexcept + { + if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) { + return inLayout.mNumberChannelDescriptions; + } + if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) { + return static_cast( + std::bitset<32>(inLayout.mChannelBitmap).count()); // NOLINT magic # + } + return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag); + } + +private: + constexpr static size_t kHeaderSize = offsetof(AudioChannelLayout, mChannelDescriptions[0]); + std::vector mStorage; +}; + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark AudioBufferList + +/// Utility functions relating to AudioBufferList. +namespace ABL { + +// if the return result is odd, there was a null buffer. +inline uint32_t IsBogusAudioBufferList(const AudioBufferList& abl) +{ + const AudioBuffer *buf = abl.mBuffers, *const bufEnd = buf + abl.mNumberBuffers; + uint32_t sum = + 0; // defeat attempts by the compiler to optimize away the code that touches the buffers + uint32_t anyNull = 0; + for (; buf < bufEnd; ++buf) { + const uint32_t* const p = static_cast(buf->mData); + if (p == nullptr) { + anyNull = 1; + continue; + } + const auto dataSize = buf->mDataByteSize; + if (dataSize >= sizeof(*p)) { + const size_t frameCount = dataSize / sizeof(*p); + sum += p[0]; + sum += p[frameCount - 1]; + } + } + return anyNull | (sum & ~1u); +} + +} // namespace ABL + +// ------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark HostTime + +/// Utility functions relating to Mach absolute time. +namespace HostTime { + +/// Returns the current host time +inline uint64_t Current() { return mach_absolute_time(); } + +/// Returns the frequency of the host timebase, in ticks per second. +inline double Frequency() +{ + struct mach_timebase_info timeBaseInfo { + }; // NOLINT + mach_timebase_info(&timeBaseInfo); + // the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9 + return static_cast(timeBaseInfo.denom) / static_cast(timeBaseInfo.numer) * + 1.0e9; // NOLINT +} + +} // namespace HostTime + +// ------------------------------------------------------------------------------------------------- + +/// Basic RAII wrapper for CoreFoundation types +template +class Owned { + explicit Owned(T obj, bool fromget) noexcept : mImpl{ obj } + { + if (fromget) { + retainRef(); + } + } + +public: + static Owned from_get(T obj) noexcept { return Owned{ obj, true }; } + + static Owned from_create(T obj) noexcept { return Owned{ obj, false }; } + static Owned from_copy(T obj) noexcept { return Owned{ obj, false }; } + + Owned() noexcept = default; + ~Owned() noexcept { releaseRef(); } + + Owned(const Owned& other) noexcept : mImpl{ other.mImpl } { retainRef(); } + + Owned(Owned&& other) noexcept : mImpl{ std::exchange(other.mImpl, nullptr) } {} + + Owned& operator=(const Owned& other) noexcept + { + if (this != &other) { + releaseRef(); + mImpl = other.mImpl; + retainRef(); + } + return *this; + } + + Owned& operator=(Owned&& other) noexcept + { + std::swap(mImpl, other.mImpl); + return *this; + } + + T operator*() const noexcept { return get(); } + T get() const noexcept { return mImpl; } + + /// As with `unique_ptr::release()`, releases ownership of the reference to the caller (not + /// to be confused with decrementing the reference count as with `CFRelease()`). + T release() noexcept { return std::exchange(mImpl, nullptr); } + + /// This is a from_get operation. + Owned& operator=(T cfobj) noexcept + { + if (mImpl != cfobj) { + releaseRef(); + mImpl = cfobj; + retainRef(); + } + return *this; + } + +private: + void retainRef() noexcept + { + if (mImpl != nullptr) { + CFRetain(mImpl); + } + } + + void releaseRef() noexcept + { + if (mImpl != nullptr) { + CFRelease(mImpl); + } + } + + T mImpl{ nullptr }; +}; + +// ------------------------------------------------------------------------------------------------- + +constexpr bool safe_isprint(char in_char) noexcept { return (in_char >= ' ') && (in_char <= '~'); } + +inline std::string make_string_from_4cc(uint32_t in_4cc) noexcept +{ +#if !TARGET_RT_BIG_ENDIAN + in_4cc = OSSwapInt32(in_4cc); // NOLINT +#endif + + char* const string = reinterpret_cast(&in_4cc); // NOLINT + for (size_t i = 0; i < sizeof(in_4cc); ++i) { + if (!safe_isprint(string[i])) { // NOLINT + string[i] = '.'; // NOLINT + } + } + return std::string{ string, sizeof(in_4cc) }; +} + +} // namespace ausdk + +#endif // AudioUnitSDK_AUUtility_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AudioUnitSDK.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AudioUnitSDK.h new file mode 100644 index 0000000000..1336244149 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/AudioUnitSDK.h @@ -0,0 +1,22 @@ +/*! + @file AudioUnitSDK/AudioUnitSDK.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_h +#define AudioUnitSDK_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* AudioUnitSDK_h */ diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.cpp new file mode 100644 index 0000000000..d043591226 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.cpp @@ -0,0 +1,98 @@ +/*! + @file AudioUnitSDK/ComponentBase.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +// self +#include +#include + +// std +#include + +namespace ausdk { + +static OSStatus CB_GetComponentDescription( + AudioComponentInstance inInstance, AudioComponentDescription* outDesc); + +std::recursive_mutex& ComponentBase::InitializationMutex() +{ + __attribute__((no_destroy)) static std::recursive_mutex global; + return global; +} + +ComponentBase::ComponentBase(AudioComponentInstance inInstance) : mComponentInstance(inInstance) +{ + (void)GetComponentDescription(); +} + +void ComponentBase::DoPostConstructor() +{ + PostConstructorInternal(); + PostConstructor(); +} + +void ComponentBase::DoPreDestructor() +{ + PreDestructor(); + PreDestructorInternal(); +} + +OSStatus ComponentBase::AP_Open(void* self, AudioComponentInstance compInstance) +{ + OSStatus result = noErr; + const auto acpi = static_cast(self); + try { + const std::lock_guard guard{ InitializationMutex() }; + + auto* const cb = + static_cast((*acpi->mConstruct)(&acpi->mInstanceStorage, compInstance)); + cb->DoPostConstructor(); // allows base class to do additional initialization + // once the derived class is fully constructed + result = noErr; + } + AUSDK_Catch(result) + if (result != noErr) { + delete acpi; // NOLINT + } + return result; +} + +OSStatus ComponentBase::AP_Close(void* self) +{ + OSStatus result = noErr; + try { + const auto acpi = static_cast(self); + if (const auto acImp = + reinterpret_cast(&acpi->mInstanceStorage)) { // NOLINT + acImp->DoPreDestructor(); + (*acpi->mDestruct)(&acpi->mInstanceStorage); + free(self); // NOLINT manual memory management + } + } + AUSDK_Catch(result) + return result; +} + +AudioComponentDescription ComponentBase::GetComponentDescription() const +{ + AudioComponentDescription desc = {}; + + if (CB_GetComponentDescription(mComponentInstance, &desc) == noErr) { + return desc; + } + + return {}; +} + +static OSStatus CB_GetComponentDescription( + AudioComponentInstance inInstance, AudioComponentDescription* outDesc) +{ + const AudioComponent comp = AudioComponentInstanceGetComponent(inInstance); + if (comp != nullptr) { + return AudioComponentGetDescription(comp, outDesc); + } + + return kAudio_ParamError; +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.h new file mode 100644 index 0000000000..ece9602abd --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.h @@ -0,0 +1,162 @@ +/*! + @file AudioUnitSDK/ComponentBase.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_ComponentBase_h +#define AudioUnitSDK_ComponentBase_h + +// module +#include + +// OS +#include + +// std +#include +#include +#include + +namespace ausdk { + +/*! + @class ComponentBase + @brief Base class for implementing an `AudioComponentInstance`. +*/ +class ComponentBase { +public: + /// Construct given an AudioComponentInstance, typically from APFactory::Constuct. + explicit ComponentBase(AudioComponentInstance inInstance); + + virtual ~ComponentBase() = default; + + ComponentBase(const ComponentBase&) = delete; + ComponentBase(ComponentBase&&) = delete; + ComponentBase& operator=(const ComponentBase&) = delete; + ComponentBase& operator=(ComponentBase&&) = delete; + + /// Called from dispatchers after constructing an instance. + void DoPostConstructor(); + + /// Called from dispatchers before destroying an instance. + void DoPreDestructor(); + + /// Obtain the wrapped `AudioComponentInstance` (underlying type of `AudioUnit`, `AudioCodec`, + /// and others). + [[nodiscard]] AudioComponentInstance GetComponentInstance() const noexcept + { + return mComponentInstance; + } + + /// Return the instance's `AudioComponentDescription`. + [[nodiscard]] AudioComponentDescription GetComponentDescription() const; + + /// Component dispatch method. + static OSStatus AP_Open(void* self, AudioComponentInstance compInstance); + + /// Component dispatch method. + static OSStatus AP_Close(void* self); + + /// A mutex which is held during `Open`, since some AU's and the Component Manager itself + /// are not thread-safe against globals. + static std::recursive_mutex& InitializationMutex(); + +protected: + // subclasses are free to to override these methods to add functionality + virtual void PostConstructor() {} + virtual void PreDestructor() {} + // these methods, however, are reserved for override only within this SDK + virtual void PostConstructorInternal() {} + virtual void PreDestructorInternal() {} + +private: + AudioComponentInstance mComponentInstance; +}; + +/*! + @class AudioComponentPlugInInstance + @brief Object which implements an AudioComponentPlugInInterface for the framework, and + which holds the C++ implementation object. +*/ +struct AudioComponentPlugInInstance { + // The AudioComponentPlugInInterface must remain first + + AudioComponentPlugInInterface mPlugInInterface; + + void* (*mConstruct)(void* memory, AudioComponentInstance ci); + + void (*mDestruct)(void* memory); + + std::array mPad; // 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 + @tparam APMethodLookup A class (e.g. AUBaseLookup) which provides a method selector lookup + function. + @tparam Implementor The class which implements the full plug-in (AudioUnit) interface. + @brief Provides an AudioComponentFactoryFunction and a convenience wrapper for + AudioComponentRegister. +*/ +template +class APFactory { +public: + static void* Construct(void* memory, AudioComponentInstance compInstance) + { + return new (memory) Implementor(compInstance); // NOLINT manual memory management + } + + static void Destruct(void* memory) { static_cast(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 */) + { + auto* const acpi = // NOLINT owning memory + static_cast(malloc( // NOLINT manual memory management + 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 = nullptr; + acpi->mConstruct = Construct; + acpi->mDestruct = Destruct; + acpi->mPad[0] = nullptr; + acpi->mPad[1] = nullptr; + return &acpi->mPlugInInterface; + } + + // 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) + { + const AudioComponentDescription desc = { type, subtype, manuf, flags, 0 }; + return AudioComponentRegister(&desc, name, vers, Factory); + } +}; + +#ifndef AUSDK_EXPORT +#if __GNUC__ +#define AUSDK_EXPORT __attribute__((visibility("default"))) // NOLINT +#else +#warning export? +#endif +#endif + + +/// Macro to generate the factory function for the specified Audio Component. Factory is an +/// APFactory such as AUBaseFactory. Class is the name of the final ComponentBase class which +/// implements instances of the class. +#define AUSDK_COMPONENT_ENTRY(FactoryType, Class) /* NOLINT macro */ \ + AUSDK_EXPORT \ + extern "C" void* Class##Factory(const AudioComponentDescription* inDesc); \ + extern "C" void* Class##Factory(const AudioComponentDescription* inDesc) \ + { \ + return FactoryType::Factory(inDesc); /* NOLINT parens */ \ + } + +} // namespace ausdk + +#endif // AudioUnitSDK_ComponentBase_h diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.cpp b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.cpp new file mode 100644 index 0000000000..19404b41ed --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.cpp @@ -0,0 +1,117 @@ +/*! + @file AudioUnitSDK/MusicDeviceBase.cpp + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#include + +namespace ausdk { + + +MusicDeviceBase::MusicDeviceBase( + AudioComponentInstance inInstance, UInt32 numInputs, UInt32 numOutputs, UInt32 numGroups) + : AUBase(inInstance, numInputs, numOutputs, numGroups), AUMIDIBase(*static_cast(this)) +{ +} + +OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) +{ + OSStatus result = noErr; + + switch (inID) { // NOLINT if/else + case kMusicDeviceProperty_InstrumentCount: + if (inScope != kAudioUnitScope_Global) { + return kAudioUnitErr_InvalidScope; + } + outDataSize = sizeof(UInt32); + outWritable = false; + result = noErr; + break; + default: + result = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); + + if (result == kAudioUnitErr_InvalidProperty) { + result = AUMIDIBase::DelegateGetPropertyInfo( + inID, inScope, inElement, outDataSize, outWritable); + } + break; + } + return result; +} + +OSStatus MusicDeviceBase::GetProperty( + AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData) +{ + OSStatus result = noErr; + + switch (inID) { // NOLINT if/else + case kMusicDeviceProperty_InstrumentCount: + if (inScope != kAudioUnitScope_Global) { + return kAudioUnitErr_InvalidScope; + } + return GetInstrumentCount(*static_cast(outData)); + default: + result = AUBase::GetProperty(inID, inScope, inElement, outData); + + if (result == kAudioUnitErr_InvalidProperty) { + result = AUMIDIBase::DelegateGetProperty(inID, inScope, inElement, outData); + } + } + + return result; +} + + +OSStatus MusicDeviceBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) + +{ + + OSStatus result = AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize); + + if (result == kAudioUnitErr_InvalidProperty) { + result = AUMIDIBase::DelegateSetProperty(inID, inScope, inElement, inData, inDataSize); + } + + return result; +} + +// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral) +// then this call should return an instrument count of zero and noErr +OSStatus MusicDeviceBase::GetInstrumentCount(UInt32& outInstCount) const +{ + outInstCount = 0; + return noErr; +} + +OSStatus MusicDeviceBase::HandleNoteOn( + UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) +{ + const MusicDeviceNoteParams params{ .argCount = 2, + .mPitch = static_cast(inNoteNumber), + .mVelocity = static_cast(inVelocity) }; + return StartNote(kMusicNoteEvent_UseGroupInstrument, inChannel, nullptr, 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 == nullptr || outNoteInstanceID == nullptr) { + return kAudio_ParamError; + } + + if (!IsInitialized()) { + return kAudioUnitErr_Uninitialized; + } + + return StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams); +} + +} // namespace ausdk diff --git a/modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.h b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.h new file mode 100644 index 0000000000..f4eb5f47bb --- /dev/null +++ b/modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.h @@ -0,0 +1,64 @@ +/*! + @file AudioUnitSDK/MusicDeviceBase.h + @copyright © 2000-2021 Apple Inc. All rights reserved. +*/ +#ifndef AudioUnitSDK_MusicDeviceBase_h +#define AudioUnitSDK_MusicDeviceBase_h + +#include + +namespace ausdk { + +// ________________________________________________________________________ +// MusicDeviceBase +// + +/*! + @class MusicDeviceBase + @brief Deriving from AUBase and AUMIDIBase, an abstract base class for Music Device + subclasses. +*/ +class MusicDeviceBase : public AUBase, public AUMIDIBase { +public: + MusicDeviceBase(AudioComponentInstance inInstance, UInt32 numInputs, UInt32 numOutputs, + UInt32 numGroups = 0); + + OSStatus MIDIEvent( + UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame) override + { + return AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame); + } + OSStatus SysEx(const UInt8* inData, UInt32 inLength) override + { + return AUMIDIBase::SysEx(inData, inLength); + } + +#if AUSDK_MIDI2_AVAILABLE + OSStatus MIDIEventList( + UInt32 inOffsetSampleFrame, const struct MIDIEventList* eventList) override + { + return AUMIDIBase::MIDIEventList(inOffsetSampleFrame, eventList); + } +#endif + + OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) override; + OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, void* outData) override; + OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, + AudioUnitElement inElement, const void* inData, UInt32 inDataSize) override; + OSStatus HandleNoteOn( + UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) override; + OSStatus HandleNoteOff( + UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) override; + virtual OSStatus GetInstrumentCount(UInt32& outInstCount) const; + +private: + OSStatus HandleStartNoteMessage(MusicDeviceInstrumentID inInstrument, + MusicDeviceGroupID inGroupID, NoteInstanceID* outNoteInstanceID, UInt32 inOffsetSampleFrame, + const MusicDeviceNoteParams* inParams); +}; + +} // namespace ausdk + +#endif // AudioUnitSDK_MusicDeviceBase_h diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp deleted file mode 100644 index 70791f6be8..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp +++ /dev/null @@ -1,2400 +0,0 @@ -/* - File: AUBase.cpp - Abstract: AUBase.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 "AUDispatch.h" -#include "AUInputElement.h" -#include "AUOutputElement.h" -#include -#include -#include "CAAudioChannelLayout.h" -#include "CAHostTimeBase.h" -#include "CAVectorUnit.h" -#include "CAXException.h" - -// This is for JUCE, added as a workaround for problems in older hosts following an API change. -struct OldHostCallbackInfo -{ - void* hostUserData; - HostCallback_GetBeatAndTempo beatAndTempoProc; - HostCallback_GetMusicalTimeLocation musicalTimeLocationProc; - HostCallback_GetTransportState transportStateProc; -}; - - -#if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64) - // our compiler does ALL floating point with SSE - inline int GETCSR () { int _result; asm volatile ("stmxcsr %0" : "=m" (*&_result) ); return _result; } - inline void SETCSR (int a) { int _temp = a; asm volatile( "ldmxcsr %0" : : "m" (*&_temp ) ); } - - #define DISABLE_DENORMALS int _savemxcsr = GETCSR(); SETCSR(_savemxcsr | 0x8040); - #define RESTORE_DENORMALS SETCSR(_savemxcsr); -#else - #define DISABLE_DENORMALS - #define RESTORE_DENORMALS -#endif - -static bool sAUBaseCFStringsInitialized = false; -// this is used for the presets -static CFStringRef kUntitledString = NULL; -//these are the current keys for the class info document -static CFStringRef kVersionString = NULL; -static CFStringRef kTypeString = NULL; -static CFStringRef kSubtypeString = NULL; -static CFStringRef kManufacturerString = NULL; -static CFStringRef kDataString = NULL; -static CFStringRef kNameString = NULL; -static CFStringRef kRenderQualityString = NULL; -static CFStringRef kCPULoadString = NULL; -static CFStringRef kElementNameString = NULL; -static CFStringRef kPartString = NULL; - -SInt32 AUBase::sVectorUnitType = kVecUninitialized; - -//_____________________________________________________________________________ -// -AUBase::AUBase( AudioComponentInstance inInstance, - UInt32 numInputElements, - UInt32 numOutputElements, - UInt32 numGroupElements) : - ComponentBase(inInstance), - mElementsCreated(false), - mInitialized(false), - mHasBegunInitializing(false), - mInitNumInputEls(numInputElements), mInitNumOutputEls(numOutputElements), -#if !CA_BASIC_AU_FEATURES - mInitNumGroupEls(numGroupElements), -#endif - mRenderCallbacksTouched(false), - mRenderThreadID (NULL), - mWantsRenderThreadID (false), - mLastRenderError(0), - mUsesFixedBlockSize(false), - mBuffersAllocated(false), - mLogString (NULL), - mNickName (NULL), - mAUMutex(NULL) - #if !CA_NO_AU_UI_FEATURES - , - mContextName(NULL) - #endif -{ - ResetRenderTime (); - - if(!sAUBaseCFStringsInitialized) - { - kUntitledString = CFSTR("Untitled"); - kVersionString = CFSTR(kAUPresetVersionKey); - kTypeString = CFSTR(kAUPresetTypeKey); - kSubtypeString = CFSTR(kAUPresetSubtypeKey); - kManufacturerString = CFSTR(kAUPresetManufacturerKey); - kDataString = CFSTR(kAUPresetDataKey); - kNameString = CFSTR(kAUPresetNameKey); - kRenderQualityString = CFSTR(kAUPresetRenderQualityKey); - kCPULoadString = CFSTR(kAUPresetCPULoadKey); - kElementNameString = CFSTR(kAUPresetElementNameKey); - kPartString = CFSTR(kAUPresetPartKey); - sAUBaseCFStringsInitialized = true; - } - - if (sVectorUnitType == kVecUninitialized) { - sVectorUnitType = CAVectorUnit::GetVectorUnitType() ; - } - - mAudioUnitAPIVersion = 2; - - SetMaxFramesPerSlice(kAUDefaultMaxFramesPerSlice); - - GlobalScope().Initialize(this, kAudioUnitScope_Global, 1); - -#if !CA_NO_AU_UI_FEATURES - memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo)); -#endif - - - mCurrentPreset.presetNumber = -1; - mCurrentPreset.presetName = kUntitledString; - CFRetain (mCurrentPreset.presetName); -} - -//_____________________________________________________________________________ -// -AUBase::~AUBase() -{ - if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName); -#if !CA_NO_AU_UI_FEATURES - if (mContextName) CFRelease (mContextName); -#endif - if (mLogString) delete [] mLogString; - if (mNickName) CFRelease(mNickName); -} - -//_____________________________________________________________________________ -// -void AUBase::CreateElements() -{ - if (!mElementsCreated) { - Inputs().Initialize(this, kAudioUnitScope_Input, mInitNumInputEls); - Outputs().Initialize(this, kAudioUnitScope_Output, mInitNumOutputEls); -#if !CA_BASIC_AU_FEATURES - Groups().Initialize(this, kAudioUnitScope_Group, mInitNumGroupEls); -#endif - CreateExtendedElements(); - - mElementsCreated = true; - } -} - -//_____________________________________________________________________________ -// -void AUBase::SetMaxFramesPerSlice(UInt32 nFrames) -{ - mMaxFramesPerSlice = nFrames; - if (mBuffersAllocated) - ReallocateBuffers(); - PropertyChanged(kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0); -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::CanSetMaxFrames() const -{ - return IsInitialized() ? kAudioUnitErr_Initialized : OSStatus(noErr); -} - -//_____________________________________________________________________________ -// -void AUBase::ReallocateBuffers() -{ - CreateElements(); - - UInt32 nOutputs = Outputs().GetNumberOfElements(); - for (UInt32 i = 0; i < nOutputs; ++i) { - AUOutputElement *output = GetOutput(i); - output->AllocateBuffer(); // does no work if already allocated - } - UInt32 nInputs = Inputs().GetNumberOfElements(); - for (UInt32 i = 0; i < nInputs; ++i) { - AUInputElement *input = GetInput(i); - input->AllocateBuffer(); // does no work if already allocated - } - mBuffersAllocated = true; -} - -//_____________________________________________________________________________ -// -void AUBase::DeallocateIOBuffers() -{ - if (!mBuffersAllocated) - return; - - UInt32 nOutputs = Outputs().GetNumberOfElements(); - for (UInt32 i = 0; i < nOutputs; ++i) { - AUOutputElement *output = GetOutput(i); - output->DeallocateBuffer(); - } - UInt32 nInputs = Inputs().GetNumberOfElements(); - for (UInt32 i = 0; i < nInputs; ++i) { - AUInputElement *input = GetInput(i); - input->DeallocateBuffer(); - } - mBuffersAllocated = false; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::DoInitialize() -{ - OSStatus result = noErr; - - if (!mInitialized) { - result = Initialize(); - if (result == noErr) { - if (CanScheduleParameters()) - mParamList.reserve(24); - mHasBegunInitializing = true; - ReallocateBuffers(); // calls CreateElements() - mInitialized = true; // signal that it's okay to render - CAMemoryBarrier(); - } - } - - return result; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::Initialize() -{ - return noErr; -} - -//_____________________________________________________________________________ -// -void AUBase::PreDestructor() -{ - // this is called from the ComponentBase dispatcher, which doesn't know anything about our (optional) lock - CAMutex::Locker lock(mAUMutex); - DoCleanup(); -} - -//_____________________________________________________________________________ -// -void AUBase::DoCleanup() -{ - if (mInitialized) - Cleanup(); - - DeallocateIOBuffers(); - ResetRenderTime (); - - mInitialized = false; - mHasBegunInitializing = false; -} - -//_____________________________________________________________________________ -// -void AUBase::Cleanup() -{ -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::Reset( AudioUnitScope inScope, - AudioUnitElement inElement) -{ - ResetRenderTime (); - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - UInt32 & outDataSize, - Boolean & outWritable) -{ - OSStatus result = noErr; - bool validateElement = true; - - switch (inID) { - case kAudioUnitProperty_MakeConnection: - ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(AudioUnitConnection); - outWritable = true; - break; - - - case kAudioUnitProperty_SetRenderCallback: - ca_require(AudioUnitAPIVersion() > 1, InvalidProperty); - ca_require(inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(AURenderCallbackStruct); - outWritable = true; - break; - - case kAudioUnitProperty_StreamFormat: - outDataSize = sizeof(CAStreamBasicDescription); - outWritable = IsStreamFormatWritable(inScope, inElement); - break; - - case kAudioUnitProperty_SampleRate: - outDataSize = sizeof(Float64); - outWritable = IsStreamFormatWritable(inScope, inElement); - break; - - case kAudioUnitProperty_ClassInfo: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(CFPropertyListRef); - outWritable = true; - break; - - case kAudioUnitProperty_FactoryPresets: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - result = GetPresets(NULL); - if (!result) { - outDataSize = sizeof(CFArrayRef); - outWritable = false; - } - break; - - case kAudioUnitProperty_PresentPreset: -#if !CA_USE_AUDIO_PLUGIN_ONLY -#ifndef __LP64__ - case kAudioUnitProperty_CurrentPreset: -#endif -#endif - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(AUPreset); - outWritable = true; - break; - - case kAudioUnitProperty_ElementName: - outDataSize = sizeof (CFStringRef); - outWritable = true; - break; - - case kAudioUnitProperty_ParameterList: - { - UInt32 nparams = 0; - result = GetParameterList(inScope, NULL, nparams); - - outDataSize = sizeof(AudioUnitParameterID) * nparams; - outWritable = false; - validateElement = false; - } - break; - - case kAudioUnitProperty_ParameterInfo: - outDataSize = sizeof(AudioUnitParameterInfo); - outWritable = false; - validateElement = false; - break; - - case kAudioUnitProperty_ParameterHistoryInfo: - outDataSize = sizeof(AudioUnitParameterHistoryInfo); - outWritable = false; - validateElement = false; - break; - - case kAudioUnitProperty_ElementCount: - outDataSize = sizeof(UInt32); - outWritable = BusCountWritable(inScope); - validateElement = false; - break; - - case kAudioUnitProperty_Latency: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(Float64); - outWritable = false; - break; - - case kAudioUnitProperty_TailTime: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - if (SupportsTail()) { - outDataSize = sizeof(Float64); - outWritable = false; - } else - goto InvalidProperty; - break; - - case kAudioUnitProperty_MaximumFramesPerSlice: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(UInt32); - outWritable = true; - break; - - case kAudioUnitProperty_LastRenderError: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(OSStatus); - outWritable = false; - break; - - case kAudioUnitProperty_SupportedNumChannels: - { - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - UInt32 num = SupportedNumChannels (NULL); - if (num) { - outDataSize = sizeof (AUChannelInfo) * num; - result = noErr; - } else - goto InvalidProperty; - outWritable = false; - break; - } - - case kAudioUnitProperty_SupportedChannelLayoutTags: - { - UInt32 numLayouts = GetChannelLayoutTags(inScope, inElement, NULL); - if (numLayouts) { - outDataSize = numLayouts * sizeof(AudioChannelLayoutTag); - result = noErr; - } else - goto InvalidProperty; - outWritable = false; - validateElement = false; //already done it - break; - } - - case kAudioUnitProperty_AudioChannelLayout: - { - outWritable = false; - outDataSize = GetAudioChannelLayout(inScope, inElement, NULL, outWritable); - if (outDataSize) { - result = noErr; - } else { - if (GetChannelLayoutTags(inScope, inElement, NULL) == 0) - goto InvalidProperty; - else - result = kAudioUnitErr_InvalidPropertyValue; - } - validateElement = false; //already done it - break; - } - -#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE - case kAudioUnitProperty_ShouldAllocateBuffer: - ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope); - outWritable = true; - outDataSize = sizeof(UInt32); - break; -#endif - -#if !CA_USE_AUDIO_PLUGIN_ONLY - case kAudioUnitProperty_FastDispatch: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - if (!IsCMgrObject()) goto InvalidProperty; - outDataSize = sizeof(void *); - outWritable = false; - validateElement = false; - break; - - case kAudioUnitProperty_GetUIComponentList: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = GetNumCustomUIComponents(); - if (outDataSize == 0) - goto InvalidProperty; - outDataSize *= sizeof (AudioComponentDescription); - - outWritable = false; - break; -#endif - - case kAudioUnitProperty_ParameterValueStrings: - result = GetParameterValueStrings(inScope, inElement, NULL); - if (result == noErr) { - outDataSize = sizeof(CFArrayRef); - outWritable = false; - validateElement = false; - } - break; - -#if !CA_NO_AU_HOST_CALLBACKS - case kAudioUnitProperty_HostCallbacks: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(OldHostCallbackInfo); - outWritable = true; - break; -#endif -#if !CA_NO_AU_UI_FEATURES - case kAudioUnitProperty_ContextName: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(CFStringRef); - outWritable = true; - break; - - case kAudioUnitProperty_IconLocation: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outWritable = false; - if (!HasIcon()) - goto InvalidProperty; - outDataSize = sizeof(CFURLRef); - break; - - case kAudioUnitProperty_ParameterClumpName: - outDataSize = sizeof(AudioUnitParameterNameInfo ); - outWritable = false; - break; - -#endif // !CA_NO_AU_UI_FEATURES - - case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime - outDataSize = sizeof(Float64); - outWritable = false; - break; - - case /*kAudioUnitProperty_NickName*/ 54: - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - outDataSize = sizeof(CFStringRef); - outWritable = true; - break; - - default: - result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); - validateElement = false; - break; - } - - if (result == noErr && validateElement) { - ca_require(GetElement(inScope, inElement) != NULL, InvalidElement); - } - - return result; -InvalidProperty: - return kAudioUnitErr_InvalidProperty; -InvalidScope: - return kAudioUnitErr_InvalidScope; -InvalidElement: - return kAudioUnitErr_InvalidElement; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::DispatchGetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - void * outData) -{ - // NOTE: We're currently only called from AUBase::ComponentEntryDispatch, which - // calls DispatchGetPropertyInfo first, which performs validation of the scope/element, - // and ensures that the outData buffer is non-null and large enough. - OSStatus result = noErr; - - switch (inID) { - case kAudioUnitProperty_StreamFormat: - *(CAStreamBasicDescription *)outData = GetStreamFormat(inScope, inElement); - break; - - case kAudioUnitProperty_SampleRate: - *(Float64 *)outData = GetStreamFormat(inScope, inElement).mSampleRate; - break; - - case kAudioUnitProperty_ParameterList: - { - UInt32 nparams = 0; - result = GetParameterList(inScope, (AudioUnitParameterID *)outData, nparams); - } - break; - - case kAudioUnitProperty_ParameterInfo: - result = GetParameterInfo(inScope, inElement, *(AudioUnitParameterInfo *)outData); - break; - - case kAudioUnitProperty_ParameterHistoryInfo: - { - AudioUnitParameterHistoryInfo* info = (AudioUnitParameterHistoryInfo*)outData; - result = GetParameterHistoryInfo(inScope, inElement, info->updatesPerSecond, info->historyDurationInSeconds); - } - break; - - case kAudioUnitProperty_ClassInfo: - { - *(CFPropertyListRef *)outData = NULL; - result = SaveState((CFPropertyListRef *)outData); - } - break; - - case kAudioUnitProperty_FactoryPresets: - { - *(CFArrayRef *)outData = NULL; - result = GetPresets ((CFArrayRef *)outData); - } - break; - - case kAudioUnitProperty_PresentPreset: -#if !CA_USE_AUDIO_PLUGIN_ONLY -#ifndef __LP64__ - case kAudioUnitProperty_CurrentPreset: -#endif -#endif - { - *(AUPreset *)outData = mCurrentPreset; - - // retain current string (as client owns a reference to it and will release it) - if (inID == kAudioUnitProperty_PresentPreset && mCurrentPreset.presetName) - CFRetain (mCurrentPreset.presetName); - - result = noErr; - } - break; - - case kAudioUnitProperty_ElementName: - { - AUElement * element = GetElement(inScope, inElement); - if (element->HasName()) { - *(CFStringRef *)outData = element->GetName(); - CFRetain (element->GetName()); - result = noErr; - } else - result = kAudioUnitErr_InvalidPropertyValue; - } - break; - - case kAudioUnitProperty_ElementCount: - *(UInt32 *)outData = GetScope(inScope).GetNumberOfElements(); - break; - - case kAudioUnitProperty_Latency: - *(Float64 *)outData = GetLatency(); - break; - - case kAudioUnitProperty_TailTime: - if (SupportsTail()) - *(Float64 *)outData = GetTailTime(); - else - result = kAudioUnitErr_InvalidProperty; - break; - - case kAudioUnitProperty_MaximumFramesPerSlice: - *(UInt32 *)outData = mMaxFramesPerSlice; - break; - - case kAudioUnitProperty_LastRenderError: - *(OSStatus *)outData = mLastRenderError; - mLastRenderError = 0; - break; - - case kAudioUnitProperty_SupportedNumChannels: - { - const AUChannelInfo* infoPtr = NULL; - UInt32 num = SupportedNumChannels (&infoPtr); - if(num != 0 && infoPtr != NULL) - memcpy (outData, infoPtr, num * sizeof (AUChannelInfo)); - } - break; - - case kAudioUnitProperty_SupportedChannelLayoutTags: - { - AudioChannelLayoutTag* ptr = outData ? static_cast(outData) : NULL; - UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, ptr); - if (numLayouts == 0) - result = kAudioUnitErr_InvalidProperty; - } - break; - - case kAudioUnitProperty_AudioChannelLayout: - { - AudioChannelLayout* ptr = outData ? static_cast(outData) : NULL; - Boolean writable; - UInt32 dataSize = GetAudioChannelLayout(inScope, inElement, ptr, writable); - if (!dataSize) { - result = kAudioUnitErr_InvalidProperty; - } - break; - } - -#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE - case kAudioUnitProperty_ShouldAllocateBuffer: - { - AUIOElement * element = GetIOElement(inScope, inElement); - *(UInt32*)outData = element->WillAllocateBuffer(); - break; - } -#endif - - case kAudioUnitProperty_ParameterValueStrings: - result = GetParameterValueStrings(inScope, inElement, (CFArrayRef *)outData); - break; - -#if !CA_USE_AUDIO_PLUGIN_ONLY - case kAudioUnitProperty_FastDispatch: - if (!IsCMgrObject()) result = kAudioUnitErr_InvalidProperty; - else { - switch (inElement) { - case kAudioUnitGetParameterSelect: - *(AudioUnitGetParameterProc *)outData = (AudioUnitGetParameterProc)CMgr_AudioUnitBaseGetParameter; - break; - case kAudioUnitSetParameterSelect: - *(AudioUnitSetParameterProc *)outData = (AudioUnitSetParameterProc)CMgr_AudioUnitBaseSetParameter; - break; - case kAudioUnitRenderSelect: - if (AudioUnitAPIVersion() > 1) - *(AudioUnitRenderProc *)outData = (AudioUnitRenderProc)CMgr_AudioUnitBaseRender; - else result = kAudioUnitErr_InvalidElement; - break; - default: - result = GetProperty(inID, inScope, inElement, outData); - break; - } - } - break; - - case kAudioUnitProperty_GetUIComponentList: - GetUIComponentDescs ((ComponentDescription*)outData); - break; -#endif - -#if !CA_NO_AU_HOST_CALLBACKS - case kAudioUnitProperty_HostCallbacks: - memcpy(outData, &mHostCallbackInfo, sizeof(OldHostCallbackInfo)); - break; -#endif -#if !CA_NO_AU_UI_FEATURES - case kAudioUnitProperty_IconLocation: - { - CFURLRef iconLocation = CopyIconLocation(); - if (iconLocation) { - *(CFURLRef*)outData = iconLocation; - } else - result = kAudioUnitErr_InvalidProperty; - } - break; - - case kAudioUnitProperty_ContextName: - *(CFStringRef *)outData = mContextName; - if (mContextName) { - CFRetain(mContextName); - // retain CFString (if exists) since client will be responsible for its release - result = noErr; - } else { - result = kAudioUnitErr_InvalidPropertyValue; - } - break; - - case kAudioUnitProperty_ParameterClumpName: - { - AudioUnitParameterNameInfo * ioClumpInfo = (AudioUnitParameterNameInfo*) outData; - if (ioClumpInfo->inID == kAudioUnitClumpID_System) // this ID value is reserved - result = kAudioUnitErr_InvalidPropertyValue; - else - { - result = CopyClumpName(inScope, ioClumpInfo->inID, ioClumpInfo->inDesiredLength, &ioClumpInfo->outName); - - // this is provided for compatbility with existing implementations that don't know - // about this new mechanism - if (result == kAudioUnitErr_InvalidProperty) - result = GetProperty (inID, inScope, inElement, outData); - } - } - break; - -#endif // !CA_NO_AU_UI_FEATURES - - case 'lrst' : // kAudioUnitProperty_LastRenderedSampleTime - *(Float64*)outData = mCurrentRenderTime.mSampleTime; - break; - - case /*kAudioUnitProperty_NickName*/ 54: - // Ownership follows Core Foundation's 'Copy Rule' - if (mNickName) CFRetain(mNickName); - *(CFStringRef*)outData = mNickName; - break; - - default: - result = GetProperty(inID, inScope, inElement, outData); - break; - } - return result; -} - - -//_____________________________________________________________________________ -// -OSStatus AUBase::DispatchSetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - const void * inData, - UInt32 inDataSize) -{ - OSStatus result = noErr; - - switch (inID) { - case kAudioUnitProperty_MakeConnection: - ca_require(inDataSize >= sizeof(AudioUnitConnection), InvalidPropertyValue); - { - AudioUnitConnection &connection = *(AudioUnitConnection *)inData; - result = SetConnection(connection); - } - break; - - - case kAudioUnitProperty_SetRenderCallback: - { - ca_require(inDataSize >= sizeof(AURenderCallbackStruct), InvalidPropertyValue); - ca_require(AudioUnitAPIVersion() > 1, InvalidProperty); - AURenderCallbackStruct &callback = *(AURenderCallbackStruct*)inData; - result = SetInputCallback(kAudioUnitProperty_SetRenderCallback, inElement, callback.inputProc, callback.inputProcRefCon); - } - break; - - case kAudioUnitProperty_ElementCount: - ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue); - ca_require(BusCountWritable(inScope), NotWritable); - result = SetBusCount(inScope, *(UInt32*)inData); - if (result == noErr) { - PropertyChanged(inID, inScope, inElement); - } - break; - - case kAudioUnitProperty_MaximumFramesPerSlice: - ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue); - result = CanSetMaxFrames(); - if (result) return result; - SetMaxFramesPerSlice(*(UInt32 *)inData); - break; - - case kAudioUnitProperty_StreamFormat: - { - if (inDataSize < 36) goto InvalidPropertyValue; - ca_require(GetElement(inScope, inElement) != NULL, InvalidElement); - - CAStreamBasicDescription newDesc; - // now we're going to be ultra conservative! because of discrepancies between - // sizes of this struct based on aligment padding inconsistencies - memset (&newDesc, 0, sizeof(newDesc)); - memcpy (&newDesc, inData, 36); - - ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat); - - const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement); - - if ( !curDesc.IsEqual(newDesc, false) ) { - ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable); - result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc); - } - } - break; - - case kAudioUnitProperty_SampleRate: - { - ca_require(inDataSize == sizeof(Float64), InvalidPropertyValue); - ca_require(GetElement(inScope, inElement) != NULL, InvalidElement); - - const CAStreamBasicDescription curDesc = GetStreamFormat(inScope, inElement); - CAStreamBasicDescription newDesc = curDesc; - newDesc.mSampleRate = *(Float64 *)inData; - - ca_require(ValidFormat(inScope, inElement, newDesc), InvalidFormat); - - if ( !curDesc.IsEqual(newDesc, false) ) { - ca_require(IsStreamFormatWritable(inScope, inElement), NotWritable); - result = ChangeStreamFormat(inScope, inElement, curDesc, newDesc); - } - } - break; - - case kAudioUnitProperty_AudioChannelLayout: - { - const AudioChannelLayout *layout = static_cast(inData); - size_t headerSize = sizeof(AudioChannelLayout) - sizeof(AudioChannelDescription); - - ca_require(inDataSize >= headerSize + layout->mNumberChannelDescriptions * sizeof(AudioChannelDescription), InvalidPropertyValue); - result = SetAudioChannelLayout(inScope, inElement, layout); - if (result == noErr) - PropertyChanged(inID, inScope, inElement); - break; - } - - case kAudioUnitProperty_ClassInfo: - ca_require(inDataSize == sizeof(CFPropertyListRef *), InvalidPropertyValue); - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - result = RestoreState(*(CFPropertyListRef *)inData); - break; - - case kAudioUnitProperty_PresentPreset: -#if !CA_USE_AUDIO_PLUGIN_ONLY -#ifndef __LP64__ - case kAudioUnitProperty_CurrentPreset: -#endif -#endif - { - ca_require(inDataSize == sizeof(AUPreset), InvalidPropertyValue); - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - AUPreset & newPreset = *(AUPreset *)inData; - - if (newPreset.presetNumber >= 0) - { - result = NewFactoryPresetSet(newPreset); - // NewFactoryPresetSet SHOULD call SetAFactoryPreset if the preset is valid - // from its own list of preset number->name - if (!result) - PropertyChanged(inID, inScope, inElement); - } - else if (newPreset.presetName) - { - result = NewCustomPresetSet(newPreset); - if (!result) - PropertyChanged(inID, inScope, inElement); - } - else - result = kAudioUnitErr_InvalidPropertyValue; - } - break; - - case kAudioUnitProperty_ElementName: - { - ca_require(GetElement(inScope, inElement) != NULL, InvalidElement); - ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue); - AUElement * element = GetScope(inScope).GetElement (inElement); - element->SetName (*(CFStringRef *)inData); - PropertyChanged(inID, inScope, inElement); - } - break; - -#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || TARGET_OS_IPHONE - case kAudioUnitProperty_ShouldAllocateBuffer: - { - ca_require((inScope == kAudioUnitScope_Input || inScope == kAudioUnitScope_Output), InvalidScope); - ca_require(GetElement(inScope, inElement) != NULL, InvalidElement); - ca_require(inDataSize == sizeof(UInt32), InvalidPropertyValue); - ca_require(!IsInitialized(), Initialized); - - AUIOElement * element = GetIOElement(inScope, inElement); - element->SetWillAllocateBuffer(*(UInt32 *)inData != 0); - } - break; -#endif - -#if !CA_NO_AU_HOST_CALLBACKS - case kAudioUnitProperty_HostCallbacks: - { - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - UInt32 availSize = std::min(inDataSize, (UInt32)sizeof(HostCallbackInfo)); - bool hasChanged = !memcmp (&mHostCallbackInfo, inData, availSize); - memset (&mHostCallbackInfo, 0, sizeof (mHostCallbackInfo)); - memcpy (&mHostCallbackInfo, inData, availSize); - if (hasChanged) - PropertyChanged(inID, inScope, inElement); - break; - } -#endif -#if !CA_NO_AU_UI_FEATURES - case kAudioUnitProperty_SetExternalBuffer: - ca_require(inDataSize >= sizeof(AudioUnitExternalBuffer), InvalidPropertyValue); - ca_require(IsInitialized(), Uninitialized); - { - AudioUnitExternalBuffer &buf = *(AudioUnitExternalBuffer*)inData; - if (intptr_t(buf.buffer) & 0x0F) result = kAudio_ParamError; - else if (inScope == kAudioUnitScope_Input) { - AUInputElement *input = GetInput(inElement); - input->UseExternalBuffer(buf); - } else { - AUOutputElement *output = GetOutput(inElement); - output->UseExternalBuffer(buf); - } - } - break; - - case kAudioUnitProperty_ContextName: - { - ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue); - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - CFStringRef inStr = *(CFStringRef *)inData; - if (mContextName) CFRelease(mContextName); - if (inStr) CFRetain(inStr); - mContextName = inStr; - PropertyChanged(inID, inScope, inElement); - } - break; - -#endif // !CA_NO_AU_UI_FEATURES - - case /*kAudioUnitProperty_NickName*/ 54: - { - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - ca_require(inDataSize == sizeof(CFStringRef), InvalidPropertyValue); - CFStringRef inStr = *(CFStringRef *)inData; - if (mNickName) CFRelease(mNickName); - if (inStr) CFRetain(inStr); - mNickName = inStr; - PropertyChanged(inID, inScope, inElement); - break; - } - - default: - result = SetProperty(inID, inScope, inElement, inData, inDataSize); - if (result == noErr) - PropertyChanged(inID, inScope, inElement); - - break; - } - return result; -NotWritable: - return kAudioUnitErr_PropertyNotWritable; -InvalidFormat: - return kAudioUnitErr_FormatNotSupported; -#if !CA_NO_AU_UI_FEATURES -Uninitialized: - return kAudioUnitErr_Uninitialized; -#endif -#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || CA_USE_AUDIO_PLUGIN_ONLY -Initialized: - return kAudioUnitErr_Initialized; -#endif -InvalidScope: - return kAudioUnitErr_InvalidScope; -InvalidProperty: - return kAudioUnitErr_InvalidProperty; -InvalidPropertyValue: - return kAudioUnitErr_InvalidPropertyValue; -InvalidElement: - return kAudioUnitErr_InvalidElement; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::DispatchRemovePropertyValue (AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement) -{ - OSStatus result = noErr; - switch (inID) - { - case kAudioUnitProperty_AudioChannelLayout: - { - result = RemoveAudioChannelLayout(inScope, inElement); - if (result == noErr) - PropertyChanged(inID, inScope, inElement); - break; - } - -#if !CA_NO_AU_HOST_CALLBACKS - case kAudioUnitProperty_HostCallbacks: - { - ca_require(inScope == kAudioUnitScope_Global, InvalidScope); - bool hasValue = false; - void* ptr = &mHostCallbackInfo; - for (unsigned int i = 0; i < sizeof (HostCallbackInfo); ++i) { - if (static_cast(ptr)[i]) { - hasValue = true; - break; - } - } - if (hasValue) { - memset (&mHostCallbackInfo, 0, sizeof (HostCallbackInfo)); - PropertyChanged(inID, inScope, inElement); - } - break; - } -#endif -#if !CA_NO_AU_UI_FEATURES - case kAudioUnitProperty_ContextName: - if (mContextName) CFRelease(mContextName); - mContextName = NULL; - result = noErr; - break; - -#endif // !CA_NO_AU_UI_FEATURES - - case /*kAudioUnitProperty_NickName*/ 54: - { - if(inScope == kAudioUnitScope_Global) { - if (mNickName) CFRelease(mNickName); - mNickName = NULL; - PropertyChanged(inID, inScope, inElement); - } else { - result = kAudioUnitErr_InvalidScope; - } - break; - } - - default: - result = RemovePropertyValue (inID, inScope, inElement); - break; - } - - return result; -#if !CA_NO_AU_UI_FEATURES || !CA_NO_AU_HOST_CALLBACKS -InvalidScope: - return kAudioUnitErr_InvalidScope; -#endif -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetPropertyInfo( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - UInt32 & outDataSize, - Boolean & outWritable) -{ - return kAudioUnitErr_InvalidProperty; -} - - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - void * outData) -{ - return kAudioUnitErr_InvalidProperty; -} - - -//_____________________________________________________________________________ -// -OSStatus AUBase::SetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - const void * inData, - UInt32 inDataSize) -{ - return kAudioUnitErr_InvalidProperty; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::RemovePropertyValue ( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement) -{ - return kAudioUnitErr_InvalidPropertyValue; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::AddPropertyListener( AudioUnitPropertyID inID, - AudioUnitPropertyListenerProc inProc, - void * inProcRefCon) -{ - PropertyListener pl; - - pl.propertyID = inID; - pl.listenerProc = inProc; - pl.listenerRefCon = inProcRefCon; - - if (mPropertyListeners.empty()) - mPropertyListeners.reserve(32); - mPropertyListeners.push_back(pl); - - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::RemovePropertyListener( AudioUnitPropertyID inID, - AudioUnitPropertyListenerProc inProc, - void * inProcRefCon, - bool refConSpecified) -{ - // iterate in reverse so that it's safe to erase in the middle of the vector - for (int i = (int)mPropertyListeners.size(); --i >=0; ) { - PropertyListeners::iterator it = mPropertyListeners.begin() + i; - if ((*it).propertyID == inID && (*it).listenerProc == inProc && (!refConSpecified || (*it).listenerRefCon == inProcRefCon)) - mPropertyListeners.erase(it); - } - return noErr; -} - -//_____________________________________________________________________________ -// -void AUBase::PropertyChanged( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement) -{ - for (PropertyListeners::iterator it = mPropertyListeners.begin(); it != mPropertyListeners.end(); ++it) - if ((*it).propertyID == inID) - ((*it).listenerProc)((*it).listenerRefCon, mComponentInstance, inID, inScope, inElement); -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::SetRenderNotification( AURenderCallback inProc, - void * inRefCon) -{ - if (inProc == NULL) - return kAudio_ParamError; - - mRenderCallbacksTouched = true; - mRenderCallbacks.deferred_add(RenderCallback(inProc, inRefCon)); - // this will do nothing if it's already in the list - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::RemoveRenderNotification( AURenderCallback inProc, - void * inRefCon) -{ - mRenderCallbacks.deferred_remove(RenderCallback(inProc, inRefCon)); - return noErr; // error? -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetParameter( AudioUnitParameterID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - AudioUnitParameterValue & outValue) -{ - AUElement *elem = SafeGetElement(inScope, inElement); - outValue = elem->GetParameter(inID); - return noErr; -} - - -//_____________________________________________________________________________ -// -OSStatus AUBase::SetParameter( AudioUnitParameterID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - AudioUnitParameterValue inValue, - UInt32 inBufferOffsetInFrames) -{ - AUElement *elem = SafeGetElement(inScope, inElement); - elem->SetParameter(inID, inValue); - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent, - UInt32 inNumEvents) -{ - bool canScheduleParameters = CanScheduleParameters(); - - for (UInt32 i = 0; i < inNumEvents; ++i) - { - if (inParameterEvent[i].eventType == kParameterEvent_Immediate) - { - SetParameter (inParameterEvent[i].parameter, - inParameterEvent[i].scope, - inParameterEvent[i].element, - inParameterEvent[i].eventValues.immediate.value, - inParameterEvent[i].eventValues.immediate.bufferOffset); - } - if (canScheduleParameters) { - mParamList.push_back (inParameterEvent[i]); - } - } - - return noErr; -} - -// ____________________________________________________________________________ -// -static bool SortParameterEventList(const AudioUnitParameterEvent &ev1, const AudioUnitParameterEvent &ev2 ) -{ - int offset1 = ev1.eventType == kParameterEvent_Immediate ? ev1.eventValues.immediate.bufferOffset : ev1.eventValues.ramp.startBufferOffset; - int offset2 = ev2.eventType == kParameterEvent_Immediate ? ev2.eventValues.immediate.bufferOffset : ev2.eventValues.ramp.startBufferOffset; - - if(offset1 < offset2) return true; - return false; -} - - -// ____________________________________________________________________________ -// -OSStatus AUBase::ProcessForScheduledParams( ParameterEventList &inParamList, - UInt32 inFramesToProcess, - void *inUserData ) -{ - OSStatus result = noErr; - - int totalFramesToProcess = inFramesToProcess; - - int framesRemaining = totalFramesToProcess; - - unsigned int currentStartFrame = 0; // start of the whole buffer - - - - // sort the ParameterEventList by startBufferOffset - std::sort(inParamList.begin(), inParamList.end(), SortParameterEventList); - - ParameterEventList::iterator iter = inParamList.begin(); - - - while(framesRemaining > 0 ) - { - // first of all, go through the ramped automation events and find out where the next - // division of our whole buffer will be - - int currentEndFrame = totalFramesToProcess; // start out assuming we'll process all the way to - // the end of the buffer - - iter = inParamList.begin(); - - // find the next break point - while(iter != inParamList.end() ) - { - AudioUnitParameterEvent &event = *iter; - - int offset = event.eventType == kParameterEvent_Immediate ? event.eventValues.immediate.bufferOffset : event.eventValues.ramp.startBufferOffset; - - if(offset > (int)currentStartFrame && offset < currentEndFrame ) - { - currentEndFrame = offset; - break; - } - - // consider ramp end to be a possible choice (there may be gaps in the supplied ramp events) - if(event.eventType == kParameterEvent_Ramped ) - { - offset = event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames; - - if(offset > (int)currentStartFrame && offset < currentEndFrame ) - { - currentEndFrame = offset; - } - } - - iter++; - } - - int framesThisTime = currentEndFrame - currentStartFrame; - - // next, setup the parameter maps to be current for the ramp parameters active during - // this time segment... - - for(ParameterEventList::iterator iter2 = inParamList.begin(); iter2 != inParamList.end(); iter2++ ) - { - AudioUnitParameterEvent &event = *iter2; - - bool eventFallsInSlice; - - - if(event.eventType == kParameterEvent_Ramped) - eventFallsInSlice = event.eventValues.ramp.startBufferOffset < currentEndFrame - && event.eventValues.ramp.startBufferOffset + event.eventValues.ramp.durationInFrames > currentStartFrame; - else /* kParameterEvent_Immediate */ - // actually, for the same parameter, there may be future immediate events which override this one, - // but it's OK since the event list is sorted in time order, we're guaranteed to end up with the current one - eventFallsInSlice = event.eventValues.immediate.bufferOffset <= currentStartFrame; - - if(eventFallsInSlice) - { - AUElement *element = GetElement(event.scope, event.element ); - - if(element) element->SetScheduledEvent( event.parameter, - event, - currentStartFrame, - currentEndFrame - currentStartFrame ); - } - } - - - - // Finally, actually do the processing for this slice..... - - result = ProcessScheduledSlice( inUserData, - currentStartFrame, - framesThisTime, - inFramesToProcess ); - - if(result != noErr) break; - - framesRemaining -= framesThisTime; - currentStartFrame = currentEndFrame; // now start from where we left off last time - } - - return result; -} - -//_____________________________________________________________________________ -// -void AUBase::SetWantsRenderThreadID (bool inFlag) -{ - if (inFlag == mWantsRenderThreadID) - return; - - mWantsRenderThreadID = inFlag; - if (!mWantsRenderThreadID) - mRenderThreadID = NULL; -} - -//_____________________________________________________________________________ -// - -//_____________________________________________________________________________ -// -OSStatus AUBase::DoRender( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inBusNumber, - UInt32 inFramesToProcess, - AudioBufferList & ioData) -{ - OSStatus theError; - RenderCallbackList::iterator rcit; - - AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (uintptr_t)this, inBusNumber, inFramesToProcess, (uintptr_t)ioData.mBuffers[0].mData); - DISABLE_DENORMALS - - try { - ca_require(IsInitialized(), Uninitialized); - ca_require(mAudioUnitAPIVersion >= 2, ParamErr); - if (inFramesToProcess > mMaxFramesPerSlice) { - static time_t lastTimeMessagePrinted = 0; - time_t now = time(NULL); - if (now != lastTimeMessagePrinted) { - lastTimeMessagePrinted = now; - syslog(LOG_ERR, "kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=%u, mMaxFramesPerSlice=%u", (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice); - DebugMessageN4("%s:%d inFramesToProcess=%u, mMaxFramesPerSlice=%u; TooManyFrames", __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)mMaxFramesPerSlice); - } - goto TooManyFrames; - } - ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr); - - AUOutputElement *output = GetScope(kAudioUnitScope_Output).GetNumberOfElements() > 0 ? GetOutput(inBusNumber) : NULL; // will throw if non-existant - if (output != NULL && output->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) { - DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError", - __FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams()); - goto ParamErr; - } - - unsigned expectedBufferByteSize = output != NULL ? inFramesToProcess * output->GetStreamFormat().mBytesPerFrame : 0; - for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) { - AudioBuffer &buf = ioData.mBuffers[ibuf]; - if (buf.mData != NULL) { - // only care about the size if the buffer is non-null - if (buf.mDataByteSize < expectedBufferByteSize) { - // if the buffer is too small, we cannot render safely. kAudio_ParamError. - DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError", - __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize); - goto ParamErr; - } - // Some clients incorrectly pass bigger buffers than expectedBufferByteSize. - // We will generally set the buffer size at the end of rendering, before we return. - // However we should ensure that no one, DURING rendering, READS a - // potentially incorrect size. This can lead to doing too much work, or - // reading past the end of an input buffer into unmapped memory. - buf.mDataByteSize = expectedBufferByteSize; - } - } - - if (WantsRenderThreadID()) - { - #if TARGET_OS_MAC - mRenderThreadID = pthread_self(); - #elif TARGET_OS_WIN32 - mRenderThreadID = GetCurrentThreadId(); - #endif - } - - AudioUnitRenderActionFlags flags; - if (mRenderCallbacksTouched) { - mRenderCallbacks.update(); - flags = ioActionFlags | kAudioUnitRenderAction_PreRender; - for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) { - RenderCallback &rc = *rcit; - AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0); - (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon, - &flags, - &inTimeStamp, inBusNumber, inFramesToProcess, &ioData); - AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 1, 0); - } - } - - theError = DoRenderBus(ioActionFlags, inTimeStamp, inBusNumber, output, inFramesToProcess, ioData); - - if (mRenderCallbacksTouched) { - flags = ioActionFlags | kAudioUnitRenderAction_PostRender; - - if (SetRenderError (theError)) { - flags |= kAudioUnitRenderAction_PostRenderError; - } - - for (rcit = mRenderCallbacks.begin(); rcit != mRenderCallbacks.end(); ++rcit) { - RenderCallback &rc = *rcit; - AUTRACE(kCATrace_AUBaseRenderCallbackStart, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0); - (*(AURenderCallback)rc.mRenderNotify)(rc.mRenderNotifyRefCon, - &flags, - &inTimeStamp, inBusNumber, inFramesToProcess, &ioData); - AUTRACE(kCATrace_AUBaseRenderCallbackEnd, mComponentInstance, (intptr_t)this, (intptr_t)rc.mRenderNotify, 2, 0); - } - } - - // The vector's being emptied - // because these events should only apply to this Render cycle, so anything - // left over is from a preceding cycle and should be dumped. New scheduled - // parameters must be scheduled from the next pre-render callback. - if (!mParamList.empty()) - mParamList.clear(); - - } - catch (OSStatus err) { - theError = err; - goto errexit; - } - catch (...) { - theError = -1; - goto errexit; - } -done: - RESTORE_DENORMALS - AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData)); - - return theError; - -Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit; -ParamErr: theError = kAudio_ParamError; goto errexit; -TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit; -errexit: - DebugMessageN2 (" from %s, render err: %d", GetLoggingString(), (int)theError); - SetRenderError(theError); - goto done; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::DoProcess ( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inFramesToProcess, - AudioBufferList & ioData) -{ - OSStatus theError; - AUTRACE(kCATrace_AUBaseRenderStart, mComponentInstance, (intptr_t)this, -1, inFramesToProcess, 0); - DISABLE_DENORMALS - - try { - - if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) { - ca_require(IsInitialized(), Uninitialized); - ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames); - ca_require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr); - - AUInputElement *input = GetInput(0); // will throw if non-existant - if (input->GetStreamFormat().NumberChannelStreams() != ioData.mNumberBuffers) { - DebugMessageN4("%s:%d ioData.mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError", - __FILE__, __LINE__, (unsigned)ioData.mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams()); - goto ParamErr; - } - - unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame; - for (unsigned ibuf = 0; ibuf < ioData.mNumberBuffers; ++ibuf) { - AudioBuffer &buf = ioData.mBuffers[ibuf]; - if (buf.mData != NULL) { - // only care about the size if the buffer is non-null - if (buf.mDataByteSize < expectedBufferByteSize) { - // if the buffer is too small, we cannot render safely. kAudio_ParamError. - DebugMessageN7("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioData.mBuffers[%u].mDataByteSize=%u; kAudio_ParamError", - __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibuf, (unsigned)buf.mDataByteSize); - goto ParamErr; - } - // Some clients incorrectly pass bigger buffers than expectedBufferByteSize. - // We will generally set the buffer size at the end of rendering, before we return. - // However we should ensure that no one, DURING rendering, READS a - // potentially incorrect size. This can lead to doing too much work, or - // reading past the end of an input buffer into unmapped memory. - buf.mDataByteSize = expectedBufferByteSize; - } - } - } - - if (WantsRenderThreadID()) - { - #if TARGET_OS_MAC - mRenderThreadID = pthread_self(); - #elif TARGET_OS_WIN32 - mRenderThreadID = GetCurrentThreadId(); - #endif - } - - if (NeedsToRender (inTimeStamp)) { - theError = ProcessBufferLists (ioActionFlags, ioData, ioData, inFramesToProcess); - } else - theError = noErr; - - } - catch (OSStatus err) { - theError = err; - goto errexit; - } - catch (...) { - theError = -1; - goto errexit; - } -done: - RESTORE_DENORMALS - AUTRACE(kCATrace_AUBaseRenderEnd, mComponentInstance, (intptr_t)this, theError, ioActionFlags, CATrace::ablData(ioData)); - - return theError; - -Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit; -ParamErr: theError = kAudio_ParamError; goto errexit; -TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit; -errexit: - DebugMessageN2 (" from %s, process err: %d", GetLoggingString(), (int)theError); - SetRenderError(theError); - goto done; -} - -OSStatus AUBase::DoProcessMultiple ( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inFramesToProcess, - UInt32 inNumberInputBufferLists, - const AudioBufferList ** inInputBufferLists, - UInt32 inNumberOutputBufferLists, - AudioBufferList ** ioOutputBufferLists) -{ - OSStatus theError; - DISABLE_DENORMALS - - try { - - if (!(ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)) { - ca_require(IsInitialized(), Uninitialized); - ca_require(inFramesToProcess <= mMaxFramesPerSlice, TooManyFrames); - ca_require (!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), ParamErr); - - for (unsigned ibl = 0; ibl < inNumberInputBufferLists; ++ibl) { - if (inInputBufferLists[ibl] != NULL) { - AUInputElement *input = GetInput(ibl); // will throw if non-existant - unsigned expectedBufferByteSize = inFramesToProcess * input->GetStreamFormat().mBytesPerFrame; - - if (input->GetStreamFormat().NumberChannelStreams() != inInputBufferLists[ibl]->mNumberBuffers) { - DebugMessageN5("%s:%d inInputBufferLists[%u]->mNumberBuffers=%u, input->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError", - __FILE__, __LINE__, ibl, (unsigned)inInputBufferLists[ibl]->mNumberBuffers, (unsigned)input->GetStreamFormat().NumberChannelStreams()); - goto ParamErr; - } - - for (unsigned ibuf = 0; ibuf < inInputBufferLists[ibl]->mNumberBuffers; ++ibuf) { - const AudioBuffer &buf = inInputBufferLists[ibl]->mBuffers[ibuf]; - if (buf.mData != NULL) { - if (buf.mDataByteSize < expectedBufferByteSize) { - // the buffer is too small - DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; inInputBufferLists[%u].mBuffers[%u].mDataByteSize=%u; kAudio_ParamError", - __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)input->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, ibl, ibuf, (unsigned)buf.mDataByteSize); - goto ParamErr; - } - } else { - // the buffer must exist - goto ParamErr; - } - } - } else { - // skip NULL input audio buffer list - } - } - - for (unsigned obl = 0; obl < inNumberOutputBufferLists; ++obl) { - if (ioOutputBufferLists[obl] != NULL) { - AUOutputElement *output = GetOutput(obl); // will throw if non-existant - unsigned expectedBufferByteSize = inFramesToProcess * output->GetStreamFormat().mBytesPerFrame; - - if (output->GetStreamFormat().NumberChannelStreams() != ioOutputBufferLists[obl]->mNumberBuffers) { - DebugMessageN5("%s:%d ioOutputBufferLists[%u]->mNumberBuffers=%u, output->GetStreamFormat().NumberChannelStreams()=%u; kAudio_ParamError", - __FILE__, __LINE__, obl, (unsigned)ioOutputBufferLists[obl]->mNumberBuffers, (unsigned)output->GetStreamFormat().NumberChannelStreams()); - goto ParamErr; - } - - for (unsigned obuf = 0; obuf < ioOutputBufferLists[obl]->mNumberBuffers; ++obuf) { - AudioBuffer &buf = ioOutputBufferLists[obl]->mBuffers[obuf]; - if (buf.mData != NULL) { - // only care about the size if the buffer is non-null - if (buf.mDataByteSize < expectedBufferByteSize) { - // if the buffer is too small, we cannot render safely. kAudio_ParamError. - DebugMessageN8("%s:%d %u frames, %u bytes/frame, expected %u-byte buffer; ioOutputBufferLists[%u]->mBuffers[%u].mDataByteSize=%u; kAudio_ParamError", - __FILE__, __LINE__, (unsigned)inFramesToProcess, (unsigned)output->GetStreamFormat().mBytesPerFrame, expectedBufferByteSize, obl, obuf, (unsigned)buf.mDataByteSize); - goto ParamErr; - } - // Some clients incorrectly pass bigger buffers than expectedBufferByteSize. - // We will generally set the buffer size at the end of rendering, before we return. - // However we should ensure that no one, DURING rendering, READS a - // potentially incorrect size. This can lead to doing too much work, or - // reading past the end of an input buffer into unmapped memory. - buf.mDataByteSize = expectedBufferByteSize; - } - } - } else { - // skip NULL output audio buffer list - } - } - } - - if (WantsRenderThreadID()) - { -#if TARGET_OS_MAC - mRenderThreadID = pthread_self(); -#elif TARGET_OS_WIN32 - mRenderThreadID = GetCurrentThreadId(); -#endif - } - - if (NeedsToRender (inTimeStamp)) { - theError = ProcessMultipleBufferLists (ioActionFlags, inFramesToProcess, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists); - } else - theError = noErr; - } - catch (OSStatus err) { - theError = err; - goto errexit; - } - catch (...) { - theError = -1; - goto errexit; - } -done: - RESTORE_DENORMALS - - return theError; - -Uninitialized: theError = kAudioUnitErr_Uninitialized; goto errexit; -ParamErr: theError = kAudio_ParamError; goto errexit; -TooManyFrames: theError = kAudioUnitErr_TooManyFramesToProcess; goto errexit; -errexit: - DebugMessageN2 (" from %s, processmultiple err: %d", GetLoggingString(), (int)theError); - SetRenderError(theError); - goto done; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::SetInputCallback( UInt32 inPropertyID, - AudioUnitElement inElement, - AURenderCallback inProc, - void * inRefCon) -{ - AUInputElement *input = GetInput(inElement); // may throw - - input->SetInputCallback(inProc, inRefCon); - PropertyChanged(inPropertyID, kAudioUnitScope_Input, inElement); - - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::SetConnection( const AudioUnitConnection & inConnection) -{ - - OSStatus err; - AUInputElement *input = GetInput(inConnection.destInputNumber); // may throw - - if (inConnection.sourceAudioUnit) { - // connecting, not disconnecting - CAStreamBasicDescription sourceDesc; - UInt32 size = sizeof(CAStreamBasicDescription); - ca_require_noerr(err = AudioUnitGetProperty( - inConnection.sourceAudioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - inConnection.sourceOutputNumber, - &sourceDesc, - &size), errexit); - ca_require_noerr(err = DispatchSetProperty (kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, inConnection.destInputNumber, - &sourceDesc, sizeof(CAStreamBasicDescription)), errexit); - } - input->SetConnection(inConnection); - - PropertyChanged(kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, inConnection.destInputNumber); - return noErr; - -errexit: - return err; -} - -//_____________________________________________________________________________ -// -UInt32 AUBase::SupportedNumChannels ( const AUChannelInfo** outInfo) -{ - return 0; -} - -//_____________________________________________________________________________ -// -bool AUBase::ValidFormat( AudioUnitScope inScope, - AudioUnitElement inElement, - const CAStreamBasicDescription & inNewFormat) -{ - return FormatIsCanonical(inNewFormat); -} - -//_____________________________________________________________________________ -// -bool AUBase::IsStreamFormatWritable( AudioUnitScope scope, - AudioUnitElement element) -{ - switch (scope) { - case kAudioUnitScope_Input: - { - AUInputElement *input = GetInput(element); - if (input->HasConnection()) return false; // can't write format when input comes from connection - } - // ... fall ... - case kAudioUnitScope_Output: - return StreamFormatWritable(scope, element); - -//#warning "aliasing of global scope format should be pushed to subclasses" - case kAudioUnitScope_Global: - return StreamFormatWritable(kAudioUnitScope_Output, 0); - } - return false; -} - -//_____________________________________________________________________________ -// -const CAStreamBasicDescription & - AUBase::GetStreamFormat( AudioUnitScope inScope, - AudioUnitElement inElement) -{ -//#warning "aliasing of global scope format should be pushed to subclasses" - AUIOElement *element; - - switch (inScope) { - case kAudioUnitScope_Input: - element = Inputs().GetIOElement(inElement); - break; - case kAudioUnitScope_Output: - element = Outputs().GetIOElement(inElement); - break; - case kAudioUnitScope_Global: // global stream description is an alias for that of output 0 - element = Outputs().GetIOElement(0); - break; - default: - COMPONENT_THROW(kAudioUnitErr_InvalidScope); - } - return element->GetStreamFormat(); -} - -OSStatus AUBase::SetBusCount( AudioUnitScope inScope, - UInt32 inCount) -{ - if (IsInitialized()) - return kAudioUnitErr_Initialized; - - GetScope(inScope).SetNumberOfElements(inCount); - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::ChangeStreamFormat( AudioUnitScope inScope, - AudioUnitElement inElement, - const CAStreamBasicDescription & inPrevFormat, - const CAStreamBasicDescription & inNewFormat) -{ -//#warning "aliasing of global scope format should be pushed to subclasses" - AUIOElement *element; - - switch (inScope) { - case kAudioUnitScope_Input: - element = Inputs().GetIOElement(inElement); - break; - case kAudioUnitScope_Output: - element = Outputs().GetIOElement(inElement); - break; - case kAudioUnitScope_Global: - element = Outputs().GetIOElement(0); - break; - default: - COMPONENT_THROW(kAudioUnitErr_InvalidScope); - } - element->SetStreamFormat(inNewFormat); - PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement); - return noErr; -} - -UInt32 AUBase::GetChannelLayoutTags( AudioUnitScope inScope, - AudioUnitElement inElement, - AudioChannelLayoutTag * outLayoutTags) -{ - return GetIOElement(inScope, inElement)->GetChannelLayoutTags(outLayoutTags); -} - -UInt32 AUBase::GetAudioChannelLayout( AudioUnitScope scope, - AudioUnitElement element, - AudioChannelLayout * outLayoutPtr, - Boolean & outWritable) -{ - AUIOElement * el = GetIOElement(scope, element); - return el->GetAudioChannelLayout(outLayoutPtr, outWritable); -} - -OSStatus AUBase::RemoveAudioChannelLayout( AudioUnitScope inScope, - AudioUnitElement inElement) -{ - OSStatus result = noErr; - AUIOElement * el = GetIOElement(inScope, inElement); - Boolean writable; - if (el->GetAudioChannelLayout(NULL, writable)) { - result = el->RemoveAudioChannelLayout(); - } - return result; -} - -OSStatus AUBase::SetAudioChannelLayout( AudioUnitScope inScope, - AudioUnitElement inElement, - const AudioChannelLayout * inLayout) -{ - AUIOElement* ioEl = GetIOElement (inScope, inElement); - - // the num channels of the layout HAS TO MATCH the current channels of the Element's stream format - UInt32 currentChannels = ioEl->GetStreamFormat().NumberChannels(); - UInt32 numChannelsInLayout = CAAudioChannelLayout::NumberChannels(*inLayout); - if (currentChannels != numChannelsInLayout) - return kAudioUnitErr_InvalidPropertyValue; - - UInt32 numLayouts = GetChannelLayoutTags (inScope, inElement, NULL); - if (numLayouts == 0) - return kAudioUnitErr_InvalidProperty; - AudioChannelLayoutTag *tags = (AudioChannelLayoutTag *)CA_malloc (numLayouts * sizeof (AudioChannelLayoutTag)); - GetChannelLayoutTags (inScope, inElement, tags); - bool foundTag = false; - for (unsigned int i = 0; i < numLayouts; ++i) { - if (tags[i] == inLayout->mChannelLayoutTag || tags[i] == kAudioChannelLayoutTag_UseChannelDescriptions) { - foundTag = true; - break; - } - } - free(tags); - - if (foundTag == false) - return kAudioUnitErr_InvalidPropertyValue; - - return ioEl->SetAudioChannelLayout(*inLayout); -} - -static void AddNumToDictionary (CFMutableDictionaryRef dict, CFStringRef key, SInt32 value) -{ - CFNumberRef num = CFNumberCreate (NULL, kCFNumberSInt32Type, &value); - CFDictionarySetValue (dict, key, num); - CFRelease (num); -} - -#define kCurrentSavedStateVersion 0 - -OSStatus AUBase::SaveState( CFPropertyListRef * outData) -{ - AudioComponentDescription desc = GetComponentDescription(); - - CFMutableDictionaryRef dict = CFDictionaryCreateMutable (NULL, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - -// first step -> save the version to the data ref - SInt32 value = kCurrentSavedStateVersion; - AddNumToDictionary (dict, kVersionString, value); - -// second step -> save the component type, subtype, manu to the data ref - value = desc.componentType; - AddNumToDictionary (dict, kTypeString, value); - - value = desc.componentSubType; - AddNumToDictionary (dict, kSubtypeString, value); - - value = desc.componentManufacturer; - AddNumToDictionary (dict, kManufacturerString, value); - -// fourth step -> save the state of all parameters on all scopes and elements - CFMutableDataRef data = CFDataCreateMutable(NULL, 0); - for (AudioUnitScope iscope = 0; iscope < 3; ++iscope) { - AUScope &scope = GetScope(iscope); - scope.SaveState (data); - } - - SaveExtendedScopes(data); - -// save all this in the data section of the dictionary - CFDictionarySetValue(dict, kDataString, data); - CFRelease (data); - -//OK - now we're going to do some properties -//save the preset name... - CFDictionarySetValue (dict, kNameString, mCurrentPreset.presetName); - -// Does the unit support the RenderQuality property - if so, save it... - value = 0; - OSStatus result = DispatchGetProperty (kAudioUnitProperty_RenderQuality, - kAudioUnitScope_Global, - 0, - &value); - - if (result == noErr) { - AddNumToDictionary (dict, kRenderQualityString, value); - } - -// Does the unit support the CPULoad Quality property - if so, save it... - Float32 cpuLoad; - result = DispatchGetProperty (6/*kAudioUnitProperty_CPULoad*/, - kAudioUnitScope_Global, - 0, - &cpuLoad); - - if (result == noErr) { - CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType, &cpuLoad); - CFDictionarySetValue (dict, kCPULoadString, num); - CFRelease (num); - } - -// Do we have any element names for any of our scopes? - // first check to see if we have any names... - bool foundName = false; - for (AudioUnitScope i = 0; i < kNumScopes; ++i) { - foundName = GetScope (i).HasElementWithName(); - if (foundName) - break; - } - // OK - we found a name away we go... - if (foundName) { - CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable (NULL, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - for (AudioUnitScope i = 0; i < kNumScopes; ++i) { - GetScope (i).AddElementNamesToDict (nameDict); - } - - CFDictionarySetValue (dict, kElementNameString, nameDict); - CFRelease (nameDict); - } - -// we're done!!! - *outData = dict; - - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::RestoreState( CFPropertyListRef plist) -{ - if (CFGetTypeID(plist) != CFDictionaryGetTypeID()) return kAudioUnitErr_InvalidPropertyValue; - - AudioComponentDescription desc = GetComponentDescription(); - - CFDictionaryRef dict = static_cast(plist); - -// zeroeth step - make sure the Part key is NOT present, as this method is used -// to restore the GLOBAL state of the dictionary - if (CFDictionaryContainsKey (dict, kPartString)) - return kAudioUnitErr_InvalidPropertyValue; - -// first step -> check the saved version in the data ref -// at this point we're only dealing with version==0 - CFNumberRef cfnum = reinterpret_cast(CFDictionaryGetValue (dict, kVersionString)); - if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue; - SInt32 value; - CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value); - if (value != kCurrentSavedStateVersion) return kAudioUnitErr_InvalidPropertyValue; - -// second step -> check that this data belongs to this kind of audio unit -// by checking the component subtype and manuID -// We're not checking the type, since there may be different versions (effect, format-converter, offline) -// of essentially the same AU - cfnum = reinterpret_cast(CFDictionaryGetValue (dict, kSubtypeString)); - if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue; - CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value); - if (UInt32(value) != desc.componentSubType) return kAudioUnitErr_InvalidPropertyValue; - - cfnum = reinterpret_cast(CFDictionaryGetValue (dict, kManufacturerString)); - if (cfnum == NULL) return kAudioUnitErr_InvalidPropertyValue; - CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value); - if (UInt32(value) != desc.componentManufacturer) return kAudioUnitErr_InvalidPropertyValue; - -// fourth step -> restore the state of all of the parameters for each scope and element - CFDataRef data = reinterpret_cast(CFDictionaryGetValue (dict, kDataString)); - if (data != NULL) - { - const UInt8 *p, *pend; - - p = CFDataGetBytePtr(data); - pend = p + CFDataGetLength(data); - - // we have a zero length data, which may just mean there were no parameters to save! - // if (p >= pend) return noErr; - - while (p < pend) { - UInt32 scopeIdx = CFSwapInt32BigToHost(*(UInt32 *)p); - p += sizeof(UInt32); - - AUScope &scope = GetScope(scopeIdx); - p = scope.RestoreState(p); - } - } - -//OK - now we're going to do some properties -//restore the preset name... - CFStringRef name = reinterpret_cast(CFDictionaryGetValue (dict, kNameString)); - if (mCurrentPreset.presetName) CFRelease (mCurrentPreset.presetName); - if (name) - { - mCurrentPreset.presetName = name; - mCurrentPreset.presetNumber = -1; - } - else { // no name entry make the default one - mCurrentPreset.presetName = kUntitledString; - mCurrentPreset.presetNumber = -1; - } - - CFRetain (mCurrentPreset.presetName); -#if !CA_USE_AUDIO_PLUGIN_ONLY -#ifndef __LP64__ - PropertyChanged(kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0); -#endif -#endif - PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0); - -// Does the dict contain render quality information? - if (CFDictionaryGetValueIfPresent (dict, kRenderQualityString, reinterpret_cast(&cfnum))) - { - CFNumberGetValue (cfnum, kCFNumberSInt32Type, &value); - DispatchSetProperty (kAudioUnitProperty_RenderQuality, - kAudioUnitScope_Global, - 0, - &value, - sizeof(value)); - } - -// Does the unit support the CPULoad Quality property - if so, save it... - if (CFDictionaryGetValueIfPresent (dict, kCPULoadString, reinterpret_cast(&cfnum))) - { - Float32 floatValue; - CFNumberGetValue (cfnum, kCFNumberFloatType, &floatValue); - DispatchSetProperty (6/*kAudioUnitProperty_CPULoad*/, - kAudioUnitScope_Global, - 0, - &floatValue, - sizeof(floatValue)); - } - -// Do we have any element names for any of our scopes? - CFDictionaryRef nameDict; - if (CFDictionaryGetValueIfPresent (dict, kElementNameString, reinterpret_cast(&nameDict))) - { - char string[64]; - for (int i = 0; i < kNumScopes; ++i) - { - snprintf (string, sizeof(string), "%d", i); - CFStringRef key = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII); - CFDictionaryRef elementDict; - if (CFDictionaryGetValueIfPresent (nameDict, key, reinterpret_cast(&elementDict))) - { - bool didAddElements = GetScope (i).RestoreElementNames (elementDict); - if (didAddElements) - PropertyChanged (kAudioUnitProperty_ElementCount, i, 0); - } - CFRelease (key); - } - } - - return noErr; -} - -OSStatus AUBase::GetPresets ( CFArrayRef * outData) const -{ - return kAudioUnitErr_InvalidProperty; -} - -OSStatus AUBase::NewFactoryPresetSet (const AUPreset & inNewFactoryPreset) -{ - return kAudioUnitErr_InvalidProperty; -} - -OSStatus AUBase::NewCustomPresetSet (const AUPreset & inNewCustomPreset) -{ - CFRelease (mCurrentPreset.presetName); - mCurrentPreset = inNewCustomPreset; - CFRetain (mCurrentPreset.presetName); - return noErr; -} - - // set the default preset for the unit -> the number of the preset MUST be >= 0 - // and the name should be valid, or the preset WON'T take -bool AUBase::SetAFactoryPresetAsCurrent (const AUPreset & inPreset) -{ - if (inPreset.presetNumber < 0 || inPreset.presetName == NULL) return false; - CFRelease (mCurrentPreset.presetName); - mCurrentPreset = inPreset; - CFRetain (mCurrentPreset.presetName); - return true; -} - -#if !CA_USE_AUDIO_PLUGIN_ONLY -int AUBase::GetNumCustomUIComponents () -{ - return 0; -} - -void AUBase::GetUIComponentDescs (ComponentDescription* inDescArray) {} -#endif - -bool AUBase::HasIcon () -{ -#if !CA_NO_AU_UI_FEATURES - CFURLRef url = CopyIconLocation(); - if (url) { - CFRelease (url); - return true; - } -#endif - return false; -} - -CFURLRef AUBase::CopyIconLocation () -{ - return NULL; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetParameterList( AudioUnitScope inScope, - AudioUnitParameterID * outParameterList, - UInt32 & outNumParameters) -{ - AUScope &scope = GetScope(inScope); - AUElement *elementWithMostParameters = NULL; - UInt32 maxNumParams = 0; - - int nElems = scope.GetNumberOfElements(); - for (int ielem = 0; ielem < nElems; ++ielem) { - AUElement *element = scope.GetElement(ielem); - UInt32 nParams = element->GetNumberOfParameters(); - if (nParams > maxNumParams) { - maxNumParams = nParams; - elementWithMostParameters = element; - } - } - - if (outParameterList != NULL && elementWithMostParameters != NULL) - elementWithMostParameters->GetParameterList(outParameterList); - - outNumParameters = maxNumParams; - return noErr; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetParameterInfo( AudioUnitScope inScope, - AudioUnitParameterID inParameterID, - AudioUnitParameterInfo &outParameterInfo ) -{ - return kAudioUnitErr_InvalidParameter; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetParameterValueStrings(AudioUnitScope inScope, - AudioUnitParameterID inParameterID, - CFArrayRef * outStrings) -{ - return kAudioUnitErr_InvalidProperty; -} - -//_____________________________________________________________________________ -// -OSStatus AUBase::GetParameterHistoryInfo( AudioUnitScope inScope, - AudioUnitParameterID inParameterID, - Float32 & outUpdatesPerSecond, - Float32 & outHistoryDurationInSeconds) -{ - return kAudioUnitErr_InvalidProperty; -} - - -//_____________________________________________________________________________ -// -OSStatus AUBase::CopyClumpName( AudioUnitScope inScope, - UInt32 inClumpID, - UInt32 inDesiredNameLength, - CFStringRef * outClumpName) -{ - return kAudioUnitErr_InvalidProperty; -} - -//_____________________________________________________________________________ -// -void AUBase::SetNumberOfElements( AudioUnitScope inScope, - UInt32 numElements) -{ - if (inScope == kAudioUnitScope_Global && numElements != 1) - COMPONENT_THROW(kAudioUnitErr_InvalidScope); - - GetScope(inScope).SetNumberOfElements(numElements); -} - -//_____________________________________________________________________________ -// -AUElement * AUBase::CreateElement( AudioUnitScope scope, - AudioUnitElement element) -{ - switch (scope) { - case kAudioUnitScope_Global: - return new AUElement(this); - case kAudioUnitScope_Input: - return new AUInputElement(this); - case kAudioUnitScope_Output: - return new AUOutputElement(this); -#if !CA_BASIC_AU_FEATURES - case kAudioUnitScope_Group: - return new AUElement(this); - case kAudioUnitScope_Part: - return new AUElement(this); -#endif - } - COMPONENT_THROW(kAudioUnitErr_InvalidScope); - - return NULL; // get rid of compiler warning -} - -//_____________________________________________________________________________ -// -bool AUBase::FormatIsCanonical( const CAStreamBasicDescription &f) -{ - return (f.mFormatID == kAudioFormatLinearPCM - && f.mFramesPerPacket == 1 - && f.mBytesPerPacket == f.mBytesPerFrame -// && f.mChannelsPerFrame >= 0 -- this is always true since it's unsigned - // so far, it's a valid PCM format -#if CA_PREFER_FIXED_POINT - && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) == 0 - && (((f.mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift) == kAudioUnitSampleFractionBits) -#else - && (f.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0 -#endif - && ((f.mChannelsPerFrame == 1) || ((f.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0) == (mAudioUnitAPIVersion == 1)) -#if TARGET_RT_BIG_ENDIAN - && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) != 0 -#else - && (f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) == 0 -#endif - && f.mBitsPerChannel == 8 * sizeof(AudioUnitSampleType) - && f.mBytesPerFrame == f.NumberInterleavedChannels() * sizeof(AudioUnitSampleType) - ); -} - -//_____________________________________________________________________________ -// -void AUBase::MakeCanonicalFormat( CAStreamBasicDescription & f, - int nChannels) -{ - f.SetAUCanonical(nChannels, mAudioUnitAPIVersion < 2); // interleaved for v1, non for v2 - f.mSampleRate = 0.0; -} - -const Float64 AUBase::kNoLastRenderedSampleTime = -1.; - -#include "AUBaseHelper.h" - -char* AUBase::GetLoggingString () const -{ - if (mLogString) return mLogString; - - AudioComponentDescription desc = GetComponentDescription(); - - const size_t logStringSize = 256; - const_cast(this)->mLogString = new char[logStringSize]; - char str[24]; - char str1[24]; - char str2[24]; - snprintf (const_cast(this)->mLogString, logStringSize, "AU (%p): %s %s %s", - GetComponentInstance(), - CAStringForOSType(desc.componentType, str, sizeof(str)), - CAStringForOSType(desc.componentSubType, str1, sizeof(str1)), - CAStringForOSType(desc.componentManufacturer, str2, sizeof(str2))); - - return mLogString; -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h deleted file mode 100644 index 6b52019c63..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h +++ /dev/null @@ -1,1054 +0,0 @@ -/* - File: AUBase.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 __AUBase_h__ -#define __AUBase_h__ - -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#include - -#if TARGET_OS_MAC - #include -#elif TARGET_OS_WIN32 - #include -#else - #error Unsupported Operating System -#endif - -#include - -#include "AUScopeElement.h" -#include "AUInputElement.h" -#include "AUOutputElement.h" -#include "AUBuffer.h" -#include "CAMath.h" -#include "CAThreadSafeList.h" -#include "CAVectorUnit.h" -#include "CAMutex.h" -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #if !CA_BASIC_AU_FEATURES - #include - #endif -#else - #include "AudioUnit.h" - #if !CA_BASIC_AU_FEATURES - #include "MusicDevice.h" - #endif -#endif - -#ifndef AUTRACE - #define AUTRACE(code, obj, a, b, c, d) -#endif - -#include "AUPlugInDispatch.h" - - - -// ________________________________________________________________________ -// These are to be moved to the public AudioUnit headers - -#define kAUDefaultSampleRate 44100.0 -#if !TARGET_OS_WIN32 -#define kAUDefaultMaxFramesPerSlice 1156 -//this allows enough default frames for a 512 dest 44K and SRC from 96K -// add a padding of 4 frames for any altivec rounding -#else -#define kAUDefaultMaxFramesPerSlice 2048 -#endif - -// ________________________________________________________________________ - -/*! @class AUBase */ -class AUBase : public ComponentBase { -public: - - /*! @ctor AUBase */ - AUBase( AudioComponentInstance inInstance, - UInt32 numInputElements, - UInt32 numOutputElements, - UInt32 numGroupElements = 0); - /*! @dtor AUBase */ - virtual ~AUBase(); - - /*! @method PostConstructor */ - virtual void PostConstructor() { CreateElements(); } - - /*! @method PreDestructor */ - virtual void PreDestructor(); - - /*! @method CreateElements */ - void CreateElements(); - // Called immediately after construction, when virtual methods work. - // Or, a subclass may call this in order to have access to elements - // in its constructor. - - /*! @method CreateExtendedElements */ - virtual void CreateExtendedElements() {} - -#pragma mark - -#pragma mark AU dispatch - // ________________________________________________________________________ - // Virtual methods (mostly) directly corresponding to the entry points. Many of these - // have useful implementations here and will not need overriding. - - /*! @method DoInitialize */ - OSStatus DoInitialize(); - // this implements the entry point and makes sure that initialization - // is only attempted exactly once... - - /*! @method Initialize */ - virtual OSStatus Initialize(); - // ... so that overrides to this method can assume that they will only - // be called exactly once. - - /*! @method IsInitialized */ - bool IsInitialized() const { return mInitialized; } - /*! @method HasBegunInitializing */ - bool HasBegunInitializing() const { return mHasBegunInitializing; } - - /*! @method DoCleanup */ - void DoCleanup(); - // same pattern as with Initialize - - /*! @method Cleanup */ - virtual void Cleanup(); - - /*! @method Reset */ - virtual OSStatus Reset( AudioUnitScope inScope, - AudioUnitElement inElement); - - // Note about GetPropertyInfo, GetProperty, SetProperty: - // Certain properties are trapped out in these dispatch functions and handled with different virtual - // methods. (To discourage hacks and keep vtable size down, these are non-virtual) - - /*! @method DispatchGetPropertyInfo */ - OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - UInt32 & outDataSize, - Boolean & outWritable); - - /*! @method DispatchGetProperty */ - OSStatus DispatchGetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - void * outData); - - /*! @method DispatchSetProperty */ - OSStatus DispatchSetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - const void * inData, - UInt32 inDataSize); - - OSStatus DispatchRemovePropertyValue( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement); - - /*! @method GetPropertyInfo */ - virtual OSStatus GetPropertyInfo( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - UInt32 & outDataSize, - Boolean & outWritable); - - /*! @method GetProperty */ - virtual OSStatus GetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - void * outData); - - /*! @method SetProperty */ - virtual OSStatus SetProperty( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - const void * inData, - UInt32 inDataSize); - - /*! @method ClearPropertyUsage */ - virtual OSStatus RemovePropertyValue ( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement); - - /*! @method AddPropertyListener */ - virtual OSStatus AddPropertyListener( AudioUnitPropertyID inID, - AudioUnitPropertyListenerProc inProc, - void * inProcRefCon); - - /*! @method RemovePropertyListener */ - virtual OSStatus RemovePropertyListener( AudioUnitPropertyID inID, - AudioUnitPropertyListenerProc inProc, - void * inProcRefCon, - bool refConSpecified); - - /*! @method SetRenderNotification */ - virtual OSStatus SetRenderNotification( AURenderCallback inProc, - void * inRefCon); - - /*! @method RemoveRenderNotification */ - virtual OSStatus RemoveRenderNotification( - AURenderCallback inProc, - void * inRefCon); - - /*! @method GetParameter */ - virtual OSStatus GetParameter( AudioUnitParameterID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - AudioUnitParameterValue & outValue); - - /*! @method SetParameter */ - virtual OSStatus SetParameter( AudioUnitParameterID inID, - AudioUnitScope inScope, - AudioUnitElement inElement, - AudioUnitParameterValue inValue, - UInt32 inBufferOffsetInFrames); - - /*! @method CanScheduleParams */ - virtual bool CanScheduleParameters() const = 0; - - /*! @method ScheduleParameter */ - virtual OSStatus ScheduleParameter ( const AudioUnitParameterEvent *inParameterEvent, - UInt32 inNumEvents); - - - /*! @method DoRender */ - OSStatus DoRender( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList & ioData); - - - /*! @method Process */ - OSStatus DoProcess ( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inFramesToProcess, - AudioBufferList & ioData); - - /*! @method ProcessMultiple */ - OSStatus DoProcessMultiple ( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inFramesToProcess, - UInt32 inNumberInputBufferLists, - const AudioBufferList ** inInputBufferLists, - UInt32 inNumberOutputBufferLists, - AudioBufferList ** ioOutputBufferLists); - - /*! @method ProcessBufferLists */ - virtual OSStatus ProcessBufferLists( AudioUnitRenderActionFlags & ioActionFlags, - const AudioBufferList & inBuffer, - AudioBufferList & outBuffer, - UInt32 inFramesToProcess ) - { - return kAudio_UnimplementedError; - } - - /*! @method ProcessMultipleBufferLists */ - virtual OSStatus ProcessMultipleBufferLists( AudioUnitRenderActionFlags & ioActionFlags, - UInt32 inFramesToProcess, - UInt32 inNumberInputBufferLists, - const AudioBufferList ** inInputBufferLists, - UInt32 inNumberOutputBufferLists, - AudioBufferList ** ioOutputBufferLists) - { - return kAudio_UnimplementedError; - } - - /*! @method ComplexRender */ - virtual OSStatus ComplexRender( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inOutputBusNumber, - UInt32 inNumberOfPackets, - UInt32 * outNumberOfPackets, - AudioStreamPacketDescription * outPacketDescriptions, - AudioBufferList & ioData, - void * outMetadata, - UInt32 * outMetadataByteSize) - { - return kAudio_UnimplementedError; - } - - // Override this method if your AU processes multiple output busses completely independently -- - // you'll want to just call Render without the NeedsToRender check. - // Otherwise, override Render(). - // - // N.B. Implementations of this method can assume that the output's buffer list has already been - // prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of - // GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a - // copy may occur after rendering. - /*! @method RenderBus */ - virtual OSStatus RenderBus( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames) - { - if (NeedsToRender(inTimeStamp)) - return Render(ioActionFlags, inTimeStamp, inNumberFrames); - return noErr; // was presumably already rendered via another bus - } - - // N.B. For a unit with only one output bus, it can assume in its implementation of this - // method that the output's buffer list has already been prepared and access it with - // GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames) - // -- if PrepareBuffer is called, a copy may occur after rendering. - /*! @method Render */ - virtual OSStatus Render( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inNumberFrames) - { - return noErr; - } - - -#pragma mark - -#pragma mark Property Dispatch - - static const Float64 kNoLastRenderedSampleTime; - - // ________________________________________________________________________ - // These are generated from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty - - /*! @method BusCountWritable */ - virtual bool BusCountWritable( AudioUnitScope inScope) - { - return false; - } - virtual OSStatus SetBusCount( AudioUnitScope inScope, - UInt32 inCount); - - /*! @method SetConnection */ - virtual OSStatus SetConnection( const AudioUnitConnection & inConnection); - - /*! @method SetInputCallback */ - virtual OSStatus SetInputCallback( UInt32 inPropertyID, - AudioUnitElement inElement, - AURenderCallback inProc, - void * inRefCon); - - /*! @method GetParameterList */ - virtual OSStatus GetParameterList( AudioUnitScope inScope, - AudioUnitParameterID * outParameterList, - UInt32 & outNumParameters); - // outParameterList may be a null pointer - - /*! @method GetParameterInfo */ - virtual OSStatus GetParameterInfo( AudioUnitScope inScope, - AudioUnitParameterID inParameterID, - AudioUnitParameterInfo & outParameterInfo); - - virtual OSStatus GetParameterHistoryInfo(AudioUnitScope inScope, - AudioUnitParameterID inParameterID, - Float32 & outUpdatesPerSecond, - Float32 & outHistoryDurationInSeconds); - - /*! @method SaveState */ - virtual OSStatus SaveState( CFPropertyListRef * outData); - - /*! @method SaveExtendedScopes */ - virtual void SaveExtendedScopes( CFMutableDataRef outData) {}; - - /*! @method RestoreState */ - virtual OSStatus RestoreState( CFPropertyListRef inData); - - /*! @method GetParameterValueStrings */ - virtual OSStatus GetParameterValueStrings(AudioUnitScope inScope, - AudioUnitParameterID inParameterID, - CFArrayRef * outStrings); - - /*! @method CopyClumpName */ - virtual OSStatus CopyClumpName( AudioUnitScope inScope, - UInt32 inClumpID, - UInt32 inDesiredNameLength, - CFStringRef * outClumpName); - - /*! @method GetPresets */ - virtual OSStatus GetPresets ( CFArrayRef * outData) const; - - // set the default preset for the unit -> the number of the preset MUST be >= 0 - // and the name should be valid, or the preset WON'T take - /*! @method SetAFactoryPresetAsCurrent */ - bool SetAFactoryPresetAsCurrent (const AUPreset & inPreset); - - // Called when someone sets a new, valid preset - // If this is a valid preset, then the subclass sets its state to that preset - // and returns noErr. - // If not a valid preset, return an error, and the pre-existing preset is restored - /*! @method NewFactoryPresetSet */ - virtual OSStatus NewFactoryPresetSet (const AUPreset & inNewFactoryPreset); - - /*! @method NewCustomPresetSet */ - virtual OSStatus NewCustomPresetSet (const AUPreset & inNewCustomPreset); - -#if !CA_USE_AUDIO_PLUGIN_ONLY - /*! @method GetNumCustomUIComponents */ - virtual int GetNumCustomUIComponents (); - - /*! @method GetUIComponentDescs */ - virtual void GetUIComponentDescs (ComponentDescription* inDescArray); -#endif - - /*! @method CopyIconLocation */ - virtual CFURLRef CopyIconLocation (); - - // default is no latency, and unimplemented tail time - /*! @method GetLatency */ - virtual Float64 GetLatency() {return 0.0;} - /*! @method GetTailTime */ - virtual Float64 GetTailTime() {return 0;} - /*! @method SupportsRampAndTail */ - virtual bool SupportsTail () { return false; } - - /*! @method IsStreamFormatWritable */ - bool IsStreamFormatWritable( AudioUnitScope scope, - AudioUnitElement element); - - /*! @method StreamFormatWritable */ - virtual bool StreamFormatWritable( AudioUnitScope scope, - AudioUnitElement element) = 0; - // scope will always be input or output - - // pass in a pointer to get the struct, and num channel infos - // you can pass in NULL to just get the number - // a return value of 0 (the default in AUBase) means the property is not supported... - /*! @method SupportedNumChannels */ - virtual UInt32 SupportedNumChannels ( const AUChannelInfo** outInfo); - - /*! @method ValidFormat */ - virtual bool ValidFormat( AudioUnitScope inScope, - AudioUnitElement inElement, - const CAStreamBasicDescription & inNewFormat); - // Will only be called after StreamFormatWritable - // has succeeded. - // Default implementation requires canonical format: - // native-endian 32-bit float, any sample rate, - // any number of channels; override when other - // formats are supported. A subclass's override can - // choose to always return true and trap invalid - // formats in ChangeStreamFormat. - - - /*! @method FormatIsCanonical */ - bool FormatIsCanonical( const CAStreamBasicDescription &format); - - /*! @method MakeCanonicalFormat */ - void MakeCanonicalFormat( CAStreamBasicDescription & outDesc, - int numChannels = 2); - - /*! @method GetStreamFormat */ - virtual const CAStreamBasicDescription & - GetStreamFormat( AudioUnitScope inScope, - AudioUnitElement inElement); - - /*! @method ChangeStreamFormat */ - virtual OSStatus ChangeStreamFormat( AudioUnitScope inScope, - AudioUnitElement inElement, - const CAStreamBasicDescription & inPrevFormat, - const CAStreamBasicDescription & inNewFormat); - // Will only be called after StreamFormatWritable - // and ValidFormat have succeeded. - - // ________________________________________________________________________ - -#if !CA_USE_AUDIO_PLUGIN_ONLY - /*! @method ComponentEntryDispatch */ - static OSStatus ComponentEntryDispatch( ComponentParameters * params, - AUBase * This); -#endif - - // ________________________________________________________________________ - // Methods useful for subclasses - - /*! @method GetScope */ - AUScope & GetScope( AudioUnitScope inScope) - { - if (inScope >= kNumScopes) { - AUScope * scope = GetScopeExtended(inScope); - if (!scope) COMPONENT_THROW(kAudioUnitErr_InvalidScope); - return *scope; - } - return mScopes[inScope]; - } - - /*! @method GetScopeExtended */ - virtual AUScope * GetScopeExtended (AudioUnitScope inScope) { return NULL; } - - /*! @method GlobalScope */ - AUScope & GlobalScope() { return mScopes[kAudioUnitScope_Global]; } - /*! @method Inputs */ - AUScope & Inputs() { return mScopes[kAudioUnitScope_Input]; } - /*! @method Outputs */ - AUScope & Outputs() { return mScopes[kAudioUnitScope_Output]; } -#if !CA_BASIC_AU_FEATURES - /*! @method Groups */ - AUScope & Groups() { return mScopes[kAudioUnitScope_Group]; } -#endif - /*! @method Globals */ - AUElement * Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); } - - /*! @method SetNumberOfElements */ - void SetNumberOfElements( AudioUnitScope inScope, - UInt32 numElements); - - /*! @method GetElement */ - AUElement * GetElement( AudioUnitScope inScope, - AudioUnitElement inElement) - { - return GetScope(inScope).GetElement(inElement); - } - - /*! @method GetIOElement */ - AUIOElement * GetIOElement( AudioUnitScope inScope, - AudioUnitElement inElement) - { - return GetScope(inScope).GetIOElement(inElement); - } - - /*! @method SafeGetElement */ - AUElement * SafeGetElement( AudioUnitScope inScope, - AudioUnitElement inElement) - { - return GetScope(inScope).SafeGetElement(inElement); - } - - /*! @method GetInput */ - AUInputElement * GetInput( AudioUnitElement inElement) - { - return static_cast(Inputs().SafeGetElement(inElement)); - } - - /*! @method GetOutput */ - AUOutputElement * GetOutput( AudioUnitElement inElement) - { - return static_cast(Outputs().SafeGetElement(inElement)); - } - -#if !CA_BASIC_AU_FEATURES - /*! @method GetGroup */ - AUElement * GetGroup( AudioUnitElement inElement) - { - return Groups().SafeGetElement(inElement); - } -#endif - - /*! @method PullInput */ - OSStatus PullInput( UInt32 inBusNumber, - AudioUnitRenderActionFlags &ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inNumberFrames) - { - AUInputElement *input = GetInput(inBusNumber); // throws if error - return input->PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames); - } - - /*! @method GetMaxFramesPerSlice */ - UInt32 GetMaxFramesPerSlice() const { return mMaxFramesPerSlice; } - /*! @method UsesFixedBlockSize */ - bool UsesFixedBlockSize() const { return mUsesFixedBlockSize; } - /*! @method SetUsesFixedBlockSize */ - void SetUsesFixedBlockSize(bool inUsesFixedBlockSize) { mUsesFixedBlockSize = inUsesFixedBlockSize; } - - /*! @method GetVectorUnitType */ - static SInt32 GetVectorUnitType() { return sVectorUnitType; } - /*! @method HasVectorUnit */ - static bool HasVectorUnit() { return sVectorUnitType > 0; } - /*! @method HasAltivec */ - static bool HasAltivec() { return sVectorUnitType == kVecAltivec; } - /*! @method HasSSE2 */ - static bool HasSSE2() { return sVectorUnitType >= kVecSSE2; } - /*! @method HasSSE3 */ - static bool HasSSE3() { return sVectorUnitType >= kVecSSE3; } - - /*! @method AudioUnitAPIVersion */ - UInt8 AudioUnitAPIVersion() const { return mAudioUnitAPIVersion; } - - /*! @method IsRenderThread */ - bool InRenderThread () const - { -#if TARGET_OS_MAC - return (mRenderThreadID ? pthread_equal (mRenderThreadID, pthread_self()) : false); -#elif TARGET_OS_WIN32 - return (mRenderThreadID ? mRenderThreadID == GetCurrentThreadId() : false); -#endif - } - - /*! @method HasInput */ - bool HasInput( AudioUnitElement inElement) { - AUInputElement *in = static_cast(Inputs().GetElement(inElement)); - return in != NULL && in->IsActive(); - } - // says whether an input is connected or has a callback - - /*! @method PropertyChanged */ - virtual void PropertyChanged( AudioUnitPropertyID inID, - AudioUnitScope inScope, - AudioUnitElement inElement); - -#if !CA_NO_AU_UI_FEATURES - // These calls can be used to call a Host's Callbacks. The method returns -1 if the host - // hasn't supplied the callback. Any other result is returned by the host. - // As in the API contract, for a parameter's value, you specify a pointer - // to that data type. Specify NULL for a parameter that you are not interested - // as this can save work in the host. - - /*! @method CallHostBeatAndTempo */ - OSStatus CallHostBeatAndTempo (Float64 *outCurrentBeat, - Float64 *outCurrentTempo) - { - return (mHostCallbackInfo.beatAndTempoProc - ? (*mHostCallbackInfo.beatAndTempoProc) (mHostCallbackInfo.hostUserData, - outCurrentBeat, - outCurrentTempo) - : -1); - } - - /*! @method CallHostMusicalTimeLocation */ - OSStatus CallHostMusicalTimeLocation (UInt32 *outDeltaSampleOffsetToNextBeat, - Float32 *outTimeSig_Numerator, - UInt32 *outTimeSig_Denominator, - Float64 *outCurrentMeasureDownBeat) - { - return (mHostCallbackInfo.musicalTimeLocationProc - ? (*mHostCallbackInfo.musicalTimeLocationProc) (mHostCallbackInfo.hostUserData, - outDeltaSampleOffsetToNextBeat, - outTimeSig_Numerator, - outTimeSig_Denominator, - outCurrentMeasureDownBeat) - : -1); - } - - /*! @method CallHostTransportState */ - OSStatus CallHostTransportState (Boolean *outIsPlaying, - Boolean *outTransportStateChanged, - Float64 *outCurrentSampleInTimeLine, - Boolean *outIsCycling, - Float64 *outCycleStartBeat, - Float64 *outCycleEndBeat) - { - return (mHostCallbackInfo.transportStateProc - ? (*mHostCallbackInfo.transportStateProc) (mHostCallbackInfo.hostUserData, - outIsPlaying, - outTransportStateChanged, - outCurrentSampleInTimeLine, - outIsCycling, - outCycleStartBeat, - outCycleEndBeat) - : -1); - } -#endif - - char* GetLoggingString () const; - - CAMutex* GetMutex() { return mAUMutex; } - - // ________________________________________________________________________ - /*! @method CreateElement */ - virtual AUElement * CreateElement( AudioUnitScope scope, - AudioUnitElement element); - -#pragma mark - -#pragma mark AU Output Base Dispatch - // ________________________________________________________________________ - // ________________________________________________________________________ - // ________________________________________________________________________ - // output unit methods - /*! @method Start */ - virtual OSStatus Start() { return kAudio_UnimplementedError; } - /*! @method Stop */ - virtual OSStatus Stop() { return kAudio_UnimplementedError; } - -#if !CA_BASIC_AU_FEATURES -#pragma mark - -#pragma mark AU Music Base Dispatch - -#if !TARGET_OS_IPHONE -// these methods are deprecated, so we don't include them except for compatability - /*! @method PrepareInstrument */ - virtual OSStatus PrepareInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; } - - /*! @method PrepareInstrument */ - virtual OSStatus ReleaseInstrument(MusicDeviceInstrumentID inInstrument) { return kAudio_UnimplementedError; } -#endif - - // ________________________________________________________________________ - // ________________________________________________________________________ - // ________________________________________________________________________ - // music device/music effect methods -- incomplete - /*! @method MIDIEvent */ - virtual OSStatus MIDIEvent( UInt32 inStatus, - UInt32 inData1, - UInt32 inData2, - UInt32 inOffsetSampleFrame) { return kAudio_UnimplementedError; } - - /*! @method SysEx */ - virtual OSStatus SysEx( const UInt8 * inData, - UInt32 inLength) { return kAudio_UnimplementedError;} - - /*! @method StartNote */ - virtual OSStatus StartNote( MusicDeviceInstrumentID inInstrument, - MusicDeviceGroupID inGroupID, - NoteInstanceID * outNoteInstanceID, - UInt32 inOffsetSampleFrame, - const MusicDeviceNoteParams &inParams) { return kAudio_UnimplementedError; } - - /*! @method StopNote */ - virtual OSStatus StopNote( MusicDeviceGroupID inGroupID, - NoteInstanceID inNoteInstanceID, - UInt32 inOffsetSampleFrame) { return kAudio_UnimplementedError; } -#endif - - // ________________________________________________________________________ - // ________________________________________________________________________ - // ________________________________________________________________________ - -protected: -#pragma mark - -#pragma mark Implementation methods - - /*! @method ReallocateBuffers */ - virtual void ReallocateBuffers(); - // needs to be called when mMaxFramesPerSlice changes - virtual void DeallocateIOBuffers(); - - /*! @method FillInParameterName */ - static void FillInParameterName (AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease) - { - ioInfo.cfNameString = inName; - ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString; - if (inShouldRelease) - ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease; - CFStringGetCString (inName, ioInfo.name, offsetof (AudioUnitParameterInfo, clumpID), kCFStringEncodingUTF8); - } - - static void HasClump (AudioUnitParameterInfo& ioInfo, UInt32 inClumpID) - { - ioInfo.clumpID = inClumpID; - ioInfo.flags |= kAudioUnitParameterFlag_HasClump; - } - - /*! @method SetMaxFramesPerSlice */ - virtual void SetMaxFramesPerSlice(UInt32 nFrames); - - /*! @method CanSetMaxFrames */ - virtual OSStatus CanSetMaxFrames() const; - - /*! @method WantsRenderThreadID */ - bool WantsRenderThreadID () const { return mWantsRenderThreadID; } - - /*! @method SetWantsRenderThreadID */ - void SetWantsRenderThreadID (bool inFlag); - - /*! @method SetRenderError */ - OSStatus SetRenderError (OSStatus inErr) - { - if (inErr && mLastRenderError == 0) { - mLastRenderError = inErr; - PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0); - } - return inErr; - } - -private: - /*! @method DoRenderBus */ - // shared between Render and RenderSlice, inlined to minimize function call overhead - OSStatus DoRenderBus( AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - UInt32 inBusNumber, - AUOutputElement * theOutput, - UInt32 inNumberFrames, - AudioBufferList & ioData) - { - if (theOutput != NULL) - { - if (ioData.mBuffers[0].mData == NULL || (theOutput->WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1)) - // will render into cache buffer - theOutput->PrepareBuffer(inNumberFrames); - else - // will render into caller's buffer - theOutput->SetBufferList(ioData); - } - - OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames); - if (result == noErr && theOutput != NULL) { - if (ioData.mBuffers[0].mData == NULL) { - theOutput->CopyBufferListTo(ioData); - AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, 0, *(UInt32 *)ioData.mBuffers[0].mData); - } else { - theOutput->CopyBufferContentsTo(ioData); - AUTRACE(kCATrace_AUBaseDoRenderBus, mComponentInstance, inNumberFrames, (intptr_t)theOutput->GetBufferList().mBuffers[0].mData, (intptr_t)ioData.mBuffers[0].mData, *(UInt32 *)ioData.mBuffers[0].mData); - theOutput->InvalidateBufferList(); - } - } - return result; - } - - /*! @method HasIcon */ - bool HasIcon (); - - /*! @method ResetRenderTime */ - void ResetRenderTime () - { - memset (&mCurrentRenderTime, 0, sizeof(mCurrentRenderTime)); - mCurrentRenderTime.mSampleTime = kNoLastRenderedSampleTime; - } - -protected: - /*! @method GetAudioChannelLayout */ - virtual UInt32 GetChannelLayoutTags( AudioUnitScope scope, - AudioUnitElement element, - AudioChannelLayoutTag * outLayoutTags); - - /*! @method GetAudioChannelLayout */ - virtual UInt32 GetAudioChannelLayout( AudioUnitScope scope, - AudioUnitElement element, - AudioChannelLayout * outLayoutPtr, - Boolean & outWritable); - - /*! @method SetAudioChannelLayout */ - virtual OSStatus SetAudioChannelLayout( AudioUnitScope scope, - AudioUnitElement element, - const AudioChannelLayout * inLayout); - - /*! @method RemoveAudioChannelLayout */ - virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element); - - /*! @method NeedsToRender */ - bool NeedsToRender( const AudioTimeStamp & inTimeStamp) - { - bool needsToRender = fnotequal(inTimeStamp.mSampleTime, mCurrentRenderTime.mSampleTime); - if (needsToRender) // only copy this if we need to render - mCurrentRenderTime = inTimeStamp; - return needsToRender; - } - - // Scheduled parameter implementation: - - typedef std::vector ParameterEventList; - - // Usually, you won't override this method. You only need to call this if your DSP code - // is prepared to handle scheduled immediate and ramped parameter changes. - // Before calling this method, it is assumed you have already called PullInput() on the input busses - // for which the DSP code depends. ProcessForScheduledParams() will call (potentially repeatedly) - // virtual method ProcessScheduledSlice() to perform the actual DSP for a given sub-division of - // the buffer. The job of ProcessForScheduledParams() is to sub-divide the buffer into smaller - // pieces according to the scheduled times found in the ParameterEventList (usually coming - // directly from a previous call to ScheduleParameter() ), setting the appropriate immediate or - // ramped parameter values for the corresponding scopes and elements, then calling ProcessScheduledSlice() - // to do the actual DSP for each of these divisions. - virtual OSStatus ProcessForScheduledParams( ParameterEventList &inParamList, - UInt32 inFramesToProcess, - void *inUserData ); - - // This method is called (potentially repeatedly) by ProcessForScheduledParams() - // in order to perform the actual DSP required for this portion of the entire buffer - // being processed. The entire buffer can be divided up into smaller "slices" - // according to the timestamps on the scheduled parameters... - // - // sub-classes wishing to handle scheduled parameter changes should override this method - // in order to do the appropriate DSP. AUEffectBase already overrides this for standard - // effect AudioUnits. - virtual OSStatus ProcessScheduledSlice( void *inUserData, - UInt32 inStartFrameInBuffer, - UInt32 inSliceFramesToProcess, - UInt32 inTotalBufferFrames ) {return noErr;}; // default impl does nothing... - - - /*! @method CurrentRenderTime */ - const AudioTimeStamp & CurrentRenderTime () const { return mCurrentRenderTime; } - - // ________________________________________________________________________ - // Private data members to discourage hacking in subclasses -private: - struct RenderCallback { - RenderCallback(AURenderCallback proc, void *ref) : - mRenderNotify(proc), - mRenderNotifyRefCon(ref) - { } - - AURenderCallback mRenderNotify; - void * mRenderNotifyRefCon; - - bool operator == (const RenderCallback &other) { - return this->mRenderNotify == other.mRenderNotify && - this->mRenderNotifyRefCon == other.mRenderNotifyRefCon; - } - }; - typedef TThreadSafeList RenderCallbackList; - -#if !CA_BASIC_AU_FEATURES - enum { kNumScopes = 4 }; -#else - enum { kNumScopes = 3 }; -#endif - - /*! @var mElementsCreated */ - bool mElementsCreated; -protected: - /*! @var mInitialized */ - bool mInitialized; - /*! @var mHasBegunInitializing */ - bool mHasBegunInitializing; -private: - /*! @var mAudioUnitAPIVersion */ - UInt8 mAudioUnitAPIVersion; - - /*! @var mInitNumInputEls */ - const UInt32 mInitNumInputEls; - /*! @var mInitNumOutputEls */ - const UInt32 mInitNumOutputEls; -#if !CA_BASIC_AU_FEATURES - /*! @var mInitNumGroupEls */ - const UInt32 mInitNumGroupEls; -#endif - /*! @var mScopes */ - AUScope mScopes[kNumScopes]; - - /*! @var mRenderCallbacks */ - RenderCallbackList mRenderCallbacks; - bool mRenderCallbacksTouched; - - /*! @var mRenderThreadID */ -#if TARGET_OS_MAC - pthread_t mRenderThreadID; -#elif TARGET_OS_WIN32 - UInt32 mRenderThreadID; -#endif - - /*! @var mWantsRenderThreadID */ - bool mWantsRenderThreadID; - - /*! @var mCurrentRenderTime */ - AudioTimeStamp mCurrentRenderTime; - - /*! @var mMaxFramesPerSlice */ - UInt32 mMaxFramesPerSlice; - - /*! @var mLastRenderError */ - OSStatus mLastRenderError; - /*! @var mCurrentPreset */ - AUPreset mCurrentPreset; - -protected: - /*! @var mUsesFixedBlockSize */ - bool mUsesFixedBlockSize; - - struct PropertyListener { - AudioUnitPropertyID propertyID; - AudioUnitPropertyListenerProc listenerProc; - void * listenerRefCon; - }; - typedef std::vector PropertyListeners; - - /*! @var mParamList */ - ParameterEventList mParamList; - /*! @var mPropertyListeners */ - PropertyListeners mPropertyListeners; - - /*! @var mBuffersAllocated */ - bool mBuffersAllocated; - - /*! @var mLogString */ - // if this is NOT null, it will contain identifying info about this AU. - char* mLogString; - - /*! @var mNickName */ - CFStringRef mNickName; - - /*! @var mAUMutex */ - CAMutex * mAUMutex; - -private: - /*! @var sVectorUnitType */ - static SInt32 sVectorUnitType; - -#if !CA_NO_AU_HOST_CALLBACKS -protected: - /*! @var mHostCallbackInfo */ - HostCallbackInfo mHostCallbackInfo; - -#endif -#if !CA_NO_AU_UI_FEATURES -protected: - /*! @var mContextInfo */ - CFStringRef mContextName; -#endif -}; - -inline OSStatus AUInputElement::PullInputWithBufferList( - AudioUnitRenderActionFlags & ioActionFlags, - const AudioTimeStamp & inTimeStamp, - AudioUnitElement inElement, - UInt32 nFrames, - AudioBufferList * inBufferList) -{ - OSStatus theResult; - - if (HasConnection()) { - // only support connections for V2 audio units -#if !CA_USE_AUDIO_PLUGIN_ONLY - if (mConnRenderProc != NULL) - theResult = reinterpret_cast(mConnRenderProc)( - mConnInstanceStorage, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList); - else -#endif - theResult = AudioUnitRender( - mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp, mConnection.sourceOutputNumber, nFrames, inBufferList); - } else { - // kFromCallback: - theResult = (mInputProc)( - mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames, inBufferList); - } - - if (mInputType == kNoInput) // defense: the guy upstream could have disconnected - // it's a horrible thing to do, but may happen! - return kAudioUnitErr_NoConnection; - - - return theResult; -} - -#endif // __AUBase_h__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBaseHelper.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBaseHelper.h deleted file mode 100644 index 03f750faa2..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBaseHelper.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - 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 - #include -#else - #include - #include -#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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.cpp deleted file mode 100644 index 2221bcab64..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - 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 - -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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.h deleted file mode 100644 index 875ab611fb..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - 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 -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#endif - -#include -#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(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 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.cpp deleted file mode 100644 index 5543468062..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - 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; -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.h deleted file mode 100644 index a07bd032ff..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - 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 -#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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.cpp deleted file mode 100644 index 5e5ba792fe..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - 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); -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.h deleted file mode 100644 index 4a3060c9f3..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputFormatConverter.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputFormatConverter.h deleted file mode 100644 index 91c1b8cc5b..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputFormatConverter.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.cpp deleted file mode 100644 index 1aeb7ad62d..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/* - 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 -#include "CAXException.h" - -//temporary 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(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(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(startFrame)); - // note that we're generating a bogus channel number for system messages (0xF0-FF) - } - event = NextMIDIEvent(event, packetEnd); - } - pkt = reinterpret_cast(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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.h deleted file mode 100644 index 116b18cf13..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.cpp deleted file mode 100644 index 4ee9bb7a7a..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - 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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.h deleted file mode 100644 index 685c9bce08..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.cpp deleted file mode 100644 index a062f5f05d..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - 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 "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; -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.h deleted file mode 100644 index 99b7a11a4f..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.cpp deleted file mode 100644 index 3575a64593..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.cpp +++ /dev/null @@ -1,668 +0,0 @@ -/* - 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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.h deleted file mode 100644 index 54e748e3a8..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - 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 - #if !CA_BASIC_AU_FEATURES - #include - #endif -#else - #include "AudioComponent.h" - #include "MusicDevice.h" -#endif - -#include "ComponentBase.h" - -struct AUBaseLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUBaseFactory : public APFactory -{ -}; - -struct AUOutputLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUOutputBaseFactory : public APFactory -{ -}; - -struct AUComplexOutputLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUOutputComplexBaseFactory : public APFactory -{ -}; - -struct AUBaseProcessLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUBaseProcessFactory : public APFactory -{ -}; - -struct AUBaseProcessMultipleLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUBaseProcessMultipleFactory : public APFactory -{ -}; - -struct AUBaseProcessAndMultipleLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUBaseProcessAndMultipleFactory : public APFactory -{ -}; - -#if !CA_BASIC_AU_FEATURES -struct AUMIDILookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUMIDIEffectFactory : public APFactory -{ -}; - -struct AUMIDIProcessLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUMIDIProcessFactory : public APFactory -{ -}; - -struct AUMusicLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUMusicDeviceFactory : public APFactory -{ -}; - -struct AUAuxBaseLookup { - static AudioComponentMethod Lookup (SInt16 selector); -}; -template -class AUAuxBaseFactory : public APFactory -{ -}; -#endif // CA_BASIC_AU_FEATURES - -#endif // __AUPlugInBase_h__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.cpp deleted file mode 100644 index 646b74e8f8..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - 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 "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(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(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(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(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(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(CFDictionaryGetCount(inNameDict)); - CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef)); - CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast(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(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; -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.h deleted file mode 100644 index 403d0b6297..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.h +++ /dev/null @@ -1,553 +0,0 @@ -/* - 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 -#include - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#else - #include -#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(mIndexedParameters.size()); else return static_cast(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> ParameterMap; - -/*! @var mAudioUnit */ - AUBase * mAudioUnit; -/*! @var mParameters */ - ParameterMap mParameters; - -/*! @var mUseIndexedParameters */ - bool mUseIndexedParameters; -/*! @var mIndexedParameters */ - std::vector 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(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; - else - return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); - } - Float32 * GetFloat32ChannelData(int ch) const { - if (mStreamFormat.IsInterleaved()) - return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; - else - return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); - } - SInt32 * GetSInt32ChannelData(int ch) const { - if (mStreamFormat.IsInterleaved()) - return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; - else - return static_cast(mIOBuffer.GetBufferList().mBuffers[ch].mData); - } - SInt16 * GetInt16ChannelData(int ch) const { - if (mStreamFormat.IsInterleaved()) - return static_cast(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; - else - return static_cast(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(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 ElementVector; -/*! @var mCreator */ - AUBase * mCreator; -/*! @var mScope */ - AudioUnitScope mScope; -/*! @var mElements */ - ElementVector mElements; -/*! @var mDelegate */ - AUScopeDelegate * mDelegate; -}; - - - -#endif // __AUScopeElement_h__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUSilentTimeout.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUSilentTimeout.h deleted file mode 100644 index 7e5a65eed6..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUSilentTimeout.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - 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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUTimestampGenerator.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUTimestampGenerator.h deleted file mode 100644 index 6e27f74b74..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUTimestampGenerator.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - 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 -#include "CAHostTimeBase.h" -#include - -#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 - // 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUViewLocalizedStringKeys.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUViewLocalizedStringKeys.h deleted file mode 100644 index 7f40021333..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUViewLocalizedStringKeys.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.cpp deleted file mode 100644 index 0b004867f2..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* - 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 "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(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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.h deleted file mode 100644 index f51b392403..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - 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 - -// ____________________________________________________________________________ -// 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomic.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomic.h deleted file mode 100644 index 5f9a16a90f..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomic.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - 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 - #include - #pragma intrinsic(_InterlockedOr) - #pragma intrinsic(_InterlockedAnd) -#else - #include - #include -#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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomicStack.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomicStack.h deleted file mode 100644 index 6ee083bf0d..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomicStack.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - 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 -#else - #include -#endif - -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4 - #include -#endif - -// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically -// class T must implement T *& next(). -template -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. - // 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 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 - -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 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp deleted file mode 100644 index 8171e09542..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - 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 -#include - -//============================================================================= -// CAAudioChannelLayout -//============================================================================= - -AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions) -{ - UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions); - AudioChannelLayout* theAnswer = static_cast(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]); - } - } -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.h deleted file mode 100644 index acc5e2b4ff..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - 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 - #include -#else - #include - #include -#endif -#include -#include -#include - -#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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAutoDisposer.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAutoDisposer.h deleted file mode 100644 index bb8faf2ced..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAutoDisposer.h +++ /dev/null @@ -1,508 +0,0 @@ -/* - 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 // for malloc -#include // for bad_alloc -#include // 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 -struct CAPtrRef -{ - T* ptr_; - - explicit CAPtrRef(T* ptr) : ptr_(ptr) {} -}; - -template -class CAAutoFree -{ -private: - T* ptr_; - -public: - - CAAutoFree() : ptr_(0) {} - - explicit CAAutoFree(T* ptr) : ptr_(ptr) {} - - template - CAAutoFree(CAAutoFree& that) : ptr_(that.release()) {} // take ownership - - // C++ std says: a template constructor is never a copy constructor - CAAutoFree(CAAutoFree& 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(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(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T))); - } - - void allocBytes(size_t numBytes, bool clear = false) - { - free(); - ptr_ = static_cast(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes)); - } - - void reallocBytes(size_t numBytes) - { - ptr_ = static_cast(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(CA_realloc(ptr_, numItems * sizeof(T))); - } - - template - CAAutoFree& operator=(CAAutoFree& 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 - 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 ref) : ptr_(ref.ptr_) { } - - CAAutoFree& operator=(CAPtrRef ref) - { - set(ref.ptr_); - return *this; - } - - template - operator CAPtrRef() - { return CAPtrRef(release()); } - - template - operator CAAutoFree() - { return CAAutoFree(release()); } - -}; - - -template -class CAAutoDelete -{ -private: - T* ptr_; - -public: - CAAutoDelete() : ptr_(0) {} - - explicit CAAutoDelete(T* ptr) : ptr_(ptr) {} - - template - CAAutoDelete(CAAutoDelete& that) : ptr_(that.release()) {} // take ownership - - // C++ std says: a template constructor is never a copy constructor - CAAutoDelete(CAAutoDelete& that) : ptr_(that.release()) {} // take ownership - - ~CAAutoDelete() { free(); } - - template - CAAutoDelete& operator=(CAAutoDelete& 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 - 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 ref) : ptr_(ref.ptr_) { } - - CAAutoDelete& operator=(CAPtrRef ref) - { - set(ref.ptr_); - return *this; - } - - template - operator CAPtrRef() - { return CAPtrRef(release()); } - - template - operator CAAutoFree() - { return CAAutoFree(release()); } - -}; - - -template -class CAAutoArrayDelete -{ -private: - T* ptr_; - -public: - CAAutoArrayDelete() : ptr_(0) {} - - explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {} - - template - CAAutoArrayDelete(CAAutoArrayDelete& that) : ptr_(that.release()) {} // take ownership - - // C++ std says: a template constructor is never a copy constructor - CAAutoArrayDelete(CAAutoArrayDelete& 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 - CAAutoArrayDelete& operator=(CAAutoArrayDelete& 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 - 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 ref) : ptr_(ref.ptr_) { } - - CAAutoArrayDelete& operator=(CAPtrRef ref) - { - set(ref.ptr_); - return *this; - } - - template - operator CAPtrRef() - { return CAPtrRef(release()); } - - template - operator CAAutoArrayDelete() - { return CAAutoFree(release()); } - -}; - - - - - -// convenience function -template -void free(CAAutoFree& p) -{ - p.free(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////// - -#if 0 -// example program showing ownership transfer - -CAAutoFree source() -{ - // source allocates and returns ownership to the caller. - const char* str = "this is a test"; - size_t size = strlen(str) + 1; - CAAutoFree captr(size, false); - strlcpy(captr(), str, size); - printf("source %08X %08X '%s'\n", &captr, captr(), captr()); - return captr; -} - -void user(CAAutoFree 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 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 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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugMacros.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugMacros.h deleted file mode 100644 index 28a3f5ebda..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugMacros.h +++ /dev/null @@ -1,583 +0,0 @@ -/* - 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" - -//============================================================================= -// Includes -//============================================================================= - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#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 - #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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugPrintf.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugPrintf.h deleted file mode 100644 index 37bad12054..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugPrintf.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - 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 -#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 - #define DebugPrintfRtn syslog - #define DebugPrintfFile LOG_NOTICE - #define DebugPrintfLineEnding "" - #define DebugPrintfFileComma DebugPrintfFile, - #elif defined(CoreAudio_UseSideFile) - #include - #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 - #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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAException.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAException.h deleted file mode 100644 index 1c207f191a..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAException.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - 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 -#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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAHostTimeBase.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAHostTimeBase.h deleted file mode 100644 index 5098308011..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAHostTimeBase.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - 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 -#else - #include -#endif - -#if TARGET_OS_MAC - #include - #include -#elif TARGET_OS_WIN32 - #include - #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(inEndTime - inStartTime); - } - else - { - theAnswer = static_cast(inStartTime - inEndTime); - theSign = -1; - } - - return theSign * static_cast(ConvertToNanos(static_cast(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(theAnswer); -} - -#endif diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMath.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMath.h deleted file mode 100644 index d291d1f8bd..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMath.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - 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 -#else - #include -#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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.cpp deleted file mode 100644 index e3d3b83adf..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - 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 -#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(); - } -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.h deleted file mode 100644 index ea3681338f..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - 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 -#else - #include -#endif - -#if TARGET_OS_MAC - #include -#elif TARGET_OS_WIN32 - #include -#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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAReferenceCounted.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAReferenceCounted.h deleted file mode 100644 index e16c3b4603..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAReferenceCounted.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp deleted file mode 100644 index dc1a579107..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp +++ /dev/null @@ -1,879 +0,0 @@ -/* - 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 -#else - #include -#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(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(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate); - return theBuffer; - } - } - - nc = snprintf(buf, static_cast(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(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(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(bufsize), "from %d-bit source, ", sourceBits); - else - nc = snprintf(buf, static_cast(bufsize), "from UNKNOWN source bit depth, "); - buf += nc; if ((bufsize -= nc) <= 0) goto exit; - /*nc =*/ snprintf(buf, static_cast(bufsize), "%d frames/packet", (int)mFramesPerPacket); - // buf += nc; if ((bufsize -= nc) <= 0) goto exit; - } - else - /*nc =*/ snprintf(buf, static_cast(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(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(kAudioFormatFlagIsAlignedHigh); - yFlags = yFlags & ~static_cast(kAudioFormatFlagIsAlignedHigh); - } - - // if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit. - if (xFlags & yFlags & kAudioFormatFlagIsFloat) { - xFlags = xFlags & ~static_cast(kAudioFormatFlagIsSignedInteger); - yFlags = yFlags & ~static_cast(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(kAudioFormatFlagIsBigEndian); - } - if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked)) - { - yFlags = yFlags & ~static_cast(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(kLinearPCMFormatFlagIsNonInterleaved); - yFlags &= ~static_cast(kLinearPCMFormatFlagIsNonInterleaved); - } - - if (converterOnly) { - CAStreamBasicDescription cas_x = CAStreamBasicDescription(x); - CAStreamBasicDescription cas_y = CAStreamBasicDescription(y); - if (!cas_x.PackednessIsSignificant() && !cas_y.PackednessIsSignificant()) { - xFlags &= ~static_cast(kAudioFormatFlagIsPacked); - yFlags &= ~static_cast(kAudioFormatFlagIsPacked); - } - if (!cas_x.AlignmentIsSignificant() && !cas_y.AlignmentIsSignificant()) { - xFlags &= ~static_cast(kAudioFormatFlagIsAlignedHigh); - yFlags &= ~static_cast(kAudioFormatFlagIsAlignedHigh); - } - // We don't care about whether the streams are mixable in this case - xFlags &= ~static_cast(kAudioFormatFlagIsNonMixable); - yFlags &= ~static_cast(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(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat; - ++p; - } else { - if (p[0] == 'U') { - pcmFlags &= ~static_cast(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(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(*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(*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(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(c - '0'); - else if (c >= 'A' && c <= 'F') - flags = (flags << 4) | static_cast(c - 'A' + 10); - else if (c >= 'a' && c <= 'f') - flags = (flags << 4) | static_cast(c - 'a' + 10); - else break; - } - fmt.mFormatFlags = flags; - } - if (*p == '#') { - ++p; - while (isdigit(*p)) - fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast(*p++ - '0'); - } - if (*p == ':') { - ++p; - fmt.mFormatFlags &= ~static_cast(kLinearPCMFormatFlagIsPacked); - if (*p == 'L') - fmt.mFormatFlags &= ~static_cast(kLinearPCMFormatFlagIsAlignedHigh); - else if (*p == 'H') - fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh; - else - goto Bail; - ++p; - UInt32 bytesPerFrame = 0; - while (isdigit(*p)) - bytesPerFrame = 10 * bytesPerFrame + static_cast(*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(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(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"; diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.h deleted file mode 100644 index d80dbfbf30..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - 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 - #include -#else - #include "CoreAudioTypes.h" - #include "CoreFoundation.h" -#endif - -#include "CADebugMacros.h" -#include // for memset, memcpy -#include // 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(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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAThreadSafeList.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAThreadSafeList.h deleted file mode 100644 index 479f519f61..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAThreadSafeList.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - 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 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 { - 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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.cpp deleted file mode 100644 index 9b651cd16b..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - 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 -#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; -} diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.h deleted file mode 100644 index 6693392a3d..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - 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 -#include "CAVectorUnitTypes.h" -#include -#include - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include -#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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnitTypes.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnitTypes.h deleted file mode 100644 index 5181f602ed..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnitTypes.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - 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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAXException.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAXException.h deleted file mode 100644 index 4027cb8822..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAXException.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - 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 -#else - #include - #include -#endif -#include "CADebugMacros.h" -#include -//#include -#include - - -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__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.cpp deleted file mode 100644 index 50a5438310..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* - 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 - -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 -#include -#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 - -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 diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.h deleted file mode 100644 index 6eb03214d5..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - 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 -#include "CADebugMacros.h" -#include "CAXException.h" - -#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__) - #include - #include - - #if !CA_USE_AUDIO_PLUGIN_ONLY - #include - - #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 - #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(throw_err); } while (0) - #else - #define COMPONENT_THROW(throw_err) \ - throw static_cast(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 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 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::Dispatch(params, obj); \ - } \ - extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \ - extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \ - return FactoryType::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::Dispatch(params, obj); \ - } - - /*! @class ComponentRegistrar */ -template -class ComponentRegistrar { -public: - /*! @ctor ComponentRegistrar */ - ComponentRegistrar() { ComponentEntryPoint::Register(Type, Subtype, Manufacturer); } -}; - -#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \ - static ComponentRegistrar 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::Factory(inDesc); \ - } - -#endif // !CA_USE_AUDIO_PLUGIN_ONLY - - -#endif // __ComponentBase_h__ diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp deleted file mode 100644 index 8acf8cadfb..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - 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(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(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(inComponentStorage); - if (This == NULL) return kAudio_ParamError; - result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame); - } - COMPONENT_CATCH - return result; -} - -#endif diff --git a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.h b/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.h deleted file mode 100644 index 475bab3f28..0000000000 --- a/modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - 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__ diff --git a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm index f769437035..ba363ce688 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm @@ -52,7 +52,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wshorten-64-to-32", #include #include #include -#include "CoreAudioUtilityClasses/MusicDeviceBase.h" +#include "AudioUnitSDK/MusicDeviceBase.h" JUCE_END_IGNORE_WARNINGS_GCC_LIKE @@ -73,6 +73,8 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE #endif #endif +#include + //============================================================================== using namespace juce; @@ -101,7 +103,7 @@ struct AudioProcessorHolder //============================================================================== class JuceAU : public AudioProcessorHolder, - public MusicDeviceBase, + public ausdk::MusicDeviceBase, public AudioProcessorListener, public AudioProcessorParameter::Listener { @@ -239,24 +241,6 @@ public: } } - //============================================================================== - static OSStatus ComponentEntryDispatch (ComponentParameters* params, JuceAU* effect) - { - if (effect == nullptr) - return paramErr; - - switch (params->what) - { - case kMusicDeviceMIDIEventSelect: - case kMusicDeviceSysExSelect: - return AUMIDIBase::ComponentEntryDispatch (params, effect); - default: - break; - } - - return MusicDeviceBase::ComponentEntryDispatch (params, effect); - } - //============================================================================== bool BusCountWritable (AudioUnitScope scope) override { @@ -380,7 +364,7 @@ public: AudioUnitScope inScope, AudioUnitElement inElement, UInt32& outDataSize, - Boolean& outWritable) override + bool& outWritable) override { if (inScope == kAudioUnitScope_Global) { @@ -813,8 +797,10 @@ public: #endif } - UInt32 GetAudioChannelLayout (AudioUnitScope scope, AudioUnitElement element, - AudioChannelLayout* outLayoutPtr, Boolean& outWritable) override + UInt32 GetAudioChannelLayout (AudioUnitScope scope, + AudioUnitElement element, + AudioChannelLayout* outLayoutPtr, + bool& outWritable) override { outWritable = false; @@ -839,22 +825,17 @@ public: return sizeInBytes; } - UInt32 GetChannelLayoutTags (AudioUnitScope scope, AudioUnitElement element, AudioChannelLayoutTag* outLayoutTags) override + std::vector GetChannelLayoutTags (AudioUnitScope inScope, AudioUnitElement inElement) override { - const auto info = getElementInfo (scope, element); + const auto info = getElementInfo (inScope, inElement); if (info.error != noErr) - return 0; + return {}; if (busIgnoresLayout (info.isInput, info.busNr)) - return 0; - - const Array& layouts = getSupportedBusLayouts (info.isInput, info.busNr); - - if (outLayoutTags != nullptr) - std::copy (layouts.begin(), layouts.end(), outLayoutTags); + return {}; - return (UInt32) layouts.size(); + return getSupportedBusLayouts (info.isInput, info.busNr); } OSStatus SetAudioChannelLayout (AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override @@ -870,34 +851,29 @@ public: if (inLayout == nullptr) return kAudioUnitErr_InvalidPropertyValue; - if (const AUIOElement* ioElement = GetIOElement (info.isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, element)) - { - const AudioChannelSet newChannelSet = CoreAudioLayouts::fromCoreAudio (*inLayout); - const int currentNumChannels = static_cast (ioElement->GetStreamFormat().NumberChannels()); - const int newChannelNum = newChannelSet.size(); + auto& ioElement = IOElement (info.isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, element); - if (currentNumChannels != newChannelNum) - return kAudioUnitErr_InvalidPropertyValue; + const AudioChannelSet newChannelSet = CoreAudioLayouts::fromCoreAudio (*inLayout); + const int currentNumChannels = static_cast (ioElement.NumberChannels()); + const int newChannelNum = newChannelSet.size(); - // check if the new layout could be potentially set - #ifdef JucePlugin_PreferredChannelConfigurations - short configs[][2] = {JucePlugin_PreferredChannelConfigurations}; + if (currentNumChannels != newChannelNum) + return kAudioUnitErr_InvalidPropertyValue; - if (! AudioUnitHelpers::isLayoutSupported (*juceFilter, info.isInput, info.busNr, newChannelNum, configs)) - return kAudioUnitErr_FormatNotSupported; - #else - if (! juceFilter->getBus (info.isInput, info.busNr)->isLayoutSupported (newChannelSet)) - return kAudioUnitErr_FormatNotSupported; - #endif + // check if the new layout could be potentially set + #ifdef JucePlugin_PreferredChannelConfigurations + short configs[][2] = {JucePlugin_PreferredChannelConfigurations}; - getCurrentLayout (info.isInput, info.busNr) = CoreAudioLayouts::toCoreAudio (newChannelSet); + if (! AudioUnitHelpers::isLayoutSupported (*juceFilter, info.isInput, info.busNr, newChannelNum, configs)) + return kAudioUnitErr_FormatNotSupported; + #else + if (! juceFilter->getBus (info.isInput, info.busNr)->isLayoutSupported (newChannelSet)) + return kAudioUnitErr_FormatNotSupported; + #endif - return noErr; - } - else - jassertfalse; + getCurrentLayout (info.isInput, info.busNr) = CoreAudioLayouts::toCoreAudio (newChannelSet); - return kAudioUnitErr_InvalidElement; + return noErr; } //============================================================================== @@ -1063,14 +1039,13 @@ public: bool CanScheduleParameters() const override { return false; } //============================================================================== - ComponentResult Version() override { return JucePlugin_VersionCode; } bool SupportsTail() override { return true; } Float64 GetTailTime() override { return juceFilter->getTailLengthSeconds(); } double getSampleRate() { if (AudioUnitHelpers::getBusCountForWrapper (*juceFilter, false) > 0) - return GetOutput (0)->GetStreamFormat().mSampleRate; + return Output (0).GetStreamFormat().mSampleRate; return 44100.0; } @@ -1236,14 +1211,16 @@ public: return ((! IsInitialized()) && (info.error == noErr)); } - bool ValidFormat (AudioUnitScope scope, AudioUnitElement element, const CAStreamBasicDescription& format) override + bool ValidFormat (AudioUnitScope inScope, + AudioUnitElement inElement, + const AudioStreamBasicDescription& inNewFormat) override { // DSP Quattro incorrectly uses global scope for the ValidFormat call - if (scope == kAudioUnitScope_Global) - return ValidFormat (kAudioUnitScope_Input, element, format) - || ValidFormat (kAudioUnitScope_Output, element, format); + if (inScope == kAudioUnitScope_Global) + return ValidFormat (kAudioUnitScope_Input, inElement, inNewFormat) + || ValidFormat (kAudioUnitScope_Output, inElement, inNewFormat); - const auto info = getElementInfo (scope, element); + const auto info = getElementInfo (inScope, inElement); if (info.error != noErr) return false; @@ -1251,15 +1228,15 @@ public: if (info.kind == BusKind::wrapperOnly) return true; - const int newNumChannels = static_cast (format.NumberChannels()); - const int oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr); + const auto newNumChannels = static_cast (inNewFormat.mChannelsPerFrame); + const auto oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr); if (newNumChannels == oldNumChannels) return true; if (AudioProcessor::Bus* bus = juceFilter->getBus (info.isInput, info.busNr)) { - if (! MusicDeviceBase::ValidFormat (scope, element, format)) + if (! MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat)) return false; #ifdef JucePlugin_PreferredChannelConfigurations @@ -1276,17 +1253,20 @@ public: } // AU requires us to override this for the sole reason that we need to find a default layout tag if the number of channels have changed - OSStatus ChangeStreamFormat (AudioUnitScope scope, AudioUnitElement element, const CAStreamBasicDescription& old, const CAStreamBasicDescription& format) override + OSStatus ChangeStreamFormat (AudioUnitScope inScope, + AudioUnitElement inElement, + const AudioStreamBasicDescription& inPrevFormat, + const AudioStreamBasicDescription& inNewFormat) override { - const auto info = getElementInfo (scope, element); + const auto info = getElementInfo (inScope, inElement); if (info.error != noErr) return info.error; AudioChannelLayoutTag& currentTag = getCurrentLayout (info.isInput, info.busNr); - const int newNumChannels = static_cast (format.NumberChannels()); - const int oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr); + const auto newNumChannels = static_cast (inNewFormat.mChannelsPerFrame); + const auto oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr); #ifdef JucePlugin_PreferredChannelConfigurations short configs[][2] = {JucePlugin_PreferredChannelConfigurations}; @@ -1310,7 +1290,7 @@ public: if (set == AudioChannelSet()) return kAudioUnitErr_FormatNotSupported; - const auto err = MusicDeviceBase::ChangeStreamFormat (scope, element, old, format); + const auto err = MusicDeviceBase::ChangeStreamFormat (inScope, inElement, inPrevFormat, inNewFormat); if (err == noErr) currentTag = CoreAudioLayouts::toCoreAudio (set); @@ -1375,7 +1355,7 @@ public: for (int busIdx = 0; busIdx < numInputBuses; ++busIdx) { if (pulledSucceeded[busIdx]) - audioBuffer.set (busIdx, GetInput ((UInt32) busIdx)->GetBufferList(), mapper.get (true, busIdx)); + audioBuffer.set (busIdx, Input ((UInt32) busIdx).GetBufferList(), mapper.get (true, busIdx)); else audioBuffer.clearInputBus (busIdx, (int) nFrames); } @@ -1396,7 +1376,7 @@ public: // copy back { for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx) - audioBuffer.get (busIdx, GetOutput ((UInt32) busIdx)->GetBufferList(), mapper.get (false, busIdx)); + audioBuffer.get (busIdx, Output ((UInt32) busIdx).GetBufferList(), mapper.get (false, busIdx)); } // process midi output @@ -1415,10 +1395,10 @@ public: ComponentResult StopNote (MusicDeviceGroupID, NoteInstanceID, UInt32) override { return noErr; } //============================================================================== - OSStatus HandleMidiEvent (UInt8 nStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame) override + OSStatus HandleMIDIEvent (UInt8 inStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame) override { #if JucePlugin_WantsMidiInput || JucePlugin_IsMidiEffect - const juce::uint8 data[] = { (juce::uint8) (nStatus | inChannel), + const juce::uint8 data[] = { (juce::uint8) (inStatus | inChannel), (juce::uint8) inData1, (juce::uint8) inData2 }; @@ -1426,7 +1406,7 @@ public: incomingEvents.addEvent (data, 3, (int) inStartFrame); return noErr; #else - ignoreUnused (nStatus, inChannel, inData1); + ignoreUnused (inStatus, inChannel, inData1); ignoreUnused (inData2, inStartFrame); return kAudioUnitErr_PropertyNotInUse; #endif @@ -1877,7 +1857,7 @@ private: //============================================================================== Array channelInfo; - Array> supportedInputLayouts, supportedOutputLayouts; + Array> supportedInputLayouts, supportedOutputLayouts; Array currentInputLayout, currentOutputLayout; //============================================================================== @@ -1923,15 +1903,14 @@ private: for (unsigned int i = 0; i < numInputBuses; ++i) { - if (AUInputElement* input = GetInput (i)) - { - const bool succeeded = (input->PullInput (flags, timestamp, i, nFrames) == noErr); + auto& input = Input (i); - if ((flags & kAudioUnitRenderAction_OutputIsSilence) != 0 && succeeded) - AudioUnitHelpers::clearAudioBuffer (input->GetBufferList()); + const bool succeeded = (input.PullInput (flags, timestamp, i, nFrames) == noErr); - pulledSucceeded[i] = succeeded; - } + if ((flags & kAudioUnitRenderAction_OutputIsSilence) != 0 && succeeded) + AudioUnitHelpers::clearAudioBuffer (input.GetBufferList()); + + pulledSucceeded[i] = succeeded; } } @@ -1942,13 +1921,13 @@ private: for (UInt32 busIdx = 0; busIdx < numWrapperBuses; ++busIdx) { - AUOutputElement* output = GetOutput (busIdx); + auto& output = Output (busIdx); - if (output->WillAllocateBuffer()) - output->PrepareBuffer (nFrames); + if (output.WillAllocateBuffer()) + output.PrepareBuffer (nFrames); if (busIdx >= (UInt32) numProcessorBuses) - AudioUnitHelpers::clearAudioBuffer (output->GetBufferList()); + AudioUnitHelpers::clearAudioBuffer (output.GetBufferList()); } } @@ -2026,7 +2005,7 @@ private: void GetAudioBufferList (bool isInput, int busIdx, AudioBufferList*& bufferList, bool& interleaved, int& numChannels) { - AUIOElement* element = GetElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, static_cast (busIdx))->AsIOElement(); + auto* element = Element (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, static_cast (busIdx)).AsIOElement(); jassert (element != nullptr); bufferList = &element->GetBufferList(); @@ -2124,7 +2103,7 @@ private: if (forceUseLegacyParamIDs) { - Globals()->UseIndexedParameters (numParams); + Globals()->UseIndexedParameters (static_cast (numParams)); } else { @@ -2261,8 +2240,8 @@ private: const int numInputBuses = AudioUnitHelpers::getBusCount (*juceFilter, true); const int numOutputBuses = AudioUnitHelpers::getBusCount (*juceFilter, false); - const int numInputElements = static_cast (GetScope(kAudioUnitScope_Input). GetNumberOfElements()); - const int numOutputElements = static_cast (GetScope(kAudioUnitScope_Output).GetNumberOfElements()); + const int numInputElements = static_cast (GetScope (kAudioUnitScope_Input). GetNumberOfElements()); + const int numOutputElements = static_cast (GetScope (kAudioUnitScope_Output).GetNumberOfElements()); AudioProcessor::BusesLayout requestedLayouts; for (int dir = 0; dir < 2; ++dir) @@ -2274,8 +2253,8 @@ private: for (int busIdx = 0; busIdx < n; ++busIdx) { - const AUIOElement* element = (busIdx < numAUElements ? GetIOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busIdx) : nullptr); - const int numChannels = (element != nullptr ? static_cast (element->GetStreamFormat().NumberChannels()) : 0); + const auto* element = (busIdx < numAUElements ? &IOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busIdx) : nullptr); + const int numChannels = (element != nullptr ? static_cast (element->NumberChannels()) : 0); AudioChannelLayoutTag currentLayoutTag = isInput ? currentInputLayout[busIdx] : currentOutputLayout[busIdx]; const int tagNumChannels = currentLayoutTag & 0xffff; @@ -2314,20 +2293,12 @@ private: if (numChannels == 0) return noErr; - if (AUIOElement* element = GetIOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busNr)) - { - element->SetName ((CFStringRef) juceStringToNS (juceFilter->getBus (isInput, busNr)->getName())); - - CAStreamBasicDescription streamDescription; - streamDescription.mSampleRate = getSampleRate(); + auto& element = IOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busNr); - streamDescription.SetCanonical ((UInt32) numChannels, false); - return element->SetStreamFormat (streamDescription); - } - else - jassertfalse; + element.SetName ((CFStringRef) juceStringToNS (juceFilter->getBus (isInput, busNr)->getName())); - return kAudioUnitErr_InvalidElement; + const auto streamDescription = ausdk::ASBD::CreateCommonFloat32 (getSampleRate(), (UInt32) numChannels); + return element.SetStreamFormat (streamDescription); } //============================================================================== @@ -2355,14 +2326,16 @@ private: } //============================================================================== - Array& getSupportedBusLayouts (bool isInput, int bus) noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); } - const Array& getSupportedBusLayouts (bool isInput, int bus) const noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); } + std::vector& getSupportedBusLayouts (bool isInput, int bus) noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); } + const std::vector& getSupportedBusLayouts (bool isInput, int bus) const noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); } AudioChannelLayoutTag& getCurrentLayout (bool isInput, int bus) noexcept { return (isInput ? currentInputLayout : currentOutputLayout).getReference (bus); } AudioChannelLayoutTag getCurrentLayout (bool isInput, int bus) const noexcept { return (isInput ? currentInputLayout : currentOutputLayout)[bus]; } //============================================================================== - void addSupportedLayoutTagsForBus (bool isInput, int busNum, Array& tags) + std::vector getSupportedLayoutTagsForBus (bool isInput, int busNum) const { + std::set tags; + if (AudioProcessor::Bus* bus = juceFilter->getBus (isInput, busNum)) { #ifndef JucePlugin_PreferredChannelConfigurations @@ -2370,7 +2343,7 @@ private: for (auto tag : knownTags) if (bus->isLayoutSupported (CoreAudioLayouts::fromCoreAudio (tag))) - tags.addIfNotAlreadyThere (tag); + tags.insert (tag); #endif // add discrete layout tags @@ -2384,10 +2357,12 @@ private: tags.addIfNotAlreadyThere (static_cast ((int) kAudioChannelLayoutTag_DiscreteInOrder | ch)); #else if (bus->isLayoutSupported (AudioChannelSet::discreteChannels (ch))) - tags.addIfNotAlreadyThere (static_cast ((int) kAudioChannelLayoutTag_DiscreteInOrder | ch)); + tags.insert (static_cast ((int) kAudioChannelLayoutTag_DiscreteInOrder | ch)); #endif } } + + return std::vector (tags.begin(), tags.end()); } void addSupportedLayoutTagsForDirection (bool isInput) @@ -2397,12 +2372,7 @@ private: auto numBuses = AudioUnitHelpers::getBusCount (*juceFilter, isInput); for (int busNr = 0; busNr < numBuses; ++busNr) - { - Array busLayouts; - addSupportedLayoutTagsForBus (isInput, busNr, busLayouts); - - layouts.add (busLayouts); - } + layouts.add (getSupportedLayoutTagsForBus (isInput, busNr)); } void addSupportedLayoutTags() @@ -2425,10 +2395,10 @@ private: void auPropertyListener (AudioUnitPropertyID propId, AudioUnitScope scope, AudioUnitElement) { if (scope == kAudioUnitScope_Global && propId == kAudioUnitProperty_ContextName - && juceFilter != nullptr && mContextName != nullptr) + && juceFilter != nullptr && GetContextName() != nullptr) { AudioProcessor::TrackProperties props; - props.name = String::fromCFString (mContextName); + props.name = String::fromCFString (GetContextName()); juceFilter->updateTrackProperties (props); } @@ -2444,48 +2414,17 @@ private: }; //============================================================================== -#define JUCE_COMPONENT_ENTRYX(Class, Name, Suffix) \ - extern "C" __attribute__((visibility("default"))) ComponentResult Name ## Suffix (ComponentParameters* params, Class* obj); \ - extern "C" __attribute__((visibility("default"))) ComponentResult Name ## Suffix (ComponentParameters* params, Class* obj) \ - { \ - PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnit; \ - return ComponentEntryPoint::Dispatch (params, obj); \ - } - #if JucePlugin_ProducesMidiOutput || JucePlugin_WantsMidiInput || JucePlugin_IsMidiEffect - #define FACTORY_BASE_CLASS AUMIDIEffectFactory + #define FACTORY_BASE_CLASS ausdk::AUMusicDeviceFactory #else - #define FACTORY_BASE_CLASS AUBaseFactory -#endif - -#define JUCE_FACTORY_ENTRYX(Class, Name) \ - extern "C" __attribute__((visibility("default"))) void* Name ## Factory (const AudioComponentDescription* desc); \ - extern "C" __attribute__((visibility("default"))) void* Name ## Factory (const AudioComponentDescription* desc) \ - { \ - PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnit; \ - return FACTORY_BASE_CLASS::Factory (desc); \ - } - -#define JUCE_COMPONENT_ENTRY(Class, Name, Suffix) JUCE_COMPONENT_ENTRYX(Class, Name, Suffix) -#define JUCE_FACTORY_ENTRY(Class, Name) JUCE_FACTORY_ENTRYX(Class, Name) - -//============================================================================== -JUCE_COMPONENT_ENTRY (JuceAU, JucePlugin_AUExportPrefix, Entry) - -#ifndef AUDIOCOMPONENT_ENTRY - #define JUCE_DISABLE_AU_FACTORY_ENTRY 1 -#endif - -#if ! JUCE_DISABLE_AU_FACTORY_ENTRY // (You might need to disable this for old Xcode 3 builds) -JUCE_FACTORY_ENTRY (JuceAU, JucePlugin_AUExportPrefix) + #define FACTORY_BASE_CLASS ausdk::AUBaseFactory #endif -#if ! JUCE_DISABLE_AU_FACTORY_ENTRY - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align", "-Wzero-as-null-pointer-constant") +AUSDK_COMPONENT_ENTRY (FACTORY_BASE_CLASS, JuceAU) - #include "CoreAudioUtilityClasses/AUPlugInDispatch.cpp" +#define JUCE_AU_ENTRY_POINT_NAME JUCE_CONCAT (JucePlugin_AUExportPrefix, Factory) - JUCE_END_IGNORE_WARNINGS_GCC_LIKE -#endif + extern "C" void* JUCE_AU_ENTRY_POINT_NAME (const AudioComponentDescription* inDesc); +AUSDK_EXPORT extern "C" void* JUCE_AU_ENTRY_POINT_NAME (const AudioComponentDescription* inDesc) { return JuceAUFactory (inDesc); } #endif diff --git a/modules/juce_audio_plugin_client/AUResources.r b/modules/juce_audio_plugin_client/AUResources.r deleted file mode 100644 index 30fb387ebb..0000000000 --- a/modules/juce_audio_plugin_client/AUResources.r +++ /dev/null @@ -1,150 +0,0 @@ -/* - 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 - -// 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 - // JUCE CHANGE STARTS HERE - #if defined(arm64_YES) - #if defined(NeedLeadingComma) - , - #endif - cmpThreadSafeOnMac, - 'dlle', RES_ID, 9 - #define NeedLeadingComma 1 - #endif - // JUCE CHANGE ENDS HERE - } -}; - -#undef RES_ID -#undef COMP_TYPE -#undef COMP_SUBTYPE -#undef COMP_MANUF -#undef VERSION -#undef NAME -#undef DESCRIPTION -#undef ENTRY_POINT -#undef NeedLeadingComma diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r deleted file mode 100644 index 06eb4cd5ac..0000000000 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE library. - Copyright (c) 2022 - Raw Material Software Limited - - 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 7 End-User License - Agreement and JUCE Privacy Policy. - - End User License Agreement: www.juce.com/juce-7-licence - Privacy Policy: www.juce.com/juce-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 - -//============================================================================== -/* The JucePluginDefines file should be a file in your project, containing info to describe the - plugin's name, type, etc. The Projucer 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 "JucePluginDefines.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" diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm index d36d18b2a1..ed10cded95 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm @@ -60,21 +60,42 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wparentheses", #define verify_noerr(errorCode) __Verify_noErr(errorCode) #endif -#include "AU/CoreAudioUtilityClasses/AUBase.cpp" -#include "AU/CoreAudioUtilityClasses/AUBuffer.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/ComponentBase.cpp" -#include "AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp" +#if ! defined (MAC_OS_VERSION_11_0) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_11_0 +// These constants are only defined in the macOS 11+ SDKs + +enum MIDICVStatus : unsigned int +{ + kMIDICVStatusNoteOff = 0x8, + kMIDICVStatusNoteOn = 0x9, + kMIDICVStatusPolyPressure = 0xA, + kMIDICVStatusControlChange = 0xB, + kMIDICVStatusProgramChange = 0xC, + kMIDICVStatusChannelPressure = 0xD, + kMIDICVStatusPitchBend = 0xE, + kMIDICVStatusRegisteredPNC = 0x0, + kMIDICVStatusAssignablePNC = 0x1, + kMIDICVStatusRegisteredControl = 0x2, + kMIDICVStatusAssignableControl = 0x3, + kMIDICVStatusRelRegisteredControl = 0x4, + kMIDICVStatusRelAssignableControl = 0x5, + kMIDICVStatusPerNotePitchBend = 0x6, + kMIDICVStatusPerNoteMgmt = 0xF +}; + +#endif + +#include "AU/AudioUnitSDK/AUBase.cpp" +#include "AU/AudioUnitSDK/AUBuffer.cpp" +#include "AU/AudioUnitSDK/AUBufferAllocator.cpp" +#include "AU/AudioUnitSDK/AUEffectBase.cpp" +#include "AU/AudioUnitSDK/AUInputElement.cpp" +#include "AU/AudioUnitSDK/AUMIDIBase.cpp" +#include "AU/AudioUnitSDK/AUMIDIEffectBase.cpp" +#include "AU/AudioUnitSDK/AUOutputElement.cpp" +#include "AU/AudioUnitSDK/AUPlugInDispatch.cpp" +#include "AU/AudioUnitSDK/AUScopeElement.cpp" +#include "AU/AudioUnitSDK/ComponentBase.cpp" +#include "AU/AudioUnitSDK/MusicDeviceBase.cpp" #undef verify #undef verify_noerr