2#include "Engine/Node/CommonWidgets.hpp"
3#include <Process/Dataflow/WidgetInlets.hpp>
4#include <Process/ProcessFlags.hpp>
5#include <Process/ProcessMetadata.hpp>
7#include <Dataflow/CurveInlet.hpp>
9#include <score/plugins/UuidKey.hpp>
11#include <ossia/dataflow/audio_port.hpp>
12#include <ossia/dataflow/port.hpp>
13#include <ossia/dataflow/safe_nodes/tick_policies.hpp>
14#include <ossia/detail/span.hpp>
16#include <boost/container/vector.hpp>
18#include <avnd/binding/ossia/qt.hpp>
19#include <avnd/binding/ossia/uuid.hpp>
20#include <avnd/common/concepts_polyfill.hpp>
21#include <avnd/common/struct_reflection.hpp>
22#include <avnd/concepts/audio_port.hpp>
23#include <avnd/concepts/channels.hpp>
24#include <avnd/concepts/curve.hpp>
25#include <avnd/concepts/gfx.hpp>
26#include <avnd/concepts/midi_port.hpp>
27#include <avnd/concepts/parameter.hpp>
28#include <avnd/introspection/input.hpp>
29#include <avnd/wrappers/metadatas.hpp>
30#include <avnd/wrappers/widgets.hpp>
36#define make_uuid(text) score::uuids::string_generator::compute((text))
40template <
typename Node,
typename FieldIndex>
41struct CustomFloatControl;
44template <
typename Node,
typename FieldIndex>
45struct is_custom_serialized<
oscr::CustomFloatControl<Node, FieldIndex>> : std::true_type
54 using Process::ControlInlet::ControlInlet;
59 : ControlInlet{id, parent}
64 setDomain(ossia::make_domain(min, max));
68 auto getMin()
const noexcept {
return domain().get().template convert_min<float>(); }
69 auto getMax()
const noexcept {
return domain().get().template convert_max<float>(); }
71 void setupExecution(ossia::inlet& inl, QObject* exec_context)
const noexcept override
73 auto& port = **safe_cast<ossia::value_inlet*>(&inl);
74 port.type = ossia::val_type::FLOAT;
75 port.domain = domain().get();
79template <
typename Node,
typename FieldIndex>
82 using CustomFloatControlBase::CustomFloatControlBase;
84 static key_type static_concreteKey()
noexcept
86 return make_field_uuid<Node>(
true, FieldIndex{});
88 key_type concreteKey()
const noexcept override {
return static_concreteKey(); }
90 void serialize_impl(
const VisitorVariant& vis)
const noexcept override
92 score::serialize_dyn(vis, *
this);
99template <
typename Node,
typename FieldIndex>
111template <
typename Node,
typename FieldIndex>
126template <
typename Node,
typename T, std::
size_t N>
130 using value_type = as_type(T::value);
131 constexpr auto name = avnd::get_name<T>();
132 QString qname = QString::fromUtf8(name.data(), name.size());
134 constexpr auto widg = avnd::get_widget<T>();
138 if constexpr(avnd::curve_port<T>)
142 else if constexpr(widg.widget == avnd::widget_type::bang)
144 return new Process::ImpulseButton{qname, id, parent};
146 else if constexpr(widg.widget == avnd::widget_type::button)
148 return new Process::Button{qname, id, parent};
150 else if constexpr(widg.widget == avnd::widget_type::toggle)
152 static constexpr auto c = avnd::get_range<T>();
153 if constexpr(
requires { c.values(); })
155 return new Process::ChooserToggle{
156 {c.values[0], c.values[1]}, c.init, qname, id, parent};
160 return new Process::Toggle{bool(c.init), qname, id, parent};
163 else if constexpr(widg.widget == avnd::widget_type::slider)
165 static constexpr auto c = avnd::get_range<T>();
166 if constexpr(std::is_integral_v<value_type>)
168 return new Process::IntSlider{c.min, c.max, c.init, qname, id, parent};
172 if constexpr(avnd::has_mapper<T>)
174 return new CustomFloatControl<Node, avnd::field_index<N>>{c.min, c.max, c.init,
179 return new Process::FloatSlider{c.min, c.max, c.init, qname, id, parent};
183 else if constexpr(widg.widget == avnd::widget_type::log_slider)
185 static constexpr auto c = avnd::get_range<T>();
186 return new Process::LogFloatSlider{c.min, c.max, c.init, qname, id, parent};
188 else if constexpr(widg.widget == avnd::widget_type::log_knob)
191 static constexpr auto c = avnd::get_range<T>();
192 return new Process::LogFloatSlider{c.min, c.max, c.init, qname, id, parent};
194 else if constexpr(widg.widget == avnd::widget_type::time_chooser)
196 static constexpr auto c = avnd::get_range<T>();
197 return new Process::TimeChooser{c.min, c.max, c.init, qname, id, parent};
199 else if constexpr(widg.widget == avnd::widget_type::range_slider)
201 static constexpr auto c = avnd::get_range<T>();
202 if constexpr(std::is_integral_v<value_type>)
204 auto [start, end] = c.init;
205 return new Process::IntRangeSlider{c.min, c.max, {(float)start, (
float)end},
210 auto [start, end] = c.init;
211 return new Process::FloatRangeSlider{c.min, c.max, {(float)start, (
float)end},
215 else if constexpr(widg.widget == avnd::widget_type::range_spinbox)
217 static constexpr auto c = avnd::get_range<T>();
218 if constexpr(std::is_integral_v<value_type>)
220 auto [start, end] = c.init;
221 return new Process::IntRangeSpinBox{c.min, c.max, {(float)start, (
float)end},
226 auto [start, end] = c.init;
227 return new Process::FloatRangeSpinBox{c.min, c.max, {(float)start, (
float)end},
231 else if constexpr(widg.widget == avnd::widget_type::multi_slider)
233 std::vector<ossia::value> init;
234 return new Process::MultiSlider{init, qname, id, parent};
236 else if constexpr(widg.widget == avnd::widget_type::multi_slider_xy)
238 std::vector<ossia::value> init;
239 return new Process::MultiSliderXY{init, qname, id, parent};
241 else if constexpr(widg.widget == avnd::widget_type::path_generator_xy)
243 std::vector<ossia::value> init;
244 return new Process::PathGeneratorXY{init, qname, id, parent};
246 else if constexpr(widg.widget == avnd::widget_type::spinbox)
248 static constexpr auto c = avnd::get_range<T>();
249 if constexpr(std::is_integral_v<value_type>)
251 return new Process::IntSpinBox{c.min, c.max, c.init, qname, id, parent};
255 return new Process::FloatSpinBox{c.min, c.max, c.init, qname, id, parent};
258 else if constexpr(widg.widget == avnd::widget_type::knob)
260 static constexpr auto c = avnd::get_range<T>();
261 if constexpr(std::is_integral_v<value_type>)
264 return new Process::IntSlider{c.min, c.max, c.init, qname, id, parent};
268 if constexpr(avnd::has_mapper<T>)
270 return new CustomFloatControl<Node, avnd::field_index<N>>{c.min, c.max, c.init,
275 return new Process::FloatKnob{c.min, c.max, c.init, qname, id, parent};
279 else if constexpr(widg.widget == avnd::widget_type::lineedit)
281 if constexpr(avnd::has_range<T>)
283 static constexpr auto c = avnd::get_range<T>();
284 if constexpr(avnd::program_parameter<T>)
286 auto p =
new Process::ProgramEdit{c.init.data(), qname, id, parent};
287 p->language = T::language();
291 return new Process::LineEdit{c.init.data(), qname, id, parent};
295 if constexpr(avnd::program_parameter<T>)
297 auto p =
new Process::ProgramEdit{
"", qname, id, parent};
298 p->language = T::language();
302 return new Process::LineEdit{
"", qname, id, parent};
305 else if constexpr(widg.widget == avnd::widget_type::combobox)
307 static constexpr auto c = avnd::get_range<T>();
308 return new Process::ComboBox{to_combobox_range(c.values), c.init, qname, id, parent};
310 else if constexpr(widg.widget == avnd::widget_type::choices)
312 static constexpr auto c = avnd::get_range<T>();
313 auto enums = avnd::to_enum_range(c.values);
315 std::is_integral_v<
decltype(c.init)> || std::is_enum_v<
decltype(c.init)>);
316 auto init = enums[
static_cast<int>(c.init)];
317 std::vector<QString> pixmaps;
318 if constexpr(avnd::has_pixmaps<T>)
320 for(std::string_view pix : avnd::get_pixmaps<T>())
322 pixmaps.push_back(QString::fromLatin1(pix.data(), pix.size()));
325 return new Process::Enum{
326 std::move(enums), pixmaps, std::move(init), qname, id, parent};
328 else if constexpr(widg.widget == avnd::widget_type::xy)
330 static constexpr auto c = avnd::get_range<T>();
331 if constexpr(
requires {
337 return new Process::XYSlider{
338 {c.min, c.min}, {c.max, c.max}, {c.init, c.init}, qname, id, parent};
342 auto [mx, my] = c.min;
343 auto [Mx, My] = c.max;
344 auto [ix, iy] = c.init;
345 return new Process::XYSlider{{mx, my}, {Mx, My}, {ix, iy}, qname, id, parent};
348 else if constexpr(widg.widget == avnd::widget_type::xyz)
350 static constexpr auto c = avnd::get_range<T>();
351 if constexpr(
requires {
357 return new Process::XYZSlider{
358 {c.min, c.min, c.min},
359 {c.max, c.max, c.max},
360 {c.init, c.init, c.init},
367 auto [mx, my, mz] = c.min;
368 auto [Mx, My, Mz] = c.max;
369 auto [ix, iy, iz] = c.init;
370 return new Process::XYZSlider{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
374 else if constexpr(widg.widget == avnd::widget_type::xy_spinbox)
376 using data_type = std::decay_t<
decltype(value_type{}.x)>;
377 static constexpr auto c = avnd::get_range<T>();
378 if constexpr(
requires {
384 return new Process::XYSpinboxes{
388 std::is_integral_v<data_type>,
395 auto [mx, my] = c.min;
396 auto [Mx, My] = c.max;
397 auto [ix, iy] = c.init;
398 return new Process::XYSpinboxes{
399 {mx, my}, {Mx, My}, {ix, iy}, std::is_integral_v<data_type>,
403 else if constexpr(widg.widget == avnd::widget_type::xyz_spinbox)
405 static constexpr auto c = avnd::get_range<T>();
406 if constexpr(
requires {
412 return new Process::XYZSpinboxes{
413 {c.min, c.min, c.min},
414 {c.max, c.max, c.max},
415 {c.init, c.init, c.init},
422 auto [mx, my, mz] = c.min;
423 auto [Mx, My, Mz] = c.max;
424 auto [ix, iy, iz] = c.init;
425 return new Process::XYZSpinboxes{{mx, my, mz}, {Mx, My, Mz}, {ix, iy, iz},
429 else if constexpr(widg.widget == avnd::widget_type::color)
431 static constexpr auto c = avnd::get_range<T>();
432 static constexpr auto i = c.init;
433 return new Process::HSVSlider{{i.r, i.g, i.b, i.a}, qname, id, parent};
435 else if constexpr(widg.widget == avnd::widget_type::control)
439 else if constexpr(widg.widget == avnd::widget_type::no_control)
447 static_assert(T::is_not_a_valid_control);
451template <
typename T, std::
size_t N>
455 constexpr auto name = avnd::get_name<T>();
456 constexpr auto widg = avnd::get_widget<T>();
457 QString qname = QString::fromUtf8(name.data(), name.size());
461 if constexpr(widg.widget == avnd::widget_type::bargraph)
463 static constexpr auto c = avnd::get_range<T>();
464 return new Process::Bargraph{c.min, c.max, c.init, qname, id, parent};
466 else if constexpr(widg.widget == avnd::widget_type::control)
470 else if constexpr(widg.widget == avnd::widget_type::no_control)
476 else if constexpr(avnd::fp_ish<
decltype(T::value)>)
478 static constexpr auto c = avnd::get_range<T>();
479 return new Process::Bargraph{c.min, c.max, c.init, qname, id, parent};
488static inline constexpr auto make_control_out(
const T& t)
490 return make_control_out<T>();
498 ossia::audio_vector* buffer{};
502 tcb::span<const double> operator[](std::size_t i)
const noexcept
504 auto& chan = (*buffer)[i];
505 int64_t min_dur = std::min(int64_t(chan.size()) - offset, duration);
509 return tcb::span<const double>{chan.data() + offset, std::size_t(min_dur)};
512 std::size_t channels()
const noexcept {
return buffer->size(); }
513 void resize(std::size_t i)
const noexcept {
return buffer->resize(i); }
514 void reserve(std::size_t channels, std::size_t bufferSize)
517 for(
auto& vec : *buffer)
518 vec.reserve(bufferSize);
524 ossia::audio_vector* buffer{};
528 tcb::span<double> operator[](std::size_t i)
const noexcept
530 auto& chan = (*buffer)[i];
531 int64_t min_dur = std::min(int64_t(chan.size()) - offset, duration);
535 return tcb::span<double>{chan.data() + offset, std::size_t(min_dur)};
538 std::size_t channels()
const noexcept {
return buffer->size(); }
539 void resize(std::size_t channels, std::size_t samples_to_write)
const noexcept
541 buffer->resize(channels);
542 for(
auto& c : *buffer)
543 c.resize(offset + samples_to_write);
546 void reserve(std::size_t channels, std::size_t bufferSize)
548 buffer->resize(channels);
549 for(
auto& c : *buffer)
550 c.reserve(bufferSize);
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:344
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:53
Definition Concepts.hpp:81
Definition Concepts.hpp:497
Definition Concepts.hpp:523