1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-02-03 03:30:06 +00:00

Tidied up some AUv3 code

This commit is contained in:
jules 2016-04-08 16:07:25 +01:00
parent 5049babe51
commit 32178f4a1f
3 changed files with 193 additions and 182 deletions

View file

@ -50,9 +50,9 @@
#endif
#if JUCE_IOS
#define IOS_MAC_VIEW UIView
#define JUCE_IOS_MAC_VIEW UIView
#else
#define IOS_MAC_VIEW NSView
#define JUCE_IOS_MAC_VIEW NSView
#endif
#define JUCE_AUDIOUNIT_OBJC_NAME(x) JUCE_JOIN_MACRO (x, AUv3)
@ -63,32 +63,32 @@
JUCE_DEFINE_WRAPPER_TYPE (wrapperType_AudioUnitv3);
// TODO: ask Timur: use SFINAE to automatically generate this for all NSObjects
template <> struct ContainerDeletePolicy<AUAudioUnitBusArray> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUParameterTree> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<AUParameterNode *> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUParameter> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<AUAudioUnitBus*> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUAudioUnitBus> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AVAudioFormat> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AVAudioPCMBuffer> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<NSNumber*> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSNumber> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<AUAudioUnitPreset*> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUAudioUnitPreset> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUAudioUnitBusArray> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUParameterTree> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<AUParameterNode *> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUParameter> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<AUAudioUnitBus*> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUAudioUnitBus> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AVAudioFormat> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AVAudioPCMBuffer> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<NSNumber*> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSNumber> { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<NSMutableArray<AUAudioUnitPreset*> > { static void destroy (NSObject* o) { [o release]; } };
template <> struct ContainerDeletePolicy<AUAudioUnitPreset> { static void destroy (NSObject* o) { [o release]; } };
//==============================================================================
struct AudioProcessorHolder : public ReferenceCountedObject
{
AudioProcessorHolder() {}
AudioProcessorHolder (AudioProcessor* p) : juceFilter (p) {}
AudioProcessor& operator*() noexcept { return *juceFilter; }
AudioProcessor* operator->() noexcept { return juceFilter; }
AudioProcessor* get() noexcept { return juceFilter; }
AudioProcessorHolder (AudioProcessor* p) : processor (p) {}
AudioProcessor& operator*() noexcept { return *processor; }
AudioProcessor* operator->() noexcept { return processor; }
AudioProcessor* get() noexcept { return processor; }
typedef ReferenceCountedObjectPtr<AudioProcessorHolder> Ptr;
private:
ScopedPointer<AudioProcessor> juceFilter;
ScopedPointer<AudioProcessor> processor;
AudioProcessorHolder& operator= (AudioProcessor*) JUCE_DELETED_FUNCTION;
AudioProcessorHolder (AudioProcessorHolder&) JUCE_DELETED_FUNCTION;
@ -99,7 +99,8 @@ private:
class JuceAudioUnitv3Base
{
public:
JuceAudioUnitv3Base (const AudioComponentDescription& descr, AudioComponentInstantiationOptions options,
JuceAudioUnitv3Base (const AudioComponentDescription& descr,
AudioComponentInstantiationOptions options,
NSError** error)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-method-access"
@ -117,6 +118,8 @@ public:
initialiseJuce_GUI();
}
virtual ~JuceAudioUnitv3Base() {}
//==============================================================================
AUAudioUnit* getAudioUnit() noexcept { return au; }
virtual int getVirtualMIDICableCount() { return 0; }
@ -175,12 +178,8 @@ public:
ObjCMsgSendSuper<void> (&s, @selector (deallocateRenderResources));
}
//==============================================================================
protected:
virtual ~JuceAudioUnitv3Base() {}
private:
struct Class : public ObjCClass<AUAudioUnit>
struct Class : public ObjCClass<AUAudioUnit>
{
Class() : ObjCClass<AUAudioUnit> ("AUAudioUnit_")
{
@ -271,17 +270,17 @@ private:
static NSArray<AUAudioUnitPreset*>* getFactoryPresets (id self, SEL) { return _this (self)->getFactoryPresets(); }
static AUAudioUnitPreset* getCurrentPreset (id self, SEL) { return _this (self)->getCurrentPreset(); }
static void setCurrentPreset (id self, SEL, AUAudioUnitPreset* preset) { return _this (self)->setCurrentPreset (preset); }
static NSDictionary<NSString *, id>* getFullState (id self, SEL) { return _this (self)->getFullState(); }
static NSDictionary<NSString*, id>* getFullState (id self, SEL) { return _this (self)->getFullState(); }
static void setFullState (id self, SEL, NSDictionary<NSString *, id>* state) { return _this (self)->setFullState (state); }
static NSTimeInterval getLatency (id self, SEL) { return _this (self)->getLatency(); }
static NSTimeInterval getTailTime (id self, SEL) { return _this (self)->getTailTime(); }
static BOOL getCanProcessInPlace (id self, SEL) { return _this (self)->getCanProcessInPlace(); }
static BOOL getRenderingOffline (id self, SEL) { return _this (self)->getRenderingOffline(); }
static void setRenderingOffline (id self, SEL, BOOL renderingOffline) { _this (self)->setRenderingOffline (renderingOffline); }
static NSArray<NSNumber *>* getChannelCapabilities (id self, SEL) { return _this (self)->getChannelCapabilities(); }
static NSArray<NSNumber*>* getChannelCapabilities (id self, SEL) { return _this (self)->getChannelCapabilities(); }
};
static JuceAudioUnitv3Base* create (AUAudioUnit* audioUnit, AudioComponentDescription descr, AudioComponentInstantiationOptions options, NSError** error);
static JuceAudioUnitv3Base* create (AUAudioUnit*, AudioComponentDescription, AudioComponentInstantiationOptions, NSError**);
//==============================================================================
static Class audioUnitObjCClass;
@ -296,15 +295,18 @@ JuceAudioUnitv3Base::Class JuceAudioUnitv3Base::audioUnitObjCClass;
//==============================================================================
//=========================== The actual AudioUnit =============================
//==============================================================================
class JuceAudioUnitv3 : public JuceAudioUnitv3Base, public AudioProcessorListener, public AudioPlayHead
class JuceAudioUnitv3 : public JuceAudioUnitv3Base,
public AudioProcessorListener,
public AudioPlayHead
{
public:
JuceAudioUnitv3 (const AudioProcessorHolder::Ptr& jFilter,
JuceAudioUnitv3 (const AudioProcessorHolder::Ptr& processor,
const AudioComponentDescription& descr,
AudioComponentInstantiationOptions options,
NSError** error)
: JuceAudioUnitv3Base (descr, options, error),
juceFilter (jFilter), busUtils (**juceFilter, true, 8),
processorHolder (processor),
busUtils (**processorHolder, true, 8),
mapper (busUtils)
{
init();
@ -312,19 +314,34 @@ public:
JuceAudioUnitv3 (AUAudioUnit* audioUnit, AudioComponentDescription, AudioComponentInstantiationOptions, NSError**)
: JuceAudioUnitv3Base (audioUnit),
juceFilter (new AudioProcessorHolder (createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))),
busUtils (**juceFilter, true, 8),
processorHolder (new AudioProcessorHolder (createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))),
busUtils (**processorHolder, true, 8),
mapper (busUtils)
{
init();
}
~JuceAudioUnitv3()
{
auto& processor = getAudioProcessor();
processor.removeListener (this);
if (AudioProcessorEditor* editor = processor.getActiveEditor())
processor.editorBeingDeleted (editor);
if (editorObserverToken != nullptr)
{
[paramTree removeParameterObserver: editorObserverToken];
editorObserverToken = nullptr;
}
}
//==============================================================================
void init()
{
busUtils.init();
(*juceFilter)->setPlayHead (this);
getAudioProcessor().setPlayHead (this);
totalInChannels = busUtils.findTotalNumChannels (true);
totalOutChannels = busUtils.findTotalNumChannels (false);
@ -347,10 +364,11 @@ public:
internalRenderBlock = CreateObjCBlock (this, &JuceAudioUnitv3::renderCallback);
const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender];
(*juceFilter)->setRateAndBufferSizeDetails (kDefaultSampleRate, static_cast<int> (maxFrames));
(*juceFilter)->prepareToPlay (kDefaultSampleRate, static_cast<int> (maxFrames));
(*juceFilter)->addListener (this);
auto& processor = getAudioProcessor();
processor.setRateAndBufferSizeDetails (kDefaultSampleRate, static_cast<int> (maxFrames));
processor.prepareToPlay (kDefaultSampleRate, static_cast<int> (maxFrames));
processor.addListener (this);
addParameters();
addPresets();
@ -360,20 +378,21 @@ public:
}
//==============================================================================
AudioProcessor& getAudioProcessor() const noexcept { return **processorHolder; }
AUAudioUnitBusArray* getInputBusses() override { return inputBusses; }
AUAudioUnitBusArray* getOutputBusses() override { return outputBusses; }
AUParameterTree* getParameterTree() override { return paramTree; }
AUInternalRenderBlock getInternalRenderBlock() override { return internalRenderBlock; }
NSArray<AUAudioUnitPreset*>* getFactoryPresets() override { return factoryPresets; }
bool getRenderingOffline() override { return (*juceFilter)->isNonRealtime(); }
void setRenderingOffline (bool offline) override { (*juceFilter)->setNonRealtime (offline); }
NSArray<NSNumber *>* getChannelCapabilities() override { return channelCapabilities; }
bool getRenderingOffline() override { return getAudioProcessor().isNonRealtime(); }
void setRenderingOffline (bool offline) override { getAudioProcessor().setNonRealtime (offline); }
NSArray<NSNumber*>* getChannelCapabilities() override { return channelCapabilities; }
//==============================================================================
AUAudioUnitPreset* getCurrentPreset() override
{
const int n = static_cast<int> ([factoryPresets count]);
const int idx = static_cast<int> ((*juceFilter)->getCurrentProgram());
const int idx = static_cast<int> (getAudioProcessor().getCurrentProgram());
if (idx < n)
return [factoryPresets objectAtIndex:static_cast<unsigned int> (idx)];
@ -385,8 +404,9 @@ public:
{
const int n = static_cast<int> ([factoryPresets count]);
const int idx = static_cast<int> ([preset number]);
if (isPositiveAndBelow (idx, n))
(*juceFilter)->setCurrentProgram (idx);
getAudioProcessor().setCurrentProgram (idx);
}
//==============================================================================
@ -402,7 +422,8 @@ public:
}
juce::MemoryBlock state;
(*juceFilter)->getCurrentProgramStateInformation (state);
getAudioProcessor().getCurrentProgramStateInformation (state);
if (state.getSize() > 0)
{
NSData* ourState = [[NSData alloc] initWithBytes: state.getData()
@ -447,7 +468,7 @@ public:
const juce::uint8* const rawBytes = reinterpret_cast< const juce::uint8* const> ([data bytes]);
if (numBytes > 0)
(*juceFilter)->setCurrentProgramStateInformation (rawBytes, numBytes);
getAudioProcessor().setCurrentProgramStateInformation (rawBytes, numBytes);
}
}
@ -498,8 +519,9 @@ public:
double sampleRate = (jmax (busUtils.getBusCount (true), busUtils.getBusCount (false)) > 0 ?
[[[([inputBusses count] > 0 ? inputBusses : outputBusses) objectAtIndexedSubscript: 0] format] sampleRate] : 44100.0);
(*juceFilter)->setRateAndBufferSizeDetails (sampleRate, static_cast<int> (maxFrames));
(*juceFilter)->prepareToPlay (sampleRate, static_cast<int> (maxFrames));
auto& processor = getAudioProcessor();
processor.setRateAndBufferSizeDetails (sampleRate, static_cast<int> (maxFrames));
processor.prepareToPlay (sampleRate, static_cast<int> (maxFrames));
zeromem (&lastAudioHead, sizeof (lastAudioHead));
hostMusicalContextCallback = [getAudioUnit() musicalContextBlock];
@ -515,7 +537,7 @@ public:
hostMusicalContextCallback = nullptr;
hostTransportStateCallback = nullptr;
(*juceFilter)->releaseResources();
getAudioProcessor().releaseResources();
audioBuffer.release();
inBusBuffers. clear();
@ -549,7 +571,7 @@ public:
if (newLayout.size() != newNumChannels)
return false;
bool success = (*juceFilter)->setPreferredBusArrangement (isInput, busIdx, newLayout);
bool success = getAudioProcessor().setPreferredBusArrangement (isInput, busIdx, newLayout);
totalInChannels = busUtils.findTotalNumChannels (true);
totalOutChannels = busUtils.findTotalNumChannels (false);
@ -571,8 +593,7 @@ public:
if (AUParameter* param = [paramTree parameterWithAddress: static_cast<AUParameterAddress> (idx)])
{
if (editorObserverToken != nullptr)
[param setValue: newValue
originator: editorObserverToken];
[param setValue: newValue originator: editorObserverToken];
else
[param setValue: newValue];
}
@ -581,11 +602,11 @@ public:
//==============================================================================
NSTimeInterval getLatency() override
{
double samples = static_cast<double> ((*juceFilter)->getLatencySamples());
return samples / (*juceFilter)->getSampleRate();
auto& p = getAudioProcessor();
return p.getLatencySamples() / p.getSampleRate();
}
NSTimeInterval getTailTime() override { return (*juceFilter)->getTailLengthSeconds(); }
NSTimeInterval getTailTime() override { return getAudioProcessor().getTailLengthSeconds(); }
//==============================================================================
bool getCurrentPosition (CurrentPositionInfo& info) override
@ -595,7 +616,7 @@ public:
info = lastAudioHead;
info.timeInSamples = (int64) (lastTimeStamp.mSampleTime + 0.5);
info.timeInSeconds = info.timeInSamples / (*juceFilter)->getSampleRate();
info.timeInSeconds = info.timeInSamples / getAudioProcessor().getSampleRate();
switch (lastTimeStamp.mSMPTETime.mType)
{
@ -637,16 +658,18 @@ public:
if (hostTransportStateCallback != nullptr)
{
AUHostTransportStateBlock transportStateCallback = hostTransportStateCallback;
if (transportStateCallback (&flags, &outCurrentSampleInTimeLine, &outCycleStartBeat, &outCycleEndBeat))
{
transportStateCallSucceeded = true;
info.isPlaying = ((flags & AUHostTransportStateMoving) != 0);
info.timeInSamples = (int64) (outCurrentSampleInTimeLine + 0.5);
info.timeInSeconds = info.timeInSamples / (*juceFilter)->getSampleRate();
info.isLooping = ((flags & AUHostTransportStateCycling) != 0);
info.isRecording = ((flags & AUHostTransportStateRecording) != 0);
info.ppqLoopStart = outCycleStartBeat;
info.ppqLoopEnd = outCycleEndBeat;
info.timeInSamples = (int64) (outCurrentSampleInTimeLine + 0.5);
info.timeInSeconds = info.timeInSamples / getAudioProcessor().getSampleRate();
info.isPlaying = ((flags & AUHostTransportStateMoving) != 0);
info.isLooping = ((flags & AUHostTransportStateCycling) != 0);
info.isRecording = ((flags & AUHostTransportStateRecording) != 0);
info.ppqLoopStart = outCycleStartBeat;
info.ppqLoopEnd = outCycleEndBeat;
}
}
@ -656,29 +679,10 @@ public:
return true;
}
protected:
//==============================================================================
virtual ~JuceAudioUnitv3()
{
(*juceFilter)->removeListener (this);
if (AudioProcessorEditor* editor = (*juceFilter)->getActiveEditor())
(*juceFilter)->editorBeingDeleted (editor);
if (editorObserverToken != nullptr)
{
[paramTree removeParameterObserver: editorObserverToken];
editorObserverToken = nullptr;
}
}
private:
//==============================================================================
class BusBuffer
struct BusBuffer
{
public:
BusBuffer (AUAudioUnitBus* bus, int maxFramesPerBuffer)
: auBus (bus), bufferList (nullptr),
maxFrames (maxFramesPerBuffer),
@ -719,7 +723,7 @@ private:
void prepare (UInt32 nFrames, const AudioBufferList* other = nullptr) noexcept
{
const int numBuffers = isInterleaved ? 1 : numberOfChannels;
const bool isCompatible = compatible (other);
const bool isCompatible = isCompatibleWith (other);
bufferList->mNumberBuffers = static_cast<UInt32> (numBuffers);
@ -727,13 +731,14 @@ private:
{
const UInt32 bufferChannels = static_cast<UInt32> (isInterleaved ? numberOfChannels : 1);
bufferList->mBuffers[i].mNumberChannels = bufferChannels;
bufferList->mBuffers[i].mData = (isCompatible ? other->mBuffers[i].mData : scratchBuffer.getWritePointer (i));
bufferList->mBuffers[i].mData = (isCompatible ? other->mBuffers[i].mData
: scratchBuffer.getWritePointer (i));
bufferList->mBuffers[i].mDataByteSize = nFrames * bufferChannels * sizeof (float);
}
}
//==============================================================================
bool compatible (const AudioBufferList* other) const noexcept
bool isCompatibleWith (const AudioBufferList* other) const noexcept
{
if (other == nullptr)
return false;
@ -741,16 +746,17 @@ private:
if (other->mNumberBuffers > 0)
{
const bool otherInterleaved = AudioUnitHelpers::isAudioBufferInterleaved (*other);
const int otherChannels = static_cast<int> (otherInterleaved ? other->mBuffers[0].mNumberChannels : other->mNumberBuffers);
const int otherChannels = static_cast<int> (otherInterleaved ? other->mBuffers[0].mNumberChannels
: other->mNumberBuffers);
return (otherInterleaved == isInterleaved && numberOfChannels == otherChannels);
return otherInterleaved == isInterleaved
&& numberOfChannels == otherChannels;
}
return (numberOfChannels == 0);
return numberOfChannels == 0;
}
private:
//==============================================================================
AUAudioUnitBus* auBus;
HeapBlock<char> bufferListStorage;
AudioBufferList* bufferList;
@ -793,11 +799,13 @@ private:
overviewParams = [[NSMutableArray<NSNumber*> alloc] init];
const int n = (*juceFilter)->getNumParameters();
auto& processor = getAudioProcessor();
const int n = processor.getNumParameters();
for (int idx = 0; idx < n; ++idx)
{
const String identifier = String (idx);
const String name = (*juceFilter)->getParameterName (idx);
const String identifier (idx);
const String name = processor.getParameterName (idx);
AudioUnitParameterOptions flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
| kAudioUnitParameterFlag_IsReadable
@ -809,10 +817,10 @@ private:
#endif
// set whether the param is automatable (unnamed parameters aren't allowed to be automated)
if (name.isEmpty() || ! (*juceFilter)->isParameterAutomatable (idx))
if (name.isEmpty() || ! processor.isParameterAutomatable (idx))
flags |= kAudioUnitParameterFlag_NonRealTime;
if ((*juceFilter)->isMetaParameter (idx))
if (processor.isMetaParameter (idx))
flags |= kAudioUnitParameterFlag_IsGlobalMeta;
AUParameterAddress address = static_cast<AUParameterAddress> (idx);
@ -840,7 +848,7 @@ private:
[paramTree setImplementorValueObserver: paramObserver];
[paramTree setImplementorValueProvider: paramProvider];
if ((*juceFilter)->hasEditor())
if (processor.hasEditor())
{
editorParamObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedForObserver);
editorObserverToken = [paramTree tokenByAddingParameterObserver: editorParamObserver];
@ -851,11 +859,11 @@ private:
{
factoryPresets = [[NSMutableArray<AUAudioUnitPreset*> alloc] init];
const int n = (*juceFilter)->getNumPrograms();
const int n = getAudioProcessor().getNumPrograms();
for (int idx = 0; idx < n; ++idx)
{
String name = (*juceFilter)->getProgramName (idx);
String name = getAudioProcessor().getProgramName (idx);
ScopedPointer<AUAudioUnitPreset> preset = [[AUAudioUnitPreset alloc] init];
[preset setName: juceStringToNS (name)];
@ -875,7 +883,8 @@ private:
const AUAudioFrameCount maxFrames = [getAudioUnit() maximumFramesToRender];
for (int busIdx = 0; busIdx < n; ++busIdx)
busBuffers.add (new BusBuffer ([(isInput ? inputBusses : outputBusses) objectAtIndexedSubscript: static_cast<unsigned int> (busIdx)], static_cast<int> (maxFrames)));
busBuffers.add (new BusBuffer ([(isInput ? inputBusses : outputBusses) objectAtIndexedSubscript: static_cast<unsigned int> (busIdx)],
static_cast<int> (maxFrames)));
}
void processEvents (const AURenderEvent *__nullable realtimeEventListHead, int numParams, AUEventSampleTime startTime)
@ -884,23 +893,26 @@ private:
{
switch (event->head.eventType)
{
case AURenderEventMIDI:
case AURenderEventMIDI:
{
const AUMIDIEvent& midiEvent = event->MIDI;
midiMessages.addEvent (midiEvent.data, midiEvent.length, static_cast<int> (midiEvent.eventSampleTime - startTime));
}
break;
case AURenderEventParameter:
case AURenderEventParameterRamp:
case AURenderEventParameter:
case AURenderEventParameterRamp:
{
const AUParameterEvent& paramEvent = event->parameter;
const int idx = static_cast<int> (paramEvent.parameterAddress);
if (isPositiveAndBelow (idx, numParams))
(*juceFilter)->setParameter (idx, paramEvent.value);
getAudioProcessor().setParameter (idx, paramEvent.value);
}
break;
default:
break;
default:
break;
}
}
}
@ -909,10 +921,10 @@ private:
NSInteger outputBusNumber, AudioBufferList* outputData, const AURenderEvent *__nullable realtimeEventListHead,
AURenderPullInputBlock __nullable pullInputBlock)
{
jassert (static_cast<int> (frameCount) <= (*juceFilter)->getBlockSize());
jassert (static_cast<int> (frameCount) <= getAudioProcessor().getBlockSize());
// process params
const int numParams = (*juceFilter)->getNumParameters();
const int numParams = getAudioProcessor().getNumParameters();
processEvents (realtimeEventListHead, numParams, static_cast<AUEventSampleTime> (timestamp->mSampleTime));
if (lastTimeStamp.mSampleTime != timestamp->mSampleTime)
@ -960,6 +972,7 @@ private:
// set buffer pointer to minimize copying
{
int chIdx = 0;
for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
{
BusBuffer& busBuffer = *outBusBuffers[busIdx];
@ -976,6 +989,7 @@ private:
// use input pointers on remaining channels
int channelCount = 0;
for (int busIdx = 0; chIdx < totalInChannels;)
{
busIdx = busUtils.getBusIdxForChannelIdx (true, chIdx, channelCount, busIdx);
@ -1009,52 +1023,50 @@ private:
}
// copy back
{
audioBuffer.pop (*outBusBuffers[(int) outputBusNumber]->get(), mapper.get (false, (int) outputBusNumber));
}
audioBuffer.pop (*outBusBuffers[(int) outputBusNumber]->get(),
mapper.get (false, (int) outputBusNumber));
return noErr;
}
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiBuffer) noexcept
{
const ScopedLock sl ((*juceFilter)->getCallbackLock());
auto& processor = getAudioProcessor();
const ScopedLock sl (processor.getCallbackLock());
if ((*juceFilter)->isSuspended())
{
if (processor.isSuspended())
buffer.clear();
}
else if ([au shouldBypassEffect])
{
(*juceFilter)->processBlockBypassed (buffer, midiBuffer);
}
processor.processBlockBypassed (buffer, midiBuffer);
else
{
(*juceFilter)->processBlock (buffer, midiBuffer);
}
processor.processBlock (buffer, midiBuffer);
}
//==============================================================================
void valueChangedFromHost (AUParameter *param, AUValue value)
void valueChangedFromHost (AUParameter* param, AUValue value)
{
if (param != nullptr)
{
const int idx = static_cast<int> ([param address]);
if (isPositiveAndBelow (idx, (*juceFilter)->getNumParameters()))
(*juceFilter)->setParameter (idx, value);
auto& processor = getAudioProcessor();
if (isPositiveAndBelow (idx, processor.getNumParameters()))
processor.setParameter (idx, value);
}
}
AUValue getValue(AUParameter *param)
AUValue getValue (AUParameter* param)
{
if (param != nullptr)
{
const int idx = static_cast<int> ([param address]);
if (isPositiveAndBelow (idx, (*juceFilter)->getNumParameters()))
return (*juceFilter)->getParameter (idx);
auto& processor = getAudioProcessor();
if (isPositiveAndBelow (idx, processor.getNumParameters()))
return processor.getParameter (idx);
}
return 0.f;
return 0;
}
void valueChangedForObserver(AUParameterAddress, AUValue)
@ -1065,7 +1077,7 @@ private:
//==============================================================================
static const double kDefaultSampleRate;
AudioProcessorHolder::Ptr juceFilter;
AudioProcessorHolder::Ptr processorHolder;
PluginBusUtilities busUtils;
int totalInChannels, totalOutChannels;
@ -1115,8 +1127,8 @@ class JuceAUViewController
{
public:
JuceAUViewController (AUViewController <AUAudioUnitFactory>* p)
: myself (p), juceFilter (nullptr), preferredSize (1.f, 1.f)
JuceAUViewController (AUViewController<AUAudioUnitFactory>* p)
: myself (p), processorHolder (nullptr), preferredSize (1.0f, 1.0f)
{
jassert (MessageManager::getInstance()->isThisTheMessageThread());
@ -1129,26 +1141,23 @@ public:
jassert (MessageManager::getInstance()->isThisTheMessageThread());
}
//==============================================================================
AUViewController <AUAudioUnitFactory>* getController() noexcept { return myself; }
//==============================================================================
void loadView()
{
jassert (MessageManager::getInstance()->isThisTheMessageThread());
AudioProcessor* filter = createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3);
if (filter != nullptr)
if (AudioProcessor* p = createPluginFilterOfType (AudioProcessor::wrapperType_AudioUnitv3))
{
juceFilter = new AudioProcessorHolder (filter);
if ((*juceFilter)->hasEditor())
processorHolder = new AudioProcessorHolder (p);
auto& processor = getAudioProcessor();
if (processor.hasEditor())
{
if (AudioProcessorEditor* editor = (*juceFilter)->createEditorIfNeeded())
if (AudioProcessorEditor* editor = processor.createEditorIfNeeded())
{
preferredSize = editor->getBounds();
IOS_MAC_VIEW* view = [[[IOS_MAC_VIEW alloc] initWithFrame: (convertToCGRect (editor->getBounds()))] autorelease];
JUCE_IOS_MAC_VIEW* view = [[[JUCE_IOS_MAC_VIEW alloc] initWithFrame: convertToCGRect (editor->getBounds())] autorelease];
[myself setView: view];
editor->setVisible (true);
@ -1160,13 +1169,13 @@ public:
void viewDidLayoutSubviews()
{
if (juceFilter != nullptr && [myself view] != nullptr)
if (processorHolder != nullptr && [myself view] != nullptr)
{
if (AudioProcessorEditor* editor = (*juceFilter)->getActiveEditor())
if (AudioProcessorEditor* editor = getAudioProcessor().getActiveEditor())
{
editor->setBounds (convertToRectInt ([[myself view] bounds]));
if (IOS_MAC_VIEW* peerView = [[[myself view] subviews] objectAtIndex: 0])
if (JUCE_IOS_MAC_VIEW* peerView = [[[myself view] subviews] objectAtIndex: 0])
{
#if JUCE_IOS
[peerView setNeedsDisplay];
@ -1178,15 +1187,16 @@ public:
}
}
CGSize getPreferredContentSize()
CGSize getPreferredContentSize() const
{
return CGSizeMake (static_cast<float> (preferredSize.getWidth()), static_cast<float> (preferredSize.getHeight()));
return CGSizeMake (static_cast<float> (preferredSize.getWidth()),
static_cast<float> (preferredSize.getHeight()));
}
//==============================================================================
AUAudioUnit* createAudioUnit (const AudioComponentDescription& descr, NSError** error)
{
AUAudioUnit* retval = nullptr;
AUAudioUnit* retval = nil;
if (! MessageManager::getInstance()->isThisTheMessageThread())
{
@ -1194,7 +1204,7 @@ public:
// AUv3 headers say that we may block this thread and that the message thread is guaranteed
// to be unblocked
struct AUCreator : public CallbackMessage
struct AUCreator : public CallbackMessage
{
JuceAUViewController& owner;
AudioComponentDescription pDescr;
@ -1207,9 +1217,6 @@ public:
: owner (parent), pDescr (paramDescr), pError (paramError), outAU (outputAU), e (event)
{}
~AUCreator()
{}
void messageCallback() override
{
outAU = owner.createAudioUnitOnMessageThread (pDescr, pError);
@ -1227,38 +1234,42 @@ public:
}
private:
//==============================================================================
AUViewController<AUAudioUnitFactory>* myself;
AudioProcessorHolder::Ptr processorHolder;
Rectangle<int> preferredSize;
//==============================================================================
AUAudioUnit* createAudioUnitOnMessageThread (const AudioComponentDescription& descr, NSError** error)
{
jassert (MessageManager::getInstance()->isThisTheMessageThread());
// this will call [view load] and ensure that the juce filter has been instantiated
[myself view];
if (juceFilter == nullptr)
[myself view]; // this will call [view load] and ensure that the AudioProcessor has been instantiated
if (processorHolder == nullptr)
return nullptr;
return (new JuceAudioUnitv3 (juceFilter, descr, 0, error))->getAudioUnit();
return (new JuceAudioUnitv3 (processorHolder, descr, 0, error))->getAudioUnit();
}
//==============================================================================
AUViewController <AUAudioUnitFactory>* myself;
AudioProcessorHolder::Ptr juceFilter;
Rectangle<int> preferredSize;
AudioProcessor& getAudioProcessor() const noexcept { return **processorHolder; }
};
//==============================================================================
// necessary glue code
@interface JUCE_VIEWCONTROLLER_OBJC_NAME (JucePlugin_AUExportPrefix) : AUViewController <AUAudioUnitFactory>
@interface JUCE_VIEWCONTROLLER_OBJC_NAME (JucePlugin_AUExportPrefix) : AUViewController<AUAudioUnitFactory>
@end
@implementation JUCE_VIEWCONTROLLER_OBJC_NAME (JucePlugin_AUExportPrefix) {
@implementation JUCE_VIEWCONTROLLER_OBJC_NAME (JucePlugin_AUExportPrefix)
{
ScopedPointer<JuceAUViewController> cpp;
}
- (instancetype)initWithNibName:(nullable NSString *)nib bundle:(nullable NSBundle *)bndl { self = [super initWithNibName:nib bundle:bndl]; cpp = new JuceAUViewController (self); return self;}
- (void) loadView { cpp->loadView(); }
- (instancetype) initWithNibName: (nullable NSString*) nib bundle: (nullable NSBundle*) bndl { self = [super initWithNibName: nib bundle: bndl]; cpp = new JuceAUViewController (self); return self;}
- (void) loadView { cpp->loadView(); }
- (AUAudioUnit *)createAudioUnitWithComponentDescription:(AudioComponentDescription)desc error:(NSError **)error { return cpp->createAudioUnit (desc, error); }
- (CGSize) preferredContentSize { return cpp->getPreferredContentSize(); }
- (void)viewDidLayoutSubviews { return cpp->viewDidLayoutSubviews(); }
- (void)viewDidLayoutSubviews { return cpp->viewDidLayoutSubviews(); }
@end
#pragma clang diagnostic pop

View file

@ -1467,7 +1467,7 @@ public:
}
#if JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES
void embedViewController (IOS_MAC_VIEW* pluginView, const CGSize& size)
void embedViewController (JUCE_IOS_MAC_VIEW* pluginView, const CGSize& size)
{
wrapper.setView (pluginView);
waitingForViewCallback = false;
@ -1516,7 +1516,7 @@ private:
if (! plugin.initialiseAudioUnit())
return false;
IOS_MAC_VIEW* pluginView = nil;
JUCE_IOS_MAC_VIEW* pluginView = nil;
UInt32 dataSize = 0;
Boolean isWritable = false;
@ -1616,10 +1616,10 @@ private:
struct AsyncViewControllerCallback : public CallbackMessage
{
AudioUnitPluginWindowCocoa* owner;
IOS_MAC_VIEW* controllerView;
JUCE_IOS_MAC_VIEW* controllerView;
CGSize size;
AsyncViewControllerCallback (AudioUnitPluginWindowCocoa* plugInWindow, IOS_MAC_VIEW* inView,
AsyncViewControllerCallback (AudioUnitPluginWindowCocoa* plugInWindow, JUCE_IOS_MAC_VIEW* inView,
const CGSize& preferredSize)
: owner (plugInWindow), controllerView ([inView retain]), size (preferredSize)
{}

View file

@ -56,16 +56,20 @@
#define JUCE_PLUGINHOST_VST3 0
#endif
#if JUCE_IOS
#define IOS_MAC_VIEW UIView
#elif JUCE_MAC
#define IOS_MAC_VIEW NSView
#endif
//==============================================================================
namespace juce
{
#if JUCE_IOS
#define JUCE_IOS_MAC_VIEW UIView
typedef UIViewComponent ViewComponentBaseClass;
#elif JUCE_MAC
#define JUCE_IOS_MAC_VIEW NSView
typedef NSViewComponent ViewComponentBaseClass;
#else
#error
#endif
static inline bool arrayContainsPlugin (const OwnedArray<PluginDescription>& list,
const PluginDescription& desc)
{
@ -77,14 +81,10 @@ static inline bool arrayContainsPlugin (const OwnedArray<PluginDescription>& lis
}
#if JUCE_MAC || JUCE_IOS
//==============================================================================
struct AutoResizingNSViewComponent :
#if JUCE_MAC
public NSViewComponent,
#else
public UIViewComponent,
#endif
private AsyncUpdater
struct AutoResizingNSViewComponent : public ViewComponentBaseClass,
private AsyncUpdater
{
AutoResizingNSViewComponent() : recursive (false) {}
@ -113,16 +113,16 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone
{
AutoResizingNSViewComponentWithParent()
{
IOS_MAC_VIEW* v = [[IOS_MAC_VIEW alloc] init];
JUCE_IOS_MAC_VIEW* v = [[JUCE_IOS_MAC_VIEW alloc] init];
setView (v);
[v release];
startTimer (30);
}
IOS_MAC_VIEW* getChildView() const
JUCE_IOS_MAC_VIEW* getChildView() const
{
if (IOS_MAC_VIEW* parent = (IOS_MAC_VIEW*) getView())
if (JUCE_IOS_MAC_VIEW* parent = (JUCE_IOS_MAC_VIEW*) getView())
if ([[parent subviews] count] > 0)
return [[parent subviews] objectAtIndex: 0];
@ -131,7 +131,7 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone
void timerCallback() override
{
if (IOS_MAC_VIEW* child = getChildView())
if (JUCE_IOS_MAC_VIEW* child = getChildView())
{
stopTimer();
setView (child);