OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
graph_ordering.hpp
1#pragma once
2#include <ossia/audio/audio_parameter.hpp>
3#include <ossia/dataflow/data_copy.hpp>
4#include <ossia/dataflow/graph_edge.hpp>
5#include <ossia/dataflow/graph_node.hpp>
6#include <ossia/dataflow/port.hpp>
8#include <ossia/network/common/path.hpp>
9
10#include <boost/range/algorithm/lexicographical_compare.hpp>
11
12namespace ossia
13{
14
15struct node_sorter
16{
17 const std::vector<graph_node*>& node_order;
18 const execution_state& st;
19
20 bool compare(const graph_node* lhs, const graph_node* rhs) const
21 {
22 for(std::size_t i = 0, N = node_order.size(); i < N; i++)
23 {
24 if(node_order[i] == lhs)
25 return true;
26 else if(node_order[i] == rhs)
27 return false;
28 else
29 continue;
30 }
31 ossia_do_throw(
32 std::runtime_error, "lhs and rhs have to be found");
33 }
34
35 bool operator()(const graph_node* lhs, const graph_node* rhs) const
36 {
37 // This sorting method ensures that if for instance
38 // node A produces "/a" and node B consumes "/a",
39 // A executes before B.
40 bool c1 = lhs->has_port_inputs();
41 bool c2 = rhs->has_port_inputs();
42 if(c1 && !c2)
43 return true;
44 else if(!c1 && c2)
45 return false;
46 else if(c1 && c2)
47 // the nodes are already sorted through the toposort
48 // so we can just keep their original order
49 return compare(lhs, rhs);
50
51 bool l1 = lhs->has_local_inputs(st);
52 bool l2 = rhs->has_local_inputs(st);
53
54 if(l1 && !l2)
55 return true;
56 else if(!l1 && l2)
57 return false;
58 else if(l1 && l2)
59 return compare(lhs, rhs);
60
61 bool g1 = lhs->has_global_inputs();
62 bool g2 = rhs->has_global_inputs();
63 if(g1 && !g2)
64 return true;
65 else if(!g1 && g2)
66 return false;
67 else if(g1 && g2)
68 return compare(lhs, rhs);
69
70 return compare(lhs, rhs);
71 }
72};
73
74struct init_node_visitor
75{
76 inlet& in;
77 const graph_edge& edge;
78 execution_state& e;
79
80 static bool copy(const delay_line_type& out, std::size_t pos, inlet& in)
81 {
82 const auto w = out.which();
83 if(w.to_std_index() == in.which() && w.valid())
84 {
85 switch(w.index())
86 {
87 case delay_line_type::index_of<ossia::audio_delay_line>().index():
88 return copy_data_pos{pos}(
89 *reinterpret_cast<const ossia::audio_delay_line*>(out.target()),
90 in.cast<ossia::audio_port>());
91 case delay_line_type::index_of<ossia::midi_delay_line>().index():
92 return copy_data_pos{pos}(
93 *reinterpret_cast<const ossia::midi_delay_line*>(out.target()),
94 in.cast<ossia::midi_port>());
95 case delay_line_type::index_of<ossia::value_delay_line>().index():
96 return copy_data_pos{pos}(
97 *reinterpret_cast<const ossia::value_delay_line*>(out.target()),
98 in.cast<ossia::value_port>());
99 case delay_line_type::index_of<ossia::geometry_delay_line>().index():
100 return copy_data_pos{pos}(
101 *reinterpret_cast<const ossia::geometry_delay_line*>(out.target()),
102 in.cast<ossia::geometry_port>());
103 }
104 }
105 return false;
106 }
107
108 static void move(outlet& out, inlet& in)
109 {
110 const auto w = out.which();
111 if(w == in.which())
112 {
113 switch(w)
114 {
115 case ossia::audio_port::which:
116 move_data{}(out.cast<ossia::audio_port>(), in.cast<ossia::audio_port>());
117 break;
118 case ossia::midi_port::which:
119 move_data{}(out.cast<ossia::midi_port>(), in.cast<ossia::midi_port>());
120 break;
121 case ossia::value_port::which:
122 move_data{}(out.cast<ossia::value_port>(), in.cast<ossia::value_port>());
123 break;
124 case ossia::geometry_port::which:
125 move_data{}(out.cast<ossia::geometry_port>(), in.cast<ossia::geometry_port>());
126 break;
127 }
128 }
129 }
130 static void copy(outlet& out, inlet& in)
131 {
132 if(out.cables().size() == 1 && in.cables().size() == 1 && !out.address
133 && !in.address)
134 {
135 move(out, in);
136 }
137 else
138 {
139 const auto w = out.which();
140 if(w == in.which())
141 {
142 switch(w)
143 {
144 case ossia::audio_port::which:
145 copy_data{}(out.cast<ossia::audio_port>(), in.cast<ossia::audio_port>());
146 break;
147 case ossia::midi_port::which:
148 copy_data{}(out.cast<ossia::midi_port>(), in.cast<ossia::midi_port>());
149 break;
150 case ossia::value_port::which:
151 copy_data{}(out.cast<ossia::value_port>(), in.cast<ossia::value_port>());
152 break;
153 case ossia::geometry_port::which:
154 copy_data{}(
155 out.cast<ossia::geometry_port>(), in.cast<ossia::geometry_port>());
156 break;
157 }
158 }
159 }
160 }
161
162 bool operator()(immediate_glutton_connection) const
163 {
164 if(edge.out_node->enabled())
165 {
166 copy(*edge.out, in);
167 return false;
168 }
169 else
170 {
171 // todo delay, etc
172 return true;
173 }
174 }
175
176 bool operator()(immediate_strict_connection) const
177 {
178 // if it's a strict connection then the other node
179 // is necessarily enabled
180 copy(*edge.out, in);
181 return false;
182 }
183
184 bool operator()(delayed_glutton_connection& con) const
185 {
186 if(copy(con.buffer, con.pos, in))
187 con.pos++;
188 return false;
189 }
190
191 bool operator()(delayed_strict_connection& con) const
192 {
193 if(copy(con.buffer, con.pos, in))
194 con.pos++;
195 return false;
196 }
197
198 bool operator()(dependency_connection) const { return true; }
199
200 bool operator()() const { return true; }
201};
202struct init_must_copy_visitor
203{
204 const graph_edge& edge;
205
206 bool operator()(const immediate_glutton_connection&) const
207 {
208 return !edge.out_node->enabled();
209 }
210
211 bool operator()(const immediate_strict_connection&) const { return false; }
212
213 bool operator()(const delayed_glutton_connection&) const { return false; }
214
215 bool operator()(const delayed_strict_connection&) const { return false; }
216
217 bool operator()(const dependency_connection&) const { return true; }
218
219 bool operator()() const { return true; }
220};
221
222struct env_writer
223{
224 outlet& out;
225 graph_edge& edge;
226 bool operator()(const immediate_glutton_connection&) const
227 {
228 return !edge.in_node->enabled();
229 }
230 bool operator()(const immediate_strict_connection& con) const
231 {
232 using rs = immediate_strict_connection::required_sides_t;
233 switch(con.required_sides)
234 {
235 case rs::inbound:
236 case rs::outbound:
237 // TODO
238 break;
239 default:
240 case rs::both:
241 // Nothing to do : copied on "input" phase if the node is active,
242 // or no need to copy if the node isn't
243 break;
244 }
245 return false;
246 }
247 bool operator()(delayed_glutton_connection& con) const
248 {
249 // Copy to the buffer
250 const auto con_w = con.buffer.which();
251 const auto out_w = out.which();
252 if(con_w.to_std_index() == out_w)
253 {
254 switch(con_w.index())
255 {
256 case delay_line_type::index_of<ossia::audio_delay_line>().index():
257 copy_data{}(
258 out.cast<ossia::audio_port>(),
259 *reinterpret_cast<ossia::audio_delay_line*>(con.buffer.target()));
260 break;
261 case delay_line_type::index_of<ossia::midi_delay_line>().index():
262 copy_data{}(
263 out.cast<ossia::midi_port>(),
264 *reinterpret_cast<ossia::midi_delay_line*>(con.buffer.target()));
265 break;
266 case delay_line_type::index_of<ossia::value_delay_line>().index():
267 copy_data{}(
268 out.cast<ossia::value_port>(),
269 *reinterpret_cast<ossia::value_delay_line*>(con.buffer.target()));
270 break;
271 }
272 }
273 return false;
274 }
275 bool operator()(delayed_strict_connection& con) const
276 {
277 // Copy to the buffer
278 const auto con_w = con.buffer.which();
279 const auto out_w = out.which();
280 if(con_w.to_std_index() == out_w)
281 {
282 switch(con_w.index())
283 {
284 case delay_line_type::index_of<ossia::audio_delay_line>().index():
285 copy_data{}(
286 out.cast<ossia::audio_port>(),
287 *reinterpret_cast<ossia::audio_delay_line*>(con.buffer.target()));
288 break;
289 case delay_line_type::index_of<ossia::midi_delay_line>().index():
290 copy_data{}(
291 out.cast<ossia::midi_port>(),
292 *reinterpret_cast<ossia::midi_delay_line*>(con.buffer.target()));
293 break;
294 case delay_line_type::index_of<ossia::value_delay_line>().index():
295 copy_data{}(
296 out.cast<ossia::value_port>(),
297 *reinterpret_cast<ossia::value_delay_line*>(con.buffer.target()));
298 break;
299 }
300 }
301 return false;
302 }
303 bool operator()(const dependency_connection&) const { return false; }
304 bool operator()() const { return false; }
305};
306}
Definition git_info.h:7