aboutsummaryrefslogtreecommitdiffstats
path: root/src/jalv.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-08-10 14:26:07 -0400
committerDavid Robillard <d@drobilla.net>2022-08-17 13:51:08 -0400
commit97cfde95c365a2f33b6a14b29b5cd5b9c6397616 (patch)
treeffde6254af2a750098626481e5c77b5bd099ff85 /src/jalv.c
parenta71bbcd5d699b155daf37be93c521c00b3b06ae6 (diff)
downloadjalv-97cfde95c365a2f33b6a14b29b5cd5b9c6397616.tar.gz
jalv-97cfde95c365a2f33b6a14b29b5cd5b9c6397616.tar.bz2
jalv-97cfde95c365a2f33b6a14b29b5cd5b9c6397616.zip
Fix thread-safety of plugin/UI communication rings
Diffstat (limited to 'src/jalv.c')
-rw-r--r--src/jalv.c133
1 files changed, 86 insertions, 47 deletions
diff --git a/src/jalv.c b/src/jalv.c
index 9dfab5c..7b6da03 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -494,6 +494,42 @@ jalv_ui_is_resizable(Jalv* jalv)
return !fs_matches && !nrs_matches;
}
+static void
+jalv_send_control_to_plugin(Jalv* const jalv,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ const void* buffer)
+{
+ if (buffer_size != sizeof(float)) {
+ jalv_log(JALV_LOG_ERR, "UI wrote invalid control size %u\n", buffer_size);
+
+ } else {
+ jalv_write_control(
+ jalv, jalv->ui_to_plugin, port_index, *(const float*)buffer);
+ }
+}
+
+static void
+jalv_send_event_to_plugin(Jalv* const jalv,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ const void* buffer)
+{
+ const LV2_Atom* const atom = (const LV2_Atom*)buffer;
+
+ if (buffer_size < sizeof(LV2_Atom)) {
+ jalv_log(JALV_LOG_ERR, "UI wrote impossible atom size\n");
+
+ } else if (sizeof(LV2_Atom) + atom->size != buffer_size) {
+ jalv_log(JALV_LOG_ERR, "UI wrote corrupt atom size\n");
+
+ } else {
+ jalv_dump_atom(jalv, stdout, "UI => Plugin", atom, 36);
+ jalv_write_event(
+ jalv, jalv->ui_to_plugin, port_index, atom->size, atom->type, atom + 1U);
+ }
+}
+
void
jalv_send_to_plugin(void* const jalv_handle,
uint32_t port_index,
@@ -503,30 +539,21 @@ jalv_send_to_plugin(void* const jalv_handle,
{
Jalv* const jalv = (Jalv*)jalv_handle;
- if (protocol != 0 && protocol != jalv->urids.atom_eventTransfer) {
+ if (port_index >= jalv->num_ports) {
+ jalv_log(JALV_LOG_ERR, "UI wrote to invalid port index %u\n", port_index);
+
+ } else if (protocol == 0U) {
+ jalv_send_control_to_plugin(jalv, port_index, buffer_size, buffer);
+
+ } else if (protocol == jalv->urids.atom_eventTransfer) {
+ jalv_send_event_to_plugin(jalv, port_index, buffer_size, buffer);
+
+ } else {
jalv_log(JALV_LOG_ERR,
"UI wrote with unsupported protocol %u (%s)\n",
protocol,
unmap_uri(jalv, protocol));
- return;
- }
-
- if (port_index >= jalv->num_ports) {
- jalv_log(JALV_LOG_ERR, "UI wrote to invalid port index %u\n", port_index);
- return;
- }
-
- if (protocol == jalv->urids.atom_eventTransfer) {
- jalv_dump_atom(jalv, stdout, "UI => Plugin", (const LV2_Atom*)buffer, 36);
}
-
- char buf[MSG_BUFFER_SIZE];
- ControlChange* ev = (ControlChange*)buf;
- ev->index = port_index;
- ev->protocol = protocol;
- ev->size = buffer_size;
- memcpy(ev + 1, buffer, buffer_size);
- zix_ring_write(jalv->ui_to_plugin, buf, sizeof(ControlChange) + buffer_size);
}
void
@@ -536,10 +563,13 @@ jalv_apply_ui_events(Jalv* jalv, uint32_t nframes)
return;
}
- ControlChange ev;
+ ControlChange ev = {0U, 0U, 0U};
const size_t space = zix_ring_read_space(jalv->ui_to_plugin);
for (size_t i = 0; i < space; i += sizeof(ev) + ev.size) {
- zix_ring_read(jalv->ui_to_plugin, &ev, sizeof(ev));
+ if (zix_ring_read(jalv->ui_to_plugin, &ev, sizeof(ev)) != sizeof(ev)) {
+ jalv_log(JALV_LOG_ERR, "Failed to read header from UI ring buffer\n");
+ break;
+ }
char buffer[MSG_BUFFER_SIZE];
if (zix_ring_read(jalv->ui_to_plugin, buffer, ev.size) != ev.size) {
@@ -592,6 +622,27 @@ jalv_init_ui(Jalv* jalv)
}
}
+static int
+jalv_write_control_change(Jalv* const jalv,
+ ZixRing* const target,
+ const void* const header,
+ const uint32_t header_size,
+ const void* const body,
+ const uint32_t body_size)
+{
+ ZixRingTransaction tx = zix_ring_begin_write(target);
+ if (zix_ring_amend_write(target, &tx, header, header_size) ||
+ zix_ring_amend_write(target, &tx, body, body_size)) {
+ jalv_log(JALV_LOG_ERR,
+ target == jalv->plugin_to_ui ? "Plugin => UI buffer overflow"
+ : "UI => Plugin buffer overflow");
+ return -1;
+ }
+
+ zix_ring_commit_write(target, &tx);
+ return 0;
+}
+
int
jalv_write_event(Jalv* const jalv,
ZixRing* const target,
@@ -601,23 +652,18 @@ jalv_write_event(Jalv* const jalv,
const void* const body)
{
// TODO: Be more discriminate about what to send
- char evbuf[sizeof(ControlChange) + sizeof(LV2_Atom)];
- ControlChange* ev = (ControlChange*)evbuf;
- ev->index = port_index;
- ev->protocol = jalv->urids.atom_eventTransfer;
- ev->size = sizeof(LV2_Atom) + size;
-
- LV2_Atom* atom = (LV2_Atom*)(ev + 1);
- atom->type = type;
- atom->size = size;
-
- if (zix_ring_write_space(target) >= sizeof(evbuf) + size) {
- zix_ring_write(target, evbuf, sizeof(evbuf));
- zix_ring_write(target, (const char*)body, size);
- return 0;
- }
- return 1;
+ typedef struct {
+ ControlChange change;
+ LV2_Atom atom;
+ } Header;
+
+ const Header header = {
+ {port_index, jalv->urids.atom_eventTransfer, sizeof(LV2_Atom) + size},
+ {size, type}};
+
+ return jalv_write_control_change(
+ jalv, target, &header, sizeof(header), body, size);
}
int
@@ -626,17 +672,10 @@ jalv_write_control(Jalv* const jalv,
const uint32_t port_index,
const float value)
{
- (void)jalv;
-
- char buf[sizeof(ControlChange) + sizeof(value)];
-
- ControlChange* const ev = (ControlChange*)buf;
- ev->index = port_index;
- ev->protocol = 0U;
- ev->size = sizeof(value);
- *(float*)(ev + 1) = value;
+ const ControlChange header = {port_index, 0, sizeof(value)};
- return zix_ring_write(target, buf, sizeof(buf)) != sizeof(buf);
+ return jalv_write_control_change(
+ jalv, target, &header, sizeof(header), &value, sizeof(value));
}
void