ui: the node editor offers the de-noise node and persists its window
The form gains a `median samples` row, shown only for `DeNoise`; the corner row widens to anything that reads `fc` (`math_op_uses_fc()`) while `q` stays band-pass-only, and the wiring row keeps its place at the end so the form's order is unchanged for every existing op. The session format gains a thirteenth field, `med_n`, after `y`. A twelve-field node -- a file written before this node existed -- still loads, with `med_n` left at the struct's default, which is what such a file meant; the reader's `return number(...) && ...` chain had to become a guarded sequence so the thirteenth field could be read conditionally. The math probe enables the channel it builds its graphs from, the same self-sufficiency rule the noise and measurement probes already follow: `enable_all_probe` ends by switching one signal off, and with `sine` gone the graphs landed on `square`, changing a documented line for reasons unrelated to the math. Readings: `[math-probe] 2 math channels on 'sine' and 'noise'`, `pane add: 'math3' sources 'sine'`, `graph edit: stored_slots 31000 -> 32000`, `dialog build: nodes=2, output after add=1` and the rest of the suite unchanged; no `Gtk-CRITICAL`.
This commit is contained in:
1 parent
1bde8809dd
commit
5c2c221777
5 files changed
+41
-7
No files matched your search
+14
-4
@@ -366,7 +366,7 @@ std::string math_node_text(const MathNode& node) {
|
||||
std::ostringstream o;
|
||||
o << kind << '|' << node.source << '|' << node.in_a << '|' << node.in_b << '|' << node.gain << '|'
|
||||
<< node.offset << '|' << node.fc << '|' << node.q << '|' << node.lo << '|' << node.hi << '|'
|
||||
<< node.x << '|' << node.y;
|
||||
<< node.x << '|' << node.y << '|' << node.med_n;
|
||||
return o.str();
|
||||
}
|
||||
|
||||
@@ -382,7 +382,9 @@ bool math_node_from_text(const std::string& text, MathNode& out) {
|
||||
}
|
||||
}
|
||||
f.push_back(cur);
|
||||
if (f.size() != 12u) return false;
|
||||
// Twelve fields is a session file written before the de-noise node existed; its `med_n` stays at the
|
||||
// struct's default, which is what that file meant.
|
||||
if (f.size() != 12u && f.size() != 13u) return false;
|
||||
const auto number = [&](std::size_t i, double& v) {
|
||||
try {
|
||||
v = std::stod(f[i]);
|
||||
@@ -402,8 +404,16 @@ bool math_node_from_text(const std::string& text, MathNode& out) {
|
||||
out.source = f[1];
|
||||
out.in_a = static_cast<int>(in_a);
|
||||
out.in_b = static_cast<int>(in_b);
|
||||
return number(4, out.gain) && number(5, out.offset) && number(6, out.fc) && number(7, out.q) &&
|
||||
number(8, out.lo) && number(9, out.hi) && number(10, out.x) && number(11, out.y);
|
||||
if (!(number(4, out.gain) && number(5, out.offset) && number(6, out.fc) && number(7, out.q) &&
|
||||
number(8, out.lo) && number(9, out.hi) && number(10, out.x) && number(11, out.y))) {
|
||||
return false;
|
||||
}
|
||||
if (f.size() == 13u) {
|
||||
double med = 0.0;
|
||||
if (!number(12, med)) return false;
|
||||
out.med_n = static_cast<int>(med);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_layout(const std::string& path, LayoutState& out) {
|
||||
|
||||
+9
-1
@@ -2140,6 +2140,14 @@ void open_math_dialog(App& app, int edit) {
|
||||
gtk_box_append(GTK_BOX(form), clamp_rows);
|
||||
}
|
||||
|
||||
// Odd, 3..9. The engine rounds up to odd anyway, but a step of 2 means the widget never offers an even
|
||||
// one.
|
||||
d->med = gtk_spin_button_new_with_range(3.0, 9.0, 2.0);
|
||||
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->med), 0);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->med), 5.0);
|
||||
g_signal_connect(d->med, "value-changed", G_CALLBACK(on_math_param_changed), d);
|
||||
gtk_box_append(GTK_BOX(form), math_row("median samples", d->med, &d->rows[6]));
|
||||
|
||||
d->inputs = gtk_label_new("");
|
||||
gtk_label_set_wrap(GTK_LABEL(d->inputs), true);
|
||||
gtk_widget_add_css_class(d->inputs, "dim-label");
|
||||
@@ -2159,7 +2167,7 @@ void open_math_dialog(App& app, int edit) {
|
||||
gtk_widget_set_visible(d->problem, FALSE);
|
||||
gtk_box_append(GTK_BOX(form), d->problem);
|
||||
|
||||
// A menu of the twelve ops rather than one button that always makes a gain: building anything
|
||||
// A menu of the thirteen ops rather than one button that always makes a gain: building anything
|
||||
// else was add-then-change-the-dropdown, which is two steps for the common case.
|
||||
GtkWidget* add = gtk_menu_button_new();
|
||||
gtk_menu_button_set_label(GTK_MENU_BUTTON(add), "add node");
|
||||
|
||||
+2
-1
@@ -978,9 +978,10 @@ struct MathDialog {
|
||||
GtkWidget* offset = nullptr;
|
||||
GtkWidget* fc = nullptr;
|
||||
GtkWidget* q = nullptr;
|
||||
GtkWidget* med = nullptr; ///< MathNode::med_n
|
||||
GtkWidget* lo = nullptr;
|
||||
GtkWidget* hi = nullptr;
|
||||
GtkWidget* rows[6] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
GtkWidget* rows[7] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
GtkWidget* inputs = nullptr;
|
||||
/// The validation line and the button it governs. Both are set from `math_dialog_sync()` and from
|
||||
/// nowhere else, so what the line says and what the button allows cannot disagree.
|
||||
|
||||
+6
-1
@@ -835,6 +835,7 @@ void on_math_param_changed(GtkWidget*, gpointer user) {
|
||||
n.offset = gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->offset));
|
||||
n.fc = gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->fc));
|
||||
n.q = gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->q));
|
||||
n.med_n = static_cast<int>(gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->med)));
|
||||
n.lo = gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->lo));
|
||||
n.hi = gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->hi));
|
||||
if (d->source_drop != nullptr) {
|
||||
@@ -930,14 +931,18 @@ void math_dialog_sync_form(MathDialog* d) {
|
||||
const bool source = op == MathOp::Source;
|
||||
gtk_widget_set_visible(d->rows[0], source); // the source channel
|
||||
gtk_widget_set_visible(d->rows[1], gain);
|
||||
gtk_widget_set_visible(d->rows[2], filter);
|
||||
// The corner row is shown for anything that reads `fc`, which is now the three biquads *and* the
|
||||
// de-noise node; `q` stays a band-pass-only row.
|
||||
gtk_widget_set_visible(d->rows[2], math_op_uses_fc(op));
|
||||
gtk_widget_set_visible(d->rows[3], filter && op == MathOp::BandPass);
|
||||
gtk_widget_set_visible(d->rows[4], clamp);
|
||||
gtk_widget_set_visible(d->rows[5], true); // the inputs, always: they say what is wired
|
||||
gtk_widget_set_visible(d->rows[6], math_op_uses_median(op));
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->gain), n.gain);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->offset), n.offset);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->fc), n.fc);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->q), n.q);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->med), static_cast<double>(n.med_n));
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->lo), n.lo);
|
||||
gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->hi), n.hi);
|
||||
if (d->source_drop != nullptr) {
|
||||
|
||||
@@ -281,6 +281,16 @@ gboolean eventzoom_probe(gpointer user) {
|
||||
gboolean math_probe(gpointer user) {
|
||||
App* a = static_cast<App*>(user);
|
||||
if (a->window == nullptr) return G_SOURCE_REMOVE;
|
||||
// The channel the graphs are built from is enabled *here*, for the reason the noise and measurement
|
||||
// probes give: `enable_all_probe` finishes by switching one signal off, and with `sine` gone the graphs
|
||||
// land on `square`, which turns the documented "2 math channels on 'sine' and 'noise'" into a different
|
||||
// line for reasons that have nothing to do with the math.
|
||||
{
|
||||
const std::vector<SignalInfo>& signals = a->model->signals();
|
||||
for (std::size_t i = 0; i < signals.size(); ++i) {
|
||||
if (signals[i].name == "sine") a->model->set_signal_enabled(i, true);
|
||||
}
|
||||
}
|
||||
std::string name;
|
||||
std::string late_name;
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user