OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
qml_udp_outbound_socket.hpp
1#pragma once
2#include <ossia/network/context.hpp>
3#include <ossia/network/sockets/udp_socket.hpp>
4
5#include <ossia-qt/protocols/utils.hpp>
6
7#include <QJSValue>
8#include <QObject>
9#include <QQmlEngine>
10
11#include <nano_observer.hpp>
12
13#include <verdigris>
14
15namespace ossia::qt
16{
17
18class qml_udp_outbound_socket
19 : public QObject
20 , public Nano::Observer
21 , public protocols_sender
22{
23 W_OBJECT(qml_udp_outbound_socket)
24public:
25 struct state
26 {
27 ossia::net::udp_send_socket socket;
28 std::atomic_bool alive{true};
29
30 state(
31 const ossia::net::outbound_socket_configuration& conf,
32 boost::asio::io_context& ctx)
33 : socket{conf, ctx}
34 {
35 }
36 };
37
38 ossia::net::udp_send_socket* socket = nullptr;
39
40 qml_udp_outbound_socket() { }
41
42 ~qml_udp_outbound_socket()
43 {
44 if(m_state)
45 {
46 m_state->alive = false;
47 close();
48 }
49 }
50
51 bool isOpen() const noexcept { return m_state != nullptr; }
52
53 void open(
54 const ossia::net::outbound_socket_configuration& conf,
55 boost::asio::io_context& ctx)
56 {
57 m_state = std::make_shared<state>(conf, ctx);
58 socket = &m_state->socket;
59
60 if(onClose.isCallable())
61 m_state->socket.on_close.connect<&qml_udp_outbound_socket::on_close>(*this);
62
63 m_state->socket.connect();
64
65 if(onOpen.isCallable())
66 onOpen.call({qjsEngine(this)->newQObject(this)});
67 }
68
69 void close()
70 {
71 if(!m_state)
72 return;
73 if(!m_state->socket.m_socket.is_open())
74 return;
75 auto st = m_state;
76 boost::asio::post(st->socket.m_context, [st] {
77 try
78 {
79 st->socket.m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
80 }
81 catch(...)
82 {
83 }
84 st->socket.m_socket.close();
85 st->socket.on_close();
86 });
87 }
88 W_SLOT(close)
89
90 void on_close()
91 {
92 if(!m_state || !m_state->alive)
93 return;
94 ossia::qt::run_async(this, [=, this] { onClose.call(); }, Qt::AutoConnection);
95 }
96
97 void write(QByteArray buffer)
98 {
99 if(!m_state)
100 return;
101 auto st = m_state;
102 boost::asio::dispatch(st->socket.m_context, [st, buffer] {
103 if(st->alive)
104 st->socket.write(buffer.data(), buffer.size());
105 });
106 }
107 W_SLOT(write)
108
109 void osc(QByteArray address, QJSValueList values)
110 {
111 if(socket)
112 this->send_osc(address, values);
113 }
114 W_SLOT(osc)
115
116 QJSValue onOpen;
117 QJSValue onClose;
118 QJSValue onError;
119
120private:
121 std::shared_ptr<state> m_state;
122};
123}
Definition qml_device.cpp:43