diff DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCarla.cpp @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCarla.cpp	Mon Oct 16 21:53:34 2023 +0200
@@ -0,0 +1,551 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2022 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 "DistrhoPluginInternal.hpp"
+
+#if DISTRHO_PLUGIN_HAS_UI
+# include "DistrhoUIInternal.hpp"
+#endif
+
+#include "CarlaNative.hpp"
+
+// TODO
+#undef DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
+#define DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 0
+
+// -----------------------------------------------------------------------
+
+START_NAMESPACE_DISTRHO
+
+#if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
+static constexpr const writeMidiFunc writeMidiCallback = nullptr;
+#endif
+#if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
+static constexpr const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr;
+#endif
+// TODO
+static constexpr const updateStateValueFunc updateStateValueCallback = nullptr;
+
+#if DISTRHO_PLUGIN_HAS_UI
+// -----------------------------------------------------------------------
+// Carla UI
+
+#if ! DISTRHO_PLUGIN_WANT_STATE
+static const setStateFunc setStateCallback = nullptr;
+#endif
+#if ! DISTRHO_PLUGIN_IS_SYNTH
+static const sendNoteFunc sendNoteCallback = nullptr;
+#endif
+
+class UICarla
+{
+public:
+    UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin)
+        : fHost(host),
+          fUI(this, 0, plugin->getSampleRate(),
+              editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback,
+              nullptr, // window size
+              nullptr, // TODO file request
+              nullptr, // bundle path
+              plugin->getInstancePointer())
+    {
+        fUI.setWindowTitle(host->uiName);
+
+        if (host->uiParentId != 0)
+            fUI.setWindowTransientWinId(host->uiParentId);
+    }
+
+    ~UICarla()
+    {
+        fUI.quit();
+    }
+
+    // ---------------------------------------------
+
+    void carla_show(const bool yesNo)
+    {
+        fUI.setWindowVisible(yesNo);
+    }
+
+    bool carla_idle()
+    {
+        return fUI.plugin_idle();
+    }
+
+    void carla_setParameterValue(const uint32_t index, const float value)
+    {
+        fUI.parameterChanged(index, value);
+    }
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+    void carla_setMidiProgram(const uint32_t realProgram)
+    {
+        fUI.programLoaded(realProgram);
+    }
+#endif
+
+#if DISTRHO_PLUGIN_WANT_STATE
+    void carla_setCustomData(const char* const key, const char* const value)
+    {
+        fUI.stateChanged(key, value);
+    }
+#endif
+
+    void carla_setUiTitle(const char* const uiTitle)
+    {
+        fUI.setWindowTitle(uiTitle);
+    }
+
+    // ---------------------------------------------
+
+protected:
+    void handleEditParameter(const uint32_t, const bool)
+    {
+        // TODO
+    }
+
+    void handleSetParameterValue(const uint32_t rindex, const float value)
+    {
+        fHost->ui_parameter_changed(fHost->handle, rindex, value);
+    }
+
+#if DISTRHO_PLUGIN_WANT_STATE
+    void handleSetState(const char* const key, const char* const value)
+    {
+        fHost->ui_custom_data_changed(fHost->handle, key, value);
+    }
+#endif
+
+#if DISTRHO_PLUGIN_IS_SYNTH
+    void handleSendNote(const uint8_t, const uint8_t, const uint8_t)
+    {
+        // TODO
+    }
+#endif
+
+    // ---------------------------------------------
+
+private:
+    // Plugin stuff
+    const NativeHostDescriptor* const fHost;
+
+    // UI
+    UIExporter fUI;
+
+    // ---------------------------------------------
+    // Callbacks
+
+    #define handlePtr ((UICarla*)ptr)
+
+    static void editParameterCallback(void* ptr, uint32_t index, bool started)
+    {
+        handlePtr->handleEditParameter(index, started);
+    }
+
+    static void setParameterCallback(void* ptr, uint32_t rindex, float value)
+    {
+        handlePtr->handleSetParameterValue(rindex, value);
+    }
+
+#if DISTRHO_PLUGIN_WANT_STATE
+    static void setStateCallback(void* ptr, const char* key, const char* value)
+    {
+        handlePtr->handleSetState(key, value);
+    }
+#endif
+
+#if DISTRHO_PLUGIN_IS_SYNTH
+    static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
+    {
+        handlePtr->handleSendNote(channel, note, velocity);
+    }
+#endif
+
+    #undef handlePtr
+
+    CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla)
+};
+#endif // DISTRHO_PLUGIN_HAS_UI
+
+// -----------------------------------------------------------------------
+// Carla Plugin
+
+class PluginCarla : public NativePluginClass
+{
+public:
+    PluginCarla(const NativeHostDescriptor* const host)
+        : NativePluginClass(host),
+          fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback),
+          fScalePointsCache(nullptr)
+    {
+#if DISTRHO_PLUGIN_HAS_UI
+        fUiPtr = nullptr;
+#endif
+    }
+
+    ~PluginCarla() override
+    {
+#if DISTRHO_PLUGIN_HAS_UI
+        if (fUiPtr != nullptr)
+        {
+            delete fUiPtr;
+            fUiPtr = nullptr;
+        }
+#endif
+
+        if (fScalePointsCache != nullptr)
+        {
+            delete[] fScalePointsCache;
+            fScalePointsCache = nullptr;
+        }
+    }
+
+protected:
+    // -------------------------------------------------------------------
+    // Plugin parameter calls
+
+    uint32_t getParameterCount() const override
+    {
+        return fPlugin.getParameterCount();
+    }
+
+    const NativeParameter* getParameterInfo(const uint32_t index) const override
+    {
+        CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
+
+        static NativeParameter param;
+
+        param.scalePointCount = 0;
+        param.scalePoints = nullptr;
+
+        {
+            int      nativeParamHints = ::NATIVE_PARAMETER_IS_ENABLED;
+            const uint32_t paramHints = fPlugin.getParameterHints(index);
+
+            if (paramHints & kParameterIsAutomatable)
+                nativeParamHints |= ::NATIVE_PARAMETER_IS_AUTOMABLE;
+            if (paramHints & kParameterIsBoolean)
+                nativeParamHints |= ::NATIVE_PARAMETER_IS_BOOLEAN;
+            if (paramHints & kParameterIsInteger)
+                nativeParamHints |= ::NATIVE_PARAMETER_IS_INTEGER;
+            if (paramHints & kParameterIsLogarithmic)
+                nativeParamHints |= ::NATIVE_PARAMETER_IS_LOGARITHMIC;
+            if (paramHints & kParameterIsOutput)
+                nativeParamHints |= ::NATIVE_PARAMETER_IS_OUTPUT;
+
+            param.hints = static_cast<NativeParameterHints>(nativeParamHints);
+        }
+
+        param.name = fPlugin.getParameterName(index);
+        param.unit = fPlugin.getParameterUnit(index);
+
+        {
+            const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
+
+            param.ranges.def = ranges.def;
+            param.ranges.min = ranges.min;
+            param.ranges.max = ranges.max;
+        }
+
+        {
+            const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index));
+
+            if (const uint32_t scalePointCount = enumValues.count)
+            {
+                NativeParameterScalePoint* const scalePoints = new NativeParameterScalePoint[scalePointCount];
+
+                for (uint32_t i=0; i<scalePointCount; ++i)
+                {
+                    scalePoints[i].label = enumValues.values[i].label.buffer();
+                    scalePoints[i].value = enumValues.values[i].value;
+                }
+
+                param.scalePoints     = scalePoints;
+                param.scalePointCount = scalePointCount;
+
+                if (enumValues.restrictedMode)
+                    param.hints = static_cast<NativeParameterHints>(param.hints|::NATIVE_PARAMETER_USES_SCALEPOINTS);
+            }
+            else if (fScalePointsCache != nullptr)
+            {
+                delete[] fScalePointsCache;
+                fScalePointsCache = nullptr;
+            }
+        }
+
+        return &param;
+    }
+
+    float getParameterValue(const uint32_t index) const override
+    {
+        CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
+
+        return fPlugin.getParameterValue(index);
+    }
+
+    // -------------------------------------------------------------------
+    // Plugin midi-program calls
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+    uint32_t getMidiProgramCount() const override
+    {
+        return fPlugin.getProgramCount();
+    }
+
+    const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override
+    {
+        CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
+
+        static NativeMidiProgram midiProgram;
+
+        midiProgram.bank    = index / 128;
+        midiProgram.program = index % 128;
+        midiProgram.name    = fPlugin.getProgramName(index);
+
+        return &midiProgram;
+    }
+#endif
+
+    // -------------------------------------------------------------------
+    // Plugin state calls
+
+    void setParameterValue(const uint32_t index, const float value) override
+    {
+        CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
+
+        fPlugin.setParameterValue(index, value);
+    }
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+    void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
+    {
+        const uint32_t realProgram(bank * 128 + program);
+
+        CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);
+
+        fPlugin.loadProgram(realProgram);
+    }
+#endif
+
+#if DISTRHO_PLUGIN_WANT_STATE
+    void setCustomData(const char* const key, const char* const value) override
+    {
+        CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
+        CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
+
+        fPlugin.setState(key, value);
+    }
+#endif
+
+    // -------------------------------------------------------------------
+    // Plugin process calls
+
+    void activate() override
+    {
+        fPlugin.activate();
+    }
+
+    void deactivate() override
+    {
+        fPlugin.deactivate();
+    }
+
+#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
+    void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames,
+                 const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
+    {
+        MidiEvent realMidiEvents[midiEventCount];
+
+        for (uint32_t i=0; i < midiEventCount; ++i)
+        {
+            const NativeMidiEvent& midiEvent(midiEvents[i]);
+            MidiEvent& realMidiEvent(realMidiEvents[i]);
+
+            realMidiEvent.frame = midiEvent.time;
+            realMidiEvent.size  = midiEvent.size;
+
+            uint8_t j=0;
+            for (; j<midiEvent.size; ++j)
+                realMidiEvent.data[j] = midiEvent.data[j];
+            for (; j<midiEvent.size; ++j)
+                realMidiEvent.data[j] = midiEvent.data[j];
+
+            realMidiEvent.dataExt = nullptr;
+        }
+
+        fPlugin.run(const_cast<const float**>(inBuffer), outBuffer, frames, realMidiEvents, midiEventCount);
+    }
+#else
+    void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames,
+                 const NativeMidiEvent* const, const uint32_t) override
+    {
+        fPlugin.run(const_cast<const float**>(inBuffer), outBuffer, frames);
+    }
+#endif
+
+    // -------------------------------------------------------------------
+    // Plugin UI calls
+
+#if DISTRHO_PLUGIN_HAS_UI
+    void uiShow(const bool show) override
+    {
+        if (show)
+        {
+            createUiIfNeeded();
+            CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
+
+            fUiPtr->carla_show(show);
+        }
+        else if (fUiPtr != nullptr)
+        {
+            delete fUiPtr;
+            fUiPtr = nullptr;
+        }
+    }
+
+    void uiIdle() override
+    {
+        CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
+
+        if (! fUiPtr->carla_idle())
+        {
+            uiClosed();
+
+            delete fUiPtr;
+            fUiPtr = nullptr;
+        }
+    }
+
+    void uiSetParameterValue(const uint32_t index, const float value) override
+    {
+        CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
+        CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
+
+        fUiPtr->carla_setParameterValue(index, value);
+    }
+
+# if DISTRHO_PLUGIN_WANT_PROGRAMS
+    void uiSetMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
+    {
+        CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
+
+        const uint32_t realProgram(bank * 128 + program);
+
+        CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);
+
+        fUiPtr->carla_setMidiProgram(realProgram);
+    }
+# endif
+
+# if DISTRHO_PLUGIN_WANT_STATE
+    void uiSetCustomData(const char* const key, const char* const value) override
+    {
+        CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
+        CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
+        CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
+
+        fUiPtr->carla_setCustomData(key, value);
+    }
+# endif
+#endif
+
+    // -------------------------------------------------------------------
+    // Plugin dispatcher calls
+
+    void bufferSizeChanged(const uint32_t bufferSize) override
+    {
+        fPlugin.setBufferSize(bufferSize, true);
+    }
+
+    void sampleRateChanged(const double sampleRate) override
+    {
+        fPlugin.setSampleRate(sampleRate, true);
+    }
+
+#if DISTRHO_PLUGIN_HAS_UI
+    void uiNameChanged(const char* const uiName) override
+    {
+        CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
+
+        fUiPtr->carla_setUiTitle(uiName);
+    }
+#endif
+
+    // -------------------------------------------------------------------
+
+private:
+    PluginExporter fPlugin;
+    mutable NativeParameterScalePoint* fScalePointsCache;
+
+#if DISTRHO_PLUGIN_HAS_UI
+    // UI
+    UICarla* fUiPtr;
+
+    void createUiIfNeeded()
+    {
+        if (fUiPtr == nullptr)
+            fUiPtr = new UICarla(getHostHandle(), &fPlugin);
+    }
+#endif
+
+#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
+    static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
+    {
+        if (midiEvent.size > 4)
+            return;
+
+        const NativeMidiEvent event = {
+            midiEvent.frame, 0, midiEvent.size, midiEvent.data
+        };
+
+        return ((PluginCarla*)ptr)->fPlugin.writeMidiEvent(midiEvent);
+    }
+#endif
+
+#if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
+    bool requestParameterValueChange(const uint32_t index, const float value)
+    {
+        // TODO implementation
+        return false;
+    }
+
+    static bool requestParameterValueChangeCallback(void* ptr, const uint32_t index, const float value)
+    {
+        return thisPtr->requestParameterValueChange(index, value);
+    }
+#endif
+
+    CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla)
+
+    // -------------------------------------------------------------------
+
+public:
+    static NativePluginHandle _instantiate(const NativeHostDescriptor* host)
+    {
+        d_nextBufferSize = host->get_buffer_size(host->handle);
+        d_nextSampleRate = host->get_sample_rate(host->handle);
+        return new PluginCarla(host);
+    }
+
+    static void _cleanup(NativePluginHandle handle)
+    {
+        delete (PluginCarla*)handle;
+    }
+};
+
+END_NAMESPACE_DISTRHO
+
+// -----------------------------------------------------------------------