OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
qml_unix_outbound_socket.hpp
1#pragma once
2#include <ossia/network/context.hpp>
3#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
4#include <ossia/network/sockets/unix_socket.hpp>
5
6#include <ossia-qt/protocols/utils.hpp>
7
8#include <QJSValue>
9#include <QObject>
10#include <QQmlEngine>
11
12#include <nano_observer.hpp>
13
14#include <verdigris>
15
16namespace ossia::qt
17{
18class qml_unix_datagram_outbound_socket
19 : public QObject
20 , public Nano::Observer
21 , public protocols_sender
22{
23 W_OBJECT(qml_unix_datagram_outbound_socket)
24public:
25 struct state
26 {
27 ossia::net::unix_datagram_socket socket;
28 std::atomic_bool alive{true};
29
30 state(const ossia::net::fd_configuration& conf, boost::asio::io_context& ctx)
31 : socket{conf, ctx}
32 {
33 }
34 };
35
36private:
37 std::shared_ptr<state> m_state;
38
39public:
40 ossia::net::unix_datagram_socket& socket;
41
42 qml_unix_datagram_outbound_socket(
43 const ossia::net::fd_configuration& conf, boost::asio::io_context& ctx)
44 : m_state{std::make_shared<state>(conf, ctx)}
45 , socket{m_state->socket}
46 {
47 }
48
49 ~qml_unix_datagram_outbound_socket() { m_state->alive = false; }
50
51 inline boost::asio::io_context& context() noexcept { return m_state->socket.m_context; }
52
53 void open()
54 {
55 if(onClose.isCallable())
56 m_state->socket.on_close.connect<&qml_unix_datagram_outbound_socket::on_close>(this);
57
58 m_state->socket.connect();
59
60 if(onOpen.isCallable())
61
62 onOpen.call({qjsEngine(this)->newQObject(this)});
63 }
64
65 void close() { m_state->socket.close(); }
66 W_SLOT(close)
67
68 void on_close()
69 {
70 if(!m_state->alive)
71 return;
72 ossia::qt::run_async(this, [=, this] { onClose.call(); }, Qt::AutoConnection);
73 }
74
75 void write(QByteArray buffer)
76 {
77 auto st = m_state;
78 boost::asio::dispatch(st->socket.m_context, [st, buffer] {
79 if(st->alive)
80 st->socket.write(buffer.data(), buffer.size());
81 });
82 }
83 W_SLOT(write)
84
85 void osc(QByteArray address, QJSValueList values) { this->send_osc(address, values); }
86 W_SLOT(osc)
87
88 QJSValue onOpen;
89 QJSValue onClose;
90 QJSValue onError;
91};
92
93class qml_unix_stream_outbound_socket
94 : public QObject
95 , public Nano::Observer
96 , public protocols_sender
97{
98 W_OBJECT(qml_unix_stream_outbound_socket)
99public:
100 struct state
101 {
102 ossia::net::unix_stream_client socket;
103 std::atomic_bool alive{true};
104
105 state(const ossia::net::fd_configuration& conf, boost::asio::io_context& ctx)
106 : socket{conf, ctx}
107 {
108 }
109 };
110
111private:
112 std::shared_ptr<state> m_state;
113
114public:
115 ossia::net::unix_stream_client& socket;
116
117 qml_unix_stream_outbound_socket(
118 const ossia::net::fd_configuration& conf, boost::asio::io_context& ctx)
119 : m_state{std::make_shared<state>(conf, ctx)}
120 , socket{m_state->socket}
121 {
122 }
123
124 ~qml_unix_stream_outbound_socket() { m_state->alive = false; }
125
126 inline boost::asio::io_context& context() noexcept { return m_state->socket.m_context; }
127
128 void open()
129 {
130 try
131 {
132 if(onOpen.isCallable())
133 m_state->socket.on_open.connect<&qml_unix_stream_outbound_socket::on_open>(this);
134 if(onClose.isCallable())
135 m_state->socket.on_close.connect<&qml_unix_stream_outbound_socket::on_close>(this);
136 if(onError.isCallable())
137 m_state->socket.on_fail.connect<&qml_unix_stream_outbound_socket::on_fail>(this);
138 m_state->socket.connect();
139 }
140 catch(const std::exception& e)
141 {
142 if(onError.isCallable())
143 {
144 onError.call({QString::fromStdString(e.what())});
145 }
146 }
147 }
148
149 void write(QByteArray buffer)
150 {
151 auto st = m_state;
152 boost::asio::dispatch(st->socket.m_context, [st, buffer] {
153 if(st->alive)
154 st->socket.write(buffer.data(), buffer.size());
155 });
156 }
157 W_SLOT(write)
158
159 void close() { m_state->socket.close(); }
160 W_SLOT(close)
161
162 void on_open()
163 {
164 if(!m_state->alive)
165 return;
166 ossia::qt::run_async(
167 this, [=, this] { onOpen.call({qjsEngine(this)->newQObject(this)}); },
168 Qt::AutoConnection);
169 }
170 void on_fail()
171 {
172 if(!m_state->alive)
173 return;
174 ossia::qt::run_async(this, [=, this] { onError.call(); }, Qt::AutoConnection);
175 }
176 void on_close()
177 {
178 if(!m_state->alive)
179 return;
180 ossia::qt::run_async(this, [=, this] { onClose.call(); }, Qt::AutoConnection);
181 }
182
183 void osc(QByteArray address, QJSValueList values) { this->send_osc(address, values); }
184 W_SLOT(osc)
185
186 QJSValue onOpen;
187 QJSValue onClose;
188 QJSValue onError;
189};
190
191}
192#endif
Definition qml_device.cpp:43