Skip to content

Commit f05f891

Browse files
committed
Add support for lv2 group extension to lilv backend
1 parent 4ee3723 commit f05f891

File tree

2 files changed

+140
-4
lines changed

2 files changed

+140
-4
lines changed

utils/utils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ typedef struct {
4343
const char* email;
4444
} PluginAuthor;
4545

46+
typedef struct {
47+
bool valid;
48+
const char* symbol;
49+
const char* name;
50+
} PluginPortGroup;
51+
4652
typedef struct {
4753
bool valid;
4854
unsigned int index;
@@ -108,6 +114,7 @@ typedef struct {
108114
int rangeSteps;
109115
const PluginPortScalePoint* scalePoints;
110116
const char* shortName;
117+
const char* groupSymbol;
111118
} PluginPort;
112119

113120
typedef struct {
@@ -187,6 +194,7 @@ typedef struct {
187194
PluginPorts ports;
188195
const PluginParameter* parameters;
189196
const PluginPreset* presets;
197+
const PluginPortGroup* portGroups;
190198
} PluginInfo;
191199

192200
typedef struct {

utils/utils_lilv.cpp

Lines changed: 132 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <lv2/state/state.h>
2121
#include <lv2/units/units.h>
2222

23+
#include <lv2/port-groups/port-groups.h>
24+
2325
// do not enable external-ui support in embed targets
2426
#if !(defined(_MOD_DEVICE_DUO) || defined(_MOD_DEVICE_DUOX) || defined(_MOD_DEVICE_DWARF))
2527
#define WITH_EXTERNAL_UI_SUPPORT
@@ -210,6 +212,7 @@ static const bool kOnlyShowPluginsWithMODGUI = getenv("MOD_UI_ONLY_SHOW_PLUGINS_
210212
{ nullptr, nullptr } \
211213
}, \
212214
nullptr, \
215+
nullptr, \
213216
nullptr \
214217
}
215218

@@ -295,10 +298,12 @@ inline void fill_iotype(PInfo* const info,
295298

296299
// --------------------------------------------------------------------------------------------------------
297300

298-
#define LILV_NS_INGEN "http://drobilla.net/ns/ingen#"
299-
#define LILV_NS_MOD "http://moddevices.com/ns/mod#"
300-
#define LILV_NS_MODGUI "http://moddevices.com/ns/modgui#"
301-
#define LILV_NS_MODPEDAL "http://moddevices.com/ns/modpedal#"
301+
#define LILV_NS_INGEN "http://drobilla.net/ns/ingen#"
302+
#define LILV_NS_MOD "http://moddevices.com/ns/mod#"
303+
#define LILV_NS_MODGUI "http://moddevices.com/ns/modgui#"
304+
#define LILV_NS_MODPEDAL "http://moddevices.com/ns/modpedal#"
305+
306+
#define LV2_NS_PORT_GROUPS "http://lv2plug.in/ns/ext/port-groups#"
302307

303308
#define MOD__CVPort LILV_NS_MOD "CVPort"
304309

@@ -366,6 +371,9 @@ struct NamespaceDefinitions {
366371
LilvNode* units_render;
367372
LilvNode* units_symbol;
368373
LilvNode* units_unit;
374+
LilvNode* port_groups_inputgroup;
375+
LilvNode* port_groups_outputgroup;
376+
LilvNode* port_groups_groupName;
369377
bool initialized;
370378

371379
NamespaceDefinitions(LilvWorld* const w)
@@ -459,6 +467,9 @@ struct NamespaceDefinitions {
459467
units_render = lilv_new_uri(w, LV2_UNITS__render);
460468
units_symbol = lilv_new_uri(w, LV2_UNITS__symbol);
461469
units_unit = lilv_new_uri(w, LV2_UNITS__unit);
470+
port_groups_inputgroup = lilv_new_uri(w, LV2_PORT_GROUPS__InputGroup);
471+
port_groups_outputgroup = lilv_new_uri(w, LV2_PORT_GROUPS__OutputGroup);
472+
port_groups_groupName = lilv_new_uri(w, LV2_PORT_GROUPS__group);
462473
}
463474

464475
void cleanup()
@@ -530,6 +541,9 @@ struct NamespaceDefinitions {
530541
lilv_node_free(units_render);
531542
lilv_node_free(units_symbol);
532543
lilv_node_free(units_unit);
544+
lilv_node_free(port_groups_inputgroup);
545+
lilv_node_free(port_groups_outputgroup);
546+
lilv_node_free(port_groups_groupName);
533547
}
534548

535549
static NamespaceDefinitions& getStaticInstance(LilvWorld* const w)
@@ -1963,6 +1977,58 @@ static void _fill_units(LilvWorld* const w,
19631977

19641978
}
19651979

1980+
const PluginPortGroup _get_port_group(LilvWorld* const w, const LilvNode* const group, const NamespaceDefinitions& ns)
1981+
{
1982+
PluginPortGroup port_group;
1983+
1984+
memset(&port_group, 0, sizeof(PluginPortGroup));
1985+
if (LilvNode* const group_type = lilv_world_get(w, group, ns.rdf_type, NULL))
1986+
{
1987+
if (lilv_node_equals(group_type, ns.port_groups_inputgroup) || lilv_node_equals(group_type, ns.port_groups_outputgroup))
1988+
{
1989+
if (LilvNode* const group_symbol = lilv_world_get(w, group, ns.lv2core_symbol, nullptr))
1990+
{
1991+
const char* const groupsymbol = lilv_node_as_string(group_symbol);
1992+
if (groupsymbol != nullptr && strlen(groupsymbol) > 0)
1993+
{
1994+
// get description
1995+
LilvNode* const group_name = lilv_world_get(w, group, ns.lv2core_name, nullptr);
1996+
const char* const groupname = (group_name != nullptr) ? lilv_node_as_string(group_name) : nullptr;
1997+
1998+
// create a new port group
1999+
port_group.valid = true;
2000+
port_group.symbol = strdup(groupsymbol);
2001+
port_group.name = groupname == nullptr ? strdup(groupsymbol) : strdup(groupname);
2002+
2003+
lilv_node_free(group_name);
2004+
}
2005+
else
2006+
{
2007+
// symbol must be defined for groups
2008+
printf("WARNING: invalid group lv2:symbol is empty\n");
2009+
}
2010+
lilv_node_free(group_symbol);
2011+
}
2012+
else
2013+
{
2014+
printf("WARNING: invalid group no lv2:symbol defined\n");
2015+
}
2016+
2017+
lilv_node_free(group_type);
2018+
}
2019+
else
2020+
{
2021+
printf("WARNING: invalid group no required port type\n");
2022+
}
2023+
}
2024+
else
2025+
{
2026+
printf("WARNING: invalid group no rdf:type defined\n");
2027+
}
2028+
2029+
return port_group;
2030+
}
2031+
19662032
const PluginInfo& _get_plugin_info(LilvWorld* const w,
19672033
const LilvPlugin* const p,
19682034
const NamespaceDefinitions& ns)
@@ -2611,6 +2677,7 @@ const PluginInfo& _get_plugin_info(LilvWorld* const w,
26112677
uint32_t countControlInput=0, countControlOutput=0;
26122678
uint32_t countCvInput=0, countCvOutput=0;
26132679
uint32_t countMidiInput=0, countMidiOutput=0;
2680+
std::map<std::string, PluginPortGroup> usedGroups;
26142681

26152682
// precalculate port counts first
26162683
for (uint32_t i=0; i<count; ++i)
@@ -2851,6 +2918,36 @@ const PluginInfo& _get_plugin_info(LilvWorld* const w,
28512918
portinfo.designation = nc;
28522919
}
28532920

2921+
// ----------------------------------------------------------------------------------------------------
2922+
// groups
2923+
portinfo.groupSymbol = nc;
2924+
if (LilvNode* symbolnode = lilv_port_get(p, port, ns.port_groups_groupName))
2925+
{
2926+
const char* groupName = lilv_node_as_string(symbolnode);
2927+
if (!contains(usedGroups, groupName))
2928+
{
2929+
const PluginPortGroup& group = _get_port_group(w, symbolnode, ns);
2930+
2931+
if (group.valid)
2932+
{
2933+
// read the group definition
2934+
usedGroups[groupName] = group;
2935+
portinfo.groupSymbol = strdup(group.symbol);
2936+
}
2937+
else
2938+
{
2939+
printf("WARNING: Group definition not found for %s\n", groupName);
2940+
}
2941+
}
2942+
else
2943+
{
2944+
// already cached
2945+
portinfo.groupSymbol = strdup(usedGroups[groupName].symbol);
2946+
}
2947+
2948+
lilv_free(symbolnode);
2949+
}
2950+
28542951
// ----------------------------------------------------------------------------------------------------
28552952
// range steps
28562953

@@ -3063,6 +3160,22 @@ const PluginInfo& _get_plugin_info(LilvWorld* const w,
30633160

30643161
// also iotype
30653162
fill_iotype(&info, countAudioInput, countAudioOutput, countMidiInput, countMidiOutput);
3163+
3164+
// --------------------------------------------------------------------------------------------------------
3165+
// groups
3166+
3167+
if (size_t countGroups = usedGroups.size())
3168+
{
3169+
PluginPortGroup* const groups = new PluginPortGroup[countGroups+1];
3170+
3171+
countGroups = 0;
3172+
for (auto& group : usedGroups)
3173+
groups[countGroups++] = group.second;
3174+
3175+
memset(&groups[countGroups], 0, sizeof(PluginPortGroup));
3176+
3177+
info.portGroups = groups;
3178+
}
30663179
}
30673180
else
30683181
{
@@ -3413,6 +3526,8 @@ static void _clear_port_info(PluginPort& portinfo)
34133526
free((void*)portinfo.designation);
34143527
if (portinfo.shortName != nc)
34153528
free((void*)portinfo.shortName);
3529+
if (portinfo.groupSymbol != nc)
3530+
free((void*)portinfo.groupSymbol);
34163531

34173532
if (portinfo.properties != nullptr)
34183533
{
@@ -3441,6 +3556,12 @@ static void _clear_port_info(PluginPort& portinfo)
34413556
memset(&portinfo, 0, sizeof(PluginPort));
34423557
}
34433558

3559+
static void _clear_port_group_info(const PluginPortGroup& portGroup)
3560+
{
3561+
free((void*)portGroup.symbol);
3562+
free((void*)portGroup.name);
3563+
}
3564+
34443565
static void _clear_parameter_info(const PluginParameter& parameter)
34453566
{
34463567
free((void*)parameter.uri);
@@ -3610,6 +3731,13 @@ static void _clear_plugin_info(PluginInfo& info)
36103731
delete[] info.ports.midi.output;
36113732
}
36123733

3734+
if (info.portGroups != nullptr)
3735+
{
3736+
for (int i=0; info.portGroups[i].valid; ++i)
3737+
_clear_port_group_info(info.portGroups[i]);
3738+
delete[] info.portGroups;
3739+
}
3740+
36133741
if (info.parameters != nullptr)
36143742
{
36153743
for (int i=0; info.parameters[i].valid; ++i)

0 commit comments

Comments
 (0)