OSSIA
Open Scenario System for Interactive Application
oscquery_mirror.hpp
1 #pragma once
2 
3 #include <ossia/detail/json_fwd.hpp>
4 #include <ossia/detail/lockfree_queue.hpp>
5 #include <ossia/network/base/listening.hpp>
6 #include <ossia/network/base/protocol.hpp>
7 #include <ossia/network/oscquery/host_info.hpp>
8 
9 #include <atomic>
10 
11 namespace osc
12 {
13 template <typename T>
14 class sender;
15 class receiver;
16 }
17 
18 namespace oscpack
19 {
20 class ReceivedMessage;
21 class IpEndpointName;
22 }
23 
24 namespace ossia
25 {
26 namespace net
27 {
28 struct parameter_data;
29 class websocket_client;
30 }
31 namespace oscquery
32 {
33 struct osc_outbound_visitor;
34 struct http_client_context;
35 struct http_responder;
36 
37 class OSSIA_EXPORT oscquery_mirror_protocol final : public ossia::net::protocol_base
38 {
39 public:
40  oscquery_mirror_protocol(std::string host, uint16_t local_osc_port = 10203);
41  ~oscquery_mirror_protocol() override;
42 
43  bool pull(net::parameter_base&) override;
44  std::future<void> pull_async(net::parameter_base&) override;
45  void request(net::parameter_base&) override;
46  bool push(const net::parameter_base&, const ossia::value& v) override;
47  bool push_raw(const ossia::net::full_parameter_data& parameter_base) override;
48  bool push_bundle(const std::vector<const ossia::net::parameter_base*>&) override;
49  bool push_raw_bundle(const std::vector<ossia::net::full_parameter_data>&) override;
50  bool observe(net::parameter_base&, bool) override;
51  bool observe_quietly(net::parameter_base&, bool) override;
52  bool update(net::node_base& b) override;
53  bool echo_incoming_message(
54  const ossia::net::message_origin_identifier& id,
55  const ossia::net::parameter_base& addr, const value& val) override;
56 
57  std::future<void> update_async(net::node_base& b) override;
58 
59  void stop() override;
60  void set_device(net::device_base& dev) override;
61  ossia::net::device_base& get_device() const { return *m_device; }
62 
76  void run_commands();
77 
86  void set_command_callback(std::function<void()>);
87 
93  void request_add_node(net::node_base&, const ossia::net::parameter_data&);
94 
99  void request_remove_node(net::node_base&);
100 
105  void request_rename_node(net::node_base& node, const std::string& new_name);
106 
112  void set_zombie_on_remove(bool zombie_on_remove)
113  {
114  m_zombie_on_remove = zombie_on_remove;
115  }
116 
121  bool get_zombie_on_remove() const noexcept { return m_zombie_on_remove; }
122 
123  host_info get_host_info() const noexcept;
124 
125  bool connected() const noexcept override { return m_hasWS; }
126  void connect() override;
127 
128 private:
129  friend struct http_answer;
130 
131  void init();
132  using connection_handler = std::weak_ptr<void>;
133  bool on_WSMessage(connection_handler hdl, const std::string& message);
134  bool on_BinaryWSMessage(connection_handler hdl, const std::string& message);
135  void
136  on_OSCMessage(const oscpack::ReceivedMessage& m, const oscpack::IpEndpointName& ip);
137 
138  void cleanup_connections();
139 
140  void http_send_message(const std::string& str);
141  void http_send_message(const rapidjson::StringBuffer& str);
142 
143  void ws_send_message(const std::string& str);
144  void ws_send_binary_message(const std::string& str);
145  void ws_send_message(const rapidjson::StringBuffer& str);
146  bool query_connected();
147  void query_stop();
148 
149  void on_nodeRenamed(const ossia::net::node_base& n, std::string oldname);
150 
151  void start_http();
152 
153  void on_ws_disconnected() { m_hasWS = false; }
154 
155  std::unique_ptr<osc::sender<oscquery::osc_outbound_visitor>> m_oscSender;
156  std::unique_ptr<osc::receiver> m_oscServer;
157  std::unique_ptr<ossia::net::websocket_client> m_websocketClient;
158  std::atomic_bool m_hasWS{};
159 
160  // Listening status of the local software
161  net::listened_parameters m_listening;
162 
163  ossia::net::device_base* m_device{};
164 
165  std::promise<void> m_namespacePromise;
166 
167  struct get_osc_promise
168  {
169  std::promise<void> promise;
170  ossia::net::parameter_base* address{};
171  };
172  struct get_ws_promise
173  {
174  get_ws_promise() = default;
175  get_ws_promise(const get_ws_promise&) = delete;
176  get_ws_promise(get_ws_promise&&) noexcept = default;
177  get_ws_promise& operator=(const get_ws_promise&) = delete;
178  get_ws_promise& operator=(get_ws_promise&&) noexcept = default;
179 
180  get_ws_promise(std::promise<void>&& p, const std::string& addr)
181  : promise{std::move(p)}
182  , address{addr}
183  {
184  }
185  std::promise<void> promise;
186  std::string address{};
187  };
188 
189  ossia::spsc_queue<get_ws_promise> m_getWSPromises;
190  ossia::spsc_queue<std::function<void()>> m_functionQueue;
191  std::function<void()> m_commandCallback;
192 
193  std::thread m_wsThread;
194  std::string m_queryHost;
195  std::string m_queryPort;
196  std::string m_httpHost;
197  int m_osc_port{};
198 
199  std::unique_ptr<http_client_context> m_http;
200  host_info m_host_info;
201  mutable std::mutex m_host_info_mutex;
202 
203  ossia::net::message_origin_identifier m_id;
204 
205  bool m_zombie_on_remove{true};
206 };
207 
209 OSSIA_EXPORT void load_oscquery_device(ossia::net::device_base& dev, std::string json);
210 }
211 }
Root of a device tree.
Definition: ossia/network/base/device.hpp:58
The node_base class.
Definition: network/base/node.hpp:48
The parameter_base class.
Definition: ossia/network/base/parameter.hpp:48
The protocol_base class.
Definition: protocol.hpp:40
The value class.
Definition: value.hpp:173
Definition: git_info.h:7
Full information about a parameter.
Definition: parameter_data.hpp:61
The data that can be found inside a parameter.
Definition: parameter_data.hpp:21