From 94608eaad1da0622a5eb1fa6d169f8e92d06a6aa Mon Sep 17 00:00:00 2001 From: Johannes Lorenz Date: Fri, 22 Sep 2023 23:42:45 +0200 Subject: [PATCH] Lv2Proc: Sort scale point maps (#6859) lilv can return the scale points in randomized order, and so the linked models (of stereo effects wit 2 `Lv2Proc`) may have different scale points. This would mean that the same combo enumeration value would have different float values in linked models. This problem is fixed by sorting the scale values. Also, it is more natural for users if scale points are enumerated in a numerical order. --- include/Lv2Basics.h | 6 ++++++ src/core/lv2/Lv2Proc.cpp | 28 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/Lv2Basics.h b/include/Lv2Basics.h index 9a958d973..53489e30d 100644 --- a/include/Lv2Basics.h +++ b/include/Lv2Basics.h @@ -47,8 +47,14 @@ struct LilvNodesDeleter void operator()(LilvNodes* n) { lilv_nodes_free(n); } }; +struct LilvScalePointsDeleter +{ + void operator()(LilvScalePoints* s) { lilv_scale_points_free(s); } +}; + using AutoLilvNode = std::unique_ptr; using AutoLilvNodes = std::unique_ptr; +using AutoLilvScalePoints = std::unique_ptr; /** Return QString from a plugin's node, everything will be freed automatically diff --git a/src/core/lv2/Lv2Proc.cpp b/src/core/lv2/Lv2Proc.cpp index 6776a26ed..a5fdf4041 100644 --- a/src/core/lv2/Lv2Proc.cpp +++ b/src/core/lv2/Lv2Proc.cpp @@ -574,19 +574,25 @@ void Lv2Proc::createPort(std::size_t portNum) break; case Lv2Ports::Vis::Enumeration: { - auto comboModel = new ComboBoxModel(nullptr, dispName); - LilvScalePoints* sps = - lilv_port_get_scale_points(m_plugin, lilvPort); - LILV_FOREACH(scale_points, i, sps) + ComboBoxModel* comboModel = new ComboBoxModel(nullptr, dispName); + { - const LilvScalePoint* sp = lilv_scale_points_get(sps, i); - ctrl->m_scalePointMap.push_back(lilv_node_as_float( - lilv_scale_point_get_value(sp))); - comboModel->addItem( - lilv_node_as_string( - lilv_scale_point_get_label(sp))); + AutoLilvScalePoints sps (static_cast(lilv_port_get_scale_points(m_plugin, lilvPort))); + // temporary map, since lilv may return scale points in random order + std::map scalePointMap; + LILV_FOREACH(scale_points, i, sps.get()) + { + const LilvScalePoint* sp = lilv_scale_points_get(sps.get(), i); + const float f = lilv_node_as_float(lilv_scale_point_get_value(sp)); + const char* s = lilv_node_as_string(lilv_scale_point_get_label(sp)); + scalePointMap[f] = s; + } + for (const auto& [f,s] : scalePointMap) + { + ctrl->m_scalePointMap.push_back(f); + comboModel->addItem(s); + } } - lilv_scale_points_free(sps); ctrl->m_connectedModel.reset(comboModel); // TODO: use default value on comboModel, too? break;