Browse Source

Read lv2 midi:binding on control ports and parameters

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.3.0
falkTX 4 years ago
parent
commit
33158e3134
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
5 changed files with 76 additions and 20 deletions
  1. +7
    -0
      source/backend/plugin/CarlaPluginLV2.cpp
  2. +1
    -0
      source/modules/lilv/lilv-0.24.0/src/lilv_internal.h
  3. +3
    -0
      source/modules/lilv/lilv-0.24.0/src/node.c
  4. +2
    -0
      source/modules/lilv/lilv-0.24.0/src/world.c
  5. +63
    -20
      source/utils/CarlaLv2Utils.hpp

+ 7
- 0
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -3075,8 +3075,15 @@ public:
pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
pData->param.data[j].hints |= PARAMETER_IS_NOT_SAVED;
needsCtrlIn = true;

if (rdfParam.Flags & LV2_PARAMETER_FLAG_OUTPUT)
hasPatchParameterOutputs = true;

if (LV2_IS_PORT_MIDI_MAP_CC(rdfParam.MidiMap.Type))
{
if (! MIDI_IS_CONTROL_BANK_SELECT(rdfParam.MidiMap.Number))
pData->param.data[j].mappedControlIndex = static_cast<int16_t>(rdfParam.MidiMap.Number);
}
}
else if (rdfParam.Flags & LV2_PARAMETER_FLAG_OUTPUT)
{


+ 1
- 0
source/modules/lilv/lilv-0.24.0/src/lilv_internal.h View File

@@ -185,6 +185,7 @@ struct LilvWorldImpl {
SordNode* lv2_requiredFeature;
SordNode* lv2_symbol;
SordNode* lv2_prototype;
SordNode* midi_Event;
SordNode* mod_builderVersion;
SordNode* mod_releaseNumber;
SordNode* owl_Ontology;


+ 3
- 0
source/modules/lilv/lilv-0.24.0/src/node.c View File

@@ -131,6 +131,9 @@ lilv_node_new_from_node(LilvWorld* world, const SordNode* node)
else if (sord_node_equals(datatype_uri,
world->uris.xsd_base64Binary))
type = LILV_VALUE_BLOB;
else if (sord_node_equals(datatype_uri,
world->uris.midi_Event))
type = LILV_VALUE_BLOB;
else
LILV_ERRORF("Unknown datatype `%s'\n",
sord_node_get_string(datatype_uri));


+ 2
- 0
source/modules/lilv/lilv-0.24.0/src/world.c View File

@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>

#include "lv2/midi.h"
#include "lv2/presets.h"

#include "lilv_internal.h"
@@ -78,6 +79,7 @@ lilv_world_new(void)
world->uris.lv2_requiredFeature = NEW_URI(LV2_CORE__requiredFeature);
world->uris.lv2_symbol = NEW_URI(LV2_CORE__symbol);
world->uris.lv2_prototype = NEW_URI(LV2_CORE__prototype);
world->uris.midi_Event = NEW_URI(LV2_MIDI__MidiEvent);
world->uris.mod_builderVersion = NEW_URI("http://moddevices.com/ns/mod#builderVersion");
world->uris.mod_releaseNumber = NEW_URI("http://moddevices.com/ns/mod#releaseNumber");
world->uris.owl_Ontology = NEW_URI(NS_OWL "Ontology");


+ 63
- 20
source/utils/CarlaLv2Utils.hpp View File

@@ -20,6 +20,7 @@

#include "CarlaMathUtils.hpp"
#include "CarlaStringList.hpp"
#include "CarlaMIDI.h"

#ifndef nullptr
# undef NULL
@@ -268,6 +269,7 @@ public:
Lilv::Node rz_minSize;

// Port Data Types
Lilv::Node midi_binding;
Lilv::Node midi_event;
Lilv::Node patch_message;
Lilv::Node time_position;
@@ -403,6 +405,7 @@ public:
rz_asLargeAs (new_uri(LV2_RESIZE_PORT__asLargeAs)),
rz_minSize (new_uri(LV2_RESIZE_PORT__minimumSize)),

midi_binding (new_uri(LV2_MIDI__binding)),
midi_event (new_uri(LV2_MIDI__MidiEvent)),
patch_message (new_uri(LV2_PATCH__Message)),
time_position (new_uri(LV2_TIME__Position)),
@@ -2134,37 +2137,53 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)

// --------------------------------------------------------------------------------------------------------
// Set Port MIDI Map

if (LilvNode* const bindingNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.midi_binding.me))
{
if (LilvNode* const midiMapNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.mm_defaultControl.me))
if (const char* const bindingAsString = lilv_node_as_string(bindingNode))
{
if (lilv_node_is_blank(midiMapNode))
if (std::strncmp(bindingAsString, "B0", 2) == 0 && std::strlen(bindingAsString) == 6)
{
Lilv::Nodes midiMapTypeNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlType, nullptr));
Lilv::Nodes midiMapNumberNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlNumber, nullptr));
const char binding[3] = { bindingAsString[2], bindingAsString[3], '\0' };
const long number = std::strtol(binding, nullptr, 16);

