2 #include <Process/Dataflow/WidgetInlets.hpp>
3 #include <Process/ProcessFlags.hpp>
4 #include <Process/ProcessMetadata.hpp>
6 #include <Dataflow/CurveInlet.hpp>
8 #include <score/plugins/UuidKey.hpp>
10 #include <ossia/dataflow/audio_port.hpp>
11 #include <ossia/dataflow/port.hpp>
12 #include <ossia/dataflow/safe_nodes/tick_policies.hpp>
13 #include <ossia/detail/span.hpp>
15 #include <boost/container/vector.hpp>
17 #include <avnd/binding/ossia/qt.hpp>
18 #include <avnd/binding/ossia/uuid.hpp>
19 #include <avnd/common/concepts_polyfill.hpp>
20 #include <avnd/common/struct_reflection.hpp>
21 #include <avnd/concepts/audio_port.hpp>
22 #include <avnd/concepts/channels.hpp>
23 #include <avnd/concepts/curve.hpp>
24 #include <avnd/concepts/gfx.hpp>
25 #include <avnd/concepts/midi_port.hpp>
26 #include <avnd/concepts/parameter.hpp>
27 #include <avnd/introspection/input.hpp>
28 #include <avnd/wrappers/metadatas.hpp>
29 #include <avnd/wrappers/widgets.hpp>
33 #include <type_traits>
35 #define make_uuid(text) score::uuids::string_generator::compute((text))
39 template <
typename Node,
typename FieldIndex>
40 struct CustomFloatControl;
43 template <
typename Node,
typename FieldIndex>
44 struct is_custom_serialized<
oscr::CustomFloatControl<Node, FieldIndex>> : std::true_type
53 using Process::ControlInlet::ControlInlet;
63 setDomain(ossia::make_domain(min, max));
67 auto getMin()
const noexcept {
return domain().get().template convert_min<float>(); }
68 auto getMax()
const noexcept {
return domain().get().template convert_max<float>(); }
70 void setupExecution(ossia::inlet& inl)
const noexcept
override
72 auto& port = **safe_cast<ossia::value_inlet*>(&inl);
73 port.type = ossia::val_type::FLOAT;
74 port.domain = domain().get();
78 template <
typename Node,
typename FieldIndex>
81 using CustomFloatControlBase::CustomFloatControlBase;
83 static key_type static_concreteKey() noexcept
85 return make_field_uuid<Node>(
true, FieldIndex{});
87 key_type concreteKey()
const noexcept
override {
return static_concreteKey(); }
89 void serialize_impl(
const VisitorVariant& vis)
const noexcept
override
91 score::serialize_dyn(vis, *
this);
98 template <
typename Node,
typename FieldIndex>
110 template <
typename Node,
typename FieldIndex>
125 template <
typename Node,
typename T, std::
size_t N>
129 using value_type = as_type(T::value);
130 constexpr
auto name = avnd::get_name<T>();
131 QString qname = QString::fromUtf8(name.data(), name.size());
133 constexpr
auto widg = avnd::get_widget<T>();
137 if constexpr(avnd::curve_port<T>)
141 else if constexpr(widg.widget == avnd::widget_type::bang)
143 return new Process::ImpulseButton{qname, id, parent};
145 else if constexpr(widg.widget == avnd::widget_type::button)
147 return new Process::Button{qname, id, parent};
149 else if constexpr(widg.widget == avnd::widget_type::toggle)
151 static constexpr
auto c = avnd::get_range<T>();
152 if constexpr(requires { c.values(); })
154 return new Process::ChooserToggle{
155 {c.values[0], c.values[1]}, c.init, qname, id, parent};
159 return new Process::Toggle{bool(c.init), qname, id, parent};
162 else if constexpr(widg.widget == avnd::widget_type::slider)
164 static constexpr
auto c = avnd::get_range<T>();
165 if constexpr(std::is_integral_v<value_type>)
167 return new Process::IntSlider{c.min, c.max, c.init, qname, id, parent};
171 if constexpr(avnd::has_mapper<T>)
173 return new CustomFloatControl<Node, avnd::field_index<N>>{c.min, c.max, c.init,
178 return new Process::FloatSlider{c.min, c.max, c.init, qname, id, parent};
182 else if constexpr(widg.widget == avnd::widget_type::log_slider)
184 static constexpr
auto c = avnd::get_range<T>();
185 return new Process::LogFloatSlider{c.min, c.max, c.init, qname, id, parent};
187 else if constexpr(widg.widget == avnd::widget_type::log_knob)
190 static constexpr
auto c = avnd::get_range<T>();
191 return new Process::LogFloatSlider{c.min, c.max, c.init, qname, id, parent};
193 else if constexpr(widg.widget == avnd::widget_type::time_chooser)
195 static constexpr
auto c = avnd::get_range<T>();
196 return new Process::TimeChooser{c.min, c.max, c.init, qname, id, parent};
198 else if constexpr(widg.widget == avnd::widget_type::range_slider)
200 static constexpr
auto c = avnd::get_range<T>();
201 if constexpr(std::is_integral_v<value_type>)
203 auto [start, end] = c.init;
204 return new Process::IntRangeSlider{c.min, c.max, {(float)start, (
float)end},
209 auto [start, end] = c.init;
210 return new Process::FloatRangeSlider{c.min, c.max, {(float)start, (
float)end},
214 else if constexpr(widg.widget == avnd::widget_type::range_spinbox)
216 static constexpr
auto c = avnd::get_range<T>();
217 if constexpr(std::is_integral_v<value_type>)
219 auto [start, end] = c.init;
220 return new Process::IntRangeSpinBox{c.min, c.max, {(float)start, (
float)end},
225 auto [start, end] = c.init;
226 return new Process::FloatRangeSpinBox{c.min, c.max, {(float)start, (
float)end},
230 else if constexpr(widg.widget == avnd::widget_type::multi_slider)
232 constexpr
auto c = avnd::get_range<T>();
233 auto [start, end] = c.init;
234 std::vector<ossia::value> init;
235 return new Process::MultiSlider{init, qname, id, parent};
237 else if constexpr(widg.widget == avnd::widget_type::spinbox)
239 static constexpr
auto c = avnd::get_range<T>();
240 if constexpr(std::is_integral_v<value_type>)
242 return new Process::IntSpinBox{c.min, c.max, c.init, qname, id, parent};
246 return new Process::FloatSpinBox{c.min, c.max, c.init, qname, id, parent};
249 else if constexpr(widg.widget == avnd::widget_type::knob)
251 static constexpr
auto c = avnd::get_range<T>();
252 if constexpr(std::is_integral_v<value_type>)
255 return new Process::IntSlider{c.min, c.max, c.init, qname, id, parent};
259 if constexpr(avnd::has_mapper<T>)
261 return new CustomFloatControl<Node, avnd::field_index<N>>{c.min, c.max, c.init,
266 return new Process::FloatKnob{c.min, c.max, c.init, qname, id, parent};
270 else if constexpr(widg.widget == avnd::widget_type::lineedit)
272 if constexpr(avnd::has_range<T>)
274 static constexpr
auto c = avnd::get_range<T>();
275 if constexpr(avnd::program_parameter<T>)
277 auto p =
new Process::ProgramEdit{c.init.data(), qname, id, parent};
278 p->language = T::language();
282 return new Process::LineEdit{c.init.data(), qname, id, parent};
286 if constexpr(avnd::program_parameter<T>)
288 auto p =
new Process::ProgramEdit{
"", qname, id, parent};
289 p->language = T::language();
293 return new Process::LineEdit{
"", qname, id, parent};
296 else if constexpr(widg.widget == avnd::widget_type::combobox)
298 static constexpr
auto c = avnd::get_range<T>();
299 return new Process::ComboBox{to_combobox_range(c.values), c.init, qname, id, parent};
301 else if constexpr(widg.widget == avnd::widget_type::choices)
303 static constexpr
auto c = avnd::get_range<T>();
304 auto enums = avnd::to_enum_range(c.values);
306 std::is_integral_v<decltype(c.init)> || std::is_enum_v<decltype(c.init)>);
307 auto init = enums[
static_cast<int>(c.init)];
308 std::vector<QString> pixmaps;
309 if constexpr(avnd::has_pixmaps<T>)
311 for(std::string_view pix : avnd::get_pixmaps<T>())
313 pixmaps.push_back(QString::fromLatin1(pix.data(), pix.size()));
316 return new Process::Enum{
317 std::move(enums), pixmaps, std::move(init), qname, id, parent};
319 else if constexpr(widg.widget == avnd::widget_type::xy)
321 static constexpr
auto c = avnd::get_range<T>();
322 if constexpr(requires {
328 return new Process::XYSlider{
329 {c.min, c.min}, {c.max, c.max}, {c.init, c.init}, qname, id, parent};
333 auto [mx, my] = c.min;
334 auto [Mx, My] = c.max;
335 auto [ix, iy] = c.init;
336 return new Process::XYSlider{{mx, my}, {Mx, My}, {ix, iy}, qname, id, parent};
339 else if constexpr(widg.widget == avnd::widget_type::xyz)
341 static constexpr
auto c = avnd::get_range<T>();
342 if constexpr(requires {
348 return new Process::XYZSlider{
349 {c.min, c.min, c.min},
350 {c.max, c.max, c.max},
351 {c.init, c.init, c.init},
358 auto [mx, my, mz] = c.min;
359 auto [Mx, My, Mz] = c.max;
360 auto [ix, iy, iz] = c.init;
361 return new Process::XYZSlider{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
365 else if constexpr(widg.widget == avnd::widget_type::xy_spinbox)
367 using data_type = std::decay_t<decltype(value_type{}.x)>;
368 static constexpr
auto c = avnd::get_range<T>();
369 if constexpr(requires {
375 return new Process::XYSpinboxes{
379 std::is_integral_v<data_type>,
386 auto [mx, my] = c.min;
387 auto [Mx, My] = c.max;
388 auto [ix, iy] = c.init;
389 return new Process::XYSpinboxes{
390 {mx, my}, {Mx, My}, {ix, iy}, std::is_integral_v<data_type>,
394 else if constexpr(widg.widget == avnd::widget_type::xyz_spinbox)
396 static constexpr
auto c = avnd::get_range<T>();
397 if constexpr(requires {
403 return new Process::XYZSpinboxes{
404 {c.min, c.min, c.min},
405 {c.max, c.max, c.max},
406 {c.init, c.init, c.init},
413 auto [mx, my, mz] = c.min;
414 auto [Mx, My, Mz] = c.max;
415 auto [ix, iy, iz] = c.init;
416 return new Process::XYZSpinboxes{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
420 else if constexpr(widg.widget == avnd::widget_type::color)
422 static constexpr
auto c = avnd::get_range<T>();
423 static constexpr
auto i = c.init;
424 return new Process::HSVSlider{{i.r, i.g, i.b, i.a}, qname, id, parent};
426 else if constexpr(widg.widget == avnd::widget_type::control)
430 else if constexpr(widg.widget == avnd::widget_type::no_control)
438 static_assert(T::is_not_a_valid_control);
442 template <
typename T, std::
size_t N>
446 constexpr
auto name = avnd::get_name<T>();
447 constexpr
auto widg = avnd::get_widget<T>();
448 QString qname = QString::fromUtf8(name.data(), name.size());
452 if constexpr(widg.widget == avnd::widget_type::bargraph)
454 static constexpr
auto c = avnd::get_range<T>();
455 return new Process::Bargraph{c.min, c.max, c.init, qname, id, parent};
457 else if constexpr(widg.widget == avnd::widget_type::control)
461 else if constexpr(widg.widget == avnd::widget_type::no_control)
467 else if constexpr(avnd::fp_ish<decltype(T::value)>)
469 static constexpr
auto c = avnd::get_range<T>();
470 return new Process::Bargraph{c.min, c.max, c.init, qname, id, parent};
478 template <
typename T>
479 static inline constexpr
auto make_control_out(
const T& t)
481 return make_control_out<T>();
489 ossia::audio_vector* buffer{};
493 tcb::span<const double> operator[](std::size_t i)
const noexcept
495 auto& chan = (*buffer)[i];
496 int64_t min_dur = std::min(int64_t(chan.size()) - offset, duration);
500 return tcb::span<const double>{chan.data() + offset, std::size_t(min_dur)};
503 std::size_t channels()
const noexcept {
return buffer->size(); }
504 void resize(std::size_t i)
const noexcept {
return buffer->resize(i); }
505 void reserve(std::size_t channels, std::size_t bufferSize)
508 for(
auto& vec : *buffer)
509 vec.reserve(bufferSize);
515 ossia::audio_vector* buffer{};
519 tcb::span<double> operator[](std::size_t i)
const noexcept
521 auto& chan = (*buffer)[i];
522 int64_t min_dur = std::min(int64_t(chan.size()) - offset, duration);
526 return tcb::span<double>{chan.data() + offset, std::size_t(min_dur)};
529 std::size_t channels()
const noexcept {
return buffer->size(); }
530 void resize(std::size_t channels, std::size_t samples_to_write)
const noexcept
532 buffer->resize(channels);
533 for(
auto& c : *buffer)
534 c.resize(offset + samples_to_write);
537 void reserve(std::size_t channels, std::size_t bufferSize)
539 buffer->resize(channels);
540 for(
auto& c : *buffer)
541 c.reserve(bufferSize);
Definition: QmlObjects.hpp:114
Definition: VisitorInterface.hpp:53
Definition: DataStreamVisitor.hpp:27
Definition: DataStreamVisitor.hpp:202
Definition: VisitorInterface.hpp:61
Definition: JSONVisitor.hpp:52
Definition: JSONVisitor.hpp:423
Definition: UuidKey.hpp:343
The id_base_t class.
Definition: Identifier.hpp:57
Definition: Factories.hpp:19
Definition: CurveInlet.hpp:47
Definition: VisitorInterface.hpp:13
The VisitorVariant struct.
Definition: VisitorInterface.hpp:26
Definition: Concepts.hpp:52
Definition: Concepts.hpp:80
Definition: Concepts.hpp:488
Definition: Concepts.hpp:514