diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e57a111..6f92d617 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,10 +13,9 @@ jobs: strategy: matrix: os: - # wrong use of AU MIDIPacket - # - macos-12 - # - macos-13 - # - macos-14 + - macos-13 + - macos-14 + - macos-15 # webgui failure # - ubuntu-20.04 - ubuntu-22.04 diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4202a693..5bdbbced 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -42,11 +42,11 @@ jobs: suffix: _24_04 target: ${{ matrix.target }} - macos-12: + macos-13: strategy: matrix: target: [macos-intel, macos-universal, macos-10.15] - runs-on: macos-12 + runs-on: macos-13 steps: - uses: actions/checkout@v4 with: @@ -54,14 +54,14 @@ jobs: - uses: distrho/dpf-cmake-action@v1 with: dpf_path: . - suffix: _12 + suffix: _13 target: ${{ matrix.target }} - macos-13: + macos-14: strategy: matrix: target: [macos-intel, macos-universal, macos-10.15] - runs-on: macos-13 + runs-on: macos-14 steps: - uses: actions/checkout@v4 with: @@ -69,14 +69,14 @@ jobs: - uses: distrho/dpf-cmake-action@v1 with: dpf_path: . - suffix: _13 + suffix: _14 target: ${{ matrix.target }} - macos-14: + macos-15: strategy: matrix: target: [macos-intel, macos-universal, macos-10.15] - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 with: @@ -84,7 +84,7 @@ jobs: - uses: distrho/dpf-cmake-action@v1 with: dpf_path: . - suffix: _14 + suffix: _15 target: ${{ matrix.target }} cmake_win32: diff --git a/.github/workflows/example-plugins.yml b/.github/workflows/example-plugins.yml index 8ac77fcc..86bd43e0 100644 --- a/.github/workflows/example-plugins.yml +++ b/.github/workflows/example-plugins.yml @@ -39,11 +39,11 @@ jobs: suffix: _24_04 target: ${{ matrix.target }} - macos-12: + macos-13: strategy: matrix: target: [macos-intel, macos-universal, macos-10.15] - runs-on: macos-12 + runs-on: macos-13 steps: - uses: actions/checkout@v4 with: @@ -51,14 +51,14 @@ jobs: - uses: distrho/dpf-makefile-action@v1 with: dpf_path: . - suffix: _12 + suffix: _13 target: ${{ matrix.target }} - macos-13: + macos-14: strategy: matrix: target: [macos-intel, macos-universal, macos-10.15] - runs-on: macos-13 + runs-on: macos-14 steps: - uses: actions/checkout@v4 with: @@ -66,14 +66,14 @@ jobs: - uses: distrho/dpf-makefile-action@v1 with: dpf_path: . - suffix: _13 + suffix: _14 target: ${{ matrix.target }} - macos-14: + macos-15: strategy: matrix: target: [macos-intel, macos-universal, macos-10.15] - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 with: @@ -81,5 +81,5 @@ jobs: - uses: distrho/dpf-makefile-action@v1 with: dpf_path: . - suffix: _14 + suffix: _15 target: ${{ matrix.target }} diff --git a/.gitignore b/.gitignore index f8118073..80ba3ea4 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,9 @@ CMakeFiles CMakeSettings.json cmake_install.cmake -bin/ -build/ -docs/ -utils/lv2_ttl_generator -utils/lv2_ttl_generator.dSYM/ +/bin/ +/build/ +/docs/ +/khronos/ +/utils/lv2_ttl_generator +/utils/lv2_ttl_generator.dSYM/ diff --git a/README.md b/README.md index 18b71158..e3a2bcba 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Bug reports happen on the [DPF github project](https://github.com/DISTRHO/DPF/is Online documentation is available at [https://distrho.github.io/DPF/](https://distrho.github.io/DPF/). -Online help and discussion about DPF happens in the [kx.studio chat, DPF room](https://chat.kx.studio/channel/dpf). +Online help and discussion about DPF happens in the [DPF github discussions](https://github.com/DISTRHO/DPF/discussions). ## List of plugins made with DPF: diff --git a/dgl/EventHandlers.hpp b/dgl/EventHandlers.hpp index 443fa8d2..450ff4e2 100644 --- a/dgl/EventHandlers.hpp +++ b/dgl/EventHandlers.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho + * Copyright (C) 2012-2025 Filipe Coelho * * 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 @@ -63,6 +63,9 @@ public: bool isCheckable() const noexcept; void setCheckable(bool checkable) noexcept; + bool isEnabled() const noexcept; + void setEnabled(bool enabled, bool appliesToEventInput = true) noexcept; + Point getLastClickPosition() const noexcept; Point getLastMotionPosition() const noexcept; @@ -121,6 +124,9 @@ public: KnobEventHandler& operator=(const KnobEventHandler& other); virtual ~KnobEventHandler(); + bool isEnabled() const noexcept; + void setEnabled(bool enabled, bool appliesToEventInput = true) noexcept; + // if setStep(1) has been called before, this returns true bool isInteger() const noexcept; diff --git a/dgl/src/EventHandlers.cpp b/dgl/src/EventHandlers.cpp index a2721d2c..d3b6cd3e 100644 --- a/dgl/src/EventHandlers.cpp +++ b/dgl/src/EventHandlers.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho + * Copyright (C) 2012-2025 Filipe Coelho * * 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 @@ -31,6 +31,8 @@ struct ButtonEventHandler::PrivateData { int state; bool checkable; bool checked; + bool enabled; + bool enabledInput; Point lastClickPos; Point lastMotionPos; @@ -44,11 +46,16 @@ struct ButtonEventHandler::PrivateData { state(kButtonStateDefault), checkable(false), checked(false), + enabled(true), + enabledInput(true), lastClickPos(0, 0), lastMotionPos(0, 0) {} bool mouseEvent(const Widget::MouseEvent& ev) { + if (! enabledInput) + return false; + lastClickPos = ev.pos; // button was released, handle it now @@ -98,6 +105,9 @@ struct ButtonEventHandler::PrivateData { bool motionEvent(const Widget::MotionEvent& ev) { + if (! enabledInput) + return false; + // keep pressed if (button != -1) { @@ -171,6 +181,27 @@ struct ButtonEventHandler::PrivateData { } } + void setEnabled(const bool enabled2, const bool appliesToEventInput) noexcept + { + if (appliesToEventInput) + enabledInput = enabled2; + + if (enabled == enabled2) + return; + + // reset temp vars if disabling + if (! enabled2) + { + button = -1; + state = kButtonStateDefault; + lastClickPos = Point(); + lastMotionPos = Point(); + } + + enabled = enabled2; + widget->repaint(); + } + DISTRHO_DECLARE_NON_COPYABLE(PrivateData) }; @@ -217,6 +248,16 @@ void ButtonEventHandler::setCheckable(const bool checkable) noexcept pData->checkable = checkable; } +bool ButtonEventHandler::isEnabled() const noexcept +{ + return pData->enabled; +} + +void ButtonEventHandler::setEnabled(const bool enabled, const bool appliesToEventInput) noexcept +{ + pData->setEnabled(enabled, appliesToEventInput); +} + Point ButtonEventHandler::getLastClickPosition() const noexcept { return pData->lastClickPos; @@ -281,6 +322,8 @@ struct KnobEventHandler::PrivateData { float value; float valueDef; float valueTmp; + bool enabled; + bool enabledInput; bool usingDefault; bool usingLog; Orientation orientation; @@ -301,6 +344,8 @@ struct KnobEventHandler::PrivateData { value(0.5f), valueDef(value), valueTmp(value), + enabled(true), + enabledInput(true), usingDefault(false), usingLog(false), orientation(Vertical), @@ -320,6 +365,8 @@ struct KnobEventHandler::PrivateData { value(other->value), valueDef(other->valueDef), valueTmp(value), + enabled(other->enabled), + enabledInput(other->enabledInput), usingDefault(other->usingDefault), usingLog(other->usingLog), orientation(other->orientation), @@ -338,6 +385,8 @@ struct KnobEventHandler::PrivateData { value = other->value; valueDef = other->valueDef; valueTmp = value; + enabled = other->enabled; + enabledInput = other->enabledInput; usingDefault = other->usingDefault; usingLog = other->usingLog; orientation = other->orientation; @@ -363,6 +412,9 @@ struct KnobEventHandler::PrivateData { bool mouseEvent(const Widget::MouseEvent& ev, const double scaleFactor) { + if (! enabledInput) + return false; + if (ev.button != 1) return false; @@ -416,6 +468,9 @@ struct KnobEventHandler::PrivateData { bool motionEvent(const Widget::MotionEvent& ev, const double scaleFactor) { + if (! enabledInput) + return false; + if ((state & kKnobStateDragging) == 0x0) return false; @@ -501,6 +556,9 @@ struct KnobEventHandler::PrivateData { bool scrollEvent(const Widget::ScrollEvent& ev) { + if (! enabledInput) + return false; + if (! widget->contains(ev.pos)) return false; @@ -541,6 +599,28 @@ struct KnobEventHandler::PrivateData { return ((usingLog ? invlogscale(value) : value) - minimum) / diff; } + void setEnabled(const bool enabled2, const bool appliesToEventInput) noexcept + { + if (appliesToEventInput) + enabledInput = enabled2; + + if (enabled == enabled2) + return; + + // reset temp vars if disabling + if (! enabled2) + { + state = kKnobStateDefault; + lastX = 0.0; + lastY = 0.0; + lastClickTime = 0; + valueTmp = value; + } + + enabled = enabled2; + widget->repaint(); + } + void setRange(const float min, const float max) noexcept { DISTRHO_SAFE_ASSERT_RETURN(max > min,); @@ -598,6 +678,16 @@ KnobEventHandler::~KnobEventHandler() delete pData; } +bool KnobEventHandler::isEnabled() const noexcept +{ + return pData->enabled; +} + +void KnobEventHandler::setEnabled(const bool enabled, const bool appliesToEventInput) noexcept +{ + pData->setEnabled(enabled, appliesToEventInput); +} + bool KnobEventHandler::isInteger() const noexcept { return d_isEqual(pData->step, 1.f); diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index a2afec6b..3644bc49 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -579,11 +579,11 @@ void Window::PrivateData::runAsModal(const bool blockWait) // ----------------------------------------------------------------------- // pugl events -void Window::PrivateData::onPuglConfigure(const double width, const double height) +void Window::PrivateData::onPuglConfigure(const uint width, const uint height) { DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,); - DGL_DBGp("PUGL: onReshape : %f %f\n", width, height); + DGL_DBGp("PUGL: onReshape : %d %d\n", width, height); if (autoScaling) { @@ -1188,25 +1188,21 @@ static int printEvent(const PuglEvent* event, const char* prefix, const bool ver if (verbose) { switch (event->type) { - case PUGL_CREATE: - return fprintf(stderr, "%sCreate\n", prefix); - case PUGL_DESTROY: - return fprintf(stderr, "%sDestroy\n", prefix); - case PUGL_MAP: - return fprintf(stderr, "%sMap\n", prefix); - case PUGL_UNMAP: - return fprintf(stderr, "%sUnmap\n", prefix); - case PUGL_UPDATE: - return 0; // fprintf(stderr, "%sUpdate\n", prefix); + case PUGL_REALIZE: + return PRINT("%sRealize\n", prefix); + case PUGL_UNREALIZE: + return PRINT("%sUnrealize\n", prefix); case PUGL_CONFIGURE: - return PRINT("%sConfigure " PFMT " " PFMT "\n", + return PRINT("%sConfigure %d %d %d %d\n", prefix, event->configure.x, event->configure.y, event->configure.width, event->configure.height); + case PUGL_UPDATE: + return 0; // fprintf(stderr, "%sUpdate\n", prefix); case PUGL_EXPOSE: - return PRINT("%sExpose " PFMT " " PFMT "\n", + return PRINT("%sExpose %d %d %d %d\n", prefix, event->expose.x, event->expose.y, diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp index 0983a6dc..ed7b971f 100644 --- a/dgl/src/WindowPrivateData.hpp +++ b/dgl/src/WindowPrivateData.hpp @@ -181,7 +181,7 @@ struct Window::PrivateData : IdleCallback { void runAsModal(bool blockWait); // pugl events - void onPuglConfigure(double width, double height); + void onPuglConfigure(uint width, uint height); void onPuglExpose(); void onPuglClose(); void onPuglFocus(bool focus, CrossingMode mode); diff --git a/dgl/src/pugl.cpp b/dgl/src/pugl.cpp index 4acb5334..557f046d 100644 --- a/dgl/src/pugl.cpp +++ b/dgl/src/pugl.cpp @@ -363,7 +363,8 @@ PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height) #ifdef DGL_USING_X11 // workaround issues in fluxbox, see https://github.com/lv2/pugl/issues/118 - if (view->impl->win && !view->parent && !view->transientParent) + // NOTE troublesome if used under wayland + if (view->impl->win && !view->parent && !view->transientParent && std::getenv("WAYLAND_DISPLAY") == nullptr) { view->sizeHints[PUGL_DEFAULT_SIZE].width = view->sizeHints[PUGL_DEFAULT_SIZE].height = 0; } diff --git a/distrho/DistrhoDetails.hpp b/distrho/DistrhoDetails.hpp index f72608f7..34affacb 100644 --- a/distrho/DistrhoDetails.hpp +++ b/distrho/DistrhoDetails.hpp @@ -202,7 +202,7 @@ static constexpr const uint32_t kStateIsOnlyForUI = 0x20; /** Parameter designation.@n - Allows a parameter to be specially designated for a task, like bypass. + Allows a parameter to be specially designated for a task, like bypass and reset. Each designation is unique, there must be only one parameter that uses it.@n The use of designated parameters is completely optional. @@ -214,13 +214,20 @@ enum ParameterDesignation { /** Null or unset designation. */ - kParameterDesignationNull = 0, + kParameterDesignationNull, /** Bypass designation.@n When on (> 0.5f), it means the plugin must run in a bypassed state. */ - kParameterDesignationBypass = 1 + kParameterDesignationBypass, + + /** + Reset designation.@n + When on (> 0.5f), it means the plugin should reset its internal processing state + (like filters, oscillators, envelopes, lfos, etc) and kill all voices. + */ + kParameterDesignationReset, }; /** @@ -234,7 +241,12 @@ namespace ParameterDesignationSymbols { static constexpr const char bypass[] = "dpf_bypass"; /** - Bypass designation symbol, inverted for LV2 so it becomes "enabled". + Reset designation symbol. + */ + static constexpr const char reset[] = "dpf_reset"; + + /** + LV2 bypass designation symbol, inverted for LV2 so it becomes "enabled". */ static constexpr const char bypass_lv2[] = "lv2_enabled"; }; @@ -728,6 +740,18 @@ struct Parameter { ranges.min = 0.0f; ranges.max = 1.0f; break; + case kParameterDesignationReset: + hints = kParameterIsAutomatable|kParameterIsBoolean|kParameterIsInteger|kParameterIsTrigger; + name = "Reset"; + shortName = "Reset"; + symbol = ParameterDesignationSymbols::reset; + unit = ""; + midiCC = 0; + groupId = kPortGroupNone; + ranges.def = 0.0f; + ranges.min = 0.0f; + ranges.max = 1.0f; + break; } } diff --git a/distrho/DistrhoInfo.hpp b/distrho/DistrhoInfo.hpp index 7df2003d..5016f319 100644 --- a/distrho/DistrhoInfo.hpp +++ b/distrho/DistrhoInfo.hpp @@ -553,6 +553,12 @@ START_NAMESPACE_DISTRHO */ #define DISTRHO_PLUGIN_WANT_LATENCY 1 +/** + Whether the plugin wants MPE for MIDI input and/or output. + @note Only AU and CLAP formats implement this at the moment +*/ +#define DISTRHO_PLUGIN_WANT_MIDI_AS_MPE 0 + /** Whether the plugin wants MIDI input.@n This is automatically enabled if @ref DISTRHO_PLUGIN_IS_SYNTH is true. diff --git a/distrho/extra/String.hpp b/distrho/extra/String.hpp index 0255bcd1..8a34e981 100644 --- a/distrho/extra/String.hpp +++ b/distrho/extra/String.hpp @@ -22,6 +22,10 @@ #include +#if __cplusplus >= 201703L +# include +#endif + START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- @@ -49,10 +53,7 @@ public: fBufferLen(0), fBufferAlloc(false) { - char ch[2]; - ch[0] = c; - ch[1] = '\0'; - + const char ch[2] = { c, '\0' }; _dup(ch); } @@ -87,6 +88,19 @@ public: _dup(strBuf); } + #if __cplusplus >= 201703L + /* + * std::string_view compatible variant. + */ + explicit String(const std::string_view& strView) noexcept + : fBuffer(_null()), + fBufferLen(0), + fBufferAlloc(false) + { + _dup(strView.data(), strView.size()); + } + #endif + /* * Integer. */ diff --git a/distrho/extra/WebViewImpl.cpp b/distrho/extra/WebViewImpl.cpp index cea63578..3bdb3fa5 100644 --- a/distrho/extra/WebViewImpl.cpp +++ b/distrho/extra/WebViewImpl.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho + * Copyright (C) 2012-2025 Filipe Coelho * * 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 @@ -106,7 +106,7 @@ @implementation WEB_VIEW_DELEGATE_CLASS_NAME { @public - WebViewMessageCallback callback; + DISTRHO_NAMESPACE::WebViewMessageCallback callback; void* callbackPtr; bool loaded; } @@ -1039,7 +1039,9 @@ static bool gtk3(Display* const display, { void* lib; if ((lib = dlopen("libwebkit2gtk-4.0.so.37", RTLD_NOW|RTLD_GLOBAL)) == nullptr && - (lib = dlopen("libwebkit2gtk-4.0.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) + (lib = dlopen("libwebkit2gtk-4.1.so.0", RTLD_NOW|RTLD_GLOBAL)) == nullptr && + (lib = dlopen("libwebkit2gtk-4.0.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr && + (lib = dlopen("libwebkit2gtk-4.1.so", RTLD_NOW|RTLD_GLOBAL)) == nullptr) { d_stdout("WebView gtk3 platform not available: %s", dlerror()); return false; diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp index 4262ca2e..b97bdb0d 100644 --- a/distrho/src/DistrhoPluginAU.cpp +++ b/distrho/src/DistrhoPluginAU.cpp @@ -202,7 +202,8 @@ static constexpr const uint32_t kType = d_cconst(STRINGIFY(DISTRHO_PLUGIN_AU_TYP static constexpr const uint32_t kSubType = d_cconst(STRINGIFY(DISTRHO_PLUGIN_UNIQUE_ID)); static constexpr const uint32_t kManufacturer = d_cconst(STRINGIFY(DISTRHO_PLUGIN_BRAND_ID)); -static constexpr const uint32_t kWantedAudioFormat = kAudioFormatFlagsNativeFloatPacked +static constexpr const uint32_t kWantedAudioFormat = 0 + | kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; @@ -263,7 +264,7 @@ bool isNumChannelsComboValid(const uint16_t numInputs, const uint16_t numOutputs // -------------------------------------------------------------------------------------------------------------------- struct PropertyListener { - AudioUnitPropertyID prop; + AudioUnitPropertyID prop; AudioUnitPropertyListenerProc proc; void* userData; }; @@ -276,12 +277,28 @@ struct RenderListener { typedef std::vector PropertyListeners; typedef std::vector RenderListeners; -// -------------------------------------------------------------------------------------------------------------------- - -typedef struct { - UInt32 numPackets; - MIDIPacket packets[kMaxMidiEvents]; -} d_MIDIPacketList; +#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +// useful definitions +static constexpr const uint32_t kMIDIPacketNonDataSize = sizeof(MIDIPacket) + #if __cplusplus >= 201103L + - sizeof(MIDIPacket::data); + #else + - sizeof(static_cast(0)->data); + #endif +static constexpr const uint32_t kMIDIPacketListNonDataSize = sizeof(MIDIPacketList) + #if __cplusplus >= 201103L + - sizeof(MIDIPacketList::packet); + #else + - sizeof(static_cast(0)->packet); + #endif + +// size of data used for midi events +static constexpr const uint32_t kMIDIPacketListMaxDataSize = kMIDIPacketNonDataSize * kMaxMidiEvents + + sizeof(Byte) * MidiEvent::kDataSize * kMaxMidiEvents; + +// size of midi list + data +static constexpr const uint32_t kMIDIPacketListSize = kMIDIPacketListNonDataSize + kMIDIPacketListMaxDataSize; +#endif // -------------------------------------------------------------------------------------------------------------------- @@ -331,10 +348,14 @@ public: fUsingRenderListeners(false), fParameterCount(fPlugin.getParameterCount()), fLastParameterValues(nullptr), - fBypassParameterIndex(UINT32_MAX) + fBypassParameterIndex(UINT32_MAX), + fResetParameterIndex(UINT32_MAX) #if DISTRHO_PLUGIN_WANT_MIDI_INPUT , fMidiEventCount(0) #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + , fMidiOutputDataOffset(0) + #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS , fCurrentProgram(-1) , fLastFactoryProgram(0) @@ -345,7 +366,7 @@ public: , fStateCount(fPlugin.getStateCount()) #endif { - if (fParameterCount != 0) + if (fParameterCount != 0) { fLastParameterValues = new float[fParameterCount]; std::memset(fLastParameterValues, 0, sizeof(float) * fParameterCount); @@ -354,8 +375,17 @@ public: { fLastParameterValues[i] = fPlugin.getParameterValue(i); - if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass) + switch (fPlugin.getParameterDesignation(i)) + { + case kParameterDesignationNull: + break; + case kParameterDesignationBypass: fBypassParameterIndex = i; + break; + case kParameterDesignationReset: + fResetParameterIndex = i; + break; + } } } @@ -370,8 +400,10 @@ public: #endif #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + if ((fMidiOutputPackets = static_cast(std::malloc(kMIDIPacketListSize))) != nullptr) + std::memset(fMidiOutputPackets, 0, kMIDIPacketListSize); + std::memset(&fMidiOutput, 0, sizeof(fMidiOutput)); - std::memset(&fMidiOutputPackets, 0, sizeof(fMidiOutputPackets)); #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS @@ -428,6 +460,10 @@ public: reallocAudioBufferList(false); #endif + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + std::free(fMidiOutputPackets); + #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS for (uint32_t i=0; inumPackets = 0; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS fTimePosition.clear(); @@ -635,7 +672,7 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); #if DISTRHO_PLUGIN_WANT_TIMEPOS outDataSize = sizeof(HostCallbackInfo); - outWritable = false; + outWritable = true; return noErr; #else return kAudioUnitErr_InvalidProperty; @@ -659,6 +696,17 @@ public: outWritable = true; return noErr; + case kAudioUnitProperty_SupportsMPE: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); + #if DISTRHO_PLUGIN_WANT_MIDI_AS_MPE + outDataSize = sizeof(UInt32); + outWritable = false; + return noErr; + #else + return kAudioUnitErr_InvalidProperty; + #endif + case kAudioUnitProperty_CocoaUI: DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); @@ -708,7 +756,7 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); outDataSize = sizeof(uint16_t); - outWritable = false; + outWritable = true; return noErr; case 'DPFe': @@ -739,7 +787,7 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); outDataSize = sizeof(uint32_t); - outWritable = false; + outWritable = true; return noErr; #endif @@ -748,7 +796,7 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); outDataSize = sizeof(CFArrayRef); - outWritable = false; + outWritable = true; return noErr; case 'DPFs': @@ -764,7 +812,7 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); outDataSize = sizeof(void*); - outWritable = false; + outWritable = true; return noErr; #endif @@ -885,13 +933,13 @@ public: case kAudioUnitProperty_FastDispatch: switch (inElement) { - case kAudioUnitGetParameterSelect: + case kAudioUnitGetParameterSelect: *static_cast(outData) = FastDispatchGetParameter; return noErr; - case kAudioUnitSetParameterSelect: + case kAudioUnitSetParameterSelect: *static_cast(outData) = FastDispatchSetParameter; return noErr; - case kAudioUnitRenderSelect: + case kAudioUnitRenderSelect: *static_cast(outData) = FastDispatchRender; return noErr; } @@ -1028,6 +1076,12 @@ public: } return noErr; + #if DISTRHO_PLUGIN_WANT_MIDI_AS_MPE + case kAudioUnitProperty_SupportsMPE: + *static_cast(outData) = 1; + return noErr; + #endif + #if DISTRHO_PLUGIN_HAS_UI case kAudioUnitProperty_CocoaUI: { @@ -1414,7 +1468,7 @@ public: const float value = bypass ? 1.f : 0.f; fLastParameterValues[fBypassParameterIndex] = value; fPlugin.setParameterValue(fBypassParameterIndex, value); - notifyPropertyListeners(inProp, inScope, inElement); + notifyPropertyListeners(inProp, inScope, inElement); } } return noErr; @@ -1436,12 +1490,12 @@ public: #if DISTRHO_PLUGIN_WANT_TIMEPOS { const UInt32 usableDataSize = std::min(inDataSize, static_cast(sizeof(HostCallbackInfo))); - const bool changed = std::memcmp(&fHostCallbackInfo, inData, usableDataSize) != 0; + const bool changed = std::memcmp(&fHostCallbackInfo, inData, usableDataSize) != 0; - std::memcpy(&fHostCallbackInfo, inData, usableDataSize); + std::memcpy(&fHostCallbackInfo, inData, usableDataSize); if (sizeof(HostCallbackInfo) > usableDataSize) - std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize); + std::memset(&fHostCallbackInfo + usableDataSize, 0, sizeof(HostCallbackInfo) - usableDataSize); if (changed) notifyPropertyListeners(inProp, inScope, inElement); @@ -1568,7 +1622,7 @@ public: AUEventListenerNotify(NULL, NULL, &event); if (fBypassParameterIndex == inElement) - notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0); + notifyPropertyListeners(kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0); } return noErr; @@ -1777,7 +1831,12 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(scope == kAudioUnitScope_Global || scope == kAudioUnitScope_Input || scope == kAudioUnitScope_Output, scope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(elem == 0, elem, kAudioUnitErr_InvalidElement); - if (fPlugin.isActive()) + if (fResetParameterIndex != UINT32_MAX) + { + fPlugin.setParameterValue(fResetParameterIndex, 1.f); + fPlugin.setParameterValue(fResetParameterIndex, 0.f); + } + else if (fPlugin.isActive()) { fPlugin.deactivate(); fPlugin.activate(); @@ -1787,7 +1846,8 @@ public: fMidiEventCount = 0; #endif #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT - fMidiOutputPackets.numPackets = 0; + fMidiOutputDataOffset = 0; + fMidiOutputPackets->numPackets = 0; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS fTimePosition.clear(); @@ -2015,7 +2075,7 @@ public: midiEvent.data[1] = inData1; midiEvent.data[2] = inData2; - switch (inStatus) + switch (inStatus & 0xF0) { case 0x80: case 0x90: @@ -2057,6 +2117,8 @@ public: break; default: // invalid + d_debug("auMIDIEvent received invalid event %u %u %u %u @ %u", + inStatus, inData1, inData2, inOffsetSampleFrame, fMidiEventCount); return kAudioUnitErr_InvalidPropertyValue; } @@ -2133,6 +2195,7 @@ private: const uint32_t fParameterCount; float* fLastParameterValues; uint32_t fBypassParameterIndex; + uint32_t fResetParameterIndex; #if DISTRHO_PLUGIN_WANT_MIDI_INPUT uint32_t fMidiEventCount; @@ -2141,8 +2204,9 @@ private: #endif #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + uint32_t fMidiOutputDataOffset; + MIDIPacketList* fMidiOutputPackets; AUMIDIOutputCallbackStruct fMidiOutput; - d_MIDIPacketList fMidiOutputPackets; #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS @@ -2172,7 +2236,7 @@ private: const PropertyListener& pl(*it); if (pl.prop == prop) - pl.proc(pl.userData, fComponent, prop, scope, elem); + pl.proc(pl.userData, fComponent, prop, scope, elem); } } @@ -2217,7 +2281,8 @@ private: #endif #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT - fMidiOutputPackets.numPackets = 0; + fMidiOutputDataOffset = 0; + fMidiOutputPackets->numPackets = 0; #endif #if DISTRHO_PLUGIN_WANT_TIMEPOS @@ -2294,12 +2359,11 @@ private: #endif #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT - if (fMidiOutputPackets.numPackets != 0 && fMidiOutput.midiOutputCallback != nullptr) + if (fMidiOutputPackets != nullptr && + fMidiOutputPackets->numPackets != 0 && + fMidiOutput.midiOutputCallback != nullptr) { - fMidiOutput.midiOutputCallback(fMidiOutput.userData, - inTimeStamp, - 0, - reinterpret_cast(&fMidiOutputPackets)); + fMidiOutput.midiOutputCallback(fMidiOutput.userData, inTimeStamp, 0, fMidiOutputPackets); } #else // unused @@ -2716,17 +2780,21 @@ private: bool writeMidi(const MidiEvent& midiEvent) { DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN("MIDI output unsupported", fMidiOutput.midiOutputCallback != nullptr, false); + DISTRHO_CUSTOM_SAFE_ASSERT_ONCE_RETURN("Out of memory", fMidiOutputPackets != nullptr, false); - if (midiEvent.size > sizeof(MIDIPacket::data)) - return true; - if (fMidiOutputPackets.numPackets == kMaxMidiEvents) + if (fMidiOutputDataOffset + kMIDIPacketNonDataSize + midiEvent.size >= kMIDIPacketListMaxDataSize) return false; const uint8_t* const midiData = midiEvent.size > MidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data; - MIDIPacket& packet(fMidiOutputPackets.packets[fMidiOutputPackets.numPackets++]); - packet.timeStamp = midiEvent.frame; - packet.length = midiEvent.size; - std::memcpy(packet.data, midiData, midiEvent.size); + MIDIPacket* const packet = reinterpret_cast( + reinterpret_cast(fMidiOutputPackets->packet) + fMidiOutputDataOffset); + + packet->timeStamp = midiEvent.frame; + packet->length = midiEvent.size; + std::memcpy(packet->data, midiData, midiEvent.size); + + ++fMidiOutputPackets->numPackets; + fMidiOutputDataOffset += kMIDIPacketNonDataSize + midiEvent.size; return true; } @@ -2793,7 +2861,7 @@ private: // -------------------------------------------------------------------------------------------------------------------- struct AudioComponentPlugInInstance { - AudioComponentPlugInInterface acpi; + AudioComponentPlugInInterface acpi; PluginAU* plugin; AudioComponentPlugInInstance() noexcept @@ -2802,9 +2870,9 @@ struct AudioComponentPlugInInstance { { std::memset(&acpi, 0, sizeof(acpi)); acpi.Open = Open; - acpi.Close = Close; - acpi.Lookup = Lookup; - acpi.reserved = nullptr; + acpi.Close = Close; + acpi.Lookup = Lookup; + acpi.reserved = nullptr; } ~AudioComponentPlugInInstance() @@ -2812,14 +2880,18 @@ struct AudioComponentPlugInInstance { delete plugin; } - static OSStatus Open(void* const self, const AudioUnit component) + static OSStatus Open(void* const self, const AudioUnit component) { + d_debug("AudioComponentPlugInInstance::Open(%p)", self); + static_cast(self)->plugin = new PluginAU(component); return noErr; } - static OSStatus Close(void* const self) + static OSStatus Close(void* const self) { + d_debug("AudioComponentPlugInInstance::Close(%p)", self); + delete static_cast(self); return noErr; } @@ -2908,15 +2980,15 @@ struct AudioComponentPlugInInstance { d_debug("AudioComponentPlugInInstance::GetPropertyInfo(%p, %d:%x:%s, %d:%s, %d, ...)", self, inProp, inProp, AudioUnitPropertyID2Str(inProp), inScope, AudioUnitScope2Str(inScope), inElement); - UInt32 dataSize = 0; - Boolean writable = false; + UInt32 dataSize = 0; + Boolean writable = false; const OSStatus res = self->plugin->auGetPropertyInfo(inProp, inScope, inElement, dataSize, writable); - if (outDataSize != nullptr) - *outDataSize = dataSize; + if (outDataSize != nullptr) + *outDataSize = dataSize; - if (outWritable != nullptr) - *outWritable = writable; + if (outWritable != nullptr) + *outWritable = writable; return res; } @@ -2928,8 +3000,16 @@ struct AudioComponentPlugInInstance { void* const outData, UInt32* const ioDataSize) { - d_debug("AudioComponentPlugInInstance::GetProperty(%p, %d:%x:%s, %d:%s, %d, ...)", - self, inProp, inProp, AudioUnitPropertyID2Str(inProp), inScope, AudioUnitScope2Str(inScope), inElement); + #ifdef DEBUG + switch (inProp) { + case kAudioUnitProperty_PresentPreset: + break; + default: + d_debug("AudioComponentPlugInInstance::GetProperty(%p, %d:%x:%s, %d:%s, %d, ...)", + self, inProp, inProp, AudioUnitPropertyID2Str(inProp), inScope, AudioUnitScope2Str(inScope), inElement); + break; + } + #endif DISTRHO_SAFE_ASSERT_RETURN(ioDataSize != nullptr, kAudio_ParamError); Boolean writable; @@ -2952,24 +3032,24 @@ struct AudioComponentPlugInInstance { if (res != noErr) return res; - void* outBuffer; + void* outBuffer; uint8_t* tmpBuffer; if (inDataSize < outDataSize) - { - tmpBuffer = new uint8_t[outDataSize]; - outBuffer = tmpBuffer; - } + { + tmpBuffer = new uint8_t[outDataSize]; + outBuffer = tmpBuffer; + } else { - tmpBuffer = nullptr; - outBuffer = outData; - } + tmpBuffer = nullptr; + outBuffer = outData; + } res = self->plugin->auGetProperty(inProp, inScope, inElement, outBuffer); - if (res != noErr) + if (res != noErr) { - *ioDataSize = 0; + *ioDataSize = 0; return res; } diff --git a/distrho/src/DistrhoPluginCLAP.cpp b/distrho/src/DistrhoPluginCLAP.cpp index 498957ec..68fb9e4c 100644 --- a/distrho/src/DistrhoPluginCLAP.cpp +++ b/distrho/src/DistrhoPluginCLAP.cpp @@ -751,6 +751,7 @@ public: updateStateValueCallback), fHost(host), fOutputEvents(nullptr), + fResetParameterIndex(UINT32_MAX), #if DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS != 0 fUsingCV(false), #endif @@ -763,7 +764,19 @@ public: #endif fHostExtensions(host) { - fCachedParameters.setup(fPlugin.getParameterCount()); + if (const uint32_t paramCount = fPlugin.getParameterCount()) + { + fCachedParameters.setup(paramCount); + + for (uint32_t i=0; irequest_restart(fHost); + } + } + bool process(const clap_process_t* const process) { #if DISTRHO_PLUGIN_WANT_MIDI_INPUT @@ -1114,14 +1143,19 @@ public: { const ParameterRanges& ranges(fPlugin.getParameterRanges(index)); - if (fPlugin.getParameterDesignation(index) == kParameterDesignationBypass) + switch (fPlugin.getParameterDesignation(index)) { + case kParameterDesignationBypass: info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_BYPASS|CLAP_PARAM_IS_AUTOMATABLE; std::strcpy(info->name, "Bypass"); std::strcpy(info->module, "dpf_bypass"); - } - else - { + break; + case kParameterDesignationReset: + info->flags = CLAP_PARAM_IS_STEPPED|CLAP_PARAM_IS_READONLY; + std::strcpy(info->name, "Reset"); + std::strcpy(info->module, "dpf_reset"); + break; + default: const uint32_t hints = fPlugin.getParameterHints(index); const uint32_t groupId = fPlugin.getParameterGroupId(index); @@ -1151,6 +1185,7 @@ public: } d_strncpy(info->module + wrtn, fPlugin.getParameterSymbol(index), CLAP_PATH_SIZE - wrtn); + break; } info->id = index; @@ -1786,6 +1821,7 @@ private: const clap_host_t* const fHost; const clap_output_events_t* fOutputEvents; + uint32_t fResetParameterIndex; #if DISTRHO_PLUGIN_NUM_INPUTS != 0 const float* fAudioInputs[DISTRHO_PLUGIN_NUM_INPUTS]; #endif @@ -2284,23 +2320,33 @@ static bool CLAP_ABI clap_plugin_note_ports_get(const clap_plugin_t*, uint32_t, { if (is_input) { - #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT info->id = 0; + #if DISTRHO_PLUGIN_WANT_MIDI_AS_MPE + info->supported_dialects = CLAP_NOTE_DIALECT_MIDI | CLAP_NOTE_DIALECT_MIDI_MPE; + info->preferred_dialect = CLAP_NOTE_DIALECT_MIDI_MPE; + #else info->supported_dialects = CLAP_NOTE_DIALECT_MIDI; info->preferred_dialect = CLAP_NOTE_DIALECT_MIDI; + #endif std::strcpy(info->name, "Event/MIDI Input"); return true; - #endif + #endif } else { - #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT + #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT info->id = 0; + #if DISTRHO_PLUGIN_WANT_MIDI_AS_MPE + info->supported_dialects = CLAP_NOTE_DIALECT_MIDI | CLAP_NOTE_DIALECT_MIDI_MPE; + info->preferred_dialect = CLAP_NOTE_DIALECT_MIDI_MPE; + #else info->supported_dialects = CLAP_NOTE_DIALECT_MIDI; info->preferred_dialect = CLAP_NOTE_DIALECT_MIDI; + #endif std::strcpy(info->name, "Event/MIDI Output"); return true; - #endif + #endif } return false; @@ -2440,9 +2486,10 @@ static void CLAP_ABI clap_plugin_stop_processing(const clap_plugin_t*) // nothing to do } -static void CLAP_ABI clap_plugin_reset(const clap_plugin_t*) +static void CLAP_ABI clap_plugin_reset(const clap_plugin_t* const plugin) { - // nothing to do + PluginCLAP* const instance = static_cast(plugin->plugin_data); + instance->reset(); } static clap_process_status CLAP_ABI clap_plugin_process(const clap_plugin_t* const plugin, const clap_process_t* const process) diff --git a/distrho/src/DistrhoPluginChecks.h b/distrho/src/DistrhoPluginChecks.h index fb05181b..a5349002 100644 --- a/distrho/src/DistrhoPluginChecks.h +++ b/distrho/src/DistrhoPluginChecks.h @@ -65,6 +65,10 @@ # define DISTRHO_PLUGIN_WANT_LATENCY 0 #endif +#ifndef DISTRHO_PLUGIN_WANT_MIDI_AS_MPE +# define DISTRHO_PLUGIN_WANT_MIDI_AS_MPE 0 +#endif + #ifndef DISTRHO_PLUGIN_WANT_MIDI_OUTPUT # define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 #endif @@ -178,6 +182,13 @@ # error Synths need audio output to work! #endif +// -------------------------------------------------------------------------------------------------------------------- +// Test if MIDI as MPE enabled where it doesn't make sense + +#if DISTRHO_PLUGIN_WANT_MIDI_AS_MPE && ! (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT) +# error MIDI as MPE needs MIDI input or output to work! +#endif + // -------------------------------------------------------------------------------------------------------------------- // Enable MIDI input if synth, test if midi-input disabled when synth diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp index ba3cb196..3b0d22cb 100644 --- a/distrho/src/DistrhoPluginLV2export.cpp +++ b/distrho/src/DistrhoPluginLV2export.cpp @@ -758,6 +758,16 @@ void lv2_generate_ttl(const char* const basename) pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n"; pluginString += " lv2:designation lv2:enabled ;\n"; break; + case kParameterDesignationReset: + designated = true; + pluginString += " lv2:name \"Reset\" ;\n"; + pluginString += " lv2:symbol \"" + String(ParameterDesignationSymbols::reset) + "\" ;\n"; + pluginString += " lv2:default 0 ;\n"; + pluginString += " lv2:minimum 0 ;\n"; + pluginString += " lv2:maximum 1 ;\n"; + pluginString += " lv2:portProperty lv2:toggled , lv2:integer , <" LV2_PORT_PROPS__trigger "> ;\n"; + pluginString += " lv2:designation <" LV2_KXSTUDIO_PROPERTIES__Reset "> ;\n"; + break; } } diff --git a/distrho/src/DistrhoPluginVST3.cpp b/distrho/src/DistrhoPluginVST3.cpp index a2d52367..6055bc33 100644 --- a/distrho/src/DistrhoPluginVST3.cpp +++ b/distrho/src/DistrhoPluginVST3.cpp @@ -1763,6 +1763,12 @@ public: case kParameterDesignationBypass: flags |= V3_PARAM_IS_BYPASS; break; + case kParameterDesignationReset: + info->flags = V3_PARAM_READ_ONLY | V3_PARAM_IS_HIDDEN; + info->step_count = 1; + strncpy_utf16(info->title, "Reset", 128); + strncpy_utf16(info->short_title, "Reset", 128); + return V3_OK; } if (hints & kParameterIsOutput) diff --git a/distrho/src/DistrhoUIAU.mm b/distrho/src/DistrhoUIAU.mm index c0987f51..1b3f77e5 100644 --- a/distrho/src/DistrhoUIAU.mm +++ b/distrho/src/DistrhoUIAU.mm @@ -387,6 +387,9 @@ END_NAMESPACE_DISTRHO #define COCOA_VIEW_CLASS_NAME \ MACRO_NAME(CocoaView_, DISTRHO_PLUGIN_AU_TYPE, _, DISTRHO_PLUGIN_UNIQUE_ID, _, DISTRHO_PLUGIN_BRAND_ID) +using DISTRHO_NAMESPACE::DPF_UI_AU; +using DISTRHO_NAMESPACE::d_nextSampleRate; + @interface COCOA_VIEW_CLASS_NAME : NSView { @public diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp index e9ae05c5..ea3f56a2 100644 --- a/distrho/src/DistrhoUIInternal.hpp +++ b/distrho/src/DistrhoUIInternal.hpp @@ -267,12 +267,12 @@ public: uiData->app.repaintIfNeeeded(); } - void addIdleCallbackForNativeIdle(IdleCallback* const cb, const uint timerFrequencyInMs) + void addIdleCallbackForNativeIdle(DGL_NAMESPACE::IdleCallback* const cb, const uint timerFrequencyInMs) { uiData->window->addIdleCallback(cb, timerFrequencyInMs); } - void removeIdleCallbackForNativeIdle(IdleCallback* const cb) + void removeIdleCallbackForNativeIdle(DGL_NAMESPACE::IdleCallback* const cb) { uiData->window->removeIdleCallback(cb); } diff --git a/distrho/src/DistrhoUIVST3.cpp b/distrho/src/DistrhoUIVST3.cpp index 0ecf675f..a326c4b3 100644 --- a/distrho/src/DistrhoUIVST3.cpp +++ b/distrho/src/DistrhoUIVST3.cpp @@ -129,7 +129,7 @@ static uint translateVST3Modifiers(const int64_t modifiers) noexcept * Helper class for getting a native idle timer. */ #if !DPF_VST3_USING_HOST_RUN_LOOP -class NativeIdleCallback : public IdleCallback +class NativeIdleCallback : public DGL_NAMESPACE::IdleCallback { public: NativeIdleCallback(UIExporter& ui) diff --git a/distrho/src/lv2/lv2_kxstudio_properties.h b/distrho/src/lv2/lv2_kxstudio_properties.h index 22922650..68dbe66f 100644 --- a/distrho/src/lv2/lv2_kxstudio_properties.h +++ b/distrho/src/lv2/lv2_kxstudio_properties.h @@ -1,6 +1,6 @@ /* LV2 KXStudio Properties Extension - Copyright 2014-2021 Filipe Coelho + Copyright 2014-2024 Filipe Coelho Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -27,6 +27,7 @@ #define LV2_KXSTUDIO_PROPERTIES_PREFIX LV2_KXSTUDIO_PROPERTIES_URI "#" #define LV2_KXSTUDIO_PROPERTIES__NonAutomatable LV2_KXSTUDIO_PROPERTIES_PREFIX "NonAutomatable" +#define LV2_KXSTUDIO_PROPERTIES__Reset LV2_KXSTUDIO_PROPERTIES_PREFIX "Reset" #define LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat LV2_KXSTUDIO_PROPERTIES_PREFIX "TimePositionTicksPerBeat" #define LV2_KXSTUDIO_PROPERTIES__TransientWindowId LV2_KXSTUDIO_PROPERTIES_PREFIX "TransientWindowId"