aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/eg04-sampler.lv2
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2014-08-06 01:26:06 +0000
committerDavid Robillard <d@drobilla.net>2014-08-06 01:26:06 +0000
commit74d7751c37d2c991d244c1c23e1a4cd24451ac41 (patch)
treeaf301c27cbf585ae71f95e9e14e2380f062e6739 /plugins/eg04-sampler.lv2
parentf181b31c11d6a9317695c68c6cce30319e7e2faa (diff)
downloadlv2-74d7751c37d2c991d244c1c23e1a4cd24451ac41.tar.xz
Order book chapters in build script rather than by bundle name.
Diffstat (limited to 'plugins/eg04-sampler.lv2')
-rw-r--r--plugins/eg04-sampler.lv2/README.txt13
-rw-r--r--plugins/eg04-sampler.lv2/click.wavbin644 -> 0 bytes
-rw-r--r--plugins/eg04-sampler.lv2/manifest.ttl.in19
-rw-r--r--plugins/eg04-sampler.lv2/sampler.c483
-rw-r--r--plugins/eg04-sampler.lv2/sampler.ttl67
-rw-r--r--plugins/eg04-sampler.lv2/sampler_ui.c241
-rw-r--r--plugins/eg04-sampler.lv2/uris.h135
l---------plugins/eg04-sampler.lv2/waf1
-rw-r--r--plugins/eg04-sampler.lv2/wscript80
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
deleted file mode 100644
index 520a18c..0000000
--- a/plugins/eg04-sampler.lv2/click.wav
+++ /dev/null
Binary files differ
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