From 64f7c134aabf7b336b90cf3b8954a791ae91b546 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 17 Feb 2012 03:18:21 +0000 Subject: Send a proper file URI to load sample instead of a path string. --- plugins/eg-sampler.lv2/sampler.c | 66 ++++++++++++++++++++++++++----------- plugins/eg-sampler.lv2/sampler_ui.c | 24 +++++++++++--- plugins/eg-sampler.lv2/uris.h | 6 ++-- 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, @@ -145,6 +144,26 @@ is_object_type(Sampler* plugin, LV2_URID type) || type == plugin->uris.atom_Blank; } +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 ; * ] ; * ] */ @@ -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 ; * ] ; * ] */ @@ -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); -- cgit v1.2.1