OSSIA
Open Scenario System for Interactive Application
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 
12 namespace ossia
13 {
14 
15 struct 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 
74 struct init_node_visitor
75 {
76  inlet& in;
77  const graph_edge& edge;
78  execution_state& e;
79 
80  static void 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  copy_data_pos{pos}(
89  *reinterpret_cast<const ossia::audio_delay_line*>(out.target()),
90  in.cast<ossia::audio_port>());
91  break;
92  case delay_line_type::index_of<ossia::midi_delay_line>().index():
93  copy_data_pos{pos}(
94  *reinterpret_cast<const ossia::midi_delay_line*>(out.target()),
95  in.cast<ossia::midi_port>());
96  break;
97  case delay_line_type::index_of<ossia::value_delay_line>().index():
98  copy_data_pos{pos}(
99  *reinterpret_cast<const ossia::value_delay_line*>(out.target()),
100  in.cast<ossia::value_port>());
101  break;
102  case delay_line_type::index_of<ossia::geometry_delay_line>().index():
103  copy_data_pos{pos}(
104  *reinterpret_cast<const ossia::geometry_delay_line*>(out.target()),
105  in.cast<ossia::geometry_port>());
106  break;
107  }
108  }
109  }
110 
111  static void move(outlet& out, inlet& in)
112  {
113  const auto w = out.which();
114  if(w == in.which())
115  {
116  switch(w)
117  {
118  case ossia::audio_port::which:
119  move_data{}(out.cast<ossia::audio_port>(), in.cast<ossia::audio_port>());
120  break;
121  case ossia::midi_port::which:
122  move_data{}(out.cast<ossia::midi_port>(), in.cast<ossia::midi_port>());
123  break;
124  case ossia::value_port::which:
125  move_data{}(out.cast<ossia::value_port>(), in.cast<ossia::value_port>());
126  break;
127  case ossia::geometry_port::which:
128  move_data{}(out.cast<ossia::geometry_port>(), in.cast<ossia::geometry_port>());
129  break;
130  }
131  }
132  }
133  static void copy(outlet& out, inlet& in)
134  {
135  if(out.cables().size() == 1 && in.cables().size() == 1 && !out.address
136  && !in.address)
137  {
138  move(out, in);
139  }
140  else
141  {
142  const auto w = out.which();
143  if(w == in.which())
144  {
145  switch(w)
146  {
147  case ossia::audio_port::which:
148  copy_data{}(out.cast<ossia::audio_port>(), in.cast<ossia::audio_port>());
149  break;
150  case ossia::midi_port::which:
151  copy_data{}(out.cast<ossia::midi_port>(), in.cast<ossia::midi_port>());
152  break;
153  case ossia::value_port::which:
154  copy_data{}(out.cast<ossia::value_port>(), in.cast<ossia::value_port>());
155  break;
156  case ossia::geometry_port::which:
157  copy_data{}(
158  out.cast<ossia::geometry_port>(), in.cast<ossia::geometry_port>());
159  break;
160  }
161  }
162  }
163  }
164 
165  bool operator()(immediate_glutton_connection) const
166  {
167  if(edge.out_node->enabled())
168  {
169  copy(*edge.out, in);
170  return false;
171  }
172  else
173  {
174  // todo delay, etc
175  return true;
176  }
177  }
178 
179  bool operator()(immediate_strict_connection) const
180  {
181  // if it's a strict connection then the other node
182  // is necessarily enabled
183  copy(*edge.out, in);
184  return false;
185  }
186 
187  bool operator()(delayed_glutton_connection& con) const
188  {
189  // TODO If there is data...
190  // Else...
191  copy(con.buffer, con.pos, in);
192  con.pos++;
193  return false;
194  }
195 
196  bool operator()(delayed_strict_connection& con) const
197  {
198  copy(con.buffer, con.pos, in);
199  con.pos++;
200  return false;
201  }
202 
203  bool operator()(dependency_connection) const { return true; }
204 
205  bool operator()() const { return true; }
206 };
207 struct init_must_copy_visitor
208 {
209  const graph_edge& edge;
210 
211  bool operator()(const immediate_glutton_connection&) const
212  {
213  return !edge.out_node->enabled();
214  }
215 
216  bool operator()(const immediate_strict_connection&) const { return false; }
217 
218  bool operator()(const delayed_glutton_connection&) const { return false; }
219 
220  bool operator()(const delayed_strict_connection&) const { return false; }
221 
222  bool operator()(const dependency_connection&) const { return true; }
223 
224  bool operator()() const { return true; }
225 };
226 
227 struct env_writer
228 {
229  outlet& out;
230  graph_edge& edge;
231  bool operator()(const immediate_glutton_connection&) const
232  {
233  return !edge.in_node->enabled();
234  }
235  bool operator()(const immediate_strict_connection& con) const
236  {
237  using rs = immediate_strict_connection::required_sides_t;
238  switch(con.required_sides)
239  {
240  case rs::inbound:
241  case rs::outbound:
242  // TODO
243  break;
244  default:
245  case rs::both:
246  // Nothing to do : copied on "input" phase if the node is active,
247  // or no need to copy if the node isn't
248  break;
249  }
250  return false;
251  }
252  bool operator()(delayed_glutton_connection& con) const
253  {
254  // Copy to the buffer
255  const auto con_w = con.buffer.which();
256  const auto out_w = out.which();
257  if(con_w.to_std_index() == out_w)
258  {
259  switch(con_w.index())
260  {
261  case delay_line_type::index_of<ossia::audio_delay_line>().index():
262  copy_data{}(
263  out.cast<ossia::audio_port>(),
264  *reinterpret_cast<ossia::audio_delay_line*>(con.buffer.target()));
265  break;
266  case delay_line_type::index_of<ossia::midi_delay_line>().index():
267  copy_data{}(
268  out.cast<ossia::midi_port>(),
269  *reinterpret_cast<ossia::midi_delay_line*>(con.buffer.target()));
270  break;
271  case delay_line_type::index_of<ossia::value_delay_line>().index():
272  copy_data{}(
273  out.cast<ossia::value_port>(),
274  *reinterpret_cast<ossia::value_delay_line*>(con.buffer.target()));
275  break;
276  }
277  }
278  return false;
279  }
280  bool operator()(delayed_strict_connection& con) const
281  {
282  // Copy to the buffer
283  const auto con_w = con.buffer.which();
284  const auto out_w = out.which();
285  if(con_w.to_std_index() == out_w)
286  {
287  switch(con_w.index())
288  {
289  case delay_line_type::index_of<ossia::audio_delay_line>().index():
290  copy_data{}(
291  out.cast<ossia::audio_port>(),
292  *reinterpret_cast<ossia::audio_delay_line*>(con.buffer.target()));
293  break;
294  case delay_line_type::index_of<ossia::midi_delay_line>().index():
295  copy_data{}(
296  out.cast<ossia::midi_port>(),
297  *reinterpret_cast<ossia::midi_delay_line*>(con.buffer.target()));
298  break;
299  case delay_line_type::index_of<ossia::value_delay_line>().index():
300  copy_data{}(
301  out.cast<ossia::value_port>(),
302  *reinterpret_cast<ossia::value_delay_line*>(con.buffer.target()));
303  break;
304  }
305  }
306  return false;
307  }
308  bool operator()(const dependency_connection&) const { return false; }
309  bool operator()() const { return false; }
310 };
311 }
Definition: git_info.h:7