diff options
Diffstat (limited to 'plugins/eg-params.lv2')
| -rw-r--r-- | plugins/eg-params.lv2/README.txt | 21 | ||||
| -rw-r--r-- | plugins/eg-params.lv2/manifest.ttl.in | 7 | ||||
| -rw-r--r-- | plugins/eg-params.lv2/meson.build | 42 | ||||
| -rw-r--r-- | plugins/eg-params.lv2/params.c | 519 | ||||
| -rw-r--r-- | plugins/eg-params.lv2/params.ttl | 126 | ||||
| -rw-r--r-- | plugins/eg-params.lv2/state_map.h | 102 |
6 files changed, 0 insertions, 817 deletions
diff --git a/plugins/eg-params.lv2/README.txt b/plugins/eg-params.lv2/README.txt deleted file mode 100644 index acf90c1..0000000 --- a/plugins/eg-params.lv2/README.txt +++ /dev/null @@ -1,21 +0,0 @@ -== Params == - -The basic LV2 mechanism for controls is -http://lv2plug.in/ns/lv2core#ControlPort[lv2:ControlPort], inherited from -LADSPA. Control ports are problematic because they are not sample accurate, -support only one type (`float`), and require that plugins poll to know when a -control has changed. - -Parameters can be used instead to address these issues. Parameters can be -thought of as properties of a plugin instance; they are identified by URI and -have a value of any type. This deliberately meshes with the concept of plugin -state defined by the http://lv2plug.in/ns/ext/state[LV2 state extension]. -The state extension allows plugins to save and restore their parameters (along -with other internal state information, if necessary). - -Parameters are accessed and manipulated using messages sent via a sequence -port. The http://lv2plug.in/ns/ext/patch[LV2 patch extension] defines the -standard messages for working with parameters. Typically, only two are used -for simple plugins: http://lv2plug.in/ns/ext/patch#Set[patch:Set] sets a -parameter to some value, and http://lv2plug.in/ns/ext/patch#Get[patch:Get] -requests that the plugin send a description of its parameters. diff --git a/plugins/eg-params.lv2/manifest.ttl.in b/plugins/eg-params.lv2/manifest.ttl.in deleted file mode 100644 index 913de7c..0000000 --- a/plugins/eg-params.lv2/manifest.ttl.in +++ /dev/null @@ -1,7 +0,0 @@ -@prefix lv2: <http://lv2plug.in/ns/lv2core#> . -@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . - -<http://lv2plug.in/plugins/eg-params> - a lv2:Plugin ; - lv2:binary <params@LIB_EXT@> ; - rdfs:seeAlso <params.ttl> . diff --git a/plugins/eg-params.lv2/meson.build b/plugins/eg-params.lv2/meson.build deleted file mode 100644 index 83c6ef9..0000000 --- a/plugins/eg-params.lv2/meson.build +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2022 David Robillard <d@drobilla.net> -# SPDX-License-Identifier: 0BSD OR ISC - -plugin_sources = files('params.c') -bundle_name = 'eg-params.lv2' -data_filenames = ['manifest.ttl.in', 'params.ttl'] - -module = shared_library( - 'params', - plugin_sources, - c_args: c_suppressions, - dependencies: [lv2_dep, m_dep], - gnu_symbol_visibility: 'hidden', - implicit_include_directories: false, - install: true, - install_dir: lv2dir / bundle_name, - name_prefix: '', -) - -config = configuration_data( - { - 'LIB_EXT': '.' + module.full_path().split('.')[-1], - }, -) - -foreach filename : data_filenames - if filename.endswith('.in') - configure_file( - configuration: config, - input: files(filename), - install_dir: lv2dir / bundle_name, - output: filename.substring(0, -3), - ) - else - configure_file( - copy: true, - input: files(filename), - install_dir: lv2dir / bundle_name, - output: filename, - ) - endif -endforeach diff --git a/plugins/eg-params.lv2/params.c b/plugins/eg-params.lv2/params.c deleted file mode 100644 index 9fbaa46..0000000 --- a/plugins/eg-params.lv2/params.c +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright 2014-2016 David Robillard <d@drobilla.net> -// SPDX-License-Identifier: ISC - -#include "state_map.h" - -#include <lv2/atom/atom.h> -#include <lv2/atom/forge.h> -#include <lv2/atom/util.h> -#include <lv2/core/lv2.h> -#include <lv2/core/lv2_util.h> -#include <lv2/log/log.h> -#include <lv2/log/logger.h> -#include <lv2/midi/midi.h> -#include <lv2/patch/patch.h> -#include <lv2/state/state.h> -#include <lv2/urid/urid.h> - -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define MAX_STRING 1024 - -#define EG_PARAMS_URI "http://lv2plug.in/plugins/eg-params" - -#define N_PROPS 9 - -typedef struct { - LV2_URID plugin; - LV2_URID atom_Path; - LV2_URID atom_Sequence; - LV2_URID atom_URID; - LV2_URID atom_eventTransfer; - LV2_URID eg_spring; - LV2_URID midi_Event; - LV2_URID patch_Get; - LV2_URID patch_Set; - LV2_URID patch_Put; - LV2_URID patch_body; - LV2_URID patch_subject; - LV2_URID patch_property; - LV2_URID patch_value; -} URIs; - -typedef struct { - LV2_Atom_Int aint; - LV2_Atom_Long along; - LV2_Atom_Float afloat; - LV2_Atom_Double adouble; - LV2_Atom_Bool abool; - LV2_Atom astring; - char string[MAX_STRING]; - LV2_Atom apath; - char path[MAX_STRING]; - LV2_Atom_Float lfo; - LV2_Atom_Float spring; -} State; - -static inline void -map_uris(LV2_URID_Map* map, URIs* uris) -{ - uris->plugin = map->map(map->handle, EG_PARAMS_URI); - - uris->atom_Path = map->map(map->handle, LV2_ATOM__Path); - 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_spring = map->map(map->handle, EG_PARAMS_URI "#spring"); - uris->midi_Event = map->map(map->handle, LV2_MIDI__MidiEvent); - uris->patch_Get = map->map(map->handle, LV2_PATCH__Get); - uris->patch_Set = map->map(map->handle, LV2_PATCH__Set); - uris->patch_Put = map->map(map->handle, LV2_PATCH__Put); - uris->patch_body = map->map(map->handle, LV2_PATCH__body); - uris->patch_subject = map->map(map->handle, LV2_PATCH__subject); - uris->patch_property = map->map(map->handle, LV2_PATCH__property); - uris->patch_value = map->map(map->handle, LV2_PATCH__value); -} - -enum { PARAMS_IN = 0, PARAMS_OUT = 1 }; - -typedef struct { - // Features - LV2_URID_Map* map; - LV2_URID_Unmap* unmap; - LV2_Log_Logger log; - - // Forge for creating atoms - LV2_Atom_Forge forge; - - // Ports - const LV2_Atom_Sequence* in_port; - LV2_Atom_Sequence* out_port; - - // URIs - URIs uris; - - // Plugin state - StateMapItem props[N_PROPS]; - State state; - - // Buffer for making strings from URIDs if unmap is not provided - char urid_buf[12]; -} Params; - -static void -connect_port(LV2_Handle instance, uint32_t port, void* data) -{ - Params* self = (Params*)instance; - switch (port) { - case PARAMS_IN: - self->in_port = (const LV2_Atom_Sequence*)data; - break; - case PARAMS_OUT: - self->out_port = (LV2_Atom_Sequence*)data; - break; - default: - break; - } -} - -static LV2_Handle -instantiate(const LV2_Descriptor* descriptor, - double rate, - const char* path, - const LV2_Feature* const* features) -{ - // Allocate instance - Params* self = (Params*)calloc(1, sizeof(Params)); - if (!self) { - return NULL; - } - - // Get host features - // clang-format off - const char* missing = lv2_features_query( - features, - LV2_LOG__log, &self->log.log, false, - LV2_URID__map, &self->map, true, - LV2_URID__unmap, &self->unmap, false, - NULL); - // clang-format on - - lv2_log_logger_set_map(&self->log, self->map); - if (missing) { - lv2_log_error(&self->log, "Missing feature <%s>\n", missing); - free(self); - return NULL; - } - - // Map URIs and initialise forge - map_uris(self->map, &self->uris); - lv2_atom_forge_init(&self->forge, self->map); - - // Initialise state dictionary - // clang-format off - State* state = &self->state; - state_map_init( - self->props, self->map, self->map->handle, - EG_PARAMS_URI "#int", STATE_MAP_INIT(Int, &state->aint), - EG_PARAMS_URI "#long", STATE_MAP_INIT(Long, &state->along), - EG_PARAMS_URI "#float", STATE_MAP_INIT(Float, &state->afloat), - EG_PARAMS_URI "#double", STATE_MAP_INIT(Double, &state->adouble), - EG_PARAMS_URI "#bool", STATE_MAP_INIT(Bool, &state->abool), - EG_PARAMS_URI "#string", STATE_MAP_INIT(String, &state->astring), - EG_PARAMS_URI "#path", STATE_MAP_INIT(Path, &state->apath), - EG_PARAMS_URI "#lfo", STATE_MAP_INIT(Float, &state->lfo), - EG_PARAMS_URI "#spring", STATE_MAP_INIT(Float, &state->spring), - NULL); - // clang-format on - - return (LV2_Handle)self; -} - -static void -cleanup(LV2_Handle instance) -{ - free(instance); -} - -/** Helper function to unmap a URID if possible. */ -static const char* -unmap(Params* self, LV2_URID urid) -{ - if (self->unmap) { - return self->unmap->unmap(self->unmap->handle, urid); - } - - snprintf(self->urid_buf, sizeof(self->urid_buf), "%u", urid); - return self->urid_buf; -} - -static LV2_State_Status -check_type(Params* self, LV2_URID key, LV2_URID type, LV2_URID required_type) -{ - if (type != required_type) { - lv2_log_trace(&self->log, - "Bad type <%s> for <%s> (needs <%s>)\n", - unmap(self, type), - unmap(self, key), - unmap(self, required_type)); - return LV2_STATE_ERR_BAD_TYPE; - } - return LV2_STATE_SUCCESS; -} - -static LV2_State_Status -set_parameter(Params* self, - LV2_URID key, - uint32_t size, - LV2_URID type, - const void* body, - bool from_state) -{ - // Look up property in state dictionary - const StateMapItem* entry = state_map_find(self->props, N_PROPS, key); - if (!entry) { - lv2_log_trace(&self->log, "Unknown parameter <%s>\n", unmap(self, key)); - return LV2_STATE_ERR_NO_PROPERTY; - } - - // Ensure given type matches property's type - if (check_type(self, key, type, entry->value->type)) { - return LV2_STATE_ERR_BAD_TYPE; - } - - // Set property value in state dictionary - lv2_log_trace(&self->log, "Set <%s>\n", entry->uri); - memcpy(entry->value + 1, body, size); - entry->value->size = size; - return LV2_STATE_SUCCESS; -} - -static const LV2_Atom* -get_parameter(Params* self, LV2_URID key) -{ - const StateMapItem* entry = state_map_find(self->props, N_PROPS, key); - if (entry) { - lv2_log_trace(&self->log, "Get <%s>\n", entry->uri); - return entry->value; - } - - lv2_log_trace(&self->log, "Unknown parameter <%s>\n", unmap(self, key)); - return NULL; -} - -static LV2_State_Status -write_param_to_forge(LV2_State_Handle handle, - uint32_t key, - const void* value, - size_t size, - uint32_t type, - uint32_t flags) -{ - LV2_Atom_Forge* forge = (LV2_Atom_Forge*)handle; - - if (!lv2_atom_forge_key(forge, key) || - !lv2_atom_forge_atom(forge, size, type) || - !lv2_atom_forge_write(forge, value, size)) { - return LV2_STATE_ERR_UNKNOWN; - } - - return LV2_STATE_SUCCESS; -} - -static void -store_prop(Params* self, - LV2_State_Map_Path* map_path, - LV2_State_Status* save_status, - LV2_State_Store_Function store, - LV2_State_Handle handle, - LV2_URID key, - const LV2_Atom* value) -{ - LV2_State_Status st = LV2_STATE_SUCCESS; - if (map_path && value->type == self->uris.atom_Path) { - // Map path to abstract path for portable storage - const char* path = (const char*)(value + 1); - char* apath = map_path->abstract_path(map_path->handle, path); - st = store(handle, - key, - apath, - strlen(apath) + 1, - self->uris.atom_Path, - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); - free(apath); - } else { - // Store simple property - st = store(handle, - key, - value + 1, - value->size, - value->type, - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); - } - - if (save_status && !*save_status) { - *save_status = st; - } -} - -/** - State save method. - - This is used in the usual way when called by the host to save plugin state, - but also internally for writing messages in the audio thread by passing a - "store" function which actually writes the description to the forge. -*/ -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) -{ - Params* self = (Params*)instance; - LV2_State_Map_Path* map_path = - (LV2_State_Map_Path*)lv2_features_data(features, LV2_STATE__mapPath); - - LV2_State_Status st = LV2_STATE_SUCCESS; - for (unsigned i = 0; i < N_PROPS; ++i) { - const StateMapItem* prop = &self->props[i]; - store_prop(self, map_path, &st, store, handle, prop->urid, prop->value); - } - - return st; -} - -static void -retrieve_prop(Params* self, - LV2_State_Status* restore_status, - LV2_State_Retrieve_Function retrieve, - LV2_State_Handle handle, - LV2_URID key) -{ - // Retrieve value from saved state - size_t vsize = 0; - uint32_t vtype = 0; - uint32_t vflags = 0; - const void* value = retrieve(handle, key, &vsize, &vtype, &vflags); - - // Set plugin instance state - const LV2_State_Status st = - value ? set_parameter(self, key, vsize, vtype, value, true) - : LV2_STATE_ERR_NO_PROPERTY; - - if (!*restore_status) { - *restore_status = st; // Set status if there has been no error yet - } -} - -/** State restore method. */ -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) -{ - Params* self = (Params*)instance; - LV2_State_Status st = LV2_STATE_SUCCESS; - - for (unsigned i = 0; i < N_PROPS; ++i) { - retrieve_prop(self, &st, retrieve, handle, self->props[i].urid); - } - - return st; -} - -static inline bool -subject_is_plugin(Params* self, const LV2_Atom_URID* subject) -{ - // This simple plugin only supports one subject: itself - return (!subject || (subject->atom.type == self->uris.atom_URID && - subject->body == self->uris.plugin)); -} - -static void -run(LV2_Handle instance, uint32_t sample_count) -{ - Params* self = (Params*)instance; - URIs* uris = &self->uris; - - // Initially, self->out_port contains a Chunk with size set to capacity - // Set up forge to write directly to output port - const uint32_t out_capacity = self->out_port->atom.size; - lv2_atom_forge_set_buffer( - &self->forge, (uint8_t*)self->out_port, out_capacity); - - // Start a sequence in the output port - LV2_Atom_Forge_Frame out_frame; - lv2_atom_forge_sequence_head(&self->forge, &out_frame, 0); - - // Read incoming events - LV2_ATOM_SEQUENCE_FOREACH (self->in_port, ev) { - const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body; - if (obj->body.otype == uris->patch_Set) { - // Get the property and value of the set message - const LV2_Atom_URID* subject = NULL; - const LV2_Atom_URID* property = NULL; - const LV2_Atom* value = NULL; - - // clang-format off - lv2_atom_object_get(obj, - uris->patch_subject, (const LV2_Atom**)&subject, - uris->patch_property, (const LV2_Atom**)&property, - uris->patch_value, &value, - 0); - // clang-format on - - if (!subject_is_plugin(self, subject)) { - lv2_log_error(&self->log, "Set for unknown subject\n"); - } else if (!property) { - lv2_log_error(&self->log, "Set with no property\n"); - } else if (property->atom.type != uris->atom_URID) { - lv2_log_error(&self->log, "Set property is not a URID\n"); - } else { - // Set property to the given value - const LV2_URID key = property->body; - set_parameter(self, key, value->size, value->type, value + 1, false); - } - } else if (obj->body.otype == uris->patch_Get) { - // Get the property of the get message - const LV2_Atom_URID* subject = NULL; - const LV2_Atom_URID* property = NULL; - - // clang-format off - lv2_atom_object_get(obj, - uris->patch_subject, (const LV2_Atom**)&subject, - uris->patch_property, (const LV2_Atom**)&property, - 0); - // clang-format on - - if (!subject_is_plugin(self, subject)) { - lv2_log_error(&self->log, "Get with unknown subject\n"); - } else if (!property) { - // Get with no property, emit complete state - lv2_atom_forge_frame_time(&self->forge, ev->time.frames); - LV2_Atom_Forge_Frame pframe; - lv2_atom_forge_object(&self->forge, &pframe, 0, uris->patch_Put); - lv2_atom_forge_key(&self->forge, uris->patch_body); - - LV2_Atom_Forge_Frame bframe; - lv2_atom_forge_object(&self->forge, &bframe, 0, 0); - save(self, write_param_to_forge, &self->forge, 0, NULL); - - lv2_atom_forge_pop(&self->forge, &bframe); - lv2_atom_forge_pop(&self->forge, &pframe); - } else if (property->atom.type != uris->atom_URID) { - lv2_log_error(&self->log, "Get property is not a URID\n"); - } else { - // Get for a specific property - const LV2_URID key = property->body; - const LV2_Atom* value = get_parameter(self, key); - if (value) { - lv2_atom_forge_frame_time(&self->forge, ev->time.frames); - LV2_Atom_Forge_Frame frame; - lv2_atom_forge_object(&self->forge, &frame, 0, uris->patch_Set); - lv2_atom_forge_key(&self->forge, uris->patch_property); - lv2_atom_forge_urid(&self->forge, property->body); - store_prop(self, - NULL, - NULL, - write_param_to_forge, - &self->forge, - uris->patch_value, - value); - lv2_atom_forge_pop(&self->forge, &frame); - } - } - } else { - lv2_log_trace( - &self->log, "Unknown object type <%s>\n", unmap(self, obj->body.otype)); - } - } - - if (self->state.spring.body > 0.0f) { - const float spring = self->state.spring.body; - self->state.spring.body = (spring >= 0.001) ? spring - 0.001f : 0.0f; - lv2_atom_forge_frame_time(&self->forge, 0); - LV2_Atom_Forge_Frame frame; - lv2_atom_forge_object(&self->forge, &frame, 0, uris->patch_Set); - - lv2_atom_forge_key(&self->forge, uris->patch_property); - lv2_atom_forge_urid(&self->forge, uris->eg_spring); - lv2_atom_forge_key(&self->forge, uris->patch_value); - lv2_atom_forge_float(&self->forge, self->state.spring.body); - - lv2_atom_forge_pop(&self->forge, &frame); - } - - lv2_atom_forge_pop(&self->forge, &out_frame); -} - -static const void* -extension_data(const char* uri) -{ - static const LV2_State_Interface state = {save, restore}; - if (!strcmp(uri, LV2_STATE__interface)) { - return &state; - } - return NULL; -} - -static const LV2_Descriptor descriptor = {EG_PARAMS_URI, - instantiate, - connect_port, - NULL, // activate, - run, - NULL, // deactivate, - cleanup, - extension_data}; - -LV2_SYMBOL_EXPORT const LV2_Descriptor* -lv2_descriptor(uint32_t index) -{ - return (index == 0) ? &descriptor : NULL; -} diff --git a/plugins/eg-params.lv2/params.ttl b/plugins/eg-params.lv2/params.ttl deleted file mode 100644 index 931c826..0000000 --- a/plugins/eg-params.lv2/params.ttl +++ /dev/null @@ -1,126 +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 param: <http://lv2plug.in/ns/ext/parameters#> . -@prefix patch: <http://lv2plug.in/ns/ext/patch#> . -@prefix plug: <http://lv2plug.in/plugins/eg-params#> . -@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . -@prefix state: <http://lv2plug.in/ns/ext/state#> . -@prefix urid: <http://lv2plug.in/ns/ext/urid#> . -@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . - -# An existing parameter or RDF property can be used as a parameter. The LV2 -# parameters extension <http://lv2plug.in/ns/ext/parameters> defines many -# common audio parameters. Where possible, existing parameters should be used -# so hosts can intelligently control plugins. - -# If no suitable parameter exists, one can be defined for the plugin like so: - -plug:int - a lv2:Parameter ; - rdfs:label "int" ; - rdfs:range atom:Int . - -plug:long - a lv2:Parameter ; - rdfs:label "long" ; - rdfs:range atom:Long . - -plug:float - a lv2:Parameter ; - rdfs:label "float" ; - rdfs:range atom:Float . - -plug:double - a lv2:Parameter ; - rdfs:label "double" ; - rdfs:range atom:Double . - -plug:bool - a lv2:Parameter ; - rdfs:label "bool" ; - rdfs:range atom:Bool . - -plug:string - a lv2:Parameter ; - rdfs:label "string" ; - rdfs:range atom:String . - -plug:path - a lv2:Parameter ; - rdfs:label "path" ; - rdfs:range atom:Path . - -plug:lfo - a lv2:Parameter ; - rdfs:label "LFO" ; - rdfs:range atom:Float ; - lv2:minimum -1.0 ; - lv2:maximum 1.0 . - -plug:spring - a lv2:Parameter ; - rdfs:label "spring" ; - rdfs:range atom:Float . - -# Most of the plugin description is similar to the others we have seen, but -# this plugin has only two ports, for receiving and sending messages used to -# manipulate and access parameters. -<http://lv2plug.in/plugins/eg-params> - a lv2:Plugin , - lv2:UtilityPlugin ; - doap:name "Example Parameters" ; - doap:license <http://opensource.org/licenses/isc> ; - lv2:project <http://lv2plug.in/ns/lv2> ; - lv2:requiredFeature urid:map ; - lv2:optionalFeature lv2:hardRTCapable , - state:loadDefaultState ; - lv2:extensionData state:interface ; - lv2:port [ - a lv2:InputPort , - atom:AtomPort ; - atom:bufferType atom:Sequence ; - atom:supports patch:Message ; - lv2:designation lv2:control ; - lv2:index 0 ; - lv2:symbol "in" ; - lv2:name "In" - ] , [ - a lv2:OutputPort , - atom:AtomPort ; - atom:bufferType atom:Sequence ; - atom:supports patch:Message ; - lv2:designation lv2:control ; - lv2:index 1 ; - lv2:symbol "out" ; - lv2:name "Out" - ] ; -# The plugin must list all parameters that can be written (e.g. changed by the -# user) as patch:writable: - patch:writable plug:int , - plug:long , - plug:float , - plug:double , - plug:bool , - plug:string , - plug:path , - plug:spring ; -# Similarly, parameters that may change internally must be listed as patch:readable, -# meaning to host should watch for changes to the parameter's value: - patch:readable plug:lfo , - plug:spring ; -# Parameters map directly to properties of the plugin's state. So, we can -# specify initial parameter values with the state:state property. The -# state:loadDefaultState feature (required above) requires that the host loads -# the default state after instantiation but before running the plugin. - state:state [ - plug:int 0 ; - plug:long "0"^^xsd:long ; - plug:float "0.1234"^^xsd:float ; - plug:double "0e0"^^xsd:double ; - plug:bool false ; - plug:string "Hello, world" ; - plug:path <params.ttl> ; - plug:spring "0.0"^^xsd:float ; - plug:lfo "0.0"^^xsd:float - ] . diff --git a/plugins/eg-params.lv2/state_map.h b/plugins/eg-params.lv2/state_map.h deleted file mode 100644 index c81ea29..0000000 --- a/plugins/eg-params.lv2/state_map.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2016 David Robillard <d@drobilla.net> -// SPDX-License-Identifier: ISC - -#include <lv2/atom/atom.h> -#include <lv2/urid/urid.h> - -#include <stdarg.h> -#include <stdint.h> -#include <stdlib.h> - -/** Entry in an array that serves as a dictionary of properties. */ -typedef struct { - const char* uri; - LV2_URID urid; - LV2_Atom* value; -} StateMapItem; - -/** Comparator for StateMapItems sorted by URID. */ -static int -state_map_cmp(const void* a, const void* b) -{ - const StateMapItem* ka = (const StateMapItem*)a; - const StateMapItem* kb = (const StateMapItem*)b; - if (ka->urid < kb->urid) { - return -1; - } - - if (kb->urid < ka->urid) { - return 1; - } - - return 0; -} - -/** Helper macro for terse state map initialisation. */ -#define STATE_MAP_INIT(type, ptr) \ - (LV2_ATOM__##type), (sizeof(*(ptr)) - sizeof(LV2_Atom)), (ptr) - -/** - Initialise a state map. - - The variable parameters list must be NULL terminated, and is a sequence of - const char* uri, const char* type, uint32_t size, LV2_Atom* value. The - value must point to a valid atom that resides elsewhere, the state map is - only an index and does not contain actual state values. The macro - STATE_MAP_INIT can be used to make simpler code when state is composed of - standard atom types, for example: - - struct Plugin { - LV2_URID_Map* map; - StateMapItem props[3]; - // ... - }; - - state_map_init( - self->props, self->map, self->map->handle, - PLUG_URI "#gain", STATE_MAP_INIT(Float, &state->gain), - PLUG_URI "#offset", STATE_MAP_INIT(Int, &state->offset), - PLUG_URI "#file", STATE_MAP_INIT(Path, &state->file), - NULL); -*/ -static void -state_map_init( - StateMapItem dict[], - LV2_URID_Map* map, - LV2_URID_Map_Handle handle, - /* const char* uri, const char* type, uint32_t size, LV2_Atom* value */...) -{ - // Set dict entries from parameters - unsigned i = 0; - va_list args; // NOLINT(cppcoreguidelines-init-variables) - va_start(args, handle); - for (const char* uri = NULL; (uri = va_arg(args, const char*)); ++i) { - const char* type = va_arg(args, const char*); - const uint32_t size = va_arg(args, uint32_t); - LV2_Atom* const value = va_arg(args, LV2_Atom*); - dict[i].uri = uri; - dict[i].urid = map->map(map->handle, uri); - dict[i].value = value; - dict[i].value->size = size; - dict[i].value->type = map->map(map->handle, type); - } - va_end(args); - - // Sort for fast lookup by URID by state_map_find() - qsort(dict, i, sizeof(StateMapItem), state_map_cmp); -} - -/** - Retrieve an item from a state map by URID. - - This takes O(lg(n)) time, and is useful for implementing generic property - access with little code, for example to respond to patch:Get messages for a - specific property. -*/ -static StateMapItem* -state_map_find(StateMapItem dict[], uint32_t n_entries, LV2_URID urid) -{ - const StateMapItem key = {NULL, urid, NULL}; - return (StateMapItem*)bsearch( - &key, dict, n_entries, sizeof(StateMapItem), state_map_cmp); -} |