OSSIA
Open Scenario System for Interactive Application
scenario.hpp
1 #pragma once
2 #include <ossia/detail/config.hpp>
3 
4 #include <ossia/dataflow/graph/small_graph.hpp>
5 #include <ossia/detail/flat_map.hpp>
6 #include <ossia/detail/flat_set.hpp>
7 #include <ossia/detail/pod_vector.hpp>
9 #include <ossia/detail/ptr_set.hpp>
10 #include <ossia/detail/small_vector.hpp>
13 
14 #include <boost/graph/adjacency_list.hpp>
15 
16 #include <ankerl/unordered_dense.h>
17 
18 namespace ossia
19 {
20 class time_event;
21 class time_interval;
22 class time_sync;
23 using interval_set = ossia::flat_set<time_interval*>;
24 using sync_set = ossia::flat_set<time_sync*>;
25 using small_sync_vec = ossia::small_vector<time_sync*, 4>;
26 using small_event_vec = std::vector<time_event*>;
27 struct overtick
28 {
31  ossia::time_value offset;
32 };
33 using overtick_map = ossia::flat_map<time_sync*, overtick>;
34 
35 class scenario;
36 using scenario_graph_vertex = time_sync*;
37 using scenario_graph_edge = time_interval*;
38 
39 using scenario_graph_t = boost::adjacency_list<
40  boost::smallvecS, boost::smallvecS, boost::undirectedS, scenario_graph_vertex,
41  scenario_graph_edge>;
42 
43 inline void
44 remove_vertex(typename scenario_graph_t::vertex_descriptor v, scenario_graph_t& g)
45 {
46  typedef typename scenario_graph_t::directed_category Cat;
47  g.removing_vertex(v, boost::graph_detail::iterator_stability(g.m_vertices));
48  boost::detail::remove_vertex_dispatch(g, v, Cat());
49 }
50 
51 /*
52 template <typename T, typename V>
53 using dense_ptr_map = ankerl::unordered_dense::map<
54  T, V, EgurHash<std::remove_pointer_t<T>>, std::equal_to<T>,
55  ossia::small_vector<std::pair<T, V>, 1024>>;
56 struct scenario_graph
57 {
58  scenario& scenar;
59 
60  scenario_graph(scenario& sc);
61 
62  void add_vertice(scenario_graph_vertex timeSync);
63  void add_edge(scenario_graph_edge itv);
64  void remove_vertice(scenario_graph_vertex timeSync);
65  void remove_edge(scenario_graph_edge itv);
66 
67  void reset_component(ossia::time_sync& sync) const;
68 
69 private:
70  void recompute_maps();
71  void update_components_cache() const;
72  scenario_graph_t graph;
73  mutable ossia::int_vector m_components_cache;
74  mutable bool dirty = false;
75  ossia::dense_ptr_map<const time_sync*, scenario_graph_t::vertex_descriptor> vertices;
76  ossia::dense_ptr_map<const time_interval*, scenario_graph_t::edge_descriptor> edges;
77 
78  std::vector<std::shared_ptr<ossia::time_sync>> to_disable_sync;
79  std::vector<std::shared_ptr<ossia::time_interval>> to_disable_itv;
80 }; */
81 
82 class OSSIA_EXPORT scenario final : public looping_process<scenario>
83 {
84  friend class looping_process<scenario>;
85 
86 public:
87  scenario();
88  ~scenario() override;
89 
94  void add_time_interval(std::shared_ptr<time_interval>);
95 
99  void remove_time_interval(const std::shared_ptr<time_interval>&);
100 
103  void add_time_sync(std::shared_ptr<time_sync>);
104 
107  void remove_time_sync(const std::shared_ptr<time_sync>&);
108 
111  const std::shared_ptr<time_sync>& get_start_time_sync() const;
112 
115  const ptr_container<time_sync>& get_time_syncs() const;
116 
119  const ptr_container<time_interval>& get_time_intervals() const;
120 
121  friend struct scenario_graph;
122  void offset_impl(ossia::time_value) override;
123 
124  void state_impl(const ossia::token_request& req);
125 
126  void start() override;
127  void stop() override;
128  void pause() override;
129  void resume() override;
130 
131  void transport_impl(ossia::time_value offset) override;
132  void mute_impl(bool) override;
133 
139  void request_start_interval(ossia::time_interval&, double ratio = 0.0);
145  void request_stop_interval(ossia::time_interval&, double ratio = 0.0);
146 
147  small_sync_vec get_roots() const noexcept;
148 
149  void reset_subgraph(
150  const ptr_container<time_sync>&, const ptr_container<time_interval>&,
151  time_sync& root);
152 
153  ossia::time_value last_date() const noexcept { return m_last_date; }
154 
155  void set_exclusive(bool excl) noexcept;
156  bool exclusive(bool excl) const noexcept;
157 
158 private:
159  void stop_all_intervals();
160  ossia::time_value m_last_date{ossia::Infinite};
161 
162  ptr_container<time_interval> m_intervals;
163  ptr_container<time_sync> m_nodes; // list of all TimeSyncs of the scenario
164  // (the first is the start node)
165 
166  interval_set m_runningIntervals;
167  sync_set m_waitingNodes;
168  small_sync_vec m_rootNodes;
169  small_event_vec m_pendingEvents;
170  small_event_vec m_maxReachedEvents;
171  overtick_map m_overticks; // used as cache
172  ossia::flat_map<time_interval*, time_value> m_itv_end_map;
173  sync_set m_retry_syncs; // used as cache
174  sync_set m_endNodes; // used as cache
175  // scenario_graph m_sg; // used as cache
176 
177  sync_set m_component_visit_cache;
178  std::vector<ossia::time_sync*> m_component_visit_stack;
179 
180  bool m_exclusive{};
181 
182  // Used to start intervals off-time
183  struct quantized_interval
184  {
185  ossia::time_interval* interval{};
186  double quantization_ratio{};
187  operator ossia::time_interval*() const noexcept { return interval; }
188  };
189 
190  ossia::small_vector<quantized_interval, 2> m_itv_to_start;
191  ossia::small_vector<quantized_interval, 2> m_itv_to_stop;
192 
193  static void make_happen(
194  time_event& event, interval_set& started, interval_set& stopped,
195  ossia::time_value tick_offset, const ossia::token_request& tok);
196 
197  static void make_dispose(time_event& event, interval_set& stopped);
198 
199  sync_status process_this(
200  time_sync& node, small_event_vec& pendingEvents, small_event_vec& maxReachedEvents,
201  interval_set& started, interval_set& stopped, ossia::time_value tick_offset,
202  const token_request& tok);
203 
204  sync_status trigger_sync(
205  time_sync& node, small_event_vec& pending, small_event_vec& maxReachedEv,
206  interval_set& started, interval_set& stopped, ossia::time_value tick_offset,
207  const token_request& req, bool maxReached);
208 
209  sync_status process_this_musical(
210  time_sync& node, small_event_vec& pendingEvents, small_event_vec& maxReachedEvents,
211  ossia::time_value tick_offset, const token_request& tok) noexcept;
212 
213  sync_status trigger_sync_musical(
214  time_sync& node, small_event_vec& maxReachedEvents, ossia::time_value tick_offset,
215  const token_request& req, bool maxReached) noexcept;
216 
217  sync_status
218  quantify_time_sync(time_sync& sync, const ossia::token_request& tk) noexcept;
219 
220  sync_status
221  trigger_quantified_time_sync(time_sync& sync, bool& maximalDurationReached) noexcept;
222 
223  void run_interval(
224  ossia::time_interval& interval, const ossia::token_request& tk,
225  const time_value& tick_ms, ossia::time_value tick, ossia::time_value offset);
226 
227  void stop_interval(ossia::time_interval& itv);
228  void reset_component(ossia::time_sync& n);
229  void reset_all_components_except(ossia::time_sync& n);
230 };
231 }
The time_interval class.
Definition: time_interval.hpp:49
#time_sync is use to describe temporal structure to synchronize each attached #time_event evaluation.
Definition: time_sync.hpp:103
Definition: git_info.h:7
constexpr OSSIA_INLINE auto min(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
min function tailored for values
Definition: math.hpp:125
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96
The time_value class.
Definition: ossia/editor/scenario/time_value.hpp:28