aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/jalv.16
-rw-r--r--src/atom_rdf.c138
-rw-r--r--src/jalv.c36
-rw-r--r--src/jalv_console.c5
-rw-r--r--src/jalv_gtk2.c4
-rw-r--r--src/jalv_internal.h8
-rw-r--r--src/symap.c6
-rw-r--r--wscript2
8 files changed, 181 insertions, 24 deletions
diff --git a/doc/jalv.1 b/doc/jalv.1
index 116a1ce..bc44007 100644
--- a/doc/jalv.1
+++ b/doc/jalv.1
@@ -1,4 +1,4 @@
-.TH JALV "17 Jan 2012"
+.TH JALV "18 Feb 2012"
.SH NAME
.B jalv \- Run an LV2 plugin as a JACK application.
@@ -20,6 +20,10 @@ UUID for Jack session restoration.
\fB\-l DIR\fR
Load state from state directory.
+.TP
+\fB\-d DIR\fR
+Dump plugin <=> UI communication.
+
.SH SEE ALSO
.BR lv2ls(1),
.BR jackd(1)
diff --git a/src/atom_rdf.c b/src/atom_rdf.c
new file mode 100644
index 0000000..2ee97f2
--- /dev/null
+++ b/src/atom_rdf.c
@@ -0,0 +1,138 @@
+/*
+ Copyright 2012 David Robillard <http://drobilla.net>
+
+ 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.
+
+ THIS 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.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
+#include "lv2/lv2plug.in/ns/ext/atom/atom-helpers.h"
+#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
+
+#include "serd/serd.h"
+
+#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
+#define NS_XSD "http://www.w3.org/2001/XMLSchema#"
+
+#define USTR(str) ((const uint8_t*)str)
+
+typedef struct {
+ char* buf;
+ size_t len;
+} String;
+
+static size_t
+string_sink(const void* buf, size_t len, void* stream)
+{
+ String* str = (String*)stream;
+ str->buf = realloc(str->buf, str->len + len);
+ memcpy(str->buf + str->len, buf, len);
+ str->len += len;
+ return len;
+}
+
+void
+atom_to_rdf(SerdWriter* writer,
+ LV2_URID_Unmap* unmap,
+ const SerdNode* subject,
+ const SerdNode* predicate,
+ const LV2_Atom* atom,
+ uint32_t flags)
+{
+ const char* const type = unmap->unmap(unmap->handle, atom->type);
+ SerdNode object = SERD_NODE_NULL;
+ SerdNode datatype = SERD_NODE_NULL;
+ bool new_node = false;
+ if (atom->type == 0 && atom->size == 0) {
+ object = serd_node_from_string(SERD_BLANK, USTR("null"));
+ } else if (!strcmp(type, NS_ATOM "String")) {
+ const uint8_t* str = USTR(LV2_ATOM_BODY(atom));
+ object = serd_node_from_string(SERD_LITERAL, str);
+ } else if (!strcmp(type, NS_ATOM "URID")) {
+ const uint32_t id = *(const uint32_t*)LV2_ATOM_BODY(atom);
+ const uint8_t* str = USTR(unmap->unmap(unmap->handle, id));
+ object = serd_node_from_string(SERD_URI, str);
+ } else if (!strcmp(type, NS_ATOM "URI")) {
+ const uint8_t* str = USTR(LV2_ATOM_BODY(atom));
+ object = serd_node_from_string(SERD_URI, str);
+ } else if (!strcmp(type, NS_ATOM "Int32")) {
+ new_node = true;
+ object = serd_node_new_integer(*(int32_t*)LV2_ATOM_BODY(atom));
+ datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "integer"));
+ } else if (!strcmp(type, NS_ATOM "Float")) {
+ new_node = true;
+ object = serd_node_new_decimal(*(float*)LV2_ATOM_BODY(atom), 8);
+ datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "decimal"));
+ } else if (!strcmp(type, NS_ATOM "Double")) {
+ new_node = true;
+ object = serd_node_new_decimal(*(float*)LV2_ATOM_BODY(atom), 16);
+ datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "decimal"));
+ } else if (!strcmp(type, NS_ATOM "Bool")) {
+ new_node = true;
+ datatype = serd_node_from_string(SERD_URI, USTR(NS_XSD "boolean"));
+ if (*(int32_t*)LV2_ATOM_BODY(atom)) {
+ object = serd_node_from_string(SERD_LITERAL, USTR("true"));
+ } else {
+ object = serd_node_from_string(SERD_LITERAL, USTR("false"));
+ }
+ } else if (!strcmp(type, NS_ATOM "Blank")) {
+ const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom;
+ SerdNode idnum = serd_node_new_integer(obj->id);
+ SerdNode id = serd_node_from_string(SERD_BLANK, idnum.buf);
+ serd_writer_write_statement(
+ writer, flags|SERD_ANON_O_BEGIN, NULL,
+ subject, predicate, &id, NULL, NULL);
+ LV2_OBJECT_FOREACH(obj, i) {
+ const LV2_Atom_Property_Body* prop = lv2_object_iter_get(i);
+ const char* const key = unmap->unmap(unmap->handle, prop->key);
+ SerdNode pred = serd_node_from_string(SERD_URI, USTR(key));
+ atom_to_rdf(writer, unmap, &id, &pred, &prop->value, SERD_ANON_CONT);
+ }
+ serd_writer_end_anon(writer, &id);
+ serd_node_free(&idnum);
+ }
+
+ if (object.buf) {
+ serd_writer_write_statement(
+ writer, flags, NULL, subject, predicate, &object, &datatype, NULL);
+ }
+
+ if (new_node) {
+ serd_node_free(&object);
+ }
+}
+
+char*
+atom_to_turtle(LV2_URID_Unmap* unmap,
+ const SerdNode* subject,
+ const SerdNode* predicate,
+ const LV2_Atom* atom)
+{
+ SerdURI base_uri = SERD_URI_NULL;
+ SerdEnv* env = serd_env_new(NULL);
+ String str = { NULL, 0 };
+ SerdWriter* writer = serd_writer_new(
+ SERD_TURTLE,
+ SERD_STYLE_ABBREVIATED|SERD_STYLE_RESOLVED|SERD_STYLE_CURIED,
+ env, &base_uri, string_sink, &str);
+
+ atom_to_rdf(writer, unmap, subject, predicate, atom, 0);
+ serd_writer_finish(writer);
+ string_sink("", 1, &str);
+
+ serd_writer_free(writer);
+ serd_env_free(env);
+ return str.buf;
+}
diff --git a/src/jalv.c b/src/jalv.c
index ab81162..f1b01d0 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -1,5 +1,5 @@
/*
- Copyright 2007-2011 David Robillard <http://drobilla.net>
+ Copyright 2007-2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -52,7 +52,10 @@
#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
#define NS_MIDI "http://lv2plug.in/ns/ext/midi#"
#define NS_PSET "http://lv2plug.in/ns/ext/presets#"
+#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+#define USTR(str) ((const uint8_t*)str)
+
ZixSem exit_sem; /**< Exit semaphore */
LV2_URID
@@ -386,11 +389,6 @@ jack_process_cb(jack_nframes_t nframes, void* data)
assert(ev.size == sizeof(float));
port->control = *(float*)body;
} else if (ev.protocol == host->atom_prot_id) {
- printf("ATOM UI READ\n");
- for (uint32_t i = 0; i < ev.size; ++i) {
- printf("%c", body[i]);
- }
- printf("\n");
LV2_Evbuf_Iterator i = lv2_evbuf_end(port->evbuf);
const LV2_Atom* const atom = (const LV2_Atom*)body;
lv2_evbuf_write(&i, nframes, 0,
@@ -511,11 +509,11 @@ jalv_ui_write(SuilController controller,
}
if (protocol == host->atom_prot_id) {
- printf("ATOM UI WRITE: %d\n", protocol);
- for (uint32_t i = 0; i < buffer_size; ++i) {
- printf("%c", ((uint8_t*)buffer)[i]);
- }
- printf("\n");
+ SerdNode s = serd_node_from_string(SERD_BLANK, USTR("msg"));
+ SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value"));
+ char* str = atom_to_turtle(&host->unmap, &s, &p, (LV2_Atom*)buffer);
+ printf("\n## UI => Plugin ##\n%s\n", str);
+ free(str);
}
char buf[sizeof(ControlChange) + buffer_size];
@@ -524,13 +522,6 @@ jalv_ui_write(SuilController controller,
ev->protocol = protocol;
ev->size = buffer_size;
memcpy(ev->body, buffer, buffer_size);
- #if 0
- printf("WRITE: ");
- for (uint32_t i = 0; i < sizeof(buf); ++i) {
- printf("%c", buf[i]);
- }
- printf("\n");
- #endif
jack_ringbuffer_write(host->ui_events, buf, sizeof(buf));
}
@@ -543,6 +534,15 @@ jalv_emit_ui_events(Jalv* host)
jack_ringbuffer_read(host->plugin_events, (char*)&ev, sizeof(ev));
char buf[ev.size];
jack_ringbuffer_read(host->plugin_events, buf, ev.size);
+
+ if (ev.protocol == host->atom_prot_id) {
+ SerdNode s = serd_node_from_string(SERD_BLANK, USTR("msg"));
+ SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value"));
+ char* str = atom_to_turtle(&host->unmap, &s, &p, (LV2_Atom*)buf);
+ printf("\n## Plugin => UI ##\n%s\n", str);
+ free(str);
+ }
+
suil_instance_port_event(host->ui_instance, ev.index,
ev.size, ev.protocol, buf);
}
diff --git a/src/jalv_console.c b/src/jalv_console.c
index 80be5cd..ae5c30f 100644
--- a/src/jalv_console.c
+++ b/src/jalv_console.c
@@ -1,5 +1,5 @@
/*
- Copyright 2007-2011 David Robillard <http://drobilla.net>
+ Copyright 2007-2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -30,6 +30,7 @@ print_usage(const char* name, bool error)
fprintf(os, " -h Display this help and exit\n");
fprintf(os, " -u UUID UUID for Jack session restoration\n");
fprintf(os, " -l DIR Load state from save directory\n");
+ fprintf(os, " -d DIR Dump plugin <=> UI communication\n");
return error ? 1 : 0;
}
@@ -58,6 +59,8 @@ jalv_init(int* argc, char*** argv, JalvOptions* opts)
return 1;
}
opts->load = jalv_strdup((*argv)[a]);
+ } else if ((*argv)[a][1] == 'd') {
+ opts->dump = true;
} else {
fprintf(stderr, "Unknown option %s\n", (*argv)[a]);
return print_usage((*argv)[0], true);
diff --git a/src/jalv_gtk2.c b/src/jalv_gtk2.c
index fad7609..3e20398 100644
--- a/src/jalv_gtk2.c
+++ b/src/jalv_gtk2.c
@@ -1,5 +1,5 @@
/*
- Copyright 2007-2011 David Robillard <http://drobilla.net>
+ Copyright 2007-2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -36,6 +36,8 @@ jalv_init(int* argc, char*** argv, JalvOptions* opts)
"UUID for Jack session restoration", "UUID" },
{ "load", 'l', 0, G_OPTION_ARG_STRING, &opts->load,
"Load state from save directory", "DIR" },
+ { "dump", 'd', 0, G_OPTION_ARG_NONE, &opts->dump,
+ "Dump plugin <=> UI communication", NULL },
{ 0, 0, 0, 0, 0, 0, 0 } };
GError* error = NULL;
const int err = gtk_init_with_args(
diff --git a/src/jalv_internal.h b/src/jalv_internal.h
index 25da829..1dc225f 100644
--- a/src/jalv_internal.h
+++ b/src/jalv_internal.h
@@ -27,6 +27,7 @@
#include "serd/serd.h"
#include "suil/suil.h"
+#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#include "lv2/lv2plug.in/ns/ext/state/state.h"
@@ -78,6 +79,7 @@ typedef struct {
typedef struct {
char* uuid;
char* load;
+ bool dump;
} JalvOptions;
typedef enum {
@@ -189,6 +191,12 @@ jalv_make_path(LV2_State_Make_Path_Handle handle,
void
jalv_apply_state(Jalv* jalv, LilvState* state);
+char*
+atom_to_turtle(LV2_URID_Unmap* unmap,
+ const SerdNode* subject,
+ const SerdNode* predicate,
+ const LV2_Atom* atom);
+
static inline char*
jalv_strdup(const char* str)
{
diff --git a/src/symap.c b/src/symap.c
index ee9320d..f7cc653 100644
--- a/src/symap.c
+++ b/src/symap.c
@@ -1,5 +1,5 @@
/*
- Copyright 2011 David Robillard <http://drobilla.net>
+ Copyright 2011-2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -172,7 +172,9 @@ symap_map(Symap* map, const char* sym)
const char*
symap_unmap(Symap* map, uint32_t id)
{
- if (id <= map->size) {
+ if (id == 0) {
+ return NULL;
+ } else if (id <= map->size) {
return map->symbols[id - 1];
}
return NULL;
diff --git a/wscript b/wscript
index f04a9e0..4c5933b 100644
--- a/wscript
+++ b/wscript
@@ -83,7 +83,7 @@ def configure(conf):
def build(bld):
libs = 'LILV SUIL JACK SERD LV2CORE LV2_EVENT LV2_ATOM LV2_URI_MAP LV2_STATE'
- source = 'src/jalv.c src/symap.c src/state.c src/lv2_evbuf.c'
+ source = 'src/jalv.c src/symap.c src/state.c src/lv2_evbuf.c src/atom_rdf.c'
# Non-GUI version
obj = bld(features = 'c cprogram',