| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2018 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 | |||
| @@ -89,6 +89,15 @@ static const uint32_t kParameterIsLogarithmic = 0x08; | |||
| */ | |||
| static const uint32_t kParameterIsOutput = 0x10; | |||
| /** | |||
| Parameter value is a trigger.@n | |||
| This means the value resets back to its default after each process/run call.@n | |||
| Cannot be used for output parameters. | |||
| @note Only officially supported under LV2. For other formats DPF simulates the behaviour. | |||
| */ | |||
| static const uint32_t kParameterIsTrigger = 0x20 | kParameterIsBoolean; | |||
| /** @} */ | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| @@ -274,6 +283,90 @@ struct ParameterRanges { | |||
| } | |||
| }; | |||
| /** | |||
| Parameter enumeration value.@n | |||
| A string representation of a plugin parameter value.@n | |||
| Used together can be used to give meaning to parameter values, working as an enumeration. | |||
| */ | |||
| struct ParameterEnumerationValue { | |||
| /** | |||
| Parameter value. | |||
| */ | |||
| float value; | |||
| /** | |||
| String representation of this value. | |||
| */ | |||
| String label; | |||
| /** | |||
| Default constructor, using 0.0 as value and empty label. | |||
| */ | |||
| ParameterEnumerationValue() noexcept | |||
| : value(0.0f), | |||
| label() {} | |||
| /** | |||
| Constructor using custom values. | |||
| */ | |||
| ParameterEnumerationValue(float v, const char* l) noexcept | |||
| : value(v), | |||
| label(l) {} | |||
| }; | |||
| /** | |||
| Collection of parameter enumeration values.@n | |||
| Handy class to handle the lifetime and count of all enumeration values. | |||
| */ | |||
| struct ParameterEnumerationValues { | |||
| /** | |||
| Number of elements allocated in @values. | |||
| */ | |||
| uint8_t count; | |||
| /** | |||
| Wherever the host is to be restricted to only use enumeration values. | |||
| @note This mode is only a hint! Not all hosts and plugin formats support this mode. | |||
| */ | |||
| bool restrictedMode; | |||
| /** | |||
| Array of @ParameterEnumerationValue items.@n | |||
| This pointer must be null or have been allocated on the heap with `new`. | |||
| */ | |||
| const ParameterEnumerationValue* values; | |||
| /** | |||
| Default constructor, for zero enumeration values. | |||
| */ | |||
| ParameterEnumerationValues() noexcept | |||
| : count(0), | |||
| restrictedMode(false), | |||
| values() {} | |||
| /** | |||
| Constructor using custom values.@n | |||
| The pointer to @values must have been allocated on the heap with `new`. | |||
| */ | |||
| ParameterEnumerationValues(uint32_t c, bool r, const ParameterEnumerationValue* v) noexcept | |||
| : count(c), | |||
| restrictedMode(r), | |||
| values(v) {} | |||
| ~ParameterEnumerationValues() noexcept | |||
| { | |||
| count = 0; | |||
| restrictedMode = false; | |||
| if (values != nullptr) | |||
| { | |||
| delete[] values; | |||
| values = nullptr; | |||
| } | |||
| } | |||
| }; | |||
| /** | |||
| Parameter. | |||
| */ | |||
| @@ -312,6 +405,12 @@ struct Parameter { | |||
| */ | |||
| ParameterRanges ranges; | |||
| /** | |||
| Enumeration values.@n | |||
| Can be used to give meaning to parameter values, working as an enumeration. | |||
| */ | |||
| ParameterEnumerationValues enumValues; | |||
| /** | |||
| Designation for this parameter. | |||
| */ | |||
| @@ -334,6 +433,7 @@ struct Parameter { | |||
| symbol(), | |||
| unit(), | |||
| ranges(), | |||
| enumValues(), | |||
| designation(kParameterDesignationNull), | |||
| midiCC(0) {} | |||
| @@ -346,6 +446,7 @@ struct Parameter { | |||
| symbol(s), | |||
| unit(u), | |||
| ranges(def, min, max), | |||
| enumValues(), | |||
| designation(kParameterDesignationNull), | |||
| midiCC(0) {} | |||
| @@ -593,9 +694,6 @@ public: | |||
| Write a MIDI output event.@n | |||
| This function must only be called during run().@n | |||
| Returns false when the host buffer is full, in which case do not call this again until the next run(). | |||
| @note This function is not implemented yet!@n | |||
| It's here so that developers can prepare MIDI plugins in advance.@n | |||
| If you plan to use this, please report to DPF authors so it can be implemented. | |||
| */ | |||
| bool writeMidiEvent(const MidiEvent& midiEvent) noexcept; | |||
| #endif | |||
| @@ -90,10 +90,11 @@ public: | |||
| void setState(const char* key, const char* value); | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| /** | |||
| sendNote. | |||
| @TODO Document this. | |||
| @note Work in progress. Implemented for DSSI and LV2 formats. | |||
| */ | |||
| void sendNote(uint8_t channel, uint8_t note, uint8_t velocity); | |||
| #endif | |||
| @@ -106,7 +106,7 @@ std::vector<uint8_t> d_getChunkFromBase64String(const char* const base64string) | |||
| if (c == ' ' || c == '\n') | |||
| continue; | |||
| DISTRHO_SAFE_ASSERT_CONTINUE(CarlaBase64Helpers::isBase64Char(c)); | |||
| DISTRHO_SAFE_ASSERT_CONTINUE(DistrhoBase64Helpers::isBase64Char(c)); | |||
| charArray4[i++] = static_cast<uint>(c); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2018 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 | |||
| @@ -27,9 +27,10 @@ double d_lastSampleRate = 0.0; | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Static fallback data, see DistrhoPluginInternal.hpp */ | |||
| const String PluginExporter::sFallbackString; | |||
| const AudioPort PluginExporter::sFallbackAudioPort; | |||
| const ParameterRanges PluginExporter::sFallbackRanges; | |||
| const String PluginExporter::sFallbackString; | |||
| const AudioPort PluginExporter::sFallbackAudioPort; | |||
| const ParameterRanges PluginExporter::sFallbackRanges; | |||
| const ParameterEnumerationValues PluginExporter::sFallbackEnumValues; | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Plugin */ | |||
| @@ -102,10 +103,9 @@ void Plugin::setLatency(uint32_t frames) noexcept | |||
| #endif | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| bool Plugin::writeMidiEvent(const MidiEvent& /*midiEvent*/) noexcept | |||
| bool Plugin::writeMidiEvent(const MidiEvent& midiEvent) noexcept | |||
| { | |||
| // TODO | |||
| return false; | |||
| return pData->writeMidiCallback(midiEvent); | |||
| } | |||
| #endif | |||
| @@ -1,17 +1,17 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * 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. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LGPL.txt file | |||
| * 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" | |||
| @@ -30,6 +30,9 @@ START_NAMESPACE_DISTRHO | |||
| // ----------------------------------------------------------------------- | |||
| // Carla UI | |||
| #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| static const writeMidiFunc writeMidiCallback = nullptr; | |||
| #endif | |||
| #if ! DISTRHO_PLUGIN_WANT_STATE | |||
| static const setStateFunc setStateCallback = nullptr; | |||
| #endif | |||
| @@ -104,15 +107,19 @@ protected: | |||
| 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 | |||
| void handleSetSize(const uint width, const uint height) | |||
| { | |||
| @@ -175,7 +182,8 @@ class PluginCarla : public NativePluginClass | |||
| { | |||
| public: | |||
| PluginCarla(const NativeHostDescriptor* const host) | |||
| : NativePluginClass(host) | |||
| : NativePluginClass(host), | |||
| fPlugin(this, writeMidiCallback) | |||
| { | |||
| #if DISTRHO_PLUGIN_HAS_UI | |||
| fUiPtr = nullptr; | |||
| @@ -317,7 +325,7 @@ protected: | |||
| fPlugin.deactivate(); | |||
| } | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override | |||
| { | |||
| MidiEvent realMidiEvents[midiEventCount]; | |||
| @@ -455,6 +463,20 @@ private: | |||
| } | |||
| #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 | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla) | |||
| // ------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2018 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 | |||
| @@ -32,6 +32,11 @@ static const uint32_t kMaxMidiEvents = 512; | |||
| extern uint32_t d_lastBufferSize; | |||
| extern double d_lastSampleRate; | |||
| // ----------------------------------------------------------------------- | |||
| // DSP callbacks | |||
| typedef bool (*writeMidiFunc) (void* ptr, const MidiEvent& midiEvent); | |||
| // ----------------------------------------------------------------------- | |||
| // Plugin private data | |||
| @@ -65,6 +70,10 @@ struct Plugin::PrivateData { | |||
| TimePosition timePosition; | |||
| #endif | |||
| // Callbacks | |||
| void* callbacksPtr; | |||
| writeMidiFunc writeMidiCallbackFunc; | |||
| uint32_t bufferSize; | |||
| double sampleRate; | |||
| @@ -88,6 +97,8 @@ struct Plugin::PrivateData { | |||
| #if DISTRHO_PLUGIN_WANT_LATENCY | |||
| latency(0), | |||
| #endif | |||
| callbacksPtr(nullptr), | |||
| writeMidiCallbackFunc(nullptr), | |||
| bufferSize(d_lastBufferSize), | |||
| sampleRate(d_lastSampleRate) | |||
| { | |||
| @@ -149,6 +160,16 @@ struct Plugin::PrivateData { | |||
| } | |||
| #endif | |||
| } | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |||
| bool writeMidiCallback(const MidiEvent& midiEvent) | |||
| { | |||
| if (writeMidiCallbackFunc != nullptr) | |||
| return writeMidiCallbackFunc(callbacksPtr, midiEvent); | |||
| return false; | |||
| } | |||
| #endif | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -157,7 +178,7 @@ struct Plugin::PrivateData { | |||
| class PluginExporter | |||
| { | |||
| public: | |||
| PluginExporter() | |||
| PluginExporter(void* const callbacksPtr, const writeMidiFunc writeMidiCall) | |||
| : fPlugin(createPlugin()), | |||
| fData((fPlugin != nullptr) ? fPlugin->pData : nullptr), | |||
| fIsActive(false) | |||
| @@ -191,6 +212,9 @@ public: | |||
| for (uint32_t i=0, count=fData->stateCount; i < count; ++i) | |||
| fPlugin->initState(i, fData->stateKeys[i], fData->stateDefValues[i]); | |||
| #endif | |||
| fData->callbacksPtr = callbacksPtr; | |||
| fData->writeMidiCallbackFunc = writeMidiCall; | |||
| } | |||
| ~PluginExporter() | |||
| @@ -322,9 +346,26 @@ public: | |||
| return fData->parameters[index].designation; | |||
| } | |||
| bool isParameterInput(const uint32_t index) const noexcept | |||
| { | |||
| return (getParameterHints(index) & kParameterIsOutput) == 0x0; | |||
| } | |||
| bool isParameterOutput(const uint32_t index) const noexcept | |||
| { | |||
| return (getParameterHints(index) & kParameterIsOutput); | |||
| return (getParameterHints(index) & kParameterIsOutput) != 0x0; | |||
| } | |||
| bool isParameterOutputOrTrigger(const uint32_t index) const noexcept | |||
| { | |||
| const uint32_t hints = getParameterHints(index); | |||
| if (hints & kParameterIsOutput) | |||
| return true; | |||
| if ((hints & kParameterIsTrigger) == kParameterIsTrigger) | |||
| return true; | |||
| return false; | |||
| } | |||
| const String& getParameterName(const uint32_t index) const noexcept | |||
| @@ -348,6 +389,13 @@ public: | |||
| return fData->parameters[index].unit; | |||
| } | |||
| const ParameterEnumerationValues& getParameterEnumValues(const uint32_t index) const noexcept | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackEnumValues); | |||
| return fData->parameters[index].enumValues; | |||
| } | |||
| const ParameterRanges& getParameterRanges(const uint32_t index) const noexcept | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, sFallbackRanges); | |||
| @@ -503,7 +551,7 @@ public: | |||
| } | |||
| } | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| void run(const float** const inputs, float** const outputs, const uint32_t frames, | |||
| const MidiEvent* const midiEvents, const uint32_t midiEventCount) | |||
| { | |||
| @@ -601,9 +649,10 @@ private: | |||
| // ------------------------------------------------------------------- | |||
| // Static fallback data, see DistrhoPlugin.cpp | |||
| static const String sFallbackString; | |||
| static const AudioPort sFallbackAudioPort; | |||
| static const ParameterRanges sFallbackRanges; | |||
| static const String sFallbackString; | |||
| static const AudioPort sFallbackAudioPort; | |||
| static const ParameterRanges sFallbackRanges; | |||
| static const ParameterEnumerationValues sFallbackEnumValues; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginExporter) | |||
| DISTRHO_PREVENT_HEAP_ALLOCATION | |||
| @@ -82,7 +82,7 @@ void UI::setState(const char* key, const char* value) | |||
| } | |||
| #endif | |||
| #if DISTRHO_PLUGIN_IS_SYNTH | |||
| #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
| void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | |||
| { | |||
| pData->sendNoteCallback(channel, note, velocity); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2018 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 | |||
| @@ -61,12 +61,12 @@ struct UI::PrivateData { | |||
| #endif | |||
| // Callbacks | |||
| void* callbacksPtr; | |||
| editParamFunc editParamCallbackFunc; | |||
| setParamFunc setParamCallbackFunc; | |||
| setStateFunc setStateCallbackFunc; | |||
| sendNoteFunc sendNoteCallbackFunc; | |||
| setSizeFunc setSizeCallbackFunc; | |||
| void* ptr; | |||
| PrivateData() noexcept | |||
| : sampleRate(d_lastUiSampleRate), | |||
| @@ -74,12 +74,12 @@ struct UI::PrivateData { | |||
| #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
| dspPtr(d_lastUiDspPtr), | |||
| #endif | |||
| callbacksPtr(nullptr), | |||
| editParamCallbackFunc(nullptr), | |||
| setParamCallbackFunc(nullptr), | |||
| setStateCallbackFunc(nullptr), | |||
| sendNoteCallbackFunc(nullptr), | |||
| setSizeCallbackFunc(nullptr), | |||
| ptr(nullptr) | |||
| setSizeCallbackFunc(nullptr) | |||
| { | |||
| DISTRHO_SAFE_ASSERT(d_isNotZero(sampleRate)); | |||
| @@ -103,31 +103,31 @@ struct UI::PrivateData { | |||
| void editParamCallback(const uint32_t rindex, const bool started) | |||
| { | |||
| if (editParamCallbackFunc != nullptr) | |||
| editParamCallbackFunc(ptr, rindex, started); | |||
| editParamCallbackFunc(callbacksPtr, rindex, started); | |||
| } | |||
| void setParamCallback(const uint32_t rindex, const float value) | |||
| { | |||
| if (setParamCallbackFunc != nullptr) | |||
| setParamCallbackFunc(ptr, rindex, value); | |||
| setParamCallbackFunc(callbacksPtr, rindex, value); | |||
| } | |||
| void setStateCallback(const char* const key, const char* const value) | |||
| { | |||
| if (setStateCallbackFunc != nullptr) | |||
| setStateCallbackFunc(ptr, key, value); | |||
| setStateCallbackFunc(callbacksPtr, key, value); | |||
| } | |||
| void sendNoteCallback(const uint8_t channel, const uint8_t note, const uint8_t velocity) | |||
| { | |||
| if (sendNoteCallbackFunc != nullptr) | |||
| sendNoteCallbackFunc(ptr, channel, note, velocity); | |||
| sendNoteCallbackFunc(callbacksPtr, channel, note, velocity); | |||
| } | |||
| void setSizeCallback(const uint width, const uint height) | |||
| { | |||
| if (setSizeCallbackFunc != nullptr) | |||
| setSizeCallbackFunc(ptr, width, height); | |||
| setSizeCallbackFunc(callbacksPtr, width, height); | |||
| } | |||
| }; | |||
| @@ -221,8 +221,13 @@ UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const char* const | |||
| class UIExporter | |||
| { | |||
| public: | |||
| UIExporter(void* const ptr, const intptr_t winId, | |||
| const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall, | |||
| UIExporter(void* const callbacksPtr, | |||
| const intptr_t winId, | |||
| const editParamFunc editParamCall, | |||
| const setParamFunc setParamCall, | |||
| const setStateFunc setStateCall, | |||
| const sendNoteFunc sendNoteCall, | |||
| const setSizeFunc setSizeCall, | |||
| void* const dspPtr = nullptr, | |||
| const char* const bundlePath = nullptr) | |||
| #ifdef HAVE_DGL | |||
| @@ -238,7 +243,7 @@ public: | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
| fData->ptr = ptr; | |||
| fData->callbacksPtr = callbacksPtr; | |||
| fData->editParamCallbackFunc = editParamCall; | |||
| fData->setParamCallbackFunc = setParamCall; | |||
| fData->setStateCallbackFunc = setStateCall; | |||