|
@@ -51,6 +51,7 @@ |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
#include <atomic> |
|
|
#include <atomic> |
|
|
|
|
|
#include <unordered_map> |
|
|
|
|
|
|
|
|
CARLA_BACKEND_START_NAMESPACE |
|
|
CARLA_BACKEND_START_NAMESPACE |
|
|
|
|
|
|
|
@@ -99,11 +100,273 @@ static uint32_t V3_API v3_unref_static(void*) { return 0; } |
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
struct v3_var { |
|
|
|
|
|
char type; |
|
|
|
|
|
uint32_t size; |
|
|
|
|
|
union { |
|
|
|
|
|
int64_t i; |
|
|
|
|
|
double f; |
|
|
|
|
|
int16_t* s; |
|
|
|
|
|
void* b; |
|
|
|
|
|
} value; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void v3_var_cleanup(v3_var& var) |
|
|
|
|
|
{ |
|
|
|
|
|
switch (var.type) |
|
|
|
|
|
{ |
|
|
|
|
|
case 's': |
|
|
|
|
|
std::free(var.value.s); |
|
|
|
|
|
break; |
|
|
|
|
|
case 'b': |
|
|
|
|
|
std::free(var.value.b); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
carla_zeroStruct(var); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct carla_v3_attribute_list : v3_attribute_list_cpp { |
|
|
|
|
|
// std::atomic<int> refcounter; |
|
|
|
|
|
std::unordered_map<std::string, v3_var> vars; |
|
|
|
|
|
|
|
|
|
|
|
carla_v3_attribute_list() |
|
|
|
|
|
// : refcounter(1) |
|
|
|
|
|
{ |
|
|
|
|
|
query_interface = carla_query_interface; |
|
|
|
|
|
ref = v3_ref_static; |
|
|
|
|
|
unref = v3_unref_static; |
|
|
|
|
|
attrlist.set_int = carla_set_int; |
|
|
|
|
|
attrlist.get_int = carla_get_int; |
|
|
|
|
|
attrlist.set_float = carla_set_float; |
|
|
|
|
|
attrlist.get_float = carla_get_float; |
|
|
|
|
|
attrlist.set_string = carla_set_string; |
|
|
|
|
|
attrlist.get_string = carla_get_string; |
|
|
|
|
|
attrlist.set_binary = carla_set_binary; |
|
|
|
|
|
attrlist.get_binary = carla_get_binary; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
~carla_v3_attribute_list() |
|
|
|
|
|
{ |
|
|
|
|
|
for (std::unordered_map<std::string, v3_var>::iterator it = vars.begin(); it != vars.end(); ++it) |
|
|
|
|
|
v3_var_cleanup(it->second); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
v3_result add(const char* const id, const v3_var& var) |
|
|
|
|
|
{ |
|
|
|
|
|
const std::string sid(id); |
|
|
|
|
|
|
|
|
|
|
|
for (std::unordered_map<std::string, v3_var>::iterator it = vars.begin(); it != vars.end(); ++it) |
|
|
|
|
|
{ |
|
|
|
|
|
if (it->first == sid) |
|
|
|
|
|
{ |
|
|
|
|
|
v3_var_cleanup(it->second); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vars[sid] = var; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool get(const char* const id, v3_var& var) |
|
|
|
|
|
{ |
|
|
|
|
|
const std::string sid(id); |
|
|
|
|
|
|
|
|
|
|
|
for (std::unordered_map<std::string, v3_var>::iterator it = vars.begin(); it != vars.end(); ++it) |
|
|
|
|
|
{ |
|
|
|
|
|
if (it->first == sid) |
|
|
|
|
|
{ |
|
|
|
|
|
var = it->second; |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface) |
|
|
|
|
|
{ |
|
|
|
|
|
carla_debug("%s %s %p", __PRETTY_FUNCTION__, tuid2str(iid), iface); |
|
|
|
|
|
// carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
if (v3_tuid_match(iid, v3_funknown_iid) || |
|
|
|
|
|
v3_tuid_match(iid, v3_attribute_list_iid)) |
|
|
|
|
|
{ |
|
|
|
|
|
// ++attrlist->refcounter; |
|
|
|
|
|
*iface = self; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*iface = nullptr; |
|
|
|
|
|
carla_stdout("TODO carla_v3_attribute_list::query_interface %s", tuid2str(iid)); |
|
|
|
|
|
return V3_NO_INTERFACE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
static uint32_t V3_API carla_ref(void* const self) |
|
|
|
|
|
{ |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
const int refcount = ++msg->refcounter; |
|
|
|
|
|
carla_debug("carla_v3_attribute_list::ref => %p | refcount %i", self, refcount); |
|
|
|
|
|
return refcount; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static uint32_t V3_API carla_unref(void* const self) |
|
|
|
|
|
{ |
|
|
|
|
|
carla_v3_attribute_list** const attrlistptr = static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *attrlistptr; |
|
|
|
|
|
|
|
|
|
|
|
if (const int refcount = --attrlist->refcounter) |
|
|
|
|
|
{ |
|
|
|
|
|
carla_debug("carla_v3_attribute_list::unref => %p | refcount %i", self, refcount); |
|
|
|
|
|
return refcount; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
carla_debug("carla_v3_attribute_list::unref => %p | refcount is zero, deleting factory", self); |
|
|
|
|
|
|
|
|
|
|
|
delete attrlist; |
|
|
|
|
|
delete attrlistptr; |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_set_int(void* const self, const char* const id, const int64_t value) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
var.type = 'i'; |
|
|
|
|
|
var.value.i = value; |
|
|
|
|
|
return attrlist->add(id, var); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_get_int(void* const self, const char* const id, int64_t* const value) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
if (attrlist->get(id, var)) |
|
|
|
|
|
{ |
|
|
|
|
|
*value = var.value.i; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return V3_INVALID_ARG; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_set_float(void* const self, const char* const id, const double value) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
var.type = 'f'; |
|
|
|
|
|
var.value.f = value; |
|
|
|
|
|
return attrlist->add(id, var); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_get_float(void* const self, const char* const id, double* const value) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
if (attrlist->get(id, var)) |
|
|
|
|
|
{ |
|
|
|
|
|
*value = var.value.f; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return V3_INVALID_ARG; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_set_string(void* const self, const char* const id, const int16_t* const string) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(string != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
const size_t size = sizeof(int16_t) * (strlen_utf16(string) + 1); |
|
|
|
|
|
int16_t* const s = static_cast<int16_t*>(std::malloc(size)); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(s != nullptr, V3_NOMEM); |
|
|
|
|
|
std::memcpy(s, string, size); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
var.type = 's'; |
|
|
|
|
|
var.size = size; |
|
|
|
|
|
var.value.s = s; |
|
|
|
|
|
return attrlist->add(id, var); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_get_string(void* const self, const char* const id, |
|
|
|
|
|
int16_t* const string, const uint32_t size) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(string != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(size != 0, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
if (attrlist->get(id, var)) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_UINT2_RETURN(var.size >= size, var.size, size, V3_INVALID_ARG); |
|
|
|
|
|
std::memcpy(string, var.value.s, size); |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return V3_INVALID_ARG; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_set_binary(void* const self, const char* const id, |
|
|
|
|
|
const void* const data, const uint32_t size) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(data != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(size != 0, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
void* const b = std::malloc(size); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(b != nullptr, V3_NOMEM); |
|
|
|
|
|
std::memcpy(b, data, size); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
var.type = 'b'; |
|
|
|
|
|
var.size = size; |
|
|
|
|
|
var.value.b = b; |
|
|
|
|
|
return attrlist->add(id, var); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_get_binary(void* const self, const char* const id, |
|
|
|
|
|
const void** const data, uint32_t* const size) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self); |
|
|
|
|
|
|
|
|
|
|
|
v3_var var = {}; |
|
|
|
|
|
if (attrlist->get(id, var)) |
|
|
|
|
|
{ |
|
|
|
|
|
*data = var.value.b; |
|
|
|
|
|
*size = var.size; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return V3_INVALID_ARG; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
struct carla_v3_message : v3_message_cpp { |
|
|
struct carla_v3_message : v3_message_cpp { |
|
|
std::atomic<int> refcounter; |
|
|
std::atomic<int> refcounter; |
|
|
|
|
|
carla_v3_attribute_list attrlist; |
|
|
|
|
|
carla_v3_attribute_list* attrlistptr; |
|
|
|
|
|
const char* msgId; |
|
|
|
|
|
|
|
|
carla_v3_message() |
|
|
carla_v3_message() |
|
|
: refcounter(1) |
|
|
|
|
|
|
|
|
: refcounter(1), |
|
|
|
|
|
attrlistptr(&attrlist), |
|
|
|
|
|
msgId(nullptr) |
|
|
{ |
|
|
{ |
|
|
query_interface = carla_query_interface; |
|
|
query_interface = carla_query_interface; |
|
|
ref = carla_ref; |
|
|
ref = carla_ref; |
|
@@ -113,6 +376,11 @@ struct carla_v3_message : v3_message_cpp { |
|
|
msg.get_attributes = carla_get_attributes; |
|
|
msg.get_attributes = carla_get_attributes; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
~carla_v3_message() |
|
|
|
|
|
{ |
|
|
|
|
|
delete[] msgId; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface) |
|
|
static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface) |
|
|
{ |
|
|
{ |
|
|
carla_debug("%s %s %p", __PRETTY_FUNCTION__, tuid2str(iid), iface); |
|
|
carla_debug("%s %s %p", __PRETTY_FUNCTION__, tuid2str(iid), iface); |
|
@@ -157,21 +425,23 @@ struct carla_v3_message : v3_message_cpp { |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static const char* V3_API carla_get_message_id(void*) |
|
|
|
|
|
|
|
|
static const char* V3_API carla_get_message_id(void* const self) |
|
|
{ |
|
|
{ |
|
|
carla_debug("TODO %s", __PRETTY_FUNCTION__); |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
|
|
|
carla_v3_message* const msg = *static_cast<carla_v3_message**>(self); |
|
|
|
|
|
return msg->msgId; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void V3_API carla_set_message_id(void*, const char*) |
|
|
|
|
|
|
|
|
static void V3_API carla_set_message_id(void* const self, const char* const id) |
|
|
{ |
|
|
{ |
|
|
carla_debug("TODO %s", __PRETTY_FUNCTION__); |
|
|
|
|
|
|
|
|
carla_v3_message* const msg = *static_cast<carla_v3_message**>(self); |
|
|
|
|
|
delete[] msg->msgId; |
|
|
|
|
|
msg->msgId = id != nullptr ? carla_strdup(id) : nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static v3_attribute_list** V3_API carla_get_attributes(void*) |
|
|
|
|
|
|
|
|
static v3_attribute_list** V3_API carla_get_attributes(void* const self) |
|
|
{ |
|
|
{ |
|
|
carla_debug("TODO %s", __PRETTY_FUNCTION__); |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
|
|
|
carla_v3_message* const msg = *static_cast<carla_v3_message**>(self); |
|
|
|
|
|
return (v3_attribute_list**)&msg->attrlistptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
CARLA_DECLARE_NON_COPYABLE(carla_v3_message) |
|
|
CARLA_DECLARE_NON_COPYABLE(carla_v3_message) |
|
@@ -179,6 +449,114 @@ struct carla_v3_message : v3_message_cpp { |
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
struct carla_v3_bstream : v3_bstream_cpp { |
|
|
|
|
|
void* buffer; |
|
|
|
|
|
int64_t size; |
|
|
|
|
|
int64_t pos; |
|
|
|
|
|
|
|
|
|
|
|
carla_v3_bstream() |
|
|
|
|
|
: buffer(nullptr), |
|
|
|
|
|
size(0), |
|
|
|
|
|
pos(0) |
|
|
|
|
|
{ |
|
|
|
|
|
query_interface = carla_query_interface; |
|
|
|
|
|
ref = v3_ref_static; |
|
|
|
|
|
unref = v3_unref_static; |
|
|
|
|
|
stream.read = carla_read; |
|
|
|
|
|
stream.write = carla_write; |
|
|
|
|
|
stream.seek = carla_seek; |
|
|
|
|
|
stream.tell = carla_tell; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface) |
|
|
|
|
|
{ |
|
|
|
|
|
carla_debug("%s %s %p", __PRETTY_FUNCTION__, tuid2str(iid), iface); |
|
|
|
|
|
|
|
|
|
|
|
if (v3_tuid_match(iid, v3_funknown_iid) || |
|
|
|
|
|
v3_tuid_match(iid, v3_bstream_iid)) |
|
|
|
|
|
{ |
|
|
|
|
|
*iface = self; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*iface = nullptr; |
|
|
|
|
|
carla_stdout("TODO carla_v3_bstream::query_interface %s", tuid2str(iid)); |
|
|
|
|
|
return V3_NO_INTERFACE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_read(void* const self, void* const buffer, int32_t num_bytes, int32_t* const bytes_read) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(buffer != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(num_bytes > 0, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(bytes_read != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self); |
|
|
|
|
|
|
|
|
|
|
|
if (stream->pos + num_bytes > stream->size) |
|
|
|
|
|
num_bytes = stream->size - stream->pos; |
|
|
|
|
|
|
|
|
|
|
|
std::memcpy(buffer, static_cast<uint8_t*>(stream->buffer) + stream->pos, num_bytes); |
|
|
|
|
|
stream->pos += num_bytes; |
|
|
|
|
|
*bytes_read = num_bytes; |
|
|
|
|
|
|
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_write(void* const self, |
|
|
|
|
|
void* const buffer, const int32_t num_bytes, int32_t* const bytes_read) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(buffer != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(num_bytes > 0, V3_INVALID_ARG); |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(bytes_read != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self); |
|
|
|
|
|
|
|
|
|
|
|
const int64_t size = stream->size + num_bytes; |
|
|
|
|
|
void* const oldbuffer = stream->buffer; |
|
|
|
|
|
stream->buffer = std::realloc(oldbuffer, size); // FIXME detect alloc failure |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(stream->buffer != oldbuffer, V3_NOMEM); |
|
|
|
|
|
|
|
|
|
|
|
stream->size += num_bytes; |
|
|
|
|
|
*bytes_read = num_bytes; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_seek(void* const self, const int64_t pos, const int32_t seek_mode, int64_t* const result) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(result != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self); |
|
|
|
|
|
|
|
|
|
|
|
switch (seek_mode) |
|
|
|
|
|
{ |
|
|
|
|
|
case V3_SEEK_SET: |
|
|
|
|
|
CARLA_SAFE_ASSERT_INT2_RETURN(pos <= stream->size, pos, stream->size, V3_INVALID_ARG); |
|
|
|
|
|
*result = stream->pos = pos; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
case V3_SEEK_CUR: |
|
|
|
|
|
CARLA_SAFE_ASSERT_INT2_RETURN(stream->pos + pos <= stream->size, pos, stream->size, V3_INVALID_ARG); |
|
|
|
|
|
*result = stream->pos = stream->pos + pos; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
case V3_SEEK_END: |
|
|
|
|
|
CARLA_SAFE_ASSERT_INT2_RETURN(pos <= stream->size, pos, stream->size, V3_INVALID_ARG); |
|
|
|
|
|
*result = stream->pos = stream->size - pos; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return V3_INVALID_ARG; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static v3_result carla_tell(void* const self, int64_t* const pos) |
|
|
|
|
|
{ |
|
|
|
|
|
CARLA_SAFE_ASSERT_RETURN(pos != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self); |
|
|
|
|
|
|
|
|
|
|
|
*pos = stream->pos; |
|
|
|
|
|
return V3_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CARLA_DECLARE_NON_COPYABLE(carla_v3_bstream) |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
struct carla_v3_host_application : v3_host_application_cpp { |
|
|
struct carla_v3_host_application : v3_host_application_cpp { |
|
|
carla_v3_host_application() |
|
|
carla_v3_host_application() |
|
|
{ |
|
|
{ |
|
@@ -779,13 +1157,13 @@ private: |
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
// -------------------------------------------------------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
struct carla_v3_plugin_frame : v3_plugin_frame_cpp { |
|
|
struct carla_v3_plugin_frame : v3_plugin_frame_cpp { |
|
|
|
|
|
CarlaPluginUI::Callback* const callback; |
|
|
carla_v3_run_loop loop; |
|
|
carla_v3_run_loop loop; |
|
|
carla_v3_run_loop* loopPtr; |
|
|
carla_v3_run_loop* loopPtr; |
|
|
CarlaPluginUI::Callback* uiCallback; |
|
|
|
|
|
|
|
|
|
|
|
carla_v3_plugin_frame() |
|
|
|
|
|
: loopPtr(&loop), |
|
|
|
|
|
uiCallback(nullptr) |
|
|
|
|
|
|
|
|
carla_v3_plugin_frame(CarlaPluginUI::Callback* const cb) |
|
|
|
|
|
: callback(cb), |
|
|
|
|
|
loopPtr(&loop) |
|
|
{ |
|
|
{ |
|
|
query_interface = carla_query_interface; |
|
|
query_interface = carla_query_interface; |
|
|
ref = v3_ref_static; |
|
|
ref = v3_ref_static; |
|
@@ -823,8 +1201,7 @@ private: |
|
|
{ |
|
|
{ |
|
|
carla_debug("TODO %s", __PRETTY_FUNCTION__); |
|
|
carla_debug("TODO %s", __PRETTY_FUNCTION__); |
|
|
const carla_v3_plugin_frame* const me = *static_cast<const carla_v3_plugin_frame**>(self); |
|
|
const carla_v3_plugin_frame* const me = *static_cast<const carla_v3_plugin_frame**>(self); |
|
|
CARLA_SAFE_ASSERT_RETURN(me->uiCallback != nullptr, V3_INVALID_ARG); |
|
|
|
|
|
me->uiCallback->handlePluginUIResized(rect->right - rect->left, rect->bottom - rect->top); |
|
|
|
|
|
|
|
|
me->callback->handlePluginUIResized(rect->right - rect->left, rect->bottom - rect->top); |
|
|
return V3_OK; |
|
|
return V3_OK; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -848,6 +1225,8 @@ public: |
|
|
fV3ApplicationPtr(&fV3Application), |
|
|
fV3ApplicationPtr(&fV3Application), |
|
|
fComponentHandler(), |
|
|
fComponentHandler(), |
|
|
fComponentHandlerPtr(&fComponentHandler), |
|
|
fComponentHandlerPtr(&fComponentHandler), |
|
|
|
|
|
fPluginFrame(this), |
|
|
|
|
|
fPluginFramePtr(&fPluginFrame), |
|
|
fV3ClassInfo(), |
|
|
fV3ClassInfo(), |
|
|
fV3(), |
|
|
fV3(), |
|
|
fEvents(), |
|
|
fEvents(), |
|
@@ -871,7 +1250,6 @@ public: |
|
|
if (fUI.isAttached) |
|
|
if (fUI.isAttached) |
|
|
{ |
|
|
{ |
|
|
fUI.isAttached = false; |
|
|
fUI.isAttached = false; |
|
|
fUI.frame.uiCallback = nullptr; |
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr); |
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr); |
|
|
v3_cpp_obj(fV3.view)->removed(fV3.view); |
|
|
v3_cpp_obj(fV3.view)->removed(fV3.view); |
|
|
} |
|
|
} |
|
@@ -1216,9 +1594,7 @@ public: |
|
|
// TODO inform plugin of what UI scale we use |
|
|
// TODO inform plugin of what UI scale we use |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
fUI.frame.uiCallback = this; |
|
|
|
|
|
|
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fUI.framePtr); |
|
|
|
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fPluginFramePtr); |
|
|
|
|
|
|
|
|
if (v3_cpp_obj(fV3.view)->attached(fV3.view, fUI.window->getPtr(), |
|
|
if (v3_cpp_obj(fV3.view)->attached(fV3.view, fUI.window->getPtr(), |
|
|
V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_OK) |
|
|
V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_OK) |
|
@@ -1243,7 +1619,6 @@ public: |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
fUI.frame.uiCallback = nullptr; |
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr); |
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr); |
|
|
|
|
|
|
|
|
delete fUI.window; |
|
|
delete fUI.window; |
|
@@ -1276,9 +1651,7 @@ public: |
|
|
CARLA_SAFE_ASSERT_RETURN(fUI.window == nullptr, nullptr); |
|
|
CARLA_SAFE_ASSERT_RETURN(fUI.window == nullptr, nullptr); |
|
|
CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr, nullptr); |
|
|
CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr, nullptr); |
|
|
|
|
|
|
|
|
fUI.frame.uiCallback = this; |
|
|
|
|
|
|
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fUI.framePtr); |
|
|
|
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fPluginFramePtr); |
|
|
|
|
|
|
|
|
#ifndef CARLA_OS_MAC |
|
|
#ifndef CARLA_OS_MAC |
|
|
const EngineOptions& opts(pData->engine->getOptions()); |
|
|
const EngineOptions& opts(pData->engine->getOptions()); |
|
@@ -1317,7 +1690,6 @@ public: |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
fUI.isVisible = false; |
|
|
fUI.isVisible = false; |
|
|
fUI.frame.uiCallback = nullptr; |
|
|
|
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr); |
|
|
v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr); |
|
|
|
|
|
|
|
|
carla_stderr2("Plugin refused to open its own UI"); |
|
|
carla_stderr2("Plugin refused to open its own UI"); |
|
@@ -1345,7 +1717,7 @@ public: |
|
|
void uiIdle() override |
|
|
void uiIdle() override |
|
|
{ |
|
|
{ |
|
|
#ifdef _POSIX_VERSION |
|
|
#ifdef _POSIX_VERSION |
|
|
LinkedList<HostPosixFileDescriptor>& posixfds(fUI.frame.loop.posixfds); |
|
|
|
|
|
|
|
|
LinkedList<HostPosixFileDescriptor>& posixfds(fPluginFrame.loop.posixfds); |
|
|
|
|
|
|
|
|
if (posixfds.isNotEmpty()) |
|
|
if (posixfds.isNotEmpty()) |
|
|
{ |
|
|
{ |
|
@@ -1388,7 +1760,7 @@ public: |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
LinkedList<HostTimer>& timers(fUI.frame.loop.timers); |
|
|
|
|
|
|
|
|
LinkedList<HostTimer>& timers(fPluginFrame.loop.timers); |
|
|
|
|
|
|
|
|
if (timers.isNotEmpty()) |
|
|
if (timers.isNotEmpty()) |
|
|
{ |
|
|
{ |
|
@@ -2019,7 +2391,7 @@ public: |
|
|
#endif |
|
|
#endif |
|
|
bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; |
|
|
bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0; |
|
|
|
|
|
|
|
|
uint32_t startTime = 0; |
|
|
|
|
|
|
|
|
uint32_t startTime = 0; |
|
|
uint32_t timeOffset = 0; |
|
|
uint32_t timeOffset = 0; |
|
|
|
|
|
|
|
|
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH |
|
|
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH |
|
@@ -2838,10 +3210,13 @@ private: |
|
|
v3_process_context fV3TimeContext; |
|
|
v3_process_context fV3TimeContext; |
|
|
|
|
|
|
|
|
carla_v3_host_application fV3Application; |
|
|
carla_v3_host_application fV3Application; |
|
|
carla_v3_host_application* fV3ApplicationPtr; |
|
|
|
|
|
|
|
|
carla_v3_host_application* const fV3ApplicationPtr; |
|
|
|
|
|
|
|
|
carla_v3_component_handler fComponentHandler; |
|
|
carla_v3_component_handler fComponentHandler; |
|
|
carla_v3_component_handler* fComponentHandlerPtr; |
|
|
|
|
|
|
|
|
carla_v3_component_handler* const fComponentHandlerPtr; |
|
|
|
|
|
|
|
|
|
|
|
carla_v3_plugin_frame fPluginFrame; |
|
|
|
|
|
carla_v3_plugin_frame* const fPluginFramePtr; |
|
|
|
|
|
|
|
|
// v3_class_info_2 is ABI compatible with v3_class_info |
|
|
// v3_class_info_2 is ABI compatible with v3_class_info |
|
|
union ClassInfo { |
|
|
union ClassInfo { |
|
@@ -3143,15 +3518,12 @@ private: |
|
|
bool isAttached; |
|
|
bool isAttached; |
|
|
bool isEmbed; |
|
|
bool isEmbed; |
|
|
bool isVisible; |
|
|
bool isVisible; |
|
|
carla_v3_plugin_frame frame; |
|
|
|
|
|
carla_v3_plugin_frame* framePtr; |
|
|
|
|
|
CarlaPluginUI* window; |
|
|
CarlaPluginUI* window; |
|
|
|
|
|
|
|
|
UI() noexcept |
|
|
UI() noexcept |
|
|
: isAttached(false), |
|
|
: isAttached(false), |
|
|
isEmbed(false), |
|
|
isEmbed(false), |
|
|
isVisible(false), |
|
|
isVisible(false), |
|
|
framePtr(&frame), |
|
|
|
|
|
window(nullptr) {} |
|
|
window(nullptr) {} |
|
|
|
|
|
|
|
|
~UI() |
|
|
~UI() |
|
|