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 SCORE_PLUGIN_JS_EXPORT 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& rootPath, 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 QPointer<JS::ProcessModel> m_modelContext;
63 std::function<void(QVariant)> m_messageToUi;
64 std::size_t m_gcIndex{};
65
66 JS::JSState m_modelState;
67
68 bool triggerStart{};
69 bool triggerStop{};
70 bool triggerPause{};
71 bool triggerResume{};
72
73 void setControl(std::size_t index, const QVariant& val)
74 {
75 if(index >= m_jsInlets.size())
76 return;
77 if(auto v = qobject_cast<ValueInlet*>(m_jsInlets[index]))
78 v->setValue(val);
79 else if(auto v = qobject_cast<ControlInlet*>(m_jsInlets[index]))
80 v->setValue(val);
81 }
82 void impulse(std::size_t index)
83 {
84 if(index >= m_jsInlets.size())
85 return;
86 if(auto v = qobject_cast<Impulse*>(m_jsInlets[index]))
87 v->impulse();
88 }
89
90 void uiMessage(const QVariant& v)
91 {
92 if(!m_object)
93 return;
94
95 const auto& on_ui = this->m_object->uiEvent();
96 if(!on_ui.isCallable())
97 return;
98
99 on_ui.call({m_engine->toScriptValue(v)});
100 }
101
102 void stateElementChanged(const QString& k, const ossia::value& v)
103 {
104 if(!m_object)
105 return;
106
107 const auto& on_stateUpdated = this->m_object->stateUpdated();
108 if(!on_stateUpdated.isCallable())
109 return;
110
111 if(v.valid())
112 {
113 if(auto res = v.apply(ossia::qt::ossia_to_qvariant{}); res.isValid())
114 on_stateUpdated.call({k, m_engine->toScriptValue(res)});
115 else
116 on_stateUpdated.call({k, QJSValue{}});
117 }
118 else
119 on_stateUpdated.call({k, QJSValue{}});
120 }
121};
122
123struct js_process final : public ossia::node_process
124{
125 using node_process::node_process;
126 js_node& js() const { return static_cast<js_node&>(*node); }
127 void start() override { js().triggerStart = true; }
128 void stop() override { js().triggerStop = true; }
129 void pause() override { js().triggerPause = true; }
130 void resume() override { js().triggerResume = true; }
131 void transport_impl(ossia::time_value date) override
132 {
133 QMetaObject::invokeMethod(
134 js().m_object, "transport", Qt::DirectConnection,
135 Q_ARG(QVariant, double(date.impl)));
136 }
137 void offset_impl(ossia::time_value date) override
138 {
139 QMetaObject::invokeMethod(
140 js().m_object, "offset", Qt::DirectConnection,
141 Q_ARG(QVariant, double(date.impl)));
142 }
143};
144
145}
Definition QmlObjects.hpp:849
Definition CPUNode.hpp:33
Definition CPUNode.hpp:124