aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-02-17 03:18:21 +0000
committerDavid Robillard <d@drobilla.net>2012-02-17 03:18:21 +0000
commit64f7c134aabf7b336b90cf3b8954a791ae91b546 (patch)
tree22cd11977f2a4d6c636b5714926a2feafc319e4c
parent71f3c70c39bf6e914bacb7d7901fb4f7a98e2d13 (diff)
downloadlv2-64f7c134aabf7b336b90cf3b8954a791ae91b546.tar.xz
Send a proper file URI to load sample instead of a path string.
-rw-r--r--plugins/eg-sampler.lv2/sampler.c66
-rw-r--r--plugins/eg-sampler.lv2/sampler_ui.c24
-rw-r--r--plugins/eg-sampler.lv2/uris.h6
3 files changed, 69 insertions, 27 deletions
diff --git a/plugins/eg-sampler.lv2/sampler.c b/plugins/eg-sampler.lv2/sampler.c
index 0842c4a..65339c7 100644
--- a/plugins/eg-sampler.lv2/sampler.c
+++ b/plugins/eg-sampler.lv2/sampler.c
@@ -52,7 +52,6 @@
#include "./uris.h"
#define RING_SIZE 4096
-#define STRING_BUF 8192
enum {
SAMPLER_CONTROL = 0,
@@ -146,6 +145,26 @@ is_object_type(Sampler* plugin, LV2_URID type)
}
static bool
+parse_file_uri(const char* uri,
+ const char** host, size_t* host_len,
+ const char** path, size_t* path_len)
+{
+ if (strncmp(uri, "file://", strlen("file://"))) {
+ return false;
+ }
+
+ *host = uri + strlen("file://");
+ const char* host_end = *host;
+ for (; *host_end && *host_end != '/'; ++host_end) {}
+
+ *host_len = host_end - *host;
+ *path = host_end;
+ *path_len = (uri + strlen(uri)) - host_end;
+
+ return true;
+}
+
+static bool
handle_set_message(Sampler* plugin,
const LV2_Atom_Object* obj)
{
@@ -156,9 +175,9 @@ handle_set_message(Sampler* plugin,
/* Message should look like this:
* [
- * a msg:SetMessage ;
+ * a msg:Set ;
* msg:body [
- * eg:filename "/some/value.wav" ;
+ * eg-sampler:file <file://hal/home/me/foo.wav> ;
* ] ;
* ]
*/
@@ -175,17 +194,29 @@ handle_set_message(Sampler* plugin,
return false;
}
- /* Get filename from body. */
- const LV2_Atom* filename = NULL;
- lv2_object_getv(body, plugin->uris.eg_filename, &filename, 0);
- if (!filename) {
- fprintf(stderr, "Ignored set message with no filename.\n");
+ /* Get file URI from body. */
+ const LV2_Atom* file_uri = NULL;
+ lv2_object_getv(body, plugin->uris.eg_file, &file_uri, 0);
+ if (!file_uri) {
+ fprintf(stderr, "Ignored set message with no file URI.\n");
return false;
}
/* Load sample. */
- const char* path = (const char*)LV2_ATOM_BODY(filename);
- Sample* sample = load_sample(plugin, path, filename->size - 1);
+ const char* uri = (const char*)LV2_ATOM_BODY(file_uri);
+ const char* host = NULL;
+ const char* path = NULL;
+ size_t host_len = 0;
+ size_t path_len = 0;
+ if (!parse_file_uri(uri, &host, &host_len, &path, &path_len)) {
+ fprintf(stderr, "Request to load bad file URI %s\n", uri);
+ return false;
+ }
+
+ /* Probably should check if the host is local here, but we'll just
+ blissfully attempt to load the path on this machine... */
+
+ Sample* sample = load_sample(plugin, path, path_len);
if (sample) {
/* Loaded sample, send it to run() to be applied. */
@@ -292,6 +323,9 @@ instantiate(const LV2_Descriptor* descriptor,
plugin->to_worker = zix_ring_new(RING_SIZE);
plugin->from_worker = zix_ring_new(RING_SIZE);
+ zix_ring_mlock(plugin->to_worker);
+ zix_ring_mlock(plugin->from_worker);
+
/* Scan host features for URID map */
LV2_URID_Map* map = NULL;
for (int i = 0; features[i]; ++i) {
@@ -427,12 +461,6 @@ run(LV2_Handle instance,
}
}
-static uint32_t
-map_uri(Sampler* plugin, const char* uri)
-{
- return plugin->map->map(plugin->map->handle, uri);
-}
-
static void
save(LV2_Handle instance,
LV2_State_Store_Function store,
@@ -452,7 +480,7 @@ save(LV2_Handle instance,
plugin->sample->path);
store(callback_data,
- map_uri(plugin, FILENAME_URI),
+ plugin->uris.eg_file,
apath,
strlen(plugin->sample->path) + 1,
plugin->uris.state_Path,
@@ -476,12 +504,12 @@ restore(LV2_Handle instance,
const void* value = retrieve(
callback_data,
- map_uri(plugin, FILENAME_URI),
+ plugin->uris.eg_file,
&size, &type, &valflags);
if (value) {
const char* path = (const char*)value;
- printf("Restoring filename %s\n", path);
+ printf("Restoring file %s\n", path);
// FIXME: leak?
plugin->sample = load_sample(plugin, path, size - 1);
}
diff --git a/plugins/eg-sampler.lv2/sampler_ui.c b/plugins/eg-sampler.lv2/sampler_ui.c
index 0fba481..ad28a0f 100644
--- a/plugins/eg-sampler.lv2/sampler_ui.c
+++ b/plugins/eg-sampler.lv2/sampler_ui.c
@@ -58,6 +58,7 @@ on_load_clicked(GtkWidget* widget,
{
SamplerUI* ui = (SamplerUI*)handle;
+ /* Create a dialog to select a sample file. */
GtkWidget* dialog = gtk_file_chooser_dialog_new(
"Load Sample",
NULL,
@@ -66,15 +67,27 @@ on_load_clicked(GtkWidget* widget,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
+ /* Run the dialog, and return if it is cancelled. */
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
gtk_widget_destroy(dialog);
return;
}
- char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
- const size_t filename_len = strlen(filename);
+ /* Get the file path from the dialog. */
+ char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+
+ /* Got what we need, destroy the dialog. */
gtk_widget_destroy(dialog);
+ /* Build a complete file URI with hostname, e.g. file://hal/home/me/foo.wav
+ This is to precisely specify the file location, even if the plugin is
+ running on a different host (which is entirely possible). Plugins
+ should do this even though some hosts may not support such setups.
+ */
+ const char* hostname = g_get_host_name();
+ char* file_uri = g_filename_to_uri(filename, hostname, NULL);
+ const size_t file_uri_len = strlen(file_uri);
+
#define OBJ_BUF_SIZE 1024
uint8_t obj_buf[OBJ_BUF_SIZE];
lv2_atom_forge_set_buffer(&ui->forge, obj_buf, OBJ_BUF_SIZE);
@@ -82,7 +95,7 @@ on_load_clicked(GtkWidget* widget,
/* Send [
* a msg:Set ;
* msg:body [
- * eg-sampler:filename "/foo/bar.wav" ;
+ * eg-sampler:filename <file://hal/home/me/foo.wav> ;
* ] ;
* ]
*/
@@ -92,8 +105,8 @@ on_load_clicked(GtkWidget* widget,
lv2_atom_forge_property_head(&ui->forge, set, ui->uris.msg_body, 0);
LV2_Atom* body = (LV2_Atom*)lv2_atom_forge_blank(&ui->forge, set, 0, 0);
- lv2_atom_forge_property_head(&ui->forge, body, ui->uris.eg_filename, 0);
- lv2_atom_forge_string(&ui->forge, set, (uint8_t*)filename, filename_len);
+ lv2_atom_forge_property_head(&ui->forge, body, ui->uris.eg_file, 0);
+ lv2_atom_forge_uri(&ui->forge, set, (const uint8_t*)file_uri, file_uri_len);
lv2_atom_forge_property_head(&ui->forge, body, ui->uris.msg_body, 0);
set->size += body->size;
@@ -103,6 +116,7 @@ on_load_clicked(GtkWidget* widget,
set);
g_free(filename);
+ g_free(file_uri);
}
static LV2UI_Handle
diff --git a/plugins/eg-sampler.lv2/uris.h b/plugins/eg-sampler.lv2/uris.h
index a607737..8c8801a 100644
--- a/plugins/eg-sampler.lv2/uris.h
+++ b/plugins/eg-sampler.lv2/uris.h
@@ -25,7 +25,7 @@
#define SAMPLER_URI "http://lv2plug.in/plugins/eg-sampler"
#define MIDI_EVENT_URI "http://lv2plug.in/ns/ext/midi#MidiEvent"
-#define FILENAME_URI SAMPLER_URI "#filename"
+#define FILE_URI SAMPLER_URI "#file"
#define APPLY_SAMPLE_URI SAMPLER_URI "#applySample"
#define FREE_SAMPLE_URI SAMPLER_URI "#freeSample"
@@ -34,7 +34,7 @@ typedef struct {
LV2_URID atom_Resource;
LV2_URID eg_applySample;
LV2_URID eg_freeSample;
- LV2_URID eg_filename;
+ LV2_URID eg_file;
LV2_URID midi_Event;
LV2_URID msg_Set;
LV2_URID msg_body;
@@ -47,7 +47,7 @@ map_sampler_uris(LV2_URID_Map* map, SamplerURIs* uris)
uris->atom_Blank = map->map(map->handle, NS_ATOM "Blank");
uris->atom_Resource = map->map(map->handle, NS_ATOM "Resource");
uris->eg_applySample = map->map(map->handle, APPLY_SAMPLE_URI);
- uris->eg_filename = map->map(map->handle, FILENAME_URI);
+ uris->eg_file = map->map(map->handle, FILE_URI);
uris->eg_freeSample = map->map(map->handle, FREE_SAMPLE_URI);
uris->midi_Event = map->map(map->handle, MIDI_EVENT_URI);
uris->msg_Set = map->map(map->handle, LV2_MESSAGE_Set);