mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added Inter-App Audio capabilities to standalone plug-ins
This commit is contained in:
parent
00f57d43c5
commit
4c59a920b4
80 changed files with 2949 additions and 163 deletions
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist>
|
||||
<dict>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This app requires microphone input.</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>InterAppAudioEffect</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>InterAppAudioEffect</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>ROLI Ltd.</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
<key>AudioComponents</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>ROLI Ltd.: InterAppAudioEffect</string>
|
||||
<key>manufacturer</key>
|
||||
<string>ROLI</string>
|
||||
<key>type</key>
|
||||
<string>aurx</string>
|
||||
<key>subtype</key>
|
||||
<string>IAAE</string>
|
||||
<key>version</key>
|
||||
<integer>65536</integer>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>inter-app-audio</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -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 = "<group>"; };
|
||||
EB371D6195C6398C6F1946EF = {isa = PBXGroup; children = (
|
||||
9D54126CE5CE65025DE4742F, ); name = InterAppAudioEffect; sourceTree = "<group>"; };
|
||||
3CDCF2D2F9AA23710946CF21 = {isa = PBXGroup; children = (
|
||||
CB7EB47782C231D8D6CD52FD,
|
||||
C6F57BB192F1BC9BE7D82F99,
|
||||
6E90633D52FCA2BC0B99F9F2,
|
||||
50724579E5DD043CD53B0C95,
|
||||
51A5B253018FC02A6AFB7416,
|
||||
EBA214D367A10FDDC99E8922,
|
||||
2A2D7663F8BC39E97FF490E3,
|
||||
54EEC3679EBFF5E6C7B580F1,
|
||||
78F41A05666E3B38C9FDE9D3,
|
||||
C1507624A4C7CFDCE375CEB6,
|
||||
FEBA6F6C0A62E2749D6ACC88,
|
||||
59469A0541A1B91E7968B8FC, ); name = "Juce Modules"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
E1CFC4C60E9EC5DBE60DB32F = {isa = PBXGroup; children = (
|
||||
7B37ABD2C5B9FF909250C8DE,
|
||||
E5A657DE5A5B1516B3E35FA8, ); name = Resources; sourceTree = "<group>"; };
|
||||
BF7815807DD5B5FAF4BC3669 = {isa = PBXGroup; children = (
|
||||
67BBA32BE9EE1CAF8A105F6A,
|
||||
E43030B35C6CB127DC67FEE7,
|
||||
53BB9950BAA9E837613ED83B,
|
||||
212019C041EE17C23460CE02,
|
||||
C293562C310CB0B3259811F0,
|
||||
E4431E84242848EF9D250FC7,
|
||||
C43FC3A63342AA4CDE8F0906,
|
||||
AD9B42ED650058295A747510,
|
||||
F07FA71EC2B5FCA584FAA10B,
|
||||
41CB50701EE5BFDCE1F89BBA,
|
||||
B69C94CF64688C5270D8122C,
|
||||
82F310E23852E0C002F5A2D1, ); name = Frameworks; sourceTree = "<group>"; };
|
||||
196E6AA022E8A0902AB15281 = {isa = PBXGroup; children = (
|
||||
E9D6BA12BDD1947BDDAE08F7,
|
||||
873711620EC157BCCFFF80B1, ); name = Products; sourceTree = "<group>"; };
|
||||
EC01685A042C62251C5AF093 = {isa = PBXGroup; children = (
|
||||
3158E31C9E0DBE333E275FB1,
|
||||
EB371D6195C6398C6F1946EF,
|
||||
3CDCF2D2F9AA23710946CF21,
|
||||
C560791DA1D2E0CA6690BC9E,
|
||||
E1CFC4C60E9EC5DBE60DB32F,
|
||||
BF7815807DD5B5FAF4BC3669,
|
||||
196E6AA022E8A0902AB15281, ); name = Source; sourceTree = "<group>"; };
|
||||
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;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<JUCERPROJECT id="rgYEL2" name="InterAppAudioEffect" projectType="audioplug"
|
||||
version="1.0.0" bundleIdentifier="com.yourcompany.InterAppAudioEffect"
|
||||
includeBinaryInAppConfig="1" buildVST="0" buildVST3="0" buildAU="0"
|
||||
buildAUv3="0" buildRTAS="0" buildAAX="0" enableIAA="1" pluginName="InterAppAudioEffect"
|
||||
pluginDesc="InterAppAudioEffect" pluginManufacturer="ROLI Ltd."
|
||||
pluginManufacturerCode="ROLI" pluginCode="IAAE" pluginChannelConfigs=""
|
||||
pluginIsSynth="0" pluginWantsMidiIn="0" pluginProducesMidiOut="0"
|
||||
pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="InterAppAudioEffectAU"
|
||||
pluginRTASCategory="" aaxIdentifier="com.yourcompany.InterAppAudioEffect"
|
||||
pluginAAXCategory="AAX_ePlugInCategory_Dynamics" jucerVersion="4.3.1"
|
||||
companyName="ROLI Ltd." buildStandalone="1">
|
||||
<MAINGROUP id="BhTVmm" name="InterAppAudioEffect">
|
||||
<GROUP id="{79B2188B-B073-DD2F-F997-AFE1A88B5908}" name="Source">
|
||||
<FILE id="s4nZon" name="IAAEffectProcessor.h" compile="0" resource="0"
|
||||
file="Source/IAAEffectProcessor.h"/>
|
||||
<FILE id="yg8oqf" name="IAAEffectProcessor.cpp" compile="1" resource="0"
|
||||
file="Source/IAAEffectProcessor.cpp"/>
|
||||
<FILE id="CRAxnV" name="IAAEffectEditor.h" compile="0" resource="0"
|
||||
file="Source/IAAEffectEditor.h"/>
|
||||
<FILE id="xALLmD" name="SimpleMeter.h" compile="0" resource="0" file="Source/SimpleMeter.h"/>
|
||||
</GROUP>
|
||||
</MAINGROUP>
|
||||
<EXPORTFORMATS>
|
||||
<XCODE_IPHONE targetFolder="Builds/iOS" iosScreenOrientation="portraitlandscape"
|
||||
microphonePermissionNeeded="1" iosBackgroundAudio="1" extraCompilerFlags="-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">
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="InterAppAudioEffect"/>
|
||||
<CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="InterAppAudioEffect"/>
|
||||
</CONFIGURATIONS>
|
||||
<MODULEPATHS>
|
||||
<MODULEPATH id="juce_core" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_events" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_graphics" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_gui_basics" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_audio_basics" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_audio_devices" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_audio_formats" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_audio_processors" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_audio_plugin_client" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_audio_utils" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_data_structures" path="../../../modules"/>
|
||||
<MODULEPATH id="juce_gui_extra" path="../../../modules"/>
|
||||
</MODULEPATHS>
|
||||
</XCODE_IPHONE>
|
||||
</EXPORTFORMATS>
|
||||
<MODULES>
|
||||
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_core" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_events" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0"/>
|
||||
<MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0"/>
|
||||
</MODULES>
|
||||
<JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
|
||||
</JUCERPROJECT>
|
||||
|
|
@ -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
|
||||
|
|
@ -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 <juce_audio_basics/juce_audio_basics.h>
|
||||
#include <juce_audio_devices/juce_audio_devices.h>
|
||||
#include <juce_audio_formats/juce_audio_formats.h>
|
||||
#include <juce_audio_plugin_client/juce_audio_plugin_client.h>
|
||||
#include <juce_audio_processors/juce_audio_processors.h>
|
||||
#include <juce_audio_utils/juce_audio_utils.h>
|
||||
#include <juce_core/juce_core.h>
|
||||
#include <juce_data_structures/juce_data_structures.h>
|
||||
#include <juce_events/juce_events.h>
|
||||
#include <juce_graphics/juce_graphics.h>
|
||||
#include <juce_gui_basics/juce_gui_basics.h>
|
||||
#include <juce_gui_extra/juce_gui_extra.h>
|
||||
|
||||
|
||||
#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
|
||||
|
|
@ -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).
|
||||
|
|
@ -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 <juce_audio_basics/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 <juce_audio_basics/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 <juce_audio_devices/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 <juce_audio_devices/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 <juce_audio_formats/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 <juce_audio_formats/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_plugin_client/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 <juce_audio_processors/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 <juce_audio_processors/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 <juce_audio_utils/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 <juce_audio_utils/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 <juce_core/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 <juce_core/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 <juce_data_structures/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 <juce_data_structures/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 <juce_events/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 <juce_events/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 <juce_graphics/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 <juce_graphics/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 <juce_gui_basics/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 <juce_gui_basics/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 <juce_gui_extra/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 <juce_gui_extra/juce_gui_extra.mm>
|
||||
|
|
@ -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<int> 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<SimpleMeter, 2> meters;
|
||||
|
||||
ImageButton switchToHostButton;
|
||||
Label transportText, switchToHostButtonLabel;
|
||||
Image hostImage;
|
||||
|
||||
AudioPlayHead::CurrentPositionInfo lastPosInfo;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IAAEffectEditor)
|
||||
};
|
||||
|
||||
|
||||
#endif // IAAEFFECTEDITOR_H_INCLUDED
|
||||
|
|
@ -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<float> (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<XmlElement> (parameters.state.createXml());
|
||||
copyXmlToBinary (*xml, destData);
|
||||
}
|
||||
|
||||
void IAAEffectProcessor::setStateInformation (const void* data, int sizeInBytes)
|
||||
{
|
||||
auto xmlState = std::unique_ptr<XmlElement> (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();
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef PLUGINPROCESSOR_H_INCLUDED
|
||||
#define PLUGINPROCESSOR_H_INCLUDED
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
||||
// 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 <float, 2> 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<MeterListener> meterListeners;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IAAEffectProcessor)
|
||||
};
|
||||
|
||||
|
||||
#endif // PLUGINPROCESSOR_H_INCLUDED
|
||||
|
|
@ -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<float> 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
|
||||
|
|
@ -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,7 +957,9 @@ public:
|
|||
s.add ("SEPARATE_STRIP = YES");
|
||||
}
|
||||
|
||||
if (owner.project.getProjectType().isAudioPlugin() && type == Target::AudioUnitv3PlugIn && owner.isOSX())
|
||||
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,7 +1118,9 @@ public:
|
|||
if (owner.settings ["UIStatusBarHidden"] && type != AudioUnitv3PlugIn)
|
||||
addPlistDictionaryKeyBool (dict, "UIStatusBarHidden", true);
|
||||
|
||||
if (owner.iOS && type != AudioUnitv3PlugIn)
|
||||
if (owner.iOS)
|
||||
{
|
||||
if (type != AudioUnitv3PlugIn)
|
||||
{
|
||||
// Forcing full screen disables the split screen feature and prevents error ITMS-90475
|
||||
addPlistDictionaryKeyBool (dict, "UIRequiresFullScreen", true);
|
||||
|
|
@ -1122,6 +1130,26 @@ public:
|
|||
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)
|
||||
dict->addChildElement (new XmlElement (e));
|
||||
|
||||
|
|
@ -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 =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
|
||||
"<plist version=\"1.0\">"
|
||||
"<dict>"
|
||||
" <key>com.apple.security.app-sandbox</key>"
|
||||
" <true/>"
|
||||
"</dict>"
|
||||
"</plist>";
|
||||
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 =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
||||
"<plist version=\"1.0\">\n"
|
||||
"<dict>\n";
|
||||
for (auto& key : keys)
|
||||
{
|
||||
content += "\t<key>" + key + "</key>\n"
|
||||
"\t<true/>\n";
|
||||
}
|
||||
content += "</dict>\n"
|
||||
"</plist>\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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {};
|
||||
};
|
||||
|
|
@ -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"
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@
|
|||
#include <juce_events/juce_events.h>
|
||||
#include <juce_audio_basics/juce_audio_basics.h>
|
||||
|
||||
#if JUCE_MODULE_AVAILABLE_juce_gui_extra
|
||||
#include <juce_gui_extra/juce_gui_extra.h>
|
||||
#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"
|
||||
|
|
|
|||
|
|
@ -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 <juce_graphics/native/juce_mac_CoreGraphicsHelpers.h>
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
class iOSAudioIODevice : public AudioIODevice
|
||||
class iOSAudioIODevice::Pimpl : public AudioPlayHead
|
||||
{
|
||||
public:
|
||||
iOSAudioIODevice (const String& deviceName)
|
||||
: AudioIODevice (deviceName, iOSAudioDeviceName)
|
||||
Pimpl (iOSAudioIODevice& ioDevice)
|
||||
: owner (ioDevice)
|
||||
{
|
||||
sessionHolder->activeDevices.add (this);
|
||||
updateSampleRateAndAudioInput();
|
||||
sessionHolder->activeDevices.add (&owner);
|
||||
}
|
||||
|
||||
~iOSAudioIODevice()
|
||||
~Pimpl()
|
||||
{
|
||||
sessionHolder->activeDevices.removeFirstMatchingValue (this);
|
||||
close();
|
||||
}
|
||||
|
||||
StringArray getOutputChannelNames() override
|
||||
{
|
||||
return { "Left", "Right" };
|
||||
}
|
||||
|
||||
StringArray getInputChannelNames() override
|
||||
{
|
||||
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<double> getAvailableSampleRates() override
|
||||
Array<double> getAvailableSampleRates()
|
||||
{
|
||||
Array<double> 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<int> getAvailableBufferSizes() override
|
||||
Array<int> getAvailableBufferSizes()
|
||||
{
|
||||
Array<int> 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)
|
||||
{
|
||||
callback->audioDeviceStopped();
|
||||
callback->audioDeviceAboutToStart (this);
|
||||
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)
|
||||
{
|
||||
setAudioSessionActive (true);
|
||||
AudioOutputUnitStart (audioUnit);
|
||||
|
||||
if (owner.callback != nullptr)
|
||||
owner.callback->audioDeviceAboutToStart (&owner);
|
||||
}
|
||||
else if (! inForeground)
|
||||
{
|
||||
AudioOutputUnitStop (audioUnit);
|
||||
setAudioSessionActive (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
iOSAudioIODevice& owner;
|
||||
SharedResourcePointer<AudioSessionHolder> 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<iOSAudioIODevice*> (client)->process (flags, time, numFrames, data);
|
||||
return static_cast<Pimpl*> (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<int> (framesPerSlice) != actualBufferSize)
|
||||
&& dataSize == sizeof (framesPerSlice) && static_cast<int> (framesPerSlice) != owner.actualBufferSize)
|
||||
{
|
||||
prepareFloatBuffers (static_cast<int> (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<iOSAudioIODevice*> (device)->handleStreamFormatChange();
|
||||
static_cast<Pimpl*> (device)->handleStreamFormatChange();
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)
|
||||
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<Pimpl*> (client)->handleMidiMessage (MidiMessage ((int) status,
|
||||
(int) data1,
|
||||
(int) data2,
|
||||
Time::getMillisecondCounter() / 1000.0));
|
||||
}
|
||||
|
||||
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<double> iOSAudioIODevice::getAvailableSampleRates() { return pimpl->getAvailableSampleRates(); }
|
||||
Array<int> 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
|
||||
{
|
||||
|
|
|
|||
107
modules/juce_audio_devices/native/juce_ios_Audio.h
Normal file
107
modules/juce_audio_devices/native/juce_ios_Audio.h
Normal file
|
|
@ -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<double> getAvailableSampleRates() override;
|
||||
Array<int> 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> pimpl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<StandaloneFilterWindow> 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
|
||||
|
|
|
|||
|
|
@ -182,6 +182,14 @@ public:
|
|||
void startPlaying()
|
||||
{
|
||||
player.setProcessor (processor);
|
||||
|
||||
#if JucePlugin_Enable_IAA && JUCE_IOS
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
{
|
||||
processor->setPlayHead (device->getAudioPlayHead());
|
||||
device->setMidiMessageCollector (&player.getMidiMessageCollector());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void stopPlaying()
|
||||
|
|
@ -260,6 +268,41 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void switchToHostApplication()
|
||||
{
|
||||
#if JUCE_IOS
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
device->switchApplication();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isInterAppAudioConnected()
|
||||
{
|
||||
#if JUCE_IOS
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
return device->isInterAppAudioConnected();
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if JUCE_MODULE_AVAILABLE_juce_gui_basics
|
||||
Image getIAAHostIcon (int size)
|
||||
{
|
||||
#if JUCE_IOS && JucePlugin_Enable_IAA
|
||||
if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))
|
||||
return device->getIcon (size);
|
||||
#else
|
||||
ignoreUnused (size);
|
||||
#endif
|
||||
|
||||
return Image();
|
||||
}
|
||||
#endif
|
||||
|
||||
static StandalonePluginHolder* getInstance();
|
||||
|
||||
//==============================================================================
|
||||
OptionalScopedPointer<PropertySet> settings;
|
||||
ScopedPointer<AudioProcessor> 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<StandalonePluginHolder> 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<StandaloneFilterWindow*> (desktop.getComponent (i)))
|
||||
return window->getPluginHolder();
|
||||
}
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
28
modules/juce_graphics/native/juce_android_IconHelpers.cpp
Normal file
28
modules/juce_graphics/native/juce_android_IconHelpers.cpp
Normal file
|
|
@ -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();
|
||||
}
|
||||
28
modules/juce_graphics/native/juce_linux_IconHelpers.cpp
Normal file
28
modules/juce_graphics/native/juce_linux_IconHelpers.cpp
Normal file
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
135
modules/juce_graphics/native/juce_mac_IconHelpers.cpp
Normal file
135
modules/juce_graphics/native/juce_mac_IconHelpers.cpp
Normal file
|
|
@ -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<juce::ImageFileFormat> internalFormats;
|
||||
internalFormats.add (new PNGImageFormat());
|
||||
internalFormats.add (new JPEGImageFormat());
|
||||
|
||||
Array<Image> 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<CFStringRef> (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;
|
||||
}
|
||||
28
modules/juce_graphics/native/juce_win32_IconHelpers.cpp
Normal file
28
modules/juce_graphics/native/juce_win32_IconHelpers.cpp
Normal file
|
|
@ -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();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue