diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/Info-Standalone_Plugin.plist b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/Info-Standalone_Plugin.plist new file mode 100644 index 0000000000..89f52de629 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/Info-Standalone_Plugin.plist @@ -0,0 +1,62 @@ + + + + + + LSRequiresIPhoneOS + + NSMicrophoneUsageDescription + This app requires microphone input. + UIViewControllerBasedStatusBarAppearance + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleName + InterAppAudioEffect + CFBundleDisplayName + InterAppAudioEffect + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1.0.0 + NSHumanReadableCopyright + ROLI Ltd. + NSHighResolutionCapable + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIBackgroundModes + + audio + + AudioComponents + + + name + ROLI Ltd.: InterAppAudioEffect + manufacturer + ROLI + type + aurx + subtype + IAAE + version + 65536 + + + + diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect.entitlements b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect.entitlements new file mode 100644 index 0000000000..ee8c4fb8d8 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect.entitlements @@ -0,0 +1,8 @@ + + + + + inter-app-audio + + + diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect.xcodeproj/project.pbxproj b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..2f6cef507d --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect.xcodeproj/project.pbxproj @@ -0,0 +1,373 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + + 48524E1776017288798AB20A = {isa = PBXBuildFile; fileRef = E9D6BA12BDD1947BDDAE08F7; }; + 8EF8670E422BB9CF164302DF = {isa = PBXBuildFile; fileRef = 873711620EC157BCCFFF80B1; }; + 61D6F1506B76AFBA614F491E = {isa = PBXBuildFile; fileRef = 67BBA32BE9EE1CAF8A105F6A; }; + 03A7A8C261C0A1B578F219EF = {isa = PBXBuildFile; fileRef = E43030B35C6CB127DC67FEE7; }; + E9FB1841DE3518ADBD86293C = {isa = PBXBuildFile; fileRef = 53BB9950BAA9E837613ED83B; }; + 7B71DA92A48B9D67BA68C69E = {isa = PBXBuildFile; fileRef = 212019C041EE17C23460CE02; }; + BC8485848043996AFA210EF9 = {isa = PBXBuildFile; fileRef = C293562C310CB0B3259811F0; }; + 7FF11BF2317D79501E0632DB = {isa = PBXBuildFile; fileRef = E4431E84242848EF9D250FC7; }; + DD2143886468728A97F9586E = {isa = PBXBuildFile; fileRef = C43FC3A63342AA4CDE8F0906; }; + EE6B5FC34FB47B41336EA293 = {isa = PBXBuildFile; fileRef = AD9B42ED650058295A747510; }; + B2E5CB24DBACF25E2CBAC9A1 = {isa = PBXBuildFile; fileRef = F07FA71EC2B5FCA584FAA10B; }; + 6FAEC70FAE3DBC629160F86C = {isa = PBXBuildFile; fileRef = 41CB50701EE5BFDCE1F89BBA; }; + DFF48C0819F2191B154569A9 = {isa = PBXBuildFile; fileRef = B69C94CF64688C5270D8122C; }; + 9BB46E700B9A4617B4CFDC24 = {isa = PBXBuildFile; fileRef = 82F310E23852E0C002F5A2D1; }; + 4EC4A8C3AF328E40626CBAE7 = {isa = PBXBuildFile; fileRef = E5A657DE5A5B1516B3E35FA8; }; + 9A7D9D7490AF3D82BA8D9686 = {isa = PBXBuildFile; fileRef = 2C4476A46744766A478A74B6; }; + 40833B424B5E9EC84C09EE40 = {isa = PBXBuildFile; fileRef = 131A768FD64EB99097B0B190; }; + 7ACC830E1DDF0F171C890B2B = {isa = PBXBuildFile; fileRef = 7C1F5AA6FE8016951F45F916; }; + 78BD211C42E345A8048DEDD5 = {isa = PBXBuildFile; fileRef = 0EB1F323BA52207C49A27479; }; + A49F3F55F083BAD332CA4324 = {isa = PBXBuildFile; fileRef = 223C6D257BB45525A7C2D495; }; + B2BE378326805DEBB71B3016 = {isa = PBXBuildFile; fileRef = D9C8C1E2D3F27800C6E774D7; }; + BCA424EEB2F9F33372CA4909 = {isa = PBXBuildFile; fileRef = CDCF152172E34769B268ECDA; }; + 246490CF3D197E69B1F7FCC8 = {isa = PBXBuildFile; fileRef = 02ABCEB5E369CDE6AEA817B3; }; + 873E620B819DC84C953EC518 = {isa = PBXBuildFile; fileRef = 32E0486AA56B56AD10D18A56; }; + 40E6F5A9B432DEB7689AF7D0 = {isa = PBXBuildFile; fileRef = 4B55841B06C897F72BC2F8CE; }; + 78412E76B9D1D75907390309 = {isa = PBXBuildFile; fileRef = C450D63325E2C29C72B6606C; }; + E3DD6181D2A4E2703637E1EF = {isa = PBXBuildFile; fileRef = 36A796A962C81B44E9233775; }; + E8410AF631A96357D2807C3A = {isa = PBXBuildFile; fileRef = 10EEE1E56B53B7A31753365C; }; + DCEE24917F78097ACF14EAD0 = {isa = PBXBuildFile; fileRef = 1F042A6F2A0986F23B7097FC; }; + CA28F22C95EBC20CB37612FF = {isa = PBXBuildFile; fileRef = A3BDBD773FBCCD4F9440D174; }; + 02ABCEB5E369CDE6AEA817B3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_processors.mm"; path = "../../JuceLibraryCode/juce_audio_processors.mm"; sourceTree = "SOURCE_ROOT"; }; + 0EB1F323BA52207C49A27479 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_formats.mm"; path = "../../JuceLibraryCode/juce_audio_formats.mm"; sourceTree = "SOURCE_ROOT"; }; + 10EEE1E56B53B7A31753365C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_graphics.mm"; path = "../../JuceLibraryCode/juce_graphics.mm"; sourceTree = "SOURCE_ROOT"; }; + 131A768FD64EB99097B0B190 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_basics.mm"; path = "../../JuceLibraryCode/juce_audio_basics.mm"; sourceTree = "SOURCE_ROOT"; }; + 1F042A6F2A0986F23B7097FC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_basics.mm"; path = "../../JuceLibraryCode/juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; }; + 212019C041EE17C23460CE02 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; + 223C6D257BB45525A7C2D495 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_audio_plugin_client_Standalone.cpp"; path = "../../JuceLibraryCode/juce_audio_plugin_client_Standalone.cpp"; sourceTree = "SOURCE_ROOT"; }; + 2A2D7663F8BC39E97FF490E3 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_core"; path = "../../../../../modules/juce_core"; sourceTree = "SOURCE_ROOT"; }; + 2C4476A46744766A478A74B6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IAAEffectProcessor.cpp; path = ../../Source/IAAEffectProcessor.cpp; sourceTree = "SOURCE_ROOT"; }; + 3158E31C9E0DBE333E275FB1 = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = InterAppAudioEffect.entitlements; path = InterAppAudioEffect.entitlements; sourceTree = "SOURCE_ROOT"; }; + 32E0486AA56B56AD10D18A56 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_utils.mm"; path = "../../JuceLibraryCode/juce_audio_utils.mm"; sourceTree = "SOURCE_ROOT"; }; + 36A796A962C81B44E9233775 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_events.mm"; path = "../../JuceLibraryCode/juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; + 41CB50701EE5BFDCE1F89BBA = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4B55841B06C897F72BC2F8CE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_core.mm"; path = "../../JuceLibraryCode/juce_core.mm"; sourceTree = "SOURCE_ROOT"; }; + 4D36B733C9B175319B696E33 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = "SOURCE_ROOT"; }; + 50724579E5DD043CD53B0C95 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_plugin_client"; path = "../../../../../modules/juce_audio_plugin_client"; sourceTree = "SOURCE_ROOT"; }; + 51A5B253018FC02A6AFB7416 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_processors"; path = "../../../../../modules/juce_audio_processors"; sourceTree = "SOURCE_ROOT"; }; + 53BB9950BAA9E837613ED83B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + 54EEC3679EBFF5E6C7B580F1 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; + 59469A0541A1B91E7968B8FC = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_gui_extra"; path = "../../../../../modules/juce_gui_extra"; sourceTree = "SOURCE_ROOT"; }; + 67BBA32BE9EE1CAF8A105F6A = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + 6E90633D52FCA2BC0B99F9F2 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_formats"; path = "../../../../../modules/juce_audio_formats"; sourceTree = "SOURCE_ROOT"; }; + 746E2820600C97BD2E760C34 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IAAEffectEditor.h; path = ../../Source/IAAEffectEditor.h; sourceTree = "SOURCE_ROOT"; }; + 78F41A05666E3B38C9FDE9D3 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_events"; path = "../../../../../modules/juce_events"; sourceTree = "SOURCE_ROOT"; }; + 7B37ABD2C5B9FF909250C8DE = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-Standalone_Plugin.plist"; path = "Info-Standalone_Plugin.plist"; sourceTree = "SOURCE_ROOT"; }; + 7C1F5AA6FE8016951F45F916 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_devices.mm"; path = "../../JuceLibraryCode/juce_audio_devices.mm"; sourceTree = "SOURCE_ROOT"; }; + 82F310E23852E0C002F5A2D1 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 9C809DD426D6B660393427D4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SimpleMeter.h; path = ../../Source/SimpleMeter.h; sourceTree = "SOURCE_ROOT"; }; + A3BDBD773FBCCD4F9440D174 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_extra.mm"; path = "../../JuceLibraryCode/juce_gui_extra.mm"; sourceTree = "SOURCE_ROOT"; }; + AD9B42ED650058295A747510 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; }; + B3D01A391D4DF11709AE5688 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; }; + B69C94CF64688C5270D8122C = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + C1507624A4C7CFDCE375CEB6 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_graphics"; path = "../../../../../modules/juce_graphics"; sourceTree = "SOURCE_ROOT"; }; + C21DF85AC43B32B0E0735A3E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IAAEffectProcessor.h; path = ../../Source/IAAEffectProcessor.h; sourceTree = "SOURCE_ROOT"; }; + C293562C310CB0B3259811F0 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; }; + C43FC3A63342AA4CDE8F0906 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; + C450D63325E2C29C72B6606C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_data_structures.mm"; path = "../../JuceLibraryCode/juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; + C6F57BB192F1BC9BE7D82F99 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_devices"; path = "../../../../../modules/juce_audio_devices"; sourceTree = "SOURCE_ROOT"; }; + CB7EB47782C231D8D6CD52FD = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_basics"; path = "../../../../../modules/juce_audio_basics"; sourceTree = "SOURCE_ROOT"; }; + CDCF152172E34769B268ECDA = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_audio_plugin_client_VST_utils.mm"; path = "../../JuceLibraryCode/juce_audio_plugin_client_VST_utils.mm"; sourceTree = "SOURCE_ROOT"; }; + E43030B35C6CB127DC67FEE7 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + E4431E84242848EF9D250FC7 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + E9D6BA12BDD1947BDDAE08F7 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InterAppAudioEffect.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; + 873711620EC157BCCFFF80B1 = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libInterAppAudioEffect.a; sourceTree = "BUILT_PRODUCTS_DIR"; }; + D9C8C1E2D3F27800C6E774D7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_audio_plugin_client_utils.cpp"; path = "../../JuceLibraryCode/juce_audio_plugin_client_utils.cpp"; sourceTree = "SOURCE_ROOT"; }; + E5A657DE5A5B1516B3E35FA8 = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = InterAppAudioEffect/Images.xcassets; sourceTree = "SOURCE_ROOT"; }; + EBA214D367A10FDDC99E8922 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_utils"; path = "../../../../../modules/juce_audio_utils"; sourceTree = "SOURCE_ROOT"; }; + F07FA71EC2B5FCA584FAA10B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; + FEBA6F6C0A62E2749D6ACC88 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_gui_basics"; path = "../../../../../modules/juce_gui_basics"; sourceTree = "SOURCE_ROOT"; }; + 9D54126CE5CE65025DE4742F = {isa = PBXGroup; children = ( + C21DF85AC43B32B0E0735A3E, + 2C4476A46744766A478A74B6, + 746E2820600C97BD2E760C34, + 9C809DD426D6B660393427D4, ); name = Source; sourceTree = ""; }; + EB371D6195C6398C6F1946EF = {isa = PBXGroup; children = ( + 9D54126CE5CE65025DE4742F, ); name = InterAppAudioEffect; sourceTree = ""; }; + 3CDCF2D2F9AA23710946CF21 = {isa = PBXGroup; children = ( + CB7EB47782C231D8D6CD52FD, + C6F57BB192F1BC9BE7D82F99, + 6E90633D52FCA2BC0B99F9F2, + 50724579E5DD043CD53B0C95, + 51A5B253018FC02A6AFB7416, + EBA214D367A10FDDC99E8922, + 2A2D7663F8BC39E97FF490E3, + 54EEC3679EBFF5E6C7B580F1, + 78F41A05666E3B38C9FDE9D3, + C1507624A4C7CFDCE375CEB6, + FEBA6F6C0A62E2749D6ACC88, + 59469A0541A1B91E7968B8FC, ); name = "Juce Modules"; sourceTree = ""; }; + C560791DA1D2E0CA6690BC9E = {isa = PBXGroup; children = ( + 4D36B733C9B175319B696E33, + 131A768FD64EB99097B0B190, + 7C1F5AA6FE8016951F45F916, + 0EB1F323BA52207C49A27479, + 223C6D257BB45525A7C2D495, + D9C8C1E2D3F27800C6E774D7, + CDCF152172E34769B268ECDA, + 02ABCEB5E369CDE6AEA817B3, + 32E0486AA56B56AD10D18A56, + 4B55841B06C897F72BC2F8CE, + C450D63325E2C29C72B6606C, + 36A796A962C81B44E9233775, + 10EEE1E56B53B7A31753365C, + 1F042A6F2A0986F23B7097FC, + A3BDBD773FBCCD4F9440D174, + B3D01A391D4DF11709AE5688, ); name = "Juce Library Code"; sourceTree = ""; }; + E1CFC4C60E9EC5DBE60DB32F = {isa = PBXGroup; children = ( + 7B37ABD2C5B9FF909250C8DE, + E5A657DE5A5B1516B3E35FA8, ); name = Resources; sourceTree = ""; }; + BF7815807DD5B5FAF4BC3669 = {isa = PBXGroup; children = ( + 67BBA32BE9EE1CAF8A105F6A, + E43030B35C6CB127DC67FEE7, + 53BB9950BAA9E837613ED83B, + 212019C041EE17C23460CE02, + C293562C310CB0B3259811F0, + E4431E84242848EF9D250FC7, + C43FC3A63342AA4CDE8F0906, + AD9B42ED650058295A747510, + F07FA71EC2B5FCA584FAA10B, + 41CB50701EE5BFDCE1F89BBA, + B69C94CF64688C5270D8122C, + 82F310E23852E0C002F5A2D1, ); name = Frameworks; sourceTree = ""; }; + 196E6AA022E8A0902AB15281 = {isa = PBXGroup; children = ( + E9D6BA12BDD1947BDDAE08F7, + 873711620EC157BCCFFF80B1, ); name = Products; sourceTree = ""; }; + EC01685A042C62251C5AF093 = {isa = PBXGroup; children = ( + 3158E31C9E0DBE333E275FB1, + EB371D6195C6398C6F1946EF, + 3CDCF2D2F9AA23710946CF21, + C560791DA1D2E0CA6690BC9E, + E1CFC4C60E9EC5DBE60DB32F, + BF7815807DD5B5FAF4BC3669, + 196E6AA022E8A0902AB15281, ); name = Source; sourceTree = ""; }; + 22DBBF091193373BEA063A5B = {isa = XCBuildConfiguration; buildSettings = { }; name = Debug; }; + 54D411166886E8F3BBC0E25F = {isa = XCBuildConfiguration; buildSettings = { }; name = Release; }; + 8DA1E39A676F877EB549B8CA = {isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_LINK_OBJC_RUNTIME = NO; + CODE_SIGN_ENTITLEMENTS = "InterAppAudioEffect.entitlements"; + COMBINE_HIDPI_IMAGES = YES; + CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "_DEBUG=1", + "DEBUG=1", + "JUCER_XCODE_IPHONE_5BC26AE3=1", + "JUCE_APP_VERSION=1.0.0", + "JUCE_APP_VERSION_HEX=0x10000", + "JucePlugin_Build_VST=0", + "JucePlugin_Build_VST3=0", + "JucePlugin_Build_AU=0", + "JucePlugin_Build_AUv3=0", + "JucePlugin_Build_RTAS=0", + "JucePlugin_Build_AAX=0", + "JucePlugin_Build_Standalone=1", ); + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../../modules", "$(inherited)"); + INFOPLIST_FILE = Info-Standalone_Plugin.plist; + OTHER_CPLUSPLUSFLAGS = "-Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare -Wint-conversion -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wsign-conversion"; + OTHER_LDFLAGS = "-lInterAppAudioEffect"; + PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.InterAppAudioEffect; }; name = Debug; }; + 07EA55A19B872E1F49C62539 = {isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_LINK_OBJC_RUNTIME = NO; + CODE_SIGN_ENTITLEMENTS = "InterAppAudioEffect.entitlements"; + COMBINE_HIDPI_IMAGES = YES; + CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; + DEAD_CODE_STRIPPING = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "_NDEBUG=1", + "NDEBUG=1", + "JUCER_XCODE_IPHONE_5BC26AE3=1", + "JUCE_APP_VERSION=1.0.0", + "JUCE_APP_VERSION_HEX=0x10000", + "JucePlugin_Build_VST=0", + "JucePlugin_Build_VST3=0", + "JucePlugin_Build_AU=0", + "JucePlugin_Build_AUv3=0", + "JucePlugin_Build_RTAS=0", + "JucePlugin_Build_AAX=0", + "JucePlugin_Build_Standalone=1", ); + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../../modules", "$(inherited)"); + INFOPLIST_FILE = Info-Standalone_Plugin.plist; + OTHER_CPLUSPLUSFLAGS = "-Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare -Wint-conversion -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wsign-conversion"; + OTHER_LDFLAGS = "-lInterAppAudioEffect"; + PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.InterAppAudioEffect; }; name = Release; }; + E6FA0B75AC78727D8A3F1888 = {isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_LINK_OBJC_RUNTIME = NO; + COMBINE_HIDPI_IMAGES = YES; + CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "_DEBUG=1", + "DEBUG=1", + "JUCER_XCODE_IPHONE_5BC26AE3=1", + "JUCE_APP_VERSION=1.0.0", + "JUCE_APP_VERSION_HEX=0x10000", + "JucePlugin_Build_VST=0", + "JucePlugin_Build_VST3=0", + "JucePlugin_Build_AU=0", + "JucePlugin_Build_AUv3=0", + "JucePlugin_Build_RTAS=0", + "JucePlugin_Build_AAX=0", + "JucePlugin_Build_Standalone=1", + "JUCE_SHARED_CODE=1", ); + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../../modules", "$(inherited)"); + INSTALL_PATH = "@executable_path/Frameworks"; + OTHER_CPLUSPLUSFLAGS = "-Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare -Wint-conversion -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wsign-conversion"; + PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.InterAppAudioEffect; }; name = Debug; }; + 665044AFDC3F0D4E11643857 = {isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_LINK_OBJC_RUNTIME = NO; + COMBINE_HIDPI_IMAGES = YES; + CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; + DEAD_CODE_STRIPPING = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "_NDEBUG=1", + "NDEBUG=1", + "JUCER_XCODE_IPHONE_5BC26AE3=1", + "JUCE_APP_VERSION=1.0.0", + "JUCE_APP_VERSION_HEX=0x10000", + "JucePlugin_Build_VST=0", + "JucePlugin_Build_VST3=0", + "JucePlugin_Build_AU=0", + "JucePlugin_Build_AUv3=0", + "JucePlugin_Build_RTAS=0", + "JucePlugin_Build_AAX=0", + "JucePlugin_Build_Standalone=1", + "JUCE_SHARED_CODE=1", ); + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../../modules", "$(inherited)"); + INSTALL_PATH = "@executable_path/Frameworks"; + OTHER_CPLUSPLUSFLAGS = "-Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare -Wint-conversion -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wsign-conversion"; + PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.InterAppAudioEffect; }; name = Release; }; + 4650CE5DEC4B4B8ED96435A4 = {isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf"; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c11; + GCC_INLINES_ARE_PRIVATE_EXTERN = YES; + GCC_MODEL_TUNING = G5; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "InterAppAudioEffect"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = -Wreorder; + ZERO_LINK = NO; }; name = Debug; }; + C2BB86E774E1461CAF0D87DD = {isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf"; + GCC_C_LANGUAGE_STANDARD = c11; + GCC_INLINES_ARE_PRIVATE_EXTERN = YES; + GCC_MODEL_TUNING = G5; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + PRODUCT_NAME = "InterAppAudioEffect"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + WARNING_CFLAGS = -Wreorder; + ZERO_LINK = NO; }; name = Release; }; + 2C494CD599EC256FDB6CCE00 = {isa = PBXTargetDependency; target = 51FB6E6A2D0998D38E999826; }; + CECAF531D33909A1FB3ABE80 = {isa = PBXTargetDependency; target = A3401CC1AC6C5B89EFBAEF01; }; + 016ACE6B9EC6F47020502F4F = {isa = XCConfigurationList; buildConfigurations = ( + 4650CE5DEC4B4B8ED96435A4, + C2BB86E774E1461CAF0D87DD, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + D10DBCC16019A5712E897068 = {isa = XCConfigurationList; buildConfigurations = ( + 22DBBF091193373BEA063A5B, + 54D411166886E8F3BBC0E25F, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + 03BD5476C606A5BA65CD4FDF = {isa = PBXAggregateTarget; buildConfigurationList = D10DBCC16019A5712E897068; buildPhases = ( ); buildRules = ( ); dependencies = ( + 2C494CD599EC256FDB6CCE00, + CECAF531D33909A1FB3ABE80, ); name = "InterAppAudioEffect - All"; productName = InterAppAudioEffect; }; + 10A00DA553BF0C30212421D2 = {isa = XCConfigurationList; buildConfigurations = ( + 8DA1E39A676F877EB549B8CA, + 07EA55A19B872E1F49C62539, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + C8358163192CC594074B35EA = {isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4EC4A8C3AF328E40626CBAE7, ); runOnlyForDeploymentPostprocessing = 0; }; + AC1841BDF7829D1EA1146F56 = {isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A49F3F55F083BAD332CA4324, ); runOnlyForDeploymentPostprocessing = 0; }; + A0069210E3FD182F29030BDB = {isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 61D6F1506B76AFBA614F491E, + 03A7A8C261C0A1B578F219EF, + E9FB1841DE3518ADBD86293C, + 7B71DA92A48B9D67BA68C69E, + BC8485848043996AFA210EF9, + 7FF11BF2317D79501E0632DB, + DD2143886468728A97F9586E, + EE6B5FC34FB47B41336EA293, + B2E5CB24DBACF25E2CBAC9A1, + 6FAEC70FAE3DBC629160F86C, + DFF48C0819F2191B154569A9, + 9BB46E700B9A4617B4CFDC24, ); runOnlyForDeploymentPostprocessing = 0; }; + 51FB6E6A2D0998D38E999826 = {isa = PBXNativeTarget; buildConfigurationList = 10A00DA553BF0C30212421D2; buildPhases = ( + C8358163192CC594074B35EA, + AC1841BDF7829D1EA1146F56, + A0069210E3FD182F29030BDB, ); buildRules = ( ); dependencies = ( + CECAF531D33909A1FB3ABE80, ); name = "InterAppAudioEffect - Standalone Plugin"; productName = InterAppAudioEffect; productReference = E9D6BA12BDD1947BDDAE08F7; productType = "com.apple.product-type.application"; }; + AA6F190D4FECB06C7A7A0658 = {isa = XCConfigurationList; buildConfigurations = ( + E6FA0B75AC78727D8A3F1888, + 665044AFDC3F0D4E11643857, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + 177DC2A7A303F23EDDE5183A = {isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9A7D9D7490AF3D82BA8D9686, + 40833B424B5E9EC84C09EE40, + 7ACC830E1DDF0F171C890B2B, + 78BD211C42E345A8048DEDD5, + B2BE378326805DEBB71B3016, + BCA424EEB2F9F33372CA4909, + 246490CF3D197E69B1F7FCC8, + 873E620B819DC84C953EC518, + 40E6F5A9B432DEB7689AF7D0, + 78412E76B9D1D75907390309, + E3DD6181D2A4E2703637E1EF, + E8410AF631A96357D2807C3A, + DCEE24917F78097ACF14EAD0, + CA28F22C95EBC20CB37612FF, ); runOnlyForDeploymentPostprocessing = 0; }; + A3401CC1AC6C5B89EFBAEF01 = {isa = PBXNativeTarget; buildConfigurationList = AA6F190D4FECB06C7A7A0658; buildPhases = ( + 177DC2A7A303F23EDDE5183A, ); buildRules = ( ); dependencies = ( ); name = "InterAppAudioEffect - Shared Code"; productName = InterAppAudioEffect; productReference = 873711620EC157BCCFFF80B1; productType = "com.apple.product-type.library.static"; }; + DF3D0C1B88ADC0274AE6BD73 = {isa = PBXProject; buildConfigurationList = 016ACE6B9EC6F47020502F4F; attributes = { LastUpgradeCheck = 0820; TargetAttributes = { 03BD5476C606A5BA65CD4FDF = { SystemCapabilities = {com.apple.InAppPurchase = { enabled = 0; }; com.apple.InterAppAudio = { enabled = 0; }; com.apple.Sandbox = { enabled = 0; }; }; };51FB6E6A2D0998D38E999826 = { SystemCapabilities = {com.apple.InAppPurchase = { enabled = 0; }; com.apple.InterAppAudio = { enabled = 1; }; com.apple.Sandbox = { enabled = 0; }; }; };A3401CC1AC6C5B89EFBAEF01 = { SystemCapabilities = {com.apple.InAppPurchase = { enabled = 0; }; com.apple.InterAppAudio = { enabled = 0; }; com.apple.Sandbox = { enabled = 0; }; }; }; }; }; compatibilityVersion = "Xcode 3.2"; hasScannedForEncodings = 0; mainGroup = EC01685A042C62251C5AF093; projectDirPath = ""; projectRoot = ""; targets = (03BD5476C606A5BA65CD4FDF, 51FB6E6A2D0998D38E999826, A3401CC1AC6C5B89EFBAEF01); }; + }; + rootObject = DF3D0C1B88ADC0274AE6BD73; +} diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-1x.png b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-1x.png new file mode 100644 index 0000000000..b8a0025f63 Binary files /dev/null and b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-1x.png differ diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-2x.png b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-2x.png new file mode 100644 index 0000000000..817cdf8057 Binary files /dev/null and b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-landscape-2x.png differ diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-1x.png b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-1x.png new file mode 100644 index 0000000000..f3685597a1 Binary files /dev/null and b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-1x.png differ diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-2x.png b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-2x.png new file mode 100644 index 0000000000..5447ddfc5b Binary files /dev/null and b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-ipad-portrait-2x.png differ diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-2x.png b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-2x.png new file mode 100644 index 0000000000..efe9e82a32 Binary files /dev/null and b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-2x.png differ diff --git a/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-retina4.png b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-retina4.png new file mode 100644 index 0000000000..d0e3261440 Binary files /dev/null and b/examples/PlugInSamples/InterAppAudioEffect/Builds/iOS/InterAppAudioEffect/Images.xcassets/LaunchImage.launchimage/LaunchImage-iphone-retina4.png differ diff --git a/examples/PlugInSamples/InterAppAudioEffect/InterAppAudioEffect.jucer b/examples/PlugInSamples/InterAppAudioEffect/InterAppAudioEffect.jucer new file mode 100644 index 0000000000..ccd185b9d1 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/InterAppAudioEffect.jucer @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/AppConfig.h b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/AppConfig.h new file mode 100644 index 0000000000..f6a6a0a543 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/AppConfig.h @@ -0,0 +1,363 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + + There's a section below where you can add your own custom code safely, and the + Projucer will preserve the contents of that block, but the best way to change + any of these definitions is by using the Projucer's project settings. + + Any commented-out settings will assume their default values. + +*/ + +#pragma once + +//============================================================================== +// [BEGIN_USER_CODE_SECTION] + +// (You can add your own code in this section, and the Projucer will not overwrite it) + +// [END_USER_CODE_SECTION] + +//============================================================================== +#define JUCE_MODULE_AVAILABLE_juce_audio_basics 1 +#define JUCE_MODULE_AVAILABLE_juce_audio_devices 1 +#define JUCE_MODULE_AVAILABLE_juce_audio_formats 1 +#define JUCE_MODULE_AVAILABLE_juce_audio_plugin_client 1 +#define JUCE_MODULE_AVAILABLE_juce_audio_processors 1 +#define JUCE_MODULE_AVAILABLE_juce_audio_utils 1 +#define JUCE_MODULE_AVAILABLE_juce_core 1 +#define JUCE_MODULE_AVAILABLE_juce_data_structures 1 +#define JUCE_MODULE_AVAILABLE_juce_events 1 +#define JUCE_MODULE_AVAILABLE_juce_graphics 1 +#define JUCE_MODULE_AVAILABLE_juce_gui_basics 1 +#define JUCE_MODULE_AVAILABLE_juce_gui_extra 1 + +//============================================================================== +#ifndef JUCE_STANDALONE_APPLICATION + #if defined(JucePlugin_Name) && defined(JucePlugin_Build_Standalone) + #define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone + #else + #define JUCE_STANDALONE_APPLICATION 0 + #endif +#endif + +#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1 + +//============================================================================== +// juce_audio_devices flags: + +#ifndef JUCE_ASIO + //#define JUCE_ASIO +#endif + +#ifndef JUCE_WASAPI + //#define JUCE_WASAPI +#endif + +#ifndef JUCE_WASAPI_EXCLUSIVE + //#define JUCE_WASAPI_EXCLUSIVE +#endif + +#ifndef JUCE_DIRECTSOUND + //#define JUCE_DIRECTSOUND +#endif + +#ifndef JUCE_ALSA + //#define JUCE_ALSA +#endif + +#ifndef JUCE_JACK + //#define JUCE_JACK +#endif + +#ifndef JUCE_USE_ANDROID_OPENSLES + //#define JUCE_USE_ANDROID_OPENSLES +#endif + +#ifndef JUCE_USE_WINRT_MIDI + //#define JUCE_USE_WINRT_MIDI +#endif + +//============================================================================== +// juce_audio_formats flags: + +#ifndef JUCE_USE_FLAC + //#define JUCE_USE_FLAC +#endif + +#ifndef JUCE_USE_OGGVORBIS + //#define JUCE_USE_OGGVORBIS +#endif + +#ifndef JUCE_USE_MP3AUDIOFORMAT + //#define JUCE_USE_MP3AUDIOFORMAT +#endif + +#ifndef JUCE_USE_LAME_AUDIO_FORMAT + //#define JUCE_USE_LAME_AUDIO_FORMAT +#endif + +#ifndef JUCE_USE_WINDOWS_MEDIA_FORMAT + //#define JUCE_USE_WINDOWS_MEDIA_FORMAT +#endif + +//============================================================================== +// juce_audio_plugin_client flags: + +#ifndef JUCE_FORCE_USE_LEGACY_PARAM_IDS + //#define JUCE_FORCE_USE_LEGACY_PARAM_IDS +#endif + +#ifndef JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS + //#define JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS +#endif + +//============================================================================== +// juce_audio_processors flags: + +#ifndef JUCE_PLUGINHOST_VST + //#define JUCE_PLUGINHOST_VST +#endif + +#ifndef JUCE_PLUGINHOST_VST3 + //#define JUCE_PLUGINHOST_VST3 +#endif + +#ifndef JUCE_PLUGINHOST_AU + //#define JUCE_PLUGINHOST_AU +#endif + +//============================================================================== +// juce_audio_utils flags: + +#ifndef JUCE_USE_CDREADER + //#define JUCE_USE_CDREADER +#endif + +#ifndef JUCE_USE_CDBURNER + //#define JUCE_USE_CDBURNER +#endif + +//============================================================================== +// juce_core flags: + +#ifndef JUCE_FORCE_DEBUG + //#define JUCE_FORCE_DEBUG +#endif + +#ifndef JUCE_LOG_ASSERTIONS + //#define JUCE_LOG_ASSERTIONS +#endif + +#ifndef JUCE_CHECK_MEMORY_LEAKS + //#define JUCE_CHECK_MEMORY_LEAKS +#endif + +#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES + //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES +#endif + +#ifndef JUCE_INCLUDE_ZLIB_CODE + //#define JUCE_INCLUDE_ZLIB_CODE +#endif + +#ifndef JUCE_USE_CURL + //#define JUCE_USE_CURL +#endif + +#ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS + //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS +#endif + +#ifndef JUCE_ALLOW_STATIC_NULL_VARIABLES + //#define JUCE_ALLOW_STATIC_NULL_VARIABLES +#endif + +//============================================================================== +// juce_events flags: + +#ifndef JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK + //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK +#endif + +//============================================================================== +// juce_graphics flags: + +#ifndef JUCE_USE_COREIMAGE_LOADER + //#define JUCE_USE_COREIMAGE_LOADER +#endif + +#ifndef JUCE_USE_DIRECTWRITE + //#define JUCE_USE_DIRECTWRITE +#endif + +//============================================================================== +// juce_gui_basics flags: + +#ifndef JUCE_ENABLE_REPAINT_DEBUGGING + //#define JUCE_ENABLE_REPAINT_DEBUGGING +#endif + +#ifndef JUCE_USE_XSHM + //#define JUCE_USE_XSHM +#endif + +#ifndef JUCE_USE_XRENDER + //#define JUCE_USE_XRENDER +#endif + +#ifndef JUCE_USE_XCURSOR + //#define JUCE_USE_XCURSOR +#endif + +//============================================================================== +// juce_gui_extra flags: + +#ifndef JUCE_WEB_BROWSER + //#define JUCE_WEB_BROWSER +#endif + +#ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR + //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR +#endif + +//============================================================================== +// Audio plugin settings.. + +#ifndef JucePlugin_Build_VST + #define JucePlugin_Build_VST 0 +#endif +#ifndef JucePlugin_Build_VST3 + #define JucePlugin_Build_VST3 0 +#endif +#ifndef JucePlugin_Build_AU + #define JucePlugin_Build_AU 0 +#endif +#ifndef JucePlugin_Build_AUv3 + #define JucePlugin_Build_AUv3 0 +#endif +#ifndef JucePlugin_Build_RTAS + #define JucePlugin_Build_RTAS 0 +#endif +#ifndef JucePlugin_Build_AAX + #define JucePlugin_Build_AAX 0 +#endif +#ifndef JucePlugin_Build_STANDALONE + #define JucePlugin_Build_STANDALONE 1 +#endif +#ifndef JucePlugin_Enable_IAA + #define JucePlugin_Enable_IAA 1 +#endif +#ifndef JucePlugin_Name + #define JucePlugin_Name "InterAppAudioEffect" +#endif +#ifndef JucePlugin_Desc + #define JucePlugin_Desc "InterAppAudioEffect" +#endif +#ifndef JucePlugin_Manufacturer + #define JucePlugin_Manufacturer "ROLI Ltd." +#endif +#ifndef JucePlugin_ManufacturerWebsite + #define JucePlugin_ManufacturerWebsite "" +#endif +#ifndef JucePlugin_ManufacturerEmail + #define JucePlugin_ManufacturerEmail "" +#endif +#ifndef JucePlugin_ManufacturerCode + #define JucePlugin_ManufacturerCode 0x524f4c49 // 'ROLI' +#endif +#ifndef JucePlugin_PluginCode + #define JucePlugin_PluginCode 0x49414145 // 'IAAE' +#endif +#ifndef JucePlugin_IsSynth + #define JucePlugin_IsSynth 0 +#endif +#ifndef JucePlugin_WantsMidiInput + #define JucePlugin_WantsMidiInput 0 +#endif +#ifndef JucePlugin_ProducesMidiOutput + #define JucePlugin_ProducesMidiOutput 0 +#endif +#ifndef JucePlugin_IsMidiEffect + #define JucePlugin_IsMidiEffect 0 +#endif +#ifndef JucePlugin_EditorRequiresKeyboardFocus + #define JucePlugin_EditorRequiresKeyboardFocus 0 +#endif +#ifndef JucePlugin_Version + #define JucePlugin_Version 1.0.0 +#endif +#ifndef JucePlugin_VersionCode + #define JucePlugin_VersionCode 0x10000 +#endif +#ifndef JucePlugin_VersionString + #define JucePlugin_VersionString "1.0.0" +#endif +#ifndef JucePlugin_VSTUniqueID + #define JucePlugin_VSTUniqueID JucePlugin_PluginCode +#endif +#ifndef JucePlugin_VSTCategory + #define JucePlugin_VSTCategory kPlugCategEffect +#endif +#ifndef JucePlugin_AUMainType + #define JucePlugin_AUMainType kAudioUnitType_Effect +#endif +#ifndef JucePlugin_AUSubType + #define JucePlugin_AUSubType JucePlugin_PluginCode +#endif +#ifndef JucePlugin_AUExportPrefix + #define JucePlugin_AUExportPrefix InterAppAudioEffectAU +#endif +#ifndef JucePlugin_AUExportPrefixQuoted + #define JucePlugin_AUExportPrefixQuoted "InterAppAudioEffectAU" +#endif +#ifndef JucePlugin_AUManufacturerCode + #define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode +#endif +#ifndef JucePlugin_CFBundleIdentifier + #define JucePlugin_CFBundleIdentifier com.yourcompany.InterAppAudioEffect +#endif +#ifndef JucePlugin_RTASCategory + #define JucePlugin_RTASCategory ePlugInCategory_None +#endif +#ifndef JucePlugin_RTASManufacturerCode + #define JucePlugin_RTASManufacturerCode JucePlugin_ManufacturerCode +#endif +#ifndef JucePlugin_RTASProductId + #define JucePlugin_RTASProductId JucePlugin_PluginCode +#endif +#ifndef JucePlugin_RTASDisableBypass + #define JucePlugin_RTASDisableBypass 0 +#endif +#ifndef JucePlugin_RTASDisableMultiMono + #define JucePlugin_RTASDisableMultiMono 0 +#endif +#ifndef JucePlugin_AAXIdentifier + #define JucePlugin_AAXIdentifier com.yourcompany.InterAppAudioEffect +#endif +#ifndef JucePlugin_AAXManufacturerCode + #define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode +#endif +#ifndef JucePlugin_AAXProductId + #define JucePlugin_AAXProductId JucePlugin_PluginCode +#endif +#ifndef JucePlugin_AAXCategory + #define JucePlugin_AAXCategory AAX_ePlugInCategory_Dynamics +#endif +#ifndef JucePlugin_AAXDisableBypass + #define JucePlugin_AAXDisableBypass 0 +#endif +#ifndef JucePlugin_AAXDisableMultiMono + #define JucePlugin_AAXDisableMultiMono 0 +#endif +#ifndef JucePlugin_IAAType + #define JucePlugin_IAAType 0x61757278 // 'aurx' +#endif +#ifndef JucePlugin_IAASubType + #define JucePlugin_IAASubType JucePlugin_PluginCode +#endif +#ifndef JucePlugin_IAAName + #define JucePlugin_IAAName "ROLI Ltd.: InterAppAudioEffect" +#endif diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/JuceHeader.h b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/JuceHeader.h new file mode 100644 index 0000000000..7dd9559672 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/JuceHeader.h @@ -0,0 +1,44 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + + This is the header file that your files should include in order to get all the + JUCE library headers. You should avoid including the JUCE headers directly in + your own source files, because that wouldn't pick up the correct configuration + options for your app. + +*/ + +#pragma once + +#include "AppConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if ! DONT_SET_USING_JUCE_NAMESPACE + // If your code uses a lot of JUCE classes, then this will obviously save you + // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. + using namespace juce; +#endif + +#if ! JUCE_DONT_DECLARE_PROJECTINFO +namespace ProjectInfo +{ + const char* const projectName = "InterAppAudioEffect"; + const char* const versionString = "1.0.0"; + const int versionNumber = 0x10000; +} +#endif diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/ReadMe.txt b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/ReadMe.txt new file mode 100644 index 0000000000..091a5aa6eb --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/ReadMe.txt @@ -0,0 +1,12 @@ + + Important Note!! + ================ + +The purpose of this folder is to contain files that are auto-generated by the Projucer, +and ALL files in this folder will be mercilessly DELETED and completely re-written whenever +the Projucer saves your project. + +Therefore, it's a bad idea to make any manual changes to the files in here, or to +put any of your own files in here if you don't want to lose them. (Of course you may choose +to add the folder's contents to your version-control system so that you can re-merge your own +modifications after the Projucer has saved its changes). diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_basics.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_basics.cpp new file mode 100644 index 0000000000..418694873c --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_basics.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_basics.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_basics.mm new file mode 100644 index 0000000000..e0e6c577cc --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_basics.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_devices.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_devices.cpp new file mode 100644 index 0000000000..fb5c2219d7 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_devices.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_devices.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_devices.mm new file mode 100644 index 0000000000..e58b67ea49 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_devices.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_formats.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_formats.cpp new file mode 100644 index 0000000000..a3c61170eb --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_formats.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_formats.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_formats.mm new file mode 100644 index 0000000000..f325b8fb67 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_formats.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AAX.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AAX.cpp new file mode 100644 index 0000000000..c599b8759f --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AAX.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AAX.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AAX.mm new file mode 100644 index 0000000000..d4b8c31117 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AAX.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AU_1.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AU_1.mm new file mode 100644 index 0000000000..a4fdf7f366 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AU_1.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AU_2.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AU_2.mm new file mode 100644 index 0000000000..175b30047f --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AU_2.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AUv3.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AUv3.mm new file mode 100644 index 0000000000..0ac2b2f599 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_AUv3.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_1.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_1.cpp new file mode 100644 index 0000000000..29d48f3faa --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_1.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_2.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_2.cpp new file mode 100644 index 0000000000..2da08c6dc3 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_2.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_3.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_3.cpp new file mode 100644 index 0000000000..72a8426cbe --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_3.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_4.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_4.cpp new file mode 100644 index 0000000000..6064f99d28 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_4.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_utils.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_utils.cpp new file mode 100644 index 0000000000..5c5509abde --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_utils.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_utils.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_utils.mm new file mode 100644 index 0000000000..56af9aebab --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_RTAS_utils.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_Standalone.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_Standalone.cpp new file mode 100644 index 0000000000..d3b6529a80 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_Standalone.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST2.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST2.cpp new file mode 100644 index 0000000000..c35394b418 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST2.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST3.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST3.cpp new file mode 100644 index 0000000000..8e2e5cde2e --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST3.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST_utils.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST_utils.mm new file mode 100644 index 0000000000..ee2f414e66 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_VST_utils.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_utils.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_utils.cpp new file mode 100644 index 0000000000..183f61b238 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_plugin_client_utils.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_processors.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_processors.cpp new file mode 100644 index 0000000000..bfe172edd0 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_processors.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_processors.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_processors.mm new file mode 100644 index 0000000000..b80ae9017f --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_processors.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_utils.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_utils.cpp new file mode 100644 index 0000000000..97bd2c568c --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_utils.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_utils.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_utils.mm new file mode 100644 index 0000000000..8eae7c6e2f --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_audio_utils.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_core.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_core.cpp new file mode 100644 index 0000000000..d0ce1636f0 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_core.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_core.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_core.mm new file mode 100644 index 0000000000..72b10bf817 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_core.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_data_structures.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_data_structures.cpp new file mode 100644 index 0000000000..9315aa1686 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_data_structures.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_data_structures.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_data_structures.mm new file mode 100644 index 0000000000..695ec43925 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_data_structures.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_events.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_events.cpp new file mode 100644 index 0000000000..1bba110a97 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_events.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_events.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_events.mm new file mode 100644 index 0000000000..4cc34fc401 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_events.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_graphics.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_graphics.cpp new file mode 100644 index 0000000000..319c76de0e --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_graphics.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_graphics.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_graphics.mm new file mode 100644 index 0000000000..b28e6dd056 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_graphics.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_basics.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_basics.cpp new file mode 100644 index 0000000000..216c76bb05 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_basics.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_basics.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_basics.mm new file mode 100644 index 0000000000..6a9726fa5f --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_basics.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_extra.cpp b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_extra.cpp new file mode 100644 index 0000000000..7226e19833 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_extra.cpp @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_extra.mm b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_extra.mm new file mode 100644 index 0000000000..c9b6c3bfc6 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/JuceLibraryCode/juce_gui_extra.mm @@ -0,0 +1,9 @@ +/* + + IMPORTANT! This file is auto-generated each time you save your + project - if you alter its contents, your changes may be overwritten! + +*/ + +#include "AppConfig.h" +#include diff --git a/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectEditor.h b/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectEditor.h new file mode 100644 index 0000000000..7f44b4e87c --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectEditor.h @@ -0,0 +1,277 @@ +#ifndef IAAEFFECTEDITOR_H_INCLUDED +#define IAAEFFECTEDITOR_H_INCLUDED + +#include "../JuceLibraryCode/JuceHeader.h" +#include "IAAEffectProcessor.h" +#include "SimpleMeter.h" + + +class IAAEffectEditor : public AudioProcessorEditor, + private IAAEffectProcessor::MeterListener, + private ButtonListener, + private Timer +{ +public: + IAAEffectEditor (IAAEffectProcessor& p, + AudioProcessorValueTreeState& vts) + : AudioProcessorEditor (p), + processor (p), + parameters (vts) + { + // Register for meter value updates. + processor.addMeterListener (*this); + + gainSlider.setSliderStyle (Slider::SliderStyle::LinearVertical); + gainSlider.setTextBoxStyle (Slider::TextEntryBoxPosition::TextBoxAbove, false, 60, 20); + addAndMakeVisible (gainSlider); + + for (auto& meter : meters) + addAndMakeVisible (meter); + + // Configure all the graphics for the transport control. + + transportText.setColour (Label::textColourId, Colours::white); + transportText.setFont (Font (Font::getDefaultMonospacedFontName(), 18.0f, Font::plain)); + transportText.setJustificationType (Justification::topLeft); + addChildComponent (transportText); + + Path rewindShape; + rewindShape.addRectangle (0.0, 0.0, 5.0, buttonSize); + rewindShape.addTriangle (0.0, buttonSize / 2, buttonSize, 0.0, buttonSize, buttonSize); + rewindButton.setShape (rewindShape, true, true, false); + rewindButton.addListener (this); + addChildComponent (rewindButton); + + Path playShape; + playShape.addTriangle (0.0, 0.0, 0.0, buttonSize, buttonSize, buttonSize / 2); + playButton.setShape (playShape, true, true, false); + playButton.addListener (this); + addChildComponent (playButton); + + Path recordShape; + recordShape.addEllipse (0.0, 0.0, buttonSize, buttonSize); + recordButton.setShape (recordShape, true, true, false); + recordButton.addListener (this); + addChildComponent (recordButton); + + // Configure the switch to host button. + + switchToHostButtonLabel.setColour (Label::textColourId, Colours::white); + switchToHostButtonLabel.setFont (Font (Font::getDefaultMonospacedFontName(), 18.0f, Font::plain)); + switchToHostButtonLabel.setJustificationType (Justification::centredRight); + switchToHostButtonLabel.setText ("Switch to\nhost app:", dontSendNotification); + addChildComponent (switchToHostButtonLabel); + + switchToHostButton.addListener (this); + addChildComponent (switchToHostButton); + + Rectangle screenSize = Desktop::getInstance().getDisplays().getMainDisplay().userArea; + setSize (screenSize.getWidth(), screenSize.getHeight()); + + resized(); + + startTimerHz (60); + } + + //============================================================================== + void paint (Graphics& g) override + { + g.fillAll (Colours::darkgrey); + } + + void resized() override + { + auto area = getBounds().reduced (10); + + gainSlider.setBounds (area.removeFromLeft (60)); + + for (auto& meter : meters) + { + area.removeFromLeft (10); + meter.setBounds (area.removeFromLeft (20)); + } + + area.removeFromLeft (20); + transportText.setBounds (area.removeFromTop (120)); + + auto navigationArea = area.removeFromTop (buttonSize); + rewindButton.setTopLeftPosition (navigationArea.getPosition()); + navigationArea.removeFromLeft (buttonSize + 10); + playButton.setTopLeftPosition (navigationArea.getPosition()); + navigationArea.removeFromLeft (buttonSize + 10); + recordButton.setTopLeftPosition (navigationArea.getPosition()); + + area.removeFromTop (30); + + auto appSwitchArea = area.removeFromTop (buttonSize); + switchToHostButtonLabel.setBounds (appSwitchArea.removeFromLeft (100)); + appSwitchArea.removeFromLeft (5); + switchToHostButton.setBounds (appSwitchArea.removeFromLeft (buttonSize)); + } + +private: + //============================================================================== + // Called from the audio thread. + void handleNewMeterValue (int channel, float value) override + { + meters[(size_t) channel].update (value); + } + + //============================================================================== + void timerCallback () override + { + auto timeInfoSuccess = processor.updateCurrentTimeInfoFromHost (lastPosInfo); + transportText.setVisible (timeInfoSuccess); + if (timeInfoSuccess) + updateTransportTextDisplay(); + + updateTransportButtonsDisplay(); + + updateSwitchToHostDisplay(); + } + + //============================================================================== + void buttonClicked (Button* b) override + { + auto playHead = processor.getPlayHead(); + if (playHead != nullptr && playHead->canControlTransport()) + { + if (b == &rewindButton) + { + playHead->transportRewind(); + } + else if (b == &playButton) + { + playHead->transportPlay(! lastPosInfo.isPlaying); + } + else if (b == &recordButton) + { + playHead->transportRecord (! lastPosInfo.isRecording); + } + else if (b == &switchToHostButton) + { + PluginHostType hostType; + + hostType.switchToHostApplication(); + } + } + } + + //============================================================================== + // quick-and-dirty function to format a timecode string + String timeToTimecodeString (double seconds) + { + auto millisecs = roundToInt (seconds * 1000.0); + auto absMillisecs = std::abs (millisecs); + + return String::formatted ("%02d:%02d:%02d.%03d", + millisecs / 360000, + (absMillisecs / 60000) % 60, + (absMillisecs / 1000) % 60, + absMillisecs % 1000); + } + + // A quick-and-dirty function to format a bars/beats string. + String quarterNotePositionToBarsBeatsString (double quarterNotes, int numerator, int denominator) + { + if (numerator == 0 || denominator == 0) + return "1|1|000"; + + auto quarterNotesPerBar = (numerator * 4 / denominator); + auto beats = (fmod (quarterNotes, quarterNotesPerBar) / quarterNotesPerBar) * numerator; + + auto bar = ((int) quarterNotes) / quarterNotesPerBar + 1; + auto beat = ((int) beats) + 1; + auto ticks = ((int) (fmod (beats, 1.0) * 960.0 + 0.5)); + + return String::formatted ("%d|%d|%03d", bar, beat, ticks); + } + + void updateTransportTextDisplay() + { + MemoryOutputStream displayText; + + displayText << "[" << SystemStats::getJUCEVersion() << "]\n" + << String (lastPosInfo.bpm, 2) << " bpm\n" + << lastPosInfo.timeSigNumerator << '/' << lastPosInfo.timeSigDenominator << "\n" + << timeToTimecodeString (lastPosInfo.timeInSeconds) << "\n" + << quarterNotePositionToBarsBeatsString (lastPosInfo.ppqPosition, + lastPosInfo.timeSigNumerator, + lastPosInfo.timeSigDenominator) << "\n"; + + if (lastPosInfo.isRecording) + displayText << "(recording)"; + else if (lastPosInfo.isPlaying) + displayText << "(playing)"; + + transportText.setText (displayText.toString(), dontSendNotification); + } + + void updateTransportButtonsDisplay() + { + auto visible = processor.getPlayHead() != nullptr + && processor.getPlayHead()->canControlTransport(); + + if (rewindButton.isVisible() != visible) + { + rewindButton.setVisible (visible); + playButton.setVisible (visible); + recordButton.setVisible (visible); + } + + if (visible) + { + Colour playColour = lastPosInfo.isPlaying ? Colours::green : defaultButtonColour; + playButton.setColours (playColour, playColour, playColour); + playButton.repaint(); + + Colour recordColour = lastPosInfo.isRecording ? Colours::red : defaultButtonColour; + recordButton.setColours (recordColour, recordColour, recordColour); + recordButton.repaint(); + } + } + + void updateSwitchToHostDisplay() + { + PluginHostType hostType; + const bool visible = hostType.isInterAppAudioConnected(); + + if (switchToHostButtonLabel.isVisible() != visible) + { + switchToHostButtonLabel.setVisible (visible); + switchToHostButton.setVisible (visible); + if (visible) { + auto icon = hostType.getHostIcon (buttonSize); + switchToHostButton.setImages(false, true, true, + icon, 1.0, Colours::transparentBlack, + icon, 1.0, Colours::transparentBlack, + icon, 1.0, Colours::transparentBlack); + } + } + } + + IAAEffectProcessor& processor; + AudioProcessorValueTreeState& parameters; + + const int buttonSize = 30; + const Colour defaultButtonColour = Colours::lightgrey; + ShapeButton rewindButton {"Rewind", defaultButtonColour, defaultButtonColour, defaultButtonColour}; + ShapeButton playButton {"Play", defaultButtonColour, defaultButtonColour, defaultButtonColour}; + ShapeButton recordButton {"Record", defaultButtonColour, defaultButtonColour, defaultButtonColour}; + + Slider gainSlider; + AudioProcessorValueTreeState::SliderAttachment gainAttachment = {parameters, "gain", gainSlider}; + + std::array meters; + + ImageButton switchToHostButton; + Label transportText, switchToHostButtonLabel; + Image hostImage; + + AudioPlayHead::CurrentPositionInfo lastPosInfo; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IAAEffectEditor) +}; + + +#endif // IAAEFFECTEDITOR_H_INCLUDED diff --git a/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectProcessor.cpp b/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectProcessor.cpp new file mode 100644 index 0000000000..ae65414bb6 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectProcessor.cpp @@ -0,0 +1,169 @@ +#include "IAAEffectProcessor.h" +#include "IAAEffectEditor.h" + + +IAAEffectProcessor::IAAEffectProcessor() + : AudioProcessor (BusesProperties() + .withInput ("Input", AudioChannelSet::stereo(), true) + .withOutput ("Output", AudioChannelSet::stereo(), true)), + parameters (*this, nullptr) +{ + parameters.createAndAddParameter ("gain", + "Gain", + String(), + NormalisableRange (0.0f, 1.0f), + (float) (1.0 / 3.14), + nullptr, + nullptr); + + parameters.state = ValueTree (Identifier ("InterAppAudioEffect")); +} + +IAAEffectProcessor::~IAAEffectProcessor() +{ +} + +//============================================================================== +const String IAAEffectProcessor::getName() const +{ + return JucePlugin_Name; +} + +bool IAAEffectProcessor::acceptsMidi() const +{ + return false; +} + +bool IAAEffectProcessor::producesMidi() const +{ + return false; +} + +double IAAEffectProcessor::getTailLengthSeconds() const +{ + return 0.0; +} + +int IAAEffectProcessor::getNumPrograms() +{ + return 1; +} + +int IAAEffectProcessor::getCurrentProgram() +{ + return 0; +} + +void IAAEffectProcessor::setCurrentProgram (int) +{ +} + +const String IAAEffectProcessor::getProgramName (int) +{ + return String(); +} + +void IAAEffectProcessor::changeProgramName (int, const String&) +{ +} + +//============================================================================== +void IAAEffectProcessor::prepareToPlay (double, int) +{ + previousGain = *parameters.getRawParameterValue ("gain"); +} + +void IAAEffectProcessor::releaseResources() +{ +} + +bool IAAEffectProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const +{ + if (layouts.getMainInputChannelSet() != AudioChannelSet::stereo()) + return false; + + if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) + return false; + + return true; +} + +void IAAEffectProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer&) +{ + const float gain = *parameters.getRawParameterValue ("gain"); + + const int totalNumInputChannels = getTotalNumInputChannels(); + const int totalNumOutputChannels = getTotalNumOutputChannels(); + + const int numSamples = buffer.getNumSamples(); + + for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i) + buffer.clear (i, 0, buffer.getNumSamples()); + + // Apply the gain to the samples using a ramp to avoid discontinuities in + // the audio between processed buffers. + for (int channel = 0; channel < totalNumInputChannels; ++channel) + { + buffer.applyGainRamp (channel, 0, numSamples, previousGain, gain); + + meterListeners.call (&IAAEffectProcessor::MeterListener::handleNewMeterValue, + channel, + buffer.getMagnitude (channel, 0, numSamples)); + } + + previousGain = gain; + + // Now ask the host for the current time so we can store it to be displayed later. + updateCurrentTimeInfoFromHost (lastPosInfo); +} + +//============================================================================== +bool IAAEffectProcessor::hasEditor() const +{ + return true; +} + +AudioProcessorEditor* IAAEffectProcessor::createEditor() +{ + return new IAAEffectEditor (*this, parameters); +} + +//============================================================================== +void IAAEffectProcessor::getStateInformation (MemoryBlock& destData) +{ + auto xml = std::unique_ptr (parameters.state.createXml()); + copyXmlToBinary (*xml, destData); +} + +void IAAEffectProcessor::setStateInformation (const void* data, int sizeInBytes) +{ + auto xmlState = std::unique_ptr (getXmlFromBinary (data, sizeInBytes)); + if (xmlState.get() != nullptr) + if (xmlState->hasTagName (parameters.state.getType())) + parameters.state = ValueTree::fromXml (*xmlState); +} + +bool IAAEffectProcessor::updateCurrentTimeInfoFromHost (AudioPlayHead::CurrentPositionInfo &posInfo) +{ + if (AudioPlayHead* ph = getPlayHead()) + { + AudioPlayHead::CurrentPositionInfo newTime; + + if (ph->getCurrentPosition (newTime)) + { + posInfo = newTime; // Successfully got the current time from the host. + return true; + } + } + + // If the host fails to provide the current time, we'll just reset our copy to a default. + lastPosInfo.resetToDefault(); + + return false; +} + +//============================================================================== +AudioProcessor* JUCE_CALLTYPE createPluginFilter() +{ + return new IAAEffectProcessor(); +} diff --git a/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectProcessor.h b/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectProcessor.h new file mode 100644 index 0000000000..779ed17961 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Source/IAAEffectProcessor.h @@ -0,0 +1,78 @@ +#ifndef PLUGINPROCESSOR_H_INCLUDED +#define PLUGINPROCESSOR_H_INCLUDED + +#include "../JuceLibraryCode/JuceHeader.h" + +#include + + +// A simple Inter-App Audio plug-in with a gain control and some meters. +class IAAEffectProcessor : public AudioProcessor +{ +public: + IAAEffectProcessor(); + ~IAAEffectProcessor(); + + //============================================================================== + void prepareToPlay (double sampleRate, int samplesPerBlock) override; + void releaseResources() override; + + bool isBusesLayoutSupported (const BusesLayout& layouts) const override; + + void processBlock (AudioSampleBuffer&, MidiBuffer&) override; + + //============================================================================== + AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; + + //============================================================================== + const String getName() const override; + + bool acceptsMidi() const override; + bool producesMidi() const override; + double getTailLengthSeconds() const override; + + //============================================================================== + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram (int index) override; + const String getProgramName (int index) override; + void changeProgramName (int index, const String& newName) override; + + //============================================================================== + void getStateInformation (MemoryBlock& destData) override; + void setStateInformation (const void* data, int sizeInBytes) override; + + //============================================================================== + bool updateCurrentTimeInfoFromHost (AudioPlayHead::CurrentPositionInfo&); + + // Allow an IAAAudioProcessorEditor to register as a listener to receive new + // meter values directly from the audio thread. + struct MeterListener + { + virtual ~MeterListener() {}; + + virtual void handleNewMeterValue (int, float) = 0; + }; + + void addMeterListener (MeterListener& listener) { meterListeners.add (&listener); }; + void removeMeterListener (MeterListener& listener) { meterListeners.remove (&listener); }; + + +private: + //============================================================================== + AudioProcessorValueTreeState parameters; + float previousGain = 0.0; + std::array meterValues = { { 0, 0 } }; + + // This keeps a copy of the last set of timing info that was acquired during an + // audio callback - the UI component will display this. + AudioPlayHead::CurrentPositionInfo lastPosInfo; + + ListenerList meterListeners; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IAAEffectProcessor) +}; + + +#endif // PLUGINPROCESSOR_H_INCLUDED diff --git a/examples/PlugInSamples/InterAppAudioEffect/Source/SimpleMeter.h b/examples/PlugInSamples/InterAppAudioEffect/Source/SimpleMeter.h new file mode 100644 index 0000000000..9547193536 --- /dev/null +++ b/examples/PlugInSamples/InterAppAudioEffect/Source/SimpleMeter.h @@ -0,0 +1,97 @@ +#ifndef SIMPLEMETER_H_INCLUDED +#define SIMPLEMETER_H_INCLUDED + +#include "../JuceLibraryCode/JuceHeader.h" + +// A very simple decaying meter. +class SimpleMeter : public Component, + private Timer +{ +public: + SimpleMeter() + { + startTimerHz (30); + } + + //============================================================================== + void paint (Graphics& g) override + { + g.fillAll(Colours::transparentBlack); + + auto area = g.getClipBounds(); + g.setColour (Colours::skyblue); + g.fillRoundedRectangle(area.toFloat(), 6.0); + + auto unfilledHeight = area.getHeight() * (1.0 - level); + g.reduceClipRegion (area.getX(), area.getY(), + area.getWidth(), (int) unfilledHeight); + g.setColour (Colours::grey); + g.fillRoundedRectangle(area.toFloat(), 6.0); + } + + void resized() override {} + + //============================================================================== + // Called from the audio thread. + void update (float newLevel) + { + // We don't care if maxLevel gets set to zero (in timerCallback) between the + // load and the assignment. + maxLevel = jmax (maxLevel.load(), newLevel); + } + +private: + //============================================================================== + void timerCallback() override + { + auto callbackLevel = maxLevel.exchange (0.0); + + auto decayFactor = 0.95; + if (callbackLevel > level) + level = callbackLevel; + else if (level > 0.001) + level *= decayFactor; + else + level = 0; + + repaint(); + } + + std::atomic maxLevel {0.0}; + float level = 0; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimpleMeter) +}; + +#if JUCE_PROJUCER_LIVE_BUILD + +// Animate the meter in the Projucer live build. +struct MockSimpleMeter : public Component, + private Timer +{ + MockSimpleMeter() + { + addAndMakeVisible (meter); + resized(); + startTimerHz (100); + } + + void paint (Graphics&) override {} + + void resized() override + { + meter.setBounds (getBounds()); + } + + void timerCallback() override + { + meter.update (std::pow (randomNumberGenerator.nextFloat(), 2)); + } + + SimpleMeter meter; + Random randomNumberGenerator; +}; + +#endif + +#endif // SIMPLEMETER_H_INCLUDED diff --git a/extras/Projucer/Source/Project Saving/jucer_ProjectExport_XCode.h b/extras/Projucer/Source/Project Saving/jucer_ProjectExport_XCode.h index 4318d3f4c2..b41e931c9c 100644 --- a/extras/Projucer/Source/Project Saving/jucer_ProjectExport_XCode.h +++ b/extras/Projucer/Source/Project Saving/jucer_ProjectExport_XCode.h @@ -732,10 +732,14 @@ public: attributes << "DevelopmentTeam = " << developmentTeamID << "; "; const int inAppPurchasesEnabled = (owner.iOS && owner.isInAppPurchasesEnabled()) ? 1 : 0; + const int interAppAudioEnabled = (owner.iOS + && type == Target::StandalonePlugIn + && owner.getProject().shouldEnableIAA()) ? 1 : 0; const int sandboxEnabled = (type == Target::AudioUnitv3PlugIn ? 1 : 0); attributes << "SystemCapabilities = {"; attributes << "com.apple.InAppPurchase = { enabled = " << inAppPurchasesEnabled << "; }; "; + attributes << "com.apple.InterAppAudio = { enabled = " << interAppAudioEnabled << "; }; "; attributes << "com.apple.Sandbox = { enabled = " << sandboxEnabled << "; }; "; attributes << "}; };"; @@ -953,8 +957,10 @@ public: s.add ("SEPARATE_STRIP = YES"); } - if (owner.project.getProjectType().isAudioPlugin() && type == Target::AudioUnitv3PlugIn && owner.isOSX()) - s.add (String ("CODE_SIGN_ENTITLEMENTS = \"") + owner.getEntitlementsFileName() + String ("\"")); + if (owner.project.getProjectType().isAudioPlugin()) + if ((owner.isOSX() && type == Target::AudioUnitv3PlugIn) + || (owner.isiOS() && type == Target::StandalonePlugIn)) + s.add (String ("CODE_SIGN_ENTITLEMENTS = \"") + owner.getEntitlementsFileName() + String ("\"")); defines = mergePreprocessorDefs (defines, owner.getAllPreprocessorDefs (config, type)); @@ -1112,14 +1118,36 @@ public: if (owner.settings ["UIStatusBarHidden"] && type != AudioUnitv3PlugIn) addPlistDictionaryKeyBool (dict, "UIStatusBarHidden", true); - if (owner.iOS && type != AudioUnitv3PlugIn) + if (owner.iOS) { - // Forcing full screen disables the split screen feature and prevents error ITMS-90475 - addPlistDictionaryKeyBool (dict, "UIRequiresFullScreen", true); - addPlistDictionaryKeyBool (dict, "UIStatusBarHidden", true); + if (type != AudioUnitv3PlugIn) + { + // Forcing full screen disables the split screen feature and prevents error ITMS-90475 + addPlistDictionaryKeyBool (dict, "UIRequiresFullScreen", true); + addPlistDictionaryKeyBool (dict, "UIStatusBarHidden", true); - addIosScreenOrientations (dict); - addIosBackgroundModes (dict); + addIosScreenOrientations (dict); + addIosBackgroundModes (dict); + } + + if (type == StandalonePlugIn && owner.getProject().shouldEnableIAA()) + { + XmlElement audioComponentsPlistKey ("key"); + audioComponentsPlistKey.addTextElement ("AudioComponents"); + + dict->addChildElement (new XmlElement (audioComponentsPlistKey)); + + XmlElement audioComponentsPlistEntry ("array"); + XmlElement* audioComponentsDict = audioComponentsPlistEntry.createNewChildElement ("dict"); + + addPlistDictionaryKey (audioComponentsDict, "name", owner.project.getIAAPluginName()); + addPlistDictionaryKey (audioComponentsDict, "manufacturer", owner.project.getPluginManufacturerCode().toString().trim().substring (0, 4)); + addPlistDictionaryKey (audioComponentsDict, "type", owner.project.getIAATypeCode()); + addPlistDictionaryKey (audioComponentsDict, "subtype", owner.project.getPluginCode().toString().trim().substring (0, 4)); + addPlistDictionaryKeyInt (audioComponentsDict, "version", owner.project.getVersionAsHexInteger()); + + dict->addChildElement (new XmlElement (audioComponentsPlistEntry)); + } } for (auto& e : xcodeExtraPListEntries) @@ -1500,8 +1528,9 @@ private: void addFilesAndGroupsToProject (StringArray& topLevelGroupIDs) const { - if (! isiOS() && project.getProjectType().isAudioPlugin()) - topLevelGroupIDs.add (addEntitlementsFile()); + StringArray entitlements = getEntitlements(); + if (! entitlements.isEmpty()) + topLevelGroupIDs.add (addEntitlementsFile (entitlements)); for (auto& group : getAllGroups()) if (group.getNumChildren() > 0) @@ -2188,20 +2217,41 @@ private: return project.getProjectFilenameRoot() + String (".entitlements"); } - String addEntitlementsFile() const + StringArray getEntitlements() const { - const char* sandboxEntitlement = - "" - "" - "" - "" - " com.apple.security.app-sandbox" - " " - "" - ""; + StringArray keys; + if (project.getProjectType().isAudioPlugin()) + { + if (isiOS()) + { + if (project.shouldEnableIAA()) + keys.add ("inter-app-audio"); + } + else + { + keys.add ("com.apple.security.app-sandbox"); + } + } + return keys; + } + + String addEntitlementsFile (StringArray keys) const + { + String content = + "\n" + "\n" + "\n" + "\n"; + for (auto& key : keys) + { + content += "\t" + key + "\n" + "\t\n"; + } + content += "\n" + "\n"; File entitlementsFile = getTargetFolder().getChildFile (getEntitlementsFileName()); - overwriteFileIfDifferentOrThrow (entitlementsFile, sandboxEntitlement); + overwriteFileIfDifferentOrThrow (entitlementsFile, content); RelativePath plistPath (entitlementsFile, getTargetFolder(), RelativePath::buildTargetFolder); return addFile (plistPath, false, false, false, false, nullptr); diff --git a/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.cpp b/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.cpp index 2ca0f9f4a7..7b86286de9 100644 --- a/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.cpp +++ b/extras/Projucer/Source/Project Saving/jucer_ProjectSaver.cpp @@ -80,6 +80,7 @@ void ProjectSaver::writePluginCharacteristicsFile() flags.set ("JucePlugin_Build_RTAS", valueToBool (project.getShouldBuildRTASAsValue())); flags.set ("JucePlugin_Build_AAX", valueToBool (project.getShouldBuildAAXAsValue())); flags.set ("JucePlugin_Build_STANDALONE", valueToBool (project.getShouldBuildStandalonePluginAsValue())); + flags.set ("JucePlugin_Enable_IAA", valueToBool (project.getShouldEnableIAAAsValue())); flags.set ("JucePlugin_Name", valueToStringLiteral (project.getPluginName())); flags.set ("JucePlugin_Desc", valueToStringLiteral (project.getPluginDesc())); flags.set ("JucePlugin_Manufacturer", valueToStringLiteral (project.getPluginManufacturer())); @@ -114,6 +115,9 @@ void ProjectSaver::writePluginCharacteristicsFile() flags.set ("JucePlugin_AAXCategory", project.getPluginAAXCategory().toString()); flags.set ("JucePlugin_AAXDisableBypass", valueToBool (project.getPluginAAXBypassDisabled())); flags.set ("JucePlugin_AAXDisableMultiMono", valueToBool (project.getPluginAAXMultiMonoDisabled())); + flags.set ("JucePlugin_IAAType", valueToCharLiteral (project.getIAATypeCode())); + flags.set ("JucePlugin_IAASubType", "JucePlugin_PluginCode"); + flags.set ("JucePlugin_IAAName", project.getIAAPluginName().quoted()); { String plugInChannelConfig = project.getPluginChannelConfigs().toString(); diff --git a/extras/Projucer/Source/Project/jucer_Project.cpp b/extras/Projucer/Source/Project/jucer_Project.cpp index 1d30292872..042b19c7d8 100644 --- a/extras/Projucer/Source/Project/jucer_Project.cpp +++ b/extras/Projucer/Source/Project/jucer_Project.cpp @@ -153,6 +153,7 @@ void Project::setMissingAudioPluginDefaultValues() setValueIfVoid (getShouldBuildRTASAsValue(), false); setValueIfVoid (getShouldBuildAAXAsValue(), false); setValueIfVoid (getShouldBuildStandalonePluginAsValue(), false); + setValueIfVoid (getShouldEnableIAAAsValue(), false); setValueIfVoid (getPluginName(), getTitle()); setValueIfVoid (getPluginDesc(), getTitle()); @@ -629,6 +630,9 @@ void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) "Whether the project should produce an AAX plugin."); props.add (new BooleanPropertyComponent (getShouldBuildStandalonePluginAsValue(), "Build Standalone Plug-In", "Enabled"), "Whether the project should produce a standalone version of your plugin."); + props.add (new BooleanPropertyComponent (getShouldEnableIAAAsValue(), "Enable Inter-App Audio", "Enabled"), + "Whether a standalone plug-in should be an Inter-App Audio app. You should also enable the audio " + "background capability in the iOS exporter."); props.add (new TextPropertyComponent (getPluginName(), "Plugin Name", 128, false), "The name of your plugin (keep it short!)"); @@ -1258,6 +1262,34 @@ String Project::getAUMainTypeCode() return s; } +String Project::getIAATypeCode() +{ + String s; + if (getPluginWantsMidiInput().getValue()) + { + if (getPluginIsSynth().getValue()) + s = "auri"; + else + s = "aurm"; + } + else + { + if (getPluginIsSynth().getValue()) + s = "aurg"; + else + s = "aurx"; + } + return s; +} + +String Project::getIAAPluginName() +{ + String s = getPluginManufacturer().toString(); + s << ": "; + s << getPluginName().toString(); + return s; +} + String Project::getPluginVSTCategoryString() { String s (getPluginVSTCategory().toString().trim()); diff --git a/extras/Projucer/Source/Project/jucer_Project.h b/extras/Projucer/Source/Project/jucer_Project.h index 06cd9251c2..b0c03a8311 100644 --- a/extras/Projucer/Source/Project/jucer_Project.h +++ b/extras/Projucer/Source/Project/jucer_Project.h @@ -130,6 +130,7 @@ public: Value getShouldBuildRTASAsValue() { return getProjectValue ("buildRTAS"); } Value getShouldBuildAAXAsValue() { return getProjectValue ("buildAAX"); } Value getShouldBuildStandalonePluginAsValue() { return getProjectValue ("buildStandalone");} + Value getShouldEnableIAAAsValue() { return getProjectValue ("enableIAA"); } bool shouldBuildVST() const { return getProjectVar ("buildVST"); } bool shouldBuildVST3() const { return getProjectVar ("buildVST3"); } @@ -138,6 +139,7 @@ public: bool shouldBuildRTAS() const { return getProjectVar ("buildRTAS"); } bool shouldBuildAAX() const { return getProjectVar ("buildAAX"); } bool shouldBuildStandalonePlugin() const { return getProjectVar ("buildStandalone"); } + bool shouldEnableIAA() const { return getProjectVar ("enableIAA"); } //============================================================================== Value getPluginName() { return getProjectValue ("pluginName"); } @@ -163,6 +165,8 @@ public: String getPluginRTASCategoryCode(); String getAUMainTypeString(); String getAUMainTypeCode(); + String getIAATypeCode(); + String getIAAPluginName(); String getPluginVSTCategoryString(); bool isAUPluginHost(); diff --git a/modules/juce_audio_processors/processors/juce_AudioPlayHead.h b/modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h similarity index 88% rename from modules/juce_audio_processors/processors/juce_AudioPlayHead.h rename to modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h index 6eb0139937..96b2d83f6f 100644 --- a/modules/juce_audio_processors/processors/juce_AudioPlayHead.h +++ b/modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h @@ -137,4 +137,16 @@ public: multithreading issues if it's not called on the audio thread. */ virtual bool getCurrentPosition (CurrentPositionInfo& result) = 0; + + /** Returns true if this object can control the transport. */ + virtual bool canControlTransport() { return false; }; + + /** Starts or stops the audio. */ + virtual void transportPlay (bool shouldStartPlaying) { ignoreUnused (shouldStartPlaying); }; + + /** Starts or stops recording the audio. */ + virtual void transportRecord (bool shouldStartRecording) { ignoreUnused (shouldStartRecording); }; + + /** Rewinds the audio. */ + virtual void transportRewind() {}; }; diff --git a/modules/juce_audio_basics/juce_audio_basics.h b/modules/juce_audio_basics/juce_audio_basics.h index 4f033bd0da..24fac78df5 100644 --- a/modules/juce_audio_basics/juce_audio_basics.h +++ b/modules/juce_audio_basics/juce_audio_basics.h @@ -101,5 +101,6 @@ namespace juce #include "sources/juce_ReverbAudioSource.h" #include "sources/juce_ToneGeneratorAudioSource.h" #include "synthesisers/juce_Synthesiser.h" +#include "audio_play_head/juce_AudioPlayHead.h" } diff --git a/modules/juce_audio_devices/juce_audio_devices.cpp b/modules/juce_audio_devices/juce_audio_devices.cpp index a4b079c0ce..f2d832c88f 100644 --- a/modules/juce_audio_devices/juce_audio_devices.cpp +++ b/modules/juce_audio_devices/juce_audio_devices.cpp @@ -182,6 +182,7 @@ namespace juce //============================================================================== #elif JUCE_IOS + #include "native/juce_ios_Audio.h" #include "native/juce_ios_Audio.cpp" #include "native/juce_mac_CoreMidi.cpp" diff --git a/modules/juce_audio_devices/juce_audio_devices.h b/modules/juce_audio_devices/juce_audio_devices.h index cac19bc90b..5c3b2d22d6 100644 --- a/modules/juce_audio_devices/juce_audio_devices.h +++ b/modules/juce_audio_devices/juce_audio_devices.h @@ -62,6 +62,10 @@ #include #include +#if JUCE_MODULE_AVAILABLE_juce_gui_extra +#include +#endif + //============================================================================== /** Config: JUCE_ASIO Enables ASIO audio devices (MS Windows only). @@ -147,12 +151,12 @@ namespace juce { -#include "audio_io/juce_AudioIODevice.h" -#include "audio_io/juce_AudioIODeviceType.h" -#include "audio_io/juce_SystemAudioVolume.h" #include "midi_io/juce_MidiInput.h" #include "midi_io/juce_MidiMessageCollector.h" #include "midi_io/juce_MidiOutput.h" +#include "audio_io/juce_AudioIODevice.h" +#include "audio_io/juce_AudioIODeviceType.h" +#include "audio_io/juce_SystemAudioVolume.h" #include "sources/juce_AudioSourcePlayer.h" #include "sources/juce_AudioTransportSource.h" #include "audio_io/juce_AudioDeviceManager.h" diff --git a/modules/juce_audio_devices/native/juce_ios_Audio.cpp b/modules/juce_audio_devices/native/juce_ios_Audio.cpp index e39b80cb7d..5c4b03772a 100644 --- a/modules/juce_audio_devices/native/juce_ios_Audio.cpp +++ b/modules/juce_audio_devices/native/juce_ios_Audio.cpp @@ -210,35 +210,24 @@ static void logNSError (NSError* e) #define JUCE_NSERROR_CHECK(X) { NSError* error = nil; X; logNSError (error); } +#if JUCE_MODULE_AVAILABLE_juce_graphics +#include +#endif //============================================================================== -class iOSAudioIODevice : public AudioIODevice +class iOSAudioIODevice::Pimpl : public AudioPlayHead { public: - iOSAudioIODevice (const String& deviceName) - : AudioIODevice (deviceName, iOSAudioDeviceName) - { - sessionHolder->activeDevices.add (this); - updateSampleRateAndAudioInput(); - } - - ~iOSAudioIODevice() - { - sessionHolder->activeDevices.removeFirstMatchingValue (this); - close(); - } - - StringArray getOutputChannelNames() override + Pimpl (iOSAudioIODevice& ioDevice) + : owner (ioDevice) { - return { "Left", "Right" }; + sessionHolder->activeDevices.add (&owner); } - StringArray getInputChannelNames() override + ~Pimpl() { - if (audioInputIsAvailable) - return { "Left", "Right" }; - - return {}; + sessionHolder->activeDevices.removeFirstMatchingValue (&owner); + owner.close(); } static void setAudioSessionActive (bool enabled) @@ -255,7 +244,7 @@ public: return session.sampleRate; } - Array getAvailableSampleRates() override + Array getAvailableSampleRates() { Array rates; @@ -279,7 +268,7 @@ public: rate = jmax (rate, supportedRate); } - trySampleRate (getCurrentSampleRate()); + trySampleRate (owner.getCurrentSampleRate()); AudioUnitAddPropertyListener (audioUnit, kAudioUnitProperty_StreamFormat, @@ -295,7 +284,7 @@ public: return rates; } - Array getAvailableBufferSizes() override + Array getAvailableBufferSizes() { Array r; @@ -305,43 +294,33 @@ public: return r; } - int getDefaultBufferSize() override - { - #if TARGET_IPHONE_SIMULATOR - return 512; - #else - return 256; - #endif - } - String open (const BigInteger& inputChannelsWanted, const BigInteger& outputChannelsWanted, - double targetSampleRate, int bufferSize) override + double targetSampleRate, int bufferSize) { close(); - lastError.clear(); - preferredBufferSize = bufferSize <= 0 ? getDefaultBufferSize() - : bufferSize; + owner.lastError.clear(); + owner.preferredBufferSize = bufferSize <= 0 ? owner.getDefaultBufferSize() : bufferSize; // xxx set up channel mapping - activeOutputChans = outputChannelsWanted; - activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false); - numOutputChannels = activeOutputChans.countNumberOfSetBits(); - monoOutputChannelNumber = activeOutputChans.findNextSetBit (0); + owner.activeOutputChans = outputChannelsWanted; + owner.activeOutputChans.setRange (2, owner.activeOutputChans.getHighestBit(), false); + owner.numOutputChannels = owner.activeOutputChans.countNumberOfSetBits(); + monoOutputChannelNumber = owner.activeOutputChans.findNextSetBit (0); - activeInputChans = inputChannelsWanted; - activeInputChans.setRange (2, activeInputChans.getHighestBit(), false); - numInputChannels = activeInputChans.countNumberOfSetBits(); - monoInputChannelNumber = activeInputChans.findNextSetBit (0); + owner.activeInputChans = inputChannelsWanted; + owner.activeInputChans.setRange (2, owner.activeInputChans.getHighestBit(), false); + owner.numInputChannels = owner.activeInputChans.countNumberOfSetBits(); + monoInputChannelNumber = owner.activeInputChans.findNextSetBit (0); setAudioSessionActive (true); // Set the session category & options: auto session = [AVAudioSession sharedInstance]; - const bool useInputs = (numInputChannels > 0 && audioInputIsAvailable); + const bool useInputs = (owner.numInputChannels > 0 && owner.audioInputIsAvailable); NSString* category = (useInputs ? AVAudioSessionCategoryPlayAndRecord : AVAudioSessionCategoryPlayback); @@ -357,26 +336,26 @@ public: // Set the sample rate trySampleRate (targetSampleRate); - updateSampleRateAndAudioInput(); + owner.updateSampleRateAndAudioInput(); updateCurrentBufferSize(); - prepareFloatBuffers (actualBufferSize); + prepareFloatBuffers (owner.actualBufferSize); - isRunning = true; + owner.isRunning = true; handleRouteChange ("Started AudioUnit"); - lastError = (audioUnit != 0 ? "" : "Couldn't open the device"); + owner.lastError = (audioUnit != 0 ? "" : "Couldn't open the device"); setAudioSessionActive (true); - return lastError; + return owner.lastError; } - void close() override + void close() { - if (isRunning) + if (owner.isRunning) { - isRunning = false; + owner.isRunning = false; if (audioUnit != 0) { @@ -389,40 +368,28 @@ public: } } - bool isOpen() override { return isRunning; } - - int getCurrentBufferSizeSamples() override { return actualBufferSize; } - double getCurrentSampleRate() override { return sampleRate; } - int getCurrentBitDepth() override { return 16; } - - BigInteger getActiveOutputChannels() const override { return activeOutputChans; } - BigInteger getActiveInputChannels() const override { return activeInputChans; } - - int getOutputLatencyInSamples() override { return roundToInt (getCurrentSampleRate() * [AVAudioSession sharedInstance].outputLatency); } - int getInputLatencyInSamples() override { return roundToInt (getCurrentSampleRate() * [AVAudioSession sharedInstance].inputLatency); } - - void start (AudioIODeviceCallback* newCallback) override + void start (AudioIODeviceCallback* newCallback) { - if (isRunning && callback != newCallback) + if (owner.isRunning && owner.callback != newCallback) { if (newCallback != nullptr) - newCallback->audioDeviceAboutToStart (this); + newCallback->audioDeviceAboutToStart (&owner); const ScopedLock sl (callbackLock); - callback = newCallback; + owner.callback = newCallback; } } - void stop() override + void stop() { - if (isRunning) + if (owner.isRunning) { AudioIODeviceCallback* lastCallback; { const ScopedLock sl (callbackLock); - lastCallback = callback; - callback = nullptr; + lastCallback = owner.callback; + owner.callback = nullptr; } if (lastCallback != nullptr) @@ -430,10 +397,7 @@ public: } } - bool isPlaying() override { return isRunning && callback != nullptr; } - String getLastError() override { return lastError; } - - bool setAudioPreprocessingEnabled (bool enable) override + bool setAudioPreprocessingEnabled (bool enable) { auto session = [AVAudioSession sharedInstance]; @@ -446,12 +410,169 @@ public: return session.mode == mode; } + //============================================================================== + bool canControlTransport() override { return owner.interAppAudioConnected; } + + void transportPlay (bool shouldSartPlaying) override + { + if (! canControlTransport()) + return; + + HostCallbackInfo callbackInfo; + fillHostCallbackInfo (callbackInfo); + + Boolean hostIsPlaying = NO; + OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData, + &hostIsPlaying, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + jassert (err == noErr); + + if (hostIsPlaying != shouldSartPlaying) + handleAudioTransportEvent (kAudioUnitRemoteControlEvent_TogglePlayPause); + } + + void transportRecord (bool shouldStartRecording) override + { + if (! canControlTransport()) + return; + + HostCallbackInfo callbackInfo; + fillHostCallbackInfo (callbackInfo); + + Boolean hostIsRecording = NO; + OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData, + NULL, + &hostIsRecording, + NULL, + NULL, + NULL, + NULL, + NULL); + jassert (err == noErr); + + if (hostIsRecording != shouldStartRecording) + handleAudioTransportEvent (kAudioUnitRemoteControlEvent_ToggleRecord); + } + + void transportRewind() override + { + if (canControlTransport()) + handleAudioTransportEvent (kAudioUnitRemoteControlEvent_Rewind); + } + + bool getCurrentPosition (CurrentPositionInfo& result) override + { + if (! canControlTransport()) + return false; + + zerostruct (result); + + HostCallbackInfo callbackInfo; + fillHostCallbackInfo (callbackInfo); + + if (callbackInfo.hostUserData == nullptr) + return false; + + Boolean hostIsPlaying = NO; + Boolean hostIsRecording = NO; + Float64 hostCurrentSampleInTimeLine = 0; + Boolean hostIsCycling = NO; + Float64 hostCycleStartBeat = 0; + Float64 hostCycleEndBeat = 0; + OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData, + &hostIsPlaying, + &hostIsRecording, + NULL, + &hostCurrentSampleInTimeLine, + &hostIsCycling, + &hostCycleStartBeat, + &hostCycleEndBeat); + if (err == kAUGraphErr_CannotDoInCurrentContext) + return false; + + jassert (err == noErr); + + result.timeInSamples = (int64) hostCurrentSampleInTimeLine; + result.isPlaying = hostIsPlaying; + result.isRecording = hostIsRecording; + result.isLooping = hostIsCycling; + result.ppqLoopStart = hostCycleStartBeat; + result.ppqLoopEnd = hostCycleEndBeat; + + result.timeInSeconds = result.timeInSamples / owner.sampleRate; + + Float64 hostBeat = 0; + Float64 hostTempo = 0; + err = callbackInfo.beatAndTempoProc (callbackInfo.hostUserData, + &hostBeat, + &hostTempo); + jassert (err == noErr); + + result.ppqPosition = hostBeat; + result.bpm = hostTempo; + + Float32 hostTimeSigNumerator = 0; + UInt32 hostTimeSigDenominator = 0; + Float64 hostCurrentMeasureDownBeat = 0; + err = callbackInfo.musicalTimeLocationProc (callbackInfo.hostUserData, + NULL, + &hostTimeSigNumerator, + &hostTimeSigDenominator, + &hostCurrentMeasureDownBeat); + jassert (err == noErr); + + result.ppqPositionOfLastBarStart = hostCurrentMeasureDownBeat; + result.timeSigNumerator = (int) hostTimeSigNumerator; + result.timeSigDenominator = (int) hostTimeSigDenominator; + + result.frameRate = AudioPlayHead::fpsUnknown; + + return true; + } + + //============================================================================== + #if JUCE_MODULE_AVAILABLE_juce_gui_basics + Image getIcon (int size) + { + if (owner.interAppAudioConnected) + { + UIImage* hostUIImage = AudioOutputUnitGetHostIcon (audioUnit, size); + if (hostUIImage != nullptr) + return juce_createImageFromUIImage (hostUIImage); + } + return Image(); + } + #endif + + void switchApplication() + { + if (! owner.interAppAudioConnected) + return; + + CFURLRef hostUrl; + UInt32 dataSize = sizeof (hostUrl); + OSStatus err = AudioUnitGetProperty(audioUnit, + kAudioUnitProperty_PeerURL, + kAudioUnitScope_Global, + 0, + &hostUrl, + &dataSize); + if (err == noErr) + [[UIApplication sharedApplication] openURL:(NSURL*)hostUrl]; + } + + //============================================================================== void invokeAudioDeviceErrorCallback (const String& reason) { const ScopedLock sl (callbackLock); - if (callback != nullptr) - callback->audioDeviceError (reason); + if (owner.callback != nullptr) + owner.callback->audioDeviceError (reason); } void handleStatusChange (bool enabled, const char* reason) @@ -460,7 +581,7 @@ public: JUCE_IOS_AUDIO_LOG ("handleStatusChange: enabled: " << (int) enabled << ", reason: " << reason); - isRunning = enabled; + owner.isRunning = enabled; setAudioSessionActive (enabled); if (enabled) @@ -480,10 +601,10 @@ public: fixAudioRouteIfSetToReceiver(); - if (isRunning) + if (owner.isRunning) { invokeAudioDeviceErrorCallback (reason); - updateSampleRateAndAudioInput(); + owner.updateSampleRateAndAudioInput(); updateCurrentBufferSize(); createAudioUnit(); @@ -496,29 +617,72 @@ public: AudioOutputUnitStart (audioUnit); } - if (callback != nullptr) + if (owner.callback != nullptr) + { + owner.callback->audioDeviceStopped(); + owner.callback->audioDeviceAboutToStart (&owner); + } + } + } + + void handleAudioUnitPropertyChange (AudioUnit, + AudioUnitPropertyID propertyID, + AudioUnitScope, + AudioUnitElement) + { + const ScopedLock myScopedLock (callbackLock); + + switch (propertyID) + { + case kAudioUnitProperty_IsInterAppConnected: return handleInterAppAudioConnectionChange(); + default: return; + } + } + + void handleInterAppAudioConnectionChange() + { + UInt32 connected; + UInt32 dataSize = sizeof (connected); + OSStatus err = AudioUnitGetProperty (audioUnit, kAudioUnitProperty_IsInterAppConnected, + kAudioUnitScope_Global, 0, &connected, &dataSize); + jassert (err == noErr); + + JUCE_IOS_AUDIO_LOG ("handleInterAppAudioConnectionChange: " << connected ? "connected" + : "disconnected"); + + if (connected != owner.interAppAudioConnected) + { + const ScopedLock myScopedLock (callbackLock); + + owner.interAppAudioConnected = connected; + + UIApplicationState appstate = [UIApplication sharedApplication].applicationState; + bool inForeground = (appstate != UIApplicationStateBackground); + + if (owner.interAppAudioConnected || inForeground) { - callback->audioDeviceStopped(); - callback->audioDeviceAboutToStart (this); + setAudioSessionActive (true); + AudioOutputUnitStart (audioUnit); + + if (owner.callback != nullptr) + owner.callback->audioDeviceAboutToStart (&owner); + } + else if (! inForeground) + { + AudioOutputUnitStop (audioUnit); + setAudioSessionActive (false); } } } private: //============================================================================== + iOSAudioIODevice& owner; SharedResourcePointer sessionHolder; CriticalSection callbackLock; - NSTimeInterval sampleRate = 0; - int numInputChannels = 2, numOutputChannels = 2; - int preferredBufferSize = 0, actualBufferSize = 0; - bool isRunning = false; - String lastError; AudioStreamBasicDescription format; AudioUnit audioUnit {}; - bool audioInputIsAvailable = false; - AudioIODeviceCallback* callback = nullptr; - BigInteger activeOutputChans, activeInputChans; AudioSampleBuffer floatData; float* inputChannels[3]; @@ -527,17 +691,17 @@ private: void prepareFloatBuffers (int bufferSize) { - if (numInputChannels + numOutputChannels > 0) + if (owner.numInputChannels + owner.numOutputChannels > 0) { - floatData.setSize (numInputChannels + numOutputChannels, bufferSize); + floatData.setSize (owner.numInputChannels + owner.numOutputChannels, bufferSize); zeromem (inputChannels, sizeof (inputChannels)); zeromem (outputChannels, sizeof (outputChannels)); - for (int i = 0; i < numInputChannels; ++i) + for (int i = 0; i < owner.numInputChannels; ++i) inputChannels[i] = floatData.getWritePointer (i); - for (int i = 0; i < numOutputChannels; ++i) - outputChannels[i] = floatData.getWritePointer (i + numInputChannels); + for (int i = 0; i < owner.numOutputChannels; ++i) + outputChannels[i] = floatData.getWritePointer (i + owner.numInputChannels); } } @@ -547,21 +711,21 @@ private: { OSStatus err = noErr; - if (audioInputIsAvailable && numInputChannels > 0) + if (owner.audioInputIsAvailable && owner.numInputChannels > 0) err = AudioUnitRender (audioUnit, flags, time, 1, numFrames, data); const ScopedTryLock stl (callbackLock); - if (stl.isLocked() && callback != nullptr) + if (stl.isLocked() && owner.callback != nullptr) { if ((int) numFrames > floatData.getNumSamples()) prepareFloatBuffers ((int) numFrames); - if (audioInputIsAvailable && numInputChannels > 0) + if (owner.audioInputIsAvailable && owner.numInputChannels > 0) { short* shortData = (short*) data->mBuffers[0].mData; - if (numInputChannels >= 2) + if (owner.numInputChannels >= 2) { for (UInt32 i = 0; i < numFrames; ++i) { @@ -583,17 +747,17 @@ private: } else { - for (int i = numInputChannels; --i >= 0;) + for (int i = owner.numInputChannels; --i >= 0;) zeromem (inputChannels[i], sizeof (float) * numFrames); } - callback->audioDeviceIOCallback ((const float**) inputChannels, numInputChannels, - outputChannels, numOutputChannels, (int) numFrames); + owner.callback->audioDeviceIOCallback ((const float**) inputChannels, owner.numInputChannels, + outputChannels, owner.numOutputChannels, (int) numFrames); short* const shortData = (short*) data->mBuffers[0].mData; int n = 0; - if (numOutputChannels >= 2) + if (owner.numOutputChannels >= 2) { for (UInt32 i = 0; i < numFrames; ++i) { @@ -601,7 +765,7 @@ private: shortData [n++] = (short) (outputChannels[1][i] * 32767.0f); } } - else if (numOutputChannels == 1) + else if (owner.numOutputChannels == 1) { for (UInt32 i = 0; i < numFrames; ++i) { @@ -623,25 +787,13 @@ private: return err; } - void updateSampleRateAndAudioInput() - { - auto session = [AVAudioSession sharedInstance]; - sampleRate = session.sampleRate; - audioInputIsAvailable = session.isInputAvailable; - actualBufferSize = roundToInt (sampleRate * session.IOBufferDuration); - - JUCE_IOS_AUDIO_LOG ("AVAudioSession: sampleRate: " << sampleRate - << " Hz, audioInputAvailable: " << (int) audioInputIsAvailable - << ", buffer size: " << actualBufferSize); - } - void updateCurrentBufferSize() { - NSTimeInterval bufferDuration = sampleRate > 0 ? (NSTimeInterval) ((preferredBufferSize + 1) / sampleRate) : 0.0; + NSTimeInterval bufferDuration = owner.sampleRate > 0 ? (NSTimeInterval) ((owner.preferredBufferSize + 1) / owner.sampleRate) : 0.0; JUCE_NSERROR_CHECK ([[AVAudioSession sharedInstance] setPreferredIOBufferDuration: bufferDuration error: &error]); - updateSampleRateAndAudioInput(); + owner.updateSampleRateAndAudioInput(); } //============================================================================== @@ -649,7 +801,7 @@ private: UInt32 /*busNumber*/, UInt32 numFrames, AudioBufferList* data) { - return static_cast (client)->process (flags, time, numFrames, data); + return static_cast (client)->process (flags, time, numFrames, data); } //============================================================================== @@ -687,7 +839,32 @@ private: if (audioUnit == 0) return false; - if (numInputChannels > 0) + #if JucePlugin_Enable_IAA + AudioComponentDescription appDesc; + appDesc.componentType = JucePlugin_IAAType; + appDesc.componentSubType = JucePlugin_IAASubType; + appDesc.componentManufacturer = JucePlugin_ManufacturerCode; + appDesc.componentFlags = 0; + appDesc.componentFlagsMask = 0; + OSStatus err = AudioOutputUnitPublish (&appDesc, + CFSTR(JucePlugin_IAAName), + JucePlugin_VersionCode, + audioUnit); + + // This assert will be hit if the Inter-App Audio entitlement has not + // been enabled, or the description being published with + // AudioOutputUnitPublish is different from any in the AudioComponents + // array in this application's .plist file. + jassert (err == noErr); + + err = AudioUnitAddPropertyListener(audioUnit, + kAudioUnitProperty_IsInterAppConnected, + audioUnitPropertyChangeDispatcher, + this); + jassert (err == noErr); + #endif + + if (owner.numInputChannels > 0) { const UInt32 one = 1; AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof (one)); @@ -721,7 +898,7 @@ private: if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, &dataSize) == noErr - && dataSize == sizeof (framesPerSlice) && static_cast (framesPerSlice) != actualBufferSize) + && dataSize == sizeof (framesPerSlice) && static_cast (framesPerSlice) != owner.actualBufferSize) { prepareFloatBuffers (static_cast (framesPerSlice)); } @@ -731,6 +908,26 @@ private: return true; } + void fillHostCallbackInfo (HostCallbackInfo& callbackInfo) + { + zerostruct (callbackInfo); + UInt32 dataSize = sizeof (HostCallbackInfo); + OSStatus err = AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_HostCallbacks, + kAudioUnitScope_Global, + 0, + &callbackInfo, + &dataSize); + jassert (err == noErr); + } + + void handleAudioTransportEvent (AudioUnitRemoteControlEvent event) + { + OSStatus err = AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_RemoteControlToHost, + kAudioUnitScope_Global, 0, &event, sizeof (event)); + jassert (err == noErr); + } + // If the routing is set to go through the receiver (i.e. the speaker, but quiet), this re-routes it // to make it loud. Needed because by default when using an input + output, the output is kept quiet. static void fixAudioRouteIfSetToReceiver() @@ -768,14 +965,14 @@ private: 0, &desc, &dataSize); - if (desc.mSampleRate != getCurrentSampleRate()) + if (desc.mSampleRate != owner.getCurrentSampleRate()) { - updateSampleRateAndAudioInput(); + owner.updateSampleRateAndAudioInput(); const ScopedLock sl (callbackLock); - if (callback != nullptr) + if (owner.callback != nullptr) { - callback->audioDeviceStopped(); - callback->audioDeviceAboutToStart (this); + owner.callback->audioDeviceStopped(); + owner.callback->audioDeviceAboutToStart (&owner); } } } @@ -787,13 +984,91 @@ private: AudioUnitElement element) { if (scope == kAudioUnitScope_Output && element == 0) - static_cast (device)->handleStreamFormatChange(); + static_cast (device)->handleStreamFormatChange(); + } + + static void audioUnitPropertyChangeDispatcher (void* data, AudioUnit unit, AudioUnitPropertyID propertyID, + AudioUnitScope scope, AudioUnitElement element) + { + Pimpl* device = (Pimpl*)data; + device->handleAudioUnitPropertyChange (unit, propertyID, scope, element); + } + + void handleMidiMessage (MidiMessage msg) + { + if (owner.messageCollector != nullptr) + owner.messageCollector->addMessageToQueue (msg); + } + + static void midiEventCallback (void *client, UInt32 status, UInt32 data1, UInt32 data2, UInt32) + { + return static_cast (client)->handleMidiMessage (MidiMessage ((int) status, + (int) data1, + (int) data2, + Time::getMillisecondCounter() / 1000.0)); } - JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice) + JUCE_DECLARE_NON_COPYABLE (Pimpl) }; +//============================================================================== +iOSAudioIODevice::iOSAudioIODevice (const String& deviceName) + : AudioIODevice (deviceName, iOSAudioDeviceName), + #if TARGET_IPHONE_SIMULATOR + defaultBufferSize (512), + #else + defaultBufferSize (256), + #endif + sampleRate (0), numInputChannels (2), numOutputChannels (2), + preferredBufferSize (0), actualBufferSize (0), isRunning (false), + audioInputIsAvailable (false), interAppAudioConnected (false), + callback (nullptr), messageCollector (nullptr), + pimpl (new Pimpl (*this)) +{ + updateSampleRateAndAudioInput(); +} + +//============================================================================== +int iOSAudioIODevice::getOutputLatencyInSamples() { return roundToInt (sampleRate * [AVAudioSession sharedInstance].outputLatency); } +int iOSAudioIODevice::getInputLatencyInSamples() { return roundToInt (sampleRate * [AVAudioSession sharedInstance].inputLatency); } + +//============================================================================== +AudioPlayHead* iOSAudioIODevice::getAudioPlayHead() const { return pimpl; } +void iOSAudioIODevice::close() { pimpl->close(); } +void iOSAudioIODevice::start (AudioIODeviceCallback* callbackToUse) { pimpl->start (callbackToUse); } +void iOSAudioIODevice::stop() { pimpl->stop(); } +Array iOSAudioIODevice::getAvailableSampleRates() { return pimpl->getAvailableSampleRates(); } +Array iOSAudioIODevice::getAvailableBufferSizes() { return pimpl->getAvailableBufferSizes(); } +bool iOSAudioIODevice::setAudioPreprocessingEnabled (bool enabled) { return pimpl->setAudioPreprocessingEnabled (enabled); } +void iOSAudioIODevice::switchApplication() { return pimpl->switchApplication(); } + +//============================================================================== +void iOSAudioIODevice::handleStatusChange (bool enabled, const char* reason) { pimpl->handleStatusChange (enabled, reason); } +void iOSAudioIODevice::handleRouteChange (const char* reason) { pimpl->handleRouteChange (reason); } + +#if JUCE_MODULE_AVAILABLE_juce_gui_basics +Image iOSAudioIODevice::getIcon (int size) { return pimpl->getIcon (size); } +#endif + +//============================================================================== +String iOSAudioIODevice::open (const BigInteger& inChans, const BigInteger& outChans, double requestedSampleRate, int requestedBufferSize) +{ + return pimpl->open (inChans, outChans, requestedSampleRate, requestedBufferSize); +} + +void iOSAudioIODevice::updateSampleRateAndAudioInput() +{ + auto session = [AVAudioSession sharedInstance]; + sampleRate = session.sampleRate; + audioInputIsAvailable = session.isInputAvailable; + actualBufferSize = roundToInt (sampleRate * session.IOBufferDuration); + + JUCE_IOS_AUDIO_LOG ("AVAudioSession: sampleRate: " << sampleRate + << " Hz, audioInputAvailable: " << (int) audioInputIsAvailable + << ", buffer size: " << actualBufferSize); +} + //============================================================================== class iOSAudioIODeviceType : public AudioIODeviceType { diff --git a/modules/juce_audio_devices/native/juce_ios_Audio.h b/modules/juce_audio_devices/native/juce_ios_Audio.h new file mode 100644 index 0000000000..8964935b85 --- /dev/null +++ b/modules/juce_audio_devices/native/juce_ios_Audio.h @@ -0,0 +1,107 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2016 - ROLI Ltd. + + Permission is granted to use this software under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license/ + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, + OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. + + ----------------------------------------------------------------------------- + + To release a closed-source product which uses other parts of JUCE not + licensed under the ISC terms, commercial licenses are available: visit + www.juce.com for more information. + + ============================================================================== +*/ + +#pragma once + +class iOSAudioIODeviceType; + +class iOSAudioIODevice : public AudioIODevice +{ +public: + //============================================================================== + String open (const BigInteger&, const BigInteger&, double, int) override; + void close() override; + + void start (AudioIODeviceCallback*) override; + void stop() override; + + Array getAvailableSampleRates() override; + Array getAvailableBufferSizes() override; + bool setAudioPreprocessingEnabled (bool) override; + + //============================================================================== + bool isPlaying() override { return isRunning && callback != nullptr; } + bool isOpen() override { return isRunning; } + String getLastError() override { return lastError; }; + + //============================================================================== + StringArray getOutputChannelNames() override { return { "Left", "Right" }; } + StringArray getInputChannelNames() override { return audioInputIsAvailable ? getOutputChannelNames() : StringArray(); } + int getDefaultBufferSize() override { return defaultBufferSize; } + int getCurrentBufferSizeSamples() override { return actualBufferSize; } + double getCurrentSampleRate() override { return sampleRate; } + int getCurrentBitDepth() override { return 16; } + BigInteger getActiveOutputChannels() const override { return activeOutputChans; } + BigInteger getActiveInputChannels() const override { return activeInputChans; } + int getOutputLatencyInSamples() override; + int getInputLatencyInSamples() override; + + //============================================================================== + void handleStatusChange (bool enabled, const char* reason); + void handleRouteChange (const char* reason); + + //============================================================================== + virtual void setMidiMessageCollector (MidiMessageCollector* collector) { messageCollector = collector; } + virtual AudioPlayHead* getAudioPlayHead() const; + + //============================================================================== + virtual bool isInterAppAudioConnected() const { return interAppAudioConnected; } + #if JUCE_MODULE_AVAILABLE_juce_gui_basics + virtual Image getIcon (int size); + #endif + virtual void switchApplication(); +private: + //============================================================================== + void updateSampleRateAndAudioInput(); + + //============================================================================== + friend class iOSAudioIODeviceType; + iOSAudioIODevice (const String& deviceName); + + //============================================================================== + const int defaultBufferSize; + double sampleRate; + int numInputChannels, numOutputChannels; + int preferredBufferSize, actualBufferSize; + bool isRunning; + String lastError; + + bool audioInputIsAvailable, interAppAudioConnected; + BigInteger activeOutputChans, activeInputChans; + + AudioIODeviceCallback* callback; + MidiMessageCollector* messageCollector; + + class Pimpl; + friend class Pimpl; + ScopedPointer pimpl; + + JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice) +}; diff --git a/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm index ca0d8ae5a4..631a62e28f 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm @@ -1431,5 +1431,14 @@ private: - (void)viewDidLayoutSubviews { return cpp->viewDidLayoutSubviews(); } @end +//============================================================================== +#if JUCE_IOS +bool JUCE_CALLTYPE juce_isInterAppAudioConnected() { return false; } +void JUCE_CALLTYPE juce_switchToHostApplication() {} +#if JUCE_MODULE_AVAILABLE_juce_gui_basics +Image JUCE_CALLTYPE juce_getIAAHostIcon (int) { return Image(); } +#endif +#endif + #pragma clang diagnostic pop #endif diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp index d80723e7ff..490de16807 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp @@ -43,6 +43,10 @@ extern AudioProcessor* JUCE_CALLTYPE createPluginFilter(); namespace juce { + #if JucePlugin_Enable_IAA && JUCE_IOS + #include "../../juce_audio_devices/native/juce_ios_Audio.h" + #endif + #include "juce_StandaloneFilterWindow.h" } @@ -107,4 +111,31 @@ protected: ScopedPointer mainWindow; }; +#if JucePlugin_Build_STANDALONE && JUCE_IOS + +bool JUCE_CALLTYPE juce_isInterAppAudioConnected() +{ + if (auto holder = StandalonePluginHolder::getInstance()) + return holder->isInterAppAudioConnected(); + + return false; +} + +void JUCE_CALLTYPE juce_switchToHostApplication() +{ + if (auto holder = StandalonePluginHolder::getInstance()) + holder->switchToHostApplication(); +} + +#if JUCE_MODULE_AVAILABLE_juce_gui_basics +Image JUCE_CALLTYPE juce_getIAAHostIcon (int size) +{ + if (auto holder = StandalonePluginHolder::getInstance()) + return holder->getIAAHostIcon (size); + + return Image(); +} +#endif +#endif + #endif diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index df6866c085..8b11566188 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -182,6 +182,14 @@ public: void startPlaying() { player.setProcessor (processor); + + #if JucePlugin_Enable_IAA && JUCE_IOS + if (auto device = dynamic_cast (deviceManager.getCurrentAudioDevice())) + { + processor->setPlayHead (device->getAudioPlayHead()); + device->setMidiMessageCollector (&player.getMidiMessageCollector()); + } + #endif } void stopPlaying() @@ -260,6 +268,41 @@ public: } } + //============================================================================== + void switchToHostApplication() + { + #if JUCE_IOS + if (auto device = dynamic_cast (deviceManager.getCurrentAudioDevice())) + device->switchApplication(); + #endif + } + + bool isInterAppAudioConnected() + { + #if JUCE_IOS + if (auto device = dynamic_cast (deviceManager.getCurrentAudioDevice())) + return device->isInterAppAudioConnected(); + #endif + + return false; + } + + #if JUCE_MODULE_AVAILABLE_juce_gui_basics + Image getIAAHostIcon (int size) + { + #if JUCE_IOS && JucePlugin_Enable_IAA + if (auto device = dynamic_cast (deviceManager.getCurrentAudioDevice())) + return device->getIcon (size); + #else + ignoreUnused (size); + #endif + + return Image(); + } + #endif + + static StandalonePluginHolder* getInstance(); + //============================================================================== OptionalScopedPointer settings; ScopedPointer processor; @@ -328,7 +371,6 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandalonePluginHolder) }; - //============================================================================== /** A class that can be used to run a simple standalone application containing your filter. @@ -481,6 +523,8 @@ public: optionsButton.setBounds (8, 6, 60, getTitleBarHeight() - 8); } + virtual StandalonePluginHolder* getPluginHolder() { return pluginHolder; } + ScopedPointer pluginHolder; private: @@ -489,3 +533,20 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandaloneFilterWindow) }; + +StandalonePluginHolder* StandalonePluginHolder::getInstance() +{ + #if JucePlugin_Enable_IAA || JucePlugin_Build_STANDALONE + if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) + { + Desktop& desktop (Desktop::getInstance()); + const int numTopLevelWindows = desktop.getNumComponents(); + + for (int i = 0; i < numTopLevelWindows; ++i) + if (auto window = dynamic_cast (desktop.getComponent (i))) + return window->getPluginHolder(); + } + #endif + + return nullptr; +} diff --git a/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h b/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h index 8e34504fac..935c988986 100644 --- a/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h +++ b/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h @@ -169,6 +169,14 @@ public: return "Unknown"; } + //============================================================================== + bool isInterAppAudioConnected() const; + void switchToHostApplication() const; + + #if JUCE_MODULE_AVAILABLE_juce_gui_basics + Image getHostIcon (int size) const; + #endif + //============================================================================== static String getHostPath() { diff --git a/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp b/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp index 80afc6c3f6..dea2574436 100644 --- a/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp +++ b/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp @@ -149,6 +149,15 @@ bool JUCE_API handleManufacturerSpecificVST2Opcode (int32 index, pointer_sized_i */ extern AudioProcessor* JUCE_CALLTYPE createPluginFilter(); +#if JucePlugin_Enable_IAA && JucePlugin_Build_STANDALONE && JUCE_IOS && (! JUCE_USE_CUSTOM_AU3_STANDALONE_APP) +extern bool JUCE_CALLTYPE juce_isInterAppAudioConnected(); +extern void JUCE_CALLTYPE juce_switchToHostApplication(); + +#if JUCE_MODULE_AVAILABLE_juce_gui_basics +extern Image JUCE_CALLTYPE juce_getIAAHostIcon (int); +#endif +#endif + AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType type) { AudioProcessor::setTypeOfNextNewPlugin (type); @@ -160,3 +169,46 @@ AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor: return pluginInstance; } + +bool PluginHostType::isInterAppAudioConnected() const +{ + #if JucePlugin_Enable_IAA && JucePlugin_Build_STANDALONE && JUCE_IOS && (! JUCE_USE_CUSTOM_AU3_STANDALONE_APP) + if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) + return juce_isInterAppAudioConnected(); + #endif + + return false; +} + +void PluginHostType::switchToHostApplication() const +{ + #if JucePlugin_Enable_IAA && JucePlugin_Build_STANDALONE && JUCE_IOS && (! JUCE_USE_CUSTOM_AU3_STANDALONE_APP) + if (getPluginLoadedAs() == AudioProcessor::wrapperType_Standalone) + juce_switchToHostApplication(); + #endif +} + +#if JUCE_MODULE_AVAILABLE_juce_gui_basics +namespace juce { + +extern Image JUCE_API getIconFromApplication (const String&, const int); + +Image PluginHostType::getHostIcon (int size) const +{ + ignoreUnused (size); + + #if JucePlugin_Enable_IAA && JucePlugin_Build_STANDALONE && JUCE_IOS && (! JUCE_USE_CUSTOM_AU3_STANDALONE_APP) + if (isInterAppAudioConnected()) + return juce_getIAAHostIcon (size); + #endif + + #if JUCE_MAC + String bundlePath (getHostPath().upToLastOccurrenceOf (".app", true, true)); + return getIconFromApplication (bundlePath, size); + #endif + + return Image(); +} + +} +#endif diff --git a/modules/juce_audio_processors/juce_audio_processors.h b/modules/juce_audio_processors/juce_audio_processors.h index 0ec754fa6a..dcb76df6e4 100644 --- a/modules/juce_audio_processors/juce_audio_processors.h +++ b/modules/juce_audio_processors/juce_audio_processors.h @@ -102,7 +102,6 @@ namespace juce { class AudioProcessor; -#include "processors/juce_AudioPlayHead.h" #include "processors/juce_AudioProcessorEditor.h" #include "processors/juce_AudioProcessorListener.h" #include "processors/juce_AudioProcessorParameter.h" diff --git a/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp b/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp index cf32f3a546..4c4e0c3da8 100644 --- a/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp +++ b/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp @@ -223,13 +223,23 @@ bool JPEGImageFormat::usesFileExtension (const File& f) { return f.hasFileExte bool JPEGImageFormat::canUnderstand (InputStream& in) { - const int bytesNeeded = 10; + const int bytesNeeded = 24; uint8 header [bytesNeeded]; - return in.read (header, bytesNeeded) == bytesNeeded + if (in.read (header, bytesNeeded) == bytesNeeded && header[0] == 0xff && header[1] == 0xd8 - && header[2] == 0xff; + && header[2] == 0xff) + return true; + + #if JUCE_USING_COREIMAGE_LOADER + return header[20] == 'j' + && header[21] == 'p' + && header[22] == '2' + && header[23] == ' '; + #endif + + return false; } #if JUCE_USING_COREIMAGE_LOADER diff --git a/modules/juce_graphics/juce_graphics.cpp b/modules/juce_graphics/juce_graphics.cpp index 50a5d3f151..84dbe01e4f 100644 --- a/modules/juce_graphics/juce_graphics.cpp +++ b/modules/juce_graphics/juce_graphics.cpp @@ -144,21 +144,25 @@ namespace juce #if JUCE_MAC || JUCE_IOS #include "native/juce_mac_Fonts.mm" #include "native/juce_mac_CoreGraphicsContext.mm" + #include "native/juce_mac_IconHelpers.cpp" #elif JUCE_WINDOWS #include "native/juce_win32_DirectWriteTypeface.cpp" #include "native/juce_win32_DirectWriteTypeLayout.cpp" #include "native/juce_win32_Fonts.cpp" + #include "native/juce_win32_IconHelpers.cpp" #if JUCE_DIRECT2D #include "native/juce_win32_Direct2DGraphicsContext.cpp" #endif #elif JUCE_LINUX #include "native/juce_linux_Fonts.cpp" + #include "native/juce_linux_IconHelpers.cpp" #elif JUCE_ANDROID #include "native/juce_android_GraphicsContext.cpp" #include "native/juce_android_Fonts.cpp" + #include "native/juce_android_IconHelpers.cpp" #endif } diff --git a/modules/juce_graphics/juce_graphics.h b/modules/juce_graphics/juce_graphics.h index 3a4f630d7c..c4b5defb43 100644 --- a/modules/juce_graphics/juce_graphics.h +++ b/modules/juce_graphics/juce_graphics.h @@ -41,7 +41,7 @@ dependencies: juce_events OSXFrameworks: Cocoa QuartzCore - iOSFrameworks: CoreGraphics CoreText QuartzCore + iOSFrameworks: CoreGraphics CoreImage CoreText QuartzCore linuxPackages: x11 xinerama xext freetype2 END_JUCE_MODULE_DECLARATION diff --git a/modules/juce_graphics/native/juce_android_IconHelpers.cpp b/modules/juce_graphics/native/juce_android_IconHelpers.cpp new file mode 100644 index 0000000000..2fffd5e192 --- /dev/null +++ b/modules/juce_graphics/native/juce_android_IconHelpers.cpp @@ -0,0 +1,28 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +Image JUCE_API getIconFromApplication (const String&, const int) +{ + return Image(); +} diff --git a/modules/juce_graphics/native/juce_linux_IconHelpers.cpp b/modules/juce_graphics/native/juce_linux_IconHelpers.cpp new file mode 100644 index 0000000000..2fffd5e192 --- /dev/null +++ b/modules/juce_graphics/native/juce_linux_IconHelpers.cpp @@ -0,0 +1,28 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +Image JUCE_API getIconFromApplication (const String&, const int) +{ + return Image(); +} diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm index 957d9cfa26..93fdaf6f0c 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm @@ -876,7 +876,6 @@ Image juce_loadWithCoreImage (InputStream& input) } #endif -#if JUCE_MAC Image juce_createImageFromCIImage (CIImage*, int, int); Image juce_createImageFromCIImage (CIImage* im, int w, int h) { @@ -904,4 +903,16 @@ CGContextRef juce_getImageContext (const Image& image) return 0; } +#if JUCE_IOS +Image juce_createImageFromUIImage (UIImage* img) +{ + CGImageRef image = [img CGImage]; + + Image retval (Image::ARGB, (int) CGImageGetWidth (image), (int) CGImageGetHeight (image), true); + CGContextRef ctx = juce_getImageContext (retval); + + CGContextDrawImage (ctx, CGRectMake (0.0f, 0.0f, CGImageGetWidth (image), CGImageGetHeight (image)), image); + + return retval; +} #endif diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h b/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h index e9fdeadad4..9c5551d454 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h @@ -55,3 +55,7 @@ namespace extern CGImageRef juce_createCoreGraphicsImage (const Image&, CGColorSpaceRef, bool mustOutliveSource); extern CGContextRef juce_getImageContext (const Image&); + +#if JUCE_IOS +extern Image juce_createImageFromUIImage (UIImage*); +#endif diff --git a/modules/juce_graphics/native/juce_mac_IconHelpers.cpp b/modules/juce_graphics/native/juce_mac_IconHelpers.cpp new file mode 100644 index 0000000000..a054093e9d --- /dev/null +++ b/modules/juce_graphics/native/juce_mac_IconHelpers.cpp @@ -0,0 +1,135 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +Image getIconFromIcnsFile (const File& icnsFile, const int size) +{ + FileInputStream stream (icnsFile); + if (! stream.openedOk()) + return {}; + + const int numHeaderSectionBytes = 4; + char headerSection [numHeaderSectionBytes]; + + if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes + || headerSection[0] != 'i' + || headerSection[1] != 'c' + || headerSection[2] != 'n' + || headerSection[3] != 's') + return {}; + + if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes) + return {}; + + const auto dataSize = juce::ByteOrder::bigEndianInt (headerSection); + if (dataSize <= 0) + return {}; + + OwnedArray internalFormats; + internalFormats.add (new PNGImageFormat()); + internalFormats.add (new JPEGImageFormat()); + + Array images; + auto maxWidth = 0; + auto maxWidthIndex = -1; + + while (stream.getPosition() < dataSize) + { + const auto sectionStart = stream.getPosition(); + + if (! stream.setPosition (sectionStart + 4)) + break; + + if (stream.read (headerSection, numHeaderSectionBytes) != numHeaderSectionBytes) + break; + + const auto sectionSize = ByteOrder::bigEndianInt (headerSection); + if (sectionSize <= 0) + break; + + const auto sectionDataStart = stream.getPosition(); + + for (auto* fmt : internalFormats) + { + if (fmt->canUnderstand (stream)) + { + stream.setPosition (sectionDataStart); + + images.add (fmt->decodeImage (stream)); + + const auto lastImageIndex = images.size() - 1; + const auto lastWidth = images.getReference (lastImageIndex).getWidth(); + if (lastWidth > maxWidth) + { + maxWidthIndex = lastImageIndex; + maxWidth = lastWidth; + } + } + + stream.setPosition (sectionDataStart); + } + + stream.setPosition (sectionStart + sectionSize); + } + + return maxWidthIndex == -1 ? juce::Image() + : images.getReference (maxWidthIndex).rescaled (size, size, Graphics::ResamplingQuality::highResamplingQuality); +} + +Image JUCE_API getIconFromApplication (const String& applicationPath, const int size) +{ + Image hostIcon; + + if (CFStringRef pathCFString = CFStringCreateWithCString (kCFAllocatorDefault, applicationPath.toRawUTF8(), kCFStringEncodingUTF8)) + { + if (CFURLRef url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, pathCFString, kCFURLPOSIXPathStyle, 1)) + { + if (CFBundleRef appBundle = CFBundleCreate (kCFAllocatorDefault, url)) + { + if (CFTypeRef infoValue = CFBundleGetValueForInfoDictionaryKey (appBundle, CFSTR("CFBundleIconFile"))) + { + if (CFGetTypeID (infoValue) == CFStringGetTypeID()) + { + CFStringRef iconFilename = reinterpret_cast (infoValue); + CFStringRef resourceURLSuffix = CFStringHasSuffix (iconFilename, CFSTR(".icns")) ? nullptr : CFSTR("icns"); + if (CFURLRef iconURL = CFBundleCopyResourceURL (appBundle, iconFilename, resourceURLSuffix, nullptr)) + { + if (CFStringRef iconPath = CFURLCopyFileSystemPath (iconURL, kCFURLPOSIXPathStyle)) + { + File icnsFile (CFStringGetCStringPtr (iconPath, CFStringGetSystemEncoding())); + hostIcon = getIconFromIcnsFile (icnsFile, size); + CFRelease (iconPath); + } + CFRelease (iconURL); + } + } + } + CFRelease (appBundle); + } + CFRelease (url); + } + CFRelease (pathCFString); + } + + return hostIcon; +} diff --git a/modules/juce_graphics/native/juce_win32_IconHelpers.cpp b/modules/juce_graphics/native/juce_win32_IconHelpers.cpp new file mode 100644 index 0000000000..2fffd5e192 --- /dev/null +++ b/modules/juce_graphics/native/juce_win32_IconHelpers.cpp @@ -0,0 +1,28 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2017 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +Image JUCE_API getIconFromApplication (const String&, const int) +{ + return Image(); +}