Browse Source

VST3: Implement UI->DSP parameter changes

Signed-off-by: falkTX <falktx@falktx.com>
pull/330/head
falkTX 4 years ago
parent
commit
4645f65e96
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 112 additions and 68 deletions
  1. +6
    -0
      distrho/src/DistrhoPluginInternal.hpp
  2. +40
    -35
      distrho/src/DistrhoPluginVST3.cpp
  3. +1
    -0
      distrho/src/DistrhoUIPrivateData.hpp
  4. +47
    -32
      distrho/src/DistrhoUIVST3.cpp
  5. +5
    -1
      distrho/src/travesty/base.h
  6. +13
    -0
      distrho/src/travesty/edit_controller.h

+ 6
- 0
distrho/src/DistrhoPluginInternal.hpp View File

@@ -170,6 +170,12 @@ struct Plugin::PrivateData {
# if (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || DISTRHO_PLUGIN_WANT_STATE)
parameterOffset += 1;
# endif
#endif

#ifdef DISTRHO_PLUGIN_TARGET_VST3
# if DISTRHO_PLUGIN_WANT_PROGRAMS
parameterOffset += 1;
# endif
#endif
}



+ 40
- 35
distrho/src/DistrhoPluginVST3.cpp View File

@@ -1048,15 +1048,15 @@ public:
return fPlugin.getParameterCount() + fParameterOffset;
}

v3_result getParameterInfo(const int32_t index, v3_param_info* const info) const noexcept
v3_result getParameterInfo(const int32_t rindex, v3_param_info* const info) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(index >= 0, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_RETURN(rindex >= 0, V3_INVALID_ARG);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
{
std::memset(info, 0, sizeof(v3_param_info));
info->param_id = index;
info->param_id = rindex;
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);
@@ -1065,8 +1065,8 @@ public:
}
#endif

const uint32_t uindex = static_cast<uint32_t>(index) - fParameterOffset;
DISTRHO_SAFE_ASSERT_RETURN(uindex < fPlugin.getParameterCount(), V3_INVALID_ARG);
const uint32_t index = static_cast<uint32_t>(rindex) - fParameterOffset;
DISTRHO_SAFE_ASSERT_UINT_RETURN(index < fPlugin.getParameterCount(), index, V3_INVALID_ARG);

// set up flags
int32_t flags = 0;
@@ -1100,7 +1100,7 @@ public:
step_count = ranges.max - ranges.min - 1;

std::memset(info, 0, sizeof(v3_param_info));
info->param_id = index;
info->param_id = rindex;
info->flags = flags;
info->step_count = step_count;
info->default_normalised_value = ranges.getNormalizedValue(ranges.def);
@@ -1111,12 +1111,12 @@ public:
return V3_OK;
}

v3_result getParameterStringForValue(const v3_param_id index, const double normalised, v3_str_128 output)
v3_result getParameterStringForValue(const v3_param_id rindex, const double normalised, v3_str_128 output)
{
DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fPlugin.getParameterCount() + fParameterOffset, rindex, V3_INVALID_ARG);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
{
DISTRHO_SAFE_ASSERT_RETURN(normalised >= 0.0 && normalised <= 1.0, V3_INVALID_ARG);

@@ -1126,17 +1126,17 @@ public:
}
#endif

const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
const ParameterRanges& ranges(fPlugin.getParameterRanges(rindex - fParameterOffset));
snprintf_f32_utf16(output, ranges.getUnnormalizedValue(normalised), 128);
return V3_OK;
}

v3_result getParameterValueForString(const v3_param_id index, int16_t*, double*)
v3_result getParameterValueForString(const v3_param_id rindex, int16_t*, double*)
{
DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fPlugin.getParameterCount() + fParameterOffset, rindex, V3_INVALID_ARG);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
{
// TODO find program index based on name
return V3_NOT_IMPLEMENTED;
@@ -1147,53 +1147,53 @@ public:
return V3_NOT_IMPLEMENTED;
};

