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 | |||