From c43aed97c6b874a80fd5a9f759e651953bcec1f9 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 9 Nov 2011 01:19:29 +0000 Subject: Implement file name changing from UI. --- plugins/eg-sampler.lv2/sampler.c | 62 ++++++++++++++++++++--------- plugins/eg-sampler.lv2/sampler.ttl | 1 + plugins/eg-sampler.lv2/sampler_ui.c | 78 +++++++++++++++++-------------------- plugins/eg-sampler.lv2/uris.h | 25 ++++++++++++ 4 files changed, 104 insertions(+), 62 deletions(-) create mode 100644 plugins/eg-sampler.lv2/uris.h (limited to 'plugins') diff --git a/plugins/eg-sampler.lv2/sampler.c b/plugins/eg-sampler.lv2/sampler.c index 449aad1..5a00e64 100644 --- a/plugins/eg-sampler.lv2/sampler.c +++ b/plugins/eg-sampler.lv2/sampler.c @@ -42,16 +42,14 @@ #include #include "lv2/lv2plug.in/ns/ext/atom/atom-buffer.h" +#include "lv2/lv2plug.in/ns/ext/atom/atom-helpers.h" #include "lv2/lv2plug.in/ns/ext/state/state.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "lv2/lv2plug.in/ns/lv2core/lv2.h" -#define NS_ATOM "http://lv2plug.in/ns/ext/atom#" +#include "./uris.h" -#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 STRING_BUF 8192 +#define STRING_BUF 8192 enum { SAMPLER_CONTROL = 0, @@ -81,6 +79,9 @@ typedef struct { float* output_port; LV2_Atom_Buffer* event_port; LV2_URID midi_event_id; + LV2_URID atom_message_id; + LV2_URID set_message_id; + LV2_URID filename_key_id; /* Playback state */ bool play; @@ -95,6 +96,7 @@ handle_load_sample(Sampler* plugin) { plugin->pending_sample_ready = 0; + printf("Loading sample %s\n", plugin->pending_samp->filepath); SF_INFO* const info = &plugin->pending_samp->info; SNDFILE* const sample = sf_open(plugin->pending_samp->filepath, SFM_READ, @@ -199,7 +201,10 @@ instantiate(const LV2_Descriptor* descriptor, memset(plugin->samp, 0, sizeof(SampleFile)); memset(plugin->pending_samp, 0, sizeof(SampleFile)); - plugin->midi_event_id = -1; + plugin->midi_event_id = -1; + plugin->atom_message_id = -1; + plugin->set_message_id = -1; + plugin->filename_key_id = -1; /* Initialise mutexes and conditions for the worker thread */ if (pthread_mutex_init(&plugin->pending_samp_mutex, 0)) { @@ -221,6 +226,12 @@ instantiate(const LV2_Descriptor* descriptor, plugin->mapper = (LV2_URID_Mapper*)features[i]->data; plugin->midi_event_id = plugin->mapper->map_uri( plugin->mapper->handle, MIDI_EVENT_URI); + plugin->atom_message_id = plugin->mapper->map_uri( + plugin->mapper->handle, ATOM_MESSAGE_URI); + plugin->set_message_id = plugin->mapper->map_uri( + plugin->mapper->handle, SET_MESSAGE_URI); + plugin->filename_key_id = plugin->mapper->map_uri( + plugin->mapper->handle, FILENAME_URI); } } @@ -265,18 +276,31 @@ run(LV2_Handle instance, plugin->frame = 0; plugin->play = true; } - } - /*************************************************** - * XXX TODO: * - * ADD CODE HERE TO DETECT AN INCOMING MESSAGE TO * - * DYNAMICALLY LOAD A SAMPLE * - *************************************************** - */ - else if (0) { - /* message to load a sample comes in */ - /* write filename to plugin->pending_samp->filepath */ - /* strncpy(plugin->pending_samp->filepath, some_src_string, STRING_BUF); */ - pthread_cond_signal(&plugin->pending_samp_cond); + } else if (ev->body.type == plugin->atom_message_id) { + const LV2_Object* msg = (LV2_Object*)&ev->body; + if (msg->id == plugin->set_message_id) { + const LV2_Atom* filename = NULL; + LV2_Object_Query q[] = { + { plugin->filename_key_id, &filename }, + LV2_OBJECT_QUERY_END + }; + lv2_object_query(msg, q); + + if (filename) { + memcpy(plugin->pending_samp->filepath, + filename->body, + filename->size); + pthread_cond_signal(&plugin->pending_samp_cond); + + } else { + fprintf(stderr, "Ignored set message with no filename\n"); + } + } else { + fprintf(stderr, "Unknown message type %d\n", msg->id); + } + + } else { + fprintf(stderr, "Unknown event type %d\n", ev->body.type); } } @@ -310,7 +334,7 @@ run(LV2_Handle instance, plugin->samp = plugin->pending_samp; plugin->pending_samp = tmp; plugin->pending_sample_ready = 0; - free(plugin->pending_samp->data); + free(plugin->pending_samp->data); // FIXME: non-realtime! pthread_mutex_unlock(&plugin->pending_samp_mutex); } diff --git a/plugins/eg-sampler.lv2/sampler.ttl b/plugins/eg-sampler.lv2/sampler.ttl index 51c6c28..9dd512f 100644 --- a/plugins/eg-sampler.lv2/sampler.ttl +++ b/plugins/eg-sampler.lv2/sampler.ttl @@ -46,4 +46,5 @@ a ui:GtkUI ; + lv2:requiredFeature ; ui:binary . diff --git a/plugins/eg-sampler.lv2/sampler_ui.c b/plugins/eg-sampler.lv2/sampler_ui.c index 1895f22..24a79aa 100644 --- a/plugins/eg-sampler.lv2/sampler_ui.c +++ b/plugins/eg-sampler.lv2/sampler_ui.c @@ -25,19 +25,17 @@ #include "lv2/lv2plug.in/ns/ext/atom/atom-helpers.h" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" +#include "lv2/lv2plug.in/ns/ext/atom/forge.h" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "lv2/lv2plug.in/ns/extensions/ui/ui.h" -#define NS_ATOM "http://lv2plug.in/ns/ext/atom#" +#include "./uris.h" -#define SAMPLER_URI "http://lv2plug.in/plugins/eg-sampler" #define SAMPLER_UI_URI "http://lv2plug.in/plugins/eg-sampler#ui" -#define MIDI_EVENT_URI "http://lv2plug.in/ns/ext/midi#MidiEvent" -#define FILENAME_URI SAMPLER_URI "#filename" -#define STRING_BUF 8192 typedef struct { - LV2_URI_Map_Feature* uri_map; + LV2_URID_Mapper* mapper; + LV2_Atom_Forge* forge; LV2UI_Write_Function write; LV2UI_Controller controller; @@ -45,11 +43,10 @@ typedef struct { GtkWidget* button; } SamplerUI; -static uint32_t +static LV2_URID uri_to_id(SamplerUI* ui, const char* uri) { - return ui->uri_map->uri_to_id(ui->uri_map->callback_data, - NULL, uri); + return ui->mapper->map_uri(ui->mapper->handle, uri); } static void @@ -66,36 +63,29 @@ on_load_clicked(GtkWidget* widget, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - const size_t filename_len = strlen(filename); - fprintf(stderr, "LOAD SAMPLE %s\n", filename); - const size_t msg_size = sizeof(LV2_Atom) - + sizeof(LV2_Object) - + sizeof(LV2_Atom_Property) - + filename_len + 1;; - - uint8_t buf[msg_size]; - LV2_Atom* msg = (LV2_Atom*)buf; - - msg->type = uri_to_id(ui, NS_ATOM "Blank"); - msg->size = 0; - LV2_Object* obj = (LV2_Object*)msg->body; - obj->context = 0; - obj->id = 0; - - lv2_atom_append_property(msg, - uri_to_id(ui, FILENAME_URI), - uri_to_id(ui, NS_ATOM "String"), - filename_len + 1, - (const uint8_t*)filename); - - //ui->write(ui->controller, - // 0, - - - + 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); + gtk_widget_destroy(dialog); + + uint8_t msg_buf[4096]; + LV2_Object* msg = (LV2_Object*)msg_buf; + lv2_atom_forge_set_message(ui->forge, msg, uri_to_id(ui, SET_MESSAGE_URI)); + lv2_object_append(msg, + uri_to_id(ui, FILENAME_URI), + uri_to_id(ui, NS_ATOM "String"), + filename_len, + filename); + + ui->write(ui->controller, 0, sizeof(LV2_Atom) + msg->size, + uri_to_id(ui, NS_ATOM "atomTransfer"), + msg); + + g_free(filename); } static LV2UI_Handle @@ -108,7 +98,7 @@ instantiate(const LV2UI_Descriptor* descriptor, const LV2_Feature* const* features) { SamplerUI* ui = (SamplerUI*)malloc(sizeof(SamplerUI)); - ui->uri_map = NULL; + ui->mapper = NULL; ui->write = write_function; ui->controller = controller; ui->button = NULL; @@ -116,17 +106,19 @@ instantiate(const LV2UI_Descriptor* descriptor, *widget = NULL; for (int i = 0; features[i]; ++i) { - if (strcmp(features[i]->URI, LV2_URI_MAP_URI) == 0) { - ui->uri_map = (LV2_URI_Map_Feature*)features[i]->data; + if (!strcmp(features[i]->URI, LV2_URID_URI "#Mapper")) { + ui->mapper = (LV2_URID_Mapper*)features[i]->data; } } - if (!ui->uri_map) { + if (!ui->mapper) { fprintf(stderr, "sampler_ui: Host does not support uri-map\n"); free(ui); return NULL; } + ui->forge = lv2_atom_forge_new(ui->mapper); + ui->button = gtk_button_new_with_label("Load Sample"); g_signal_connect(ui->button, "clicked", G_CALLBACK(on_load_clicked), diff --git a/plugins/eg-sampler.lv2/uris.h b/plugins/eg-sampler.lv2/uris.h new file mode 100644 index 0000000..d4df237 --- /dev/null +++ b/plugins/eg-sampler.lv2/uris.h @@ -0,0 +1,25 @@ +/* + LV2 Sampler Example Plugin + Copyright 2011 David Robillard + + 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. +*/ + +#define NS_ATOM "http://lv2plug.in/ns/ext/atom#" +#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" + +#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 ATOM_MESSAGE_URI "http://lv2plug.in/ns/ext/atom#Message" +#define SET_MESSAGE_URI "http: //example.org/set" -- cgit v1.2.1