The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1647 lines
73KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../../juce_core/system/juce_TargetPlatform.h"
  20. #include "../utility/juce_CheckSettingMacros.h"
  21. #if JucePlugin_Build_AUv3
  22. #import <CoreAudioKit/CoreAudioKit.h>
  23. #import <AudioToolbox/AudioToolbox.h>
  24. #import <AVFoundation/AVFoundation.h>
  25. #if JUCE_MAC
  26. #if (! defined MAC_OS_X_VERSION_MIN_REQUIRED) || (! defined MAC_OS_X_VERSION_10_11) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11)
  27. #error AUv3 needs Deployment Target OS X 10.11 or higher to compile
  28. #endif
  29. #if (defined MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_13)
  30. #define JUCE_AUV3_MIDI_OUTPUT_SUPPORTED 1
  31. #define JUCE_AUV3_VIEW_CONFIG_SUPPORTED 1
  32. #endif
  33. #endif
  34. #if JUCE_IOS
  35. #if (! defined __IPHONE_OS_VERSION_MIN_REQUIRED) || (! defined __IPHONE_9_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
  36. #error AUv3 needs Deployment Target iOS 9.0 or higher to compile
  37. #endif
  38. #if (defined __IPHONE_11_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_11_0)
  39. #define JUCE_AUV3_MIDI_OUTPUT_SUPPORTED 1
  40. #define JUCE_AUV3_VIEW_CONFIG_SUPPORTED 1
  41. #endif
  42. #endif
  43. #ifndef __OBJC2__
  44. #error AUv3 needs Objective-C 2 support (compile with 64-bit)
  45. #endif
  46. #define JUCE_CORE_INCLUDE_OBJC_HELPERS 1
  47. #include "../utility/juce_IncludeSystemHeaders.h"
  48. #include "../utility/juce_IncludeModuleHeaders.h"
  49. #include "../../juce_graphics/native/juce_mac_CoreGraphicsHelpers.h"
  50. #include "../../juce_audio_basics/native/juce_mac_CoreAudioLayouts.h"
  51. #include "../../juce_audio_processors/format_types/juce_AU_Shared.h"
  52. #define JUCE_VIEWCONTROLLER_OBJC_NAME(x) JUCE_JOIN_MACRO (x, FactoryAUv3)
  53. #if ! JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES
  54. #error AUv3 wrapper requires variadic template support
  55. #endif
  56. #if JUCE_IOS
  57. #define JUCE_IOS_MAC_VIEW UIView
  58. #else
  59. #define JUCE_IOS_MAC_VIEW NSView
  60. #endif
  61. #define JUCE_AUDIOUNIT_OBJC_NAME(x) JUCE_JOIN_MACRO (x, AUv3)
  62. #pragma clang diagnostic push
  63. #pragma clang diagnostic ignored "-Wnullability-completeness"
  64. using namespace juce;
  65. // TODO: use SFINAE to automatically generate this for all NSObjects
  66. template <> struct ContainerDeletePolicy<AUAudioUnitBusArray> { static void destroy (NSObject* o) { [o release]; } };
  67. template <> struct ContainerDeletePolicy<AUParameterTree> { static void destroy (NSObject* o) { [o release]; } };
  68. template <> struct ContainerDeletePolicy<NSMutableArray<AUParameterNode *> > { static void destroy (NSObject* o) { [o release]; } };
  69. template <> struct ContainerDeletePolicy<AUParameter> { static void destroy (NSObject* o) { [o release]; } };
  70. template <> struct ContainerDeletePolicy<NSMutableArray<AUAudioUnitBus*> > { static void destroy (NSObject* o) { [o release]; } };
  71. template <> struct ContainerDeletePolicy<AUAudioUnitBus> { static void destroy (NSObject* o) { [o release]; } };
  72. template <> struct ContainerDeletePolicy<AVAudioFormat> { static void destroy (NSObject* o) { [o release]; } };
  73. template <> struct ContainerDeletePolicy<AVAudioPCMBuffer> { static void destroy (NSObject* o) { [o release]; } };
  74. template <> struct ContainerDeletePolicy<NSMutableArray<NSNumber*> > { static void destroy (NSObject* o) { [o release]; } };
  75. template <> struct ContainerDeletePolicy<NSNumber> { static void destroy (NSObject* o) { [o release]; } };
  76. template <> struct ContainerDeletePolicy<NSMutableArray<AUAudioUnitPreset*> > { static void destroy (NSObject* o) { [o release]; } };
  77. template <> struct ContainerDeletePolicy<AUAudioUnitPreset> { static void destroy (NSObject* o) { [o release]; } };
  78. //==============================================================================
  79. struct AudioProcessorHolder : public ReferenceCountedObject
  80. {
  81. AudioProcessorHolder() {}
  82. AudioProcessorHolder (AudioProcessor* p) : processor (p) {}
  83. AudioProcessor& operator*() noexcept { return *processor; }
  84. AudioProcessor* operator->() noexcept { return processor; }
  85. AudioProcessor* get() noexcept { return processor; }
  86. struct ViewConfig
  87. {
  88. double width;
  89. double height;
  90. bool hostHasMIDIController;
  91. };
  92. ScopedPointer<ViewConfig> viewConfiguration;
  93. typedef ReferenceCountedObjectPtr<AudioProcessorHolder> Ptr;
  94. private:
  95. ScopedPointer<AudioProcessor> processor;
  96. AudioProcessorHolder& operator= (AudioProcessor*) JUCE_DELETED_FUNCTION;
  97. AudioProcessorHolder (AudioProcessorHolder&) JUCE_DELETED_FUNCTION;
  98. AudioProcessorHolder& operator= (AudioProcessorHolder&) JUCE_DELETED_FUNCTION;
  99. };
  100. //==============================================================================
  101. class JuceAudioUnitv3Base
  102. {
  103. public:
  104. JuceAudioUnitv3Base (const AudioComponentDescription& descr,
  105. AudioComponentInstantiationOptions options,
  106. NSError** error)
  107. #pragma clang diagnostic push
  108. #pragma clang diagnostic ignored "-Wobjc-method-access"
  109. : au ([audioUnitObjCClass.createInstance() initWithComponentDescription: descr
  110. options: options
  111. error: error
  112. juceClass: this])
  113. #pragma clang diagnostic pop
  114. {}
  115. JuceAudioUnitv3Base (AUAudioUnit* audioUnit) : au (audioUnit)
  116. {
  117. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  118. initialiseJuce_GUI();
  119. }
  120. virtual ~JuceAudioUnitv3Base() {}
  121. //==============================================================================
  122. AUAudioUnit* getAudioUnit() noexcept { return au; }
  123. //==============================================================================
  124. virtual void reset() = 0;
  125. //==============================================================================
  126. virtual AUAudioUnitPreset* getCurrentPreset() = 0;
  127. virtual void setCurrentPreset(AUAudioUnitPreset*) = 0;
  128. virtual NSArray<AUAudioUnitPreset*>* getFactoryPresets() = 0;
  129. virtual NSDictionary<NSString*, id>* getFullState()
  130. {
  131. objc_super s = { getAudioUnit(), [AUAudioUnit class] };
  132. return ObjCMsgSendSuper<NSDictionary<NSString*, id>*> (&s, @selector (fullState));
  133. }
  134. virtual void setFullState (NSDictionary<NSString*, id>* state)
  135. {
  136. objc_super s = { getAudioUnit(), [AUAudioUnit class] };
  137. ObjCMsgSendSuper<void, NSDictionary<NSString*, id>*> (&s, @selector (setFullState:), state);
  138. }
  139. virtual AUParameterTree* getParameterTree() = 0;
  140. virtual NSArray<NSNumber*>* parametersForOverviewWithCount (int) = 0;
  141. //==============================================================================
  142. virtual NSTimeInterval getLatency() = 0;
  143. virtual NSTimeInterval getTailTime() = 0;
  144. //==============================================================================
  145. virtual AUAudioUnitBusArray* getInputBusses() = 0;
  146. virtual AUAudioUnitBusArray* getOutputBusses() = 0;
  147. virtual NSArray<NSNumber*>* getChannelCapabilities() = 0;
  148. virtual bool shouldChangeToFormat (AVAudioFormat*, AUAudioUnitBus*) = 0;
  149. //==============================================================================
  150. virtual int getVirtualMIDICableCount() = 0;
  151. virtual bool getSupportsMPE() = 0;
  152. virtual NSArray<NSString*>* getMIDIOutputNames() = 0;
  153. //==============================================================================
  154. virtual AUInternalRenderBlock getInternalRenderBlock() = 0;
  155. virtual bool getCanProcessInPlace() { return false; }
  156. virtual bool getRenderingOffline() = 0;
  157. virtual void setRenderingOffline (bool offline) = 0;
  158. //==============================================================================
  159. virtual NSString* getContextName() const = 0;
  160. virtual void setContextName (NSString*) = 0;
  161. virtual bool allocateRenderResourcesAndReturnError (NSError **outError)
  162. {
  163. objc_super s = { getAudioUnit(), [AUAudioUnit class] };
  164. return (ObjCMsgSendSuper<BOOL, NSError**> (&s, @selector (allocateRenderResourcesAndReturnError:), outError) == YES);
  165. }
  166. virtual void deallocateRenderResources()
  167. {
  168. objc_super s = { getAudioUnit(), [AUAudioUnit class] };
  169. ObjCMsgSendSuper<void> (&s, @selector (deallocateRenderResources));
  170. }
  171. //==============================================================================
  172. #if JUCE_AUV3_VIEW_CONFIG_SUPPORTED
  173. virtual NSIndexSet* getSupportedViewConfigurations (NSArray<AUAudioUnitViewConfiguration*>*) = 0;
  174. virtual void selectViewConfiguration (AUAudioUnitViewConfiguration*) = 0;
  175. #endif
  176. private:
  177. struct Class : public ObjCClass<AUAudioUnit>
  178. {
  179. Class() : ObjCClass<AUAudioUnit> ("AUAudioUnit_")
  180. {
  181. addIvar<JuceAudioUnitv3Base*> ("cppObject");
  182. #pragma clang diagnostic push
  183. #pragma clang diagnostic ignored "-Wundeclared-selector"
  184. addMethod (@selector (initWithComponentDescription:options:error:juceClass:),
  185. initWithComponentDescriptionAndJuceClass, "@@:",
  186. @encode (AudioComponentDescription),
  187. @encode (AudioComponentInstantiationOptions), "^@@");
  188. #pragma clang diagnostic pop
  189. addMethod (@selector (initWithComponentDescription:options:error:),
  190. initWithComponentDescription, "@@:",
  191. @encode (AudioComponentDescription),
  192. @encode (AudioComponentInstantiationOptions), "^@");
  193. addMethod (@selector (dealloc), dealloc, "v@:");
  194. //==============================================================================
  195. addMethod (@selector (reset), reset, "v@:");
  196. //==============================================================================
  197. addMethod (@selector (currentPreset), getCurrentPreset, "@@:");
  198. addMethod (@selector (setCurrentPreset:), setCurrentPreset, "v@:@");
  199. addMethod (@selector (factoryPresets), getFactoryPresets, "@@:");
  200. addMethod (@selector (fullState), getFullState, "@@:");
  201. addMethod (@selector (setFullState:), setFullState, "v@:@");
  202. addMethod (@selector (parameterTree), getParameterTree, "@@:");
  203. addMethod (@selector (parametersForOverviewWithCount:), parametersForOverviewWithCount, "@@:", @encode (NSInteger));
  204. //==============================================================================
  205. addMethod (@selector (latency), getLatency, @encode (NSTimeInterval), "@:");
  206. addMethod (@selector (tailTime), getTailTime, @encode (NSTimeInterval), "@:");
  207. //==============================================================================
  208. addMethod (@selector (inputBusses), getInputBusses, "@@:");
  209. addMethod (@selector (outputBusses), getOutputBusses, "@@:");
  210. addMethod (@selector (channelCapabilities), getChannelCapabilities, "@@:");
  211. addMethod (@selector (shouldChangeToFormat:forBus:), shouldChangeToFormat, "B@:@@");
  212. //==============================================================================
  213. addMethod (@selector (virtualMIDICableCount), getVirtualMIDICableCount, @encode (NSInteger), "@:");
  214. addMethod (@selector (supportsMPE), getSupportsMPE, @encode (BOOL), "@:");
  215. #if JUCE_AUV3_MIDI_OUTPUT_SUPPORTED
  216. addMethod (@selector (MIDIOutputNames), getMIDIOutputNames, "@@:");
  217. #endif
  218. //==============================================================================
  219. addMethod (@selector (internalRenderBlock), getInternalRenderBlock, @encode (AUInternalRenderBlock), "@:");
  220. addMethod (@selector (canProcessInPlace), getCanProcessInPlace, @encode (BOOL), "@:");
  221. addMethod (@selector (isRenderingOffline), getRenderingOffline, @encode (BOOL), "@:");
  222. addMethod (@selector (setRenderingOffline:), setRenderingOffline, "v@:", @encode (BOOL));
  223. addMethod (@selector (allocateRenderResourcesAndReturnError:), allocateRenderResourcesAndReturnError, "B@:^@");
  224. addMethod (@selector (deallocateRenderResources), deallocateRenderResources, "v@:");
  225. //==============================================================================
  226. addMethod (@selector (contextName), getContextName, "@@:");
  227. addMethod (@selector (setContextName:), setContextName, "v@:@");
  228. //==============================================================================
  229. #if JUCE_AUV3_VIEW_CONFIG_SUPPORTED
  230. addMethod (@selector (supportedViewConfigurations:), getSupportedViewConfigurations, "@@:@");
  231. addMethod (@selector (selectViewConfiguration:), selectViewConfiguration, "v@:@");
  232. #endif
  233. registerClass();
  234. }
  235. //==============================================================================
  236. static JuceAudioUnitv3Base* _this (id self) { return getIvar<JuceAudioUnitv3Base*> (self, "cppObject"); }
  237. static void setThis (id self, JuceAudioUnitv3Base* cpp) { object_setInstanceVariable (self, "cppObject", cpp); }
  238. //==============================================================================
  239. static id initWithComponentDescription (id _self, SEL, AudioComponentDescription descr, AudioComponentInstantiationOptions options, NSError** error)
  240. {
  241. AUAudioUnit* self = _self;
  242. objc_super s = { self, [AUAudioUnit class] };
  243. self = ObjCMsgSendSuper<AUAudioUnit*, AudioComponentDescription,
  244. AudioComponentInstantiationOptions, NSError**> (&s, @selector(initWithComponentDescription:options:error:), descr, options, error);
  245. JuceAudioUnitv3Base* juceAU = JuceAudioUnitv3Base::create (self, descr, options, error);
  246. setThis (self, juceAU);
  247. return self;
  248. }
  249. static id initWithComponentDescriptionAndJuceClass (id _self, SEL, AudioComponentDescription descr, AudioComponentInstantiationOptions options, NSError** error, JuceAudioUnitv3Base* juceAU)
  250. {
  251. AUAudioUnit* self = _self;
  252. objc_super s = { self, [AUAudioUnit class] };
  253. self = ObjCMsgSendSuper<AUAudioUnit*, AudioComponentDescription,
  254. AudioComponentInstantiationOptions, NSError**> (&s, @selector(initWithComponentDescription:options:error:), descr, options, error);
  255. setThis (self, juceAU);
  256. return self;
  257. }
  258. static void dealloc (id self, SEL) { delete _this (self); }
  259. //==============================================================================
  260. static void reset (id self, SEL) { _this (self)->reset(); }
  261. //==============================================================================
  262. static AUAudioUnitPreset* getCurrentPreset (id self, SEL) { return _this (self)->getCurrentPreset(); }
  263. static void setCurrentPreset (id self, SEL, AUAudioUnitPreset* preset) { return _this (self)->setCurrentPreset (preset); }
  264. static NSArray<AUAudioUnitPreset*>* getFactoryPresets (id self, SEL) { return _this (self)->getFactoryPresets(); }
  265. static NSDictionary<NSString*, id>* getFullState (id self, SEL) { return _this (self)->getFullState(); }
  266. static void setFullState (id self, SEL, NSDictionary<NSString *, id>* state) { return _this (self)->setFullState (state); }
  267. static AUParameterTree* getParameterTree (id self, SEL) { return _this (self)->getParameterTree(); }
  268. static NSArray<NSNumber*>* parametersForOverviewWithCount (id self, SEL, NSInteger count) { return _this (self)->parametersForOverviewWithCount (static_cast<int> (count)); }
  269. //==============================================================================
  270. static NSTimeInterval getLatency (id self, SEL) { return _this (self)->getLatency(); }
  271. static NSTimeInterval getTailTime (id self, SEL) { return _this (self)->getTailTime(); }
  272. //==============================================================================
  273. static AUAudioUnitBusArray* getInputBusses (id self, SEL) { return _this (self)->getInputBusses(); }
  274. static AUAudioUnitBusArray* getOutputBusses (id self, SEL) { return _this (self)->getOutputBusses(); }
  275. static NSArray<NSNumber*>* getChannelCapabilities (id self, SEL) { return _this (self)->getChannelCapabilities(); }
  276. static BOOL shouldChangeToFormat (id self, SEL, AVAudioFormat* format, AUAudioUnitBus* bus) { return _this (self)->shouldChangeToFormat (format, bus) ? YES : NO; }
  277. //==============================================================================
  278. static NSInteger getVirtualMIDICableCount (id self, SEL) { return _this (self)->getVirtualMIDICableCount(); }
  279. static BOOL getSupportsMPE (id self, SEL) { return _this (self)->getSupportsMPE() ? YES : NO; }
  280. static NSArray<NSString*>* getMIDIOutputNames (id self, SEL) { return _this (self)->getMIDIOutputNames(); }
  281. //==============================================================================
  282. static AUInternalRenderBlock getInternalRenderBlock (id self, SEL) { return _this (self)->getInternalRenderBlock(); }
  283. static BOOL getCanProcessInPlace (id self, SEL) { return _this (self)->getCanProcessInPlace() ? YES : NO; }
  284. static BOOL getRenderingOffline (id self, SEL) { return _this (self)->getRenderingOffline() ? YES : NO; }
  285. static void setRenderingOffline (id self, SEL, BOOL renderingOffline) { _this (self)->setRenderingOffline (renderingOffline); }
  286. static BOOL allocateRenderResourcesAndReturnError (id self, SEL, NSError** error) { return _this (self)->allocateRenderResourcesAndReturnError (error) ? YES : NO; }
  287. static void deallocateRenderResources (id self, SEL) { _this (self)->deallocateRenderResources(); }
  288. //==============================================================================
  289. static NSString* getContextName (id self, SEL) { return _this (self)->getContextName(); }
  290. static void setContextName (id self, SEL, NSString* str) { return _this (self)->setContextName (str); }
  291. //==============================================================================
  292. #if JUCE_AUV3_VIEW_CONFIG_SUPPORTED
  293. static NSIndexSet* getSupportedViewConfigurations (id self, SEL, NSArray<AUAudioUnitViewConfiguration*>* configs) { return _this (self)->getSupportedViewConfigurations (configs); }
  294. static void selectViewConfiguration (id self, SEL, AUAudioUnitViewConfiguration* config) { _this (self)->selectViewConfiguration (config); }
  295. #endif
  296. };
  297. static JuceAudioUnitv3Base* create (AUAudioUnit*, AudioComponentDescription, AudioComponentInstantiationOptions, NSError**);
  298. //==============================================================================
  299. static Class audioUnitObjCClass;
  300. protected:
  301. AUAudioUnit* au;
  302. };
  303. //==============================================================================
  304. JuceAudioUnitv3Base::Class JuceAudioUnitv3Base::audioUnitObjCClass;
  305. //==============================================================================
  306. //=========================== The actual AudioUnit =============================
  307. //==============================================================================
  308. class JuceAudioUnitv3 : public JuceAudioUnitv3Base,
  309. public AudioProcessorListener,
  310. public AudioPlayHead
  311. {
  312. public:
  313. JuceAudioUnitv3 (const AudioProcessorHolder::Ptr& processor,
  314. const AudioComponentDescription& descr,
  315. AudioComponentInstantiationOptions options,
  316. NSError** error)
  317. : JuceAudioUnitv3Base (descr, options, error),
  318. processorHolder (processor),
  319. mapper (*processorHolder->get())
  320. {
  321. init();
  322. }
  323. JuceAudioUnitv3 (AUAudioUnit* audioUnit, AudioComponentDescription, AudioComponentInstantiationOptions, NSError**)
  324. : JuceAudioUnitv3Base (audioUnit),
  325. processorHolder (new AudioProcessorHolder (createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))),
  326. mapper (*processorHolder->get())
  327. {
  328. init();
  329. }
  330. ~JuceAudioUnitv3()
  331. {
  332. auto& processor = getAudioProcessor();
  333. processor.removeListener (this);
  334. removeEditor (processor);
  335. if (editorObserverToken != nullptr)
  336. {
  337. [paramTree removeParameterObserver: editorObserverToken];
  338. editorObserverToken = nullptr;
  339. }
  340. }
  341. //==============================================================================
  342. void init()
  343. {
  344. AudioProcessor& processor = getAudioProcessor();
  345. const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender];
  346. #ifdef JucePlugin_PreferredChannelConfigurations
  347. short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
  348. const int numConfigs = sizeof (configs) / sizeof (short[2]);
  349. jassert (numConfigs > 0 && (configs[0][0] > 0 || configs[0][1] > 0));
  350. processor.setPlayConfigDetails (configs[0][0], configs[0][1], kDefaultSampleRate, static_cast<int> (maxFrames));
  351. Array<AUChannelInfo> channelInfos;
  352. for (int i = 0; i < numConfigs; ++i)
  353. {
  354. AUChannelInfo channelInfo;
  355. channelInfo.inChannels = configs[i][0];
  356. channelInfo.outChannels = configs[i][1];
  357. channelInfos.add (channelInfo);
  358. }
  359. #else
  360. Array<AUChannelInfo> channelInfos = AudioUnitHelpers::getAUChannelInfo (processor);
  361. #endif
  362. processor.setPlayHead (this);
  363. totalInChannels = processor.getTotalNumInputChannels();
  364. totalOutChannels = processor.getTotalNumOutputChannels();
  365. {
  366. channelCapabilities = [[NSMutableArray<NSNumber*> alloc] init];
  367. for (int i = 0; i < channelInfos.size(); ++i)
  368. {
  369. AUChannelInfo& info = channelInfos.getReference (i);
  370. [channelCapabilities addObject: [NSNumber numberWithInteger: info.inChannels]];
  371. [channelCapabilities addObject: [NSNumber numberWithInteger: info.outChannels]];
  372. }
  373. }
  374. editorObserverToken = nullptr;
  375. internalRenderBlock = CreateObjCBlock (this, &JuceAudioUnitv3::renderCallback);
  376. processor.setRateAndBufferSizeDetails (kDefaultSampleRate, static_cast<int> (maxFrames));
  377. processor.prepareToPlay (kDefaultSampleRate, static_cast<int> (maxFrames));
  378. processor.addListener (this);
  379. addParameters();
  380. addPresets();
  381. addAudioUnitBusses (true);
  382. addAudioUnitBusses (false);
  383. }
  384. AudioProcessor& getAudioProcessor() const noexcept { return **processorHolder; }
  385. //==============================================================================
  386. void reset() override
  387. {
  388. midiMessages.clear();
  389. lastTimeStamp.mSampleTime = std::numeric_limits<Float64>::max();
  390. }
  391. //==============================================================================
  392. AUAudioUnitPreset* getCurrentPreset() override
  393. {
  394. const int n = static_cast<int> ([factoryPresets count]);
  395. const int idx = static_cast<int> (getAudioProcessor().getCurrentProgram());
  396. if (idx < n)
  397. return [factoryPresets objectAtIndex:static_cast<unsigned int> (idx)];
  398. return nullptr;
  399. }
  400. void setCurrentPreset(AUAudioUnitPreset* preset) override
  401. {
  402. const int n = static_cast<int> ([factoryPresets count]);
  403. const int idx = static_cast<int> ([preset number]);
  404. if (isPositiveAndBelow (idx, n))
  405. getAudioProcessor().setCurrentProgram (idx);
  406. }
  407. NSArray<AUAudioUnitPreset*>* getFactoryPresets() override
  408. {
  409. return factoryPresets;
  410. }
  411. NSDictionary<NSString*, id>* getFullState() override
  412. {
  413. NSMutableDictionary<NSString*, id>* retval = [[NSMutableDictionary<NSString*, id> alloc] init];
  414. {
  415. NSDictionary<NSString*, id>* superRetval = JuceAudioUnitv3Base::getFullState();
  416. if (superRetval != nullptr)
  417. [retval addEntriesFromDictionary:superRetval];
  418. }
  419. juce::MemoryBlock state;
  420. getAudioProcessor().getCurrentProgramStateInformation (state);
  421. if (state.getSize() > 0)
  422. {
  423. NSData* ourState = [[NSData alloc] initWithBytes: state.getData()
  424. length: state.getSize()];
  425. NSString* nsKey = [[NSString alloc] initWithUTF8String: JUCE_STATE_DICTIONARY_KEY];
  426. [retval setObject: ourState
  427. forKey: nsKey];
  428. [nsKey release];
  429. [ourState release];
  430. }
  431. return [retval autorelease];
  432. }
  433. void setFullState (NSDictionary<NSString*, id>* state) override
  434. {
  435. if (state == nullptr)
  436. return;
  437. NSMutableDictionary<NSString*, id>* modifiedState = [[NSMutableDictionary<NSString*, id> alloc] init];
  438. [modifiedState addEntriesFromDictionary: state];
  439. NSString* nsPresetKey = [[NSString alloc] initWithUTF8String: kAUPresetDataKey];
  440. [modifiedState removeObjectForKey: nsPresetKey];
  441. [nsPresetKey release];
  442. JuceAudioUnitv3Base::setFullState (modifiedState);
  443. NSString* nsKey = [[NSString alloc] initWithUTF8String: JUCE_STATE_DICTIONARY_KEY];
  444. NSObject* obj = [modifiedState objectForKey: nsKey];
  445. [nsKey release];
  446. if (obj != nullptr)
  447. {
  448. if ([obj isKindOfClass:[NSData class]])
  449. {
  450. NSData* data = reinterpret_cast<NSData*> (obj);
  451. const int numBytes = static_cast<int> ([data length]);
  452. const juce::uint8* const rawBytes = reinterpret_cast< const juce::uint8* const> ([data bytes]);
  453. if (numBytes > 0)
  454. getAudioProcessor().setCurrentProgramStateInformation (rawBytes, numBytes);
  455. }
  456. }
  457. [modifiedState release];
  458. }
  459. AUParameterTree* getParameterTree() override
  460. {
  461. return paramTree;
  462. }
  463. NSArray<NSNumber*>* parametersForOverviewWithCount (int count) override
  464. {
  465. const int n = static_cast<int> ([overviewParams count]);
  466. if (count >= n)
  467. return overviewParams;
  468. NSMutableArray<NSNumber*>* retval = [[NSMutableArray<NSNumber*>alloc] initWithArray: overviewParams];
  469. [retval removeObjectsInRange: NSMakeRange (static_cast<unsigned int> (count), static_cast<unsigned int> (n - count))];
  470. return [retval autorelease];
  471. }
  472. //==============================================================================
  473. NSTimeInterval getLatency() override
  474. {
  475. auto& p = getAudioProcessor();
  476. return p.getLatencySamples() / p.getSampleRate();
  477. }
  478. NSTimeInterval getTailTime() override
  479. {
  480. return getAudioProcessor().getTailLengthSeconds();
  481. }
  482. //==============================================================================
  483. AUAudioUnitBusArray* getInputBusses() override { return inputBusses; }
  484. AUAudioUnitBusArray* getOutputBusses() override { return outputBusses; }
  485. NSArray<NSNumber*>* getChannelCapabilities() override { return channelCapabilities; }
  486. bool shouldChangeToFormat (AVAudioFormat* format, AUAudioUnitBus* auBus) override
  487. {
  488. const bool isInput = ([auBus busType] == AUAudioUnitBusTypeInput);
  489. const int busIdx = static_cast<int> ([auBus index]);
  490. const int newNumChannels = static_cast<int> ([format channelCount]);
  491. AudioProcessor& processor = getAudioProcessor();
  492. if (AudioProcessor::Bus* bus = processor.getBus (isInput, busIdx))
  493. {
  494. #ifdef JucePlugin_PreferredChannelConfigurations
  495. ignoreUnused (bus);
  496. short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
  497. if (! AudioUnitHelpers::isLayoutSupported (processor, isInput, busIdx, newNumChannels, configs))
  498. return false;
  499. #else
  500. const AVAudioChannelLayout* layout = [format channelLayout];
  501. const AudioChannelLayoutTag layoutTag = (layout != nullptr ? [layout layoutTag] : 0);
  502. if (layoutTag != 0)
  503. {
  504. AudioChannelSet newLayout = CoreAudioLayouts::fromCoreAudio (layoutTag);
  505. if (newLayout.size() != newNumChannels)
  506. return false;
  507. if (! bus->isLayoutSupported (newLayout))
  508. return false;
  509. }
  510. else
  511. {
  512. if (! bus->isNumberOfChannelsSupported (newNumChannels))
  513. return false;
  514. }
  515. #endif
  516. return true;
  517. }
  518. return false;
  519. }
  520. //==============================================================================
  521. int getVirtualMIDICableCount() override
  522. {
  523. #if JucePlugin_WantsMidiInput
  524. return 1;
  525. #else
  526. return 0;
  527. #endif
  528. }
  529. bool getSupportsMPE() override
  530. {
  531. return getAudioProcessor().supportsMPE();
  532. }
  533. NSArray<NSString*>* getMIDIOutputNames() override
  534. {
  535. #if JucePlugin_ProducesMidiOutput
  536. return @[@"MIDI Out"];
  537. #else
  538. return @[];
  539. #endif
  540. }
  541. //==============================================================================
  542. AUInternalRenderBlock getInternalRenderBlock() override { return internalRenderBlock; }
  543. bool getRenderingOffline() override { return getAudioProcessor().isNonRealtime(); }
  544. void setRenderingOffline (bool offline) override { getAudioProcessor().setNonRealtime (offline); }
  545. //==============================================================================
  546. NSString* getContextName() const override { return juceStringToNS (contextName); }
  547. void setContextName (NSString* str) override
  548. {
  549. if (str != nullptr)
  550. {
  551. AudioProcessor::TrackProperties props;
  552. props.name = nsStringToJuce (str);
  553. getAudioProcessor().updateTrackProperties (props);
  554. }
  555. }
  556. //==============================================================================
  557. bool allocateRenderResourcesAndReturnError (NSError **outError) override
  558. {
  559. AudioProcessor& processor = getAudioProcessor();
  560. const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender];
  561. if (! JuceAudioUnitv3Base::allocateRenderResourcesAndReturnError (outError))
  562. return false;
  563. if (outError != nullptr)
  564. *outError = nullptr;
  565. AudioProcessor::BusesLayout layouts;
  566. for (int dir = 0; dir < 2; ++dir)
  567. {
  568. const bool isInput = (dir == 0);
  569. const int n = AudioUnitHelpers::getBusCount (&processor, isInput);
  570. Array<AudioChannelSet>& channelSets = (isInput ? layouts.inputBuses : layouts.outputBuses);
  571. AUAudioUnitBusArray* auBuses = (isInput ? [getAudioUnit() inputBusses] : [getAudioUnit() outputBusses]);
  572. jassert ([auBuses count] == static_cast<NSUInteger> (n));
  573. for (int busIdx = 0; busIdx < n; ++busIdx)
  574. {
  575. AudioProcessor::Bus* bus = processor.getBus (isInput, busIdx);
  576. AVAudioFormat* format = [[auBuses objectAtIndexedSubscript:static_cast<NSUInteger> (busIdx)] format];
  577. AudioChannelSet newLayout;
  578. const AVAudioChannelLayout* layout = [format channelLayout];
  579. const AudioChannelLayoutTag layoutTag = (layout != nullptr ? [layout layoutTag] : 0);
  580. if (layoutTag != 0)
  581. newLayout = CoreAudioLayouts::fromCoreAudio (layoutTag);
  582. else
  583. newLayout = bus->supportedLayoutWithChannels (static_cast<int> ([format channelCount]));
  584. if (newLayout.isDisabled())
  585. return false;
  586. channelSets.add (newLayout);
  587. }
  588. }
  589. #ifdef JucePlugin_PreferredChannelConfigurations
  590. short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
  591. if (! AudioProcessor::containsLayout (layouts, configs))
  592. {
  593. if (outError != nullptr)
  594. *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:kAudioUnitErr_FormatNotSupported userInfo:nullptr];
  595. return false;
  596. }
  597. #endif
  598. if (! AudioUnitHelpers::setBusesLayout (&getAudioProcessor(), layouts))
  599. {
  600. if (outError != nullptr)
  601. *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:kAudioUnitErr_FormatNotSupported userInfo:nullptr];
  602. return false;
  603. }
  604. totalInChannels = processor.getTotalNumInputChannels();
  605. totalOutChannels = processor.getTotalNumOutputChannels();
  606. allocateBusBuffer (true);
  607. allocateBusBuffer (false);
  608. mapper.alloc();
  609. audioBuffer.prepare (totalInChannels, totalOutChannels, static_cast<int> (maxFrames));
  610. double sampleRate = (jmax (AudioUnitHelpers::getBusCount (&processor, true), AudioUnitHelpers::getBusCount (&processor, false)) > 0 ?
  611. [[[([inputBusses count] > 0 ? inputBusses : outputBusses) objectAtIndexedSubscript: 0] format] sampleRate] : 44100.0);
  612. processor.setRateAndBufferSizeDetails (sampleRate, static_cast<int> (maxFrames));
  613. processor.prepareToPlay (sampleRate, static_cast<int> (maxFrames));
  614. zeromem (&lastAudioHead, sizeof (lastAudioHead));
  615. hostMusicalContextCallback = [getAudioUnit() musicalContextBlock];
  616. hostTransportStateCallback = [getAudioUnit() transportStateBlock];
  617. reset();
  618. return true;
  619. }
  620. void deallocateRenderResources() override
  621. {
  622. hostMusicalContextCallback = nullptr;
  623. hostTransportStateCallback = nullptr;
  624. getAudioProcessor().releaseResources();
  625. audioBuffer.release();
  626. inBusBuffers. clear();
  627. outBusBuffers.clear();
  628. mapper.release();
  629. JuceAudioUnitv3Base::deallocateRenderResources();
  630. }
  631. //==============================================================================
  632. #if JUCE_AUV3_VIEW_CONFIG_SUPPORTED
  633. NSIndexSet* getSupportedViewConfigurations (NSArray<AUAudioUnitViewConfiguration*>* configs) override
  634. {
  635. auto supportedViewIndecies = [[NSMutableIndexSet alloc] init];
  636. auto n = [configs count];
  637. if (auto* editor = getAudioProcessor().createEditorIfNeeded())
  638. {
  639. // If you hit this assertion then your plug-in's editor is reporting that it doesn't support
  640. // any host MIDI controller configurations!
  641. jassert (editor->supportsHostMIDIControllerPresence (true) || editor->supportsHostMIDIControllerPresence (false));
  642. for (auto i = 0u; i < n; ++i)
  643. {
  644. if (auto* viewConfiguration = [configs objectAtIndex:i])
  645. {
  646. if (editor->supportsHostMIDIControllerPresence ([viewConfiguration hostHasController] == YES))
  647. {
  648. auto* constrainer = editor->getConstrainer();
  649. auto height = (int) [viewConfiguration height];
  650. auto width = (int) [viewConfiguration width];
  651. if (height <= constrainer->getMaximumHeight() && height >= constrainer->getMinimumHeight()
  652. && width <= constrainer->getMaximumWidth() && width >= constrainer->getMinimumWidth())
  653. [supportedViewIndecies addIndex: i];
  654. }
  655. }
  656. }
  657. }
  658. return [supportedViewIndecies autorelease];
  659. }
  660. void selectViewConfiguration (AUAudioUnitViewConfiguration* config) override
  661. {
  662. processorHolder->viewConfiguration = new AudioProcessorHolder::ViewConfig { [config width], [config height], [config hostHasController] == YES };
  663. }
  664. #endif
  665. //==============================================================================
  666. void audioProcessorChanged (AudioProcessor* processor) override
  667. {
  668. ignoreUnused (processor);
  669. [au willChangeValueForKey: @"allParameterValues"];
  670. addPresets();
  671. [au didChangeValueForKey: @"allParameterValues"];
  672. }
  673. void audioProcessorParameterChanged (AudioProcessor*, int idx, float newValue) override
  674. {
  675. if (isPositiveAndBelow (idx, getAudioProcessor().getNumParameters()))
  676. {
  677. if (AUParameter* param = [paramTree parameterWithAddress: getAUParameterAddressForIndex (idx)])
  678. {
  679. if (editorObserverToken != nullptr)
  680. [param setValue: newValue originator: editorObserverToken];
  681. else
  682. [param setValue: newValue];
  683. }
  684. }
  685. }
  686. //==============================================================================
  687. bool getCurrentPosition (CurrentPositionInfo& info) override
  688. {
  689. bool musicContextCallSucceeded = false;
  690. bool transportStateCallSucceeded = false;
  691. info = lastAudioHead;
  692. info.timeInSamples = (int64) (lastTimeStamp.mSampleTime + 0.5);
  693. info.timeInSeconds = info.timeInSamples / getAudioProcessor().getSampleRate();
  694. switch (lastTimeStamp.mSMPTETime.mType)
  695. {
  696. case kSMPTETimeType2398: info.frameRate = AudioPlayHead::fps23976; break;
  697. case kSMPTETimeType24: info.frameRate = AudioPlayHead::fps24; break;
  698. case kSMPTETimeType25: info.frameRate = AudioPlayHead::fps25; break;
  699. case kSMPTETimeType2997: info.frameRate = AudioPlayHead::fps2997; break;
  700. case kSMPTETimeType2997Drop: info.frameRate = AudioPlayHead::fps2997drop; break;
  701. case kSMPTETimeType30Drop: info.frameRate = AudioPlayHead::fps30drop; break;
  702. case kSMPTETimeType30: info.frameRate = AudioPlayHead::fps30; break;
  703. case kSMPTETimeType60Drop: info.frameRate = AudioPlayHead::fps60drop; break;
  704. case kSMPTETimeType60: info.frameRate = AudioPlayHead::fps60; break;
  705. default: info.frameRate = AudioPlayHead::fpsUnknown; break;
  706. }
  707. double num;
  708. NSInteger den;
  709. NSInteger outDeltaSampleOffsetToNextBeat;
  710. double outCurrentMeasureDownBeat, bpm;
  711. double ppqPosition;
  712. if (hostMusicalContextCallback != nullptr)
  713. {
  714. AUHostMusicalContextBlock musicalContextCallback = hostMusicalContextCallback;
  715. if (musicalContextCallback (&bpm, &num, &den, &ppqPosition, &outDeltaSampleOffsetToNextBeat, &outCurrentMeasureDownBeat))
  716. {
  717. musicContextCallSucceeded = true;
  718. info.timeSigNumerator = (int) num;
  719. info.timeSigDenominator = (int) den;
  720. info.ppqPositionOfLastBarStart = outCurrentMeasureDownBeat;
  721. info.bpm = bpm;
  722. info.ppqPosition = ppqPosition;
  723. info.ppqPositionOfLastBarStart = outCurrentMeasureDownBeat;
  724. }
  725. }
  726. double outCurrentSampleInTimeLine, outCycleStartBeat = 0, outCycleEndBeat = 0;
  727. AUHostTransportStateFlags flags;
  728. if (hostTransportStateCallback != nullptr)
  729. {
  730. AUHostTransportStateBlock transportStateCallback = hostTransportStateCallback;
  731. if (transportStateCallback (&flags, &outCurrentSampleInTimeLine, &outCycleStartBeat, &outCycleEndBeat))
  732. {
  733. transportStateCallSucceeded = true;
  734. info.timeInSamples = (int64) (outCurrentSampleInTimeLine + 0.5);
  735. info.timeInSeconds = info.timeInSamples / getAudioProcessor().getSampleRate();
  736. info.isPlaying = ((flags & AUHostTransportStateMoving) != 0);
  737. info.isLooping = ((flags & AUHostTransportStateCycling) != 0);
  738. info.isRecording = ((flags & AUHostTransportStateRecording) != 0);
  739. info.ppqLoopStart = outCycleStartBeat;
  740. info.ppqLoopEnd = outCycleEndBeat;
  741. }
  742. }
  743. if (musicContextCallSucceeded && transportStateCallSucceeded)
  744. lastAudioHead = info;
  745. return true;
  746. }
  747. //==============================================================================
  748. static void removeEditor (AudioProcessor& processor)
  749. {
  750. ScopedLock editorLock (processor.getCallbackLock());
  751. if (AudioProcessorEditor* editor = processor.getActiveEditor())
  752. {
  753. processor.editorBeingDeleted (editor);
  754. delete editor;
  755. }
  756. }
  757. private:
  758. //==============================================================================
  759. struct BusBuffer
  760. {
  761. BusBuffer (AUAudioUnitBus* bus, int maxFramesPerBuffer)
  762. : auBus (bus),
  763. maxFrames (maxFramesPerBuffer),
  764. numberOfChannels (static_cast<int> ([[auBus format] channelCount])),
  765. isInterleaved ([[auBus format] isInterleaved])
  766. {
  767. alloc();
  768. }
  769. //==============================================================================
  770. void alloc()
  771. {
  772. const int numBuffers = isInterleaved ? 1 : numberOfChannels;
  773. int bytes = static_cast<int> (sizeof (AudioBufferList))
  774. + ((numBuffers - 1) * static_cast<int> (sizeof (::AudioBuffer)));
  775. jassert (bytes > 0);
  776. bufferListStorage.calloc (static_cast<size_t> (bytes));
  777. bufferList = reinterpret_cast<AudioBufferList*> (bufferListStorage.getData());
  778. const int bufferChannels = isInterleaved ? numberOfChannels : 1;
  779. scratchBuffer.setSize (numBuffers, bufferChannels * maxFrames);
  780. }
  781. void dealloc()
  782. {
  783. bufferList = nullptr;
  784. bufferListStorage.free();
  785. scratchBuffer.setSize (0, 0);
  786. }
  787. //==============================================================================
  788. int numChannels() const noexcept { return numberOfChannels; }
  789. bool interleaved() const noexcept { return isInterleaved; }
  790. AudioBufferList* get() const noexcept { return bufferList; }
  791. //==============================================================================
  792. void prepare (UInt32 nFrames, const AudioBufferList* other = nullptr) noexcept
  793. {
  794. const int numBuffers = isInterleaved ? 1 : numberOfChannels;
  795. const bool isCompatible = isCompatibleWith (other);
  796. bufferList->mNumberBuffers = static_cast<UInt32> (numBuffers);
  797. for (int i = 0; i < numBuffers; ++i)
  798. {
  799. const UInt32 bufferChannels = static_cast<UInt32> (isInterleaved ? numberOfChannels : 1);
  800. bufferList->mBuffers[i].mNumberChannels = bufferChannels;
  801. bufferList->mBuffers[i].mData = (isCompatible ? other->mBuffers[i].mData
  802. : scratchBuffer.getWritePointer (i));
  803. bufferList->mBuffers[i].mDataByteSize = nFrames * bufferChannels * sizeof (float);
  804. }
  805. }
  806. //==============================================================================
  807. bool isCompatibleWith (const AudioBufferList* other) const noexcept
  808. {
  809. if (other == nullptr)
  810. return false;
  811. if (other->mNumberBuffers > 0)
  812. {
  813. const bool otherInterleaved = AudioUnitHelpers::isAudioBufferInterleaved (*other);
  814. const int otherChannels = static_cast<int> (otherInterleaved ? other->mBuffers[0].mNumberChannels
  815. : other->mNumberBuffers);
  816. return otherInterleaved == isInterleaved
  817. && numberOfChannels == otherChannels;
  818. }
  819. return numberOfChannels == 0;
  820. }
  821. private:
  822. AUAudioUnitBus* auBus;
  823. HeapBlock<char> bufferListStorage;
  824. AudioBufferList* bufferList = nullptr;
  825. int maxFrames, numberOfChannels;
  826. bool isInterleaved;
  827. AudioSampleBuffer scratchBuffer;
  828. };
  829. //==============================================================================
  830. void addAudioUnitBusses (bool isInput)
  831. {
  832. ScopedPointer<NSMutableArray<AUAudioUnitBus*> > array = [[NSMutableArray<AUAudioUnitBus*> alloc] init];
  833. AudioProcessor& processor = getAudioProcessor();
  834. const int n = AudioUnitHelpers::getBusCount (&processor, isInput);
  835. for (int i = 0; i < n; ++i)
  836. {
  837. ScopedPointer<AUAudioUnitBus> audioUnitBus;
  838. {
  839. ScopedPointer<AVAudioFormat> defaultFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate: kDefaultSampleRate
  840. channels: static_cast<AVAudioChannelCount> (processor.getChannelCountOfBus (isInput, i))];
  841. audioUnitBus = [[AUAudioUnitBus alloc] initWithFormat: defaultFormat
  842. error: nullptr];
  843. }
  844. [array addObject: audioUnitBus];
  845. }
  846. (isInput ? inputBusses : outputBusses) = [[AUAudioUnitBusArray alloc] initWithAudioUnit: au
  847. busType: (isInput ? AUAudioUnitBusTypeInput : AUAudioUnitBusTypeOutput)
  848. busses: array];
  849. }
  850. void addParameters()
  851. {
  852. ScopedPointer<NSMutableArray<AUParameterNode*> > params = [[NSMutableArray<AUParameterNode*> alloc] init];
  853. paramObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
  854. paramProvider = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
  855. overviewParams = [[NSMutableArray<NSNumber*> alloc] init];
  856. auto& processor = getAudioProcessor();
  857. const int n = processor.getNumParameters();
  858. #if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
  859. // check if all parameters are managed?
  860. usingManagedParameter = (processor.getParameters().size() == processor.getNumParameters());
  861. #endif
  862. for (int idx = 0; idx < n; ++idx)
  863. {
  864. const String identifier (idx);
  865. const String name = processor.getParameterName (idx);
  866. AudioUnitParameterUnit unit = kAudioUnitParameterUnit_Generic;
  867. AudioUnitParameterOptions flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
  868. | kAudioUnitParameterFlag_IsReadable
  869. | kAudioUnitParameterFlag_HasCFNameString
  870. | kAudioUnitParameterFlag_ValuesHaveStrings);
  871. #if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
  872. flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
  873. #endif
  874. // set whether the param is automatable (unnamed parameters aren't allowed to be automated)
  875. if (name.isEmpty() || ! processor.isParameterAutomatable (idx))
  876. flags |= kAudioUnitParameterFlag_NonRealTime;
  877. if (processor.isMetaParameter (idx))
  878. flags |= kAudioUnitParameterFlag_IsGlobalMeta;
  879. // is this a meter?
  880. if (((processor.getParameterCategory (idx) & 0xffff0000) >> 16) == 2)
  881. {
  882. flags &= ~kAudioUnitParameterFlag_IsWritable;
  883. flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
  884. unit = kAudioUnitParameterUnit_LinearGain;
  885. }
  886. #if JUCE_FORCE_USE_LEGACY_PARAM_IDS
  887. AUParameterAddress address = static_cast<AUParameterAddress> (idx);
  888. #else
  889. AUParameterAddress address = generateAUParameterAddressForIndex (idx);
  890. // Consider yourself very unlucky if you hit this assertion. The hash code of your
  891. // parameter ids are not unique.
  892. jassert (! paramMap.contains (static_cast<int64> (address)));
  893. paramAddresses.add (address);
  894. paramMap.set (static_cast<int64> (address), idx);
  895. #endif
  896. // create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
  897. ScopedPointer<AUParameter> param = [[AUParameterTree createParameterWithIdentifier: juceStringToNS (identifier)
  898. name: juceStringToNS (name)
  899. address: address
  900. min: 0.0f
  901. max: 1.0f
  902. unit: unit
  903. unitName: nullptr
  904. flags: flags
  905. valueStrings: nullptr
  906. dependentParameters: nullptr] retain];
  907. [params addObject: param];
  908. [overviewParams addObject: [NSNumber numberWithUnsignedLongLong:address]];
  909. }
  910. // create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
  911. paramTree = [[AUParameterTree createTreeWithChildren: params] retain];
  912. [paramTree setImplementorValueObserver: paramObserver];
  913. [paramTree setImplementorValueProvider: paramProvider];
  914. if (processor.hasEditor())
  915. {
  916. editorParamObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedForObserver);
  917. editorObserverToken = [paramTree tokenByAddingParameterObserver: editorParamObserver];
  918. }
  919. }
  920. void addPresets()
  921. {
  922. factoryPresets = [[NSMutableArray<AUAudioUnitPreset*> alloc] init];
  923. const int n = getAudioProcessor().getNumPrograms();
  924. for (int idx = 0; idx < n; ++idx)
  925. {
  926. String name = getAudioProcessor().getProgramName (idx);
  927. ScopedPointer<AUAudioUnitPreset> preset = [[AUAudioUnitPreset alloc] init];
  928. [preset setName: juceStringToNS (name)];
  929. [preset setNumber: static_cast<NSInteger> (idx)];
  930. [factoryPresets addObject: preset];
  931. }
  932. }
  933. //==============================================================================
  934. void allocateBusBuffer (bool isInput)
  935. {
  936. OwnedArray<BusBuffer>& busBuffers = isInput ? inBusBuffers : outBusBuffers;
  937. busBuffers.clear();
  938. const int n = AudioUnitHelpers::getBusCount (&getAudioProcessor(), isInput);
  939. const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender];
  940. for (int busIdx = 0; busIdx < n; ++busIdx)
  941. busBuffers.add (new BusBuffer ([(isInput ? inputBusses : outputBusses) objectAtIndexedSubscript: static_cast<unsigned int> (busIdx)],
  942. static_cast<int> (maxFrames)));
  943. }
  944. //==============================================================================
  945. void processEvents (const AURenderEvent *__nullable realtimeEventListHead, int numParams, AUEventSampleTime startTime)
  946. {
  947. for (const AURenderEvent* event = realtimeEventListHead; event != nullptr; event = event->head.next)
  948. {
  949. switch (event->head.eventType)
  950. {
  951. case AURenderEventMIDI:
  952. {
  953. const AUMIDIEvent& midiEvent = event->MIDI;
  954. midiMessages.addEvent (midiEvent.data, midiEvent.length, static_cast<int> (midiEvent.eventSampleTime - startTime));
  955. }
  956. break;
  957. case AURenderEventParameter:
  958. case AURenderEventParameterRamp:
  959. {
  960. const AUParameterEvent& paramEvent = event->parameter;
  961. const int idx = getJuceParameterIndexForAUAddress (paramEvent.parameterAddress);
  962. if (isPositiveAndBelow (idx, numParams))
  963. getAudioProcessor().setParameter (idx, paramEvent.value);
  964. }
  965. break;
  966. default:
  967. break;
  968. }
  969. }
  970. }
  971. AUAudioUnitStatus renderCallback (AudioUnitRenderActionFlags* actionFlags, const AudioTimeStamp* timestamp, AUAudioFrameCount frameCount,
  972. NSInteger outputBusNumber, AudioBufferList* outputData, const AURenderEvent *__nullable realtimeEventListHead,
  973. AURenderPullInputBlock __nullable pullInputBlock)
  974. {
  975. auto& processor = getAudioProcessor();
  976. jassert (static_cast<int> (frameCount) <= getAudioProcessor().getBlockSize());
  977. // process params
  978. const int numParams = processor.getNumParameters();
  979. processEvents (realtimeEventListHead, numParams, static_cast<AUEventSampleTime> (timestamp->mSampleTime));
  980. if (lastTimeStamp.mSampleTime != timestamp->mSampleTime)
  981. {
  982. lastTimeStamp = *timestamp;
  983. const int numInputBuses = inBusBuffers. size();
  984. const int numOutputBuses = outBusBuffers.size();
  985. // prepare buffers
  986. {
  987. for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
  988. {
  989. BusBuffer& busBuffer = *outBusBuffers[busIdx];
  990. const bool canUseDirectOutput =
  991. (busIdx == outputBusNumber && outputData != nullptr && outputData->mNumberBuffers > 0);
  992. busBuffer.prepare (frameCount, canUseDirectOutput ? outputData : nullptr);
  993. }
  994. for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
  995. {
  996. BusBuffer& busBuffer = *inBusBuffers[busIdx];
  997. busBuffer.prepare (frameCount, busIdx < numOutputBuses ? outBusBuffers[busIdx]->get() : nullptr);
  998. }
  999. audioBuffer.reset();
  1000. }
  1001. // pull inputs
  1002. {
  1003. for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
  1004. {
  1005. BusBuffer& busBuffer = *inBusBuffers[busIdx];
  1006. AudioBufferList* buffer = busBuffer.get();
  1007. if (pullInputBlock == nullptr || pullInputBlock (actionFlags, timestamp, frameCount, busIdx, buffer) != noErr)
  1008. AudioUnitHelpers::clearAudioBuffer (*buffer);
  1009. if (actionFlags != nullptr && (*actionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0)
  1010. AudioUnitHelpers::clearAudioBuffer (*buffer);
  1011. }
  1012. }
  1013. // set buffer pointer to minimize copying
  1014. {
  1015. int chIdx = 0;
  1016. for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
  1017. {
  1018. BusBuffer& busBuffer = *outBusBuffers[busIdx];
  1019. AudioBufferList* buffer = busBuffer.get();
  1020. const bool interleaved = busBuffer.interleaved();
  1021. const int numChannels = busBuffer.numChannels();
  1022. const int* outLayoutMap = mapper.get (false, busIdx);
  1023. for (int ch = 0; ch < numChannels; ++ch)
  1024. audioBuffer.setBuffer (chIdx++, interleaved ? nullptr : static_cast<float*> (buffer->mBuffers[outLayoutMap[ch]].mData));
  1025. }
  1026. // use input pointers on remaining channels
  1027. for (int busIdx = 0; chIdx < totalInChannels;)
  1028. {
  1029. const int channelOffset = processor.getOffsetInBusBufferForAbsoluteChannelIndex (true, chIdx, busIdx);
  1030. BusBuffer& busBuffer = *inBusBuffers[busIdx];
  1031. AudioBufferList* buffer = busBuffer.get();
  1032. const int* inLayoutMap = mapper.get (true, busIdx);
  1033. audioBuffer.setBuffer (chIdx++, busBuffer.interleaved() ? nullptr : static_cast<float*> (buffer->mBuffers[inLayoutMap[channelOffset]].mData));
  1034. }
  1035. }
  1036. // copy input
  1037. {
  1038. for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
  1039. audioBuffer.push (*inBusBuffers[busIdx]->get(), mapper.get (true, busIdx));
  1040. // clear remaining channels
  1041. for (int i = totalInChannels; i < totalOutChannels; ++i)
  1042. zeromem (audioBuffer.push(), sizeof (float) * frameCount);
  1043. }
  1044. // process audio
  1045. processBlock (audioBuffer.getBuffer (frameCount), midiMessages);
  1046. // send MIDI
  1047. #if JucePlugin_ProducesMidiOutput && JUCE_AUV3_MIDI_OUTPUT_SUPPORTED
  1048. auto midiOut = [au MIDIOutputEventBlock];
  1049. MidiMessage msg;
  1050. int samplePosition;
  1051. for (MidiBuffer::Iterator it (midiMessages); it.getNextEvent (msg, samplePosition);)
  1052. midiOut (samplePosition, 0, msg.getRawDataSize(), msg.getRawData());
  1053. #endif
  1054. midiMessages.clear();
  1055. }
  1056. // copy back
  1057. audioBuffer.pop (*outBusBuffers[(int) outputBusNumber]->get(),
  1058. mapper.get (false, (int) outputBusNumber));
  1059. return noErr;
  1060. }
  1061. void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiBuffer) noexcept
  1062. {
  1063. auto& processor = getAudioProcessor();
  1064. const ScopedLock sl (processor.getCallbackLock());
  1065. if (processor.isSuspended())
  1066. buffer.clear();
  1067. else if ([au shouldBypassEffect])
  1068. processor.processBlockBypassed (buffer, midiBuffer);
  1069. else
  1070. processor.processBlock (buffer, midiBuffer);
  1071. }
  1072. //==============================================================================
  1073. void valueChangedFromHost (AUParameter* param, AUValue value)
  1074. {
  1075. if (param != nullptr)
  1076. {
  1077. const int idx = getJuceParameterIndexForAUAddress ([param address]);
  1078. auto& processor = getAudioProcessor();
  1079. if (isPositiveAndBelow (idx, processor.getNumParameters()))
  1080. processor.setParameter (idx, value);
  1081. }
  1082. }
  1083. AUValue getValue (AUParameter* param)
  1084. {
  1085. if (param != nullptr)
  1086. {
  1087. const int idx = getJuceParameterIndexForAUAddress ([param address]);
  1088. auto& processor = getAudioProcessor();
  1089. if (isPositiveAndBelow (idx, processor.getNumParameters()))
  1090. return processor.getParameter (idx);
  1091. }
  1092. return 0;
  1093. }
  1094. void valueChangedForObserver(AUParameterAddress, AUValue)
  1095. {
  1096. // this will have already been handled by valueChangedFromHost
  1097. }
  1098. //==============================================================================
  1099. #if JUCE_FORCE_USE_LEGACY_PARAM_IDS
  1100. inline AUParameterAddress getAUParameterAddressForIndex (int paramIndex) const noexcept { return static_cast<AUParameterAddress> (paramIndex); }
  1101. inline int getJuceParameterIndexForAUAddress (AUParameterAddress address) const noexcept { return static_cast<int> (address); }
  1102. #else
  1103. AUParameterAddress generateAUParameterAddressForIndex (int paramIndex) const
  1104. {
  1105. auto& processor = getAudioProcessor();
  1106. const int n = processor.getNumParameters();
  1107. if (isPositiveAndBelow (paramIndex, n))
  1108. {
  1109. const String& juceParamID = processor.getParameterID (paramIndex);
  1110. return usingManagedParameter ? static_cast<AUParameterAddress> (juceParamID.hashCode64())
  1111. : static_cast<AUParameterAddress> (juceParamID.getIntValue());
  1112. }
  1113. return static_cast<AUParameterAddress> (-1);
  1114. }
  1115. inline AUParameterAddress getAUParameterAddressForIndex (int paramIndex) const noexcept
  1116. {
  1117. return usingManagedParameter ? paramAddresses.getReference (paramIndex)
  1118. : static_cast<AUParameterAddress> (paramIndex);
  1119. }
  1120. inline int getJuceParameterIndexForAUAddress (AUParameterAddress address) const noexcept
  1121. {
  1122. return usingManagedParameter ? paramMap[static_cast<int64> (address)]
  1123. : static_cast<int> (address);
  1124. }
  1125. #endif
  1126. //==============================================================================
  1127. static const double kDefaultSampleRate;
  1128. AudioProcessorHolder::Ptr processorHolder;
  1129. int totalInChannels, totalOutChannels;
  1130. ScopedPointer<AUAudioUnitBusArray> inputBusses;
  1131. ScopedPointer<AUAudioUnitBusArray> outputBusses;
  1132. ObjCBlock<AUImplementorValueObserver> paramObserver;
  1133. ObjCBlock<AUImplementorValueProvider> paramProvider;
  1134. #if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
  1135. bool usingManagedParameter;
  1136. Array<AUParameterAddress> paramAddresses;
  1137. HashMap<int64, int> paramMap;
  1138. #endif
  1139. // to avoid recursion on parameter changes, we need to add an
  1140. // editor observer to do the parameter changes
  1141. ObjCBlock<AUParameterObserver> editorParamObserver;
  1142. AUParameterObserverToken editorObserverToken;
  1143. ScopedPointer<AUParameterTree> paramTree;
  1144. ScopedPointer<NSMutableArray<NSNumber*>> overviewParams;
  1145. ScopedPointer<NSMutableArray<NSNumber*>> channelCapabilities;
  1146. ScopedPointer<NSMutableArray<AUAudioUnitPreset*> > factoryPresets;
  1147. ObjCBlock<AUInternalRenderBlock> internalRenderBlock;
  1148. AudioUnitHelpers::CoreAudioBufferList audioBuffer;
  1149. AudioUnitHelpers::ChannelRemapper mapper;
  1150. OwnedArray<BusBuffer> inBusBuffers, outBusBuffers;
  1151. MidiBuffer midiMessages;
  1152. ObjCBlock<AUHostMusicalContextBlock> hostMusicalContextCallback;
  1153. ObjCBlock<AUHostTransportStateBlock> hostTransportStateCallback;
  1154. AudioTimeStamp lastTimeStamp;
  1155. CurrentPositionInfo lastAudioHead;
  1156. String contextName;
  1157. };
  1158. const double JuceAudioUnitv3::kDefaultSampleRate = 44100.0;
  1159. JuceAudioUnitv3Base* JuceAudioUnitv3Base::create (AUAudioUnit* audioUnit, AudioComponentDescription descr, AudioComponentInstantiationOptions options, NSError** error)
  1160. {
  1161. PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnitv3;
  1162. return new JuceAudioUnitv3 (audioUnit, descr, options, error);
  1163. }
  1164. //==============================================================================
  1165. class JuceAUViewController
  1166. {
  1167. public:
  1168. JuceAUViewController (AUViewController<AUAudioUnitFactory>* p)
  1169. : myself (p)
  1170. {
  1171. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  1172. PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnitv3;
  1173. initialiseJuce_GUI();
  1174. }
  1175. ~JuceAUViewController()
  1176. {
  1177. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  1178. if (processorHolder != nullptr)
  1179. JuceAudioUnitv3::removeEditor (getAudioProcessor());
  1180. }
  1181. //==============================================================================
  1182. void loadView()
  1183. {
  1184. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  1185. if (AudioProcessor* p = createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))
  1186. {
  1187. processorHolder = new AudioProcessorHolder (p);
  1188. auto& processor = getAudioProcessor();
  1189. if (processor.hasEditor())
  1190. {
  1191. if (AudioProcessorEditor* editor = processor.createEditorIfNeeded())
  1192. {
  1193. preferredSize = editor->getBounds();
  1194. JUCE_IOS_MAC_VIEW* view = [[[JUCE_IOS_MAC_VIEW alloc] initWithFrame: convertToCGRect (editor->getBounds())] autorelease];
  1195. [myself setView: view];
  1196. editor->setVisible (true);
  1197. editor->addToDesktop (0, view);
  1198. }
  1199. }
  1200. }
  1201. }
  1202. void viewDidLayoutSubviews()
  1203. {
  1204. if (processorHolder != nullptr && [myself view] != nullptr)
  1205. {
  1206. if (AudioProcessorEditor* editor = getAudioProcessor().getActiveEditor())
  1207. {
  1208. if (processorHolder->viewConfiguration != nullptr)
  1209. editor->hostMIDIControllerIsAvailable (processorHolder->viewConfiguration->hostHasMIDIController);
  1210. editor->setBounds (convertToRectInt ([[myself view] bounds]));
  1211. if (JUCE_IOS_MAC_VIEW* peerView = [[[myself view] subviews] objectAtIndex: 0])
  1212. {
  1213. #if JUCE_IOS
  1214. [peerView setNeedsDisplay];
  1215. #else
  1216. [peerView setNeedsDisplay: YES];
  1217. #endif
  1218. }
  1219. }
  1220. }
  1221. }
  1222. CGSize getPreferredContentSize() const
  1223. {
  1224. return CGSizeMake (static_cast<float> (preferredSize.getWidth()),
  1225. static_cast<float> (preferredSize.getHeight()));
  1226. }
  1227. //==============================================================================
  1228. AUAudioUnit* createAudioUnit (const AudioComponentDescription& descr, NSError** error)
  1229. {
  1230. AUAudioUnit* retval = nil;
  1231. if (! MessageManager::getInstance()->isThisTheMessageThread())
  1232. {
  1233. WaitableEvent creationEvent;
  1234. // AUv3 headers say that we may block this thread and that the message thread is guaranteed
  1235. // to be unblocked
  1236. struct AUCreator : public CallbackMessage
  1237. {
  1238. JuceAUViewController& owner;
  1239. AudioComponentDescription pDescr;
  1240. NSError** pError;
  1241. AUAudioUnit*& outAU;
  1242. WaitableEvent& e;
  1243. AUCreator (JuceAUViewController& parent, const AudioComponentDescription& paramDescr, NSError** paramError,
  1244. AUAudioUnit*& outputAU, WaitableEvent& event)
  1245. : owner (parent), pDescr (paramDescr), pError (paramError), outAU (outputAU), e (event)
  1246. {}
  1247. void messageCallback() override
  1248. {
  1249. outAU = owner.createAudioUnitOnMessageThread (pDescr, pError);
  1250. e.signal();
  1251. }
  1252. };
  1253. (new AUCreator (*this, descr, error, retval, creationEvent))->post();
  1254. creationEvent.wait (-1);
  1255. }
  1256. else
  1257. retval = createAudioUnitOnMessageThread (descr, error);
  1258. return [retval autorelease];
  1259. }
  1260. private:
  1261. //==============================================================================
  1262. AUViewController<AUAudioUnitFactory>* myself;
  1263. AudioProcessorHolder::Ptr processorHolder = nullptr;
  1264. Rectangle<int> preferredSize { 1, 1 };
  1265. //==============================================================================
  1266. AUAudioUnit* createAudioUnitOnMessageThread (const AudioComponentDescription& descr, NSError** error)
  1267. {
  1268. jassert (MessageManager::getInstance()->isThisTheMessageThread());
  1269. [myself view]; // this will call [view load] and ensure that the AudioProcessor has been instantiated
  1270. if (processorHolder == nullptr)
  1271. return nullptr;
  1272. return (new JuceAudioUnitv3 (processorHolder, descr, 0, error))->getAudioUnit();
  1273. }
  1274. AudioProcessor& getAudioProcessor() const noexcept { return **processorHolder; }
  1275. };
  1276. //==============================================================================
  1277. // necessary glue code
  1278. @interface JUCE_VIEWCONTROLLER_OBJC_NAME (JucePlugin_AUExportPrefix) : AUViewController<AUAudioUnitFactory>
  1279. @end
  1280. @implementation JUCE_VIEWCONTROLLER_OBJC_NAME (JucePlugin_AUExportPrefix)
  1281. {
  1282. ScopedPointer<JuceAUViewController> cpp;
  1283. }
  1284. - (instancetype) initWithNibName: (nullable NSString*) nib bundle: (nullable NSBundle*) bndl { self = [super initWithNibName: nib bundle: bndl]; cpp = new JuceAUViewController (self); return self;}
  1285. - (void) loadView { cpp->loadView(); }
  1286. - (AUAudioUnit *)createAudioUnitWithComponentDescription:(AudioComponentDescription)desc error:(NSError **)error { return cpp->createAudioUnit (desc, error); }
  1287. - (CGSize) preferredContentSize { return cpp->getPreferredContentSize(); }
  1288. - (void)viewDidLayoutSubviews { return cpp->viewDidLayoutSubviews(); }
  1289. @end
  1290. //==============================================================================
  1291. #if JUCE_IOS
  1292. bool JUCE_CALLTYPE juce_isInterAppAudioConnected() { return false; }
  1293. void JUCE_CALLTYPE juce_switchToHostApplication() {}
  1294. #if JUCE_MODULE_AVAILABLE_juce_gui_basics
  1295. Image JUCE_CALLTYPE juce_getIAAHostIcon (int) { return Image(); }
  1296. #endif
  1297. #endif
  1298. #pragma clang diagnostic pop
  1299. #endif