Loading...
Searching...
No Matches
QmlObjects.hpp
1#pragma once
2#include <State/Domain.hpp>
3
4#include <Process/Dataflow/Port.hpp>
5#include <Process/Dataflow/WidgetInlets.hpp>
6
7#include <JS/Qml/QtMetatypes.hpp>
8
9#include <libremidi/detail/conversion.hpp>
10
11#if defined(SCORE_HAS_GPU_JS)
12#include <Gfx/TexturePort.hpp>
13
14#include <QQuickItem>
15#endif
16
17#include <score/tools/Debug.hpp>
18
19#include <ossia/detail/math.hpp>
20#include <ossia/detail/ssize.hpp>
21#include <ossia/network/domain/domain.hpp>
22
23#include <ossia-qt/js_utilities.hpp>
24
25#include <QJSValue>
26#include <QObject>
27#include <QQmlListProperty>
28#include <QVariant>
29#include <QVector>
30
31#include <libremidi/message.hpp>
32#include <libremidi/ump.hpp>
33
34#include <score_plugin_js_export.h>
35#include <wobjectimpl.h>
36
37#include <verdigris>
38
39class QQuickItem;
40namespace JS
41{
42class SCORE_PLUGIN_JS_EXPORT Inlet : public QObject
43{
44 W_OBJECT(Inlet)
45
46public:
47 using QObject::QObject;
48 virtual ~Inlet() override;
49 virtual Process::Inlet* make(Id<Process::Port>&& id, QObject*) = 0;
50 virtual bool isEvent() const { return false; }
51
52 W_INLINE_PROPERTY_CREF(QString, address, {}, address, setAddress, addressChanged)
53};
54
55class SCORE_PLUGIN_JS_EXPORT Outlet : public QObject
56{
57 W_OBJECT(Outlet)
58
59public:
60 using QObject::QObject;
61 virtual ~Outlet() override;
62 virtual Process::Outlet* make(Id<Process::Port>&& id, QObject*) = 0;
63
64 W_INLINE_PROPERTY_CREF(QString, address, {}, address, setAddress, addressChanged)
65};
66
67struct SCORE_PLUGIN_JS_EXPORT InValueMessage
68{
69 W_GADGET(InValueMessage)
70
71public:
72 qreal timestamp;
73 QVariant value;
74 W_PROPERTY(qreal, timestamp MEMBER timestamp)
75 W_PROPERTY(QVariant, value MEMBER value)
76};
77
78struct SCORE_PLUGIN_JS_EXPORT OutValueMessage
79{
80 W_GADGET(OutValueMessage)
81
82public:
83 qreal timestamp;
84 QJSValue value;
85 W_PROPERTY(qreal, timestamp MEMBER timestamp)
86 W_PROPERTY(QJSValue, value MEMBER value)
87};
88
89class SCORE_PLUGIN_JS_EXPORT ValueInlet : public Inlet
90{
91 W_OBJECT(ValueInlet)
92
93 QVariant m_value;
94 QVariantList m_values;
95
96public:
97 explicit ValueInlet(QObject* parent = nullptr);
98 virtual ~ValueInlet() override;
99 QVariant value() const;
100 QVariantList values() const { return m_values; }
101
102 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
103 {
104 return new Process::ValueInlet(id, parent);
105 }
106
107 int length() const noexcept;
108 W_SLOT(length)
109
110 QVariant at(int index) const noexcept;
111 W_SLOT(at)
112
113 void clear() { m_values.clear(); }
114 void setValue(QVariant value);
115 void addValue(QVariant&& val) { m_values.append(std::move(val)); }
116 void valueChanged(QVariant value) W_SIGNAL(valueChanged, value);
117
118 W_PROPERTY(QVariantList, values READ values)
119 W_PROPERTY(QVariant, value READ value NOTIFY valueChanged)
120};
121
122class SCORE_PLUGIN_JS_EXPORT ControlInlet : public Inlet
123{
124 W_OBJECT(ControlInlet)
125
126 QVariant m_value;
127
128public:
129 explicit ControlInlet(QObject* parent = nullptr);
130 virtual ~ControlInlet() override;
131 QVariant value() const noexcept;
132
133 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
134 {
135 return new Process::ControlInlet(id, parent);
136 }
137
138 void clear() { m_value = QVariant{}; }
139 virtual void setValue(QVariant value);
140 void valueChanged(QVariant value) W_SIGNAL(valueChanged, value);
141
142 W_PROPERTY(QVariant, value READ value NOTIFY valueChanged)
143};
144
145template <typename Impl, typename ValueType, typename OssiaType>
146class SCORE_PLUGIN_JS_EXPORT GenericControlInlet : public ControlInlet
147{
148 W_OBJECT(GenericControlInlet)
149
150public:
151 using ControlInlet::ControlInlet;
152 virtual ~GenericControlInlet() override = default;
153 bool isEvent() const override { return true; }
154 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
155 {
156 return new Impl(id, parent);
157 }
158
159 void clear() { m_value = {}; }
160 ValueType value() const noexcept { return m_value; }
161 void setValue(QVariant value) override
162 {
163 auto conv = value.value<ValueType>();
164 if(m_value == conv)
165 return;
166
167 m_value = std::move(conv);
168 valueChanged(m_value);
169 }
170 void setValue(ValueType value)
171 {
172 if(m_value == value)
173 return;
174
175 m_value = value;
176 valueChanged(m_value);
177 }
178 void valueChanged(ValueType value) W_SIGNAL(valueChanged, value);
179
180 W_PROPERTY(ValueType, value READ value NOTIFY valueChanged)
181
182private:
183 ValueType m_value{};
184};
185W_OBJECT_IMPL(
186 (GenericControlInlet<A, B, C>), template <typename A, typename B, typename C>)
187struct SCORE_PLUGIN_JS_EXPORT MultiSlider
189 Process::MultiSlider, QVector<qreal>, std::vector<ossia::value>>
190{
191 W_OBJECT(MultiSlider);
192 using GenericControlInlet::GenericControlInlet;
193};
194struct SCORE_PLUGIN_JS_EXPORT FileChooser
195 : JS::GenericControlInlet<Process::FileChooser, QString, std::string>
196{
197 W_OBJECT(FileChooser);
198 using GenericControlInlet::GenericControlInlet;
199};
200struct SCORE_PLUGIN_JS_EXPORT AudioFileChooser
201 : JS::GenericControlInlet<Process::AudioFileChooser, QString, std::string>
202{
203 W_OBJECT(AudioFileChooser);
204 using GenericControlInlet::GenericControlInlet;
205};
206struct SCORE_PLUGIN_JS_EXPORT VideoFileChooser
207 : JS::GenericControlInlet<Process::VideoFileChooser, QString, std::string>
208{
209 W_OBJECT(VideoFileChooser);
210 using GenericControlInlet::GenericControlInlet;
211};
212
213template <typename Impl = Process::FloatSlider>
214class SCORE_PLUGIN_JS_EXPORT FloatSlider : public GenericControlInlet<Impl, float, float>
215{
216 W_OBJECT(FloatSlider)
217
218public:
219 using GenericControlInlet<Impl, float, float>::GenericControlInlet;
220 virtual ~FloatSlider() override = default;
221 bool isEvent() const override { return true; }
222
223 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
224 {
225 return new Impl{(float)m_min, (float)m_max, (float)m_init,
226 this->objectName(), id, parent};
227 }
228
229 W_INLINE_PROPERTY_VALUE(qreal, init, {0.5}, init, setInit, initChanged)
230 W_INLINE_PROPERTY_VALUE(qreal, min, {0.}, getMin, setMin, minChanged)
231 W_INLINE_PROPERTY_VALUE(qreal, max, {1.}, getMax, setMax, maxChanged)
232};
233W_OBJECT_IMPL(JS::FloatSlider<Impl>, template <typename Impl>)
234
235template <typename Impl = Process::IntSlider>
236class SCORE_PLUGIN_JS_EXPORT IntSlider : public GenericControlInlet<Impl, int, int>
237{
238 W_OBJECT(IntSlider)
239
240public:
241 using GenericControlInlet<Impl, int, int>::GenericControlInlet;
242 virtual ~IntSlider() override = default;
243 bool isEvent() const override { return true; }
244
245 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
246 {
247 return new Impl{m_min, m_max, m_init, this->objectName(), id, parent};
248 }
249
250 W_INLINE_PROPERTY_VALUE(int, init, {0}, init, setInit, initChanged)
251 W_INLINE_PROPERTY_VALUE(int, min, {0}, getMin, setMin, minChanged)
252 W_INLINE_PROPERTY_VALUE(int, max, {127}, getMax, setMax, maxChanged)
253};
254W_OBJECT_IMPL(JS::IntSlider<Impl>, template <typename Impl>)
255
256static constexpr auto vec2(double v)
257{
258 return QVector2D{(float)v, (float)v};
259}
260static constexpr auto vec3(double v)
261{
262 return QVector3D{(float)v, (float)v, (float)v};
263}
264static constexpr auto vec4(double v)
265{
266 return QVector4D{(float)v, (float)v, (float)v, (float)v};
267}
268static constexpr auto vec_to_ossia(QVector2D v)
269{
270 return ossia::vec2f{(float)v[0], (float)v[1]};
271}
272static constexpr auto vec_to_ossia(QVector3D v)
273{
274 return ossia::vec3f{(float)v[0], (float)v[1], (float)v[2]};
275}
276static constexpr auto vec_to_ossia(QVector4D v)
277{
278 return ossia::vec4f{(float)v[0], (float)v[1], (float)v[2], (float)v[3]};
279}
280
281template <typename Impl>
282class SCORE_PLUGIN_JS_EXPORT FloatControl2D
283 : public GenericControlInlet<Impl, QVector2D, ossia::vec2f>
284{
285 W_OBJECT(FloatControl2D)
286
287public:
288 using GenericControlInlet<Impl, QVector2D, ossia::vec2f>::GenericControlInlet;
289 virtual ~FloatControl2D() override = default;
290 bool isEvent() const override { return true; }
291
292 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
293 {
294 if constexpr(std::is_constructible_v<
295 Impl, ossia::vec2f, ossia::vec2f, ossia::vec2f, bool, QString,
296 Id<Process::Port>, QObject*>)
297 return new Impl{
298 vec_to_ossia(m_min),
299 vec_to_ossia(m_max),
300 vec_to_ossia(m_init),
301 false,
302 this->objectName(),
303 id,
304 parent};
305 else if constexpr(std::is_constructible_v<
306 Impl, ossia::vec2f, ossia::vec2f, ossia::vec2f, QString,
307 Id<Process::Port>, QObject*>)
308 return new Impl{
309 vec_to_ossia(m_min),
310 vec_to_ossia(m_max),
311 vec_to_ossia(m_init),
312 this->objectName(),
313 id,
314 parent};
315 else
316 return new Impl{vec_to_ossia(m_init), this->objectName(), id, parent};
317 }
318
319 W_INLINE_PROPERTY_VALUE(QVector2D, init, {vec2(0.)}, init, setInit, initChanged);
320 W_INLINE_PROPERTY_VALUE(QVector2D, min, {vec2(0.)}, getMin, setMin, minChanged);
321 W_INLINE_PROPERTY_VALUE(QVector2D, max, {vec2(1.)}, getMax, setMax, maxChanged);
322};
323W_OBJECT_IMPL(JS::FloatControl2D<Impl>, template <typename Impl>)
324
325template <typename Impl>
326class SCORE_PLUGIN_JS_EXPORT IntControl2D
327 : public GenericControlInlet<Impl, QVector2D, ossia::vec2f>
328{
329 W_OBJECT(IntControl2D)
330
331public:
332 using GenericControlInlet<Impl, QVector2D, ossia::vec2f>::GenericControlInlet;
333 virtual ~IntControl2D() override = default;
334 bool isEvent() const override { return true; }
335
336 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
337 {
338 return new Impl{
339 vec_to_ossia(m_min),
340 vec_to_ossia(m_max),
341 vec_to_ossia(m_init),
342 true,
343 this->objectName(),
344 id,
345 parent};
346 }
347
348 W_INLINE_PROPERTY_VALUE(QVector2D, init, {vec2(0.)}, init, setInit, initChanged);
349 W_INLINE_PROPERTY_VALUE(QVector2D, min, {vec2(0.)}, getMin, setMin, minChanged);
350 W_INLINE_PROPERTY_VALUE(QVector2D, max, {vec2(1.)}, getMax, setMax, maxChanged);
351};
352W_OBJECT_IMPL(JS::IntControl2D<Impl>, template <typename Impl>)
353
354template <typename Impl>
355class SCORE_PLUGIN_JS_EXPORT FloatControl1D_2D
356 : public GenericControlInlet<Impl, QVector2D, ossia::vec2f>
357{
358 W_OBJECT(FloatControl1D_2D)
359
360public:
361 using GenericControlInlet<Impl, QVector2D, ossia::vec2f>::GenericControlInlet;
362 virtual ~FloatControl1D_2D() override = default;
363 bool isEvent() const override { return true; }
364
365 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
366 {
367 return new Impl(m_min, m_max, vec_to_ossia(m_init), this->objectName(), id, parent);
368 }
369
370 W_INLINE_PROPERTY_VALUE(QVector2D, init, {vec2(0.)}, init, setInit, initChanged);
371 W_INLINE_PROPERTY_VALUE(float, min, {0.}, getMin, setMin, minChanged);
372 W_INLINE_PROPERTY_VALUE(float, max, {1.}, getMax, setMax, maxChanged);
373};
374W_OBJECT_IMPL(JS::FloatControl1D_2D<Impl>, template <typename Impl>)
375
376template <typename Impl>
377class SCORE_PLUGIN_JS_EXPORT FloatControl3D
378 : public GenericControlInlet<Impl, QVector3D, ossia::vec3f>
379{
380 W_OBJECT(FloatControl3D)
381
382public:
383 using GenericControlInlet<Impl, QVector3D, ossia::vec3f>::GenericControlInlet;
384 virtual ~FloatControl3D() override = default;
385 bool isEvent() const override { return true; }
386
387 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
388 {
389 if constexpr(std::is_constructible_v<
390 Impl, ossia::vec3f, ossia::vec3f, ossia::vec3f, bool, QString,
391 Id<Process::Port>, QObject*>)
392 return new Impl{
393 vec_to_ossia(m_min),
394 vec_to_ossia(m_max),
395 vec_to_ossia(m_init),
396 false,
397 this->objectName(),
398 id,
399 parent};
400 else if constexpr(std::is_constructible_v<
401 Impl, ossia::vec3f, ossia::vec3f, ossia::vec3f, QString,
402 Id<Process::Port>, QObject*>)
403 return new Impl{
404 vec_to_ossia(m_min),
405 vec_to_ossia(m_max),
406 vec_to_ossia(m_init),
407 this->objectName(),
408 id,
409 parent};
410 else
411 return new Impl{vec_to_ossia(m_init), this->objectName(), id, parent};
412 }
413
414 W_INLINE_PROPERTY_VALUE(QVector3D, init, {vec3(0.)}, init, setInit, initChanged);
415 W_INLINE_PROPERTY_VALUE(QVector3D, min, {vec3(0.)}, getMin, setMin, minChanged);
416 W_INLINE_PROPERTY_VALUE(QVector3D, max, {vec3(1.)}, getMax, setMax, maxChanged);
417};
418W_OBJECT_IMPL(JS::FloatControl3D<Impl>, template <typename Impl>)
419
420template <typename Impl>
421class SCORE_PLUGIN_JS_EXPORT IntControl3D
422 : public GenericControlInlet<Impl, QVector3D, ossia::vec3f>
423{
424 W_OBJECT(IntControl3D)
425
426public:
427 using GenericControlInlet<Impl, QVector3D, ossia::vec3f>::GenericControlInlet;
428 virtual ~IntControl3D() override = default;
429 bool isEvent() const override { return true; }
430
431 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
432 {
433 return new Impl{
434 vec_to_ossia(m_min),
435 vec_to_ossia(m_max),
436 vec_to_ossia(m_init),
437 true,
438 this->objectName(),
439 id,
440 parent};
441 }
442
443 W_INLINE_PROPERTY_VALUE(QVector3D, init, {vec3(0.)}, init, setInit, initChanged);
444 W_INLINE_PROPERTY_VALUE(QVector3D, min, {vec3(0.)}, getMin, setMin, minChanged);
445 W_INLINE_PROPERTY_VALUE(QVector3D, max, {vec3(1.)}, getMax, setMax, maxChanged);
446};
447W_OBJECT_IMPL(JS::IntControl3D<Impl>, template <typename Impl>)
448
449template <typename Impl>
450class SCORE_PLUGIN_JS_EXPORT FloatControl4D
451 : public GenericControlInlet<Impl, QVector4D, ossia::vec4f>
452{
453 W_OBJECT(FloatControl4D)
454
455public:
456 using GenericControlInlet<Impl, QVector4D, ossia::vec4f>::GenericControlInlet;
457 virtual ~FloatControl4D() override = default;
458 bool isEvent() const override { return true; }
459
460 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
461 {
462 if constexpr(std::is_constructible_v<
463 Impl, ossia::vec4f, ossia::vec4f, ossia::vec4f, QString,
464 Id<Process::Port>, QObject*>)
465 return new Impl{
466 vec_to_ossia(m_min),
467 vec_to_ossia(m_max),
468 vec_to_ossia(m_init),
469 this->objectName(),
470 id,
471 parent};
472 else
473 return new Impl{vec_to_ossia(m_init), this->objectName(), id, parent};
474 }
475
476 W_INLINE_PROPERTY_VALUE(QVector4D, init, {vec4(0.)}, init, setInit, initChanged);
477 W_INLINE_PROPERTY_VALUE(QVector4D, min, {vec4(0.)}, getMin, setMin, minChanged);
478 W_INLINE_PROPERTY_VALUE(QVector4D, max, {vec4(1.)}, getMax, setMax, maxChanged);
479};
480W_OBJECT_IMPL(JS::FloatControl4D<Impl>, template <typename Impl>)
481
482class SCORE_PLUGIN_JS_EXPORT Enum : public ControlInlet
483{
484 W_OBJECT(Enum)
485
486public:
487 using ControlInlet::ControlInlet;
488 virtual ~Enum() override;
489 bool isEvent() const override { return true; }
490
491 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
492 {
493 return new Process::Enum{m_choices, {}, current(), objectName(), id, parent};
494 }
495
496 auto getValues() const { return choices(); }
497
498 std::string current() const
499 {
500 if(!m_choices.isEmpty() && ossia::valid_index(m_index, m_choices))
501 {
502 return m_choices[m_index].toStdString();
503 }
504 return {};
505 }
506
507 W_INLINE_PROPERTY_VALUE(int, index, {}, index, setIndex, indexChanged)
508 W_INLINE_PROPERTY_CREF(QStringList, choices, {}, choices, setChoices, choicesChanged)
509};
510
511class SCORE_PLUGIN_JS_EXPORT ComboBox : public ControlInlet
512{
513 W_OBJECT(ComboBox)
514
515public:
516 using ControlInlet::ControlInlet;
517 virtual ~ComboBox() override;
518 bool isEvent() const override { return true; }
519
520 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
521 {
522 std::vector<std::pair<QString, ossia::value>> choices;
523 choices.reserve(m_choices.size());
524 for(auto& c : m_choices)
525 choices.emplace_back(c, c.toStdString());
526 return new Process::ComboBox{choices, current(), objectName(), id, parent};
527 }
528
529 auto getValues() const { return choices(); }
530
531 std::string current() const
532 {
533 if(!m_choices.isEmpty() && ossia::valid_index(m_index, m_choices))
534 {
535 return m_choices[m_index].toStdString();
536 }
537 return {};
538 }
539
540 W_INLINE_PROPERTY_VALUE(int, index, {}, index, setIndex, indexChanged)
541 W_INLINE_PROPERTY_CREF(QStringList, choices, {}, choices, setChoices, choicesChanged)
542};
543
544class SCORE_PLUGIN_JS_EXPORT Toggle : public ControlInlet
545{
546 W_OBJECT(Toggle)
547
548public:
549 using ControlInlet::ControlInlet;
550 virtual ~Toggle() override;
551 bool isEvent() const override { return true; }
552 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
553 {
554 return new Process::Toggle{m_checked, objectName(), id, parent};
555 }
556
557 W_INLINE_PROPERTY_VALUE(bool, checked, {}, checked, setChecked, checkedChanged)
558};
559
560class SCORE_PLUGIN_JS_EXPORT Button : public ControlInlet
561{
562 W_OBJECT(Button)
563
564public:
565 using ControlInlet::ControlInlet;
566 virtual ~Button() override;
567 bool isEvent() const override { return true; }
568 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
569 {
570 return new Process::Button{objectName(), id, parent};
571 }
572
573 W_INLINE_PROPERTY_VALUE(bool, checked, {}, checked, setChecked, checkedChanged)
574};
575
576class SCORE_PLUGIN_JS_EXPORT Impulse : public ControlInlet
577{
578 W_OBJECT(Impulse)
579
580public:
581 using ControlInlet::ControlInlet;
582 virtual ~Impulse() override;
583 bool isEvent() const override { return false; }
584 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
585 {
586 return new Process::ImpulseButton{objectName(), id, parent};
587 }
588
589 void impulse() W_SIGNAL(impulse);
590};
591
592class SCORE_PLUGIN_JS_EXPORT LineEdit : public ControlInlet
593{
594 W_OBJECT(LineEdit)
595
596public:
597 using ControlInlet::ControlInlet;
598 virtual ~LineEdit() override;
599 bool isEvent() const override { return true; }
600 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
601 {
602 return new Process::LineEdit{m_text, objectName(), id, parent};
603 }
604
605 W_INLINE_PROPERTY_CREF(QString, text, {}, text, setText, textChanged)
606};
607
608class SCORE_PLUGIN_JS_EXPORT HSVSlider : public ControlInlet
609{
610 W_OBJECT(HSVSlider)
611
612public:
613 using ControlInlet::ControlInlet;
614 virtual ~HSVSlider() override;
615 bool isEvent() const override { return true; }
616 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
617 {
618 auto col = init().toRgb();
619 ossia::vec4f v{
620 (float)col.redF(), (float)col.greenF(), (float)col.blueF(), (float)col.alphaF()};
621 return new Process::HSVSlider{v, objectName(), id, parent};
622 }
623
624 W_INLINE_PROPERTY_CREF(QColor, init, {}, init, setInit, initChanged)
625};
626class SCORE_PLUGIN_JS_EXPORT ValueOutlet : public Outlet
627{
628 W_OBJECT(ValueOutlet)
629
630 QJSValue m_value;
631
632public:
633 std::vector<OutValueMessage> values;
634
635 explicit ValueOutlet(QObject* parent = nullptr);
636 virtual ~ValueOutlet() override;
637 const QJSValue& value() const;
638 void clear()
639 {
640 m_value = QJSValue{};
641 values.clear();
642 }
643 Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
644 {
645 return new Process::ValueOutlet(id, parent);
646 }
647
648public:
649 void setValue(const QJSValue& value);
650 W_SLOT(setValue);
651 void addValue(qreal timestamp, QJSValue t);
652 W_SLOT(addValue);
653
654 W_PROPERTY(QJSValue, value READ value WRITE setValue)
655};
656
657class SCORE_PLUGIN_JS_EXPORT AudioInlet : public Inlet
658{
659 W_OBJECT(AudioInlet)
660
661public:
662 explicit AudioInlet(QObject* parent = nullptr);
663 virtual ~AudioInlet() override;
664 const QVector<QVector<double>>& audio() const;
665 void setAudio(const QVector<QVector<double>>& audio);
666
667 QVector<double> channel(int i) const
668 {
669 if(m_audio.size() > i)
670 return m_audio[i];
671 return {};
672 }
673 W_INVOKABLE(channel);
674
675 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
676 {
677 return new Process::AudioInlet(id, parent);
678 }
679
680private:
681 QVector<QVector<double>> m_audio;
682};
683
684class SCORE_PLUGIN_JS_EXPORT AudioOutlet : public Outlet
685{
686 W_OBJECT(AudioOutlet)
687
688public:
689 explicit AudioOutlet(QObject* parent = nullptr);
690 virtual ~AudioOutlet() override;
691 Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
692 {
693 auto p = new Process::AudioOutlet(id, parent);
694 if(id.val() == 0)
695 p->setPropagate(true);
696 return p;
697 }
698
699 const QVector<QVector<double>>& audio() const;
700
701 void setChannel(int i, const QJSValue& v);
702 W_INVOKABLE(setChannel)
703private:
704 QVector<QVector<double>> m_audio;
705};
706
707class SCORE_PLUGIN_JS_EXPORT MidiMessage
708{
709 W_GADGET(MidiMessage)
710
711public:
712 QByteArray bytes;
713
714 W_PROPERTY(QByteArray, bytes MEMBER bytes)
715};
716
717class SCORE_PLUGIN_JS_EXPORT MidiInlet : public Inlet
718{
719 W_OBJECT(MidiInlet)
720
721public:
722 explicit MidiInlet(QObject* parent = nullptr);
723 virtual ~MidiInlet() override;
724 template <typename T>
725 void setMidi(const T& arr)
726 {
727 m_midi.clear();
728 for(const libremidi::ump& mess : arr)
729 {
730 auto m1 = libremidi::midi1_from_ump(mess);
731 const auto N = mess.size();
732 QVector<int> m;
733 m.resize(N);
734
735 for(std::size_t i = 0; i < N; i++)
736 m[i] = m1.bytes[i];
737
738 m_midi.push_back(QVariant::fromValue(m));
739 }
740 }
741
742 QVariantList messages() const { return m_midi; }
743 W_INVOKABLE(messages);
744
745 Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
746 {
747 return new Process::MidiInlet(id, parent);
748 }
749
750private:
751 QVariantList m_midi;
752};
753
754class SCORE_PLUGIN_JS_EXPORT MidiOutlet : public Outlet
755{
756 W_OBJECT(MidiOutlet)
757
758public:
759 explicit MidiOutlet(QObject* parent = nullptr);
760 virtual ~MidiOutlet() override;
761 Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
762 {
763 return new Process::MidiOutlet(id, parent);
764 }
765
766 void clear();
767 const QVector<QVector<int>>& midi() const;
768
769 void setMessages(const QVariantList m)
770 {
771 m_midi.clear();
772 for(auto& v : m)
773 {
774 if(v.canConvert<QVector<int>>())
775 m_midi.push_back(v.value<QVector<int>>());
776 }
777 }
778 W_INVOKABLE(setMessages);
779
780 void add(QVector<int> m) { m_midi.push_back(std::move(m)); }
781 W_INVOKABLE(add);
782
783private:
784 QVector<QVector<int>> m_midi;
785};
786
787#if defined(SCORE_HAS_GPU_JS)
788class TextureOutlet : public Outlet
789{
790 W_OBJECT(TextureOutlet)
791
792public:
793 explicit TextureOutlet(QObject* parent = nullptr);
794 virtual ~TextureOutlet() override;
795 Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
796 {
797 auto p = new Gfx::TextureOutlet(id, parent);
798 return p;
799 }
800
801 QQuickItem* item() /*Qt6: const*/ noexcept { return m_item; }
802 void setItem(QQuickItem* v) { m_item = v; }
803
804 W_PROPERTY(QQuickItem*, item READ item WRITE setItem CONSTANT)
805private:
806 QQuickItem* m_item{};
807};
808#endif
809
810class Script : public QObject
811{
812 W_OBJECT(Script)
813 W_CLASSINFO("DefaultProperty", "data")
814 W_CLASSINFO(
815 "qt_QmlJSWrapperFactoryMethod", "_q_createJSWrapper(QV4::ExecutionEngine*)")
816
817public:
818 QQmlListProperty<QObject> data() noexcept { return {this, &m_data}; }
819
820 QJSValue& tick() /*Qt6: const*/ noexcept { return m_tick; }
821 void setTick(const QJSValue& v) { m_tick = v; }
822 QJSValue& start() /*Qt6: const*/ noexcept { return m_start; }
823 void setStart(const QJSValue& v) { m_start = v; }
824 QJSValue& stop() /*Qt6: const*/ noexcept { return m_stop; }
825 void setStop(const QJSValue& v) { m_stop = v; }
826 QJSValue& pause() /*Qt6: const*/ noexcept { return m_pause; }
827 void setPause(const QJSValue& v) { m_pause = v; }
828 QJSValue& resume() /*Qt6: const*/ noexcept { return m_resume; }
829 void setResume(const QJSValue& v) { m_resume = v; }
830 W_PROPERTY(QJSValue, tick READ tick WRITE setTick CONSTANT)
831 W_PROPERTY(QJSValue, start READ start WRITE setStart CONSTANT)
832 W_PROPERTY(QJSValue, stop READ stop WRITE setStop CONSTANT)
833 W_PROPERTY(QJSValue, pause READ pause WRITE setPause CONSTANT)
834 W_PROPERTY(QJSValue, resume READ resume WRITE setResume CONSTANT)
835 W_PROPERTY(QQmlListProperty<QObject>, data READ data)
836
837private:
838 QList<QObject*> m_data;
839 QJSValue m_tick;
840 QJSValue m_start;
841 QJSValue m_stop;
842 QJSValue m_pause;
843 QJSValue m_resume;
844};
845}
846
847inline QDataStream& operator<<(QDataStream& i, const JS::MidiMessage& sel)
848{
849 SCORE_ABORT;
850 return i;
851}
852inline QDataStream& operator>>(QDataStream& i, JS::MidiMessage& sel)
853{
854 SCORE_ABORT;
855 return i;
856}
857inline QDataStream& operator<<(QDataStream& i, const JS::InValueMessage& sel)
858{
859 SCORE_ABORT;
860 return i;
861}
862inline QDataStream& operator>>(QDataStream& i, JS::InValueMessage& sel)
863{
864 SCORE_ABORT;
865 return i;
866}
867inline QDataStream& operator<<(QDataStream& i, const JS::OutValueMessage& sel)
868{
869 SCORE_ABORT;
870 return i;
871}
872inline QDataStream& operator>>(QDataStream& i, JS::OutValueMessage& sel)
873{
874 SCORE_ABORT;
875 return i;
876}
877Q_DECLARE_METATYPE(JS::ValueInlet*)
878Q_DECLARE_METATYPE(JS::ValueOutlet*)
879Q_DECLARE_METATYPE(JS::AudioInlet*)
880Q_DECLARE_METATYPE(JS::AudioOutlet*)
881Q_DECLARE_METATYPE(JS::MidiMessage)
882Q_DECLARE_METATYPE(JS::MidiInlet*)
883Q_DECLARE_METATYPE(JS::MidiOutlet*)
884
885W_REGISTER_ARGTYPE(JS::ValueInlet*)
886W_REGISTER_ARGTYPE(JS::ValueOutlet*)
887W_REGISTER_ARGTYPE(JS::AudioInlet*)
888W_REGISTER_ARGTYPE(JS::AudioOutlet*)
889W_REGISTER_ARGTYPE(JS::MidiMessage)
890W_REGISTER_ARGTYPE(JS::MidiInlet*)
891W_REGISTER_ARGTYPE(JS::MidiOutlet*)
Definition QmlObjects.hpp:658
Definition QmlObjects.hpp:685
Definition QmlObjects.hpp:561
Definition QmlObjects.hpp:512
Definition QmlObjects.hpp:123
Definition QmlObjects.hpp:483
Definition QmlObjects.hpp:357
Definition QmlObjects.hpp:284
Definition QmlObjects.hpp:379
Definition QmlObjects.hpp:452
Definition QmlObjects.hpp:215
Definition QmlObjects.hpp:147
Definition QmlObjects.hpp:609
Definition QmlObjects.hpp:577
Definition QmlObjects.hpp:43
Definition QmlObjects.hpp:328
Definition QmlObjects.hpp:423
Definition QmlObjects.hpp:237
Definition QmlObjects.hpp:593
Definition QmlObjects.hpp:718
Definition QmlObjects.hpp:708
Definition QmlObjects.hpp:755
Definition QmlObjects.hpp:56
Definition QmlObjects.hpp:811
Definition QmlObjects.hpp:545
Definition QmlObjects.hpp:90
Definition QmlObjects.hpp:627
Definition Port.hpp:301
Definition Port.hpp:324
Definition Port.hpp:204
Definition Port.hpp:178
Definition Port.hpp:380
Definition Port.hpp:403
Definition Port.hpp:274
Definition Port.hpp:493
Definition Port.hpp:516
The id_base_t class.
Definition Identifier.hpp:59
Base classes and tools to implement processes and layers.
Definition JSONVisitor.hpp:1115
STL namespace.
Definition QmlObjects.hpp:202
Definition QmlObjects.hpp:196
Definition QmlObjects.hpp:68
Definition QmlObjects.hpp:190
Definition QmlObjects.hpp:79
Definition QmlObjects.hpp:208