26#if JUCE_PLUGINHOST_AU && (JUCE_MAC || JUCE_IOS)
28JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
31#include <AudioUnit/AUCocoaUIView.h>
32#include <CoreAudioKit/AUGenericView.h>
33#include <AudioToolbox/AudioUnitUtilities.h>
35#if JUCE_PLUGINHOST_ARA
36 #include <ARA_API/ARAAudioUnit.h>
41#include <CoreMIDI/MIDIServices.h>
43#include <CoreAudioKit/AUViewController.h>
45#include <juce_audio_basics/native/juce_CoreAudioTimeConversions_mac.h>
46#include <juce_audio_basics/native/juce_CoreAudioLayouts_mac.h>
47#include "juce_AU_Shared.h"
58 #define JUCE_AU_LOG(a) Logger::writeToLog(a);
60 #define JUCE_AU_LOG(a)
80 if (s.trim().length() >= 4)
85 return (((
OSType) (
unsigned char) s[0]) << 24)
86 | (((
OSType) (
unsigned char) s[1]) << 16)
87 | (((
OSType) (
unsigned char) s[2]) << 8)
88 | ((
OSType) (
unsigned char) s[3]);
125 if (name.containsChar (
':'))
127 manufacturer = name.upToFirstOccurrenceOf (
":",
false,
false).trim();
128 name = name.fromFirstOccurrenceOf (
":",
false,
false).trim();
136 String& name, String& version, String& manufacturer)
140 String s (fileOrIdentifier.substring (
jmax (fileOrIdentifier.lastIndexOfChar (
':'),
141 fileOrIdentifier.lastIndexOfChar (
'/')) + 1));
144 tokens.addTokens (s,
",", StringRef());
145 tokens.removeEmptyStrings();
147 if (tokens.size() == 3)
158 if (manufacturer.isEmpty())
159 manufacturer = tokens[2];
161 if (version.isEmpty())
192 const File file (fileOrIdentifier);
193 if (! file.hasFileExtension (
".component") && ! file.hasFileExtension (
".appex"))
196 const char*
const utf8 = fileOrIdentifier.toUTF8();
209 name = file.getFileNameWithoutExtension();
224 explicit ScopedBundleResourceMap (CFBundleRef refIn) :
ref (refIn),
225 resFileId (CFBundleOpenBundleResourceMap (
ref)),
226 valid (resFileId != -1)
229 UseResFile (resFileId);
232 ~ScopedBundleResourceMap()
235 CFBundleCloseBundleResourceMap (ref, resFileId);
238 bool isValid() const noexcept
244 const CFBundleRef
ref;
245 const ResFileRefNum resFileId;
272 desc.componentType = types[0];
273 desc.componentSubType = types[1];
274 desc.componentManufacturer = types[2];
303 return desc.componentType != 0 && desc.componentSubType != 0;
307 static const char* getCategory (
OSType type)
noexcept
326 #if JUCE_MAC || JUCE_IOS
328 #define JUCE_IOS_MAC_VIEW UIView
331 #define JUCE_IOS_MAC_VIEW NSView
338 void childBoundsChanged (Component*)
override { triggerAsyncUpdate(); }
339 void handleAsyncUpdate()
override { resizeToFitView(); }
343 template <
typename Value>
374 void setUpMapping (AudioUnit comp,
bool isInput)
379 const auto scope = isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output;
380 const auto n = getElementCount (comp, scope);
382 for (UInt32 busIndex = 0; busIndex < n; ++busIndex)
386 if (
const auto layout = tryGetProperty<AudioChannelLayout> (comp, kAudioUnitProperty_AudioChannelLayout, scope, busIndex))
388 const auto juceChannelOrder = CoreAudioLayouts::fromCoreAudio (*layout);
389 const auto auChannelOrder = CoreAudioLayouts::getCoreAudioLayoutChannels (*layout);
391 for (
auto juceChannelIndex = 0; juceChannelIndex < juceChannelOrder.size(); ++juceChannelIndex)
392 busMap.
push_back ((
size_t) auChannelOrder.indexOf (juceChannelOrder.getTypeOfChannel (juceChannelIndex)));
395 busOffset.push_back (busMap.
empty() ? unknownChannelCount : channels.
size());
396 channels.insert (channels.end(), busMap.
begin(), busMap.
end());
400 size_t getAuIndexForJuceChannel (
size_t bus,
size_t channel)
const noexcept
402 const auto baseOffset = busOffset[bus];
403 return baseOffset != unknownChannelCount ? channels[baseOffset + channel]
430 if (@available (
macOS 10.11, *))
439 #if JUCE_PLUGINHOST_ARA
444 ARA::kAudioUnitProperty_ARAFactory,
468 #if JUCE_PLUGINHOST_ARA
472 ARA::ARAAudioUnitFactory
audioUnitFactory { ARA::kARAAudioUnitMagic,
nullptr };
477 ARA::kAudioUnitProperty_ARAFactory,
483 if ((status ==
noErr)
511 if (@available (
macOS 10.11, *))
517 callback (audioUnit, err);
535 bool isValid()
const {
return component.audioComponent !=
nullptr; }
547 if (!
format.fileMightContainThisPluginType (desc.fileOrIdentifier))
609 AUInstanceParameter (AudioUnitPluginInstance& parent,
611 const String& parameterName,
612 AudioUnitParameterValue minParameterValue,
613 AudioUnitParameterValue maxParameterValue,
614 AudioUnitParameterValue defaultParameterValue,
615 bool parameterIsAutomatable,
616 bool parameterIsDiscrete,
617 int numParameterSteps,
620 bool parameterValuesHaveStrings)
621 : pluginInstance (parent),
622 paramID (parameterID),
623 name (parameterName),
624 minValue (minParameterValue),
625 maxValue (maxParameterValue),
626 range (maxValue - minValue),
627 automatable (parameterIsAutomatable),
628 discrete (parameterIsDiscrete),
629 numSteps (numParameterSteps),
630 valuesHaveStrings (parameterValuesHaveStrings),
631 isSwitch (isBoolean),
633 defaultValue (normaliseParamValue (defaultParameterValue))
635 auValueStrings = Parameter::getAllValueStrings();
638 float getValue()
const override
642 AudioUnitParameterValue value = 0;
644 if (
auto* au = pluginInstance.audioUnit)
646 AudioUnitGetParameter (au, paramID, kAudioUnitScope_Global, 0, &value);
647 value = normaliseParamValue (value);
653 void setValue (
float newValue)
override
657 if (
auto* au = pluginInstance.audioUnit)
659 AudioUnitSetParameter (au, paramID, kAudioUnitScope_Global,
660 0, scaleParamValue (newValue), 0);
662 sendParameterChangeEvent();
666 float getDefaultValue()
const override
671 String getName (
int )
const override {
return name; }
672 String getLabel()
const override {
return valueLabel; }
674 String getText (
float value,
int maximumLength)
const override
676 if (! auValueStrings.isEmpty())
678 auto index =
roundToInt (jlimit (0.0f, 1.0f, value) * (
float) (auValueStrings.size() - 1));
679 return auValueStrings[index];
682 auto scaledValue = scaleParamValue (value);
684 if (valuesHaveStrings)
686 if (
auto* au = pluginInstance.audioUnit)
688 AudioUnitParameterStringFromValue stringValue;
689 stringValue.inParamID = paramID;
690 stringValue.inValue = &scaledValue;
691 stringValue.outString =
nullptr;
693 UInt32 propertySize =
sizeof (stringValue);
695 auto err = AudioUnitGetProperty (au,
696 kAudioUnitProperty_ParameterStringFromValue,
697 kAudioUnitScope_Global,
702 if (! err && stringValue.outString !=
nullptr)
703 return String::fromCFString (stringValue.outString).substring (0, maximumLength);
707 return Parameter::getText (scaledValue, maximumLength);
710 float getValueForText (
const String& text)
const override
712 if (! auValueStrings.isEmpty())
714 auto index = auValueStrings.indexOf (text);
717 return ((
float) index) / (
float) (auValueStrings.size() - 1);
720 if (valuesHaveStrings)
722 if (
auto* au = pluginInstance.audioUnit)
724 AudioUnitParameterValueFromString pvfs;
725 pvfs.inParamID = paramID;
726 CFUniquePtr<CFStringRef> cfString (text.toCFString());
727 pvfs.inString = cfString.get();
728 UInt32 propertySize =
sizeof (pvfs);
730 auto err = AudioUnitGetProperty (au,
731 kAudioUnitProperty_ParameterValueFromString,
732 kAudioUnitScope_Global,
738 return normaliseParamValue (pvfs.outValue);
742 return Parameter::getValueForText (text);
745 bool isAutomatable()
const override {
return automatable; }
746 bool isDiscrete()
const override {
return discrete; }
747 bool isBoolean()
const override {
return isSwitch; }
748 int getNumSteps()
const override {
return numSteps; }
750 StringArray getAllValueStrings()
const override
752 return auValueStrings;
755 String getParameterID()
const override
757 return String (paramID);
760 void sendParameterChangeEvent()
763 jassert (pluginInstance.audioUnit !=
nullptr);
766 ev.mEventType = kAudioUnitEvent_ParameterValueChange;
767 ev.mArgument.mParameter.mAudioUnit = pluginInstance.audioUnit;
768 ev.mArgument.mParameter.mParameterID = paramID;
769 ev.mArgument.mParameter.mScope = kAudioUnitScope_Global;
770 ev.mArgument.mParameter.mElement = 0;
772 AUEventListenerNotify (pluginInstance.eventListenerRef,
nullptr, &ev);
776 float normaliseParamValue (
float scaledValue)
const noexcept
778 return (scaledValue - minValue) / range;
781 float scaleParamValue (
float normalisedValue)
const noexcept
783 return minValue + (range * normalisedValue);
786 UInt32 getRawParamID()
const {
return paramID; }
788 void setName (String&& newName) { name = std::move (newName); }
789 void setLabel (String&& newLabel) { valueLabel = std::move (newLabel); }
792 AudioUnitPluginInstance& pluginInstance;
793 const UInt32 paramID;
795 const AudioUnitParameterValue minValue, maxValue, range;
796 const bool automatable, discrete;
798 const bool valuesHaveStrings, isSwitch;
800 const AudioUnitParameterValue defaultValue;
801 StringArray auValueStrings;
836 jassert (AudioUnitFormatHelpers::insideCallback.
get() == 0);
843 AUDeleter (AudioUnitPluginInstance& inInstance, WaitableEvent& inEvent)
844 : auInstance (inInstance), completionSignal (inEvent)
847 void messageCallback()
override
849 auInstance.cleanup();
850 completionSignal.signal();
853 AudioUnitPluginInstance& auInstance;
854 WaitableEvent& completionSignal;
884 bool initialise (
double rate,
int blockSize)
887 setRateAndBufferSizeDetails (rate, blockSize);
888 setLatencySamples (0);
889 refreshParameterList();
901 bool canRemoveBus (
bool isInput)
const override {
return isBusCountWritable (isInput); }
922 bool isBusesLayoutSupported (
const BusesLayout&
layouts)
const override
924 if (
layouts == getBusesLayout())
927 for (
int dir = 0; dir < 2; ++dir)
929 const bool isInput = (dir == 0);
933 const int n = getBusCount (isInput);
953 auto&
thisChannels = (isInput ? info.inChannels : info.outChannels);
954 auto&
opChannels = (isInput ? info.outChannels : info.inChannels);
996 for (
int dir = 0; dir < 2; ++dir)
998 const bool isInput = (dir == 0);
1000 const int n = getBusCount (isInput);
1011 for (
int i = 0; i < n; ++i)
1018 const AudioChannelSet& set =
layouts.getChannelSet (isInput, i);
1023 UInt32 dataSize =
sizeof (stream);
1026 if (
err !=
noErr || dataSize <
sizeof (stream))
1035 stream.mSampleRate = sampleRate;
1038 stream.mFramesPerPacket = 1;
1039 stream.mBytesPerPacket = 4;
1040 stream.mBytesPerFrame = 4;
1041 stream.mBitsPerChannel = 32;
1049 if (! set.isDiscreteLayout())
1077 actualTag = CoreAudioLayouts::toCoreAudio (CoreAudioLayouts::fromCoreAudio (layout));
1099 bool canApplyBusesLayout (
const BusesLayout&
layouts)
const override
1130 void fillInPluginDescription (PluginDescription& desc)
const override
1134 desc.fileOrIdentifier = AudioUnitFormatHelpers::createPluginIdentifier (
componentDesc);
1138 desc.lastFileModTime = Time();
1140 desc.pluginFormatName =
"AudioUnit";
1141 desc.category = AudioUnitFormatHelpers::getCategory (
componentDesc.componentType);
1142 desc.manufacturerName = manufacturer;
1143 desc.version = version;
1144 desc.numInputChannels = getTotalNumInputChannels();
1145 desc.numOutputChannels = getTotalNumOutputChannels();
1148 #if JUCE_PLUGINHOST_ARA
1149 desc.hasARAExtension = [&]
1155 ARA::kAudioUnitProperty_ARAFactory,
1166 void getExtensions (ExtensionsVisitor& visitor)
const override
1170 explicit Extensions (
const AudioUnitPluginInstance* instanceIn) : instance (instanceIn) {}
1172 AudioUnit getAudioUnitHandle() const noexcept
override {
return instance->audioUnit; }
1174 const AudioUnitPluginInstance* instance =
nullptr;
1177 visitor.visitAudioUnitClient (
Extensions {
this });
1179 #ifdef JUCE_PLUGINHOST_ARA
1182 explicit ARAExtensions (
const AudioUnitPluginInstance* instanceIn) : instance (instanceIn) {}
1186 getOrCreateARAAudioUnit ({ instance->auComponent, instance->isAUv3 },
1187 [origCb = std::move (cb)] (
auto dylibKeepAliveAudioUnit)
1189 origCb ([&]() -> ARAFactoryWrapper
1191 if (dylibKeepAliveAudioUnit !=
nullptr)
1194 return ARAFactoryWrapper {
nullptr };
1199 const AudioUnitPluginInstance* instance =
nullptr;
1208 const String getName()
const override {
return pluginName; }
1210 double getTailLengthSeconds()
const override
1235 for (
int dir = 0; dir < 2; ++dir)
1237 const bool isInput = (dir == 0);
1239 const int n = getBusCount (isInput);
1241 for (
int i = 0; i < n; ++i)
1254 UInt32 dataSize =
sizeof (stream);
1257 if (
err ==
noErr && dataSize ==
sizeof (stream))
1259 stream.mSampleRate =
sr;
1274 info.inputProcRefCon =
this;
1278 static_cast<UInt32> (i), &info,
sizeof (info));
1313 refreshParameterList();
1334 void releaseResources()
override
1346 incomingMidi.clear();
1358 const auto position =
playhead !=
nullptr ?
playhead->getPosition() : nullopt;
1360 if (
const auto hostTimeNs = position.hasValue() ? position->getHostTimeNs() : nullopt)
1379 const auto numSamples = buffer.getNumSamples();
1400 const auto*
bus = getBus (
false, i);
1401 const auto channelCount =
bus !=
nullptr ?
bus->getNumberOfChannels() : 0;
1441 for (
int i = getTotalNumOutputChannels(); --i >= 0;)
1442 buffer.clear (i, 0, buffer.getNumSamples());
1449 incomingMidi.clear();
1453 void processBlock (AudioBuffer<float>& buffer, MidiBuffer&
midiMessages)
override
1458 void processBlockBypassed (AudioBuffer<float>& buffer, MidiBuffer&
midiMessages)
override
1466 bool hasEditor()
const override
1476 && dataSize ==
sizeof (uintptr_t) &&
isWritable != 0);
1480 AudioProcessorEditor* createEditor()
override;
1482 static AudioProcessor::BusesProperties
getBusesProperties (AudioComponentInstance comp)
1486 for (
int dir = 0; dir < 2; ++dir)
1488 const auto isInput = (dir == 0);
1491 for (
UInt32 i = 0; i < n; ++i)
1510 return "Input " + String (index + 1);
1518 return "Output " + String (index + 1);
1544 ScopedFactoryPresets (AudioUnit& au)
1546 UInt32 sz =
sizeof (CFArrayRef);
1547 AudioUnitGetProperty (au, kAudioUnitProperty_FactoryPresets,
1548 kAudioUnitScope_Global, 0, &presets.object, &sz);
1551 CFArrayRef
get() const noexcept
1553 return presets.object;
1557 CFObjectHolder<CFArrayRef> presets;
1560 int getNumPrograms()
override
1570 int getCurrentProgram()
override
1573 current.presetNumber = 0;
1579 return current.presetNumber;
1582 void setCurrentProgram (
int newIndex)
override
1593 current.presetName = p->presetName;
1602 const String getProgramName (
int index)
override
1607 current.presetNumber = -1;
1608 current.presetName =
CFSTR (
"");
1624 if (p->presetNumber == index)
1631 void changeProgramName (
int ,
const String& )
override
1637 void updateTrackProperties (
const TrackProperties& properties)
override
1639 if (properties.name.isNotEmpty())
1648 void getStateInformation (MemoryBlock& destData)
override
1650 getCurrentProgramStateInformation (destData);
1653 void getCurrentProgramStateInformation (MemoryBlock& destData)
override
1671 destData.setSize ((
size_t) bytesWritten);
1676 void setStateInformation (
const void* data,
int sizeInBytes)
override
1678 setCurrentProgramStateInformation (data, sizeInBytes);
1681 void setCurrentProgramStateInformation (
const void* data,
int sizeInBytes)
override
1700 void refreshParameterList()
override
1731 if (! info.isValid())
1740 auto parameter = std::make_unique<AUInstanceParameter> (*
this,
1743 info.get().minValue,
1744 info.get().maxValue,
1745 info.get().defaultValue,
1748 isDiscrete ? (
int) (info.get().maxValue - info.get().minValue + 1.0f) : AudioProcessor::getDefaultNumParameterSteps(),
1777 return String (info.get().clumpID);
1780 auto group = std::make_unique<AudioProcessorParameterGroup> (String (info.get().clumpID),
1782 group->addChild (std::move (parameter));
1783 groupIDMap[info.get().clumpID] = group.get();
1788 groupInfo->second->addChild (std::move (parameter));
1820 void handleIncomingMidiMessage (
void*,
const MidiMessage& message)
1823 incomingMidi.addEvent (message, 0);
1826 void handlePartialSysexMessage (
void*,
const uint8*,
int,
double) {}
1833 friend class AudioUnitPluginFormat;
1840 String fileOrIdentifier;
1841 CriticalSection
lock;
1849 AUBuffer (
size_t numBuffers)
1851 bufferList.calloc (1, (
sizeof (AudioBufferList) -
sizeof (::AudioBuffer)) + (
sizeof (::AudioBuffer) * numBuffers));
1852 AudioBufferList& buffer = *bufferList.get();
1854 buffer.mNumberBuffers =
static_cast<UInt32
> (numBuffers);
1857 operator AudioBufferList&()
1859 return *bufferList.get();
1862 HeapBlock<AudioBufferList> bufferList;
1868 AUBypassParameter (AudioUnitPluginInstance& effectToUse)
1869 : parent (effectToUse), currentValue (getCurrentHostValue())
1872 bool getCurrentHostValue()
1874 if (parent.auSupportsBypass)
1876 UInt32 dataSize =
sizeof (UInt32);
1879 if (AudioUnitGetProperty (parent.audioUnit, kAudioUnitProperty_BypassEffect,
1880 kAudioUnitScope_Global, 0, &value, &dataSize) == noErr
1881 && dataSize ==
sizeof (UInt32))
1888 float getValue()
const override
1890 return currentValue ? 1.0f : 0.0f;
1893 void setValue (
float newValue)
override
1895 auto newBypassValue = (newValue != 0.0f);
1899 if (newBypassValue != currentValue)
1901 currentValue = newBypassValue;
1903 if (parent.auSupportsBypass)
1905 UInt32 value = (newValue != 0.0f ? 1 : 0);
1906 AudioUnitSetProperty (parent.audioUnit, kAudioUnitProperty_BypassEffect,
1907 kAudioUnitScope_Global, 0, &value, sizeof (UInt32));
1910 jassert (parent.audioUnit !=
nullptr);
1913 ev.mEventType = kAudioUnitEvent_PropertyChange;
1914 ev.mArgument.mProperty.mAudioUnit = parent.audioUnit;
1915 ev.mArgument.mProperty.mPropertyID = kAudioUnitProperty_BypassEffect;
1916 ev.mArgument.mProperty.mScope = kAudioUnitScope_Global;
1917 ev.mArgument.mProperty.mElement = 0;
1919 AUEventListenerNotify (parent.eventListenerRef,
nullptr, &ev);
1925 float getValueForText (
const String& text)
const override
1927 String lowercaseText (text.toLowerCase());
1929 for (
auto& testText : auOnStrings)
1930 if (lowercaseText == testText)
1933 for (
auto& testText : auOffStrings)
1934 if (lowercaseText == testText)
1937 return text.getIntValue() != 0 ? 1.0f : 0.0f;
1940 float getDefaultValue()
const override {
return 0.0f; }
1941 String getName (
int )
const override {
return "Bypass"; }
1942 String getText (
float value,
int)
const override {
return (value != 0.0f ?
TRANS (
"On") :
TRANS (
"Off")); }
1943 bool isAutomatable()
const override {
return true; }
1944 bool isDiscrete()
const override {
return true; }
1945 bool isBoolean()
const override {
return true; }
1946 int getNumSteps()
const override {
return 2; }
1947 StringArray getAllValueStrings()
const override {
return values; }
1948 String getLabel()
const override {
return {}; }
1950 String getParameterID()
const override {
return {}; }
1952 AudioUnitPluginInstance& parent;
1953 const StringArray auOnStrings {
TRANS (
"on"),
TRANS (
"yes"),
TRANS (
"true") };
1954 const StringArray auOffStrings {
TRANS (
"off"),
TRANS (
"no"),
TRANS (
"false") };
1955 const StringArray values {
TRANS (
"Off"),
TRANS (
"On") };
1957 bool currentValue =
false;
1978 MidiBuffer incomingMidi;
1993 info.userData =
this;
2004 info.hostUserData =
this;
2034 for (
auto* param : getParameters())
2039 event.mArgument.mParameter.mAudioUnit =
audioUnit;
2042 event.mArgument.mParameter.mElement = 0;
2064 event.mArgument.mProperty.mPropertyID = type;
2065 event.mArgument.mProperty.mAudioUnit =
audioUnit;
2067 event.mArgument.mProperty.mElement = 0;
2083 if (param ==
nullptr)
2087 param->sendValueChangedMessageToListeners (param->normaliseParamValue (newValue));
2089 param->beginChangeGesture();
2091 param->endChangeGesture();
2096 switch (
prop.mPropertyID)
2100 updateHostDisplay (AudioProcessorListener::ChangeDetails().withParameterInfoChanged (
true));
2105 updateHostDisplay (AudioProcessorListener::ChangeDetails().withProgramChanged (
true));
2137 if (! info.isValid())
2152 ScopedAudioUnitParameterInfo (AudioUnit au, UInt32 paramId)
2154 auto sz = (UInt32)
sizeof (info);
2155 valid = noErr == AudioUnitGetProperty (au,
2156 kAudioUnitProperty_ParameterInfo,
2157 kAudioUnitScope_Global,
2163 ScopedAudioUnitParameterInfo (
const ScopedAudioUnitParameterInfo&) =
delete;
2164 ScopedAudioUnitParameterInfo (ScopedAudioUnitParameterInfo&&) =
delete;
2165 ScopedAudioUnitParameterInfo& operator= (
const ScopedAudioUnitParameterInfo&) =
delete;
2166 ScopedAudioUnitParameterInfo& operator= (ScopedAudioUnitParameterInfo&&) =
delete;
2168 ~ScopedAudioUnitParameterInfo() noexcept
2170 if ((info.flags & kAudioUnitParameterFlag_CFNameRelease) == 0)
2173 if (info.cfNameString !=
nullptr)
2174 CFRelease (info.cfNameString);
2176 if (info.unit == kAudioUnitParameterUnit_CustomUnit && info.unitName !=
nullptr)
2177 CFRelease (info.unitName);
2180 bool isValid()
const {
return valid; }
2182 const AudioUnitParameterInfo&
get() const noexcept {
return info; }
2185 AudioUnitParameterInfo info;
2192 return { info.name,
sizeof (info.name) };
2229 const auto buffer =
static_cast<int> (
inBusNumber) < getBusCount (
true)
2231 : AudioBuffer<
float>();
2237 if (
auChannel < buffer.getNumChannels())
2263 template <
typename Type1,
typename Type2>
2266 if (p !=
nullptr) *p = value;
2279 template <
typename Result>
2282 if (
auto*
ph = getPlayHead())
2283 if (
const auto pos =
ph->getPosition())
2284 return ((*pos).*
member)();
2379 return static_cast<int> (AudioUnitFormatHelpers::getElementCount (
audioUnit, scope));
2391 busName = (isInput ?
"Input #" :
"Output #") + String (
busIdx + 1);
2421 void numBusesChanged()
override
2433 for (
int dir = 0; dir < 2; ++dir)
2435 const bool isInput = (dir == 0);
2544 bool supportsMPE()
const override
2551 && dataSize ==
sizeof (
UInt32))
2590 : AudioProcessorEditor (&p),
2593 addAndMakeVisible (wrapper);
2604 if (wrapper.getView() !=
nil)
2606 wrapper.setVisible (
false);
2607 removeChildComponent (&wrapper);
2608 wrapper.setView (
nil);
2609 plugin.editorBeingDeleted (
this);
2620 wrapper.resizeToFitView();
2623 wrapper.setSize (
static_cast<int> (
size.width),
static_cast<int> (
size.height));
2629 void paint (Graphics& g)
override
2631 g.fillAll (Colours::white);
2634 void resized()
override
2636 wrapper.setSize (getWidth(), getHeight());
2639 void childBoundsChanged (Component*)
override
2641 setSize (wrapper.getWidth(), wrapper.getHeight());
2647 AudioUnitFormatHelpers::AutoResizingNSViewComponent wrapper;
2667 info.calloc (dataSize, 1);
2670 0, info, &dataSize) ==
noErr)
2684 withSize:
NSMakeSize (getWidth(), getHeight())];
2690 CFRelease (info->mCocoaAUViewBundleLocation);
2717 String name, version, manufacturer;
2718 AudioUnitFormatHelpers::getComponentDescFromIdentifier (
"AudioUnit:Output/auou,genr,appl",
2719 desc, name, version, manufacturer);
2729 wrapper.resizeToFitView();
2736 const auto viewSize = [&controller]
2740 if (@available (
macOS 10.11, *))
2744 size = controller.view.frame.size;
2754 AudioUnitPluginWindowCocoa* owner;
2755 JUCE_IOS_MAC_VIEW* controllerView;
2758 AsyncViewControllerCallback (AudioUnitPluginWindowCocoa* plugInWindow, JUCE_IOS_MAC_VIEW* inView,
2759 const CGSize& preferredSize)
2760 : owner (plugInWindow), controllerView ([inView retain]),
size (preferredSize)
2763 void messageCallback()
override
2765 owner->embedViewController (controllerView, size);
2766 [controllerView release];
2780AudioProcessorEditor* AudioUnitPluginInstance::createEditor()
2791AudioUnitPluginFormat::AudioUnitPluginFormat()
2795AudioUnitPluginFormat::~AudioUnitPluginFormat()
2800 const String& fileOrIdentifier)
2805 PluginDescription desc;
2806 desc.fileOrIdentifier = fileOrIdentifier;
2807 desc.uniqueId = desc.deprecatedUid = 0;
2810 && requiresUnblockedMessageThreadDuringCreation (desc))
2818 results.add (
new PluginDescription (
auInstance->getPluginDescription()));
2826void AudioUnitPluginFormat::createPluginInstance (
const PluginDescription& desc,
2827 double rate,
int blockSize,
2828 PluginCreationCallback callback)
2843 auto instance = std::make_unique<AudioUnitPluginInstance> (audioUnit);
2845 if (instance->initialise (rate, blockSize))
2846 origCallback (std::move (instance), {});
2848 origCallback (nullptr, NEEDS_TRANS (
"Unable to initialise the AudioUnit plug-in"));
2852 auto errMsg = TRANS (
"An OS error occurred during initialisation of the plug-in (XXX)");
2853 origCallback (nullptr, errMsg.replace (
"XXX", String (err)));
2858void AudioUnitPluginFormat::createARAFactoryAsync (
const PluginDescription& desc, ARAFactoryCreationCallback callback)
2860 auto auComponentResult = getAudioComponent (*
this, desc);
2862 if (! auComponentResult.isValid())
2864 callback ({ {},
"Failed to create AudioComponent for " + desc.descriptiveName });
2868 getOrCreateARAAudioUnit (auComponentResult.component, [cb = std::move (callback)] (
auto dylibKeepAliveAudioUnit)
2870 cb ([&]() -> ARAFactoryResult
2872 if (dylibKeepAliveAudioUnit != nullptr)
2873 return { ARAFactoryWrapper { ::juce::getARAFactory (std::move (dylibKeepAliveAudioUnit)) },
"" };
2875 return { {},
"Failed to create ARAFactory from the provided AudioUnit" };
2880bool AudioUnitPluginFormat::requiresUnblockedMessageThreadDuringCreation (
const PluginDescription& desc)
const
2882 String pluginName, version, manufacturer;
2883 AudioComponentDescription componentDesc;
2885 if (AudioUnitFormatHelpers::getComponentDescFromIdentifier (desc.fileOrIdentifier, componentDesc,
2886 pluginName, version, manufacturer)
2887 || AudioUnitFormatHelpers::getComponentDescFromFile (desc.fileOrIdentifier, componentDesc,
2888 pluginName, version, manufacturer))
2890 if (AudioComponent auComp = AudioComponentFindNext (
nullptr, &componentDesc))
2892 if (AudioComponentGetDescription (auComp, &componentDesc) == noErr)
2893 return AudioUnitFormatHelpers::isPluginAUv3 (componentDesc);
2900StringArray AudioUnitPluginFormat::searchPathsForPlugins (
const FileSearchPath&,
bool ,
bool allowPluginsWhichRequireAsynchronousInstantiation)
2903 AudioComponent comp =
nullptr;
2907 AudioComponentDescription desc;
2910 comp = AudioComponentFindNext (comp, &desc);
2912 if (comp ==
nullptr)
2915 if (AudioComponentGetDescription (comp, &desc) != noErr)
2918 if (desc.componentType == kAudioUnitType_MusicDevice
2919 || desc.componentType == kAudioUnitType_MusicEffect
2920 || desc.componentType == kAudioUnitType_Effect
2921 || desc.componentType == kAudioUnitType_Generator
2922 || desc.componentType == kAudioUnitType_Panner
2923 || desc.componentType == kAudioUnitType_Mixer
2924 || desc.componentType == kAudioUnitType_MIDIProcessor)
2926 if (allowPluginsWhichRequireAsynchronousInstantiation || ! AudioUnitFormatHelpers::isPluginAUv3 (desc))
2927 result.add (AudioUnitFormatHelpers::createPluginIdentifier (desc));
2934bool AudioUnitPluginFormat::fileMightContainThisPluginType (
const String& fileOrIdentifier)
2936 AudioComponentDescription desc;
2937 String name, version, manufacturer;
2939 if (AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer))
2940 return AudioComponentFindNext (
nullptr, &desc) !=
nullptr;
2942 auto f = File::createFileWithoutCheckingPath (fileOrIdentifier);
2944 return (f.hasFileExtension (
".component") || f.hasFileExtension (
".appex"))
2948String AudioUnitPluginFormat::getNameOfPluginFromIdentifier (
const String& fileOrIdentifier)
2950 AudioComponentDescription desc;
2951 String name, version, manufacturer;
2952 AudioUnitFormatHelpers::getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer);
2955 name = fileOrIdentifier;
2960bool AudioUnitPluginFormat::pluginNeedsRescanning (
const PluginDescription& desc)
2962 AudioComponentDescription newDesc;
2963 String name, version, manufacturer;
2965 return ! (AudioUnitFormatHelpers::getComponentDescFromIdentifier (desc.fileOrIdentifier, newDesc,
2966 name, version, manufacturer)
2967 && version == desc.version);
2970bool AudioUnitPluginFormat::doesPluginStillExist (
const PluginDescription& desc)
2972 if (desc.fileOrIdentifier.startsWithIgnoreCase (AudioUnitFormatHelpers::auIdentifierPrefix))
2973 return fileMightContainThisPluginType (desc.fileOrIdentifier);
2975 return File (desc.fileOrIdentifier).exists();
2978FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch()
2987JUCE_END_IGNORE_WARNINGS_GCC_LIKE
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
Create a canonical channel set for a given number of channels.
Optional< double > getBpm() const
Returns the bpm, if available.
Optional< int64_t > getTimeInSamples() const
Returns the number of samples that have elapsed.
Optional< double > getPpqPositionOfLastBarStart() const
The position of the start of the last bar, in units of quarter-notes.
Optional< double > getPpqPosition() const
The current play position, in units of quarter-notes.
Optional< TimeSignature > getTimeSignature() const
Returns the time signature, if available.
Optional< LoopPoints > getLoopPoints() const
Returns host loop points, if available.
bool getIsPlaying() const
True if the transport is currently playing.
bool getIsLooping() const
True if the transport is currently looping.
virtual void processBlockBypassed(AudioBuffer< float > &buffer, MidiBuffer &midiMessages)
Renders the next block when the processor is being bypassed.
bool isThisTheMessageThread() const noexcept
Returns true if the caller-thread is the message thread.
static MessageManager * getInstance()
Returns the global instance of the MessageManager.
static String fromCFString(CFStringRef cfString)
OSX ONLY - Creates a String from an OSX CFString.
static double getMillisecondCounterHiRes() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
#define TRANS(stringLiteral)
Uses the LocalisedStrings class to translate the given string literal.
#define NEEDS_TRANS(stringLiteral)
A dummy version of the TRANS macro, used to indicate a string literal that should be added to the tra...
#define JUCE_ASSERT_MESSAGE_THREAD
This macro is used to catch unsafe use of functions which expect to only be called on the message thr...
auto & get(ProcessorChain< Processors... > &chain) noexcept
Non-member equivalent of ProcessorChain::get which avoids awkward member template syntax.
CriticalSection::ScopedLockType ScopedLock
Automatically locks and unlocks a CriticalSection object.
void zerostruct(Type &structure) noexcept
Overwrites a structure or object with zeros.
wchar_t juce_wchar
A platform-independent 32-bit unicode character type.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
void createARAFactoryAsync(AudioPluginInstance &instance, std::function< void(ARAFactoryWrapper)> cb)
Calls the provided callback with an ARAFactoryWrapper object obtained from the provided AudioPluginIn...
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
unsigned char uint8
A platform-independent 8-bit unsigned integer type.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
void zeromem(void *memory, size_t numBytes) noexcept
Fills a block of memory with zeros.