Skip to content

Commit

Permalink
[dynamic ports] Improve api
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Jul 28, 2024
1 parent 5d87d29 commit e4dd667
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 14 deletions.
166 changes: 166 additions & 0 deletions examples/Raw/DynamicPort.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#pragma once
#include <cmath>

#include <functional>
#include <vector>

/* SPDX-License-Identifier: GPL-3.0-or-later */

namespace examples
{
struct SumPorts
{
static constexpr auto name() { return "Sum"; }
static constexpr auto c_name() { return "avnd_sumports"; }
static constexpr auto author() { return "Jean-Michaël Celerier"; }
static constexpr auto category() { return "Debug"; }
static constexpr auto description()
{
return "Example of an object with dynamic number of inputs";
}
static constexpr auto uuid() { return "48b57b3e-227a-4a55-adce-86c011dcf491"; }

struct inputs
{
struct
{
static constexpr auto name() { return "Control"; }
enum widget
{
spinbox
};
struct range
{
int min = 0, max = 10, init = 0;
};
int value = 0;

static std::function<void(SumPorts&, int)> on_controller_setup()
{
return [](SumPorts& object, int value) {
object.inputs.in_i.request_port_resize(value);
object.outputs.out_i.request_port_resize(value);
};
}
static std::function<void(SumPorts&, int)> on_controller_interaction()
{
return [](SumPorts& object, int value) {
object.inputs.in_i.request_port_resize(value);
object.outputs.out_i.request_port_resize(value);
};
}
} controller;

struct
{
struct port
{
static constexpr auto name() { return "Input {}"; }
struct range
{
double min = 0, max = 1, init = 0;
};
enum widget
{
knob
};
double value;
};
std::vector<port> ports{};
std::function<void(int)> request_port_resize;
} in_i;
} inputs;

struct
{
struct
{
static constexpr auto name() { return "Output"; }
double value{};
} out;
struct
{
static constexpr auto name() { return "C"; }
double value{};
} c;

struct
{
struct port
{
static constexpr auto name() { return "Output {}"; }
double value;
};
std::vector<port> ports{};
std::function<void(int)> request_port_resize;
} out_i;
} outputs;

double filtered{};
void operator()()
{
outputs.out.value = 0;
int k = 0;
const int N = inputs.in_i.ports.size();

outputs.c.value = N;

for(auto val : inputs.in_i.ports)
outputs.out.value += std::pow(10, k++) * std::floor(10 * val.value);
for(int i = 0; i < N; i++)
outputs.out_i.ports[i].value = inputs.in_i.ports[i].value;
}

struct ui
{
static constexpr auto name() { return "Main"; }
static constexpr auto layout()
{
enum
{
hbox
};
return hbox;
}
struct
{
static constexpr auto layout()
{
enum
{
control
};
return control;
}
decltype(&inputs::controller) model = &inputs::controller;
} float_widget;

struct
{
static constexpr auto layout()
{
enum
{
control
};
return control;
}
decltype(&inputs::in_i) model = &inputs::in_i;
} multi_widget;
};
};
}

// Adding a new concept.
// Process.
// 1. Specifying the concept:
// avnd/concepts/dynamic_port.hpp

// 2. Specify the introspection struct
// avnd/introspection/port.hpp

// 3. Specify the input or output (or both) introspection struct
// avnd/introspection/input.hpp

// 4. Create a filter
// avnd/binding/ossia/dynamic_ports.hpp
10 changes: 7 additions & 3 deletions include/avnd/binding/ossia/port_run_postprocess.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,18 @@ struct process_after_run
write_value(ctrl, port, ctrl.value, 0, avnd::field_index<Idx>{});
}

template <avnd::parameter Field, std::size_t Idx>
template <avnd::dynamic_ports_port Field, std::size_t Idx>
void operator()(
Field& ctrl, std::vector<ossia::value_outlet*>& port,
avnd::field_index<Idx>) const noexcept
{
int N = port.size();

write_value(ctrl, port, ctrl.value, 0, avnd::field_index<Idx>{});
assert(N == ctrl.ports.size());
for(int i = 0; i < N; i++)
{
write_value(
ctrl.ports[i], *port[i], ctrl.ports[i].value, 0, avnd::field_index<Idx>{});
}
}

