|
|
@@ -16,12 +16,24 @@ |
|
|
|
|
|
|
|
#include "DistrhoUIInternal.hpp" |
|
|
|
|
|
|
|
#include <atomic> |
|
|
|
|
|
|
|
#include "travesty/edit_controller.h" |
|
|
|
#include "travesty/host.h" |
|
|
|
#include "travesty/view.h" |
|
|
|
|
|
|
|
#ifdef DISTRHO_PROPER_CPP11_SUPPORT |
|
|
|
# include <atomic> |
|
|
|
#else |
|
|
|
// quick and dirty std::atomic replacement for the things we need |
|
|
|
namespace std { |
|
|
|
struct atomic_int { |
|
|
|
volatile int value; |
|
|
|
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); } |
|
|
|
}; |
|
|
|
}; |
|
|
|
#endif |
|
|
|
|
|
|
|
/* TODO items: |
|
|
|
* - mousewheel event |
|
|
|
* - key down/up events |
|
|
@@ -555,6 +567,31 @@ private: |
|
|
|
* VST3 low-level pointer thingies follow, proceed with care. |
|
|
|
*/ |
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_funknown for static and single instances of classes |
|
|
|
|
|
|
|
template<const v3_tuid& v3_interface> |
|
|
|
static V3_API v3_result dpf_static__query_interface(void* self, const v3_tuid iid, void** iface) |
|
|
|
{ |
|
|
|
if (v3_tuid_match(iid, v3_funknown_iid)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
if (v3_tuid_match(iid, v3_interface)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
*iface = NULL; |
|
|
|
return V3_NO_INTERFACE; |
|
|
|
} |
|
|
|
|
|
|
|
static V3_API uint32_t dpf_static__ref(void*) { return 1; } |
|
|
|
static V3_API uint32_t dpf_static__unref(void*) { return 0; } |
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
// dpf_ui_connection_point |
|
|
|
|
|
|
@@ -566,79 +603,61 @@ struct dpf_ui_connection_point : v3_connection_point_cpp { |
|
|
|
: uivst3(v), |
|
|
|
other(nullptr) |
|
|
|
{ |
|
|
|
static const uint8_t* kSupportedInterfaces[] = { |
|
|
|
v3_funknown_iid, |
|
|
|
v3_connection_point_iid |
|
|
|
}; |
|
|
|
static constexpr const v3_tuid interface = V3_ID_COPY(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); |
|
|
|
// v3_funknown, single instance |
|
|
|
query_interface = dpf_static__query_interface<interface>; |
|
|
|
ref = dpf_static__ref; |
|
|
|
unref = dpf_static__unref; |
|
|
|
|
|
|
|
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 = connect; |
|
|
|
point.disconnect = disconnect; |
|
|
|
point.notify = notify; |
|
|
|
} |
|
|
|
|
|
|
|
point.connect = []V3_API(void* self, 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); |
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_connection_point |
|
|
|
|
|
|
|
point->other = other; |
|
|
|
static V3_API v3_result connect(void* self, v3_connection_point** other) |
|
|
|
{ |
|
|
|
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_INITIALIZED); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(point->other == nullptr, V3_INVALID_ARG); |
|
|
|
|
|
|
|
if (UIVst3* const uivst3 = point->uivst3) |
|
|
|
uivst3->connect(other); |
|
|
|
point->other = other; |
|
|
|
|
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
if (UIVst3* const uivst3 = point->uivst3) |
|
|
|
uivst3->connect(other); |
|
|
|
|
|
|
|
point.disconnect = []V3_API(void* self, 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); |
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
|
|
|
|
point->other = nullptr; |
|
|
|
static V3_API v3_result disconnect(void* self, v3_connection_point** other) |
|
|
|
{ |
|
|
|
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_INITIALIZED); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(point->other != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
|
|
if (UIVst3* const uivst3 = point->uivst3) |
|
|
|
uivst3->disconnect(); |
|
|
|
point->other = nullptr; |
|
|
|
|
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
if (UIVst3* const uivst3 = point->uivst3) |
|
|
|
uivst3->disconnect(); |
|
|
|
|
|
|
|
point.notify = []V3_API(void* self, v3_message** message) -> v3_result |
|
|
|
{ |
|
|
|
dpf_ui_connection_point* const point = *(dpf_ui_connection_point**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED); |
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
|
|
|
|
static V3_API v3_result notify(void* self, v3_message** message) |
|
|
|
{ |
|
|
|
dpf_ui_connection_point* const point = *(dpf_ui_connection_point**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = point->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
UIVst3* const uivst3 = point->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
return uivst3->notify(message); |
|
|
|
}; |
|
|
|
return uivst3->notify(message); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
@@ -654,57 +673,32 @@ struct dpf_plugin_view_content_scale : v3_plugin_view_content_scale_cpp { |
|
|
|
: uivst3(v), |
|
|
|
scaleFactor(0.0f) |
|
|
|
{ |
|
|
|
query_interface = query_interface_fn; |
|
|
|
ref = ref_fn; |
|
|
|
unref = unref_fn; |
|
|
|
scale.set_content_scale_factor = set_content_scale_factor_fn; |
|
|
|
} |
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_funknown |
|
|
|
|
|
|
|
static v3_result V3_API query_interface_fn(void* self, const v3_tuid iid, void** iface) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view_content_scale::query_interface => %p %s %p", self, tuid2str(iid), iface); |
|
|
|
*iface = NULL; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE); |
|
|
|
static constexpr const v3_tuid interface = V3_ID_COPY(v3_plugin_view_content_scale_iid); |
|
|
|
|
|
|
|
static const uint8_t* kSupportedInterfaces[] = { |
|
|
|
v3_funknown_iid, |
|
|
|
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; |
|
|
|
|
|
|
|
for (const uint8_t* interface_iid : kSupportedInterfaces) |
|
|
|
{ |
|
|
|
if (v3_tuid_match(interface_iid, iid)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return V3_NO_INTERFACE; |
|
|
|
// v3_plugin_view_content_scale |
|
|
|
scale.set_content_scale_factor = set_content_scale_factor; |
|
|
|
} |
|
|
|
|
|
|
|
// there is only a single instance of this, so we don't have to care here |
|
|
|
static uint32_t V3_API ref_fn(void*) { return 1; }; |
|
|
|
static uint32_t V3_API unref_fn(void*) { return 0; }; |
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_plugin_view_content_scale_steinberg |
|
|
|
// v3_plugin_view_content_scale |
|
|
|
|
|
|
|
static v3_result V3_API set_content_scale_factor_fn(void* self, float factor) |
|
|
|
static V3_API v3_result set_content_scale_factor(void* self, float factor) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::set_content_scale_factor => %p %f", self, factor); |
|
|
|
dpf_plugin_view_content_scale* const scale = *(dpf_plugin_view_content_scale**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(scale != nullptr, V3_NOT_INITIALISED); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(scale != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
scale->scaleFactor = factor; |
|
|
|
|
|
|
|
if (UIVst3* const uivst3 = scale->uivst3) |
|
|
|
return uivst3->setContentScaleFactor(factor); |
|
|
|
|
|
|
|
return V3_NOT_INITIALISED; |
|
|
|
return V3_NOT_INITIALIZED; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
@@ -718,46 +712,21 @@ struct dpf_timer_handler : v3_timer_handler_cpp { |
|
|
|
dpf_timer_handler(ScopedPointer<UIVst3>& v) |
|
|
|
: uivst3(v) |
|
|
|
{ |
|
|
|
query_interface = query_interface_fn; |
|
|
|
ref = ref_fn; |
|
|
|
unref = unref_fn; |
|
|
|
handler.on_timer = on_timer; |
|
|
|
} |
|
|
|
static constexpr const v3_tuid interface = V3_ID_COPY(v3_timer_handler_iid); |
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_funknown |
|
|
|
// v3_funknown, single instance |
|
|
|
query_interface = dpf_static__query_interface<interface>; |
|
|
|
ref = dpf_static__ref; |
|
|
|
unref = dpf_static__unref; |
|
|
|
|
|
|
|
static v3_result V3_API query_interface_fn(void* self, const v3_tuid iid, void** iface) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view_content_scale::query_interface => %p %s %p", self, tuid2str(iid), iface); |
|
|
|
*iface = NULL; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE); |
|
|
|
|
|
|
|
static const uint8_t* kSupportedInterfaces[] = { |
|
|
|
v3_funknown_iid, |
|
|
|
v3_plugin_view_content_scale_iid |
|
|
|
}; |
|
|
|
|
|
|
|
for (const uint8_t* interface_iid : kSupportedInterfaces) |
|
|
|
{ |
|
|
|
if (v3_tuid_match(interface_iid, iid)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return V3_NO_INTERFACE; |
|
|
|
// v3_timer_handler |
|
|
|
handler.on_timer = on_timer; |
|
|
|
} |
|
|
|
|
|
|
|
// there is only a single instance of this, so we don't have to care here |
|
|
|
static uint32_t V3_API ref_fn(void*) { return 1; }; |
|
|
|
static uint32_t V3_API unref_fn(void*) { return 0; }; |
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_timer_handler |
|
|
|
|
|
|
|
static void V3_API on_timer(void* self) |
|
|
|
static V3_API void on_timer(void* self) |
|
|
|
{ |
|
|
|
dpf_timer_handler* const handler = *(dpf_timer_handler**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(handler != nullptr,); |
|
|
@@ -770,8 +739,18 @@ struct dpf_timer_handler : v3_timer_handler_cpp { |
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
// dpf_plugin_view |
|
|
|
|
|
|
|
static const char* const kSupportedPlatforms[] = { |
|
|
|
#ifdef _WIN32 |
|
|
|
V3_VIEW_PLATFORM_TYPE_HWND, |
|
|
|
#elif defined(__APPLE__) |
|
|
|
V3_VIEW_PLATFORM_TYPE_NSVIEW, |
|
|
|
#else |
|
|
|
V3_VIEW_PLATFORM_TYPE_X11, |
|
|
|
#endif |
|
|
|
}; |
|
|
|
|
|
|
|
struct dpf_plugin_view : v3_plugin_view_cpp { |
|
|
|
std::atomic<int> refcounter; |
|
|
|
std::atomic_int refcounter; |
|
|
|
ScopedPointer<dpf_plugin_view>* self; |
|
|
|
ScopedPointer<dpf_ui_connection_point> connection; |
|
|
|
ScopedPointer<dpf_plugin_view_content_scale> scale; |
|
|
@@ -794,294 +773,301 @@ struct dpf_plugin_view : v3_plugin_view_cpp { |
|
|
|
sampleRate(sr), |
|
|
|
frame(nullptr) |
|
|
|
{ |
|
|
|
static const uint8_t* kSupportedInterfacesBase[] = { |
|
|
|
v3_funknown_iid, |
|
|
|
v3_plugin_view_iid |
|
|
|
}; |
|
|
|
|
|
|
|
static const char* const kSupportedPlatforms[] = { |
|
|
|
#ifdef _WIN32 |
|
|
|
V3_VIEW_PLATFORM_TYPE_HWND, |
|
|
|
#elif defined(__APPLE__) |
|
|
|
V3_VIEW_PLATFORM_TYPE_NSVIEW, |
|
|
|
#else |
|
|
|
V3_VIEW_PLATFORM_TYPE_X11, |
|
|
|
#endif |
|
|
|
}; |
|
|
|
// v3_funknown, everything custom |
|
|
|
query_interface = query_interface_view; |
|
|
|
ref = ref_view; |
|
|
|
unref = unref_view; |
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------------------ |
|
|
|
// v3_funknown |
|
|
|
// v3_plugin_view |
|
|
|
view.is_platform_type_supported = is_platform_type_supported; |
|
|
|
view.attached = attached; |
|
|
|
view.removed = removed; |
|
|
|
view.on_wheel = on_wheel; |
|
|
|
view.on_key_down = on_key_down; |
|
|
|
view.on_key_up = on_key_up; |
|
|
|
view.get_size = get_size; |
|
|
|
view.on_size = on_size; |
|
|
|
view.on_focus = on_focus; |
|
|
|
view.set_frame = set_frame; |
|
|
|
view.can_resize = can_resize; |
|
|
|
view.check_size_constraint = check_size_constraint; |
|
|
|
} |
|
|
|
|
|
|
|
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::query_interface => %p %s %p", self, tuid2str(iid), iface); |
|
|
|
*iface = NULL; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE); |
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_funknown |
|
|
|
|
|
|
|
for (const uint8_t* interface_iid : kSupportedInterfacesBase) |
|
|
|
{ |
|
|
|
if (v3_tuid_match(interface_iid, iid)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
static V3_API v3_result query_interface_view(void* self, const v3_tuid iid, void** iface) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::query_interface => %p %s %p", self, tuid2str(iid), iface); |
|
|
|
*iface = NULL; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE); |
|
|
|
|
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NO_INTERFACE); |
|
|
|
if (v3_tuid_match(iid, v3_funknown_iid)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
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(iid, v3_plugin_view_iid)) |
|
|
|
{ |
|
|
|
*iface = self; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
if (v3_tuid_match(v3_plugin_view_content_scale_iid, iid)) |
|
|
|
{ |
|
|
|
if (view->scale == nullptr) |
|
|
|
view->scale = new dpf_plugin_view_content_scale(view->uivst3); |
|
|
|
*iface = &view->scale; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NO_INTERFACE); |
|
|
|
|
|
|
|
return 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; |
|
|
|
} |
|
|
|
|
|
|
|
ref = []V3_API(void* self) -> uint32_t |
|
|
|
if (v3_tuid_match(v3_plugin_view_content_scale_iid, iid)) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::ref => %p", self); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, 0); |
|
|
|
if (view->scale == nullptr) |
|
|
|
view->scale = new dpf_plugin_view_content_scale(view->uivst3); |
|
|
|
*iface = &view->scale; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
return ++view->refcounter; |
|
|
|
}; |
|
|
|
return V3_NO_INTERFACE; |
|
|
|
} |
|
|
|
|
|
|
|
unref = []V3_API(void* self) -> uint32_t |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::unref => %p", self); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, 0); |
|
|
|
static V3_API uint32_t ref_view(void* self) |
|
|
|
{ |
|
|
|
return ++(*(dpf_plugin_view**)self)->refcounter; |
|
|
|
} |
|
|
|
|
|
|
|
if (const int refcounter = --view->refcounter) |
|
|
|
return refcounter; |
|
|
|
static V3_API uint32_t unref_view(void* self) |
|
|
|
{ |
|
|
|
ScopedPointer<dpf_plugin_view>* const viewptr = (ScopedPointer<dpf_plugin_view>*)self; |
|
|
|
dpf_plugin_view* const view = *viewptr; |
|
|
|
|
|
|
|
if (view->connection != nullptr && view->connection->other) |
|
|
|
v3_cpp_obj(view->connection->other)->disconnect(view->connection->other, |
|
|
|
(v3_connection_point**)&view->connection); |
|
|
|
if (const int refcount = --view->refcounter) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::unref => %p | refcount %i", self, refcount); |
|
|
|
return refcount; |
|
|
|
} |
|
|
|
|
|
|
|
*view->self = nullptr; |
|
|
|
delete (dpf_plugin_view**)self; |
|
|
|
return 0; |
|
|
|
}; |
|
|
|
d_stdout("dpf_plugin_view::unref => %p | refcount is zero, deleting everything now!", self); |
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------------------ |
|
|
|
// v3_plugin_view |
|
|
|
if (view->connection != nullptr && view->connection->other) |
|
|
|
v3_cpp_obj(view->connection->other)->disconnect(view->connection->other, |
|
|
|
(v3_connection_point**)&view->connection); |
|
|
|
|
|
|
|
view.is_platform_type_supported = []V3_API(void* self, const char* platform_type) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::is_platform_type_supported => %p %s", self, platform_type); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
*(view->self) = nullptr; |
|
|
|
delete viewptr; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
for (size_t i=0; i<ARRAY_SIZE(kSupportedPlatforms); ++i) |
|
|
|
{ |
|
|
|
if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0) |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
// ---------------------------------------------------------------------------------------------------------------- |
|
|
|
// v3_plugin_view |
|
|
|
|
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
}; |
|
|
|
static V3_API v3_result is_platform_type_supported(void* self, const char* platform_type) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::is_platform_type_supported => %p %s", self, platform_type); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
view.attached = []V3_API(void* self, void* parent, const char* platform_type) -> v3_result |
|
|
|
for (size_t i=0; i<ARRAY_SIZE(kSupportedPlatforms); ++i) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::attached => %p %p %s", self, parent, platform_type); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 == nullptr, V3_INVALID_ARG); |
|
|
|
if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0) |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
|
|
|
|
for (size_t i=0; i<ARRAY_SIZE(kSupportedPlatforms); ++i) |
|
|
|
{ |
|
|
|
if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0) |
|
|
|
{ |
|
|
|
#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 |
|
|
|
|
|
|
|
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f; |
|
|
|
view->uivst3 = new UIVst3((v3_plugin_view**)view->self, |
|
|
|
view->host, |
|
|
|
(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); |
|
|
|
|
|
|
|
#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 |
|
|
|
|
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
}; |
|
|
|
|
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
}; |
|
|
|
static V3_API v3_result attached(void* self, void* parent, const char* platform_type) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::attached => %p %p %s", self, parent, platform_type); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 == nullptr, V3_INVALID_ARG); |
|
|
|
|
|
|
|
view.removed = []V3_API(void* self) -> v3_result |
|
|
|
for (size_t i=0; i<ARRAY_SIZE(kSupportedPlatforms); ++i) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::removed => %p", self); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
|
|
#ifdef DPF_VST3_USING_HOST_RUN_LOOP |
|
|
|
// unregister our timer as needed |
|
|
|
if (view->timer != nullptr) |
|
|
|
if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0) |
|
|
|
{ |
|
|
|
#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; |
|
|
|
if (v3_cpp_obj_query_interface(view->host, v3_run_loop_iid, &runloop) == V3_OK && runloop != nullptr) |
|
|
|
v3_cpp_obj(runloop)->unregister_timer(runloop, (v3_timer_handler**)&view->timer); |
|
|
|
v3_cpp_obj_query_interface(view->frame, v3_run_loop_iid, &runloop); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(runloop != nullptr, V3_INVALID_ARG); |
|
|
|
#endif |
|
|
|
|
|
|
|
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f; |
|
|
|
view->uivst3 = new UIVst3((v3_plugin_view**)view->self, |
|
|
|
view->host, |
|
|
|
(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); |
|
|
|
|
|
|
|
#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 |
|
|
|
|
|
|
|
view->timer = nullptr; |
|
|
|
return V3_OK; |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
view->uivst3 = nullptr; |
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
}; |
|
|
|
|
|
|
|
view.on_wheel = []V3_API(void* self, float distance) -> v3_result |
|
|
|
static V3_API v3_result removed(void* self) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::removed => %p", self); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
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 |
|
|
|
// unregister our timer as needed |
|
|
|
if (view->timer != nullptr) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_wheel => %p %f", self, distance); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
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(runloop)->unregister_timer(runloop, (v3_timer_handler**)&view->timer); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
view->timer = nullptr; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
return uivst3->onWheel(distance); |
|
|
|
}; |
|
|
|
view->uivst3 = nullptr; |
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
|
|
|
|
view.on_key_down = []V3_API(void* self, int16_t key_char, int16_t key_code, int16_t modifiers) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_key_down => %p %i %i %i", self, key_char, key_code, modifiers); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
static V3_API v3_result on_wheel(void* self, float distance) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_wheel => %p %f", self, distance); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
return uivst3->onKeyDown(key_char, key_code, modifiers); |
|
|
|
}; |
|
|
|
return uivst3->onWheel(distance); |
|
|
|
}; |
|
|
|
|
|
|
|
view.on_key_up = []V3_API(void* self, int16_t key_char, int16_t key_code, int16_t modifiers) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_key_up => %p %i %i %i", self, key_char, key_code, modifiers); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
static V3_API v3_result on_key_down(void* self, int16_t key_char, int16_t key_code, int16_t modifiers) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_key_down => %p %i %i %i", self, key_char, key_code, modifiers); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
return uivst3->onKeyUp(key_char, key_code, modifiers); |
|
|
|
}; |
|
|
|
return uivst3->onKeyDown(key_char, key_code, modifiers); |
|
|
|
}; |
|
|
|
|
|
|
|
view.get_size = []V3_API(void* self, v3_view_rect* rect) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::get_size => %p", self); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
static V3_API v3_result on_key_up(void* self, int16_t key_char, int16_t key_code, int16_t modifiers) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_key_up => %p %i %i %i", self, key_char, key_code, modifiers); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
if (UIVst3* const uivst3 = view->uivst3) |
|
|
|
return uivst3->getSize(rect); |
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
// special case: allow UI to not be attached yet, as a way to get size before window creation |
|
|
|
return uivst3->onKeyUp(key_char, key_code, modifiers); |
|
|
|
}; |
|
|
|
|
|
|
|
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f; |
|
|
|
UIExporter tmpUI(nullptr, 0, view->sampleRate, |
|
|
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, |
|
|
|
view->instancePointer, scaleFactor); |
|
|
|
rect->right = tmpUI.getWidth(); |
|
|
|
rect->bottom = tmpUI.getHeight(); |
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
static V3_API v3_result get_size(void* self, v3_view_rect* rect) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::get_size => %p", self); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
view.on_size = []V3_API(void* self, v3_view_rect* rect) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_size => %p %p", self, rect); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
if (UIVst3* const uivst3 = view->uivst3) |
|
|
|
return uivst3->getSize(rect); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
// special case: allow UI to not be attached yet, as a way to get size before window creation |
|
|
|
|
|
|
|
return uivst3->onSize(rect); |
|
|
|
}; |
|
|
|
const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f; |
|
|
|
UIExporter tmpUI(nullptr, 0, view->sampleRate, |
|
|
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, |
|
|
|
view->instancePointer, scaleFactor); |
|
|
|
rect->right = tmpUI.getWidth(); |
|
|
|
rect->bottom = tmpUI.getHeight(); |
|
|
|
return V3_OK; |
|
|
|
}; |
|
|
|
|
|
|
|
view.on_focus = []V3_API(void* self, v3_bool state) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_focus => %p %u", self, state); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
static V3_API v3_result on_size(void* self, v3_view_rect* rect) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_size => %p %p", self, rect); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
return uivst3->onFocus(state); |
|
|
|
}; |
|
|
|
return uivst3->onSize(rect); |
|
|
|
}; |
|
|
|
|
|
|
|
view.set_frame = []V3_API(void* self, v3_plugin_frame** frame) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::set_frame => %p %p", self, frame); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
static V3_API v3_result on_focus(void* self, v3_bool state) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::on_focus => %p %u", self, state); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
view->frame = frame; |
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
if (UIVst3* const uivst3 = view->uivst3) |
|
|
|
return uivst3->setFrame(frame); |
|
|
|
return uivst3->onFocus(state); |
|
|
|
}; |
|
|
|
|
|
|
|
return V3_NOT_INITIALISED; |
|
|
|
}; |
|
|
|
static V3_API v3_result set_frame(void* self, v3_plugin_frame** frame) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::set_frame => %p %p", self, frame); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
view.can_resize = []V3_API(void* self) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::can_resize => %p", self); |
|
|
|
view->frame = frame; |
|
|
|
|
|
|
|
if (UIVst3* const uivst3 = view->uivst3) |
|
|
|
return uivst3->setFrame(frame); |
|
|
|
|
|
|
|
return V3_NOT_INITIALIZED; |
|
|
|
}; |
|
|
|
|
|
|
|
static V3_API v3_result can_resize(void* self) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::can_resize => %p", self); |
|
|
|
// #if DISTRHO_UI_USER_RESIZABLE |
|
|
|
// return V3_OK; |
|
|
|
// #else |
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
return V3_NOT_IMPLEMENTED; |
|
|
|
// #endif |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
view.check_size_constraint = []V3_API(void* self, v3_view_rect* rect) -> v3_result |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::check_size_constraint => %p %p", self, rect); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); |
|
|
|
static V3_API v3_result check_size_constraint(void* self, v3_view_rect* rect) |
|
|
|
{ |
|
|
|
d_stdout("dpf_plugin_view::check_size_constraint => %p %p", self, rect); |
|
|
|
dpf_plugin_view* const view = *(dpf_plugin_view**)self; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALISED); |
|
|
|
UIVst3* const uivst3 = view->uivst3; |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(uivst3 != nullptr, V3_NOT_INITIALIZED); |
|
|
|
|
|
|
|
return uivst3->checkSizeConstraint(rect); |
|
|
|
}; |
|
|
|
} |
|
|
|
return uivst3->checkSizeConstraint(rect); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|