aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/eg-sampler.lv2
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2013-02-11 00:18:55 +0000
committerDavid Robillard <d@drobilla.net>2013-02-11 00:18:55 +0000
commitb91e1a81db7b45d0460da1c8a134d855e0ff265c (patch)
tree3da714cd19b9171bc48614f1442c82383550ffca /plugins/eg-sampler.lv2
parent5367f7265e123aa8a26f8e3d3fb964f18c3250b2 (diff)
downloadlv2-b91e1a81db7b45d0460da1c8a134d855e0ff265c.tar.xz
Order examples in a sensible progression for the book.
Diffstat (limited to 'plugins/eg-sampler.lv2')
-rw-r--r--plugins/eg-sampler.lv2/README.txt1
-rw-r--r--plugins/eg-sampler.lv2/click.wavbin644 -> 0 bytes
-rw-r--r--plugins/eg-sampler.lv2/manifest.ttl.in13
-rw-r--r--plugins/eg-sampler.lv2/sampler.c498
-rw-r--r--plugins/eg-sampler.lv2/sampler.ttl83
-rw-r--r--plugins/eg-sampler.lv2/sampler_ui.c201
-rw-r--r--plugins/eg-sampler.lv2/uris.h142
l---------plugins/eg-sampler.lv2/waf1
-rw-r--r--plugins/eg-sampler.lv2/wscript80
9 files changed, 0 insertions, 1019 deletions
diff --git a/plugins/eg-sampler.lv2/README.txt b/plugins/eg-sampler.lv2/README.txt
deleted file mode 100644
index c1cac46..0000000
--- a/plugins/eg-sampler.lv2/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-== Sampler ==
diff --git a/plugins/eg-sampler.lv2/click.wav b/plugins/eg-sampler.lv2/click.wav
deleted file mode 100644
index 520a18c..0000000
--- a/plugins/eg-sampler.lv2/click.wav
+++ /dev/null
Binary files differ
diff --git a/plugins/eg-sampler.lv2/manifest.ttl.in b/plugins/eg-sampler.lv2/manifest.ttl.in
deleted file mode 100644
index b4fa23e..0000000
--- a/plugins/eg-sampler.lv2/manifest.ttl.in
+++ /dev/null
@@ -1,13 +0,0 @@
-@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/eg-sampler.lv2/sampler.c b/plugins/eg-sampler.lv2/sampler.c
deleted file mode 100644
index 5bb4e54..0000000
--- a/plugins/eg-sampler.lv2/sampler.c
+++ /dev/null
@@ -1,498 +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.
-*/
-
-/**
- @file sampler.c Sampler Plugin
-
- A simple example of an LV2 sampler that dynamically loads a single sample
- (based on incoming events) and triggers their playback (based on incoming
- MIDI note events).
-
- 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
-*/
-
-#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 */
- size_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 = 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 (is_object_type(uris, ev->body.type)) {
- const LV2_Atom_Object* obj = (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/eg-sampler.lv2/sampler.ttl b/plugins/eg-sampler.lv2/sampler.ttl
deleted file mode 100644
index e008de0..0000000
--- a/plugins/eg-sampler.lv2/sampler.ttl
+++ /dev/null
@@ -1,83 +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.
-
-@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 ;
- ui:portNotification [
- ui:plugin <http://lv2plug.in/plugins/eg-sampler> ;
- lv2:symbol "notify" ;
- ui:notifyType atom:Blank
- ] .
diff --git a/plugins/eg-sampler.lv2/sampler_ui.c b/plugins/eg-sampler.lv2/sampler_ui.c
deleted file mode 100644
index 40922ae..0000000
--- a/plugins/eg-sampler.lv2/sampler_ui.c
+++ /dev/null
@@ -1,201 +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.
-*/
-
-/**
- @file ui.c Sampler Plugin UI
-*/
-
-#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;
-} 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;
-
- *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) {
- LV2_Atom* atom = (LV2_Atom*)buffer;
- if (atom->type == ui->uris.atom_Blank) {
- LV2_Atom_Object* obj = (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(file_uri);
- gtk_label_set_text(GTK_LABEL(ui->label), uri);
- } else {
- fprintf(stderr, "Unknown message type.\n");
- }
- } else {
- fprintf(stderr, "Unknown format.\n");
- }
-}
-
-static const void*
-extension_data(const char* uri)
-{
- 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/eg-sampler.lv2/uris.h b/plugins/eg-sampler.lv2/uris.h
deleted file mode 100644
index e2ec6d0..0000000
--- a/plugins/eg-sampler.lv2/uris.h
+++ /dev/null
@@ -1,142 +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);
-}
-
-static inline bool
-is_object_type(const SamplerURIs* uris, LV2_URID type)
-{
- return type == uris->atom_Resource
- || type == uris->atom_Blank;
-}
-
-/**
- * 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 size_t filename_len)
-{
- LV2_Atom_Forge_Frame frame;
- LV2_Atom* set = (LV2_Atom*)lv2_atom_forge_blank(
- forge, &frame, 1, uris->patch_Set);
-
- lv2_atom_forge_property_head(forge, uris->patch_property, 0);
- lv2_atom_forge_urid(forge, uris->eg_sample);
- lv2_atom_forge_property_head(forge, uris->patch_value, 0);
- 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 (((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/eg-sampler.lv2/waf b/plugins/eg-sampler.lv2/waf
deleted file mode 120000
index 59a1ac9..0000000
--- a/plugins/eg-sampler.lv2/waf
+++ /dev/null
@@ -1 +0,0 @@
-../../waf \ No newline at end of file
diff --git a/plugins/eg-sampler.lv2/wscript b/plugins/eg-sampler.lv2/wscript
deleted file mode 100644
index 732c904..0000000
--- a/plugins/eg-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