Browse Source

VST3: Start handling UI->DSP messages, WIP

Signed-off-by: falkTX <falktx@falktx.com>
pull/330/head
falkTX 4 years ago
parent
commit
e41e03f724
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
4 changed files with 457 additions and 75 deletions
  1. +216
    -35
      distrho/src/DistrhoPluginVST3.cpp
  2. +173
    -40
      distrho/src/DistrhoUIVST3.cpp
  3. +13
    -0
      distrho/src/travesty/edit_controller.h
  4. +55
    -0
      distrho/src/travesty/message.h

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

@@ -21,6 +21,7 @@
#include "travesty/component.h"
#include "travesty/edit_controller.h"
#include "travesty/factory.h"
#include "travesty/message.h"

#include <atomic>
#include <vector>
@@ -89,8 +90,49 @@ static dpf_tuid dpf_tuid_view = { dpf_id_entry, dpf_id_view, 0, 0 };

const char* tuid2str(const v3_tuid iid)
{
static constexpr const struct {
v3_tuid iid;
const char* name;
} extra_known_iids[] = {
{ V3_ID(0x00000000,0x00000000,0x00000000,0x00000000), "(nil)" },
// edit-controller
{ V3_ID(0xF040B4B3,0xA36045EC,0xABCDC045,0xB4D5A2CC), "{v3_component_handler2|NOT}" },
{ V3_ID(0x7F4EFE59,0xF3204967,0xAC27A3AE,0xAFB63038), "{v3_edit_controller2|NOT}" },
{ V3_ID(0x067D02C1,0x5B4E274D,0xA92D90FD,0x6EAF7240), "{v3_component_handler_bus_activation|NOT}" },
{ V3_ID(0xDF0FF9F7,0x49B74669,0xB63AB732,0x7ADBF5E5), "{v3_midi_mapping|NOT}" },
{ V3_ID(0xC1271208,0x70594098,0xB9DD34B3,0x6BB0195E), "{v3_edit_controller_host_editing|NOT}" },
// units
{ V3_ID(0x8683B01F,0x7B354F70,0xA2651DEC,0x353AF4FF), "{v3_program_list_data|NOT}" },
{ V3_ID(0x6C389611,0xD391455D,0xB870B833,0x94A0EFDD), "{v3_unit_data|NOT}" },
{ V3_ID(0x4B5147F8,0x4654486B,0x8DAB30BA,0x163A3C56), "{v3_unit_handler|NOT}" },
{ V3_ID(0xF89F8CDF,0x699E4BA5,0x96AAC9A4,0x81452B01), "{v3_unit_handler2|NOT}" },
{ V3_ID(0x3D4BD6B5,0x913A4FD2,0xA886E768,0xA5EB92C1), "{v3_unit_info|NOT}" },
// misc
{ V3_ID(0x0F194781,0x8D984ADA,0xBBA0C1EF,0xC011D8D0), "{v3_info_listener|NOT}" },
};

if (v3_tuid_match(iid, v3_audio_processor_iid))
return "{v3_audio_processor}";
if (v3_tuid_match(iid, v3_bstream_iid))
return "{v3_bstream}";
if (v3_tuid_match(iid, v3_component_iid))
return "{v3_component}";
if (v3_tuid_match(iid, v3_component_handler_iid))
return "{v3_component_handler}";
if (v3_tuid_match(iid, v3_connection_point_iid))
return "{v3_connection_point_iid}";
if (v3_tuid_match(iid, v3_edit_controller_iid))
return "{v3_edit_controller}";
if (v3_tuid_match(iid, v3_event_list_iid))
return "{v3_event_list}";
if (v3_tuid_match(iid, v3_funknown_iid))
return "{v3_funknown}";
if (v3_tuid_match(iid, v3_message_iid))
return "{v3_message_iid}";
if (v3_tuid_match(iid, v3_param_value_queue_iid))
return "{v3_param_value_queue}";
if (v3_tuid_match(iid, v3_param_changes_iid))
return "{v3_param_changes}";
if (v3_tuid_match(iid, v3_plugin_base_iid))
return "{v3_plugin_base}";
if (v3_tuid_match(iid, v3_plugin_factory_iid))
@@ -99,32 +141,17 @@ const char* tuid2str(const v3_tuid iid)
return "{v3_plugin_factory_2}";
if (v3_tuid_match(iid, v3_plugin_factory_3_iid))
return "{v3_plugin_factory_3}";
if (v3_tuid_match(iid, v3_component_iid))
return "{v3_component}";
if (v3_tuid_match(iid, v3_bstream_iid))
return "{v3_bstream}";
if (v3_tuid_match(iid, v3_event_list_iid))
return "{v3_event_list}";
if (v3_tuid_match(iid, v3_param_value_queue_iid))
return "{v3_param_value_queue}";
if (v3_tuid_match(iid, v3_param_changes_iid))
return "{v3_param_changes}";
if (v3_tuid_match(iid, v3_process_context_requirements_iid))
return "{v3_process_context_requirements}";
if (v3_tuid_match(iid, v3_audio_processor_iid))
return "{v3_audio_processor}";
if (v3_tuid_match(iid, v3_component_handler_iid))
return "{v3_component_handler}";
if (v3_tuid_match(iid, v3_edit_controller_iid))
return "{v3_edit_controller}";
if (v3_tuid_match(iid, v3_plugin_view_iid))
return "{v3_plugin_view}";
if (v3_tuid_match(iid, v3_plugin_frame_iid))
return "{v3_plugin_frame}";
if (v3_tuid_match(iid, v3_plugin_view_iid))
return "{v3_plugin_view}";
if (v3_tuid_match(iid, v3_plugin_view_content_scale_iid))
return "{v3_plugin_view_content_scale_iid}";
if (v3_tuid_match(iid, v3_plugin_view_parameter_finder_iid))
return "{v3_plugin_view_parameter_finder}";
if (v3_tuid_match(iid, v3_process_context_requirements_iid))
return "{v3_process_context_requirements}";

if (std::memcmp(iid, dpf_tuid_class, sizeof(dpf_tuid)) == 0)
return "{dpf_tuid_class}";
if (std::memcmp(iid, dpf_tuid_component, sizeof(dpf_tuid)) == 0)
@@ -136,6 +163,12 @@ const char* tuid2str(const v3_tuid iid)
if (std::memcmp(iid, dpf_tuid_view, sizeof(dpf_tuid)) == 0)
return "{dpf_tuid_view}";

for (size_t i=0; i<ARRAY_SIZE(extra_known_iids); ++i)
{
if (v3_tuid_match(iid, extra_known_iids[i].iid))
return extra_known_iids[i].name;
}

static char buf[46];
std::snprintf(buf, sizeof(buf), "{0x%08X,0x%08X,0x%08X,0x%08X}",
(uint32_t)d_cconst(iid[ 0], iid[ 1], iid[ 2], iid[ 3]),
@@ -1238,6 +1271,17 @@ public:
}

// ----------------------------------------------------------------------------------------------------------------
// dpf_connection_point

v3_result notify(v3_message** const message)
{
d_stdout("notify received %p -> %s", message, v3_cpp_obj(message)->get_message_id(message));
// TESTING, ensure host gets the message
requestParameterValueChange(2, 1.0f);
return V3_OK;
}

// ----------------------------------------------------------------------------------------------------------------

private:
// Plugin
@@ -1309,13 +1353,15 @@ private:
{
DISTRHO_SAFE_ASSERT_RETURN(fComponentHandler != nullptr, false);

if (v3_cpp_obj(fComponentHandler)->begin_edit(fComponentHandler, index) != V3_OK)
const uint32_t rindex = index + fParameterOffset;

if (v3_cpp_obj(fComponentHandler)->begin_edit(fComponentHandler, rindex) != V3_OK)
return false;

const double normalized = fPlugin.getParameterRanges(index).getNormalizedValue(value);
const bool ret = v3_cpp_obj(fComponentHandler)->perform_edit(fComponentHandler, index, normalized) == V3_OK;
const bool ret = v3_cpp_obj(fComponentHandler)->perform_edit(fComponentHandler, rindex, normalized) == V3_OK;

v3_cpp_obj(fComponentHandler)->end_edit(fComponentHandler, index);
v3_cpp_obj(fComponentHandler)->end_edit(fComponentHandler, rindex);
return ret;
}

@@ -1395,10 +1441,99 @@ private:
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (called from DSP side)

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

// --------------------------------------------------------------------------------------------------------------------
// dpf_connection_point

struct v3_connection_point_cpp : v3_funknown {
v3_connection_point point;
};

struct dpf_connection_point : v3_connection_point_cpp {
ScopedPointer<PluginVst3>& vst3;
const bool controller; // component otherwise
bool connected;

dpf_connection_point(const bool isEditCtrl, ScopedPointer<PluginVst3>& v)
: vst3(v),
controller(isEditCtrl),
connected(false)
{
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_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_connection_point::connect => %p %p", self, other);
dpf_connection_point* const point = *(dpf_connection_point**)self;
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);

const bool connected = point->connected;
DISTRHO_SAFE_ASSERT_RETURN(! connected, V3_INVALID_ARG);

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;
DISTRHO_SAFE_ASSERT_RETURN(point != nullptr, V3_NOT_INITIALISED);

const bool connected = point->connected;
DISTRHO_SAFE_ASSERT_RETURN(connected, V3_INVALID_ARG);

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;
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);
};
}
};