double normalisedParameterToPlain(const v3_param_id index, const double normalised)
double normalisedParameterToPlain(const v3_param_id rindex, const double normalised)
{
DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fPlugin.getParameterCount() + fParameterOffset, rindex, 0.0);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
return std::round(normalised * fProgramCountMinusOne);
#endif

const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
const ParameterRanges& ranges(fPlugin.getParameterRanges(rindex - fParameterOffset));
return ranges.getUnnormalizedValue(normalised);
};

double plainParameterToNormalised(const v3_param_id index, const double plain)
double plainParameterToNormalised(const v3_param_id rindex, const double plain)
{
DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fPlugin.getParameterCount() + fParameterOffset, rindex, 0.0);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
return std::max(0.0, std::min(1.0, plain / fProgramCountMinusOne));
#endif

const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
const ParameterRanges& ranges(fPlugin.getParameterRanges(rindex - fParameterOffset));
return ranges.getNormalizedValue(plain);
};

double getParameterNormalized(const v3_param_id index)
double getParameterNormalized(const v3_param_id rindex)
{
DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, 0.0);
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fPlugin.getParameterCount() + fParameterOffset, rindex, 0.0);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
return std::max(0.0, std::min(1.0, (double)fCurrentProgram / fProgramCountMinusOne));
#endif

const float value = fPlugin.getParameterValue(index);
const ParameterRanges& ranges(fPlugin.getParameterRanges(index - fParameterOffset));
const float value = fPlugin.getParameterValue(rindex - fParameterOffset);
const ParameterRanges& ranges(fPlugin.getParameterRanges(rindex - fParameterOffset));
return ranges.getNormalizedValue(value);
}

