Browse Source

Objective-C: Tidy up block usages, and document block helpers

v7.0.9
reuk 2 years ago
parent
commit
7da615a7a3
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
4 changed files with 61 additions and 66 deletions
  1. +8
    -16
      modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm
  2. +9
    -40
      modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  3. +39
    -9
      modules/juce_core/native/juce_mac_ObjCHelpers.h
  4. +5
    -1
      modules/juce_gui_basics/native/juce_mac_FileChooser.mm

+ 8
- 16
modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm View File

@@ -1354,14 +1354,17 @@ private:
jassertfalse;
}
[paramTree.get() setImplementorValueObserver: paramObserver];
[paramTree.get() setImplementorValueProvider: paramProvider];
[paramTree.get() setImplementorStringFromValueCallback: stringFromValueProvider];
[paramTree.get() setImplementorValueFromStringCallback: valueFromStringProvider];
[paramTree.get() setImplementorValueObserver: ^(AUParameter* param, AUValue value) { this->valueChangedFromHost (param, value); }];
[paramTree.get() setImplementorValueProvider: ^(AUParameter* param) { return this->getValue (param); }];
[paramTree.get() setImplementorStringFromValueCallback: ^(AUParameter* param, const AUValue* value) { return this->stringFromValue (param, value); }];
[paramTree.get() setImplementorValueFromStringCallback: ^(AUParameter* param, NSString* str) { return this->valueFromString (param, str); }];
if (getAudioProcessor().hasEditor())
{
editorObserverToken = ObserverPtr ([paramTree.get() tokenByAddingParameterObserver: editorParamObserver],
editorObserverToken = ObserverPtr ([paramTree.get() tokenByAddingParameterObserver: ^(AUParameterAddress, AUValue)
{
// this will have already been handled by valueChangedFromHost
}],
ObserverDestructor { paramTree.get() });
}
}
@@ -1630,11 +1633,6 @@ private:
return 0;
}
void valueChangedForObserver (AUParameterAddress, AUValue)
{
// this will have already been handled by valueChangedFromHost
}
NSString* stringFromValue (AUParameter* param, const AUValue* value)
{
String text;
@@ -1738,11 +1736,6 @@ private:
CoreAudioTimeConversions timeConversions;
std::unique_ptr<AUAudioUnitBusArray, NSObjectDeleter> inputBusses, outputBusses;
ObjCBlock<AUImplementorValueObserver> paramObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
ObjCBlock<AUImplementorValueProvider> paramProvider = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
ObjCBlock<AUImplementorStringFromValueCallback> stringFromValueProvider = CreateObjCBlock (this, &JuceAudioUnitv3::stringFromValue);
ObjCBlock<AUImplementorValueFromStringCallback> valueFromStringProvider = CreateObjCBlock (this, &JuceAudioUnitv3::valueFromString);
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
std::map<AUParameterAddress, int> indexForAddress;
#endif
@@ -1752,7 +1745,6 @@ private:
// to avoid recursion on parameter changes, we need to add an
// editor observer to do the parameter changes
std::unique_ptr<AUParameterTree, NSObjectDeleter> paramTree;
ObjCBlock<AUParameterObserver> editorParamObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedForObserver);
ObserverPtr editorObserverToken;
std::unique_ptr<NSMutableArray<NSNumber*>, NSObjectDeleter> channelCapabilities;


+ 9
- 40
modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm View File

