OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
wrapped_parameter.hpp
1#pragma once
2#include <ossia/network/base/osc_address.hpp>
3#include <ossia/network/base/protocol.hpp>
4#include <ossia/network/generic/generic_parameter.hpp>
5
6namespace ossia::net
7{
8
9template <typename T, typename Parameter_T>
10class wrapped_node : public ossia::net::node_base
11{
13 ossia::net::node_base* m_parent{};
14 std::unique_ptr<Parameter_T> m_parameter;
15
16public:
17 using data_type = T;
18 wrapped_node(
19 T&& data, ossia::net::device_base& aDevice, ossia::net::node_base& aParent)
20 : m_device{aDevice}
21 , m_parent{&aParent}
22 {
23 m_name = data.name;
24 m_extended = data.extended;
25 m_oscAddressCache = ossia::net::osc_parameter_string(*this);
26 if(data.valid())
27 m_parameter.reset(new Parameter_T(std::move(data), *this));
28 }
29
30 wrapped_node(T&& data, ossia::net::device_base& aDevice)
31 : m_device{aDevice}
32 {
33 m_name = data.name;
34 m_extended = data.extended;
35 m_oscAddressCache = ossia::net::osc_parameter_string(*this);
36 if(data.valid())
37 m_parameter.reset(new Parameter_T(std::move(data), *this));
38 }
39
40 ~wrapped_node() override { clear(); }
41
42 void clear()
43 {
45
46 write_lock_t lock{m_mutex};
47 m_children.clear();
48 m_parameter.reset();
49 }
50
51 device_base& get_device() const final override { return m_device; }
52
53 node_base* get_parent() const final override { return m_parent; }
54
55 node_base& set_name(std::string) final override { return *this; }
56
57 parameter_base* get_parameter() const final override { return m_parameter.get(); }
58
59 parameter_base* create_parameter(val_type type = val_type::IMPULSE) final override
60 {
61 // Same contract as generic_node: creating a parameter on a node that
62 // already has one only retypes it.
63 if(m_parameter)
64 {
65 m_parameter->set_value_type(type);
66 return m_parameter.get();
67 }
68
69 // The protocols using this downcast every parameter to Parameter_T
70 // unchecked, so one created through the generic API must be one too.
71 T data{m_name};
72 data.type = type;
73 data.value = ossia::init_value(type);
74 m_parameter = std::make_unique<Parameter_T>(std::move(data), *this);
75
76 m_device.on_parameter_created(*m_parameter);
77 return m_parameter.get();
78 }
79
80 bool remove_parameter() final override { return false; }
81
82 void add_child(std::unique_ptr<ossia::net::node_base> p)
83 {
84 if(p)
85 {
86 write_lock_t lock{m_mutex};
87 m_children.push_back(std::move(p));
88 }
89 }
90
91private:
92 std::unique_ptr<node_base> make_child(const std::string& name) final override
93 {
94 // Must be a wrapped_node: serial, http, websocket and score's mapper
95 // static_cast their nodes back unchecked. Returning a generic_node here -
96 // as this used to - gave Device.addNode() a generic_parameter for those
97 // casts to reinterpret.
98 return std::make_unique<wrapped_node>(T{name}, m_device, *this);
99 }
100
101 void removing_child(node_base& node_base) final override { }
102};
103
104template <typename T>
105class wrapped_parameter : public ossia::net::generic_parameter
106{
107public:
108 using base_data_type = typename T::base_data_type;
109
110 wrapped_parameter(T&& data, ossia::net::node_base& node_base)
111 : generic_parameter{data, node_base}
112 , m_data(std::move(data))
113 {
114 }
115
116 wrapped_parameter() = delete;
117 wrapped_parameter(const wrapped_parameter& other) = delete;
118 wrapped_parameter(wrapped_parameter&& other) = delete;
119 wrapped_parameter& operator=(const wrapped_parameter& other) = delete;
120 wrapped_parameter& operator=(wrapped_parameter&& other) = delete;
122
123 const base_data_type& data() const { return m_data; }
124
125 base_data_type& data() { return m_data; }
126
127private:
128 base_data_type m_data;
129};
130
131template <typename Node_T, typename Protocol_T>
132class wrapped_device final
134 , public Node_T
135{
136public:
137 wrapped_device() = delete;
138 wrapped_device(const wrapped_device&) = delete;
139 wrapped_device(wrapped_device&&) = delete;
140 wrapped_device& operator=(const wrapped_device&) = delete;
141 wrapped_device& operator=(wrapped_device&&) = delete;
142
143 wrapped_device(std::unique_ptr<Protocol_T> protocol_base, std::string name)
144 : device_base(std::move(protocol_base))
145 , Node_T{typename Node_T::data_type{name}, *this}
146 {
147 m_capabilities.change_tree = true;
148 m_protocol->set_device(*this);
149 }
150
151 const ossia::net::node_base& get_root_node() const override { return *this; }
152 ossia::net::node_base& get_root_node() override { return *this; }
153
154 using Node_T::get_name;
155 using Node_T::set_name;
156
157 ~wrapped_device()
158 {
159 m_protocol->stop();
160
161 this->remove_parameter();
162
163 {
164 write_lock_t lock{this->m_mutex};
165 this->m_children.clear();
166 }
167
168 // Parameters, etc of the device's own node must also be cleared
169 // before removing the protocol:
170 Node_T::clear();
171
172 m_protocol.reset();
173 }
174};
175}
void callbacks_clear()
clear Clears callbacks.
Definition callback_container.hpp:203
Root of a device tree.
Definition ossia/network/base/device.hpp:58
Definition generic_parameter.hpp:24
generic_parameter(ossia::net::node_base &node_base)
Used for repetition filter.
Definition generic_parameter.cpp:28
The node_base class.
Definition node.hpp:48
Nano::Signal< void(const node_base &)> about_to_be_deleted
The node subclasses must call this in their destructor.
Definition node.hpp:204
node_base * add_child(std::unique_ptr< node_base >)
Adds a new child if it can be added.
Definition node.cpp:140
val_type
Enum to represent the types that a value can take.
Definition parameter_properties.hpp:16
@ IMPULSE
array<float, 4>
bool change_tree
change_tree : nodes can be added and removed externally.
Definition ossia/network/base/device.hpp:24