commit f1366080a7090a87ab5dddd71168af25b4072861
parent cff94b659c5e8de0f2ff8fd59d53663e3d46cfa2
Author: falkTX <falktx@falktx.com>
Date: Mon, 19 Feb 2024 16:42:43 +0100
stubs for AU UI creation, works but does nothing
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
5 files changed, 304 insertions(+), 9 deletions(-)
diff --git a/Makefile.plugins.mk b/Makefile.plugins.mk
@@ -467,6 +467,16 @@ $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain
@echo "Compiling DistrhoPluginMain.cpp (JACK)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_JACK $(JACK_FLAGS) -c -o $@
+$(BUILD_DIR)/DistrhoPluginMain_AU.cpp.o: $(DPF_PATH)/distrho/DistrhoPluginMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_DSP_DEPENDENCIES)
+ -@mkdir -p $(BUILD_DIR)
+ @echo "Compiling DistrhoPluginMain.cpp (AU)"
+ $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_AU -ObjC++ -c -o $@
+
+$(BUILD_DIR)/DistrhoUIMain_AU.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_UI_DEPENDENCIES)
+ -@mkdir -p $(BUILD_DIR)
+ @echo "Compiling DistrhoUIMain.cpp (AU)"
+ $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -DDISTRHO_PLUGIN_TARGET_AU -ObjC++ -c -o $@
+
$(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.o: $(DPF_PATH)/distrho/DistrhoUIMain.cpp $(EXTRA_DEPENDENCIES) $(EXTRA_UI_DEPENDENCIES)
-@mkdir -p $(BUILD_DIR)
@echo "Compiling DistrhoUIMain.cpp (DSSI)"
diff --git a/distrho/DistrhoUIMain.cpp b/distrho/DistrhoUIMain.cpp
@@ -25,6 +25,7 @@
#if defined(DISTRHO_PLUGIN_TARGET_AU)
# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1
+# import "src/DistrhoUIAU.mm"
#elif defined(DISTRHO_PLUGIN_TARGET_CARLA)
# define DISTRHO_PLUGIN_AND_UI_IN_SINGLE_OBJECT 1
#elif defined(DISTRHO_PLUGIN_TARGET_CLAP)
diff --git a/distrho/extra/FileBrowserDialogImpl.cpp b/distrho/extra/FileBrowserDialogImpl.cpp
@@ -490,7 +490,11 @@ FileBrowserHandle fileBrowserCreate(const bool isEmbed,
[nsOpenPanel setCanChooseFiles:YES];
}
- [nsBasePanel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:startDir]]];
+ NSString* const startDirString = [[NSString alloc]
+ initWithBytes:startDir
+ length:strlen(startDir)
+ encoding:NSUTF8StringEncoding];
+ [nsBasePanel setDirectoryURL:[NSURL fileURLWithPath:startDirString]];
// TODO file filter using allowedContentTypes: [UTType]
@@ -523,6 +527,9 @@ FileBrowserHandle fileBrowserCreate(const bool isEmbed,
}
}];
});
+
+ [startDirString release];
+ [titleString release];
# endif
#endif
diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp
@@ -15,6 +15,7 @@
*/
#include "DistrhoPluginInternal.hpp"
+#include "../DistrhoPluginUtils.hpp"
// #define CA_BASIC_AU_FEATURES 1
#define CA_NO_AU_UI_FEATURES 1
@@ -22,6 +23,7 @@
#define TARGET_OS_MAC 1
#include <AudioUnit/AudioUnit.h>
+#include <AudioUnit/AUCocoaUIView.h>
#define TRACE d_stderr("////////--------------------------------------------------------------- %s %d", __PRETTY_FUNCTION__, __LINE__);
@@ -356,26 +358,66 @@ protected:
return res;
}
-#if 0
- OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
- AudioUnitScope inScope,
- AudioUnitElement inElement,
+ OSStatus GetPropertyInfo(const AudioUnitPropertyID inID,
+ const AudioUnitScope inScope,
+ const AudioUnitElement inElement,
UInt32& outDataSize,
Boolean& outWritable) override
{
TRACE
+ if (inScope == kAudioUnitScope_Global)
+ {
+ switch (inID)
+ {
+ #if DISTRHO_PLUGIN_HAS_UI
+ case kAudioUnitProperty_CocoaUI:
+ outDataSize = sizeof(AudioUnitCocoaViewInfo);
+ outWritable = true;
+ return noErr;
+ #endif
+ default:
+ break;
+ }
+ }
+
return PluginBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
}
- OSStatus GetProperty(AudioUnitPropertyID inID,
- AudioUnitScope inScope,
- AudioUnitElement inElement,
- void* outData) override
+ OSStatus GetProperty(const AudioUnitPropertyID inID,
+ const AudioUnitScope inScope,
+ const AudioUnitElement inElement,
+ void* const outData) override
{
TRACE
+ if (inScope == kAudioUnitScope_Global)
+ {
+ switch (inID)
+ {
+ #if DISTRHO_PLUGIN_HAS_UI
+ case kAudioUnitProperty_CocoaUI:
+ if (AudioUnitCocoaViewInfo* const info = static_cast<AudioUnitCocoaViewInfo*>(outData))
+ {
+ NSString* const bundlePathString = [[NSString alloc]
+ initWithBytes:d_nextBundlePath
+ length:strlen(d_nextBundlePath)
+ encoding:NSUTF8StringEncoding];
+
+ info->mCocoaAUViewBundleLocation = static_cast<CFURLRef>([[NSURL fileURLWithPath: bundlePathString] retain]);
+ info->mCocoaAUViewClass[0] = CFSTR("DPF_UI_ViewFactory");
+
+ [bundlePathString release];
+ }
+ return noErr;
+ #endif
+ default:
+ break;
+ }
+ }
+
return PluginBase::GetProperty(inID, inScope, inElement, outData);
}
+#if 0
OSStatus SetProperty(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
@@ -526,6 +568,14 @@ protected:
return noErr;
}
+ void SetMaxFramesPerSlice(const UInt32 nFrames) override
+ {
+ PluginBase::SetMaxFramesPerSlice(nFrames);
+
+ DISTRHO_SAFE_ASSERT_RETURN(!fPlugin.isActive(),);
+ fPlugin.setBufferSize(nFrames, true);
+ }
+
UInt32 GetChannelLayoutTags(const AudioUnitScope scope,
const AudioUnitElement element,
AudioChannelLayoutTag* const outLayoutTags) override
@@ -647,9 +697,33 @@ void* PluginAUFactory(const AudioComponentDescription* const inDesc)
TRACE
if (d_nextBufferSize == 0)
d_nextBufferSize = kAUDefaultMaxFramesPerSlice;
+
if (d_isZero(d_nextSampleRate))
d_nextSampleRate = kAUDefaultSampleRate;
+ if (d_nextBundlePath == nullptr)
+ {
+ static String bundlePath;
+
+ String tmpPath(getBinaryFilename());
+ tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP));
+ tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP));
+
+ if (tmpPath.endsWith(DISTRHO_OS_SEP_STR "Contents"))
+ {
+ tmpPath.truncate(tmpPath.rfind(DISTRHO_OS_SEP));
+ bundlePath = tmpPath;
+ }
+ else
+ {
+ bundlePath = "error";
+ }
+
+ d_nextBundlePath = bundlePath.buffer();
+ }
+
+ // d_nextCanRequestParameterValueChanges = true;
+
return PluginBaseFactory<PluginAU>::Factory(inDesc);
}
diff --git a/distrho/src/DistrhoUIAU.mm b/distrho/src/DistrhoUIAU.mm
@@ -0,0 +1,203 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any purpose with
+ * or without fee is hereby granted, provided that the above copyright notice and this
+ * permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+// TODO
+// - g_nextBundlePath vs d_nextBundlePath cleanup
+
+#include "DistrhoUIInternal.hpp"
+
+#define Point AudioUnitPoint
+#define Size AudioUnitSize
+
+// #include <AudioUnit/AudioUnit.h>
+#include <AudioUnit/AUCocoaUIView.h>
+
+#undef Point
+#undef Size
+
+START_NAMESPACE_DISTRHO
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#if ! DISTRHO_PLUGIN_WANT_STATE
+static constexpr const setStateFunc setStateCallback = nullptr;
+#endif
+#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
+static constexpr const sendNoteFunc sendNoteCallback = nullptr;
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+// Static data, see DistrhoPlugin.cpp
+
+extern double d_nextSampleRate;
+extern const char* d_nextBundlePath;
+
+// --------------------------------------------------------------------------------------------------------------------
+
+class DPF_UI_AU
+{
+public:
+ DPF_UI_AU(const AudioUnit inAU,
+ const intptr_t winId,
+ const double sampleRate,
+ void* const instancePointer)
+ : fAU(inAU),
+ fTimerRef(nullptr),
+ fUI(this, winId, sampleRate,
+ editParameterCallback,
+ setParameterCallback,
+ setStateCallback,
+ sendNoteCallback,
+ setSizeCallback,
+ nullptr, // TODO file request
+ d_nextBundlePath,
+ instancePointer)
+ {
+ constexpr const CFTimeInterval interval = 60 * 0.0001;
+
+ CFRunLoopTimerContext context = {};
+ context.info = this;
+ fTimerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval, interval, 0, 0,
+ _idleCallback, &context);
+ DISTRHO_SAFE_ASSERT_RETURN(fTimerRef != nullptr,);
+
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), fTimerRef, kCFRunLoopCommonModes);
+ }
+
+ ~DPF_UI_AU()
+ {
+ if (fTimerRef != nullptr)
+ {
+ CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), fTimerRef, kCFRunLoopCommonModes);
+ CFRelease(fTimerRef);
+ }
+ }
+
+ NSView* getNativeView() const
+ {
+ return reinterpret_cast<NSView*>(fUI.getNativeWindowHandle());
+ }
+
+private:
+ const AudioUnit fAU;
+ CFRunLoopTimerRef fTimerRef;
+
+ UIExporter fUI;
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // Idle setup
+
+ void idleCallback()
+ {
+ fUI.idleFromNativeIdle();
+ }
+
+ static void _idleCallback(CFRunLoopTimerRef, void* const info)
+ {
+ static_cast<DPF_UI_AU*>(info)->idleCallback();
+ }
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // DPF callbacks
+
+ void editParameter(uint32_t, bool) const
+ {
+ }
+
+ static void editParameterCallback(void* const ptr, const uint32_t rindex, const bool started)
+ {
+ static_cast<DPF_UI_AU*>(ptr)->editParameter(rindex, started);
+ }
+
+ void setParameterValue(uint32_t, float)
+ {
+ }
+
+ static void setParameterCallback(void* const ptr, const uint32_t rindex, const float value)
+ {
+ static_cast<DPF_UI_AU*>(ptr)->setParameterValue(rindex, value);
+ }
+
+ #if DISTRHO_PLUGIN_WANT_STATE
+ void setState(const char*, const char*)
+ {
+ }
+
+ static void setStateCallback(void* const ptr, const char* const key, const char* const value)
+ {
+ static_cast<DPF_UI_AU*>(ptr)->setState(key, value);
+ }
+ #endif
+
+ #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
+ void sendNote(uint8_t, uint8_t, uint8_t)
+ {
+ }
+
+ static void sendNoteCallback(void* const ptr, const uint8_t channel, const uint8_t note, const uint8_t velocity)
+ {
+ static_cast<DPF_UI_AU*>(ptr)->sendNote(channel, note, velocity);
+ }
+ #endif
+
+ void setSize(uint, uint)
+ {
+ }
+
+ static void setSizeCallback(void* const ptr, const uint width, const uint height)
+ {
+ static_cast<DPF_UI_AU*>(ptr)->setSize(width, height);
+ }
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DISTRHO
+
+// --------------------------------------------------------------------------------------------------------------------
+
+@interface DPF_UI_ViewFactory : NSObject<AUCocoaUIBase>
+{
+ DPF_UI_AU* ui;
+}
+@end
+
+@implementation DPF_UI_ViewFactory
+
+- (NSString*) description
+{
+ return [NSString stringWithUTF8String:DISTRHO_PLUGIN_NAME];
+}
+
+- (unsigned) interfaceVersion
+{
+ return 0;
+}
+
+- (NSView*) uiViewForAudioUnit:(AudioUnit)inAU withSize:(NSSize)inPreferredSize
+{
+ const double sampleRate = d_nextSampleRate;
+ const intptr_t winId = 0;
+ void* const instancePointer = nullptr;
+
+ ui = new DPF_UI_AU(inAU, winId, sampleRate, instancePointer);
+
+ return ui->getNativeView();
+}
+
+@end
+
+// --------------------------------------------------------------------------------------------------------------------