template <avnd::linear_sample_accurate_parameter Field, std::size_t Idx>
Expand Down
12 changes: 6 additions & 6 deletions include/avnd/binding/ossia/port_run_preprocess.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct process_before_run
}
}

template <avnd::parameter Field, std::size_t Idx>
template <avnd::dynamic_ports_port Field, std::size_t Idx>
void init_value(
Field& ctrl, std::vector<ossia::value_inlet*>& ports,
avnd::field_index<Idx> idx) const noexcept
Expand All @@ -77,8 +77,7 @@ struct process_before_run
auto& last = port.data.get_data().back().value;

// FIXME check optional ports case
written |= self.from_ossia_value(ctrl, last, ctrl.ports[p], idx);
qDebug() << ossia::value_to_pretty_string(last) << p << ctrl.ports[p];
written |= self.from_ossia_value(ctrl.ports[p], last, ctrl.ports[p].value, idx);

// FIXME
// if constexpr(avnd::control<Field>)
Expand Down Expand Up @@ -108,7 +107,8 @@ struct process_before_run
{
init_value(ctrl, port, avnd::field_index<Idx>{});
}
template <avnd::parameter Field, std::size_t Idx>

template <avnd::dynamic_ports_port Field, std::size_t Idx>
void operator()(
Field& ctrl, std::vector<ossia::value_inlet*>& port,
avnd::field_index<Idx> idx) const noexcept
Expand Down Expand Up @@ -406,15 +406,15 @@ struct process_before_run
}
}

template <avnd::parameter Field, std::size_t Idx>
template <avnd::dynamic_ports_port Field, std::size_t Idx>
void operator()(
Field& ctrl, std::vector<ossia::value_outlet*>& ports,
avnd::field_index<Idx>) const noexcept
{
ctrl.ports.resize(ports.size());
for(auto& port_value : ctrl.ports)
{
port_value = {};
port_value.value = {};
}
}

Expand Down
19 changes: 14 additions & 5 deletions include/avnd/binding/ossia/port_setup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ struct get_ossia_inlet_type<N, T>
template <typename N, avnd::parameter T>
struct get_ossia_inlet_type<N, T>
{
using type = std::conditional_t<
avnd::dynamic_ports_port<T>, std::vector<ossia::value_inlet*>, ossia::value_inlet>;
using type = ossia::value_inlet;
};
template <typename N, avnd::dynamic_ports_port T>
struct get_ossia_inlet_type<N, T>
{
using base_type = typename decltype(T{}.ports)::value_type;
using type = std::vector<typename get_ossia_inlet_type<N, base_type>::type*>;
};
template <typename N, avnd::midi_port T>
struct get_ossia_inlet_type<N, T>
Expand Down Expand Up @@ -79,9 +84,13 @@ struct get_ossia_outlet_type<N, T>
template <typename N, avnd::parameter T>
struct get_ossia_outlet_type<N, T>
{
using type = std::conditional_t<
avnd::dynamic_ports_port<T>, std::vector<ossia::value_outlet*>,
ossia::value_outlet>;
using type = ossia::value_outlet;
};
template <typename N, avnd::dynamic_ports_port T>
struct get_ossia_outlet_type<N, T>
{
using base_type = typename decltype(T{}.ports)::value_type;
using type = std::vector<typename get_ossia_outlet_type<N, base_type>::type*>;
};
template <typename N, avnd::midi_port T>
struct get_ossia_outlet_type<N, T>
Expand Down
1 change: 1 addition & 0 deletions include/avnd/concepts/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <avnd/concepts/smooth.hpp>
#include <avnd/concepts/soundfile.hpp>
#include <avnd/concepts/synth.hpp>
#include <avnd/concepts/temporality.hpp>
#include <avnd/concepts/ui.hpp>
#include <avnd/concepts/widget.hpp>
#include <avnd/concepts/worker.hpp>

0 comments on commit e4dd667

Please sign in to comment.