commit 4c59baa3140863353827038b1e5966d7c1166880
parent 8e25227168fb528aaedf84efb0e875f9c248fbe8
Author: falkTX <falktx@falktx.com>
Date: Sun, 26 Sep 2021 15:35:44 +0100
Experiments with VST3 full data passing
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
4 files changed, 449 insertions(+), 136 deletions(-)
diff --git a/distrho/src/DistrhoPluginVST3.cpp b/distrho/src/DistrhoPluginVST3.cpp
@@ -257,6 +257,11 @@ static constexpr void (*const snprintf_f32_utf16)(int16_t*, float, size_t) = snp
static constexpr void (*const snprintf_u32_utf16)(int16_t*, uint32_t, size_t) = snprintf_utf16_t<uint32_t, format_u32>;
// --------------------------------------------------------------------------------------------------------------------
+// TESTING
+
+v3_message** dpf_message_create(const char* id);
+
+// --------------------------------------------------------------------------------------------------------------------
/**
* VST3 DSP class.
@@ -287,6 +292,7 @@ public:
PluginVst3()
: fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback),
fComponentHandler(nullptr),
+ fConnectionToUI(nullptr),
fParameterOffset(fPlugin.getParameterOffset()),
fRealParameterCount(fParameterOffset + fPlugin.getParameterCount()),
fParameterValues(nullptr)
@@ -394,6 +400,11 @@ public:
return fPlugin.getSampleRate();
}
+ void setConnectionToUI(v3_connection_point** const point) noexcept
+ {
+ fConnectionToUI = point;
+ }
+
// ----------------------------------------------------------------------------------------------------------------
// v3_component interface calls
@@ -1257,6 +1268,9 @@ public:
DISTRHO_SAFE_ASSERT_UINT_RETURN(rindex < fRealParameterCount, rindex, V3_INVALID_ARG);
DISTRHO_SAFE_ASSERT_RETURN(value >= 0.0 && value <= 1.0, V3_INVALID_ARG);
+ // TESTING remove this
+ sendParameterChangeTest(rindex, value);
+
#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (rindex == 0)
{
@@ -1294,7 +1308,21 @@ public:
}
// ----------------------------------------------------------------------------------------------------------------
- // dpf_connection_point
+ // dpf_dsp_connection_point
+
+ void connect(v3_connection_point** const other)
+ {
+ fConnectionToUI = other;
+
+ d_stdout("---------------------------------------------------------- will send plugin state now");
+ }
+
+ void disconnect()
+ {
+ fConnectionToUI = nullptr;
+
+ d_stdout("---------------------------------------------------------- ui conn now null");
+ }
v3_result notify(v3_message** const message)
{
@@ -1399,6 +1427,7 @@ private:
// VST3 stuff
v3_component_handler** fComponentHandler;
+ v3_connection_point** fConnectionToUI;
// Temporary data
const uint32_t fParameterOffset;
@@ -1422,7 +1451,7 @@ private:
#endif
// ----------------------------------------------------------------------------------------------------------------
- // functions called from the plugin side, RT no block
+ // helper functions called during process, cannot block
void updateParameterOutputsAndTriggers()
{
@@ -1460,6 +1489,28 @@ private:
}
// ----------------------------------------------------------------------------------------------------------------
+ // helper functions called during message passing, can block
+
+ void sendParameterChangeTest(const v3_param_id rindex, const double value)
+ {
+ d_stdout("will send message now");
+ DISTRHO_SAFE_ASSERT_RETURN(fConnectionToUI != nullptr,);
+
+ v3_message** const message = dpf_message_create("parameter-set");
+ DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,);
+
+ v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,);
+
+ v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 2);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "rindex", rindex);
+ v3_cpp_obj(attrlist)->set_float(attrlist, "value", value);
+ v3_cpp_obj(fConnectionToUI)->notify(fConnectionToUI, message);
+
+ v3_cpp_obj_unref(message);
+ }
+
+ // ----------------------------------------------------------------------------------------------------------------
// DPF callbacks
bool requestParameterValueChange(const uint32_t index, const float value)
@@ -1554,25 +1605,33 @@ private:
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (called from DSP side)
-v3_funknown** dpf_plugin_view_create(v3_connection_point** connection, void* instancePointer, double sampleRate);
+v3_plugin_view** dpf_plugin_view_create(void* instancePointer, double sampleRate);
#endif
// --------------------------------------------------------------------------------------------------------------------
-// dpf_connection_point
+// dpf_dsp_connection_point
+
+enum ConnectionPointType {
+ kConnectionPointComponent,
+ kConnectionControllerToComponent,
+ kConnectionControllerToView
+};
struct v3_connection_point_cpp : v3_funknown {
v3_connection_point point;
};
-struct dpf_connection_point : v3_connection_point_cpp {
+struct dpf_dsp_connection_point : v3_connection_point_cpp {
ScopedPointer<PluginVst3>& vst3;
- const bool controller; // component otherwise
- bool connected;
+ const ConnectionPointType type;
+ v3_connection_point** other;
+ v3_connection_point** bridge; // when type is controller this points to ctrl<->view point
- dpf_connection_point(const bool isEditCtrl, ScopedPointer<PluginVst3>& v)
+ dpf_dsp_connection_point(const ConnectionPointType t, ScopedPointer<PluginVst3>& v)
: vst3(v),
- controller(isEditCtrl),
- connected(false)
+ type(t),
+ other(nullptr),
+ bridge(nullptr)
{
static const uint8_t* kSupportedInterfaces[] = {
v3_funknown_iid,
@@ -1584,7 +1643,7 @@ struct dpf_connection_point : v3_connection_point_cpp {
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result
{
- d_stdout("dpf_connection_point::query_interface => %p %s %p", self, tuid2str(iid), iface);
+ d_stdout("dpf_dsp_connection_point::query_interface => %p %s %p", self, tuid2str(iid), iface);
*iface = NULL;
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE);
@@ -1609,40 +1668,121 @@ struct dpf_connection_point : v3_connection_point_cpp {
point.connect = []V3_API(void* self, struct v3_connection_point** other) -> v3_result
{
- d_stdout("dpf_connection_point::connect => %p %p", self, other);
- dpf_connection_point* const point = *(dpf_connection_point**)self;
+ d_stdout("dpf_dsp_connection_point::connect => %p %p", self, other);
+ dpf_dsp_connection_point* const point = *(dpf_dsp_connection_point**)self;
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);
+ DISTRHO_SAFE_ASSERT_RETURN(point->other == nullptr, V3_INVALID_ARG);
+ DISTRHO_SAFE_ASSERT(point->bridge == nullptr);
+
+ point->other = other;
- const bool connected = point->connected;
- DISTRHO_SAFE_ASSERT_RETURN(! connected, V3_INVALID_ARG);
+ if (point->type == kConnectionPointComponent)
+ if (PluginVst3* const vst3 = point->vst3)
+ vst3->connect((v3_connection_point**)self);
- point->connected = true;
return V3_OK;
};
point.disconnect = []V3_API(void* self, struct v3_connection_point** other) -> v3_result
{
- d_stdout("dpf_connection_point::disconnect => %p %p", self, other);
- dpf_connection_point* const point = *(dpf_connection_point**)self;
+ d_stdout("dpf_dsp_connection_point::disconnect => %p %p", self, other);
+ dpf_dsp_connection_point* const point = *(dpf_dsp_connection_point**)self;
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);
+ DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG);
+
+ point->other = nullptr;
+ point->bridge = nullptr;
- const bool connected = point->connected;
- DISTRHO_SAFE_ASSERT_RETURN(connected, V3_INVALID_ARG);
+ if (point->type == kConnectionPointComponent)
+ if (PluginVst3* const vst3 = point->vst3)
+ vst3->disconnect();
- point->connected = false;
return V3_OK;
};
point.notify = []V3_API(void* self, struct v3_message** message) -> v3_result
{
- d_stdout("dpf_connection_point::notify => %p %p", self, message);
- dpf_connection_point* const point = *(dpf_connection_point**)self;
+ d_stdout("dpf_dsp_connection_point::notify => %p %p", self, message);
+ dpf_dsp_connection_point* const point = *(dpf_dsp_connection_point**)self;
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);
PluginVst3* const vst3 = point->vst3;
DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALISED);
- return vst3->notify(message);
+ v3_connection_point** const other = point->other;
+ DISTRHO_SAFE_ASSERT_RETURN(other != nullptr, V3_NOT_INITIALISED);
+
+ v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr, V3_INVALID_ARG);
+
+ int64_t target = 0;
+ const v3_result res = v3_cpp_obj(attrlist)->get_int(attrlist, "__dpf_msg_target__", &target);
+ DISTRHO_SAFE_ASSERT_RETURN(res == V3_OK, res);
+ DISTRHO_SAFE_ASSERT_RETURN(target != 0, V3_INTERNAL_ERR);
+
+ switch (point->type)
+ {
+ // pass message from component (aka plugin) to controller
+ case kConnectionPointComponent:
+ {
+ d_stdout("dpf_dsp_connection_point::notify kConnectionPointComponent");
+
+ switch (target)
+ {
+ case 1:
+ // message is from view to controller to component
+ return vst3->notify(message);
+ case 2:
+ // message is from component to controller to view
+ return v3_cpp_obj(other)->notify(other, message);
+ }
+ break;
+ }
+
+ // pass message from controller to component (aka plugin)
+ case kConnectionControllerToComponent:
+ {
+ d_stdout("dpf_dsp_connection_point::notify kConnectionControllerToComponent");
+
+ switch (target)
+ {
+ case 1:
+ // message is from view to controller to component
+ return v3_cpp_obj(other)->notify(other, message);
+ case 2:
+ {
+ // message is from component to controller to view
+ v3_connection_point** const bridge = point->bridge;
+ DISTRHO_SAFE_ASSERT_RETURN(bridge != nullptr, V3_NOT_INITIALISED);
+ return v3_cpp_obj(bridge)->notify(bridge, message);
+ }
+ }
+ break;
+ }
+
+ // pass message from from view (aka ui) to controller
+ case kConnectionControllerToView:
+ {
+ d_stdout("dpf_dsp_connection_point::notify kConnectionControllerToView");
+
+ switch (target)
+ {
+ case 1:
+ {
+ // message is from view to controller to component
+ v3_connection_point** const bridge = point->bridge;
+ DISTRHO_SAFE_ASSERT_RETURN(bridge != nullptr, V3_NOT_INITIALISED);
+ return v3_cpp_obj(bridge)->notify(bridge, message);
+ }
+ case 2:
+ // message is from component to controller to view
+ return v3_cpp_obj(other)->notify(other, message);
+ }
+ break;
+ }
+ }
+
+ return V3_INTERNAL_ERR;
};
}
};
@@ -1656,15 +1796,18 @@ struct v3_edit_controller_cpp : v3_funknown {
};
struct dpf_edit_controller : v3_edit_controller_cpp {
- ScopedPointer<dpf_connection_point> connection;
+ ScopedPointer<dpf_dsp_connection_point> connectionComp; // kConnectionControllerToComponent
+ ScopedPointer<dpf_dsp_connection_point> connectionView; // kConnectionControllerToView
ScopedPointer<PluginVst3>& vst3;
bool initialized;
// cached values
+ v3_connection_point** connectionToUI;
v3_component_handler** handler;
dpf_edit_controller(ScopedPointer<PluginVst3>& v)
: vst3(v),
initialized(false),
+ connectionToUI(nullptr),
handler(nullptr)
{
static const uint8_t* kSupportedInterfacesBase[] = {
@@ -1695,9 +1838,10 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
if (v3_tuid_match(v3_connection_point_iid, iid))
{
- if (controller->connection == nullptr)
- controller->connection = new dpf_connection_point(true, controller->vst3);
- *iface = &controller->connection;
+ if (controller->connectionComp == nullptr)
+ controller->connectionComp = new dpf_dsp_connection_point(kConnectionControllerToComponent,
+ controller->vst3);
+ *iface = &controller->connectionComp;
return V3_OK;
}
@@ -1734,6 +1878,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
DISTRHO_SAFE_ASSERT_RETURN(initialized, V3_INVALID_ARG);
controller->initialized = false;
+ controller->connectionToUI = nullptr;
return V3_OK;
};
@@ -1880,14 +2025,6 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
PluginVst3* const vst3 = controller->vst3;
DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, V3_NOT_INITIALISED);
-// if (dpf_plugin_view* const view = controller->view)
-// {
-// if (UIVst3* const uivst3 = view->uivst3)
-// {
-// uivst3->setParameterValueFromDSP(index, vst3->normalisedParameterToPlain(index, normalised));
-// }
-// }
-
return vst3->setParameterNormalized(index, normalised);
};
@@ -1911,39 +2048,37 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, nullptr);
-#if DISTRHO_PLUGIN_HAS_UI
- // if there is no connection yet we can still manage ourselves, but only if component is initialized
- DISTRHO_SAFE_ASSERT_RETURN((controller->connection != nullptr && controller->connection->connected) ||
- controller->vst3 != nullptr, nullptr);
+ PluginVst3* const vst3 = controller->vst3;
+ DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, nullptr);
- if (controller->connection != nullptr)
- {
- // if there is a connection point, it needs to be connected
- DISTRHO_SAFE_ASSERT_RETURN(controller->connection->connected, nullptr);
- }
- else
- {
- // no connection point, let's do it ourselves (assume local usage)
- controller->connection = new dpf_connection_point(true, controller->vst3);
- controller->connection->connected = true;
- }
+#if 1 // DISTRHO_PLUGIN_HAS_UI
+ // we require a component connection
+ DISTRHO_SAFE_ASSERT_RETURN(controller->connectionComp != nullptr, nullptr);
+ DISTRHO_SAFE_ASSERT_RETURN(controller->connectionComp->other != nullptr, nullptr);
- void* instancePointer;
- double sampleRate;
+ v3_plugin_view** const view = dpf_plugin_view_create(vst3->getInstancePointer(),
+ vst3->getSampleRate());
+ DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, nullptr);
- if (PluginVst3* const vst3 = controller->vst3)
- {
- instancePointer = vst3->getInstancePointer();
- sampleRate = vst3->getSampleRate();
- }
- else
+ v3_connection_point** connection = nullptr;
+ if (v3_cpp_obj_query_interface(view, v3_connection_point_iid, &connection) == V3_OK)
{
- instancePointer = nullptr;
- sampleRate = 44100.0;
+ d_stdout("view connection query ok %p", connection);
+
+ v3_connection_point** const bridge = (v3_connection_point**)&controller->connectionComp;
+ controller->connectionView = new dpf_dsp_connection_point(kConnectionControllerToView,
+ controller->vst3);
+
+ v3_connection_point** const other = (v3_connection_point**)&controller->connectionView;
+ v3_cpp_obj(connection)->connect(connection, other);
+ v3_cpp_obj(other)->connect(other, connection);
+
+ controller->connectionComp->bridge = other;
+ controller->connectionView->bridge = bridge;
+
}
- return (v3_plugin_view**)dpf_plugin_view_create((v3_connection_point**)&controller->connection,
- instancePointer, sampleRate);
+ return view;
#else
return nullptr;
#endif
@@ -2275,7 +2410,7 @@ struct dpf_component : v3_component_cpp {
std::atomic<int> refcounter;
ScopedPointer<dpf_component>* self;
ScopedPointer<dpf_audio_processor> processor;
- ScopedPointer<dpf_connection_point> connection;
+ ScopedPointer<dpf_dsp_connection_point> connection; // kConnectionPointComponent
ScopedPointer<dpf_edit_controller> controller;
// ScopedPointer<dpf_state_stream> stream;
ScopedPointer<PluginVst3> vst3;
@@ -2321,7 +2456,8 @@ struct dpf_component : v3_component_cpp {
if (v3_tuid_match(v3_connection_point_iid, iid))
{
if (component->connection == nullptr)
- component->connection = new dpf_connection_point(false, component->vst3);
+ component->connection = new dpf_dsp_connection_point(kConnectionPointComponent,
+ component->vst3);
*iface = &component->connection;
return V3_OK;
}
diff --git a/distrho/src/DistrhoUIVST3.cpp b/distrho/src/DistrhoUIVST3.cpp
@@ -49,11 +49,9 @@
/* TODO items:
* - 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?
*/
@@ -78,12 +76,13 @@ void strncpy_utf16(int16_t* dst, const char* src, size_t length);
// --------------------------------------------------------------------------------------------------------------------
// create message object (needed by the UI class, implementation comes later)
-static v3_message** dpf_message_create(const char* id);
+v3_message** dpf_message_create(const char* id);
// --------------------------------------------------------------------------------------------------------------------
// custom attribute list struct, used for sending utf8 strings
struct v3_attribute_list_utf8 {
+ struct v3_funknown;
V3_API v3_result (*set_string_utf8)(void* self, const char* id, const char* string);
V3_API v3_result (*get_string_utf8)(void* self, const char* id, char* string, uint32_t size);
};
@@ -112,7 +111,6 @@ class UIVst3 : public Thread
{
public:
UIVst3(v3_plugin_view** const view,
- v3_connection_point** const connection,
const intptr_t winId,
const float scaleFactor,
const double sampleRate,
@@ -128,7 +126,7 @@ public:
instancePointer,
scaleFactor),
fView(view),
- fConnection(connection),
+ fConnection(nullptr),
fFrame(nullptr),
fScaleFactor(scaleFactor)
{
@@ -231,6 +229,53 @@ public:
}
// ----------------------------------------------------------------------------------------------------------------
+ // dpf_ui_connection_point
+
+ void connect(v3_connection_point** const point) noexcept
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(point != nullptr,);
+
+ fConnection = point;
+ }
+
+ void disconnect() noexcept
+ {
+ fConnection = nullptr;
+ }
+
+ v3_result notify(v3_message** const message)
+ {
+ const char* const msgid = v3_cpp_obj(message)->get_message_id(message);
+ DISTRHO_SAFE_ASSERT_RETURN(msgid != nullptr, V3_INVALID_ARG);
+
+ v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr, V3_INVALID_ARG);
+
+ if (std::strcmp(msgid, "parameter-set") == 0)
+ {
+ int64_t rindex;
+ double value;
+ v3_result res;
+
+ res = v3_cpp_obj(attrs)->get_int(attrs, "rindex", &rindex);
+ DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res);
+
+ res = v3_cpp_obj(attrs)->get_float(attrs, "value", &value);
+ DISTRHO_SAFE_ASSERT_INT_RETURN(res == V3_OK, res, res);
+
+ rindex -= fUI.getParameterOffset();
+ DISTRHO_SAFE_ASSERT_RETURN(rindex >= 0, V3_INTERNAL_ERR);
+
+ fUI.parameterChanged(rindex, value);
+ return V3_OK;
+ }
+
+ d_stdout("UIVst3 received unknown msg '%s'", msgid);
+
+ return V3_NOT_IMPLEMENTED;
+ }
+
+ // ----------------------------------------------------------------------------------------------------------------
private:
// Plugin UI
@@ -238,7 +283,7 @@ private:
// VST3 stuff
v3_plugin_view** const fView;
- v3_connection_point** const fConnection;
+ v3_connection_point** fConnection;
v3_plugin_frame** fFrame;
// Temporary data
@@ -254,11 +299,12 @@ private:
v3_message** const message = dpf_message_create("parameter-edit");
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,);
- v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message);
- DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr,);
+ v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,);
- v3_cpp_obj(attrs)->set_int(attrs, "rindex", rindex);
- v3_cpp_obj(attrs)->set_int(attrs, "started", started ? 1 : 0);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "rindex", rindex);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "started", started ? 1 : 0);
v3_cpp_obj(fConnection)->notify(fConnection, message);
v3_cpp_obj_unref(message);
@@ -276,11 +322,12 @@ private:
v3_message** const message = dpf_message_create("parameter-set");
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,);
- v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message);
- DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr,);
+ v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,);
- v3_cpp_obj(attrs)->set_int(attrs, "rindex", rindex);
- v3_cpp_obj(attrs)->set_float(attrs, "value", realValue);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "rindex", rindex);
+ v3_cpp_obj(attrlist)->set_float(attrlist, "value", realValue);
v3_cpp_obj(fConnection)->notify(fConnection, message);
v3_cpp_obj_unref(message);
@@ -323,15 +370,16 @@ private:
v3_message** const message = dpf_message_create("midi");
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,);
- v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message);
- DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr,);
+ v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,);
uint8_t midiData[3];
midiData[0] = (velocity != 0 ? 0x90 : 0x80) | channel;
midiData[1] = note;
midiData[2] = velocity;
- v3_cpp_obj(attrs)->set_binary(attrs, "data", midiData, sizeof(midiData));
+ v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1);
+ v3_cpp_obj(attrlist)->set_binary(attrlist, "data", midiData, sizeof(midiData));
v3_cpp_obj(fConnection)->notify(fConnection, message);
v3_cpp_obj_unref(message);
@@ -351,15 +399,16 @@ private:
v3_message** const message = dpf_message_create("state-set");
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,);
- v3_attribute_list** const attrs = v3_cpp_obj(message)->get_attributes(message);
- DISTRHO_SAFE_ASSERT_RETURN(attrs != nullptr,);
+ v3_attribute_list** const attrlist = v3_cpp_obj(message)->get_attributes(message);
+ DISTRHO_SAFE_ASSERT_RETURN(attrlist != nullptr,);
- v3_attribute_list_utf8** utf8attrs = nullptr;
- DISTRHO_SAFE_ASSERT_RETURN(v3_cpp_obj_query_interface(attrs, v3_attribute_list_utf8_iid, &utf8attrs) == V3_OK,);
- DISTRHO_SAFE_ASSERT_RETURN(utf8attrs != nullptr,);
+ v3_attribute_list_utf8** utf8attrlist = nullptr;
+ DISTRHO_SAFE_ASSERT_RETURN(v3_cpp_obj_query_interface(attrlist, v3_attribute_list_utf8_iid, &utf8attrs) == V3_OK,);
+ DISTRHO_SAFE_ASSERT_RETURN(utf8attrlist != nullptr,);
- v3_cpp_obj(utf8attrs)->set_string_utf8(utf8attrs, "key", key);
- v3_cpp_obj(utf8attrs)->set_string_utf8(utf8attrs, "value", value);
+ v3_cpp_obj(attrlist)->set_int(attrlist, "__dpf_msg_target__", 1);
+ v3_cpp_obj(utf8attrlist)->set_string_utf8(utf8attrlist, "key", key);
+ v3_cpp_obj(utf8attrlist)->set_string_utf8(utf8attrlist, "value", value);
v3_cpp_obj(fConnection)->notify(fConnection, message);
v3_cpp_obj_unref(message);
@@ -410,16 +459,16 @@ static void dpf_attribute_list_free(std::map<std::string, dpf_attribute_value>&
}
// --------------------------------------------------------------------------------------------------------------------
-// dpf_attribute_list_dpf (the custom utf8 variant)
+// dpf_attribute_list_utf8 (the custom variant)
struct v3_attribute_list_utf8_cpp : v3_funknown {
v3_attribute_list_utf8 attr;
};
-struct dpf_attribute_list_dpf : v3_attribute_list_utf8_cpp {
+struct dpf_attribute_list_utf8 : v3_attribute_list_utf8_cpp {
std::map<std::string, dpf_attribute_value>& attrs;
- dpf_attribute_list_dpf(std::map<std::string, dpf_attribute_value>& a)
+ dpf_attribute_list_utf8(std::map<std::string, dpf_attribute_value>& a)
: attrs(a)
{
static const uint8_t* kSupportedInterfaces[] = {
@@ -432,7 +481,7 @@ struct dpf_attribute_list_dpf : v3_attribute_list_utf8_cpp {
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result
{
- d_stdout("dpf_attribute_list_dpf::query_interface => %p %s %p", self, tuid2str(iid), iface);
+ d_stdout("dpf_attribute_list_utf8::query_interface => %p %s %p", self, tuid2str(iid), iface);
*iface = NULL;
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE);
@@ -457,7 +506,7 @@ struct dpf_attribute_list_dpf : v3_attribute_list_utf8_cpp {
attr.set_string_utf8 = []V3_API(void* self, const char* id, const char* string) -> v3_result
{
- dpf_attribute_list_dpf* const attr = *(dpf_attribute_list_dpf**)self;
+ dpf_attribute_list_utf8* const attr = *(dpf_attribute_list_utf8**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
const uint32_t size = std::strlen(string) + 1;
@@ -475,7 +524,7 @@ struct dpf_attribute_list_dpf : v3_attribute_list_utf8_cpp {
attr.get_string_utf8 = []V3_API(void* self, const char* id, char*, uint32_t) -> v3_result
{
- dpf_attribute_list_dpf* const attr = *(dpf_attribute_list_dpf**)self;
+ dpf_attribute_list_utf8* const attr = *(dpf_attribute_list_utf8**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
if (attr->attrs.find(id) == attr->attrs.end())
@@ -489,12 +538,8 @@ struct dpf_attribute_list_dpf : v3_attribute_list_utf8_cpp {
// --------------------------------------------------------------------------------------------------------------------
// dpf_attribute_list
-struct v3_attribute_list_cpp : v3_funknown {
- v3_attribute_list attr;
-};
-
struct dpf_attribute_list : v3_attribute_list_cpp {
- ScopedPointer<dpf_attribute_list_dpf> attrdpf;
+ ScopedPointer<dpf_attribute_list_utf8> attrutf8;
std::map<std::string, dpf_attribute_value> attrs;
dpf_attribute_list()
@@ -527,9 +572,9 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
if (v3_tuid_match(v3_attribute_list_utf8_iid, iid))
{
- if (attr->attrdpf == nullptr)
- attr->attrdpf = new dpf_attribute_list_dpf(attr->attrs);
- *iface = &attr->attrdpf;
+ if (attr->attrutf8 == nullptr)
+ attr->attrutf8 = new dpf_attribute_list_utf8(attr->attrs);
+ *iface = &attr->attrutf8;
return V3_OK;
}
@@ -543,7 +588,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
// ------------------------------------------------------------------------------------------------------------
// v3_attribute_list
- attr.set_int = []V3_API(void* self, const char* id, int64_t value) -> v3_result
+ attrlist.set_int = []V3_API(void* self, const char* id, int64_t value) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -554,7 +599,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_OK;
};
- attr.get_int = []V3_API(void* self, const char* id, int64_t* value) -> v3_result
+ attrlist.get_int = []V3_API(void* self, const char* id, int64_t* value) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -569,7 +614,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_OK;
};
- attr.set_float = []V3_API(void* self, const char* id, double value) -> v3_result
+ attrlist.set_float = []V3_API(void* self, const char* id, double value) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -580,7 +625,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_OK;
};
- attr.get_float = []V3_API(void* self, const char* id, double* value) -> v3_result
+ attrlist.get_float = []V3_API(void* self, const char* id, double* value) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -595,7 +640,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_OK;
};
- attr.set_string = []V3_API(void* self, const char* id, const int16_t* /*string*/) -> v3_result
+ attrlist.set_string = []V3_API(void* self, const char* id, const int16_t* /*string*/) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -607,7 +652,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_NOT_IMPLEMENTED;
};
- attr.get_string = []V3_API(void* self, const char* id, int16_t* /*string*/, uint32_t /*size*/) -> v3_result
+ attrlist.get_string = []V3_API(void* self, const char* id, int16_t* /*string*/, uint32_t /*size*/) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -621,7 +666,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_NOT_IMPLEMENTED;
};
- attr.set_binary = []V3_API(void* self, const char* id, const void* data, uint32_t size) -> v3_result
+ attrlist.set_binary = []V3_API(void* self, const char* id, const void* data, uint32_t size) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -638,7 +683,7 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
return V3_NOT_IMPLEMENTED;
};
- attr.get_binary = []V3_API(void* self, const char* id, const void** data, uint32_t* size) -> v3_result
+ attrlist.get_binary = []V3_API(void* self, const char* id, const void** data, uint32_t* size) -> v3_result
{
dpf_attribute_list* const attr = *(dpf_attribute_list**)self;
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NOT_INITIALISED);
@@ -659,10 +704,6 @@ struct dpf_attribute_list : v3_attribute_list_cpp {
// --------------------------------------------------------------------------------------------------------------------
// dpf_message
-struct v3_message_cpp : v3_funknown {
- v3_message msg;
-};
-
struct dpf_message : v3_message_cpp {
std::atomic<int> refcounter;
ScopedPointer<dpf_message>* self;
@@ -761,7 +802,7 @@ struct dpf_message : v3_message_cpp {
}
};
-static v3_message** dpf_message_create(const char* const id)
+v3_message** dpf_message_create(const char* const id)
{
ScopedPointer<dpf_message>* const messageptr = new ScopedPointer<dpf_message>;
*messageptr = new dpf_message(messageptr, id);
@@ -771,10 +812,6 @@ static v3_message** dpf_message_create(const char* const id)
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_content_scale
-struct v3_plugin_view_content_scale_cpp : v3_funknown {
- v3_plugin_view_content_scale scale;
-};
-
struct dpf_plugin_view_content_scale : v3_plugin_view_content_scale_cpp {
ScopedPointer<UIVst3>& uivst3;
// cached values
@@ -839,32 +876,113 @@ struct dpf_plugin_view_content_scale : v3_plugin_view_content_scale_cpp {
};
// --------------------------------------------------------------------------------------------------------------------
-// dpf_plugin_view
+// dpf_ui_connection_point
+
+struct dpf_ui_connection_point : v3_connection_point_cpp {
+ ScopedPointer<UIVst3>& uivst3;
+ v3_connection_point** other;
+
+ dpf_ui_connection_point(ScopedPointer<UIVst3>& v)
+ : uivst3(v),
+ other(nullptr)
+ {
+ static const uint8_t* kSupportedInterfaces[] = {
+ v3_funknown_iid,
+ v3_connection_point_iid
+ };
+
+ // ------------------------------------------------------------------------------------------------------------
+ // v3_funknown
+
+ query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result
+ {
+ d_stdout("dpf_ui_connection_point::query_interface => %p %s %p", self, tuid2str(iid), iface);
+ *iface = NULL;
+ DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE);
+
+ for (const uint8_t* interface_iid : kSupportedInterfaces)
+ {
+ if (v3_tuid_match(interface_iid, iid))
+ {
+ *iface = self;
+ return V3_OK;
+ }
+ }
+
+ return V3_NO_INTERFACE;
+ };
+
+ // there is only a single instance of this, so we don't have to care here
+ ref = []V3_API(void*) -> uint32_t { return 1; };
+ unref = []V3_API(void*) -> uint32_t { return 0; };
+
+ // ------------------------------------------------------------------------------------------------------------
+ // v3_connection_point
+
+ point.connect = []V3_API(void* self, struct v3_connection_point** other) -> v3_result
+ {
+ d_stdout("dpf_ui_connection_point::connect => %p %p", self, other);
+ dpf_ui_connection_point* const point = *(dpf_ui_connection_point**)self;
+ DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);
+ DISTRHO_SAFE_ASSERT_RETURN(point->other == nullptr, V3_INVALID_ARG);
+
+ point->other = other;
+
+ if (UIVst3* const uivst3 = point->uivst3)
+ uivst3->connect(other);
+
+ return V3_OK;
+ };
+
+ point.disconnect = []V3_API(void* self, struct v3_connection_point** other) -> v3_result
+ {
+ d_stdout("dpf_ui_connection_point::disconnect => %p %p", self, other);
+ dpf_ui_connection_point* const point = *(dpf_ui_connection_point**)self;
+ DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);
+ DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG);
+
+ point->other = nullptr;
+
+ if (UIVst3* const uivst3 = point->uivst3)
+ uivst3->disconnect();
+
+ return V3_OK;
+ };
+
+ point.notify = []V3_API(void* self, struct v3_message** message) -> v3_result
+ {
+ d_stdout("dpf_ui_connection_point::notify => %p %p", self, message);
+ dpf_ui_connection_point* const point = *(dpf_ui_connection_point**)self;
+ DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);
+
+ UIVst3* const uivst3 = point->uivst3;
+ DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED);
-struct v3_plugin_view_cpp : v3_funknown {
- v3_plugin_view view;
+ return uivst3->notify(message);
+ };
+ }
};
+// --------------------------------------------------------------------------------------------------------------------
+// dpf_plugin_view
+
struct dpf_plugin_view : v3_plugin_view_cpp {
std::atomic<int> refcounter;
ScopedPointer<dpf_plugin_view>* self;
ScopedPointer<dpf_plugin_view_content_scale> scale;
+ ScopedPointer<dpf_ui_connection_point> connection;
ScopedPointer<UIVst3> uivst3;
// cached values
- v3_connection_point** const connection;
void* const instancePointer;
double sampleRate;
v3_plugin_frame** frame = nullptr;
- dpf_plugin_view(ScopedPointer<dpf_plugin_view>* selfptr,
- v3_connection_point** const connectionptr,
- void* const instance,
- const double sr)
+ dpf_plugin_view(ScopedPointer<dpf_plugin_view>* selfptr, void* const instance, const double sr)
: refcounter(1),
self(selfptr),
- connection(connectionptr),
instancePointer(instance),
- sampleRate(sr)
+ sampleRate(sr),
+ frame(nullptr)
{
static const uint8_t* kSupportedInterfacesBase[] = {
v3_funknown_iid,
@@ -902,6 +1020,14 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
dpf_plugin_view* const view = *(dpf_plugin_view**)self;
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NO_INTERFACE);
+ if (v3_tuid_match(v3_connection_point_iid, iid))
+ {
+ if (view->connection == nullptr)
+ view->connection = new dpf_ui_connection_point(view->uivst3);
+ *iface = &view->connection;
+ return V3_OK;
+ }
+
if (v3_tuid_match(v3_plugin_view_content_scale_iid, iid))
{
if (view->scale == nullptr)
@@ -931,6 +1057,10 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
if (const int refcounter = --view->refcounter)
return refcounter;
+ if (view->connection != nullptr && view->connection->other)
+ v3_cpp_obj(view->connection->other)->disconnect(view->connection->other,
+ (v3_connection_point**)&view->connection);
+
*view->self = nullptr;
delete (dpf_plugin_view**)self;
return 0;
@@ -967,11 +1097,15 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
{
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f;
view->uivst3 = new UIVst3((v3_plugin_view**)view->self,
- view->connection,
(uintptr_t)parent,
scaleFactor,
view->sampleRate,
view->instancePointer);
+
+ if (dpf_ui_connection_point* const point = view->connection)
+ if (point->other != nullptr)
+ view->uivst3->connect(point->other);
+
view->uivst3->setFrame(view->frame);
return V3_OK;
}
@@ -1111,14 +1245,13 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (called from plugin side)
-v3_funknown** dpf_plugin_view_create(v3_connection_point** connection, void* instancePointer, double sampleRate);
+v3_plugin_view** dpf_plugin_view_create(void* instancePointer, double sampleRate);
-v3_funknown** dpf_plugin_view_create(v3_connection_point** const connection,
- void* const instancePointer, const double sampleRate)
+v3_plugin_view** dpf_plugin_view_create(void* const instancePointer, const double sampleRate)
{
ScopedPointer<dpf_plugin_view>* const viewptr = new ScopedPointer<dpf_plugin_view>;
- *viewptr = new dpf_plugin_view(viewptr, connection, instancePointer, sampleRate);
- return (v3_funknown**)viewptr;
+ *viewptr = new dpf_plugin_view(viewptr, instancePointer, sampleRate);
+ return (v3_plugin_view**)static_cast<void*>(viewptr);
}
// --------------------------------------------------------------------------------------------------------------------
diff --git a/distrho/src/travesty/message.h b/distrho/src/travesty/message.h
@@ -70,4 +70,24 @@ struct v3_connection_point {
static constexpr const v3_tuid v3_connection_point_iid =
V3_ID(0x70A4156F, 0x6E6E4026, 0x989148BF, 0xAA60D8D1);
+#ifdef __cplusplus
+
+/**
+ * C++ variants
+ */
+
+struct v3_attribute_list_cpp : v3_funknown {
+ v3_attribute_list attrlist;
+};
+
+struct v3_message_cpp : v3_funknown {
+ v3_message msg;
+};
+
+struct v3_connection_point_cpp : v3_funknown {
+ v3_connection_point point;
+};
+
+#endif
+
#include "align_pop.h"
diff --git a/distrho/src/travesty/view.h b/distrho/src/travesty/view.h
@@ -106,3 +106,27 @@ struct v3_plugin_view_parameter_finder {
static constexpr const v3_tuid v3_plugin_view_parameter_finder_iid =
V3_ID(0x0F618302, 0x215D4587, 0xA512073C, 0x77B9D383);
+
+#ifdef __cplusplus
+
+/**
+ * C++ variants
+ */
+
+struct v3_plugin_view_cpp : v3_funknown {
+ v3_plugin_view view;
+};
+
+struct v3_plugin_frame_cpp : v3_funknown {
+ v3_plugin_frame frame;
+};
+
+struct v3_plugin_view_content_scale_cpp : v3_funknown {
+ v3_plugin_view_content_scale scale;
+};
+
+struct v3_plugin_view_parameter_finder_cpp : v3_funknown {
+ v3_plugin_view_parameter_finder finder;
+};
+
+#endif