@@ -506,40 +506,16 @@ using AudioUnitCreationCallback = std::function<void (AudioUnit, OSStatus)>;
static void createAudioUnit (VersionedAudioComponent versionedComponent, AudioUnitCreationCallback callback)
{
struct AUAsyncInitializationCallback
{
typedef void (^AUCompletionCallbackBlock)(AudioComponentInstance, OSStatus);
explicit AUAsyncInitializationCallback (AudioUnitCreationCallback inOriginalCallback)
: originalCallback (std::move (inOriginalCallback))
{
block = CreateObjCBlock (this, &AUAsyncInitializationCallback::completion);
}
AUCompletionCallbackBlock getBlock() noexcept { return block; }
void completion (AudioComponentInstance audioUnit, OSStatus err)
{
originalCallback (audioUnit, err);
delete this;
}
double sampleRate;
int framesPerBuffer;
AudioUnitCreationCallback originalCallback;
ObjCBlock<AUCompletionCallbackBlock> block;
};
auto callbackBlock = new AUAsyncInitializationCallback (std::move (callback));
if (versionedComponent.isAUv3)
{
if (@available (macOS 10.11, *))
{
AudioComponentInstantiate (versionedComponent.audioComponent, kAudioComponentInstantiation_LoadOutOfProcess,
callbackBlock->getBlock());
AudioComponentInstantiate (versionedComponent.audioComponent,
kAudioComponentInstantiation_LoadOutOfProcess,
^(AudioComponentInstance audioUnit, OSStatus err)
{
callback (audioUnit, err);
});
return;
}
@@ -547,7 +523,7 @@ static void createAudioUnit (VersionedAudioComponent versionedComponent, AudioUn
AudioComponentInstance audioUnit;
auto err = AudioComponentInstanceNew (versionedComponent.audioComponent, &audioUnit);
callbackBlock->completion (err != noErr ? nullptr : audioUnit, err);
callback (err != noErr ? nullptr : audioUnit, err);
}
struct AudioComponentResult
@@ -2615,9 +2591,6 @@ public:
{
addAndMakeVisible (wrapper);
viewControllerCallback =
CreateObjCBlock (this, &AudioUnitPluginWindowCocoa::requestViewControllerCallback);
setOpaque (true);
setVisible (true);
setSize (100, 100);
@@ -2673,7 +2646,6 @@ private:
AudioUnitFormatHelpers::AutoResizingNSViewComponent wrapper;
typedef void (^ViewControllerCallbackBlock)(AUViewControllerBase *);
ObjCBlock<ViewControllerCallbackBlock> viewControllerCallback;
bool waitingForViewCallback = false;
@@ -2727,12 +2699,9 @@ private:
&& dataSize == sizeof (ViewControllerCallbackBlock))
{
waitingForViewCallback = true;
ViewControllerCallbackBlock callback;
callback = viewControllerCallback;
ViewControllerCallbackBlock* info = &callback;
auto callback = ^(AUViewControllerBase* controller) { this->requestViewControllerCallback (controller); };
if (noErr == AudioUnitSetProperty (plugin.audioUnit, kAudioUnitProperty_RequestViewController, kAudioUnitScope_Global, 0, info, dataSize))
if (noErr == AudioUnitSetProperty (plugin.audioUnit, kAudioUnitProperty_RequestViewController, kAudioUnitScope_Global, 0, &callback, dataSize))
return true;
waitingForViewCallback = false;


+ 39
- 9
modules/juce_core/native/juce_mac_ObjCHelpers.h View File

@@ -504,29 +504,59 @@ auto createObjCBlockImpl (Class* object, Fn func, Signature<Result (Params...)>)
}
} // namespace detail
/* Creates an Obj-C block automatically from a member function. */
template <typename Class, typename MemberFunc>
auto CreateObjCBlock (Class* object, MemberFunc fn)
{
return detail::createObjCBlockImpl (object, fn, detail::getSignature (fn));
}
/* Automatically copies and releases a block, a bit like a smart pointer for an Obj-C block.
This is helpful to automatically manage the lifetime of blocks, e.g. if you need to keep a block
around to be used later. This is the case in the AudioUnit API, where the host may provide a
musicalContextBlock that can be called by the plugin during rendering. Copying blocks isn't
realtime-safe, so the plugin must cache the block before rendering.
If you're just creating blocks to pass them directly to an Obj-C API, you probably won't need to
use this type.
*/
template <typename BlockType>
class ObjCBlock
{
public:
ObjCBlock() { block = nullptr; }
template <typename R, class C, typename... P>
ObjCBlock (C* _this, R (C::*fn)(P...)) : block (CreateObjCBlock (_this, fn)) {}
ObjCBlock (BlockType b) : block ([b copy]) {}
ObjCBlock& operator= (const BlockType& other) { if (block != nullptr) { [block release]; } block = [other copy]; return *this; }
bool operator== (const void* ptr) const { return ((const void*) block == ptr); }
bool operator!= (const void* ptr) const { return ((const void*) block != ptr); }
~ObjCBlock() { if (block != nullptr) [block release]; }
ObjCBlock() = default;
ObjCBlock (BlockType b)
: block ([b copy]) {}
ObjCBlock (const ObjCBlock& other)
: block (other.block != nullptr ? [other.block copy] : nullptr) {}
ObjCBlock& operator= (const BlockType& other)
{
ObjCBlock { other }.swap (*this);
return *this;
}
~ObjCBlock() noexcept
{
if (block != nullptr)
[block release];
}
bool operator== (BlockType ptr) const { return block == ptr; }
bool operator!= (BlockType ptr) const { return block != ptr; }
operator BlockType() const { return block; }
void swap (ObjCBlock& other) noexcept
{
std::swap (other.block, block);
}
private:
BlockType block;
BlockType block = nullptr;
};
//==============================================================================


+ 5
- 1
modules/juce_gui_basics/native/juce_mac_FileChooser.mm View File

@@ -189,7 +189,11 @@ public:
if (ref == nullptr)
return;
[ref->panel beginWithCompletionHandler: CreateObjCBlock (ref.getComponent(), &Native::finished)];
[ref->panel beginWithCompletionHandler: ^(NSInteger result)
{
if (auto* ptr = ref.getComponent())
ptr->finished (result);
}];
if (ref->preview != nullptr)
ref->preview->toFront (true);


Loading…
Cancel
Save