OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
qml_udp_inbound_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{
17class qml_udp_inbound_socket
18 : public QObject
19 , public Nano::Observer
20{
21 W_OBJECT(qml_udp_inbound_socket)
22public:
23 struct state
24 {
25 ossia::net::udp_receive_socket socket;
26 std::atomic_bool alive{true};
27
28 state(
29 const ossia::net::inbound_socket_configuration& conf,
30 boost::asio::io_context& ctx)
31 : socket{conf, ctx}
32 {
33 }
34 };
35
36 qml_udp_inbound_socket() { }
37
38 ~qml_udp_inbound_socket()
39 {
40 if(m_state)
41 {
42 m_state->alive = false;
43 close();
44 }
45 }
46
47 bool isOpen() const noexcept { return m_state != nullptr; }
48
49 void open(
50 const ossia::net::inbound_socket_configuration& conf,
51 boost::asio::io_context& ctx)
52 {
53 m_state = std::make_shared<state>(conf, ctx);
54
55 if(onClose.isCallable())
56 m_state->socket.on_close.connect<&qml_udp_inbound_socket::on_close>(*this);
57
58 m_state->socket.open();
59 if(onOpen.isCallable())
60 onOpen.call({qjsEngine(this)->newQObject(this)});
61
62 auto st = m_state;
63 auto self = QPointer{this};
64 st->socket.receive([st, self](const char* data, std::size_t sz) {
65 if(!st->alive)
66 return;
67 ossia::qt::run_async(
68 self.get(),
69 [self, arg = QByteArray(data, sz)] {
70 if(!self.get())
71 return;
72 if(self->onMessage.isCallable())
73 {
74 self->onMessage.call({qjsEngine(self.get())->toScriptValue(arg)});
75 }
76 },
77 Qt::AutoConnection);
78 });
79 }
80
81 void on_close()
82 {
83 if(!m_state || !m_state->alive)
84 return;
85 ossia::qt::run_async(this, [=, this] { onClose.call(); }, Qt::AutoConnection);
86 }
87
88 void close()
89 {
90 if(!m_state)
91 return;
92 if(!m_state->socket.m_socket.is_open())
93 return;
94 auto st = m_state;
95 boost::asio::post(st->socket.m_context, [st] {
96 try
97 {
98 st->socket.m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
99 }
100 catch(...)
101 {
102 }
103 st->socket.m_socket.close();
104 st->socket.on_close();
105 });
106 }
107 W_SLOT(close)
108
109 QJSValue onOpen;
110 QJSValue onClose;
111 QJSValue onError;
112 QJSValue onMessage;
113
114private:
115 std::shared_ptr<state> m_state;
116};
117
118}
Definition qml_device.cpp:43