diff options
Diffstat (limited to 'distrho/src')
-rw-r--r-- | distrho/src/CocoaUI/Info.plist | 14 | ||||
-rw-r--r-- | distrho/src/CocoaUI/PluginAU_CocoaUI.m | 156 | ||||
-rwxr-xr-x | distrho/src/CoreAudio106/Info.plist | 2 | ||||
-rw-r--r-- | distrho/src/DistrhoPluginAU.cpp | 35 | ||||
-rw-r--r-- | distrho/src/DistrhoUIAU.cpp | 211 |
5 files changed, 413 insertions, 5 deletions
diff --git a/distrho/src/CocoaUI/Info.plist b/distrho/src/CocoaUI/Info.plist new file mode 100644 index 00000000..472ef07d --- /dev/null +++ b/distrho/src/CocoaUI/Info.plist @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleExecutable</key> + <string>X-DPF-EXECUTABLE-DPF-X-CocoaUI</string> + <key>CFBundleIdentifier</key> + <string>com.example.audiounit.X-DPF-EXECUTABLE-DPF-X</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>NSPrincipalClass</key> + <string>PluginAU_CocoaUIFactory</string> +</dict> +</plist> diff --git a/distrho/src/CocoaUI/PluginAU_CocoaUI.m b/distrho/src/CocoaUI/PluginAU_CocoaUI.m new file mode 100644 index 00000000..ee8da585 --- /dev/null +++ b/distrho/src/CocoaUI/PluginAU_CocoaUI.m @@ -0,0 +1,156 @@ +#include <Cocoa/Cocoa.h> +#include <AudioUnit/AudioUnit.h> +#include <AudioToolbox/AudioToolbox.h> +#include <AudioUnit/AUCocoaUIView.h> + +#define MAX_PARAMS 100 + +@interface PluginAU_CocoaUI : NSView +{ + AudioUnit mAU; + AudioUnitParameter mParameter[MAX_PARAMS]; + AUParameterListenerRef mParameterListener; + UInt32 paramCount; +} + +#pragma mark ____ PUBLIC FUNCTIONS ____ +- (void)setAU:(AudioUnit)inAU; + +#pragma mark ____ PRIVATE FUNCTIONS +- (void)_synchronizeUIWithParameterValues; +- (void)_addListeners; +- (void)_removeListeners; + +#pragma mark ____ LISTENER CALLBACK DISPATCHEE ____ +- (void)_parameterListener:(void *)inObject + parameter:(const AudioUnitParameter *)inParameter + value:(Float32)inValue; + +@end + + +@implementation PluginAU_CocoaUI + +#pragma mark ____ (INIT /) DEALLOC ____ +- (void)dealloc { + [self _removeListeners]; + [super dealloc]; +} + +#pragma mark ____ PUBLIC FUNCTIONS ____ +- (void)setAU:(AudioUnit)inAU { + // remove previous listeners + if (mAU) [self _removeListeners]; + mAU = inAU; + + paramCount = 1; //globalUI->dspPtr.getParameterCount(); + + UInt32 i; + for (i = 0; i < paramCount; ++i) { + mParameter[i].mAudioUnit = inAU; + mParameter[i].mParameterID = i; + mParameter[i].mScope = kAudioUnitScope_Global; + mParameter[i].mElement = 0; + } + + //auUI* dspUI = [self dspUI]; + + // add new listeners + [self _addListeners]; + + // initial setup + [self _synchronizeUIWithParameterValues]; + +} + +#pragma mark ____ LISTENER CALLBACK DISPATCHER ____ +void ParameterListenerDispatcher (void *inRefCon, void *inObject, + const AudioUnitParameter *inParameter, + Float32 inValue) +{ + PluginAU_CocoaUI *SELF = (PluginAU_CocoaUI *)inRefCon; + + [SELF _parameterListener:inObject parameter:inParameter value:inValue]; +} + +#pragma mark ____ PRIVATE FUNCTIONS ____ +- (void)_addListeners { + NSAssert (AUListenerCreate(ParameterListenerDispatcher, self, + CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0.100, // 100 ms + &mParameterListener ) == noErr, + @"[_addListeners] AUListenerCreate()"); + + UInt32 i; + for (i = 0; i < paramCount; ++i) { + NSAssert(AUListenerAddParameter(mParameterListener, + NULL, &mParameter[i]) == noErr, + @"[_addListeners] AUListenerAddParameter()"); + } +} + +- (void)_removeListeners { + UInt32 i; + for (i = 0; i < paramCount; ++i) { + NSAssert (AUListenerRemoveParameter(mParameterListener, + NULL, &mParameter[i]) == noErr, + @"[_removeListeners] AUListenerRemoveParameter()"); + } + + NSAssert (AUListenerDispose(mParameterListener) == noErr, + @"[_removeListeners] AUListenerDispose()"); +} + +- (void)_synchronizeUIWithParameterValues { + Float32 value; + UInt32 i; + + for (i = 0; i < paramCount; ++i) { + // only has global parameters + NSAssert (AudioUnitGetParameter(mAU, mParameter[i].mParameterID, + kAudioUnitScope_Global, 0, &value) == noErr, + @"[synchronizeUIWithParameterValues] (x.1)"); + NSAssert (AUParameterSet(mParameterListener, self, &mParameter[i], + value, 0) == noErr, + @"[synchronizeUIWithParameterValues] (x.2)"); + NSAssert (AUParameterListenerNotify (mParameterListener, self, + &mParameter[i]) == noErr, + @"[synchronizeUIWithParameterValues] (x.3)"); + } +} + +#pragma mark ____ LISTENER CALLBACK DISPATCHEE ____ +- (void)_parameterListener:(void *)inObject + parameter: (const AudioUnitParameter *)inParameter + value: (Float32)inValue +{ + //DPF: setUIParameter(inParameter->mParameterID, inValue); +} + +@end + +@interface PluginAU_CocoaUIFactory : NSObject <AUCocoaUIBase> +{ + IBOutlet PluginAU_CocoaUI *uiFreshlyLoadedView; +} + +- (NSString *) description; + +@end + +@implementation PluginAU_CocoaUIFactory + +- (unsigned) interfaceVersion { + return 0; +} + +- (NSString *) description { + return @"DPF: AU UI"; +} + +- (NSView *)uiViewForAudioUnit:(AudioUnit)inAU withSize:(NSSize)inPreferredSize { + PluginAU_CocoaUI *view = [[PluginAU_CocoaUI alloc] init]; + [view setAU:inAU]; + return [view autorelease]; +} + +@end diff --git a/distrho/src/CoreAudio106/Info.plist b/distrho/src/CoreAudio106/Info.plist index e0e7c89f..f9d3ee2f 100755 --- a/distrho/src/CoreAudio106/Info.plist +++ b/distrho/src/CoreAudio106/Info.plist @@ -9,7 +9,7 @@ <key>CFBundleIconFile</key> <string></string> <key>CFBundleIdentifier</key> - <string>com.yourcompany.dpfplugin</string> + <string>com.example.audiounit.X-DPF-EXECUTABLE-DPF-X</string> <key>CFBundleName</key> <string>X-DPF-EXECUTABLE-DPF-X</string> <key>CFBundleInfoDictionaryVersion</key> diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp index 3b2fbc85..9c5a21bd 100644 --- a/distrho/src/DistrhoPluginAU.cpp +++ b/distrho/src/DistrhoPluginAU.cpp @@ -184,10 +184,37 @@ protected: if (inID == kAudioUnitProperty_CocoaUI && inScope == kAudioUnitScope_Global && outData != nullptr) { d_stdout("GetProperty asked for CocoaUI"); - AudioUnitCocoaViewInfo* const info = (AudioUnitCocoaViewInfo*)outData; - info->mCocoaAUViewBundleLocation = nullptr; // NSURL, CFURLRef - info->mCocoaAUViewClass[0] = nullptr; // NSString, CFStringRef - // return noErr; + + // Need to do a special dance just to get the path to the UI binary + + // Get the main DSP bundle + CFBundleRef bundle = CFBundleGetBundleWithIdentifier( + CFSTR("com.example.audiounit." DISTRHO_PLUGIN_NAME)); + if (bundle == NULL) { + d_stdout("XXX bundle=NULL"); + return fnfErr; + } + + CFURLRef auuiURL = CFBundleCopyResourceURL(bundle, + CFSTR(DISTRHO_PLUGIN_NAME "-CocoaUI"), + CFSTR("bundle"), + NULL); + + if (auuiURL == NULL) { + d_stdout("XXX auuiURL=NULL"); + return fnfErr; + } + + // Use hardcoded UI entrypoint + CFStringRef className = CFSTR("PluginAU_CocoaUIFactory"); + + AudioUnitCocoaViewInfo info; + info.mCocoaAUViewBundleLocation = auuiURL; + info.mCocoaAUViewClass[0] = className; + + *((AudioUnitCocoaViewInfo *)outData) = info; + + return noErr; } #endif diff --git a/distrho/src/DistrhoUIAU.cpp b/distrho/src/DistrhoUIAU.cpp new file mode 100644 index 00000000..dc5a61c7 --- /dev/null +++ b/distrho/src/DistrhoUIAU.cpp @@ -0,0 +1,211 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2019 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. + */ + +#include "DistrhoUIInternal.hpp" + +#include "../extra/Sleep.hpp" + +START_NAMESPACE_DISTRHO + +//#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT +static const sendNoteFunc sendNoteCallback = nullptr; +//#endif + +// ----------------------------------------------------------------------- + +class UIAu +{ +public: + UIAu(const char* const uiTitle) + : fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback), + fHostClosed(false) + { + fUI.setWindowTitle(uiTitle); + } + + ~UIAu() + { + } + + void exec() + { + for (;;) + { + if (fHostClosed || ! fUI.idle()) + break; + + d_msleep(30); + } + } + + // ------------------------------------------------------------------- + +#if 0 +#if DISTRHO_PLUGIN_WANT_STATE + void auui_configure(const char* key, const char* value) + { + fUI.stateChanged(key, value); + } +#endif +#endif + + void auui_control(ulong index, float value) + { + fUI.parameterChanged(index, value); + } + +#if 0 +#if DISTRHO_PLUGIN_WANT_PROGRAMS + void auui_program(ulong bank, ulong program) + { + fUI.programLoaded(bank * 128 + program); + } +#endif +#endif + + void auui_samplerate(const double sampleRate) + { + fUI.setSampleRate(sampleRate, true); + } + + void auui_show() + { + fUI.setWindowVisible(true); + } + + void auui_hide() + { + fUI.setWindowVisible(false); + } + + void auui_quit() + { + fHostClosed = true; + fUI.quit(); + } + + // ------------------------------------------------------------------- + +protected: + void setParameterValue(const uint32_t rindex, const float value) + { + //FIXME fUI.setParameterValue(rindex, value); + } + + void setState(const char* const key, const char* const value) + { + } + +#if 0 +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity) + { + if (fOscData.server == nullptr) + return; + if (channel > 0xF) + return; + + uint8_t mdata[4] = { + 0, + static_cast<uint8_t>(channel + (velocity != 0 ? 0x90 : 0x80)), + note, + velocity + }; + fOscData.send_midi(mdata); + } +#endif +#endif + + void setSize(const uint width, const uint height) + { + fUI.setWindowSize(width, height); + } + +private: + UIExporter fUI; + bool fHostClosed; + + // ------------------------------------------------------------------- + // Callbacks + + #define uiPtr ((UIAu*)ptr) + + static void setParameterCallback(void* ptr, uint32_t rindex, float value) + { + uiPtr->setParameterValue(rindex, value); + } + + static void setStateCallback(void* ptr, const char* key, const char* value) + { + uiPtr->setState(key, value); + } + +#if 0 +#if DISTRHO_PLUGIN_WANT_MIDI_INPUT + static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity) + { + uiPtr->sendNote(channel, note, velocity); + } +#endif +#endif + + static void setSizeCallback(void* ptr, uint width, uint height) + { + uiPtr->setSize(width, height); + } + + #undef uiPtr +}; + +// ----------------------------------------------------------------------- + +static const char* gUiTitle = nullptr; +static UIAu* globalUI = nullptr; + +static void initUiIfNeeded() +{ + if (globalUI != nullptr) + return; + + if (d_lastUiSampleRate == 0.0) + d_lastUiSampleRate = 44100.0; + + globalUI = new UIAu(gUiTitle); +} + +END_NAMESPACE_DISTRHO + +// ----------------------------------------------------------------------- + +int main(int argc, char* argv[]) +{ + USE_NAMESPACE_DISTRHO + + // dummy test mode + if (argc == 1) + { + gUiTitle = "AU UI Test"; + + initUiIfNeeded(); + globalUI->auui_show(); + globalUI->exec(); + + delete globalUI; + globalUI = nullptr; + + return 0; + } +} |