commit ead50d1c850071a4db3883b692246f8bce46dd15
parent 8e94c7783738e5cf17b651c5d6e1d7437a9da579
Author: falkTX <falktx@falktx.com>
Date: Thu, 27 May 2021 17:27:22 +0100
Add CV range flags, implement jack meta-data
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
3 files changed, 197 insertions(+), 7 deletions(-)
diff --git a/distrho/DistrhoPlugin.hpp b/distrho/DistrhoPlugin.hpp
@@ -44,6 +44,32 @@ static const uint32_t kAudioPortIsCV = 0x1;
*/
static const uint32_t kAudioPortIsSidechain = 0x2;
+/**
+ CV port has bipolar range (-1 to +1, or -5 to +5 if scaled).
+ This is merely a hint to tell the host what value range to expect.
+ */
+static const uint32_t kCVPortHasBipolarRange = 0x10;
+
+/**
+ CV port has negative unipolar range (0 to +1, or 0 to +10 if scaled).
+ This is merely a hint to tell the host what value range to expect.
+ */
+static const uint32_t kCVPortHasNegativeUnipolarRange = 0x20;
+
+/**
+ CV port has positive unipolar range (-1 to 0, or -10 to 0 if scaled).
+ This is merely a hint to tell the host what value range to expect.
+ */
+static const uint32_t kCVPortHasPositiveUnipolarRange = 0x40;
+
+/**
+ CV port has scaled range to match real values (-5 to +5v bipolar, +/-10 to 0v unipolar).
+ One range flag is required if this flag is set.
+
+ When enabled, this makes the port a mod:CVPort, compatible with the MOD Devices platform.
+ */
+static const uint32_t kCVPortHasScaledRange = 0x80;
+
/** @} */
/* ------------------------------------------------------------------------------------------------------------
diff --git a/distrho/src/DistrhoPluginJack.cpp b/distrho/src/DistrhoPluginJack.cpp
@@ -25,8 +25,11 @@
#endif
#include "jack/jack.h"
+#include "jack/metadata.h"
#include "jack/midiport.h"
#include "jack/transport.h"
+#include "jack/uuid.h"
+#include "lv2/lv2.h"
#ifndef DISTRHO_OS_WINDOWS
# include <signal.h>
@@ -119,15 +122,18 @@ public:
# if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
- std::snprintf(strBuf, 0xff, "in%i", i+1);
- fPortAudioIns[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ const AudioPort& port(fPlugin.getAudioPort(true, i));
+ fPortAudioIns[i] = jack_port_register(fClient, port.symbol, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ setAudioPortMetadata(port, fPortAudioIns[i], i);
}
# endif
# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "out%i", i+1);
- fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ const AudioPort& port(fPlugin.getAudioPort(false, i));
+ fPortAudioOuts[i] = jack_port_register(fClient, port.symbol, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ setAudioPortMetadata(port, fPortAudioOuts[i], i);
}
# endif
#endif
@@ -561,6 +567,77 @@ private:
# endif
#endif
+ void setAudioPortMetadata(const AudioPort& port, jack_port_t* const jackport, const uint32_t index)
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(jackport != nullptr,);
+
+ const jack_uuid_t uuid = jack_port_uuid(jackport);
+
+ if (jack_uuid_empty(uuid))
+ return;
+
+ jack_set_property(fClient, uuid, JACK_METADATA_PRETTY_NAME, port.name, "text/plain");
+
+ {
+ char strBuf[0xff];
+ snprintf(strBuf, sizeof(0xff)-1, "%u", index);
+ jack_set_property(fClient, uuid, JACK_METADATA_ORDER, strBuf, "http://www.w3.org/2001/XMLSchema#integer");
+ }
+
+ if (port.hints & kAudioPortIsCV)
+ {
+ jack_set_property(fClient, uuid, JACK_METADATA_SIGNAL_TYPE, "CV", "text/plain");
+ }
+ else
+ {
+ jack_set_property(fClient, uuid, JACK_METADATA_SIGNAL_TYPE, "AUDIO", "text/plain");
+ return;
+ }
+
+ // set cv ranges
+ const bool cvPortScaled = port.hints & kCVPortHasScaledRange;
+
+ if (port.hints & kCVPortHasBipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ jack_set_property(fClient, uuid, LV2_CORE__minimum, "-5", "http://www.w3.org/2001/XMLSchema#integer");
+ jack_set_property(fClient, uuid, LV2_CORE__maximum, "5", "http://www.w3.org/2001/XMLSchema#integer");
+ }
+ else
+ {
+ jack_set_property(fClient, uuid, LV2_CORE__minimum, "-1", "http://www.w3.org/2001/XMLSchema#integer");
+ jack_set_property(fClient, uuid, LV2_CORE__maximum, "1", "http://www.w3.org/2001/XMLSchema#integer");
+ }
+ }
+ else if (port.hints & kCVPortHasNegativeUnipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ jack_set_property(fClient, uuid, LV2_CORE__minimum, "-10", "http://www.w3.org/2001/XMLSchema#integer");
+ jack_set_property(fClient, uuid, LV2_CORE__maximum, "0", "http://www.w3.org/2001/XMLSchema#integer");
+ }
+ else
+ {
+ jack_set_property(fClient, uuid, LV2_CORE__minimum, "-1", "http://www.w3.org/2001/XMLSchema#integer");
+ jack_set_property(fClient, uuid, LV2_CORE__maximum, "0", "http://www.w3.org/2001/XMLSchema#integer");
+ }
+ }
+ else if (port.hints & kCVPortHasPositiveUnipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ jack_set_property(fClient, uuid, LV2_CORE__minimum, "0", "http://www.w3.org/2001/XMLSchema#integer");
+ jack_set_property(fClient, uuid, LV2_CORE__maximum, "10", "http://www.w3.org/2001/XMLSchema#integer");
+ }
+ else
+ {
+ jack_set_property(fClient, uuid, LV2_CORE__minimum, "0", "http://www.w3.org/2001/XMLSchema#integer");
+ jack_set_property(fClient, uuid, LV2_CORE__maximum, "1", "http://www.w3.org/2001/XMLSchema#integer");
+ }
+ }
+ }
+
// -------------------------------------------------------------------
// Callbacks
diff --git a/distrho/src/DistrhoPluginLV2export.cpp b/distrho/src/DistrhoPluginLV2export.cpp
@@ -22,6 +22,7 @@
#include "lv2/instance-access.h"
#include "lv2/midi.h"
#include "lv2/options.h"
+#include "lv2/parameters.h"
#include "lv2/patch.h"
#include "lv2/port-props.h"
#include "lv2/presets.h"
@@ -332,9 +333,7 @@ void lv2_generate_ttl(const char* const basename)
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
-#ifdef DISTRHO_PLUGIN_BRAND
pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n";
-#endif
pluginString += "@prefix opts: <" LV2_OPTIONS_PREFIX "> .\n";
pluginString += "@prefix patch: <" LV2_PATCH_PREFIX "> .\n";
pluginString += "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n";
@@ -410,13 +409,16 @@ void lv2_generate_ttl(const char* const basename)
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
{
const AudioPort& port(plugin.getAudioPort(true, i));
+ const bool cvPortScaled = port.hints & kCVPortHasScaledRange;
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";
- if (port.hints & kAudioPortIsCV)
+ if (cvPortScaled)
+ pluginString += " a lv2:InputPort, lv2:CVPort, mod:CVPort ;\n";
+ else if (port.hints & kAudioPortIsCV)
pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
else
pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";
@@ -428,6 +430,47 @@ void lv2_generate_ttl(const char* const basename)
if (port.hints & kAudioPortIsSidechain)
pluginString += " lv2:portProperty lv2:isSideChain;\n";
+ // set ranges
+ if (port.hints & kCVPortHasBipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ pluginString += " lv2:minimum -5.0 ;\n";
+ pluginString += " lv2:maximum 5.0 ;\n";
+ }
+ else
+ {
+ pluginString += " lv2:minimum -1.0 ;\n";
+ pluginString += " lv2:maximum 1.0 ;\n";
+ }
+ }
+ else if (port.hints & kCVPortHasNegativeUnipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ pluginString += " lv2:minimum -10.0 ;\n";
+ pluginString += " lv2:maximum 0.0 ;\n";
+ }
+ else
+ {
+ pluginString += " lv2:minimum -1.0 ;\n";
+ pluginString += " lv2:maximum 0.0 ;\n";
+ }
+ }
+ else if (port.hints & kCVPortHasPositiveUnipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ pluginString += " lv2:minimum 0.0 ;\n";
+ pluginString += " lv2:maximum 10.0 ;\n";
+ }
+ else
+ {
+ pluginString += " lv2:minimum 0.0 ;\n";
+ pluginString += " lv2:maximum 1.0 ;\n";
+ }
+ }
+
if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
pluginString += " ] ;\n";
else
@@ -440,13 +483,16 @@ void lv2_generate_ttl(const char* const basename)
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
{
const AudioPort& port(plugin.getAudioPort(false, i));
+ const bool cvPortScaled = port.hints & kCVPortHasScaledRange;
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";
- if (port.hints & kAudioPortIsCV)
+ if (cvPortScaled)
+ pluginString += " a lv2:OutputPort, lv2:CVPort, mod:CVPort ;\n";
+ else if (port.hints & kAudioPortIsCV)
pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
else
pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";
@@ -458,6 +504,47 @@ void lv2_generate_ttl(const char* const basename)
if (port.hints & kAudioPortIsSidechain)
pluginString += " lv2:portProperty lv2:isSideChain;\n";
+ // set ranges
+ if (port.hints & kCVPortHasBipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ pluginString += " lv2:minimum -5.0 ;\n";
+ pluginString += " lv2:maximum 5.0 ;\n";
+ }
+ else
+ {
+ pluginString += " lv2:minimum -1.0 ;\n";
+ pluginString += " lv2:maximum 1.0 ;\n";
+ }
+ }
+ else if (port.hints & kCVPortHasNegativeUnipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ pluginString += " lv2:minimum -10.0 ;\n";
+ pluginString += " lv2:maximum 0.0 ;\n";
+ }
+ else
+ {
+ pluginString += " lv2:minimum -1.0 ;\n";
+ pluginString += " lv2:maximum 0.0 ;\n";
+ }
+ }
+ else if (port.hints & kCVPortHasPositiveUnipolarRange)
+ {
+ if (cvPortScaled)
+ {
+ pluginString += " lv2:minimum 0.0 ;\n";
+ pluginString += " lv2:maximum 10.0 ;\n";
+ }
+ else
+ {
+ pluginString += " lv2:minimum 0.0 ;\n";
+ pluginString += " lv2:maximum 1.0 ;\n";
+ }
+ }
+
if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
pluginString += " ] ;\n";
else