Signed-off-by: falkTX <falktx@falktx.com>pull/330/head
@@ -38,6 +38,8 @@ | |||
#include "travesty/message.h" | |||
#include <atomic> | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
/* TODO items: | |||
@@ -269,7 +271,22 @@ 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 | |||
// 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); | |||
}; | |||
static constexpr const v3_tuid v3_attribute_list_utf8_iid = | |||
V3_ID(d_cconst('D','P','F',' '), | |||
d_cconst('c','l','a','s'), | |||
d_cconst('a','t','t','r'), | |||
d_cconst('u','t','f','8')); | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// create message object (implementation comes later) | |||
v3_message** dpf_message_create(const char* id); | |||
@@ -1593,6 +1610,388 @@ private: | |||
v3_plugin_view** dpf_plugin_view_create(void* instancePointer, double sampleRate); | |||
#endif | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
struct dpf_attribute_value { | |||
char type; // one of: i, f, s, b | |||
union { | |||
int64_t integer; | |||
double v_float; | |||
int16_t* string; | |||
struct { | |||
void* ptr; | |||
uint32_t size; | |||
} binary; | |||
}; | |||
}; | |||
static void dpf_attribute_list_free(std::map<std::string, dpf_attribute_value>& attrs) | |||
{ | |||
for (auto& it : attrs) | |||
{ | |||
dpf_attribute_value& v(it.second); | |||
switch (v.type) | |||
{ | |||
case 's': | |||
case 'b': | |||
std::free(v.binary.ptr); | |||
break; | |||
} | |||
} | |||
} | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_attribute_list_utf8 (the custom variant) | |||
struct v3_attribute_list_utf8_cpp : v3_funknown { | |||
v3_attribute_list_utf8 attr; | |||
}; | |||
struct dpf_attribute_list_utf8 : v3_attribute_list_utf8_cpp { | |||
std::map<std::string, dpf_attribute_value>& attrs; | |||
dpf_attribute_list_utf8(std::map<std::string, dpf_attribute_value>& a) | |||
: attrs(a) | |||
{ | |||
static const uint8_t* kSupportedInterfaces[] = { | |||
v3_funknown_iid, | |||
v3_attribute_list_utf8_iid | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------ | |||
// v3_funknown | |||
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result | |||
{ | |||
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); | |||
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_attribute_list_utf8 | |||
attr.set_string_utf8 = []V3_API(void* self, const char* id, const char* string) -> v3_result | |||
{ | |||
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; | |||
int16_t* const copy = (int16_t*)std::malloc(sizeof(int16_t) * size); | |||
DISTRHO_SAFE_ASSERT_RETURN(copy != nullptr, V3_NOMEM); | |||
DISTRHO_NAMESPACE::strncpy_utf16(copy, string, size); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 's'; | |||
attrval.binary.ptr = copy; | |||
attrval.binary.size = sizeof(int16_t) * size; | |||
return V3_OK; | |||
}; | |||
attr.get_string_utf8 = []V3_API(void* self, const char* id, char*, uint32_t) -> v3_result | |||
{ | |||
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()) | |||
return V3_INVALID_ARG; | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
} | |||
}; | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_attribute_list | |||
struct dpf_attribute_list : v3_attribute_list_cpp { | |||
ScopedPointer<dpf_attribute_list_utf8> attrutf8; | |||
std::map<std::string, dpf_attribute_value> attrs; | |||
dpf_attribute_list() | |||
{ | |||
static const uint8_t* kSupportedInterfacesBase[] = { | |||
v3_funknown_iid, | |||
v3_attribute_list_iid | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------ | |||
// v3_funknown | |||
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result | |||
{ | |||
d_stdout("dpf_attribute_list::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 : kSupportedInterfacesBase) | |||
{ | |||
if (v3_tuid_match(interface_iid, iid)) | |||
{ | |||
*iface = self; | |||
return V3_OK; | |||
} | |||
} | |||
dpf_attribute_list* const attr = *(dpf_attribute_list**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NO_INTERFACE); | |||
if (v3_tuid_match(v3_attribute_list_utf8_iid, iid)) | |||
{ | |||
if (attr->attrutf8 == nullptr) | |||
attr->attrutf8 = new dpf_attribute_list_utf8(attr->attrs); | |||
*iface = &attr->attrutf8; | |||
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_attribute_list | |||
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); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 'i'; | |||
attrval.integer = value; | |||
return V3_OK; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 'i', V3_INVALID_ARG); | |||
*value = attrval.integer; | |||
return V3_OK; | |||
}; | |||
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); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 'f'; | |||
attrval.v_float = value; | |||
return V3_OK; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 'f', V3_INVALID_ARG); | |||
*value = attrval.v_float; | |||
return V3_OK; | |||
}; | |||
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); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 's'; | |||
attrval.binary.ptr = nullptr; | |||
attrval.binary.size = 0; | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 's', V3_INVALID_ARG); | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
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); | |||
void* const copy = std::malloc(size); | |||
DISTRHO_SAFE_ASSERT_RETURN(copy != nullptr, V3_NOMEM); | |||
std::memcpy(copy, data, size); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 'b'; | |||
attrval.binary.ptr = copy; | |||
attrval.binary.size = size; | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 's' || attrval.type == 'b', V3_INVALID_ARG); | |||
*data = attrval.binary.ptr; | |||
*size = attrval.binary.size; | |||
return V3_OK; | |||
}; | |||
} | |||
}; | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_message | |||
struct dpf_message : v3_message_cpp { | |||
std::atomic<int> refcounter; | |||
ScopedPointer<dpf_message>* self; | |||
ScopedPointer<dpf_attribute_list> attrlist; | |||
String id; | |||
dpf_message(ScopedPointer<dpf_message>* const s, const char* const id2) | |||
: self(s), | |||
id(id2) | |||
{ | |||
static const uint8_t* kSupportedInterfaces[] = { | |||
v3_funknown_iid, | |||
v3_message_iid | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------ | |||
// v3_funknown | |||
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); | |||
for (const uint8_t* interface_iid : kSupportedInterfaces) | |||
{ | |||
if (v3_tuid_match(interface_iid, iid)) | |||
{ | |||
*iface = self; | |||
return V3_OK; | |||
} | |||
} | |||
return V3_NO_INTERFACE; | |||
}; | |||
ref = []V3_API(void* const self) -> uint32_t | |||
{ | |||
d_stdout("dpf_message::ref => %p", self); | |||
dpf_message** const messageptr = static_cast<dpf_message**>(self); | |||
DISTRHO_SAFE_ASSERT_RETURN(messageptr != nullptr, 0); | |||
dpf_message* const message = *messageptr; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, 0); | |||
return ++message->refcounter; | |||
}; | |||
unref = []V3_API(void* const self) -> uint32_t | |||
{ | |||
d_stdout("dpf_message::unref => %p", self); | |||
dpf_message** const messageptr = static_cast<dpf_message**>(self); | |||
DISTRHO_SAFE_ASSERT_RETURN(messageptr != nullptr, 0); | |||
dpf_message* const message = *messageptr; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, 0); | |||
if (const int refcounter = --message->refcounter) | |||
return refcounter; | |||
if (message->attrlist != nullptr) | |||
dpf_attribute_list_free(message->attrlist->attrs); | |||
*message->self = nullptr; | |||
delete messageptr; | |||
return 0; | |||
}; | |||
msg.get_message_id = []V3_API(void* const self) -> const char* | |||
{ | |||
d_stdout("dpf_message::get_message_id => %p", self); | |||
dpf_message* const message = *(dpf_message**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, nullptr); | |||
return message->id; | |||
}; | |||
msg.set_message_id = []V3_API(void* const self, const char* const id) -> void | |||
{ | |||
d_stdout("dpf_message::set_message_id => %p %s", self, id); | |||
dpf_message* const message = *(dpf_message**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); | |||
message->id = id; | |||
}; | |||
msg.get_attributes = []V3_API(void* const self) -> v3_attribute_list** | |||
{ | |||
d_stdout("dpf_message::get_attributes => %p", self); | |||
dpf_message* const message = *(dpf_message**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, nullptr); | |||
if (message->attrlist == nullptr) | |||
message->attrlist = new dpf_attribute_list(); | |||
return (v3_attribute_list**)&message->attrlist; | |||
}; | |||
} | |||
}; | |||
v3_message** dpf_message_create(const char* const id) | |||
{ | |||
ScopedPointer<dpf_message>* const messageptr = new ScopedPointer<dpf_message>; | |||
*messageptr = new dpf_message(messageptr, id); | |||
return static_cast<v3_message**>(static_cast<void*>(messageptr)); | |||
} | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_dsp_connection_point | |||
@@ -44,10 +44,6 @@ | |||
#include "travesty/message.h" | |||
#include "travesty/view.h" | |||
#include <atomic> | |||
#include <map> | |||
#include <string> | |||
/* TODO items: | |||
* - disable UI if non-embed UI build | |||
* - sample rate change listener | |||
@@ -71,21 +67,11 @@ static constexpr const setStateFunc setStateCallback = nullptr; | |||
const char* tuid2str(const v3_tuid iid); | |||
void strncpy_utf16(int16_t* dst, const char* src, size_t length); | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// create message object (needed by the UI class, implementation comes later) | |||
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); | |||
}; | |||
static constexpr const v3_tuid v3_attribute_list_utf8_iid = | |||
V3_ID(d_cconst('D','P','F',' '), | |||
d_cconst('c','l','a','s'), | |||
@@ -466,388 +452,6 @@ private: | |||
* VST3 low-level pointer thingies follow, proceed with care. | |||
*/ | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
struct dpf_attribute_value { | |||
char type; // one of: i, f, s, b | |||
union { | |||
int64_t integer; | |||
double v_float; | |||
int16_t* string; | |||
struct { | |||
void* ptr; | |||
uint32_t size; | |||
} binary; | |||
}; | |||
}; | |||
static void dpf_attribute_list_free(std::map<std::string, dpf_attribute_value>& attrs) | |||
{ | |||
for (auto& it : attrs) | |||
{ | |||
dpf_attribute_value& v(it.second); | |||
switch (v.type) | |||
{ | |||
case 's': | |||
case 'b': | |||
std::free(v.binary.ptr); | |||
break; | |||
} | |||
} | |||
} | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_attribute_list_utf8 (the custom variant) | |||
struct v3_attribute_list_utf8_cpp : v3_funknown { | |||
v3_attribute_list_utf8 attr; | |||
}; | |||
struct dpf_attribute_list_utf8 : v3_attribute_list_utf8_cpp { | |||
std::map<std::string, dpf_attribute_value>& attrs; | |||
dpf_attribute_list_utf8(std::map<std::string, dpf_attribute_value>& a) | |||
: attrs(a) | |||
{ | |||
static const uint8_t* kSupportedInterfaces[] = { | |||
v3_funknown_iid, | |||
v3_attribute_list_utf8_iid | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------ | |||
// v3_funknown | |||
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result | |||
{ | |||
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); | |||
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_attribute_list_utf8 | |||
attr.set_string_utf8 = []V3_API(void* self, const char* id, const char* string) -> v3_result | |||
{ | |||
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; | |||
int16_t* const copy = (int16_t*)std::malloc(sizeof(int16_t) * size); | |||
DISTRHO_SAFE_ASSERT_RETURN(copy != nullptr, V3_NOMEM); | |||
DISTRHO_NAMESPACE::strncpy_utf16(copy, string, size); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 's'; | |||
attrval.binary.ptr = copy; | |||
attrval.binary.size = sizeof(int16_t) * size; | |||
return V3_OK; | |||
}; | |||
attr.get_string_utf8 = []V3_API(void* self, const char* id, char*, uint32_t) -> v3_result | |||
{ | |||
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()) | |||
return V3_INVALID_ARG; | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
} | |||
}; | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_attribute_list | |||
struct dpf_attribute_list : v3_attribute_list_cpp { | |||
ScopedPointer<dpf_attribute_list_utf8> attrutf8; | |||
std::map<std::string, dpf_attribute_value> attrs; | |||
dpf_attribute_list() | |||
{ | |||
static const uint8_t* kSupportedInterfacesBase[] = { | |||
v3_funknown_iid, | |||
v3_attribute_list_iid | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------ | |||
// v3_funknown | |||
query_interface = []V3_API(void* self, const v3_tuid iid, void** iface) -> v3_result | |||
{ | |||
d_stdout("dpf_attribute_list::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 : kSupportedInterfacesBase) | |||
{ | |||
if (v3_tuid_match(interface_iid, iid)) | |||
{ | |||
*iface = self; | |||
return V3_OK; | |||
} | |||
} | |||
dpf_attribute_list* const attr = *(dpf_attribute_list**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(attr != nullptr, V3_NO_INTERFACE); | |||
if (v3_tuid_match(v3_attribute_list_utf8_iid, iid)) | |||
{ | |||
if (attr->attrutf8 == nullptr) | |||
attr->attrutf8 = new dpf_attribute_list_utf8(attr->attrs); | |||
*iface = &attr->attrutf8; | |||
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_attribute_list | |||
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); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 'i'; | |||
attrval.integer = value; | |||
return V3_OK; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 'i', V3_INVALID_ARG); | |||
*value = attrval.integer; | |||
return V3_OK; | |||
}; | |||
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); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 'f'; | |||
attrval.v_float = value; | |||
return V3_OK; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 'f', V3_INVALID_ARG); | |||
*value = attrval.v_float; | |||
return V3_OK; | |||
}; | |||
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); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 's'; | |||
attrval.binary.ptr = nullptr; | |||
attrval.binary.size = 0; | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 's', V3_INVALID_ARG); | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
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); | |||
void* const copy = std::malloc(size); | |||
DISTRHO_SAFE_ASSERT_RETURN(copy != nullptr, V3_NOMEM); | |||
std::memcpy(copy, data, size); | |||
dpf_attribute_value& attrval(attr->attrs[id]); | |||
attrval.type = 'b'; | |||
attrval.binary.ptr = copy; | |||
attrval.binary.size = size; | |||
return V3_NOT_IMPLEMENTED; | |||
}; | |||
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); | |||
if (attr->attrs.find(id) == attr->attrs.end()) | |||
return V3_INVALID_ARG; | |||
const dpf_attribute_value& attrval(attr->attrs[id]); | |||
DISTRHO_SAFE_ASSERT_RETURN(attrval.type == 's' || attrval.type == 'b', V3_INVALID_ARG); | |||
*data = attrval.binary.ptr; | |||
*size = attrval.binary.size; | |||
return V3_OK; | |||
}; | |||
} | |||
}; | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_message | |||
struct dpf_message : v3_message_cpp { | |||
std::atomic<int> refcounter; | |||
ScopedPointer<dpf_message>* self; | |||
ScopedPointer<dpf_attribute_list> attrlist; | |||
String id; | |||
dpf_message(ScopedPointer<dpf_message>* const s, const char* const id2) | |||
: self(s), | |||
id(id2) | |||
{ | |||
static const uint8_t* kSupportedInterfaces[] = { | |||
v3_funknown_iid, | |||
v3_message_iid | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------ | |||
// v3_funknown | |||
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); | |||
for (const uint8_t* interface_iid : kSupportedInterfaces) | |||
{ | |||
if (v3_tuid_match(interface_iid, iid)) | |||
{ | |||
*iface = self; | |||
return V3_OK; | |||
} | |||
} | |||
return V3_NO_INTERFACE; | |||
}; | |||
ref = []V3_API(void* const self) -> uint32_t | |||
{ | |||
d_stdout("dpf_message::ref => %p", self); | |||
dpf_message** const messageptr = static_cast<dpf_message**>(self); | |||
DISTRHO_SAFE_ASSERT_RETURN(messageptr != nullptr, 0); | |||
dpf_message* const message = *messageptr; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, 0); | |||
return ++message->refcounter; | |||
}; | |||
unref = []V3_API(void* const self) -> uint32_t | |||
{ | |||
d_stdout("dpf_message::unref => %p", self); | |||
dpf_message** const messageptr = static_cast<dpf_message**>(self); | |||
DISTRHO_SAFE_ASSERT_RETURN(messageptr != nullptr, 0); | |||
dpf_message* const message = *messageptr; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, 0); | |||
if (const int refcounter = --message->refcounter) | |||
return refcounter; | |||
if (message->attrlist != nullptr) | |||
dpf_attribute_list_free(message->attrlist->attrs); | |||
*message->self = nullptr; | |||
delete messageptr; | |||
return 0; | |||
}; | |||
msg.get_message_id = []V3_API(void* const self) -> const char* | |||
{ | |||
d_stdout("dpf_message::get_message_id => %p", self); | |||
dpf_message* const message = *(dpf_message**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, nullptr); | |||
return message->id; | |||
}; | |||
msg.set_message_id = []V3_API(void* const self, const char* const id) -> void | |||
{ | |||
d_stdout("dpf_message::set_message_id => %p %s", self, id); | |||
dpf_message* const message = *(dpf_message**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr,); | |||
message->id = id; | |||
}; | |||
msg.get_attributes = []V3_API(void* const self) -> v3_attribute_list** | |||
{ | |||
d_stdout("dpf_message::get_attributes => %p", self); | |||
dpf_message* const message = *(dpf_message**)self; | |||
DISTRHO_SAFE_ASSERT_RETURN(message != nullptr, nullptr); | |||
if (message->attrlist == nullptr) | |||
message->attrlist = new dpf_attribute_list(); | |||
return (v3_attribute_list**)&message->attrlist; | |||
}; | |||
} | |||
}; | |||
v3_message** dpf_message_create(const char* const id) | |||
{ | |||
ScopedPointer<dpf_message>* const messageptr = new ScopedPointer<dpf_message>; | |||
*messageptr = new dpf_message(messageptr, id); | |||
return static_cast<v3_message**>(static_cast<void*>(messageptr)); | |||
} | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
// dpf_plugin_view_content_scale | |||