diff options
Diffstat (limited to 'plugins/eg04-sampler.lv2')
-rw-r--r-- | plugins/eg04-sampler.lv2/README.txt | 13 | ||||
-rw-r--r-- | plugins/eg04-sampler.lv2/click.wav | bin | 644 -> 0 bytes | |||
-rw-r--r-- | plugins/eg04-sampler.lv2/manifest.ttl.in | 19 | ||||
-rw-r--r-- | plugins/eg04-sampler.lv2/sampler.c | 483 | ||||
-rw-r--r-- | plugins/eg04-sampler.lv2/sampler.ttl | 67 | ||||
-rw-r--r-- | plugins/eg04-sampler.lv2/sampler_ui.c | 241 | ||||
-rw-r--r-- | plugins/eg04-sampler.lv2/uris.h | 135 | ||||
l--------- | plugins/eg04-sampler.lv2/waf | 1 | ||||
-rw-r--r-- | plugins/eg04-sampler.lv2/wscript | 80 |
9 files changed, 0 insertions, 1039 deletions
diff --git a/plugins/eg04-sampler.lv2/README.txt b/plugins/eg04-sampler.lv2/README.txt deleted file mode 100644 index 4eed9e6..0000000 --- a/plugins/eg04-sampler.lv2/README.txt +++ /dev/null @@ -1,13 +0,0 @@ -== Sampler == - -This plugin loads a single sample from a .wav file and plays it back when a MIDI -note on is received. Any sample on the system can be loaded via another event. -A Gtk UI is included which does this, but the host can as well. - -This plugin illustrates: - -- UI <==> Plugin communication via events -- Use of the worker extension for non-realtime tasks (sample loading) -- Use of the log extension to print log messages via the host -- Saving plugin state via the state extension -- Dynamic plugin control via the same properties saved to state diff --git a/plugins/eg04-sampler.lv2/click.wav b/plugins/eg04-sampler.lv2/click.wav Binary files differdeleted file mode 100644 index 520a18c..0000000 --- a/plugins/eg04-sampler.lv2/click.wav +++ /dev/null diff --git a/plugins/eg04-sampler.lv2/manifest.ttl.in b/plugins/eg04-sampler.lv2/manifest.ttl.in deleted file mode 100644 index 8a01428..0000000 --- a/plugins/eg04-sampler.lv2/manifest.ttl.in +++ /dev/null @@ -1,19 +0,0 @@ -# Unlike the previous examples, this manifest lists more than one resource: the -# plugin as usual, and the UI. The descriptions are similar, but have -# different types, so the host can decide from this file alone whether or not -# it is interested, and avoid following the `rdfs:seeAlso` link if not (though -# in this case both are described in the same file). - -@prefix lv2: <http://lv2plug.in/ns/lv2core#> . -@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . -@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . - -<http://lv2plug.in/plugins/eg-sampler> - a lv2:Plugin ; - lv2:binary <sampler@LIB_EXT@> ; - rdfs:seeAlso <sampler.ttl> . - -<http://lv2plug.in/plugins/eg-sampler#ui> - a ui:GtkUI ; - ui:binary <sampler_ui@LIB_EXT@> ; - rdfs:seeAlso <sampler.ttl> . diff --git a/plugins/eg04-sampler.lv2/sampler.c b/plugins/eg04-sampler.lv2/sampler.c deleted file mode 100644 index 54da799..0000000 --- a/plugins/eg04-sampler.lv2/sampler.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - LV2 Sampler Example Plugin - Copyright 2011-2012 David Robillard <d@drobilla.net> - Copyright 2011 Gabriel M. Beddingfield <gabriel@teuton.org> - Copyright 2011 James Morris <jwm.art.net@gmail.com> - - 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 <math.h> -#include <stdlib.h> -#include <string.h> -#ifndef __cplusplus -# include <stdbool.h> -#endif - -#include <sndfile.h> - -#include "lv2/lv2plug.in/ns/ext/atom/forge.h" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/log/log.h" -#include "lv2/lv2plug.in/ns/ext/log/logger.h" -#include "lv2/lv2plug.in/ns/ext/midi/midi.h" -#include "lv2/lv2plug.in/ns/ext/patch/patch.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/lv2core/lv2.h" - -#include "./uris.h" - -enum { - SAMPLER_CONTROL = 0, - SAMPLER_NOTIFY = 1, - SAMPLER_OUT = 2 -}; - -static const char* default_sample_file = "click.wav"; - -typedef struct { - SF_INFO info; // Info about sample from sndfile - float* data; // Sample data in float - char* path; // Path of file - uint32_t path_len; // Length of path -} Sample; - -typedef struct { - // Features - LV2_URID_Map* map; - LV2_Worker_Schedule* schedule; - LV2_Log_Log* log; - - // Forge for creating atoms - LV2_Atom_Forge forge; - - // Logger convenience API - LV2_Log_Logger logger; - - // Sample - Sample* sample; - - // Ports - const LV2_Atom_Sequence* control_port; - LV2_Atom_Sequence* notify_port; - float* output_port; - - // Forge frame for notify port (for writing worker replies) - LV2_Atom_Forge_Frame notify_frame; - - // URIs - SamplerURIs uris; - - // Current position in run() - uint32_t frame_offset; - - // Playback state - sf_count_t frame; - bool play; -} Sampler; - -/** - An atom-like message used internally to apply/free samples. - - This is only used internally to communicate with the worker, it is never - sent to the outside world via a port since it is not POD. It is convenient - to use an Atom header so actual atoms can be easily sent through the same - ringbuffer. -*/ -typedef struct { - LV2_Atom atom; - Sample* sample; -} SampleMessage; - -/** - Load a new sample and return it. - - Since this is of course not a real-time safe action, this is called in the - worker thread only. The sample is loaded and returned only, plugin state is - not modified. -*/ -static Sample* -load_sample(Sampler* self, const char* path) -{ - const size_t path_len = strlen(path); - - lv2_log_trace(&self->logger, "Loading sample %s\n", path); - - Sample* const sample = (Sample*)malloc(sizeof(Sample)); - SF_INFO* const info = &sample->info; - SNDFILE* const sndfile = sf_open(path, SFM_READ, info); - - if (!sndfile || !info->frames || (info->channels != 1)) { - lv2_log_error(&self->logger, "Failed to open sample '%s'\n", path); - free(sample); - return NULL; - } - - // Read data - float* const data = malloc(sizeof(float) * info->frames); - if (!data) { - lv2_log_error(&self->logger, "Failed to allocate memory for sample\n"); - return NULL; - } - sf_seek(sndfile, 0ul, SEEK_SET); - sf_read_float(sndfile, data, info->frames); - sf_close(sndfile); - - // Fill sample struct and return it - sample->data = data; - sample->path = (char*)malloc(path_len + 1); - sample->path_len = (uint32_t)path_len; - memcpy(sample->path, path, path_len + 1); - - return sample; -} - -static void -free_sample(Sampler* self, Sample* sample) -{ - if (sample) { - lv2_log_trace(&self->logger, "Freeing %s\n", sample->path); - free(sample->path); - free(sample->data); - free(sample); - } -} - -/** - Do work in a non-realtime thread. - - This is called for every piece of work scheduled in the audio thread using - self->schedule->schedule_work(). A reply can be sent back to the audio - thread using the provided respond function. -*/ -static LV2_Worker_Status -work(LV2_Handle instance, - LV2_Worker_Respond_Function respond, - LV2_Worker_Respond_Handle handle, - uint32_t size, - const void* data) -{ - Sampler* self = (Sampler*)instance; - const LV2_Atom* atom = (const LV2_Atom*)data; - if (atom->type == self->uris.eg_freeSample) { - // Free old sample - const SampleMessage* msg = (const SampleMessage*)data; - free_sample(self, msg->sample); - } else { - // Handle set message (load sample). - const LV2_Atom_Object* obj = (const LV2_Atom_Object*)data; - - // Get file path from message - const LV2_Atom* file_path = read_set_file(&self->uris, obj); - if (!file_path) { - return LV2_WORKER_ERR_UNKNOWN; - } - - // Load sample. - Sample* sample = load_sample(self, LV2_ATOM_BODY_CONST(file_path)); - if (sample) { - // Loaded sample, send it to run() to be applied. - respond(handle, sizeof(sample), &sample); - } - } - - return LV2_WORKER_SUCCESS; -} - -/** - Handle a response from work() in the audio thread. - - When running normally, this will be called by the host after run(). When - freewheeling, this will be called immediately at the point the work was - scheduled. -*/ -static LV2_Worker_Status -work_response(LV2_Handle instance, - uint32_t size, - const void* data) -{ - Sampler* self = (Sampler*)instance; - - SampleMessage msg = { { sizeof(Sample*), self->uris.eg_freeSample }, - self->sample }; - - // Send a message to the worker to free the current sample - self->schedule->schedule_work(self->schedule->handle, sizeof(msg), &msg); - - // Install the new sample - self->sample = *(Sample*const*)data; - - // Send a notification that we're using a new sample. - lv2_atom_forge_frame_time(&self->forge, self->frame_offset); - write_set_file(&self->forge, &self->uris, - self->sample->path, - self->sample->path_len); - - return LV2_WORKER_SUCCESS; -} - -static void -connect_port(LV2_Handle instance, - uint32_t port, - void* data) -{ - Sampler* self = (Sampler*)instance; - switch (port) { - case SAMPLER_CONTROL: - self->control_port = (const LV2_Atom_Sequence*)data; - break; - case SAMPLER_NOTIFY: - self->notify_port = (LV2_Atom_Sequence*)data; - break; - case SAMPLER_OUT: - self->output_port = (float*)data; - break; - default: - break; - } -} - -static LV2_Handle -instantiate(const LV2_Descriptor* descriptor, - double rate, - const char* path, - const LV2_Feature* const* features) -{ - // Allocate and initialise instance structure. - Sampler* self = (Sampler*)malloc(sizeof(Sampler)); - if (!self) { - return NULL; - } - memset(self, 0, sizeof(Sampler)); - - // Get host features - for (int i = 0; features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_URID__map)) { - self->map = (LV2_URID_Map*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_WORKER__schedule)) { - self->schedule = (LV2_Worker_Schedule*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_LOG__log)) { - self->log = (LV2_Log_Log*)features[i]->data; - } - } - if (!self->map) { - lv2_log_error(&self->logger, "Missing feature urid:map\n"); - goto fail; - } else if (!self->schedule) { - lv2_log_error(&self->logger, "Missing feature work:schedule\n"); - goto fail; - } - - // Map URIs and initialise forge/logger - map_sampler_uris(self->map, &self->uris); - lv2_atom_forge_init(&self->forge, self->map); - lv2_log_logger_init(&self->logger, self->map, self->log); - - // Load the default sample file - const size_t path_len = strlen(path); - const size_t file_len = strlen(default_sample_file); - const size_t len = path_len + file_len; - char* sample_path = (char*)malloc(len + 1); - snprintf(sample_path, len + 1, "%s%s", path, default_sample_file); - self->sample = load_sample(self, sample_path); - free(sample_path); - - return (LV2_Handle)self; - -fail: - free(self); - return 0; -} - -static void -cleanup(LV2_Handle instance) -{ - Sampler* self = (Sampler*)instance; - free_sample(self, self->sample); - free(self); -} - -static void -run(LV2_Handle instance, - uint32_t sample_count) -{ - Sampler* self = (Sampler*)instance; - SamplerURIs* uris = &self->uris; - sf_count_t start_frame = 0; - sf_count_t pos = 0; - float* output = self->output_port; - - // Set up forge to write directly to notify output port. - const uint32_t notify_capacity = self->notify_port->atom.size; - lv2_atom_forge_set_buffer(&self->forge, - (uint8_t*)self->notify_port, - notify_capacity); - - // Start a sequence in the notify output port. - lv2_atom_forge_sequence_head(&self->forge, &self->notify_frame, 0); - - // Read incoming events - LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev) { - self->frame_offset = ev->time.frames; - if (ev->body.type == uris->midi_Event) { - const uint8_t* const msg = (const uint8_t*)(ev + 1); - switch (lv2_midi_message_type(msg)) { - case LV2_MIDI_MSG_NOTE_ON: - start_frame = ev->time.frames; - self->frame = 0; - self->play = true; - break; - default: - break; - } - } else if (lv2_atom_forge_is_object_type(&self->forge, ev->body.type)) { - const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body; - if (obj->body.otype == uris->patch_Set) { - // Received a set message, send it to the worker. - lv2_log_trace(&self->logger, "Queueing set message\n"); - self->schedule->schedule_work(self->schedule->handle, - lv2_atom_total_size(&ev->body), - &ev->body); - } else { - lv2_log_trace(&self->logger, - "Unknown object type %d\n", obj->body.otype); - } - } else { - lv2_log_trace(&self->logger, - "Unknown event type %d\n", ev->body.type); - } - } - - // Render the sample (possibly already in progress) - if (self->play) { - uint32_t f = self->frame; - const uint32_t lf = self->sample->info.frames; - - for (pos = 0; pos < start_frame; ++pos) { - output[pos] = 0; - } - - for (; pos < sample_count && f < lf; ++pos, ++f) { - output[pos] = self->sample->data[f]; - } - - self->frame = f; - - if (f == lf) { - self->play = false; - } - } - - // Add zeros to end if sample not long enough (or not playing) - for (; pos < sample_count; ++pos) { - output[pos] = 0.0f; - } -} - -static LV2_State_Status -save(LV2_Handle instance, - LV2_State_Store_Function store, - LV2_State_Handle handle, - uint32_t flags, - const LV2_Feature* const* features) -{ - Sampler* self = (Sampler*)instance; - if (!self->sample) { - return LV2_STATE_SUCCESS; - } - - LV2_State_Map_Path* map_path = NULL; - for (int i = 0; features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) { - map_path = (LV2_State_Map_Path*)features[i]->data; - } - } - - char* apath = map_path->abstract_path(map_path->handle, self->sample->path); - - store(handle, - self->uris.eg_sample, - apath, - strlen(self->sample->path) + 1, - self->uris.atom_Path, - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); - - free(apath); - - return LV2_STATE_SUCCESS; -} - -static LV2_State_Status -restore(LV2_Handle instance, - LV2_State_Retrieve_Function retrieve, - LV2_State_Handle handle, - uint32_t flags, - const LV2_Feature* const* features) -{ - Sampler* self = (Sampler*)instance; - - size_t size; - uint32_t type; - uint32_t valflags; - - const void* value = retrieve( - handle, - self->uris.eg_sample, - &size, &type, &valflags); - - if (value) { - const char* path = (const char*)value; - lv2_log_trace(&self->logger, "Restoring file %s\n", path); - free_sample(self, self->sample); - self->sample = load_sample(self, path); - } - - return LV2_STATE_SUCCESS; -} - -static const void* -extension_data(const char* uri) -{ - static const LV2_State_Interface state = { save, restore }; - static const LV2_Worker_Interface worker = { work, work_response, NULL }; - if (!strcmp(uri, LV2_STATE__interface)) { - return &state; - } else if (!strcmp(uri, LV2_WORKER__interface)) { - return &worker; - } - return NULL; -} - -static const LV2_Descriptor descriptor = { - EG_SAMPLER_URI, - instantiate, - connect_port, - NULL, // activate, - run, - NULL, // deactivate, - cleanup, - extension_data -}; - -LV2_SYMBOL_EXPORT -const LV2_Descriptor* lv2_descriptor(uint32_t index) -{ - switch (index) { - case 0: - return &descriptor; - default: - return NULL; - } -} diff --git a/plugins/eg04-sampler.lv2/sampler.ttl b/plugins/eg04-sampler.lv2/sampler.ttl deleted file mode 100644 index 2a89dd2..0000000 --- a/plugins/eg04-sampler.lv2/sampler.ttl +++ /dev/null @@ -1,67 +0,0 @@ -@prefix atom: <http://lv2plug.in/ns/ext/atom#> . -@prefix doap: <http://usefulinc.com/ns/doap#> . -@prefix lv2: <http://lv2plug.in/ns/lv2core#> . -@prefix patch: <http://lv2plug.in/ns/ext/patch#> . -@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . -@prefix state: <http://lv2plug.in/ns/ext/state#> . -@prefix ui: <http://lv2plug.in/ns/extensions/ui#> . -@prefix urid: <http://lv2plug.in/ns/ext/urid#> . -@prefix work: <http://lv2plug.in/ns/ext/worker#> . - -<http://lv2plug.in/plugins/eg-sampler#sample> - a lv2:Parameter ; - rdfs:label "sample" ; - rdfs:range atom:Path . - -<http://lv2plug.in/plugins/eg-sampler> - a lv2:Plugin ; - doap:name "Example Sampler" ; - doap:license <http://opensource.org/licenses/isc> ; - lv2:project <http://lv2plug.in/ns/lv2> ; - lv2:requiredFeature urid:map , - work:schedule ; - lv2:optionalFeature lv2:hardRTCapable , - state:loadDefaultState ; - lv2:extensionData state:interface , - work:interface ; - ui:ui <http://lv2plug.in/plugins/eg-sampler#ui> ; - patch:writable <http://lv2plug.in/plugins/eg-sampler#sample> ; - lv2:port [ - a lv2:InputPort , - atom:AtomPort ; - atom:bufferType atom:Sequence ; - atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> , - patch:Message ; - lv2:designation lv2:control ; - lv2:index 0 ; - lv2:symbol "control" ; - lv2:name "Control" - ] , [ - a lv2:OutputPort , - atom:AtomPort ; - atom:bufferType atom:Sequence ; - atom:supports patch:Message ; - lv2:designation lv2:control ; - lv2:index 1 ; - lv2:symbol "notify" ; - lv2:name "Notify" - ] , [ - a lv2:AudioPort , - lv2:OutputPort ; - lv2:index 2 ; - lv2:symbol "out" ; - lv2:name "Out" - ] ; - state:state [ - <http://lv2plug.in/plugins/eg-sampler#sample> <click.wav> - ] . - -<http://lv2plug.in/plugins/eg-sampler#ui> - a ui:GtkUI ; - lv2:requiredFeature urid:map ; - lv2:extensionData ui:showInterface ; - ui:portNotification [ - ui:plugin <http://lv2plug.in/plugins/eg-sampler> ; - lv2:symbol "notify" ; - ui:notifyType atom:Blank - ] . diff --git a/plugins/eg04-sampler.lv2/sampler_ui.c b/plugins/eg04-sampler.lv2/sampler_ui.c deleted file mode 100644 index d691c98..0000000 --- a/plugins/eg04-sampler.lv2/sampler_ui.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - LV2 Sampler Example Plugin UI - Copyright 2011-2012 David Robillard <d@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 <gtk/gtk.h> - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/atom/forge.h" -#include "lv2/lv2plug.in/ns/ext/atom/util.h" -#include "lv2/lv2plug.in/ns/ext/patch/patch.h" -#include "lv2/lv2plug.in/ns/ext/urid/urid.h" -#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" - -#include "./uris.h" - -#define SAMPLER_UI_URI "http://lv2plug.in/plugins/eg-sampler#ui" - -typedef struct { - LV2_Atom_Forge forge; - - LV2_URID_Map* map; - SamplerURIs uris; - - LV2UI_Write_Function write; - LV2UI_Controller controller; - - GtkWidget* box; - GtkWidget* button; - GtkWidget* label; - GtkWidget* window; /* For optional show interface. */ -} SamplerUI; - -static void -on_load_clicked(GtkWidget* widget, - void* handle) -{ - SamplerUI* ui = (SamplerUI*)handle; - - /* Create a dialog to select a sample file. */ - GtkWidget* dialog = gtk_file_chooser_dialog_new( - "Load Sample", - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - 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; - } - - /* 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); - -#define OBJ_BUF_SIZE 1024 - uint8_t obj_buf[OBJ_BUF_SIZE]; - lv2_atom_forge_set_buffer(&ui->forge, obj_buf, OBJ_BUF_SIZE); - - LV2_Atom* msg = write_set_file(&ui->forge, &ui->uris, - filename, strlen(filename)); - - ui->write(ui->controller, 0, lv2_atom_total_size(msg), - ui->uris.atom_eventTransfer, - msg); - - g_free(filename); -} - -static LV2UI_Handle -instantiate(const LV2UI_Descriptor* descriptor, - const char* plugin_uri, - const char* bundle_path, - LV2UI_Write_Function write_function, - LV2UI_Controller controller, - LV2UI_Widget* widget, - const LV2_Feature* const* features) -{ - SamplerUI* ui = (SamplerUI*)malloc(sizeof(SamplerUI)); - ui->map = NULL; - ui->write = write_function; - ui->controller = controller; - ui->box = NULL; - ui->button = NULL; - ui->label = NULL; - ui->window = NULL; - - *widget = NULL; - - for (int i = 0; features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_URID_URI "#map")) { - ui->map = (LV2_URID_Map*)features[i]->data; - } - } - - if (!ui->map) { - fprintf(stderr, "sampler_ui: Host does not support urid:Map\n"); - free(ui); - return NULL; - } - - map_sampler_uris(ui->map, &ui->uris); - - lv2_atom_forge_init(&ui->forge, ui->map); - - ui->box = gtk_vbox_new(FALSE, 4); - ui->label = gtk_label_new("?"); - ui->button = gtk_button_new_with_label("Load Sample"); - gtk_box_pack_start(GTK_BOX(ui->box), ui->label, TRUE, TRUE, 4); - gtk_box_pack_start(GTK_BOX(ui->box), ui->button, FALSE, FALSE, 4); - g_signal_connect(ui->button, "clicked", - G_CALLBACK(on_load_clicked), - ui); - - *widget = ui->box; - - return ui; -} - -static void -cleanup(LV2UI_Handle handle) -{ - SamplerUI* ui = (SamplerUI*)handle; - gtk_widget_destroy(ui->button); - free(ui); -} - -static void -port_event(LV2UI_Handle handle, - uint32_t port_index, - uint32_t buffer_size, - uint32_t format, - const void* buffer) -{ - SamplerUI* ui = (SamplerUI*)handle; - if (format == ui->uris.atom_eventTransfer) { - const LV2_Atom* atom = (const LV2_Atom*)buffer; - if (atom->type == ui->uris.atom_Blank) { - const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom; - const LV2_Atom* file_uri = read_set_file(&ui->uris, obj); - if (!file_uri) { - fprintf(stderr, "Unknown message sent to UI.\n"); - return; - } - - const char* uri = (const char*)LV2_ATOM_BODY_CONST(file_uri); - gtk_label_set_text(GTK_LABEL(ui->label), uri); - } else { - fprintf(stderr, "Unknown message type.\n"); - } - } else { - fprintf(stderr, "Unknown format.\n"); - } -} - -/* Optional non-embedded UI show interface. */ -static int -ui_show(LV2UI_Handle handle) -{ - SamplerUI* ui = (SamplerUI*)handle; - - int argc = 0; - gtk_init(&argc, NULL); - - ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_container_add(GTK_CONTAINER(ui->window), ui->box); - gtk_widget_show_all(ui->window); - gtk_window_present(GTK_WINDOW(ui->window)); - - return 0; -} - -/* Optional non-embedded UI hide interface. */ -static int -ui_hide(LV2UI_Handle handle) -{ - return 0; -} - -/* Idle interface for optional non-embedded UI. */ -static int -ui_idle(LV2UI_Handle handle) -{ - SamplerUI* ui = (SamplerUI*)handle; - if (ui->window) { - gtk_main_iteration(); - } - return 0; -} - -static const void* -extension_data(const char* uri) -{ - static const LV2UI_Show_Interface show = { ui_show, ui_hide }; - static const LV2UI_Idle_Interface idle = { ui_idle }; - if (!strcmp(uri, LV2_UI__showInterface)) { - return &show; - } else if (!strcmp(uri, LV2_UI__idleInterface)) { - return &idle; - } - return NULL; -} - -static const LV2UI_Descriptor descriptor = { - SAMPLER_UI_URI, - instantiate, - cleanup, - port_event, - extension_data -}; - -LV2_SYMBOL_EXPORT -const LV2UI_Descriptor* -lv2ui_descriptor(uint32_t index) -{ - switch (index) { - case 0: - return &descriptor; - default: - return NULL; - } -} diff --git a/plugins/eg04-sampler.lv2/uris.h b/plugins/eg04-sampler.lv2/uris.h deleted file mode 100644 index 8e9faee..0000000 --- a/plugins/eg04-sampler.lv2/uris.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - LV2 Sampler Example Plugin - Copyright 2011-2012 David Robillard <d@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. -*/ - -#ifndef SAMPLER_URIS_H -#define SAMPLER_URIS_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/state/state.h" - -#define EG_SAMPLER_URI "http://lv2plug.in/plugins/eg-sampler" -#define EG_SAMPLER__sample EG_SAMPLER_URI "#sample" -#define EG_SAMPLER__applySample EG_SAMPLER_URI "#applySample" -#define EG_SAMPLER__freeSample EG_SAMPLER_URI "#freeSample" - -typedef struct { - LV2_URID atom_Blank; - LV2_URID atom_Path; - LV2_URID atom_Resource; - LV2_URID atom_Sequence; - LV2_URID atom_URID; - LV2_URID atom_eventTransfer; - LV2_URID eg_applySample; - LV2_URID eg_sample; - LV2_URID eg_freeSample; - LV2_URID midi_Event; - LV2_URID patch_Set; - LV2_URID patch_property; - LV2_URID patch_value; -} SamplerURIs; - -static inline void -map_sampler_uris(LV2_URID_Map* map, SamplerURIs* uris) -{ - uris->atom_Blank = map->map(map->handle, LV2_ATOM__Blank); - uris->atom_Path = map->map(map->handle, LV2_ATOM__Path); - uris->atom_Resource = map->map(map->handle, LV2_ATOM__Resource); - uris->atom_Sequence = map->map(map->handle, LV2_ATOM__Sequence); - uris->atom_URID = map->map(map->handle, LV2_ATOM__URID); - uris->atom_eventTransfer = map->map(map->handle, LV2_ATOM__eventTransfer); - uris->eg_applySample = map->map(map->handle, EG_SAMPLER__applySample); - uris->eg_freeSample = map->map(map->handle, EG_SAMPLER__freeSample); - uris->eg_sample = map->map(map->handle, EG_SAMPLER__sample); - uris->midi_Event = map->map(map->handle, LV2_MIDI__MidiEvent); - uris->patch_Set = map->map(map->handle, LV2_PATCH__Set); - uris->patch_property = map->map(map->handle, LV2_PATCH__property); - uris->patch_value = map->map(map->handle, LV2_PATCH__value); -} - -/** - * Write a message like the following to @p forge: - * [] - * a patch:Set ; - * patch:property eg:sample ; - * patch:value </home/me/foo.wav> . - */ -static inline LV2_Atom* -write_set_file(LV2_Atom_Forge* forge, - const SamplerURIs* uris, - const char* filename, - const uint32_t filename_len) -{ - LV2_Atom_Forge_Frame frame; - LV2_Atom* set = (LV2_Atom*)lv2_atom_forge_object( - forge, &frame, 0, uris->patch_Set); - - lv2_atom_forge_key(forge, uris->patch_property); - lv2_atom_forge_urid(forge, uris->eg_sample); - lv2_atom_forge_key(forge, uris->patch_value); - lv2_atom_forge_path(forge, filename, filename_len); - - lv2_atom_forge_pop(forge, &frame); - - return set; -} - -/** - * Get the file path from a message like: - * [] - * a patch:Set ; - * patch:property eg:sample ; - * patch:value </home/me/foo.wav> . - */ -static inline const LV2_Atom* -read_set_file(const SamplerURIs* uris, - const LV2_Atom_Object* obj) -{ - if (obj->body.otype != uris->patch_Set) { - fprintf(stderr, "Ignoring unknown message type %d\n", obj->body.otype); - return NULL; - } - - /* Get property URI. */ - const LV2_Atom* property = NULL; - lv2_atom_object_get(obj, uris->patch_property, &property, 0); - if (!property) { - fprintf(stderr, "Malformed set message has no body.\n"); - return NULL; - } else if (property->type != uris->atom_URID) { - fprintf(stderr, "Malformed set message has non-URID property.\n"); - return NULL; - } else if (((const LV2_Atom_URID*)property)->body != uris->eg_sample) { - fprintf(stderr, "Set message for unknown property.\n"); - return NULL; - } - - /* Get value. */ - const LV2_Atom* file_path = NULL; - lv2_atom_object_get(obj, uris->patch_value, &file_path, 0); - if (!file_path) { - fprintf(stderr, "Malformed set message has no value.\n"); - return NULL; - } else if (file_path->type != uris->atom_Path) { - fprintf(stderr, "Set message value is not a Path.\n"); - return NULL; - } - - return file_path; -} - -#endif /* SAMPLER_URIS_H */ diff --git a/plugins/eg04-sampler.lv2/waf b/plugins/eg04-sampler.lv2/waf deleted file mode 120000 index 59a1ac9..0000000 --- a/plugins/eg04-sampler.lv2/waf +++ /dev/null @@ -1 +0,0 @@ -../../waf
\ No newline at end of file diff --git a/plugins/eg04-sampler.lv2/wscript b/plugins/eg04-sampler.lv2/wscript deleted file mode 100644 index 732c904..0000000 --- a/plugins/eg04-sampler.lv2/wscript +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python -from waflib.extras import autowaf as autowaf -import re - -# Variables for 'waf dist' -APPNAME = 'eg-sampler.lv2' -VERSION = '1.0.0' - -# Mandatory variables -top = '.' -out = 'build' - -def options(opt): - opt.load('compiler_c') - autowaf.set_options(opt) - -def configure(conf): - conf.load('compiler_c') - autowaf.configure(conf) - autowaf.set_c99_mode(conf) - autowaf.display_header('Sampler Configuration') - - if not autowaf.is_child(): - autowaf.check_pkg(conf, 'lv2', atleast_version='1.2.1', uselib_store='LV2') - - autowaf.check_pkg(conf, 'sndfile', uselib_store='SNDFILE', - atleast_version='1.0.0', mandatory=True) - autowaf.check_pkg(conf, 'gtk+-2.0', uselib_store='GTK2', - atleast_version='2.18.0', mandatory=False) - - autowaf.display_msg(conf, 'LV2 bundle directory', conf.env.LV2DIR) - print('') - -def build(bld): - bundle = 'eg-sampler.lv2' - - # Make a pattern for shared objects without the 'lib' prefix - module_pat = re.sub('^lib', '', bld.env.cshlib_PATTERN) - module_ext = module_pat[module_pat.rfind('.'):] - - # Build manifest.ttl by substitution (for portable lib extension) - bld(features = 'subst', - source = 'manifest.ttl.in', - target = '%s/%s' % (bundle, 'manifest.ttl'), - install_path = '${LV2DIR}/%s' % bundle, - LIB_EXT = module_ext) - - # Copy other data files to build bundle (build/eg-sampler.lv2) - for i in ['sampler.ttl', 'click.wav']: - bld(features = 'subst', - is_copy = True, - source = i, - target = '%s/%s' % (bundle, i), - install_path = '${LV2DIR}/%s' % bundle) - - # Use LV2 headers from parent directory if building as a sub-project - includes = ['.'] - if autowaf.is_child: - includes += ['../..'] - - # Build plugin library - obj = bld(features = 'c cshlib', - source = 'sampler.c', - name = 'sampler', - target = '%s/sampler' % bundle, - install_path = '${LV2DIR}/%s' % bundle, - use = 'SNDFILE LV2', - includes = includes) - obj.env.cshlib_PATTERN = module_pat - - # Build UI library - if bld.is_defined('HAVE_GTK2'): - obj = bld(features = 'c cshlib', - source = 'sampler_ui.c', - name = 'sampler_ui', - target = '%s/sampler_ui' % bundle, - install_path = '${LV2DIR}/%s' % bundle, - use = 'GTK2 LV2', - includes = includes) - obj.env.cshlib_PATTERN = module_pat |