@@ -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; | |||