commit cfb1873d85f2d291f9338ae1897d4051b5df8f9e
parent 4edb06e60ee5c81af38b0b060f225dfd05d5a41e
Author: falkTX <falktx@falktx.com>
Date: Sat, 25 Sep 2021 15:48:46 +0100
VST3: Implement programs on DSP side, update TODO items
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
4 files changed, 119 insertions(+), 24 deletions(-)
diff --git a/distrho/src/DistrhoPluginVST3.cpp b/distrho/src/DistrhoPluginVST3.cpp
@@ -27,11 +27,24 @@
/* TODO items:
* - base component refcount handling
- * - program support
+ * - parameter enumeration as lists
+ * - hide parameter outputs?
+ * - hide program parameter?
* - state support
+ * - save and restore current program
* - midi cc parameter mapping
* - full MIDI1 encode and decode
- * - call component handler restart with params-changed flag when setting program
+ * - decode version number (0x102030 -> 1.2.3)
+ * - bus arrangements
+ * - optional audio buses, create dummy buffer of max_block_size length for them
+ * - routing info, do we care?
+ * - set sidechain bus name from port group
+ * - implement getParameterValueForString
+ * - set factory class_flags
+ * - set factory sub_categories
+ * - set factory email (needs new DPF API, useful for LV2 as well)
+ * - do something with get_controller_class_id and set_io_mode?
+ * - call component handler restart with params-changed flag after changing program
* - call component handler restart with latency-changed flag when latency changes
*/
@@ -227,10 +240,15 @@ public:
PluginVst3()
: fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback),
fComponentHandler(nullptr),
+ fParameterOffset(fPlugin.getParameterOffset()),
fParameterValues(nullptr)
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
, fHostEventOutputHandle(nullptr)
#endif
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ , fCurrentProgram(0),
+ fProgramCountMinusOne(fPlugin.getProgramCount()-1)
+#endif
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS; ++i)
@@ -417,7 +435,7 @@ public:
{
const AudioPortWithBusId& port(fPlugin.getAudioPort(true, i));
- // TODO find port group name
+ // TODO find port group name for sidechain buses
if (port.busId == busId)
{
strncpy_utf16(busName, port.name, 128);
@@ -469,7 +487,7 @@ public:
{
const AudioPortWithBusId& port(fPlugin.getAudioPort(false, i));
- // TODO find port group name
+ // TODO find port group name for sidechain buses
if (port.busId == busId)
{
strncpy_utf16(busName, port.name, 128);
@@ -558,6 +576,9 @@ public:
#if DISTRHO_PLUGIN_WANT_STATE
// TODO
#endif
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ // TODO
+#endif
if (const uint32_t paramCount = fPlugin.getParameterCount())
{
@@ -1027,14 +1048,27 @@ public:
int32_t getParameterCount() const noexcept
{
- return fPlugin.getParameterCount();
+ return fPlugin.getParameterCount() + fParameterOffset;
}
v3_result getParameterInfo(const int32_t index, v3_param_info* const info) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(index >= 0, V3_INVALID_ARG);
- const uint32_t uindex = static_cast<uint32_t>(index);
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ {
+ std::memset(info, 0, sizeof(v3_param_info));
+ info->param_id = index;
+ info->flags = V3_PARAM_CAN_AUTOMATE | V3_PARAM_IS_LIST | V3_PARAM_PROGRAM_CHANGE;
+ info->step_count = fProgramCountMinusOne;
+ strncpy_utf16(info->title, "Current Program", 128);
+ strncpy_utf16(info->short_title, "Program", 128);
+ return V3_OK;
+ }
+#endif
+
+ const uint32_t uindex = static_cast<uint32_t>(index) - fParameterOffset;
DISTRHO_SAFE_ASSERT_RETURN(uindex < fPlugin.getParameterCount(), V3_INVALID_ARG);
// set up flags
@@ -1082,15 +1116,35 @@ public:
v3_result getParameterStringForValue(const v3_param_id index, const double normalised, v3_str_128 output)
{
- DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
- snprintf_f32_utf16(output, fPlugin.getParameterRanges(index).getUnnormalizedValue(normalised), 128);
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(normalised >= 0.0 && normalised <= 1.0, V3_INVALID_ARG);
+
+ const uint32_t program = std::round(normalised * fProgramCountMinusOne);
+ strncpy_utf16(output, fPlugin.getProgramName(program), 128);
+ return V3_OK;
+ }
+#endif
+
+ const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
+ snprintf_f32_utf16(output, ranges.getUnnormalizedValue(normalised), 128);
return V3_OK;
}
v3_result getParameterValueForString(const v3_param_id index, int16_t*, double*)
{
- DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ {
+ // TODO find program index based on name
+ return V3_NOT_IMPLEMENTED;
+ }
+#endif
// TODO
return V3_NOT_IMPLEMENTED;
@@ -1098,29 +1152,57 @@ public:
double normalisedParameterToPlain(const v3_param_id index, const double normalised)
{
- DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ return std::round(normalised * fProgramCountMinusOne);
+#endif
- return fPlugin.getParameterRanges(index).getUnnormalizedValue(normalised);
+ const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
+ return ranges.getUnnormalizedValue(normalised);
};
double plainParameterToNormalised(const v3_param_id index, const double plain)
{
- DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ return std::max(0.0, std::min(1.0, plain / fProgramCountMinusOne));
+#endif
- return fPlugin.getParameterRanges(index).getNormalizedValue(plain);
+ const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
+ return ranges.getNormalizedValue(plain);
};
double getParameterNormalized(const v3_param_id index)
{
- DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), 0.0);
+ DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, 0.0);
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ return std::max(0.0, std::min(1.0, (double)fCurrentProgram / fProgramCountMinusOne));
+#endif
const float value = fPlugin.getParameterValue(index);
- return fPlugin.getParameterRanges(index).getNormalizedValue(value);
+ const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
+ return ranges.getNormalizedValue(value);
}
v3_result setParameterNormalized(const v3_param_id index, const double value)
{
- DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount(), V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT_RETURN(value >= 0.0 && value <= 1.0, V3_INVALID_ARG);
+
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ if (index == 0)
+ {
+ fCurrentProgram = std::round(value * fProgramCountMinusOne);
+ fPlugin.loadProgram(fCurrentProgram);
+ return V3_OK;
+ }
+#endif
const uint32_t hints = fPlugin.getParameterHints(index);
const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
@@ -1158,6 +1240,7 @@ private:
v3_component_handler** fComponentHandler;
// Temporary data
+ const uint32_t fParameterOffset;
float* fParameterValues;
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
MidiEvent fMidiEvents[kMaxMidiEvents];
@@ -1165,6 +1248,10 @@ private:
#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
v3_event_list** fHostEventOutputHandle;
#endif
+#if DISTRHO_PLUGIN_WANT_PROGRAMS
+ uint32_t fCurrentProgram;
+ const uint32_t fProgramCountMinusOne;
+#endif
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition;
#endif
@@ -2276,7 +2363,7 @@ struct dpf_factory : v3_plugin_factory_cpp {
info->class_flags = 0;
// DISTRHO_NAMESPACE::strncpy(info->sub_categories, "", sizeof(info->sub_categories)); // TODO
DISTRHO_NAMESPACE::strncpy(info->vendor, gPluginInfo.getMaker(), ARRAY_SIZE(info->vendor));
- DISTRHO_NAMESPACE::snprintf_u32(info->version, gPluginInfo.getVersion(), ARRAY_SIZE(info->version));
+ DISTRHO_NAMESPACE::snprintf_u32(info->version, gPluginInfo.getVersion(), ARRAY_SIZE(info->version)); // FIXME
DISTRHO_NAMESPACE::strncpy(info->sdk_version, "Travesty", ARRAY_SIZE(info->sdk_version)); // TESTING use "VST 3.7" ?
return V3_OK;
};
@@ -2297,7 +2384,7 @@ struct dpf_factory : v3_plugin_factory_cpp {
info->class_flags = 0;
// DISTRHO_NAMESPACE::strncpy(info->sub_categories, "", ARRAY_SIZE(info->sub_categories)); // TODO
DISTRHO_NAMESPACE::strncpy_utf16(info->vendor, gPluginInfo.getMaker(), sizeof(info->vendor));
- DISTRHO_NAMESPACE::snprintf_u32_utf16(info->version, gPluginInfo.getVersion(), ARRAY_SIZE(info->version));
+ DISTRHO_NAMESPACE::snprintf_u32_utf16(info->version, gPluginInfo.getVersion(), ARRAY_SIZE(info->version)); // FIXME
DISTRHO_NAMESPACE::strncpy_utf16(info->sdk_version, "Travesty", ARRAY_SIZE(info->sdk_version)); // TESTING use "VST 3.7" ?
return V3_OK;
};
diff --git a/distrho/src/DistrhoUIPrivateData.hpp b/distrho/src/DistrhoUIPrivateData.hpp
@@ -332,6 +332,11 @@ struct UI::PrivateData {
parameterOffset += 1;
# endif
#endif
+#ifdef DISTRHO_PLUGIN_TARGET_VST3
+# if DISTRHO_PLUGIN_WANT_PROGRAMS
+ parameterOffset += 1;
+# endif
+#endif
}
~PrivateData() noexcept
diff --git a/distrho/src/DistrhoUIVST3.cpp b/distrho/src/DistrhoUIVST3.cpp
@@ -42,12 +42,15 @@
#include "travesty/view.h"
/* TODO items:
- * - see how to handle external non-embed UI build
- * - program listener
- * - state listener and sender
+ * - disable UI if non-embed UI build
+ * - parameter change listener
+ * - parameter change sender
+ * - program change listener
+ * - program change sender
+ * - state change listener
+ * - state change sender
* - sample rate change listener
- * - call component handler restart with params-changed flag when setting program
- * - call component handler restart with latency-changed flag when latency changes
+ * - call component handler restart with params-changed flag when setting program?
*/
START_NAMESPACE_DISTRHO
diff --git a/distrho/src/travesty/base.h b/distrho/src/travesty/base.h
@@ -29,7 +29,7 @@ struct v3_funknown;
template<class T> static inline
constexpr T* v3_cpp_obj(T** obj)
{
- return (T*)((v3_funknown*)*obj + 1);
+ return (T*)((uint8_t*)*obj + sizeof(void*)*3);
}
#else
# ifndef constexpr