// --------------------------------------------------------------------------------------------------------------------
// dpf_edit_controller

@@ -1408,6 +1543,7 @@ struct v3_edit_controller_cpp : v3_funknown {
};

struct dpf_edit_controller : v3_edit_controller_cpp {
ScopedPointer<dpf_connection_point> connection;
ScopedPointer<PluginVst3>& vst3;
bool initialized;
// cached values
@@ -1418,7 +1554,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
initialized(false),
handler(nullptr)
{
static const uint8_t* kSupportedInterfaces[] = {
static const uint8_t* kSupportedInterfacesBase[] = {
v3_funknown_iid,
v3_edit_controller_iid
};
@@ -1432,7 +1568,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
*iface = NULL;
DISTRHO_SAFE_ASSERT_RETURN(self != nullptr, V3_NO_INTERFACE);

for (const uint8_t* interface_iid : kSupportedInterfaces)
for (const uint8_t* interface_iid : kSupportedInterfacesBase)
{
if (v3_tuid_match(interface_iid, iid))
{
@@ -1441,6 +1577,17 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
}
}

dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, V3_NO_INTERFACE);

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;
return V3_OK;
}

return V3_NO_INTERFACE;
};

@@ -1527,7 +1674,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {

controller.get_parameter_count = []V3_API(void* self) -> int32_t
{
d_stdout("dpf_edit_controller::get_parameter_count => %p", self);
// d_stdout("dpf_edit_controller::get_parameter_count => %p", self);
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, V3_NOT_INITIALISED);

@@ -1539,7 +1686,7 @@ struct dpf_edit_controller : v3_edit_controller_cpp {

controller.get_parameter_info = []V3_API(void* self, int32_t param_idx, v3_param_info* param_info) -> v3_result
{
d_stdout("dpf_edit_controller::get_parameter_info => %p %i", self, param_idx);
// d_stdout("dpf_edit_controller::get_parameter_info => %p %i", self, param_idx);
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, V3_NOT_INITIALISED);

@@ -1651,14 +1798,39 @@ struct dpf_edit_controller : v3_edit_controller_cpp {
dpf_edit_controller* const controller = *(dpf_edit_controller**)self;
DISTRHO_SAFE_ASSERT_RETURN(controller != nullptr, nullptr);

PluginVst3* const vst3 = controller->vst3;
DISTRHO_SAFE_ASSERT_RETURN(vst3 != nullptr, nullptr);
// 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);

if (controller->connection != nullptr)
{
// if there is a connection point alreay 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;
}

void* instancePointer;
double sampleRate;

if (PluginVst3* const vst3 = controller->vst3)
{
instancePointer = vst3->getInstancePointer();
sampleRate = vst3->getSampleRate();
}
else
{
instancePointer = nullptr;
sampleRate = 44100.0;
}

#if DISTRHO_PLUGIN_HAS_UI
return (v3_plugin_view**)dpf_plugin_view_create((v3_edit_controller**)self,
controller->handler,
vst3->getInstancePointer(),
vst3->getSampleRate());
return (v3_plugin_view**)dpf_plugin_view_create((v3_connection_point**)&controller->connection,
instancePointer, sampleRate);
#else
return nullptr;
#endif
@@ -1990,6 +2162,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_edit_controller> controller;
// ScopedPointer<dpf_state_stream> stream;
ScopedPointer<PluginVst3> vst3;
@@ -2032,6 +2205,14 @@ struct dpf_component : v3_component_cpp {
return V3_OK;
}

if (v3_tuid_match(v3_connection_point_iid, iid))
{
if (component->connection == nullptr)
component->connection = new dpf_connection_point(false, component->vst3);
*iface = &component->connection;
return V3_OK;
}

if (v3_tuid_match(v3_edit_controller_iid, iid))
{
if (component->controller == nullptr)


+ 173
- 40
distrho/src/DistrhoUIVST3.cpp View File

@@ -39,6 +39,7 @@
// #endif

#include "travesty/edit_controller.h"
#include "travesty/message.h"
#include "travesty/view.h"

/* TODO items:
@@ -69,6 +70,21 @@ static constexpr const setStateFunc setStateCallback = nullptr;

const char* tuid2str(const v3_tuid iid);

// --------------------------------------------------------------------------------------------------------------------
// dpf_message (needed by the UI class, implementation comes later)

struct v3_message_cpp : v3_funknown {
v3_message msg;
};

// NOTE value type must be POD
template<typename T>
struct dpf_message : v3_message_cpp {
dpf_message(ScopedPointer<dpf_message>* self, const char* id, T value);
struct PrivateData;
PrivateData* const pData;
};

// --------------------------------------------------------------------------------------------------------------------

/**
@@ -77,14 +93,17 @@ const char* tuid2str(const v3_tuid iid);
* All the dynamic things from VST3 get implemented here, free of complex low-level VST3 pointer things.
* The UI is created during the "attach" view event, and destroyed during "removed".
*
* Note that DPF VST3 implementation works over the connection point interface,
* rather than using edit controller directly.
* This allows the UI to be running remotely from the DSP.
*
* The low-level VST3 stuff comes after.
*/
class UIVst3 : public Thread
{
public:
UIVst3(v3_plugin_view** const view,
v3_edit_controller** const controller,
v3_component_handler** const handler,
v3_connection_point** const connection,
const intptr_t winId,
const float scaleFactor,
const double sampleRate,
@@ -100,8 +119,7 @@ public:
instancePointer,
scaleFactor),
fView(view),
fController(controller),
fHandler(handler),
fConnection(connection),
fFrame(nullptr),
fScaleFactor(scaleFactor)
{
@@ -211,21 +229,23 @@ private:

// VST3 stuff
v3_plugin_view** const fView;
v3_edit_controller** const fController;
v3_component_handler** const fHandler;
v3_connection_point** const fConnection;
v3_plugin_frame** fFrame;

// Temporary data
float fScaleFactor;

void editParameter(const uint32_t rindex, const bool started) const
// ----------------------------------------------------------------------------------------------------------------
// DPF callbacks

void editParameter(const uint32_t /*rindex*/, const bool /*started*/) const
{
DISTRHO_SAFE_ASSERT_RETURN(fHandler != nullptr,);
// 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);
// 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 rindex, bool started)
@@ -235,11 +255,17 @@ private:

void setParameterValue(const uint32_t rindex, const float realValue)
{
DISTRHO_SAFE_ASSERT_RETURN(fController != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fHandler != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(fConnection != nullptr,);
d_stdout("setParameterValue %p %u %f", this, rindex, realValue);

struct IndexAndValue {
uint32_t index;
float value;
};
ScopedPointer<dpf_message<IndexAndValue>>* const messageptr = new ScopedPointer<dpf_message<IndexAndValue>>;
*messageptr = new dpf_message<IndexAndValue>(messageptr, "parameter-value-set", { rindex, realValue });

const double value = v3_cpp_obj(fController)->plain_parameter_to_normalised(fController, rindex, realValue);
v3_cpp_obj(fHandler)->perform_edit(fHandler, rindex, value);
v3_cpp_obj(fConnection)->notify(fConnection, (v3_message**)messageptr);
}

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
@@ -253,17 +279,17 @@ private:
DISTRHO_SAFE_ASSERT_RETURN(fFrame != nullptr,);
d_stdout("from UI setSize %u %u | %p %p", width, height, fView, fFrame);

#ifdef DISTRHO_OS_MAC
const double scaleFactor = fUI.getScaleFactor();
width /= scaleFactor;
height /= scaleFactor;
#endif
v3_view_rect rect;
std::memset(&rect, 0, sizeof(rect));
rect.right = width;
rect.bottom = height;
v3_cpp_obj(fFrame)->resize_view(fFrame, fView, &rect);
// #ifdef DISTRHO_OS_MAC
// const double scaleFactor = fUI.getScaleFactor();
// width /= scaleFactor;
// height /= scaleFactor;
// #endif
//
// v3_view_rect rect;
// std::memset(&rect, 0, sizeof(rect));
// rect.right = width;
// rect.bottom = height;
// v3_cpp_obj(fFrame)->resize_view(fFrame, fView, &rect);
}

static void setSizeCallback(void* ptr, uint width, uint height)
@@ -307,6 +333,118 @@ private:
* VST3 low-level pointer thingies follow, proceed with care.
*/

// --------------------------------------------------------------------------------------------------------------------
// dpf_message (implementation only, declaration already done as needed by UI class)

template<typename T>
struct dpf_message<T>::PrivateData {
std::atomic<int> refcounter;
ScopedPointer<dpf_message>* self;
String id;
const T value;

PrivateData(ScopedPointer<dpf_message>* const s, const char* const id2, T value2)
: refcounter(1),
self(s),
id(id2),
value(value2) {}
};

static V3_API v3_result dpf_message__query_interface(void* self, const v3_tuid iid, void** iface)
{
d_stdout("dpf_message::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_message_iid
};

for (const uint8_t* interface_iid : kSupportedInterfaces)
{
if (v3_tuid_match(interface_iid, iid))
{
*iface = self;
return V3_OK;
}
}

return V3_NO_INTERFACE;
}

template<typename T>
static V3_API uint32_t dpf_message__ref(void* const self)
{
d_stdout("dpf_message::ref => %p", self);
dpf_message<T>* const message = *(dpf_message<T>**)self;
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, 0);

return ++message->pData->refcounter;
}

template<typename T>
static V3_API uint32_t dpf_message__unref(void* const self)
{
d_stdout("dpf_message::unref => %p", self);
dpf_message<T>* const message = *(dpf_message<T>**)self;
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, 0);

if (const int refcounter = --message->pData->refcounter)
return refcounter;

dpf_message<T>* const messageptr = message->pData->self->release();
delete message->pData;
delete messageptr;
delete (dpf_message<T>**)self;
return 0;
}

template<typename T>
static V3_API const char* dpf_message__get_message_id(void* const self)
{
d_stdout("dpf_message::get_message_id => %p", self);
dpf_message<T>* const message = *(dpf_message<T>**)self;
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, nullptr);

return message->pData->id;
}

template<typename T>
static V3_API void dpf_message__set_message_id(void* const self, const char* const id)
{
d_stdout("dpf_message::set_message_id => %p %s", self, id);
dpf_message<T>* const message = *(dpf_message<T>**)self;
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,);

message->pData->id = id;
}

template<typename T>
static V3_API v3_attribute_list* dpf_message__get_attributes(void* const self)
{
d_stdout("dpf_message::get_attributes => %p", self);
dpf_message<T>* const message = *(dpf_message<T>**)self;
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, nullptr);

// TODO
return nullptr;
}

template<typename T>
dpf_message<T>::dpf_message(ScopedPointer<dpf_message>* const self, const char* const id, const T value)
: pData(new PrivateData(self, id, value))
{
query_interface = dpf_message__query_interface;
ref = dpf_message__ref<T>;
unref = dpf_message__unref<T>;
msg.get_message_id = dpf_message__get_message_id<T>;
msg.set_message_id = dpf_message__set_message_id<T>;
msg.get_attributes = dpf_message__get_attributes<T>;
}

template struct dpf_message<float>;

// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_content_scale

@@ -390,21 +528,18 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
ScopedPointer<dpf_plugin_view_content_scale> scale;
ScopedPointer<UIVst3> uivst3;
// cached values
v3_edit_controller** const controller;
v3_component_handler** const handler;
v3_connection_point** const connection;
void* const instancePointer;
double sampleRate;
v3_plugin_frame** frame = nullptr;

dpf_plugin_view(ScopedPointer<dpf_plugin_view>* selfptr,
v3_edit_controller** const controllerptr,
v3_component_handler** const handlerptr,
v3_connection_point** const connectionptr,
void* const instance,
const double sr)
: refcounter(1),
self(selfptr),
controller(controllerptr),
handler(handlerptr),
connection(connectionptr),
instancePointer(instance),
sampleRate(sr)
{
@@ -508,9 +643,8 @@ 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((v3_plugin_view**)self,
view->controller,
view->handler,
view->uivst3 = new UIVst3((v3_plugin_view**)view->self,
view->connection,
(uintptr_t)parent,
scaleFactor,
view->sampleRate,
@@ -654,14 +788,13 @@ struct dpf_plugin_view : v3_plugin_view_cpp {
// --------------------------------------------------------------------------------------------------------------------
// dpf_plugin_view_create (called from plugin side)

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

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



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

@@ -26,6 +26,19 @@
* component handler
*/

enum {
V3_RESTART_RELOAD_COMPONENT = 1 << 0,
V3_RESTART_IO_CHANGED = 1 << 1,
V3_RESTART_PARAM_VALUES_CHANGED = 1 << 2,
V3_RESTART_LATENCY_CHANGED = 1 << 3,
V3_RESTART_PARAM_TITLES_CHANGED = 1 << 4,
V3_RESTART_MIDI_CC_ASSIGNMENT_CHANGED = 1 << 5,
V3_RESTART_NOTE_EXPRESSION_CHANGED = 1 << 6,
V3_RESTART_IO_TITLES_CHANGED = 1 << 7,
V3_RESTART_PREFETCHABLE_SUPPORT_CHANGED = 1 << 8,
V3_RESTART_ROUTING_INFO_CHANGED = 1 << 9
};

struct v3_component_handler {
struct v3_funknown;



+ 55
- 0
distrho/src/travesty/message.h View File

@@ -0,0 +1,55 @@
/*
* travesty, pure C VST3-compatible interface
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#pragma once

#include "base.h"

#include "align_push.h"

/**
* message
*/

struct v3_attribute_list;

struct v3_message {
struct v3_funknown;

V3_API const char* (*get_message_id)(void* self);
V3_API void (*set_message_id)(void* self, const char* id);
V3_API v3_attribute_list* (*get_attributes)(void* self);
};

static constexpr const v3_tuid v3_message_iid =
V3_ID(0x936F033B, 0xC6C047DB, 0xBB0882F8, 0x13C1E613);

/**
* connection point
*/

struct v3_connection_point {
struct v3_funknown;

V3_API v3_result (*connect)(void* self, struct v3_connection_point** other);
V3_API v3_result (*disconnect)(void* self, struct v3_connection_point** other);
V3_API v3_result (*notify)(void* self, struct v3_message** message);
};

static constexpr const v3_tuid v3_connection_point_iid =
V3_ID(0x70A4156F, 0x6E6E4026, 0x989148BF, 0xAA60D8D1);

#include "align_pop.h"

Loading…
Cancel
Save