v3_result setParameterNormalized(const v3_param_id index, const double value)
v3_result setParameterNormalized(const v3_param_id rindex, const double value)
{
DISTRHO_SAFE_ASSERT_RETURN(index < fPlugin.getParameterCount() + fParameterOffset, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fPlugin.getParameterCount() + fParameterOffset, rindex, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_RETURN(value >= 0.0 && value <= 1.0, V3_INVALID_ARG);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (index == 0)
if (rindex == 0)
{
fCurrentProgram = std::round(value * fProgramCountMinusOne);
fPlugin.loadProgram(fCurrentProgram);
@@ -1201,6 +1201,7 @@ public:
}
#endif

const uint32_t index = rindex - fParameterOffset;
const uint32_t hints = fPlugin.getParameterHints(index);
const ParameterRanges& ranges(fPlugin.getParameterRanges(index));

@@ -1378,7 +1379,8 @@ private:
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (called from DSP side)

v3_funknown** dpf_plugin_view_create(void* instancePointer, double sampleRate);
v3_funknown** dpf_plugin_view_create(v3_edit_controller** controller, v3_component_handler** handler,
void* instancePointer, double sampleRate);
#endif

// --------------------------------------------------------------------------------------------------------------------
@@ -1570,7 +1572,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {

controller.plain_parameter_to_normalised = []V3_API(void* self, v3_param_id index, double plain) -> double
{
d_stdout("dpf_edit_controller::plain_parameter_to_normalised => %p %f", self, plain);
d_stdout("dpf_edit_controller::plain_parameter_to_normalised => %p %u %f", self, index, plain);
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, V3_NOT_INITIALISED);

@@ -1583,7 +1585,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
controller.get_parameter_normalised = []V3_API(void* self, v3_param_id index) -> double
{
// NOTE very noisy, called many times
// d_stdout("dpf_edit_controller::get_parameter_normalised => %p", self);
// d_stdout("dpf_edit_controller::get_parameter_normalised => %p %u", self, index);
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, 0.0);

@@ -1595,7 +1597,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {

controller.set_parameter_normalised = []V3_API(void* self, v3_param_id index, double normalised) -> v3_result
{
d_stdout("dpf_edit_controller::set_parameter_normalised => %p %f", self, normalised);
d_stdout("dpf_edit_controller::set_parameter_normalised => %p %u %f", self, index, normalised);
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, V3_NOT_INITIALISED);

@@ -1637,7 +1639,10 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, nullptr);

#if DISTRHO_PLUGIN_HAS_UI
return (v3_plugin_view**)dpf_plugin_view_create(vst3->getInstancePointer(), vst3->getSampleRate());
return (v3_plugin_view**)dpf_plugin_view_create((v3_edit_controller**)self,
controller->handler,
vst3->getInstancePointer(),
vst3->getSampleRate());
#else
return nullptr;
#endif


+ 1
- 0
distrho/src/DistrhoUIPrivateData.hpp View File

@@ -332,6 +332,7 @@ struct UI::PrivateData {
parameterOffset += 1;
# endif
#endif

#ifdef DISTRHO_PLUGIN_TARGET_VST3
# if DISTRHO_PLUGIN_WANT_PROGRAMS
parameterOffset += 1;


+ 47
- 32
distrho/src/DistrhoUIVST3.cpp View File

@@ -74,8 +74,13 @@ const char* tuid2str(const v3_tuid iid);
class UIVst3 : public Thread
{
public:
UIVst3(const intptr_t winId, const float scaleFactor, const double sampleRate,
void* const instancePointer, v3_plugin_view** const view)
UIVst3(v3_plugin_view** const view,
v3_edit_controller** const controller,
v3_component_handler** const handler,
const intptr_t winId,
const float scaleFactor,
const double sampleRate,
void* const instancePointer)
: fUI(this, winId, sampleRate,
editParameterCallback,
setParameterCallback,
@@ -87,6 +92,8 @@ public:
instancePointer,
scaleFactor),
fView(view),
fController(controller),
fHandler(handler),
fFrame(nullptr),
fScaleFactor(scaleFactor)
{
@@ -196,41 +203,35 @@ private:

// VST3 stuff
v3_plugin_view** const fView;
v3_edit_controller** const fController;
v3_component_handler** const fHandler;
v3_plugin_frame** fFrame;
// v3_component_handler_cpp** handler = nullptr;

// Temporary data
float fScaleFactor;

void editParameter(const uint32_t /*index*/, const bool /*started*/) const
void editParameter(const uint32_t rindex, const bool started) const
{
// DISTRHO_SAFE_ASSERT_RETURN(handler != nullptr,);
//
// v3_component_handler_cpp* const chandler = *handler;
// DISTRHO_SAFE_ASSERT_RETURN(chandler != nullptr,);
//
// if (started)
// chandler->handler.begin_edit(handler, index);
// else
// chandler->handler.end_edit(handler, index);
DISTRHO_SAFE_ASSERT_RETURN(fHandler != nullptr,);

if (started)
v3_cpp_obj(fHandler)->begin_edit(fHandler, rindex);
else
v3_cpp_obj(fHandler)->end_edit(fHandler, rindex);
}

static void editParameterCallback(void* ptr, uint32_t index, bool started)
static void editParameterCallback(void* ptr, uint32_t rindex, bool started)
{
((UIVst3*)ptr)->editParameter(index, started);
((UIVst3*)ptr)->editParameter(rindex, started);
}

void setParameterValue(const uint32_t /*index*/, const float /*realValue*/)
void setParameterValue(const uint32_t rindex, const float realValue)
{
// DISTRHO_SAFE_ASSERT_RETURN(handler != nullptr,);
//
// v3_component_handler_cpp* const chandler = *handler;
// DISTRHO_SAFE_ASSERT_RETURN(chandler != nullptr,);

// const double value = vst3->plainParameterToNormalised(index, realValue);
// chandler->handler.perform_edit(handler, index, value);
DISTRHO_SAFE_ASSERT_RETURN(fController != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fHandler != nullptr,);

// TODO send change to DSP side?
const double value = v3_cpp_obj(fController)->plain_parameter_to_normalised(fController, rindex, realValue);
v3_cpp_obj(fHandler)->perform_edit(fHandler, rindex, value);
}

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
@@ -370,14 +371,22 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
ScopedPointer<dpf_plugin_view_scale> scale;
ScopedPointer<UIVst3> uivst3;
// cached values
v3_edit_controller** const controller;
v3_component_handler** const handler;
void* const instancePointer;
double sampleRate;
// v3_component_handler_cpp** handler = nullptr;
v3_plugin_frame** frame = nullptr;

dpf_plugin_view(ScopedPointer<dpf_plugin_view>* s, void* const instance, const double sr)
dpf_plugin_view(ScopedPointer<dpf_plugin_view>* selfptr,
v3_edit_controller** const controllerptr,
v3_component_handler** const handlerptr,
void* const instance,
const double sr)
: refcounter(1),
self(s),
self(selfptr),
controller(controllerptr),
handler(handlerptr),
instancePointer(instance),
sampleRate(sr)
{
@@ -481,10 +490,14 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0)
{
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f;
view->uivst3 = new UIVst3((uintptr_t)parent, scaleFactor, view->sampleRate,
view->instancePointer, (v3_plugin_view**)self);
view->uivst3 = new UIVst3((v3_plugin_view**)self,
view->controller,
view->handler,
(uintptr_t)parent,
scaleFactor,
view->sampleRate,
view->instancePointer);
view->uivst3->setFrame(view->frame);
// view->uivst3->setHandler(view->handler);
return V3_OK;
}
}
@@ -623,12 +636,14 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (called from plugin side)

v3_funknown** dpf_plugin_view_create(void* instancePointer, double sampleRate);
v3_funknown** dpf_plugin_view_create(v3_edit_controller** controller, v3_component_handler** handler,
void* instancePointer, double sampleRate);

v3_funknown** dpf_plugin_view_create(void* const instancePointer, const double sampleRate)
v3_funknown** dpf_plugin_view_create(v3_edit_controller** const controller, v3_component_handler** const handler,
void* const instancePointer, const double sampleRate)
{
ScopedPointer<dpf_plugin_view>* const viewptr = new ScopedPointer<dpf_plugin_view>;
*viewptr = new dpf_plugin_view(viewptr, instancePointer, sampleRate);
*viewptr = new dpf_plugin_view(viewptr, controller, handler, instancePointer, sampleRate);
return (v3_funknown**)viewptr;
}



+ 5
- 1
distrho/src/travesty/base.h View File

@@ -28,7 +28,11 @@
template<class T> static inline
constexpr T* v3_cpp_obj(T** obj)
{
return (T*)((uint8_t*)*obj + sizeof(void*)*3);
/**
* this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default,
* but we need everything to be `static_cast` for it to be `constexpr` compatible.
*/
return static_cast<T*>(static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*3));
}
#else
# ifndef constexpr


+ 13
- 0
distrho/src/travesty/edit_controller.h View File

@@ -84,4 +84,17 @@ struct v3_edit_controller {
static constexpr const v3_tuid v3_edit_controller_iid =
V3_ID(0xDCD7BBE3, 0x7742448D, 0xA874AACC, 0x979C759E);

#ifdef __cplusplus
template<> inline
constexpr v3_edit_controller* v3_cpp_obj(v3_edit_controller** obj)
{
/**
* this ugly piece of code is required due to C++ assuming `reinterpret_cast` by default,
* but we need everything to be `static_cast` for it to be `constexpr` compatible.
*/
return static_cast<v3_edit_controller*>(
static_cast<void*>(static_cast<uint8_t*>(static_cast<void*>(*obj)) + sizeof(void*)*5));
}
#endif

#include "align_pop.h"

Loading…
Cancel
Save