Loading...
Searching...
No Matches
ScriptableProcessComponent.hpp
1#pragma once
2#include <State/Address.hpp>
3
4#include <Process/ProcessComponent.hpp>
5
6#include <LocalTree/ScriptableReference.hpp>
7
8
9#include <score/model/Component.hpp>
10#include <score/model/EntityMap.hpp>
11#include <score/plugins/Interface.hpp>
12#include <score/plugins/InterfaceList.hpp>
13
14#include <ossia/network/base/node.hpp>
15#include <ossia/network/base/parameter.hpp>
16
17#include <ossia/detail/hash_map.hpp>
18
19#include <QMetaObject>
20
21#include <score_lib_process_export.h>
22
23#include <nano_observer.hpp>
24
25#include <functional>
26#include <memory>
27#include <optional>
28#include <string>
29#include <vector>
30
31namespace score
32{
33class ModelMetadata;
34}
35namespace Process
36{
37class Port;
38class ControlInlet;
39}
40
41namespace LocalTree
42{
43class ScriptableTreeBase;
45enum class ControlWrites
46{
48 Edit,
52 Record,
54 Drop
55};
56
58{
59 ossia::net::node_base& controls;
60 ossia::net::node_base& triggers;
61 ossia::net::node_base& conditions;
62
64 std::function<void(ossia::net::node_base&)> retire;
65
67 std::function<void(ossia::net::node_base&)> hide;
68
70 std::function<ossia::net::node_base*(ossia::net::node_base&, const std::string&)> revive;
71
72 std::function<void(ossia::net::node_base&, const QObject&, const QString&)> tag;
73
75 std::function<void(QObject&)> referrer;
76
79
81 std::function<ControlWrites(Recall)> writes;
82
84 std::function<void(Process::ControlInlet&, const ossia::value&)> recorded;
85
87 std::function<void(Process::ControlInlet&, const ossia::value&)> played;
88};
89
90inline void announceReferrer(const ScriptableRoots& roots, QObject& object)
91{
92 if(roots.referrer)
93 roots.referrer(object);
94}
95
96inline void tagNode(
97 const ScriptableRoots& roots, ossia::net::node_base& node, const QObject& object,
98 const QString& member = {})
99{
100 if(roots.tag)
101 roots.tag(node, object, member);
102}
103
104inline void retireNode(const ScriptableRoots& roots, ossia::net::node_base& node)
105{
106 if(roots.retire)
107 roots.retire(node);
108 else if(auto parent = node.get_parent())
109 parent->remove_child(node);
110}
111
114{
115 ossia::net::parameter_base& param;
116 std::optional<ossia::net::parameter_base::callback_index> callback;
117 QMetaObject::Connection connection;
119 std::shared_ptr<bool> alive = std::make_shared<bool>(true);
120
121 explicit ParameterBinding(ossia::net::parameter_base& p)
122 : param{p}
123 {
124 }
125 ParameterBinding(const ParameterBinding&) = delete;
126 ParameterBinding& operator=(const ParameterBinding&) = delete;
128 virtual void write(const ossia::value&) { }
129 virtual ~ParameterBinding()
130 {
131 *alive = false;
132 QObject::disconnect(connection);
133 if(callback)
134 param.remove_callback(*callback);
135 }
136};
137
138SCORE_LIB_PROCESS_EXPORT ::State::Address addressOfNode(const ossia::net::node_base& n);
139
143{
144 QString name;
145 std::function<void()> restore;
146 bool active{};
147
149 void follow(const QString& current) { active = restore && current == name; }
152 {
153 if(std::exchange(active, false))
154 restore();
155 }
156};
157
158SCORE_LIB_PROCESS_EXPORT
159void giveName(
160 GivenName& given, score::ModelMetadata& metadata, const QString& own,
161 const QString& name);
162SCORE_LIB_PROCESS_EXPORT
163void giveName(GivenName& given, Process::Port& port, const QString& name);
164
166template <typename F>
167ossia::net::node_base* createScriptableNode(
168 const ScriptableRoots& roots, ossia::net::node_base& parent, const QString& name,
169 F&& writeBack)
170{
171 ossia::net::node_base* node{};
172 if(roots.revive)
173 node = roots.revive(parent, name.toStdString());
174 if(!node)
175 node = parent.create_child(name.toStdString());
176 if(!node)
177 return nullptr;
178 if(auto real = QString::fromStdString(node->get_name()); real != name)
179 writeBack(real);
180 return node;
181}
182
183template <typename F>
184void renameScriptableNode(ossia::net::node_base& node, const QString& name, F&& writeBack)
185{
186 const auto wanted = name.toStdString();
187 if(node.get_name() == wanted)
188 return;
189 node.set_name(wanted);
190 if(auto real = QString::fromStdString(node.get_name()); real != name)
191 writeBack(real);
192}
193
196class SCORE_LIB_PROCESS_EXPORT ScriptableProcessBase
197 : public Process::GenericProcessComponent<const score::DocumentContext>
198{
199 ABSTRACT_COMPONENT_METADATA(
200 ScriptableProcessBase, "ffd963c1-07f3-445f-b914-d36f59a08edf")
201public:
202 static constexpr bool is_unique = true;
205 const score::DocumentContext& ctx, QObject* parent);
206 ~ScriptableProcessBase() override;
207
208 ossia::net::node_base* node() const noexcept { return m_node; }
209 ossia::net::node_base* node(const Process::Port& port) const noexcept;
210 ossia::net::node_base* stateNode() const noexcept;
211
213 ossia::net::parameter_base* reserve(const std::string& name, const ossia::value& sample);
214
215private:
216 struct PortEntry;
217 struct Kept;
218
221 void keep(ossia::net::node_base& node, bool withValue);
222 ossia::net::node_base* takeKept(const QString& name, std::optional<ossia::value>& written);
223 void dropKept(const QString& name);
224
225 void refresh();
226 void renameNode();
228 void removeNode(bool restoreNames);
229 void publish(PortEntry& e);
230 void unpublish(PortEntry& e, bool restoreName);
231 void syncState();
232
233protected:
234 ScriptableRoots m_roots;
235
236private:
237 ossia::net::node_base* m_node{};
238 GivenName m_given;
239 std::unique_ptr<ParameterBinding> m_state;
240 std::vector<std::unique_ptr<PortEntry>> m_ports;
241 ossia::hash_map<const Process::Port*, PortEntry*> m_byPort;
242 std::vector<std::unique_ptr<Kept>> m_kept;
243};
244
245class SCORE_LIB_PROCESS_EXPORT ScriptableProcessComponent final
246 : public ScriptableProcessBase
247{
248 COMPONENT_METADATA("ed8196b3-c432-4405-a89b-ffc98a1e8f08")
249public:
250 using ScriptableProcessBase::ScriptableProcessBase;
251};
252
254class SCORE_LIB_PROCESS_EXPORT ScriptableProcessFactory : public score::InterfaceBase
255{
256 SCORE_INTERFACE(ScriptableProcessFactory, "a6313dd7-00a4-4c65-afb7-3552f0c84216")
257public:
258 ~ScriptableProcessFactory() override;
259 virtual bool matches(const Process::ProcessModel&) const noexcept = 0;
260 virtual ScriptableProcessBase* make(
262 const score::DocumentContext& ctx, QObject* parent) const = 0;
263};
264
265class SCORE_LIB_PROCESS_EXPORT ScriptableProcessFactoryList final
266 : public score::InterfaceList<ScriptableProcessFactory>
267{
268public:
270};
271
272SCORE_LIB_PROCESS_EXPORT ScriptableProcessBase* makeScriptableProcess(
274 QObject* parent);
275
276class SCORE_LIB_PROCESS_EXPORT ScriptableProcessGroup final
277 : public ScriptableProcessBase
278 , public Nano::Observer
279{
280 COMPONENT_METADATA("9b9f1041-3cda-46ea-b94b-aa0d113cea83")
281public:
285 const score::DocumentContext& ctx, QObject* parent);
287
288private:
289 void add(Process::ProcessModel& proc);
290 void remove(const Process::ProcessModel& proc);
291
292 std::vector<std::pair<Process::ProcessModel*, ScriptableProcessBase*>> m_children;
293};
294
296struct SCORE_LIB_PROCESS_EXPORT ScriptableSnapshot
297{
298 struct Entry
299 {
300 QString kind;
301 QString address;
302 QStringList children;
303 };
305 ossia::hash_map<QString, Entry> entries;
306
307 static std::shared_ptr<const ScriptableSnapshot> build(const ScriptableRoots& roots);
308};
309
311SCORE_LIB_PROCESS_EXPORT ::State::Address scriptableAddress(const Process::ProcessModel&);
312SCORE_LIB_PROCESS_EXPORT ::State::Address scriptableAddress(const Process::Port&);
314SCORE_LIB_PROCESS_EXPORT bool publishedWithProcess(const Process::Port&) noexcept;
315SCORE_LIB_PROCESS_EXPORT bool wantsPublished(const Process::Port&) noexcept;
316SCORE_LIB_PROCESS_EXPORT ::State::Address
317scriptableStateAddress(const Process::ProcessModel&);
318}
Definition ScriptableProcessComponent.hpp:198
Definition ScriptableProcessComponent.hpp:247
For processes containing other processes; others use ScriptableProcessComponent.
Definition ScriptableProcessComponent.hpp:255
Definition ScriptableProcessComponent.hpp:267
Definition ScriptableProcessComponent.hpp:279
Publishes the scriptable namespace and maps addresses to objects and back.
Definition ScriptableReference.hpp:46
Definition Port.hpp:242
Definition Port.hpp:106
Definition Process/ProcessComponent.hpp:10
The Process class.
Definition score-lib-process/Process/Process.hpp:80
The EntityMap class.
Definition EntityMap.hpp:37
Base class for plug-in interfaces.
Definition Interface.hpp:52
InterfaceList Default implementation of InterfaceListBase.
Definition InterfaceList.hpp:97
The ModelMetadata class.
Definition ModelMetadata.hpp:22
Local tree provides a way to extend the tree given through the Engine::Network::LocalDevice.
Definition BaseCallbackWrapper.hpp:9
ControlWrites
What a value written into a published control does.
Definition ScriptableProcessComponent.hpp:46
@ Drop
Ignored, e.g. the end state sent at stop.
@ Record
The whole run becomes one command at stop.
@ Edit
Undoable command.
@ Execution
Sent to the execution only, displayed until stop.
ossia::net::node_base * createScriptableNode(const ScriptableRoots &roots, ossia::net::node_base &parent, const QString &name, F &&writeBack)
writeBack gets the name the device picked when it differs, e.g. on collision
Definition ScriptableProcessComponent.hpp:167
bool publishedWithProcess(const Process::Port &port) noexcept
Controls of a scriptable process are published whether or not flagged.
Definition ScriptableProcessComponent.cpp:836
::State::Address scriptableAddress(const Process::ProcessModel &proc)
score:/controls/<process>[/<port>|/preset]; empty when not published.
Definition ScriptableProcessComponent.cpp:819
Recall
Which state sent outside of a scenario run the values of published controls come from.
Definition ScriptableReference.hpp:36
Base classes and tools to implement processes and layers.
Definition JSONVisitor.hpp:1115
Base toolkit upon which the software is built.
Definition Application.cpp:108
Definition ScriptableProcessComponent.hpp:143
void operator()()
Called when the object is unpublished but not destroyed.
Definition ScriptableProcessComponent.hpp:151
void follow(const QString &current)
Called when the object is renamed or published.
Definition ScriptableProcessComponent.hpp:149
Does not remove the node, so that it can be retired.
Definition ScriptableProcessComponent.hpp:114
std::shared_ptr< bool > alive
Checked by lambdas still queued on the event loop.
Definition ScriptableProcessComponent.hpp:119
virtual void write(const ossia::value &)
Applies a value as if the parameter had received it.
Definition ScriptableProcessComponent.hpp:128
Definition ScriptableProcessComponent.cpp:95
Definition ScriptableProcessComponent.cpp:78
Definition ScriptableProcessComponent.hpp:58
std::function< void(ossia::net::node_base &)> retire
The execution may still hold the parameter, so the device owner frees the node.
Definition ScriptableProcessComponent.hpp:64
std::function< ControlWrites(Recall)> writes
Edit when unset.
Definition ScriptableProcessComponent.hpp:81
std::function< void(Process::ControlInlet &, const ossia::value &)> played
Called when a value reached the execution only.
Definition ScriptableProcessComponent.hpp:87
std::function< ossia::net::node_base *(ossia::net::node_base &, const std::string &)> revive
Restores a node retired during the current run, keeping the execution's parameter valid.
Definition ScriptableProcessComponent.hpp:70
ScriptableTreeBase * tree
Notifies when playback ends.
Definition ScriptableProcessComponent.hpp:78
std::function< void(Process::ControlInlet &, const ossia::value &)> recorded
Called with the previous value before a control changes while recording.
Definition ScriptableProcessComponent.hpp:84
std::function< void(ossia::net::node_base &)> hide
Hides a node while its address still resolves.
Definition ScriptableProcessComponent.hpp:67
std::function< void(QObject &)> referrer
An object that may hold namespace addresses; registering twice is harmless.
Definition ScriptableProcessComponent.hpp:75
Definition ScriptableProcessComponent.hpp:299
QString kind
"node", "impulse" or "value"
Definition ScriptableProcessComponent.hpp:300
Copy of the namespace for scripts on other threads, rebuilt on the GUI thread.
Definition ScriptableProcessComponent.hpp:297
ossia::hash_map< QString, Entry > entries
Keyed by "<root>" for a root and "<root>/<path>" below it.
Definition ScriptableProcessComponent.hpp:305
Definition ObjectMatches.hpp:6
Definition DocumentContext.hpp:18