aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/jalv.c150
-rw-r--r--src/jalv_internal.h21
-rw-r--r--src/state.c31
3 files changed, 124 insertions, 78 deletions
diff --git a/src/jalv.c b/src/jalv.c
index b1cabfa..4f8a097 100644
--- a/src/jalv.c
+++ b/src/jalv.c
@@ -75,6 +75,10 @@
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+#endif
+
/* Size factor for UI ring buffers. The ring size is a few times the size of
an event output to give the UI a chance to keep up. Experiments with Ingen,
which can highly saturate its event output, led me to this value. It
@@ -108,45 +112,22 @@ unmap_uri(LV2_URID_Unmap_Handle handle,
#define NS_EXT "http://lv2plug.in/ns/ext/"
-static LV2_Extension_Data_Feature ext_data = { NULL };
-
-LV2_Feature map_feature = { LV2_URID__map, NULL };
-LV2_Feature unmap_feature = { LV2_URID__unmap, NULL };
-LV2_Feature make_path_feature = { LV2_STATE__makePath, NULL };
-LV2_Feature sched_feature = { LV2_WORKER__schedule, NULL };
-LV2_Feature state_sched_feature = { LV2_WORKER__schedule, NULL };
-LV2_Feature safe_restore_feature = { LV2_STATE__threadSafeRestore, NULL };
-LV2_Feature log_feature = { LV2_LOG__log, NULL };
-LV2_Feature options_feature = { LV2_OPTIONS__options, NULL };
-LV2_Feature def_state_feature = { LV2_STATE__loadDefaultState, NULL };
-
/** These features have no data */
-static LV2_Feature buf_size_features[3] = {
+static const LV2_Feature static_features[] = {
+ { LV2_STATE__loadDefaultState, NULL },
{ LV2_BUF_SIZE__powerOf2BlockLength, NULL },
{ LV2_BUF_SIZE__fixedBlockLength, NULL },
{ LV2_BUF_SIZE__boundedBlockLength, NULL } };
-const LV2_Feature* features[12] = {
- &map_feature, &unmap_feature,
- &sched_feature,
- &log_feature,
- &options_feature,
- &def_state_feature,
- &safe_restore_feature,
- &buf_size_features[0],
- &buf_size_features[1],
- &buf_size_features[2],
- NULL
-};
-
/** Return true iff Jalv supports the given feature. */
static bool
-feature_is_supported(const char* uri)
+feature_is_supported(Jalv* jalv, const char* uri)
{
if (!strcmp(uri, "http://lv2plug.in/ns/lv2core#isLive")) {
return true;
}
- for (const LV2_Feature*const* f = features; *f; ++f) {
+
+ for (const LV2_Feature*const* f = jalv->feature_list; *f; ++f) {
if (!strcmp(uri, (*f)->URI)) {
return true;
}
@@ -421,18 +402,19 @@ jalv_ui_instantiate(Jalv* jalv, const char* native_ui_type, void* parent)
NS_EXT "instance-access", lilv_instance_get_handle(jalv->instance)
};
const LV2_Feature data_feature = {
- LV2_DATA_ACCESS_URI, &ext_data
+ LV2_DATA_ACCESS_URI, &jalv->features.ext_data
};
const LV2_Feature idle_feature = {
LV2_UI__idleInterface, NULL
};
const LV2_Feature* ui_features[] = {
- &map_feature, &unmap_feature,
+ &jalv->features.map_feature,
+ &jalv->features.unmap_feature,
&instance_feature,
&data_feature,
- &log_feature,
+ &jalv->features.log_feature,
&parent_feature,
- &options_feature,
+ &jalv->features.options_feature,
&idle_feature,
NULL
};
@@ -729,6 +711,13 @@ signal_handler(ZIX_UNUSED int sig)
}
static void
+init_feature(LV2_Feature* const dest, const char* const URI, void* data)
+{
+ dest->URI = URI;
+ dest->data = data;
+}
+
+static void
setup_signals(Jalv* const jalv)
{
exit_sem = &jalv->done;
@@ -776,14 +765,14 @@ jalv_open(Jalv* const jalv, int argc, char** argv)
jalv->map.handle = jalv;
jalv->map.map = map_uri;
- map_feature.data = &jalv->map;
+ init_feature(&jalv->features.map_feature, LV2_URID__map, &jalv->map);
jalv->worker.jalv = jalv;
jalv->state_worker.jalv = jalv;
jalv->unmap.handle = jalv;
jalv->unmap.unmap = unmap_uri;
- unmap_feature.data = &jalv->unmap;
+ init_feature(&jalv->features.unmap_feature, LV2_URID__unmap, &jalv->unmap);
lv2_atom_forge_init(&jalv->forge, &jalv->map);
@@ -839,17 +828,26 @@ jalv_open(Jalv* const jalv, int argc, char** argv)
free(templ);
#endif
- LV2_State_Make_Path make_path = { jalv, jalv_make_path };
- make_path_feature.data = &make_path;
+ jalv->features.make_path.handle = jalv;
+ jalv->features.make_path.path = jalv_make_path;
+ init_feature(&jalv->features.make_path_feature,
+ LV2_STATE__makePath, &jalv->features.make_path);
- LV2_Worker_Schedule sched = { &jalv->worker, jalv_worker_schedule };
- sched_feature.data = &sched;
+ jalv->features.sched.handle = &jalv->worker;
+ jalv->features.sched.schedule_work = jalv_worker_schedule;
+ init_feature(&jalv->features.sched_feature,
+ LV2_WORKER__schedule, &jalv->features.sched);
- LV2_Worker_Schedule ssched = { &jalv->state_worker, jalv_worker_schedule };
- state_sched_feature.data = &ssched;
+ jalv->features.ssched.handle = &jalv->state_worker;
+ jalv->features.ssched.schedule_work = jalv_worker_schedule;
+ init_feature(&jalv->features.state_sched_feature,
+ LV2_WORKER__schedule, &jalv->features.ssched);
- LV2_Log_Log llog = { jalv, jalv_printf, jalv_vprintf };
- log_feature.data = &llog;
+ jalv->features.llog.handle = jalv;
+ jalv->features.llog.printf = jalv_printf;
+ jalv->features.llog.vprintf = jalv_vprintf;
+ init_feature(&jalv->features.log_feature,
+ LV2_LOG__log, &jalv->features.llog);
zix_sem_init(&jalv->done, 0);
@@ -955,18 +953,6 @@ jalv_open(Jalv* const jalv, int argc, char** argv)
}
}
- /* Check that any required features are supported */
- LilvNodes* req_feats = lilv_plugin_get_required_features(jalv->plugin);
- LILV_FOREACH(nodes, f, req_feats) {
- const char* uri = lilv_node_as_uri(lilv_nodes_get(req_feats, f));
- if (!feature_is_supported(uri)) {
- fprintf(stderr, "Feature %s is not supported\n", uri);
- lilv_world_free(world);
- return -6;
- }
- }
- lilv_nodes_free(req_feats);
-
/* Check for thread-safe state restore() method. */
LilvNode* state_threadSafeRestore = lilv_new_uri(
jalv->world, LV2_STATE__threadSafeRestore);
@@ -1053,7 +1039,7 @@ jalv_open(Jalv* const jalv, int argc, char** argv)
fprintf(stderr, "Update rate: %.01f Hz\n", jalv->ui_update_hz);
/* Build options array to pass to plugin */
- const LV2_Options_Option options[] = {
+ const LV2_Options_Option options[ARRAY_SIZE(jalv->features.options)] = {
{ LV2_OPTIONS_INSTANCE, 0, jalv->urids.param_sampleRate,
sizeof(float), jalv->urids.atom_Float, &jalv->sample_rate },
{ LV2_OPTIONS_INSTANCE, 0, jalv->urids.bufsz_minBlockLength,
@@ -1066,8 +1052,15 @@ jalv_open(Jalv* const jalv, int argc, char** argv)
sizeof(float), jalv->urids.atom_Float, &jalv->ui_update_hz },
{ LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, NULL }
};
+ memcpy(jalv->features.options, options, sizeof(jalv->features.options));
- options_feature.data = (void*)&options;
+ init_feature(&jalv->features.options_feature,
+ LV2_OPTIONS__options,
+ (void*)jalv->features.options);
+
+ init_feature(&jalv->features.safe_restore_feature,
+ LV2_STATE__threadSafeRestore,
+ NULL);
/* Create Plugin <=> UI communication buffers */
jalv->ui_events = zix_ring_new(jalv->opts.buffer_size);
@@ -1075,16 +1068,51 @@ jalv_open(Jalv* const jalv, int argc, char** argv)
zix_ring_mlock(jalv->ui_events);
zix_ring_mlock(jalv->plugin_events);
+ /* Build feature list for passing to plugins */
+ const LV2_Feature* const features[] = {
+ &jalv->features.map_feature,
+ &jalv->features.unmap_feature,
+ &jalv->features.sched_feature,
+ &jalv->features.log_feature,
+ &jalv->features.options_feature,
+ &static_features[0],
+ &static_features[1],
+ &static_features[2],
+ &static_features[3],
+ &static_features[4],
+ NULL
+ };
+ jalv->feature_list = calloc(1, sizeof(features));
+ if (!jalv->feature_list) {
+ fprintf(stderr, "Failed to allocate feature list\n");
+ jalv_close(jalv);
+ return -7;
+ }
+ memcpy(jalv->feature_list, features, sizeof(features));
+
+ /* Check that any required features are supported */
+ LilvNodes* req_feats = lilv_plugin_get_required_features(jalv->plugin);
+ LILV_FOREACH(nodes, f, req_feats) {
+ const char* uri = lilv_node_as_uri(lilv_nodes_get(req_feats, f));
+ if (!feature_is_supported(jalv, uri)) {
+ fprintf(stderr, "Feature %s is not supported\n", uri);
+ jalv_close(jalv);
+ return -6;
+ }
+ }
+ lilv_nodes_free(req_feats);
+
/* Instantiate the plugin */
jalv->instance = lilv_plugin_instantiate(
- jalv->plugin, jalv->sample_rate, features);
+ jalv->plugin, jalv->sample_rate, jalv->feature_list);
if (!jalv->instance) {
fprintf(stderr, "Failed to instantiate plugin.\n");
jalv_close(jalv);
return -8;
}
- ext_data.data_access = lilv_instance_get_descriptor(jalv->instance)->extension_data;
+ jalv->features.ext_data.data_access =
+ lilv_instance_get_descriptor(jalv->instance)->extension_data;
fprintf(stderr, "\n");
if (!jalv->buf_size_set) {
@@ -1197,6 +1225,12 @@ jalv_close(Jalv* const jalv)
remove(jalv->temp_dir);
free(jalv->temp_dir);
free(jalv->ui_event_buf);
+ free(jalv->feature_list);
+
+ free(jalv->opts.name);
+ free(jalv->opts.uuid);
+ free(jalv->opts.load);
+ free(jalv->opts.controls);
return 0;
}
diff --git a/src/jalv_internal.h b/src/jalv_internal.h
index a16868a..9ee880c 100644
--- a/src/jalv_internal.h
+++ b/src/jalv_internal.h
@@ -32,12 +32,14 @@
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
+#include "lv2/lv2plug.in/ns/ext/data-access/data-access.h"
#include "lv2/lv2plug.in/ns/ext/log/log.h"
#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
#include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h"
#include "lv2/lv2plug.in/ns/ext/state/state.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#include "lv2/lv2plug.in/ns/ext/worker/worker.h"
+#include "lv2/lv2plug.in/ns/ext/options/options.h"
#include "zix/ring.h"
#include "zix/sem.h"
@@ -263,6 +265,23 @@ typedef struct {
bool threaded; ///< Run work in another thread
} JalvWorker;
+typedef struct {
+ LV2_Feature map_feature;
+ LV2_Feature unmap_feature;
+ LV2_State_Make_Path make_path;
+ LV2_Feature make_path_feature;
+ LV2_Worker_Schedule sched;
+ LV2_Feature sched_feature;
+ LV2_Worker_Schedule ssched;
+ LV2_Feature state_sched_feature;
+ LV2_Log_Log llog;
+ LV2_Feature log_feature;
+ LV2_Options_Option options[6];
+ LV2_Feature options_feature;
+ LV2_Feature safe_restore_feature;
+ LV2_Extension_Data_Feature ext_data;
+} JalvFeatures;
+
struct Jalv {
JalvOptions opts; ///< Command-line options
JalvURIDs urids; ///< URIDs
@@ -318,6 +337,8 @@ struct Jalv {
bool has_ui; ///< True iff a control UI is present
bool request_update; ///< True iff a plugin update is needed
bool safe_restore; ///< Plugin restore() is thread-safe
+ JalvFeatures features;
+ const LV2_Feature** feature_list;
};
int
diff --git a/src/state.c b/src/state.c
index 0f52c86..899e61f 100644
--- a/src/state.c
+++ b/src/state.c
@@ -36,26 +36,6 @@
#define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#"
#define NS_XSD "http://www.w3.org/2001/XMLSchema#"
-extern LV2_Feature map_feature;
-extern LV2_Feature unmap_feature;
-extern LV2_Feature make_path_feature;
-extern LV2_Feature sched_feature;
-extern LV2_Feature state_sched_feature;
-extern LV2_Feature safe_restore_feature;
-extern LV2_Feature log_feature;
-extern LV2_Feature options_feature;
-extern LV2_Feature def_state_feature;
-
-const LV2_Feature* state_features[9] = {
- &map_feature, &unmap_feature,
- &make_path_feature,
- &state_sched_feature,
- &safe_restore_feature,
- &log_feature,
- &options_feature,
- NULL
-};
-
char*
jalv_make_path(LV2_State_Make_Path_Handle handle,
const char* path)
@@ -204,6 +184,17 @@ jalv_apply_state(Jalv* jalv, LilvState* state)
zix_sem_wait(&jalv->paused);
}
+ const LV2_Feature* state_features[9] = {
+ &jalv->features.map_feature,
+ &jalv->features.unmap_feature,
+ &jalv->features.make_path_feature,
+ &jalv->features.state_sched_feature,
+ &jalv->features.safe_restore_feature,
+ &jalv->features.log_feature,
+ &jalv->features.options_feature,
+ NULL
+ };
+
lilv_state_restore(
state, jalv->instance, set_port_value, jalv, 0, state_features);