2#include <ossia/network/context.hpp>
3#include <ossia/network/sockets/udp_socket.hpp>
5#include <ossia-qt/protocols/utils.hpp>
11#include <nano_observer.hpp>
19struct qml_udp_inbound_state
21 ossia::net::udp_receive_socket socket;
22 std::atomic_bool alive{
true};
23 ossia::net::encoding enc{ossia::net::encoding::none};
25 qml_udp_inbound_state(
26 const ossia::net::inbound_socket_configuration& conf,
27 boost::asio::io_context& ctx,
28 ossia::net::encoding e = ossia::net::encoding::none)
35class qml_udp_inbound_socket;
39class qml_udp_sender :
public QObject
41 W_OBJECT(qml_udp_sender)
43 explicit qml_udp_sender(QObject* parent =
nullptr)
48 QString host()
const {
return m_host; }
49 W_PROPERTY(QString, host READ host)
51 int port()
const {
return m_port; }
52 W_PROPERTY(
int, port READ port)
54 void reply(QByteArray data)
56 if(!m_state || !m_state->alive)
59 if(st->enc != ossia::net::encoding::none)
60 data = apply_encoding(st->enc, data);
62 boost::asio::dispatch(st->socket.m_context, [st, ep, data] {
65 boost::system::error_code ec;
66 st->socket.m_socket.send_to(
67 boost::asio::const_buffer(data.data(), data.size()), ep, 0, ec);
74 friend class qml_udp_inbound_socket;
75 boost::asio::ip::udp::endpoint m_endpoint;
76 std::shared_ptr<qml_udp_inbound_state> m_state;
81class qml_udp_inbound_socket
83 ,
public Nano::Observer
85 W_OBJECT(qml_udp_inbound_socket)
87 using state = qml_udp_inbound_state;
89 qml_udp_inbound_socket()
91 QQmlEngine::setObjectOwnership(&m_sender, QQmlEngine::CppOwnership);
94 ~qml_udp_inbound_socket()
98 m_state->alive =
false;
103 bool isOpen() const noexcept {
return m_state !=
nullptr; }
106 const ossia::net::inbound_socket_configuration& conf,
107 boost::asio::io_context& ctx,
108 ossia::net::encoding e = ossia::net::encoding::none)
110 m_state = std::make_shared<state>(conf, ctx, e);
112 if(onClose.isCallable())
113 m_state->socket.on_close.connect<&qml_udp_inbound_socket::on_close>(*this);
115 m_state->socket.open();
116 if(onOpen.isCallable())
117 onOpen.call({qjsEngine(
this)->newQObject(
this)});
120 auto self = QPointer{
this};
121 st->socket.receive([st, self](
const char* data, std::size_t sz) {
126 auto sender_ep = st->socket.m_endpoint;
127 ossia::qt::run_async(
129 [self, st, arg = apply_decoding(st->enc, data, sz), sender_ep] {
135 if(self->m_sender.m_endpoint != sender_ep)
137 self->m_sender.m_endpoint = sender_ep;
138 self->m_sender.m_host
139 = QString::fromStdString(sender_ep.address().to_string());
140 self->m_sender.m_port = sender_ep.port();
142 self->m_sender.m_state = st;
144 if(self->onMessage.isCallable())
146 auto engine = qjsEngine(self.get());
148 self->onMessage.call(
149 {engine->toScriptValue(arg), engine->newQObject(&self->m_sender)});
158 if(!m_state || !m_state->alive)
160 ossia::qt::run_async(
this, [=,
this] { onClose.call(); }, Qt::AutoConnection);
167 if(!m_state->socket.m_socket.is_open())
170 boost::asio::post(st->socket.m_context, [st] {
173 st->socket.m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
178 st->socket.m_socket.close();
179 st->socket.on_close();
190 std::shared_ptr<state> m_state;
191 qml_udp_sender m_sender{
this};
Definition qml_device.cpp:43