commit 4893656da0f83c16ed1e1f11a8dd87f1cb483a79
parent d9044f27fe462d1827a8fcd2a2fa0bf988c0067f
Author: falkTX <falktx@falktx.com>
Date: Sat, 2 Oct 2021 04:36:38 +0100
A few more VST3 tests on refcounter and host context
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
3 files changed, 118 insertions(+), 51 deletions(-)
diff --git a/distrho/src/DistrhoPluginVST3.cpp b/distrho/src/DistrhoPluginVST3.cpp
@@ -2311,13 +2311,16 @@ struct dpf_dsp_connection_point : v3_connection_point_cpp {
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALIZED);
DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG);
- point->other = nullptr;
- point->bridge = nullptr;
-
if (point->type == kConnectionPointComponent)
if (PluginVst3* const vst3 = point->vst3)
vst3->disconnect();
+ if (point->type == kConnectionPointBridge)
+ v3_cpp_obj_unref(point->other);
+
+ point->other = nullptr;
+ point->bridge = nullptr;
+
return V3_OK;
}
@@ -2453,13 +2456,15 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
bool initialized;
// cached values
v3_component_handler** handler;
+ v3_host_application** const originalHostContext;
v3_plugin_base::v3_funknown** hostContext;
- dpf_edit_controller(ScopedPointer<PluginVst3>& v)
+ dpf_edit_controller(ScopedPointer<PluginVst3>& v, v3_host_application** const h)
: refcounter(1),
vst3(v),
initialized(false),
handler(nullptr),
+ originalHostContext(h),
hostContext(nullptr)
{
// v3_funknown, single instance with custom query
@@ -2757,10 +2762,14 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, nullptr);
// we require host context for message creation
- DISTRHO_SAFE_ASSERT_RETURN(controller->hostContext != nullptr, nullptr);
-
v3_host_application** host = nullptr;
- v3_cpp_obj_query_interface(controller->hostContext, v3_host_application_iid, &host);
+
+ if (controller->hostContext != nullptr)
+ v3_cpp_obj_query_interface(controller->hostContext, v3_host_application_iid, &host);
+
+ if (host == nullptr)
+ host = controller->originalHostContext;
+
DISTRHO_SAFE_ASSERT_RETURN(host != nullptr, nullptr);
// if there is a component connection, we require it to be active
@@ -3031,10 +3040,12 @@ struct dpf_component : v3_component_cpp {
#endif
ScopedPointer<dpf_edit_controller> controller;
ScopedPointer<PluginVst3> vst3;
+ v3_host_application** const hostContext;
- dpf_component(ScopedPointer<dpf_component>* const s)
+ dpf_component(ScopedPointer<dpf_component>* const s, v3_host_application** const h)
: refcounter(1),
- self(s)
+ self(s),
+ hostContext(h)
{
// v3_funknown, everything custom
query_interface = query_interface_component;
@@ -3109,7 +3120,7 @@ struct dpf_component : v3_component_cpp {
if (v3_tuid_match(iid, v3_edit_controller_iid))
{
if (component->controller == nullptr)
- component->controller = new dpf_edit_controller(component->vst3);
+ component->controller = new dpf_edit_controller(component->vst3, component->hostContext);
else
++component->controller->refcounter;
*iface = &component->controller;
@@ -3225,6 +3236,9 @@ struct dpf_component : v3_component_cpp {
v3_host_application** host = nullptr;
v3_cpp_obj_query_interface(context, v3_host_application_iid, &host);
+ if (host == nullptr)
+ host = component->hostContext;
+
component->vst3 = new PluginVst3(host);
return V3_OK;
}
@@ -3373,9 +3387,6 @@ static const PluginExporter& _getPluginInfo()
d_lastSampleRate = 0.0;
d_lastCanRequestParameterValueChanges = false;
- dpf_tuid_class[2] = dpf_tuid_component[2] = dpf_tuid_controller[2]
- = dpf_tuid_processor[2] = dpf_tuid_view[2] = gPluginInfo.getUniqueId();
-
return gPluginInfo;
}
@@ -3389,12 +3400,19 @@ static const PluginExporter& getPluginInfo()
// dpf_factory
struct dpf_factory : v3_plugin_factory_cpp {
+ // cached values
+ v3_funknown** hostContext;
+
dpf_factory()
+ : hostContext(nullptr)
{
static constexpr const v3_tuid interface_v1 = V3_ID_COPY(v3_plugin_factory_iid);
static constexpr const v3_tuid interface_v2 = V3_ID_COPY(v3_plugin_factory_2_iid);
static constexpr const v3_tuid interface_v3 = V3_ID_COPY(v3_plugin_factory_3_iid);
+ dpf_tuid_class[2] = dpf_tuid_component[2] = dpf_tuid_controller[2]
+ = dpf_tuid_processor[2] = dpf_tuid_view[2] = getPluginInfo().getUniqueId();
+
// v3_funknown, used statically
query_interface = dpf_static__query_interface<interface_v1, interface_v2, interface_v3>;
ref = dpf_static__ref;
@@ -3476,8 +3494,12 @@ struct dpf_factory : v3_plugin_factory_cpp {
dpf_factory* const factory = *(dpf_factory**)self;
DISTRHO_SAFE_ASSERT_RETURN(factory != nullptr, V3_NOT_INITIALIZED);
+ // query for host context
+ v3_host_application** host = nullptr;
+ v3_cpp_obj_query_interface(factory->hostContext, v3_host_application_iid, &host);
+
ScopedPointer<dpf_component>* const componentptr = new ScopedPointer<dpf_component>;
- *componentptr = new dpf_component(componentptr);
+ *componentptr = new dpf_component(componentptr, host);
*instance = componentptr;
return V3_OK;
}
@@ -3524,10 +3546,14 @@ struct dpf_factory : v3_plugin_factory_cpp {
return V3_OK;
}
- static V3_API v3_result set_host_context(void* self, v3_funknown* host)
+ static V3_API v3_result set_host_context(void* self, v3_funknown** context)
{
- d_stdout("dpf_factory::set_host_context => %p %p", self, host);
- return V3_NOT_IMPLEMENTED;
+ d_stdout("dpf_factory::set_host_context => %p %p", self, context);
+ dpf_factory* const factory = *(dpf_factory**)self;
+ DISTRHO_SAFE_ASSERT_RETURN(factory != nullptr, V3_NOT_INITIALIZED);
+
+ factory->hostContext = context;
+ return V3_OK;
}
DISTRHO_PREVENT_HEAP_ALLOCATION
diff --git a/distrho/src/DistrhoUIVST3.cpp b/distrho/src/DistrhoUIVST3.cpp
@@ -30,6 +30,7 @@ namespace std {
explicit atomic_int(volatile int v) noexcept : value(v) {}
int operator++() volatile noexcept { return __atomic_add_fetch(&value, 1, __ATOMIC_RELAXED); }
int operator--() volatile noexcept { return __atomic_sub_fetch(&value, 1, __ATOMIC_RELAXED); }
+ operator int() volatile noexcept { return __atomic_load_n(&value, __ATOMIC_RELAXED); }
};
};
#endif
@@ -593,22 +594,39 @@ static V3_API uint32_t dpf_static__ref(void*) { return 1; }
static V3_API uint32_t dpf_static__unref(void*) { return 0; }
// --------------------------------------------------------------------------------------------------------------------
+// v3_funknown with refcounter
+
+template<class T>
+static V3_API uint32_t dpf_refcounter__ref(void* self)
+{
+ return ++(*(T**)self)->refcounter;
+}
+
+template<class T>
+static V3_API uint32_t dpf_refcounter__unref(void* self)
+{
+ return --(*(T**)self)->refcounter;
+}
+
+// --------------------------------------------------------------------------------------------------------------------
// dpf_ui_connection_point
struct dpf_ui_connection_point : v3_connection_point_cpp {
+ std::atomic_int refcounter;
ScopedPointer<UIVst3>& uivst3;
v3_connection_point** other;
dpf_ui_connection_point(ScopedPointer<UIVst3>& v)
- : uivst3(v),
+ : refcounter(1),
+ uivst3(v),
other(nullptr)
{
static constexpr const v3_tuid interface = V3_ID_COPY(v3_connection_point_iid);
// v3_funknown, single instance
query_interface = dpf_static__query_interface<interface>;
- ref = dpf_static__ref;
- unref = dpf_static__unref;
+ ref = dpf_refcounter__ref<dpf_ui_connection_point>;
+ unref = dpf_refcounter__unref<dpf_ui_connection_point>;
// v3_connection_point
point.connect = connect;
@@ -665,20 +683,22 @@ struct dpf_ui_connection_point : v3_connection_point_cpp {
// dpf_plugin_view_content_scale
struct dpf_plugin_view_content_scale : v3_plugin_view_content_scale_cpp {
+ std::atomic_int refcounter;
ScopedPointer<UIVst3>& uivst3;
// cached values
float scaleFactor;
dpf_plugin_view_content_scale(ScopedPointer<UIVst3>& v)
- : uivst3(v),
+ : refcounter(1),
+ uivst3(v),
scaleFactor(0.0f)
{
static constexpr const v3_tuid interface = V3_ID_COPY(v3_plugin_view_content_scale_iid);
// v3_funknown, single instance
query_interface = dpf_static__query_interface<interface>;
- ref = dpf_static__ref;
- unref = dpf_static__unref;
+ ref = dpf_refcounter__ref<dpf_plugin_view_content_scale>;
+ unref = dpf_refcounter__unref<dpf_plugin_view_content_scale>;
// v3_plugin_view_content_scale
scale.set_content_scale_factor = set_content_scale_factor;
@@ -751,7 +771,7 @@ static const char* const kSupportedPlatforms[] = {
struct dpf_plugin_view : v3_plugin_view_cpp {
std::atomic_int refcounter;
- ScopedPointer<dpf_plugin_view>* self;
+ dpf_plugin_view** const self;
ScopedPointer<dpf_ui_connection_point> connection;
ScopedPointer<dpf_plugin_view_content_scale> scale;
#ifdef DPF_VST3_USING_HOST_RUN_LOOP
@@ -762,12 +782,11 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
v3_host_application** const host;
void* const instancePointer;
double sampleRate;
- v3_plugin_frame** frame = nullptr;
+ v3_plugin_frame** frame;
- dpf_plugin_view(ScopedPointer<dpf_plugin_view>* selfptr,
- v3_host_application** const h, void* const instance, const double sr)
+ dpf_plugin_view(dpf_plugin_view** const s, v3_host_application** const h, void* const instance, const double sr)
: refcounter(1),
- self(selfptr),
+ self(s),
host(h),
instancePointer(instance),
sampleRate(sr),
@@ -843,7 +862,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
static V3_API uint32_t unref_view(void* self)
{
- ScopedPointer<dpf_plugin_view>* const viewptr = (ScopedPointer<dpf_plugin_view>*)self;
+ dpf_plugin_view** const viewptr = (dpf_plugin_view**)self;
dpf_plugin_view* const view = *viewptr;
if (const int refcount = --view->refcounter)
@@ -854,11 +873,31 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
d_stdout("dpf_plugin_view::unref => %p | refcount is zero, deleting everything now!", self);
+ DISTRHO_SAFE_ASSERT_RETURN(viewptr == view->self, V3_INTERNAL_ERR);
+
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;
+ if (dpf_ui_connection_point* const conn = view->connection)
+ {
+ if (const int refcount = conn->refcounter)
+ {
+ d_stderr("DPF warning: asked to delete view while connection point still active (refcount %d)", refcount);
+ return V3_INVALID_ARG;
+ }
+ }
+
+ if (dpf_plugin_view_content_scale* const scale = view->scale)
+ {
+ if (const int refcount = scale->refcounter)
+ {
+ d_stderr("DPF warning: asked to delete view while content scale still active (refcount %d)", refcount);
+ return V3_INVALID_ARG;
+ }
+ }
+
+ delete view;
delete viewptr;
return 0;
}
@@ -879,7 +918,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
}
return V3_NOT_IMPLEMENTED;
- };
+ }
static V3_API v3_result attached(void* self, void* parent, const char* platform_type)
{
@@ -892,14 +931,14 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
{
if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0)
{
- #ifdef DPF_VST3_USING_HOST_RUN_LOOP
+ #ifdef DPF_VST3_USING_HOST_RUN_LOOP
// find host run loop to plug ourselves into (required on some systems)
DISTRHO_SAFE_ASSERT_RETURN(view->frame != nullptr, V3_INVALID_ARG);
v3_run_loop** runloop = nullptr;
v3_cpp_obj_query_interface(view->frame, v3_run_loop_iid, &runloop);
DISTRHO_SAFE_ASSERT_RETURN(runloop != nullptr, V3_INVALID_ARG);
- #endif
+ #endif
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f;
view->uivst3 = new UIVst3((v3_plugin_view**)view->self,
@@ -915,20 +954,20 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
view->uivst3->setFrame(view->frame);
- #ifdef DPF_VST3_USING_HOST_RUN_LOOP
+ #ifdef DPF_VST3_USING_HOST_RUN_LOOP
// register a timer host run loop stuff
view->timer = new dpf_timer_handler(view->uivst3);
v3_cpp_obj(runloop)->register_timer(runloop,
(v3_timer_handler**)&view->timer,
DPF_VST3_TIMER_INTERVAL);
- #endif
+ #endif
return V3_OK;
}
}
return V3_NOT_IMPLEMENTED;
- };
+ }
static V3_API v3_result removed(void* self)
{
@@ -937,21 +976,23 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED);
DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 != nullptr, V3_INVALID_ARG);
- #ifdef DPF_VST3_USING_HOST_RUN_LOOP
+ #ifdef DPF_VST3_USING_HOST_RUN_LOOP
// unregister our timer as needed
if (view->timer != nullptr)
{
v3_run_loop** runloop = nullptr;
- if (v3_cpp_obj_query_interface(view->host, v3_run_loop_iid, &runloop) == V3_OK && runloop != nullptr)
+ v3_cpp_obj_query_interface(view->host, v3_run_loop_iid, &runloop);
+
+ if (runloop != nullptr)
v3_cpp_obj(runloop)->unregister_timer(runloop, (v3_timer_handler**)&view->timer);
view->timer = nullptr;
}
- #endif
+ #endif
view->uivst3 = nullptr;
return V3_OK;
- };
+ }
static V3_API v3_result on_wheel(void* self, float distance)
{
@@ -963,7 +1004,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED);
return uivst3->onWheel(distance);
- };
+ }
static V3_API v3_result on_key_down(void* self, int16_t key_char, int16_t key_code, int16_t modifiers)
{
@@ -975,7 +1016,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED);
return uivst3->onKeyDown(key_char, key_code, modifiers);
- };
+ }
static V3_API v3_result on_key_up(void* self, int16_t key_char, int16_t key_code, int16_t modifiers)
{
@@ -987,7 +1028,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED);
return uivst3->onKeyUp(key_char, key_code, modifiers);
- };
+ }
static V3_API v3_result get_size(void* self, v3_view_rect* rect)
{
@@ -1007,7 +1048,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
rect->right = tmpUI.getWidth();
rect->bottom = tmpUI.getHeight();
return V3_OK;
- };
+ }
static V3_API v3_result on_size(void* self, v3_view_rect* rect)
{
@@ -1019,7 +1060,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED);
return uivst3->onSize(rect);
- };
+ }
static V3_API v3_result on_focus(void* self, v3_bool state)
{
@@ -1031,7 +1072,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED);
return uivst3->onFocus(state);
- };
+ }
static V3_API v3_result set_frame(void* self, v3_plugin_frame** frame)
{
@@ -1045,7 +1086,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
return uivst3->setFrame(frame);
return V3_NOT_INITIALIZED;
- };
+ }
static V3_API v3_result can_resize(void* self)
{
@@ -1055,7 +1096,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
// #else
return V3_NOT_IMPLEMENTED;
// #endif
- };
+ }
static V3_API v3_result check_size_constraint(void* self, v3_view_rect* rect)
{
@@ -1067,7 +1108,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED);
return uivst3->checkSizeConstraint(rect);
- };
+ }
};
// --------------------------------------------------------------------------------------------------------------------
@@ -1079,7 +1120,7 @@ v3_plugin_view** dpf_plugin_view_create(v3_host_application** const host,
void* const instancePointer,
const double sampleRate)
{
- ScopedPointer<dpf_plugin_view>* const viewptr = new ScopedPointer<dpf_plugin_view>;
+ dpf_plugin_view** const viewptr = new dpf_plugin_view*;
*viewptr = new dpf_plugin_view(viewptr, host, instancePointer, sampleRate);
return (v3_plugin_view**)static_cast<void*>(viewptr);
}
diff --git a/distrho/src/travesty/factory.h b/distrho/src/travesty/factory.h
@@ -96,7 +96,7 @@ struct v3_plugin_factory_3 {
struct v3_plugin_factory_2;
v3_result (V3_API *get_class_info_utf16)(void* self, int32_t idx, struct v3_class_info_3*);
- v3_result (V3_API *set_host_context)(void* self, struct v3_funknown* host);
+ v3_result (V3_API *set_host_context)(void* self, struct v3_funknown** host);
};
static constexpr const v3_tuid v3_plugin_factory_3_iid =