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 #if defined(SCORE_HAS_GPU_JS)
8 #include <Gfx/TexturePort.hpp>
9 
10 #include <QQuickItem>
11 #endif
12 
13 #include <score/tools/Debug.hpp>
14 
15 #include <ossia/detail/math.hpp>
16 #include <ossia/detail/ssize.hpp>
17 #include <ossia/network/domain/domain.hpp>
18 
19 #include <QJSValue>
20 #include <QObject>
21 #include <QQmlListProperty>
22 #include <QVariant>
23 #include <QVector>
24 
25 #include <libremidi/message.hpp>
26 
27 #include <verdigris>
28 
29 class QQuickItem;
30 W_REGISTER_ARGTYPE(QJSValue)
31 namespace JS
32 {
33 class Inlet : public QObject
34 {
35  W_OBJECT(Inlet)
36 
37 public:
38  using QObject::QObject;
39  virtual ~Inlet() override;
40  virtual Process::Inlet* make(Id<Process::Port>&& id, QObject*) = 0;
41  virtual bool isEvent() const { return false; }
42 
43  W_INLINE_PROPERTY_CREF(QString, address, {}, address, setAddress, addressChanged)
44 };
45 
46 class Outlet : public QObject
47 {
48  W_OBJECT(Outlet)
49 
50 public:
51  using QObject::QObject;
52  virtual ~Outlet() override;
53  virtual Process::Outlet* make(Id<Process::Port>&& id, QObject*) = 0;
54 
55  W_INLINE_PROPERTY_CREF(QString, address, {}, address, setAddress, addressChanged)
56 };
57 
58 struct InValueMessage
59 {
60  W_GADGET(InValueMessage)
61 
62 public:
63  qreal timestamp;
64  QVariant value;
65  W_PROPERTY(qreal, timestamp MEMBER timestamp)
66  W_PROPERTY(QVariant, value MEMBER value)
67 };
68 
69 struct OutValueMessage
70 {
71  W_GADGET(OutValueMessage)
72 
73 public:
74  qreal timestamp;
75  QJSValue value;
76  W_PROPERTY(qreal, timestamp MEMBER timestamp)
77  W_PROPERTY(QJSValue, value MEMBER value)
78 };
79 
80 class ValueInlet : public Inlet
81 {
82  W_OBJECT(ValueInlet)
83 
84  QVariant m_value;
85  QVariantList m_values;
86 
87 public:
88  explicit ValueInlet(QObject* parent = nullptr);
89  virtual ~ValueInlet() override;
90  QVariant value() const;
91  QVariantList values() const { return m_values; }
92 
93  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
94  {
95  return new Process::ValueInlet(id, parent);
96  }
97 
98  int length() const noexcept;
99  W_SLOT(length)
100 
101  QVariant at(int index) const noexcept;
102  W_SLOT(at)
103 
104  void clear() { m_values.clear(); }
105  void setValue(QVariant value);
106  void addValue(QVariant&& val) { m_values.append(std::move(val)); }
107  void valueChanged(QVariant value) W_SIGNAL(valueChanged, value);
108 
109  W_PROPERTY(QVariantList, values READ values)
110  W_PROPERTY(QVariant, value READ value NOTIFY valueChanged)
111 };
112 
113 class ControlInlet : public Inlet
114 {
115  W_OBJECT(ControlInlet)
116 
117  QVariant m_value;
118 
119 public:
120  explicit ControlInlet(QObject* parent = nullptr);
121  virtual ~ControlInlet() override;
122  QVariant value() const;
123 
124  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
125  {
126  return new Process::ControlInlet(id, parent);
127  }
128 
129  void clear() { m_value = QVariant{}; }
130  void setValue(QVariant value);
131  void valueChanged(QVariant value) W_SIGNAL(valueChanged, value);
132 
133  W_PROPERTY(QVariant, value READ value NOTIFY valueChanged)
134 };
135 
136 class FloatSlider : public ControlInlet
137 {
138  W_OBJECT(FloatSlider)
139 
140 public:
141  using ControlInlet::ControlInlet;
142  virtual ~FloatSlider() override;
143  bool isEvent() const override { return true; }
144 
145  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
146  {
147  return new Process::FloatSlider{(float)m_min, (float)m_max, (float)m_init,
148  objectName(), id, parent};
149  }
150 
151  W_INLINE_PROPERTY_VALUE(qreal, init, {0.5}, init, setInit, initChanged)
152  W_INLINE_PROPERTY_VALUE(qreal, min, {0.}, getMin, setMin, minChanged)
153  W_INLINE_PROPERTY_VALUE(qreal, max, {1.}, getMax, setMax, maxChanged)
154 };
155 
156 class IntSlider : public ControlInlet
157 {
158  W_OBJECT(IntSlider)
159 
160 public:
161  using ControlInlet::ControlInlet;
162  virtual ~IntSlider() override;
163  bool isEvent() const override { return true; }
164 
165  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
166  {
167  return new Process::IntSlider{m_min, m_max, m_init, objectName(), id, parent};
168  }
169 
170  W_INLINE_PROPERTY_VALUE(int, init, {0}, init, setInit, initChanged)
171  W_INLINE_PROPERTY_VALUE(int, min, {0}, getMin, setMin, minChanged)
172  W_INLINE_PROPERTY_VALUE(int, max, {127}, getMax, setMax, maxChanged)
173 };
174 
175 class Enum : public ControlInlet
176 {
177  W_OBJECT(Enum)
178 
179 public:
180  using ControlInlet::ControlInlet;
181  virtual ~Enum() override;
182  bool isEvent() const override { return true; }
183 
184  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
185  {
186  return new Process::Enum{m_choices, {}, current(), objectName(), id, parent};
187  }
188 
189  auto getValues() const { return choices(); }
190 
191  std::string current() const
192  {
193  if(!m_choices.isEmpty() && ossia::valid_index(m_index, m_choices))
194  {
195  return m_choices[m_index].toStdString();
196  }
197  return {};
198  }
199 
200  W_INLINE_PROPERTY_VALUE(int, index, {}, index, setIndex, indexChanged)
201  W_INLINE_PROPERTY_CREF(QStringList, choices, {}, choices, setChoices, choicesChanged)
202 };
203 
204 class Toggle : public ControlInlet
205 {
206  W_OBJECT(Toggle)
207 
208 public:
209  using ControlInlet::ControlInlet;
210  virtual ~Toggle() override;
211  bool isEvent() const override { return true; }
212  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
213  {
214  return new Process::Toggle{m_checked, objectName(), id, parent};
215  }
216 
217  W_INLINE_PROPERTY_VALUE(bool, checked, {}, checked, setChecked, checkedChanged)
218 };
219 
220 class Button : public ControlInlet
221 {
222  W_OBJECT(Button)
223 
224 public:
225  using ControlInlet::ControlInlet;
226  virtual ~Button() override;
227  bool isEvent() const override { return true; }
228  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
229  {
230  return new Process::Button{objectName(), id, parent};
231  }
232 
233  W_INLINE_PROPERTY_VALUE(bool, checked, {}, checked, setChecked, checkedChanged)
234 };
235 
236 class Impulse : public ControlInlet
237 {
238  W_OBJECT(Impulse)
239 
240 public:
241  using ControlInlet::ControlInlet;
242  virtual ~Impulse() override;
243  bool isEvent() const override { return false; }
244  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
245  {
246  return new Process::ImpulseButton{objectName(), id, parent};
247  }
248 
249  void impulse() W_SIGNAL(impulse);
250 };
251 
252 class LineEdit : public ControlInlet
253 {
254  W_OBJECT(LineEdit)
255 
256 public:
257  using ControlInlet::ControlInlet;
258  virtual ~LineEdit() override;
259  bool isEvent() const override { return true; }
260  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
261  {
262  return new Process::LineEdit{m_text, objectName(), id, parent};
263  }
264 
265  W_INLINE_PROPERTY_CREF(QString, text, {}, text, setText, textChanged)
266 };
267 
268 class ValueOutlet : public Outlet
269 {
270  W_OBJECT(ValueOutlet)
271 
272  QJSValue m_value;
273 
274 public:
275  std::vector<OutValueMessage> values;
276 
277  explicit ValueOutlet(QObject* parent = nullptr);
278  virtual ~ValueOutlet() override;
279  const QJSValue& value() const;
280  void clear()
281  {
282  m_value = QJSValue{};
283  values.clear();
284  }
285  Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
286  {
287  return new Process::ValueOutlet(id, parent);
288  }
289 
290 public:
291  void setValue(const QJSValue& value);
292  W_SLOT(setValue);
293  void addValue(qreal timestamp, QJSValue t);
294  W_SLOT(addValue);
295 
296  W_PROPERTY(QJSValue, value READ value WRITE setValue)
297 };
298 
299 class AudioInlet : public Inlet
300 {
301  W_OBJECT(AudioInlet)
302 
303 public:
304  explicit AudioInlet(QObject* parent = nullptr);
305  virtual ~AudioInlet() override;
306  const QVector<QVector<double>>& audio() const;
307  void setAudio(const QVector<QVector<double>>& audio);
308 
309  QVector<double> channel(int i) const
310  {
311  if(m_audio.size() > i)
312  return m_audio[i];
313  return {};
314  }
315  W_INVOKABLE(channel);
316 
317  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
318  {
319  return new Process::AudioInlet(id, parent);
320  }
321 
322 private:
323  QVector<QVector<double>> m_audio;
324 };
325 
326 class AudioOutlet : public Outlet
327 {
328  W_OBJECT(AudioOutlet)
329 
330 public:
331  explicit AudioOutlet(QObject* parent = nullptr);
332  virtual ~AudioOutlet() override;
333  Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
334  {
335  auto p = new Process::AudioOutlet(id, parent);
336  if(id.val() == 0)
337  p->setPropagate(true);
338  return p;
339  }
340 
341  const QVector<QVector<double>>& audio() const;
342 
343  void setChannel(int i, const QJSValue& v);
344  W_INVOKABLE(setChannel)
345 private:
346  QVector<QVector<double>> m_audio;
347 };
348 
349 class MidiMessage
350 {
351  W_GADGET(MidiMessage)
352 
353 public:
354  QByteArray bytes;
355 
356  W_PROPERTY(QByteArray, bytes MEMBER bytes)
357 };
358 
359 class MidiInlet : public Inlet
360 {
361  W_OBJECT(MidiInlet)
362 
363 public:
364  explicit MidiInlet(QObject* parent = nullptr);
365  virtual ~MidiInlet() override;
366  template <typename T>
367  void setMidi(const T& arr)
368  {
369  m_midi.clear();
370  for(const libremidi::message& mess : arr)
371  {
372  const auto N = mess.size();
373  QVector<int> m;
374  m.resize(N);
375 
376  for(std::size_t i = 0; i < N; i++)
377  m[i] = mess.bytes[i];
378 
379  m_midi.push_back(QVariant::fromValue(m));
380  }
381  }
382 
383  QVariantList messages() const { return m_midi; }
384  W_INVOKABLE(messages);
385 
386  Process::Inlet* make(Id<Process::Port>&& id, QObject* parent) override
387  {
388  return new Process::MidiInlet(id, parent);
389  }
390 
391 private:
392  QVariantList m_midi;
393 };
394 
395 class MidiOutlet : public Outlet
396 {
397  W_OBJECT(MidiOutlet)
398 
399 public:
400  explicit MidiOutlet(QObject* parent = nullptr);
401  virtual ~MidiOutlet() override;
402  Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
403  {
404  return new Process::MidiOutlet(id, parent);
405  }
406 
407  void clear();
408  const QVector<QVector<int>>& midi() const;
409 
410  void setMessages(const QVariantList m)
411  {
412  m_midi.clear();
413  for(auto& v : m)
414  {
415  if(v.canConvert<QVector<int>>())
416  m_midi.push_back(v.value<QVector<int>>());
417  }
418  }
419  W_INVOKABLE(setMessages);
420 
421  void add(QVector<int> m) { m_midi.push_back(std::move(m)); }
422  W_INVOKABLE(add);
423 
424 private:
425  QVector<QVector<int>> m_midi;
426 };
427 
428 #if defined(SCORE_HAS_GPU_JS)
429 class TextureOutlet : public Outlet
430 {
431  W_OBJECT(TextureOutlet)
432 
433 public:
434  explicit TextureOutlet(QObject* parent = nullptr);
435  virtual ~TextureOutlet() override;
436  Process::Outlet* make(Id<Process::Port>&& id, QObject* parent) override
437  {
438  auto p = new Gfx::TextureOutlet(id, parent);
439  return p;
440  }
441 
442  QQuickItem* item() /*Qt6: const*/ noexcept { return m_item; }
443  void setItem(QQuickItem* v) { m_item = v; }
444 
445  W_PROPERTY(QQuickItem*, item READ item WRITE setItem CONSTANT)
446 private:
447  QQuickItem* m_item{};
448 };
449 #endif
450 
451 class Script : public QObject
452 {
453  W_OBJECT(Script)
454  W_CLASSINFO("DefaultProperty", "data")
455  W_CLASSINFO(
456  "qt_QmlJSWrapperFactoryMethod", "_q_createJSWrapper(QV4::ExecutionEngine*)")
457 
458 public:
459  QQmlListProperty<QObject> data() noexcept { return {this, &m_data}; }
460 
461  QJSValue& tick() /*Qt6: const*/ noexcept { return m_tick; }
462  void setTick(const QJSValue& v) { m_tick = v; }
463  QJSValue& start() /*Qt6: const*/ noexcept { return m_start; }
464  void setStart(const QJSValue& v) { m_start = v; }
465  QJSValue& stop() /*Qt6: const*/ noexcept { return m_stop; }
466  void setStop(const QJSValue& v) { m_stop = v; }
467  QJSValue& pause() /*Qt6: const*/ noexcept { return m_pause; }
468  void setPause(const QJSValue& v) { m_pause = v; }
469  QJSValue& resume() /*Qt6: const*/ noexcept { return m_resume; }
470  void setResume(const QJSValue& v) { m_resume = v; }
471  W_PROPERTY(QJSValue, tick READ tick WRITE setTick CONSTANT)
472  W_PROPERTY(QJSValue, start READ start WRITE setStart CONSTANT)
473  W_PROPERTY(QJSValue, stop READ stop WRITE setStop CONSTANT)
474  W_PROPERTY(QJSValue, pause READ pause WRITE setPause CONSTANT)
475  W_PROPERTY(QJSValue, resume READ resume WRITE setResume CONSTANT)
476  W_PROPERTY(QQmlListProperty<QObject>, data READ data)
477 
478 private:
479  QList<QObject*> m_data;
480  QJSValue m_tick;
481  QJSValue m_start;
482  QJSValue m_stop;
483  QJSValue m_pause;
484  QJSValue m_resume;
485 };
486 }
487 
488 inline QDataStream& operator<<(QDataStream& i, const JS::MidiMessage& sel)
489 {
490  SCORE_ABORT;
491  return i;
492 }
493 inline QDataStream& operator>>(QDataStream& i, JS::MidiMessage& sel)
494 {
495  SCORE_ABORT;
496  return i;
497 }
498 inline QDataStream& operator<<(QDataStream& i, const JS::InValueMessage& sel)
499 {
500  SCORE_ABORT;
501  return i;
502 }
503 inline QDataStream& operator>>(QDataStream& i, JS::InValueMessage& sel)
504 {
505  SCORE_ABORT;
506  return i;
507 }
508 inline QDataStream& operator<<(QDataStream& i, const JS::OutValueMessage& sel)
509 {
510  SCORE_ABORT;
511  return i;
512 }
513 inline QDataStream& operator>>(QDataStream& i, JS::OutValueMessage& sel)
514 {
515  SCORE_ABORT;
516  return i;
517 }
518 Q_DECLARE_METATYPE(JS::ValueInlet*)
519 Q_DECLARE_METATYPE(JS::ValueOutlet*)
520 Q_DECLARE_METATYPE(JS::AudioInlet*)
521 Q_DECLARE_METATYPE(JS::AudioOutlet*)
522 Q_DECLARE_METATYPE(JS::MidiMessage)
523 Q_DECLARE_METATYPE(JS::MidiInlet*)
524 Q_DECLARE_METATYPE(JS::MidiOutlet*)
525 
526 W_REGISTER_ARGTYPE(JS::ValueInlet*)
527 W_REGISTER_ARGTYPE(JS::ValueOutlet*)
528 W_REGISTER_ARGTYPE(JS::AudioInlet*)
529 W_REGISTER_ARGTYPE(JS::AudioOutlet*)
530 W_REGISTER_ARGTYPE(JS::MidiMessage)
531 W_REGISTER_ARGTYPE(JS::MidiInlet*)
532 W_REGISTER_ARGTYPE(JS::MidiOutlet*)
Definition: QmlObjects.hpp:285
Definition: QmlObjects.hpp:312
Definition: QmlObjects.hpp:209
Definition: QmlObjects.hpp:109
Definition: QmlObjects.hpp:166
Definition: QmlObjects.hpp:131
Definition: QmlObjects.hpp:224
Definition: QmlObjects.hpp:149
Definition: QmlObjects.hpp:34
Definition: QmlObjects.hpp:240
Definition: QmlObjects.hpp:343
Definition: QmlObjects.hpp:334
Definition: QmlObjects.hpp:379
Definition: QmlObjects.hpp:46
Definition: score-lib-process/Process/Dataflow/Port.hpp:290
Definition: score-lib-process/Process/Dataflow/Port.hpp:313
Definition: score-lib-process/Process/Dataflow/Port.hpp:202
Definition: score-lib-process/Process/Dataflow/Port.hpp:176
Definition: score-lib-process/Process/Dataflow/Port.hpp:369
Definition: score-lib-process/Process/Dataflow/Port.hpp:392
Definition: score-lib-process/Process/Dataflow/Port.hpp:264
Definition: score-lib-process/Process/Dataflow/Port.hpp:481
Definition: score-lib-process/Process/Dataflow/Port.hpp:504
Definition: QmlObjects.hpp:435
Definition: QmlObjects.hpp:194
Definition: QmlObjects.hpp:77
Definition: QmlObjects.hpp:255
The id_base_t class.
Definition: Identifier.hpp:57
Definition: QmlObjects.hpp:57
Definition: QmlObjects.hpp:67