Signed-off-by: falkTX <falktx@falktx.com>pull/281/head
@@ -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; | |||
/** @} */ | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
@@ -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 | |||
@@ -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 | |||