commit 7a8851e17b53963ceebfdb98177ad3ce60859620
parent cea197fb2bc9b9e07a0a79ba9829fecd032a7d8a
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date: Sun, 30 May 2021 13:17:19 +0200
Rework the param spec and add clap_midi_mappings ext
Diffstat:
3 files changed, 68 insertions(+), 19 deletions(-)
diff --git a/examples/host/plugin-host.cc b/examples/host/plugin-host.cc
@@ -613,7 +613,7 @@ void PluginHost::process() {
ev.param.param_id = param_id;
ev.param.key = -1;
ev.param.channel = -1;
- ev.param.ramp = 0;
+ ev.param.value_ramp = 0;
ev.param.value = value;
evIn_.push_back(ev);
});
diff --git a/include/clap/ext/midi-mappings.h b/include/clap/ext/midi-mappings.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "../clap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ CLAP_MIDI_MAPPING_CC7,
+ CLAP_MIDI_MAPPING_CC14,
+ CLAP_MIDI_MAPPING_RPN,
+ CLAP_MIDI_MAPPING_NRPN,
+};
+typedef int32_t clap_midi_mapping_type;
+
+typedef struct clap_midi_mapping
+{
+ int32_t channel;
+ int32_t number;
+} clap_midi_mapping;
+
+typedef struct clap_plugin_midi_mappings
+{
+ // [main-thread]
+ uint32_t (*count)(const clap_plugin *plugin);
+
+ // [main-thread]
+ bool (*get)(const clap_plugin *plugin, uint32_t index, clap_midi_mapping *mapping);
+} clap_plugin_midi_mappings;
+
+typedef struct clap_host_midi_mappings
+{
+ // [main-thread]
+ void (*changed)(const clap_host *host);
+} clap_host_midi_mappings;
+
+#ifdef __cplusplus
+}
+#endif
+\ No newline at end of file
diff --git a/include/clap/ext/params.h b/include/clap/ext/params.h
@@ -12,44 +12,52 @@ extern "C" {
/// Main idea:
///
/// The host sees the plugin as an atomic entity; and acts as a controler on top of its parameters.
+/// The plugin is responsible to keep in sync its audio processor and its GUI.
///
-/// The host can read at any time the parameter value on the [main-thread] using
+/// The host can read at any time parameters value on the [main-thread] using
/// @ref clap_plugin_params.value().
///
/// There is a single way at a time for the host to set parameters value.
-/// - if the plugin is active, send @ref CLAP_PARAM_SET event during the process call [audio-thread]
+/// - if the plugin is active, send @ref CLAP_EVENT_PARAM_SET during the process call [audio-thread]
/// - if the plugin is not active, call @ref clap_plugin_params.set_value [main-thread]
///
-/// Rationale: sending @ref CLAP_PARAM_SET event during the process call is the natural way to play parameter automation.
-/// But, the process call is only possible if the plugin is active. If it is not, then everything happens on the
-/// [main-thread] using the clap_plugin_params and clap_host_params interfaces.
+/// Rationale: Ideally there would be a single way to set parameters values.
+/// Sending @ref CLAP_EVENT_PARAM_SET via @ref clap_plugin.process is the natural way to play
+/// parameter automation. But, the process call is only possible if the plugin is active. If the
+/// plugin is not active, then everything happens on the [main-thread] using @ref clap_plugin_params
+/// and @ref clap_host_params interfaces.
///
-/// When the plugin receives a parameter set, it is responsible to keep in sync its GUI and audio processor.
-///
-/// When the plugin changes a parameter value because a knob is being adjusted on its GUI or a MIDI CC is mapped to a parameter,
-/// the plugin must inform the host. The host can then update its GUI, interrupt automation playback and record new automation points.
-/// If the plugin is active, it will send @ref CLAP_PARAM_SET events, it must set the fields begin_adjust on the first parameter set and end_adjust on the last one.
-/// If the plugin is inactive, it will use:
+/// When the plugin changes a parameter value, it must inform the host.
+/// If the plugin is active, it will send @ref CLAP_EVENT_PARAM_SET during the process call
+/// - set @ref clap_event_param.begin_adjust to mark the begining of automation recording
+/// - set @ref clap_event_param.end_adjust to mark the end of automation recording
+/// If the plugin is not active, it will use:
/// - @ref clap_host_params.adjust_begin() - marks the begining of automation recording
/// - @ref clap_host_params.adjust() - adds a new point in the automation recording
/// - @ref clap_host_params.adjust_end() - marks the end of automation recording
///
-/// @note it may be convenient for the plugin to let the host knows about the midi mapping table,
-/// and translate MIDI CCs to parameter events for the plugin, yet it is not necessary.
+/// @note MIDI CCs are a tricky because you may not know when the parameter adjustment ends.
+/// Also if the hosts records incoming MIDI CC and parameter change automation at the same time,
+/// there will be a conflict at playback: MIDI CC vs Automation.
+/// The parameter automation will always target the same parameter because the param_id is stable.
+/// The MIDI CC may have a different mapping in the future and may result in a different playback.
+///
+/// It is highly recommanded to use @ref clap_plugin_midi_mappings to let the host solve
+/// this problem and offer a consistent experience to the user across different plugins.
///
/// Scenarios:
///
/// I. Loading a preset
/// - load the preset in a temporary state, if the plugin is activated and preset will introduce
-/// breaking change like latency, audio ports change, parameter changes, ...
+/// breaking change like latency, audio ports change, new parameters, ...
/// report those to the host and wait for the host to deactivate the plugin
/// to apply those changes. If there are no breaking changes, the plugin can apply them
/// them right away.
/// The plugin is resonsible to update both its audio processor and its gui.
///
/// II. Turning a knob on the DAW interface
-/// - if the plugin is active, the host will send a CLAP_PARAM_SET event to the plugin
-/// - if the plugin is not active, the host will call plugin_params->set_value(...)
+/// - if the plugin is active, the host will send a @ref CLAP_EVENT_PARAM_SET event to the plugin
+/// - if the plugin is not active, the host will call @ref clap_plugin_params.set_value
///
/// III. Turning a knob on the Plugin interface
/// - if the plugin is not active
@@ -61,11 +69,11 @@ extern "C" {
/// - the plugin is responsible to send the parameter value to its audio processor
///
/// IV. Turning a knob via automation
-/// - host sends a CLAP_PARAM_SET event
+/// - host sends a @ref CLAP_EVENT_PARAM_SET during the process call
/// - the plugin is responsible to update its GUI
///
/// V. Turning a knob via internal MIDI mapping
-/// - the plugin sends a CLAP_PARAM_SET output event
+/// - the plugin sends a CLAP_EVENT_PARAM_SET output event
/// - the plugin is responsible to update its GUI
///
/// VI. Adding or removing parameters