commit 9f5b0132a3b783e6700f78376451ad3ff8e83dd1
parent 522f691ae6066f2445c7f2992b5c2c57816e216d
Author: falkTX <falktx@falktx.com>
Date: Sat, 24 Feb 2024 18:07:57 +0100
Proper AU view handling, delete ui on view dealloc
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
2 files changed, 111 insertions(+), 18 deletions(-)
diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp
@@ -919,6 +919,7 @@ public:
if (d_isNotEqual(fSampleRateForInput, sampleRate))
{
fSampleRateForInput = sampleRate;
+ d_nextSampleRate = sampleRate;
#if DISTRHO_PLUGIN_NUM_OUTPUTS != 0
if (d_isEqual(fSampleRateForOutput, sampleRate))
@@ -939,6 +940,7 @@ public:
if (d_isNotEqual(fSampleRateForOutput, sampleRate))
{
fSampleRateForOutput = sampleRate;
+ d_nextSampleRate = sampleRate;
#if DISTRHO_PLUGIN_NUM_INPUTS != 0
if (d_isEqual(fSampleRateForInput, sampleRate))
@@ -1798,7 +1800,7 @@ private:
{
fCurrentProgram = program;
fPlugin.loadProgram(fCurrentProgram);
- notifyListeners('DPFO', kAudioUnitScope_Global, 0);
+ notifyListeners('DPFo', kAudioUnitScope_Global, 0);
}
}
#endif
@@ -1856,7 +1858,7 @@ private:
if (fPlugin.getStateKey(j) == key)
{
if ((fPlugin.getStateHints(i) & kStateIsOnlyForDSP) == 0x0)
- notifyListeners('DPFS', kAudioUnitScope_Global, j);
+ notifyListeners('DPFs', kAudioUnitScope_Global, j);
break;
}
diff --git a/distrho/src/DistrhoUIAU.mm b/distrho/src/DistrhoUIAU.mm
@@ -21,6 +21,7 @@
#include <AudioUnit/AudioUnit.h>
#include <AudioUnit/AUCocoaUIView.h>
+#include <Cocoa/Cocoa.h>
#undef Point
#undef Size
@@ -56,12 +57,15 @@ class DPF_UI_AU
{
public:
DPF_UI_AU(const AudioUnit component,
- const intptr_t winId,
+ NSView* const view,
const double sampleRate,
void* const instancePointer)
: fComponent(component),
+ fParentView(view),
fTimerRef(nullptr),
- fUI(this, winId, sampleRate,
+ fUI(this,
+ reinterpret_cast<uintptr_t>(view),
+ sampleRate,
editParameterCallback,
setParameterCallback,
setStateCallback,
@@ -71,8 +75,6 @@ public:
d_nextBundlePath,
instancePointer)
{
- d_stdout("UI created");
-
#if DISTRHO_PLUGIN_WANT_STATE
// create state keys
{
@@ -103,6 +105,7 @@ public:
fStateKeys[i] = key;
}
+ CFRelease(keysRef);
std::free(key);
}
}
@@ -119,6 +122,7 @@ public:
CFRunLoopAddTimer(CFRunLoopGetCurrent(), fTimerRef, kCFRunLoopCommonModes);
+ AudioUnitAddPropertyListener(fComponent, kAudioUnitProperty_SampleRate, auPropertyChangedCallback, this);
AudioUnitAddPropertyListener(fComponent, 'DPFp', auPropertyChangedCallback, this);
#if DISTRHO_PLUGIN_WANT_PROGRAMS
AudioUnitAddPropertyListener(fComponent, 'DPFo', auPropertyChangedCallback, this);
@@ -130,7 +134,7 @@ public:
~DPF_UI_AU()
{
- d_stdout("UI destroyed");
+ AudioUnitRemovePropertyListenerWithUserData(fComponent, kAudioUnitProperty_SampleRate, auPropertyChangedCallback, this);
AudioUnitRemovePropertyListenerWithUserData(fComponent, 'DPFp', auPropertyChangedCallback, this);
#if DISTRHO_PLUGIN_WANT_PROGRAMS
AudioUnitRemovePropertyListenerWithUserData(fComponent, 'DPFo', auPropertyChangedCallback, this);
@@ -146,13 +150,27 @@ public:
}
}
- NSView* getNativeView() const
+ void postSetup()
{
- return reinterpret_cast<NSView*>(fUI.getNativeWindowHandle());
+ if (fUI.isResizable())
+ {
+ // [view setAutoresizingMask:NSViewNotSizable];
+ [fParentView setAutoresizesSubviews:YES];
+ }
+ else
+ {
+ [fParentView setAutoresizingMask:NSViewNotSizable];
+ [fParentView setAutoresizesSubviews:NO];
+ }
+
+ // NSView* const uiView = reinterpret_cast<NSView*>(fUI.getNativeWindowHandle());
+
+ [fParentView setFrameSize:NSMakeSize(fUI.getWidth(), fUI.getHeight())];
}
private:
const AudioUnit fComponent;
+ NSView* const fParentView;
CFRunLoopTimerRef fTimerRef;
UIExporter fUI;
@@ -177,6 +195,17 @@ private:
// ----------------------------------------------------------------------------------------------------------------
// AU callbacks
+ void auSampleRateChanged(const AudioUnitScope scope)
+ {
+ Float64 sampleRate = 0;
+ UInt32 dataSize = sizeof(Float64);
+ if (AudioUnitGetProperty(fComponent, kAudioUnitProperty_SampleRate, scope, 0, &sampleRate, &dataSize) == noErr
+ && dataSize == sizeof(Float64))
+ {
+ fUI.setSampleRate(sampleRate, true);
+ }
+ }
+
void auParameterChanged(const AudioUnitElement elem)
{
float value = 0;
@@ -236,20 +265,26 @@ private:
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(self->fComponent == component,);
- DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global, scope,);
switch (prop)
{
+ case kAudioUnitProperty_SampleRate:
+ DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Input || scope == kAudioUnitScope_Output, scope,);
+ self->auSampleRateChanged(scope);
+ break;
case 'DPFp':
+ DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global, scope,);
self->auParameterChanged(elem);
break;
#if DISTRHO_PLUGIN_WANT_PROGRAMS
case 'DPFo':
+ DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global, scope,);
self->auProgramChanged();
break;
#endif
#if DISTRHO_PLUGIN_WANT_STATE
case 'DPFs':
+ DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global, scope,);
self->auStateChanged(elem);
break;
#endif
@@ -322,8 +357,9 @@ private:
}
#endif
- void setSize(uint, uint)
+ void setSize(const uint width, const uint height)
{
+ [fParentView setFrameSize:NSMakeSize(width, height)];
}
static void setSizeCallback(void* const ptr, const uint width, const uint height)
@@ -341,17 +377,60 @@ END_NAMESPACE_DISTRHO
#define MACRO_NAME2(a, b, c, d, e, f) a ## b ## c ## d ## e ## f
#define MACRO_NAME(a, b, c, d, e, f) MACRO_NAME2(a, b, c, d, e, f)
+// --------------------------------------------------------------------------------------------------------------------
+
#define COCOA_VIEW_CLASS_NAME \
- MACRO_NAME(CocoaAUView_, DISTRHO_PLUGIN_AU_TYPE, _, DISTRHO_PLUGIN_AU_SUBTYPE, _, DISTRHO_PLUGIN_AU_MANUFACTURER)
+ MACRO_NAME(CocoaView_, DISTRHO_PLUGIN_AU_TYPE, _, DISTRHO_PLUGIN_AU_SUBTYPE, _, DISTRHO_PLUGIN_AU_MANUFACTURER)
-@interface COCOA_VIEW_CLASS_NAME : NSObject<AUCocoaUIBase>
+@interface COCOA_VIEW_CLASS_NAME : NSView
{
+@public
DPF_UI_AU* ui;
}
@end
@implementation COCOA_VIEW_CLASS_NAME
+- (id) initWithPreferredSize:(NSSize)size
+{
+ self = [super initWithFrame: NSMakeRect (0, 0, size.width, size.height)];
+ [self setHidden:NO];
+ return self;
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (void) dealloc
+{
+ delete ui;
+ ui = nullptr;
+
+ [super dealloc];
+}
+
+- (BOOL) isFlipped
+{
+ return YES;
+}
+
+@end
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#define COCOA_UI_CLASS_NAME \
+ MACRO_NAME(CocoaAUView_, DISTRHO_PLUGIN_AU_TYPE, _, DISTRHO_PLUGIN_AU_SUBTYPE, _, DISTRHO_PLUGIN_AU_MANUFACTURER)
+
+@interface COCOA_UI_CLASS_NAME : NSObject<AUCocoaUIBase>
+{
+ COCOA_VIEW_CLASS_NAME* view;
+}
+@end
+
+@implementation COCOA_UI_CLASS_NAME
+
- (NSString*) description
{
return @DISTRHO_PLUGIN_NAME;
@@ -364,16 +443,26 @@ END_NAMESPACE_DISTRHO
- (NSView*) uiViewForAudioUnit:(AudioUnit)component withSize:(NSSize)inPreferredSize
{
- const double sampleRate = d_nextSampleRate;
- const intptr_t winId = 0;
+ Float64 sampleRate = d_nextSampleRate;
void* instancePointer = nullptr;
+ UInt32 dataSize;
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
- UInt32 dataSize = sizeof(void*);
+ dataSize = sizeof(void*);
AudioUnitGetProperty(component, 'DPFa', kAudioUnitScope_Global, 0, &instancePointer, &dataSize);
#endif
- ui = new DPF_UI_AU(component, winId, sampleRate, instancePointer);
+ #if DISTRHO_PLUGIN_NUM_INPUTS != 0
+ dataSize = sizeof(Float64);
+ AudioUnitGetProperty(component, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, 0, &sampleRate, &dataSize);
+ #elif DISTRHO_PLUGIN_NUM_INPUTS != 0
+ dataSize = sizeof(Float64);
+ AudioUnitGetProperty(component, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, &dataSize);
+ #endif
+
+ view = [[[COCOA_VIEW_CLASS_NAME alloc] initWithPreferredSize:inPreferredSize] autorelease];
+ view->ui = new DPF_UI_AU(component, view, sampleRate, instancePointer);
+ view->ui->postSetup();
// request data from DSP side
{
@@ -383,11 +472,13 @@ END_NAMESPACE_DISTRHO
AudioUnitSetProperty(component, 'DPFi', kAudioUnitScope_Global, 0, &cancel, sizeof(uint16_t));
}
- return ui->getNativeView();
+ return view;
}
@end
+// --------------------------------------------------------------------------------------------------------------------
+
#undef MACRO_NAME
#undef MACRO_NAME2