|
1 | | -// SPDX-FileCopyrightText: 2012-2023 MOD Audio UG |
| 1 | +// SPDX-FileCopyrightText: 2012-2025 MOD Audio UG |
2 | 2 | // SPDX-License-Identifier: AGPL-3.0-or-later |
3 | 3 |
|
4 | 4 | #include "utils.h" |
|
15 | 15 | #include <lv2/midi/midi.h> |
16 | 16 | #include <lv2/morph/morph.h> |
17 | 17 | #include <lv2/patch/patch.h> |
| 18 | +#include <lv2/port-groups/port-groups.h> |
18 | 19 | #include <lv2/port-props/port-props.h> |
19 | 20 | #include <lv2/presets/presets.h> |
20 | 21 | #include <lv2/state/state.h> |
@@ -210,6 +211,7 @@ static const bool kOnlyShowPluginsWithMODGUI = getenv("MOD_UI_ONLY_SHOW_PLUGINS_ |
210 | 211 | { nullptr, nullptr } \ |
211 | 212 | }, \ |
212 | 213 | nullptr, \ |
| 214 | + nullptr, \ |
213 | 215 | nullptr \ |
214 | 216 | } |
215 | 217 |
|
@@ -358,6 +360,7 @@ struct NamespaceDefinitions { |
358 | 360 | LilvNode* atom_bufferType; |
359 | 361 | LilvNode* atom_Sequence; |
360 | 362 | LilvNode* midi_MidiEvent; |
| 363 | + LilvNode* pgroups_group; |
361 | 364 | LilvNode* pprops_rangeSteps; |
362 | 365 | LilvNode* patch_readable; |
363 | 366 | LilvNode* patch_writable; |
@@ -451,6 +454,7 @@ struct NamespaceDefinitions { |
451 | 454 | atom_bufferType = lilv_new_uri(w, LV2_ATOM__bufferType); |
452 | 455 | atom_Sequence = lilv_new_uri(w, LV2_ATOM__Sequence); |
453 | 456 | midi_MidiEvent = lilv_new_uri(w, LV2_MIDI__MidiEvent); |
| 457 | + pgroups_group = lilv_new_uri(w, LV2_PORT_GROUPS__group); |
454 | 458 | pprops_rangeSteps = lilv_new_uri(w, LV2_PORT_PROPS__rangeSteps); |
455 | 459 | patch_readable = lilv_new_uri(w, LV2_PATCH__readable); |
456 | 460 | patch_writable = lilv_new_uri(w, LV2_PATCH__writable); |
@@ -522,6 +526,7 @@ struct NamespaceDefinitions { |
522 | 526 | lilv_node_free(atom_bufferType); |
523 | 527 | lilv_node_free(atom_Sequence); |
524 | 528 | lilv_node_free(midi_MidiEvent); |
| 529 | + lilv_node_free(pgroups_group); |
525 | 530 | lilv_node_free(pprops_rangeSteps); |
526 | 531 | lilv_node_free(patch_readable); |
527 | 532 | lilv_node_free(patch_writable); |
@@ -2605,6 +2610,8 @@ const PluginInfo& _get_plugin_info(LilvWorld* const w, |
2605 | 2610 | // -------------------------------------------------------------------------------------------------------- |
2606 | 2611 | // ports |
2607 | 2612 |
|
| 2613 | + std::unordered_map<std::string, PluginPortGroup> portGroups; |
| 2614 | + |
2608 | 2615 | if (const uint32_t count = lilv_plugin_get_num_ports(p)) |
2609 | 2616 | { |
2610 | 2617 | uint32_t countAudioInput=0, countAudioOutput=0; |
@@ -2851,6 +2858,47 @@ const PluginInfo& _get_plugin_info(LilvWorld* const w, |
2851 | 2858 | portinfo.designation = nc; |
2852 | 2859 | } |
2853 | 2860 |
|
| 2861 | + // ---------------------------------------------------------------------------------------------------- |
| 2862 | + // group |
| 2863 | + |
| 2864 | + if (LilvNodes* const nodes = lilv_port_get_value(p, port, ns.pgroups_group)) |
| 2865 | + { |
| 2866 | + LilvNode* const group = lilv_nodes_get_first(nodes); |
| 2867 | + portinfo.group = strdup(lilv_node_as_string(group)); |
| 2868 | + |
| 2869 | + if (! contains(portGroups, portinfo.group)) |
| 2870 | + { |
| 2871 | + PluginPortGroup& portGroup = portGroups[portinfo.group] = { |
| 2872 | + true, |
| 2873 | + portinfo.group, |
| 2874 | + nc, |
| 2875 | + nc, |
| 2876 | + }; |
| 2877 | + |
| 2878 | + if (LilvNode* const group_symbol = lilv_world_get(w, group, ns.lv2core_symbol, nullptr)) |
| 2879 | + { |
| 2880 | + if (const char* const symbolstr = lilv_node_as_string(group_symbol)) |
| 2881 | + portGroup.symbol = strdup(symbolstr); |
| 2882 | + |
| 2883 | + lilv_node_free(group_symbol); |
| 2884 | + } |
| 2885 | + |
| 2886 | + if (LilvNode* const group_name = lilv_world_get(w, group, ns.lv2core_name, nullptr)) |
| 2887 | + { |
| 2888 | + if (const char* const namestr = lilv_node_as_string(group_name)) |
| 2889 | + portGroup.symbol = strdup(namestr); |
| 2890 | + |
| 2891 | + lilv_node_free(group_name); |
| 2892 | + } |
| 2893 | + } |
| 2894 | + |
| 2895 | + lilv_nodes_free(nodes); |
| 2896 | + } |
| 2897 | + else |
| 2898 | + { |
| 2899 | + portinfo.group = nc; |
| 2900 | + } |
| 2901 | + |
2854 | 2902 | // ---------------------------------------------------------------------------------------------------- |
2855 | 2903 | // range steps |
2856 | 2904 |
|
@@ -3069,6 +3117,22 @@ const PluginInfo& _get_plugin_info(LilvWorld* const w, |
3069 | 3117 | info.iotype = kPluginIONull; |
3070 | 3118 | } |
3071 | 3119 |
|
| 3120 | + // -------------------------------------------------------------------------------------------------------- |
| 3121 | + // port groups |
| 3122 | + |
| 3123 | + if (size_t count = portGroups.size()) |
| 3124 | + { |
| 3125 | + PluginPortGroup* const groups = new PluginPortGroup[count+1]; |
| 3126 | + |
| 3127 | + count = 0; |
| 3128 | + for (auto& group : portGroups) |
| 3129 | + groups[count++] = group.second; |
| 3130 | + |
| 3131 | + memset(&groups[count], 0, sizeof(PluginPortGroup)); |
| 3132 | + |
| 3133 | + info.portGroups = groups; |
| 3134 | + } |
| 3135 | + |
3072 | 3136 | // -------------------------------------------------------------------------------------------------------- |
3073 | 3137 | // parameters |
3074 | 3138 |
|
@@ -3411,6 +3475,8 @@ static void _clear_port_info(PluginPort& portinfo) |
3411 | 3475 | free((void*)portinfo.comment); |
3412 | 3476 | if (portinfo.designation != nc) |
3413 | 3477 | free((void*)portinfo.designation); |
| 3478 | + if (portinfo.group != nc) |
| 3479 | + free((void*)portinfo.group); |
3414 | 3480 | if (portinfo.shortName != nc) |
3415 | 3481 | free((void*)portinfo.shortName); |
3416 | 3482 |
|
@@ -3441,6 +3507,15 @@ static void _clear_port_info(PluginPort& portinfo) |
3441 | 3507 | memset(&portinfo, 0, sizeof(PluginPort)); |
3442 | 3508 | } |
3443 | 3509 |
|
| 3510 | +static void _clear_port_group_info(const PluginPortGroup& portGroup) |
| 3511 | +{ |
| 3512 | + // NOTE portGroup.uri points to port.group |
| 3513 | + if (portGroup.symbol != nc) |
| 3514 | + free((void*)portGroup.symbol); |
| 3515 | + if (portGroup.name != nc) |
| 3516 | + free((void*)portGroup.name); |
| 3517 | +} |
| 3518 | + |
3444 | 3519 | static void _clear_parameter_info(const PluginParameter& parameter) |
3445 | 3520 | { |
3446 | 3521 | free((void*)parameter.uri); |
@@ -3610,6 +3685,13 @@ static void _clear_plugin_info(PluginInfo& info) |
3610 | 3685 | delete[] info.ports.midi.output; |
3611 | 3686 | } |
3612 | 3687 |
|
| 3688 | + if (info.portGroups != nullptr) |
| 3689 | + { |
| 3690 | + for (int i=0; info.portGroups[i].valid; ++i) |
| 3691 | + _clear_port_group_info(info.portGroups[i]); |
| 3692 | + delete[] info.portGroups; |
| 3693 | + } |
| 3694 | + |
3613 | 3695 | if (info.parameters != nullptr) |
3614 | 3696 | { |
3615 | 3697 | for (int i=0; info.parameters[i].valid; ++i) |
|
0 commit comments