if (midiMapTypeNodes.size() == 1 && midiMapNumberNodes.size() == 1)
if (number >= 0 && number <= 0xff)
{
if (const char* const midiMapType = midiMapTypeNodes.get_first().as_string())
{
/**/ if (std::strcmp(midiMapType, LV2_MIDI_Map__CC) == 0)
rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
else if (std::strcmp(midiMapType, LV2_MIDI_Map__NRPN) == 0)
rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_NRPN;
else
carla_stderr("lv2_rdf_new(\"%s\") - got unknown port Midi-Map type '%s'", uri, midiMapType);

rdfPort->MidiMap.Number = static_cast<uint32_t>(midiMapNumberNodes.get_first().as_int());
}
rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
rdfPort->MidiMap.Number = static_cast<uint32_t>(number);
}
}
}

lilv_node_free(bindingNode);
}
else if (LilvNode* const midiMapNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.mm_defaultControl.me))
{
if (lilv_node_is_blank(midiMapNode))
{
Lilv::Nodes midiMapTypeNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlType, nullptr));
Lilv::Nodes midiMapNumberNodes(lv2World.find_nodes(midiMapNode, lv2World.mm_controlNumber, nullptr));

lilv_nodes_free(const_cast<LilvNodes*>(midiMapTypeNodes.me));
lilv_nodes_free(const_cast<LilvNodes*>(midiMapNumberNodes.me));
if (midiMapTypeNodes.size() == 1 && midiMapNumberNodes.size() == 1)
{
if (const char* const midiMapType = midiMapTypeNodes.get_first().as_string())
{
/**/ if (std::strcmp(midiMapType, LV2_MIDI_Map__CC) == 0)
rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
else if (std::strcmp(midiMapType, LV2_MIDI_Map__NRPN) == 0)
rdfPort->MidiMap.Type = LV2_PORT_MIDI_MAP_NRPN;
else
carla_stderr("lv2_rdf_new(\"%s\") - got unknown port Midi-Map type '%s'", uri, midiMapType);

rdfPort->MidiMap.Number = static_cast<uint32_t>(midiMapNumberNodes.get_first().as_int());
}
}

lilv_node_free(midiMapNode);
lilv_nodes_free(const_cast<LilvNodes*>(midiMapTypeNodes.me));
lilv_nodes_free(const_cast<LilvNodes*>(midiMapNumberNodes.me));
}

// TODO - also check using new official MIDI API too
lilv_node_free(midiMapNode);
}

// --------------------------------------------------------------------------------------------------------
@@ -2452,6 +2471,30 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets)
lilv_node_free(groupNode);
}

// ----------------------------------------------------------------------------------------------------
// Set Port MIDI Map

if (LilvNode* const bindingNode = lilv_world_get(lv2World.me, patchWritableNode,
lv2World.midi_binding.me, nullptr))
{
if (const char* const bindingAsString = lilv_node_as_string(bindingNode))
{
if (std::strncmp(bindingAsString, "B0", 2) == 0 && std::strlen(bindingAsString) == 6)
{
const char binding[3] = { bindingAsString[2], bindingAsString[3], '\0' };
const long number = std::strtol(binding, nullptr, 16);

if (number >= 0 && number <= 0xff)
{
rdfParam.MidiMap.Type = LV2_PORT_MIDI_MAP_CC;
rdfParam.MidiMap.Number = static_cast<uint32_t>(number);
}
}
}

lilv_node_free(bindingNode);
}

// ----------------------------------------------------------------------------------------------------
// Set Port Points



Loading…
Cancel
Save