clap

CLAP Audio Plugin API
Log | Files | Refs | README | LICENSE

commit cc7211ffcee4fcaeef60074e685a460ad7eb86e1
parent c95cbcef3631df134752fa396c1d441ee46f266b
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date:   Thu, 29 Dec 2022 20:13:29 +0100

Adds Preset Discovery

Diffstat:
Minclude/clap/ext/draft/preset-load.h | 12+++++++++++-
Minclude/clap/plugin-features.h | 2--
Ainclude/clap/preset-discovery.h | 231+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/clap/preset-features.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Minclude/clap/string-sizes.h | 6++++++
5 files changed, 293 insertions(+), 3 deletions(-)

diff --git a/include/clap/ext/draft/preset-load.h b/include/clap/ext/draft/preset-load.h @@ -2,7 +2,7 @@ #include "../../plugin.h" -static const char CLAP_EXT_PRESET_LOAD[] = "clap.preset-load.draft/0"; +static const char CLAP_EXT_PRESET_LOAD[] = "clap.preset-load.draft/1"; #ifdef __cplusplus extern "C" { @@ -12,6 +12,16 @@ typedef struct clap_plugin_preset_load { // Loads a preset in the plugin native preset file format from a path. // [main-thread] bool(CLAP_ABI *from_file)(const clap_plugin_t *plugin, const char *path); + + // Loads a preset in the plugin native preset file format from a path which points to a preset + // container file. + // preset_id must be a valid string, which is specific to the plugin itself and identifies the + // desired preset within the given preset container. + // + // [main-thread] + bool(CLAP_ABI *from_container_file)(const clap_plugin_t *plugin, + const char *path, + const char *preset_id); } clap_plugin_preset_load_t; #ifdef __cplusplus diff --git a/include/clap/plugin-features.h b/include/clap/plugin-features.h @@ -1,7 +1,5 @@ #pragma once -#include "private/macros.h" - // This file provides a set of standard plugin features meant to be used // within clap_plugin_descriptor.features. // diff --git a/include/clap/preset-discovery.h b/include/clap/preset-discovery.h @@ -0,0 +1,231 @@ +/** + Preset Discovery API. + + Preset Discovery enables a plug-in host to identify where presets are found, what + extensions they have, which plug-ins they apply to, and other metadata associated with the + presets so that they can be indexed and searched for quickly within the plug-in host's browser. + + This has a number of advantages for the user: + - it allows them to browse for presets from one central location in a consistent way + - the user can browse for presets without having to commit to a particular plug-in first + + The API works as follow to index presets and presets metadata: + 1. get the preset discovery factory + 2. create a preset provider + 3. list locations and file extensions from the preset provider + 4. monitor file system changes on the given locations + 5. read metadata for each preset files + 6. fetch information about collections from the preset provider + + Then to load a preset, use ext/draft/preset-load.h + + The design of this API deliberately does not define a fixed set tags or categories. It is the + plug-in host's job to try to intelligently map the raw list of features that are found for a + preset and to process this list to generate something that makes sense for the host's tagging and + categorization system. The reason for this is to reduce the work for a plug-in developer to add + Preset Discovery support for their existing preset file format and not have to be concerned with + all the different hosts and how they want to receive the metadata. +*/ + +#pragma once + +#include "private/std.h" +#include "private/macros.h" +#include "string-sizes.h" +#include "version.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Receiver that receives the metadata for a single preset file. + * The host would define the various callbacks in this interface and the preset parser function + * would then call them. + * + * This interface isn't thread-safe. + */ +typedef const struct clap_preset_metadata_receiver { + /** If there is an error reading metadata from a file this should be called with an error + * message. */ + void(CLAP_ABI *on_error)(const struct clap_preset_metadata_receiver *receiver, + const char *error_message); + + /** Marks this file as a container file meaning that it can contain other presets. */ + void(CLAP_ABI *mark_as_container_file)(const struct clap_preset_metadata_receiver *receiver); + + /** If the file being parsed is a preset container file (mark_as_container_file has been called) + * then this must be called for every preset in the file and before any preset metadata is + * sent with the calls below. If the file is not a container file then this should not be + * called at all. + * + * The path defines a human friendly path to the preset in the container file. It + * should be unique within the container file. + * + * The preset_id is a machine friendly string used to load the preset inside the container via a + * the preset-load plug-in extension. The preset_id can also just be the path if that's what the + * extension wants but it could also be some other unique id like a database primary key or a + * binary offset. It's use is entirely up to the plug-in. + */ + void(CLAP_ABI *begin_contained_preset)(const struct clap_preset_metadata_receiver *receiver, + const char *path, + const char *preset_id); + + /** Marks this preset as a bank preset, meaning that it can be assigned to the plug-in as a + * preset but will update the banks in the plug-in. + */ + void(CLAP_ABI *mark_as_bank_preset)(const struct clap_preset_metadata_receiver *receiver); + + /** Sets plug-in id that this preset can be used with. */ + void(CLAP_ABI *set_plugin_id)(const struct clap_preset_metadata_receiver *receiver, + const char *plugin_id); + + /** Sets the collection to which the preset belongs to. */ + void(CLAP_ABI *set_collection_id)(const struct clap_preset_metadata_receiver, + const char *collection_id); + + /** Adds a creator name for the preset. */ + void(CLAP_ABI *add_creator)(const struct clap_preset_metadata_receiver *receiver, + const char *creator); + + /** Sets a description of the preset. */ + void(CLAP_ABI *set_description)(const struct clap_preset_metadata_receiver *receiver, + const char *description); + + /** Sets the creation time and last modification time of the preset. + * If one of the time isn't known, then set it to 0. */ + void(CLAP_ABI *set_timestamps)(const struct clap_preset_metadata_receiver *receiver, + uint64_t creation_time, + uint64_t modification_time); + + /** + * Adds a feature to the preset. + * See plugin-features.h and preset-features.h + * + * The feature string is arbitrary, it is the indexer's job to remap it to its internal + * categorization and tagging system. + */ + void(CLAP_ABI *add_feature)(const struct clap_preset_metadata_receiver *receiver, + const char *feature); + +} *clap_preset_metadata_receiver_t; + +enum clap_preset_discovery_flags { + // This location/collection is meant for storing factory presets, most likely read-only + CLAP_PRESET_DISCOVERY_IS_FACTORY_CONTENT = 1 << 0, + + // This location/collection is meant for storing user created presets + CLAP_PRESET_DISCOVERY_IS_USER_CONTENT = 1 << 1, + + // This location/collection is meant for demo presets, those are preset which may trigger + // some limitation in the plugin because they require additionnal features which the user + // needs to purchase or the content itself needs to be bought and is only available in + // demo mode. + CLAP_PRESET_DISCOVERY_IS_DEMO_CONTENT = 1 << 2, +}; + +// Defines a place in which to search for presets +typedef struct clap_preset_location { + uint64_t flags; // see enum clap_preset_discovery_flags + + // name of this location + char name[CLAP_NAME_SIZE]; + + // path to a directory on the file system in which preset can be found + char path[CLAP_URI_SIZE]; +} clap_preset_location_t; + +// A collection, represent a collection of presets; it is will most often used to identify presets +// which belongs to the same "sound pack". +typedef struct clap_preset_collection_info { + uint64_t flags; // see enum clap_preset_discovery_flags + + char name[CLAP_NAME_SIZE]; // name of this collection + char description[CLAP_DESCRIPTION_SIZE]; // reasonably short description of the collection + char homepage_url[CLAP_URI_SIZE]; // url to the pack's homepage + char image_uri[CLAP_URI_SIZE]; // may be an image on disk or from an http server +} clap_preset_collection_info_t; + +// Describes a preset provider +typedef struct clap_preset_provider_descriptor { + clap_version_t clap_version; // initialized to CLAP_VERSION + const char *id; + const char *name; + const char *vendor; + const char *const *plugin_ids; // null terminated array of plugin ids +} clap_preset_provider_descriptor_t; + +// This interface isn't thread-safe. +typedef struct clap_preset_provider { + const clap_preset_provider_descriptor_t *desc; + + // returns the number of locations + uint32_t(CLAP_ABI *locations_count)(const struct clap_preset_provider *provider); + + // gets the location info at index + bool(CLAP_ABI *get_location)(const struct clap_preset_provider *provider, + uint32_t index, + clap_preset_location_t *out_info); + + // returns the number of different supported file extensions + uint32_t(CLAP_ABI *file_extensions_count)(const struct clap_preset_provider *provider); + + // stores the file extensions at index into out_extension. + // the `.' isn't included in the string. + // extension_capacity indicates the number of bytes available to store the extension + bool(CLAP_ABI *get_file_extension)(const struct clap_preset_provider *provider, + uint32_t index, + char *out_extension, + uint32_t extension_capacity); + + // gets information about a given collection. + bool(CLAP_ABI *get_collection_info)(const struct clap_preset_provider *provider, + const char *collection_id, + clap_preset_collection_info_t *out_info); + + // reads metadata from the given file and passes them to the metadata receiver + bool(CLAP_ABI *read_file_metadata)(const struct clap_preset_provider *provider, + const char *file_path, + const clap_preset_metadata_receiver *metadata_receiver); +} clap_preset_provider_t; + +typedef struct clap_preset_indexer { + clap_version_t clap_version; // initialized to CLAP_VERSION + const char *name; + const char *vendor; + const char *version; +} clap_preset_indexer_t; + +static const CLAP_CONSTEXPR char CLAP_PRESET_DISCOVERY_FACTORY_ID[] = + "clap.preset-discovery-factory"; + +// Every methods in this factory must be thread-safe. +// It is very important to be able to scan the plugin as quickly as possible. +// +// The host may use clap_plugin_invalidation_factory to detect filesystem changes +// which may change the factory's content. +typedef struct clap_preset_discovery_factory { + // Get the number of preset providers available. + // [thread-safe] + uint32_t(CLAP_ABI *count)(const struct clap_preset_discovery_factory *factory); + + // Retrieves a plugin descriptor by its index. + // Returns null in case of error. + // The descriptor must not be freed. + // [thread-safe] + const clap_preset_provider_descriptor_t *(CLAP_ABI *get_descriptor)( + const struct clap_preset_discovery_factory *factory, uint32_t index); + + // Create a clap_plugin by its plugin_id. + // The returned pointer must be freed by calling plugin->destroy(plugin); + // The plugin is not allowed to use the host callbacks in the create method. + // Returns null in case of error. + // [thread-safe] + const clap_preset_provider_t *(CLAP_ABI *create)( + const struct clap_preset_discovery_factory *factory, + const clap_preset_indexer_t *indexer, + const char *provider_id); +} clap_plugin_factory_t; + +#ifdef __cplusplus +} +#endif diff --git a/include/clap/preset-features.h b/include/clap/preset-features.h @@ -0,0 +1,45 @@ +#pragma once + +// This file provides a set of standard preset features meant to be used +// within clap_plugin_descriptor.features. +// +// For practical reasons we'll avoid spaces and use `-` instead to facilitate +// scripts that generate the feature array. +// +// Non-standard features should be formated as follow: "$namespace:$feature" + +#include "plugin-features.h" + +#define CLAP_PRESET_FEATURE_KICK "kick" +#define CLAP_PRESET_FEATURE_TOM "tom" +#define CLAP_PRESET_FEATURE_SNARE "snare" +#define CLAP_PRESET_FEATURE_CLAP "clap" +#define CLAP_PRESET_FEATURE_CYMBAL "cymbal" + +#define CLAP_PRESET_FEATURE_BASS "bass" +#define CLAP_PRESET_FEATURE_LEAD "lead" +#define CLAP_PRESET_FEATURE_KEY "key" +#define CLAP_PRESET_FEATURE_PLUCK "pluck" +#define CLAP_PRESET_FEATURE_STAB "stab" +#define CLAP_PRESET_FEATURE_WIND "wind" +#define CLAP_PRESET_FEATURE_STRING "string" +#define CLAP_PRESET_FEATURE_PAD "pad" +#define CLAP_PRESET_FEATURE_DRONE "drone" + +#define CLAP_PRESET_FEATURE_BRIGHT "bright" +#define CLAP_PRESET_FEATURE_DARK "dark" +#define CLAP_PRESET_FEATURE_SATURATED "saturated" +#define CLAP_PRESET_FEATURE_TAPE "tape" +#define CLAP_PRESET_FEATURE_DISTORDED "distorded" +#define CLAP_PRESET_FEATURE_METALIC "metalic" +#define CLAP_PRESET_FEATURE_ATONAL "atonal" +#define CLAP_PRESET_FEATURE_NOISE "noise" +#define CLAP_PRESET_FEATURE_DETUNED "detuned" +#define CLAP_PRESET_FEATURE_ACID "acid" +#define CLAP_PRESET_FEATURE_ANALOG "analog" +#define CLAP_PRESET_FEATURE_DIGITAL "digital" +#define CLAP_PRESET_FEATURE_CHIP "chip" // 8-bits, chiptune... + +#define CLAP_PRESET_FEATURE_SEQUENCE "sequence" +#define CLAP_PRESET_FEATURE_ARPEGGIATOR "arpeggiator" +#define CLAP_PRESET_FEATURE_CHORD "chord" diff --git a/include/clap/string-sizes.h b/include/clap/string-sizes.h @@ -14,6 +14,12 @@ enum { // This is not suited for describing a file path on the disk, as NTFS allows up to 32K long // paths. CLAP_PATH_SIZE = 1024, + + // String capacity for descriptions + CLAP_DESCRIPTION_SIZE = 1024, + + // String capacity for describing a filesystem file path, an web URL, ... + CLAP_URI_SIZE = 8096, }; #ifdef __cplusplus