Phase 25: improve LADSPA discovery, parameter editing and plugin lifecycle

This commit is contained in:
Johannes Findeisen 2026-10-27 16:24:21 +01:00
commit 7bff7b535d
18 changed files with 591 additions and 42 deletions

View file

@ -3,6 +3,8 @@
#include "../../src/gui/sequencer_widget.hpp"
#include "../../src/gui/piano_roll.hpp"
#include "../../src/gui/mixer_widget.hpp"
#include "../../src/gui/plugin_dialog.hpp"
#include <FL/Fl_Hold_Browser.H>
#include <unistd.h>
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
@ -635,6 +637,37 @@ int main(int argc, char **argv)
size_t id = SIZE_MAX;
CHECK(window.add_plugin(module,0,&id) == XTC_OK);
xtc_plugin_spec spec{};
// Exercise the actual modal chooser/editor with copied metadata only.
Fl::add_timeout(.05,[](void *) {
auto *dialog = Fl::first_window();
CHECK(dialog && dialog->label() && std::strcmp(dialog->label(),"LADSPA descriptors") == 0);
if (!dialog) return;
for (int i = 0; i < dialog->children(); ++i)
if (auto *list = dynamic_cast<Fl_Hold_Browser *>(dialog->child(i))) {
CHECK(list->size() == 7); list->select(2);
}
auto *choose = find(dialog,"Choose"); CHECK(choose); if (choose) choose->do_callback();
});
unsigned int chosen = UINT32_MAX;
CHECK(xtc_choose_plugin(module,48000,chosen) && chosen == 1);
xtc_plugin_details details{}; xtc_plugin_spec edited{};
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK);
CHECK(xtc_plugin_describe(&spec,48000,&details) == XTC_OK);
spec.values[0] = .25f; spec.point_count = 1; spec.points[0] = {0,spec.ports[0],0,.5f};
Fl::add_timeout(.05,[](void *) {
auto *dialog = Fl::first_window(); CHECK(dialog);
CHECK(contains(dialog,"Test gain"));
auto *reset = find(dialog,"Reset defaults"); CHECK(reset); if (reset) reset->do_callback();
auto *apply = find(dialog,"Apply"); CHECK(apply); if (apply) apply->do_callback();
});
CHECK(xtc_edit_plugin(spec,details,edited) && edited.values[0] == 1 && !edited.point_count);
edited.values[0] = .75f;
Fl::add_timeout(.05,[](void *) {
auto *dialog = Fl::first_window(); auto *cancel = find(dialog,"Cancel");
CHECK(cancel); if (cancel) cancel->do_callback();
});
CHECK(!xtc_edit_plugin(spec,details,edited) && edited.values[0] == .75f);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK);
CHECK(window.set_plugin_control(id,spec.ports[0],.5f) == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.values[0] == .5f);
@ -656,6 +689,33 @@ int main(int argc, char **argv)
CHECK(window.open_project("/tmp/xtc-gui-plugin-test.xtc") == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.values[0] == .5f);
CHECK(spec.point_count == 1 && spec.points[0].tick == 960 && spec.points[0].value == .25f);
CHECK(window.reset_plugin(id) == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.values[0] == 1 && !spec.point_count);
CHECK(window.undo(false) == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.values[0] == .5f && spec.point_count == 1);
// Replace an effect while preserving node ID and wires; undo restores state.
auto *canvas = graph_canvas(&window);
CHECK(canvas->add_node(XTC_NODE_OSCILLATOR) == XTC_OK);
const size_t source_id = canvas->selected_node();
CHECK(canvas->connect_ports({source_id,1,id,0}) == XTC_OK);
CHECK(window.replace_plugin(id,module,4) == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.index == 4 && spec.values[0] == 2 && !spec.point_count);
before = sequence->project();
CHECK(window.replace_plugin(id,module,1) == XTC_ERR_UNSUPPORTED && sequence->project() == before);
CHECK(window.replace_plugin(id,module,3) == XTC_ERR_INVALID_STATE && sequence->project() == before);
CHECK(window.replace_plugin(id,"/absent/plugin.so",0) == XTC_ERR_NOT_FOUND && sequence->project() == before);
CHECK(window.undo(false) == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),id,&spec) == XTC_OK && spec.index == 0 && spec.values[0] == .5f && spec.point_count == 1);
const xtc_connection_info wire{source_id,1,id,0}; size_t inserted = SIZE_MAX;
CHECK(window.insert_plugin(wire,module,0,&inserted) == XTC_OK && inserted != id);
xtc_routing_info routing{};
CHECK(canvas->routing(inserted,routing) && routing.inputs == 1 && routing.outputs == 1);
before = sequence->project();
CHECK(window.insert_plugin(wire,module,0) == XTC_ERR_NOT_FOUND && sequence->project() == before);
CHECK(canvas->select_node(inserted) && canvas->delete_selected() == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),inserted,&edited) == XTC_ERR_NOT_FOUND);
CHECK(window.undo(false) == XTC_OK);
CHECK(xtc_graph_get_plugin(xtc_project_graph(sequence->project()),inserted,&edited) == XTC_OK);
xtc_project *missing = nullptr; xtc_graph *graph = nullptr; size_t absent;
CHECK(xtc_project_create(&missing) == XTC_OK);
CHECK(xtc_graph_create(8,&graph) == XTC_OK);