Loading...
Searching...
No Matches
CPUNode.hpp
1#pragma once
2
3#include <JS/Executor/JSAPIWrapper.hpp>
4#include <JS/JSProcessMetadata.hpp>
5#include <JS/Qml/Metatypes.hpp>
6#include <JS/Qml/QmlObjects.hpp>
7#include <JS/Qml/ValueTypes.Qt6.hpp>
8
9#include <ossia/dataflow/graph/graph_interface.hpp>
10#include <ossia/dataflow/graph_edge.hpp>
11#include <ossia/dataflow/graph_edge_helpers.hpp>
12#include <ossia/dataflow/graph_node.hpp>
13#include <ossia/dataflow/node_process.hpp>
14#include <ossia/dataflow/port.hpp>
15#include <ossia/detail/logger.hpp>
16#include <ossia/detail/ssize.hpp>
17#include <ossia/editor/scenario/time_interval.hpp>
18#include <ossia/editor/state/message.hpp>
19#include <ossia/editor/state/state.hpp>
20
21#include <ossia-qt/invoke.hpp>
22#include <ossia-qt/js_utilities.hpp>
23#include <ossia-qt/time.hpp>
24#include <ossia-qt/token_request.hpp>
25namespace ossia::qt
26{
27class qml_engine_functions;
28}
29
30namespace JS
31{
32class js_node final : public ossia::graph_node
33{
34public:
35 explicit js_node(ossia::execution_state& st);
36 ~js_node();
37
38 [[nodiscard]] std::string label() const noexcept override { return "javascript"; }
39
40 void run(const ossia::token_request& t, ossia::exec_state_facade) noexcept override;
41 void clear() noexcept override;
42 void setupComponent();
43 void setScript(const QString& val);
44
45 ossia::execution_state& m_st;
46
47 std::shared_ptr<QQmlEngine> m_engine{};
48 QQmlContext* m_context{};
49 std::vector<Inlet*> m_jsInlets;
50 std::vector<std::pair<ControlInlet*, ossia::inlet_ptr>> m_ctrlInlets;
51 std::vector<std::pair<Impulse*, ossia::inlet_ptr>> m_impulseInlets;
52 std::vector<std::pair<ValueInlet*, ossia::inlet_ptr>> m_valInlets;
53 std::vector<std::pair<ValueOutlet*, ossia::outlet_ptr>> m_valOutlets;
54 std::vector<std::pair<AudioInlet*, ossia::inlet_ptr>> m_audInlets;
55 std::vector<std::pair<AudioOutlet*, ossia::outlet_ptr>> m_audOutlets;
56 std::vector<std::pair<MidiInlet*, ossia::inlet_ptr>> m_midInlets;
57 std::vector<std::pair<MidiOutlet*, ossia::outlet_ptr>> m_midOutlets;
58 JS::Script* m_object{};
59 ossia::qt::qml_engine_functions* m_execFuncs{};
60 std::optional<QJSValueList> m_tickCall;
61 QPointer<QObject> m_uiContext;
62 std::function<void(QVariant)> m_messageToUi;
63 std::size_t m_gcIndex{};
64
65 JS::JSState m_modelState;
66
67 bool triggerStart{};
68 bool triggerStop{};
69 bool triggerPause{};
70 bool triggerResume{};
71
72 void setControl(std::size_t index, const QVariant& val)
73 {
74 if(index > m_jsInlets.size())
75 return;
76 if(auto v = qobject_cast<ValueInlet*>(m_jsInlets[index]))
77 v->setValue(val);
78 else if(auto v = qobject_cast<ControlInlet*>(m_jsInlets[index]))
79 v->setValue(val);
80 }
81 void impulse(std::size_t index)
82 {
83 if(index > m_jsInlets.size())
84 return;
85 if(auto v = qobject_cast<Impulse*>(m_jsInlets[index]))
86 v->impulse();
87 }
88
89 void uiMessage(const QVariant& v)
90 {
91 if(!m_object)
92 return;
93
94 const auto& on_ui = this->m_object->uiEvent();
95 if(!on_ui.isCallable())
96 return;
97
98 on_ui.call({m_engine->toScriptValue(v)});
99 }
100
101 void stateElementChanged(const QString& k, const ossia::value& v)
102 {
103 if(!m_object)
104 return;
105
106 const auto& on_stateUpdated = this->m_object->stateUpdated();
107 if(!on_stateUpdated.isCallable())
108 return;
109
110 if(v.valid())
111 {
112 if(auto res = v.apply(ossia::qt::ossia_to_qvariant{}); res.isValid())
113 on_stateUpdated.call({k, m_engine->toScriptValue(res)});
114 else
115 on_stateUpdated.call({k, QJSValue{}});
116 }
117 else
118 on_stateUpdated.call({k, QJSValue{}});
119 }
120};
121
122struct js_process final : public ossia::node_process
123{
124 using node_process::node_process;
125 js_node& js() const { return static_cast<js_node&>(*node); }
126 void start() override { js().triggerStart = true; }
127 void stop() override { js().triggerStop = true; }
128 void pause() override { js().triggerPause = true; }
129 void resume() override { js().triggerResume = true; }
130 void transport_impl(ossia::time_value date) override
131 {
132 QMetaObject::invokeMethod(
133 js().m_object, "transport", Qt::DirectConnection,
134 Q_ARG(QVariant, double(date.impl)));
135 }
136 void offset_impl(ossia::time_value date) override
137 {
138 QMetaObject::invokeMethod(
139 js().m_object, "offset", Qt::DirectConnection,
140 Q_ARG(QVariant, double(date.impl)));
141 }
142};
143
144}
Definition QmlObjects.hpp:845
Definition CPUNode.hpp:33
Definition CPUNode.hpp:123