From a450610deaf85de19d87557413fd9264ef0d51b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Sun, 5 May 2024 11:04:40 -0400 Subject: [PATCH] [oscquery] Add a mode to force use of webscockets and add oscquery_tcp to ossia max --- 3rdparty/libremidi | 2 +- src/ossia-max/src/device.cpp | 61 +++++++++++++++++++ src/ossia-max/src/device.hpp | 9 +++ .../oscquery/oscquery_server_asio.cpp | 6 +- .../oscquery/oscquery_server_asio.hpp | 5 +- 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/3rdparty/libremidi b/3rdparty/libremidi index c82825cbedd..e24c5439fe9 160000 --- a/3rdparty/libremidi +++ b/3rdparty/libremidi @@ -1 +1 @@ -Subproject commit c82825cbedd94e5b7723b988d18e9fdb1b466db6 +Subproject commit e24c5439fe95075da6157dedccc3d0d8bba8ba25 diff --git a/src/ossia-max/src/device.cpp b/src/ossia-max/src/device.cpp index 791ba1aaf3a..6a7749a49b3 100644 --- a/src/ossia-max/src/device.cpp +++ b/src/ossia-max/src/device.cpp @@ -12,11 +12,14 @@ #include #include +#include #include #include #include #include #include +#include +#include #include @@ -101,6 +104,13 @@ void device::class_setup(t_class* c) c, "savebi", 0, "onoff", "Save bi parameters when snapshotting presets"); } +void device::asio_timer(device* x) +{ + x->network_context->context.poll(); + x->network_context->context.reset(); + clock_delay(x->network_poll_clock, 10); +} + void* device::create(t_symbol*, long argc, t_atom* argv) { auto x = make_ossia(); @@ -142,6 +152,10 @@ void* device::create(t_symbol*, long argc, t_atom* argv) // process attr args, if any attr_args_process(x, argc - attrstart, argv + attrstart); + x->network_context = std::make_shared(); + x->network_poll_clock = clock_new(x, (method)asio_timer); + clock_delay(x->network_poll_clock, 10); + auto local_proto_ptr = std::make_unique(); x->m_device = std::make_shared( @@ -193,6 +207,10 @@ void device::destroy(device* x) #endif } + clock_free((t_object*)x->network_poll_clock); + x->network_poll_clock = nullptr; + x->network_context.reset(); + x->disconnect_slots(); on_device_removing(x); @@ -346,6 +364,49 @@ void device::expose(device* x, t_symbol*, long argc, t_atom* argv) A_SETLONG(a, connected ? 1 : 0); outlet_anything(x->m_dumpout, gensym("expose"), 4, a); } + else if(protocol == "oscquery_tcp") + { + protocol_settings::oscquery settings{}; + + argc--; + argv++; + + if(argc == 2 && argv[0].a_type == A_LONG && argv[1].a_type == A_LONG) + { + settings.oscport = atom_getlong(argv++); + settings.wsport = atom_getlong(argv++); + } + + bool connected = true; + + t_atom a[4]; + A_SETSYM(a + 1, gensym("oscquery_tcp")); + A_SETLONG(a + 2, settings.oscport); + A_SETLONG(a + 3, settings.wsport); + + try + { + auto oscq_proto + = std::make_unique( + x->network_context, settings.oscport, settings.wsport, true); + x->m_device->set_echo(true); + + A_SETSYM(a + 1, gensym("oscquery_tcp")); + A_SETLONG(a + 2, oscq_proto->get_osc_port()); + A_SETLONG(a + 3, oscq_proto->get_ws_port()); + + multiplex.expose_to(std::move(oscq_proto)); + } + catch(const std::exception& e) + { + connected = false; + object_error((t_object*)x, "can't connect, port might be already in use"); + object_error((t_object*)x, "libossia error: '%s'", e.what()); + } + + A_SETLONG(a, connected ? 1 : 0); + outlet_anything(x->m_dumpout, gensym("expose"), 4, a); + } else if(protocol == "osc") { protocol_settings::osc settings{}; diff --git a/src/ossia-max/src/device.hpp b/src/ossia-max/src/device.hpp index f2ce690e3ba..10d3c3f9837 100644 --- a/src/ossia-max/src/device.hpp +++ b/src/ossia-max/src/device.hpp @@ -4,6 +4,11 @@ #include +namespace ossia::net +{ +struct network_context; +using network_context_ptr = std::shared_ptr; +} namespace ossia { namespace max_binding @@ -12,6 +17,8 @@ namespace max_binding class device : public device_base { public: + ossia::net::network_context_ptr network_context; + void* network_poll_clock{}; using is_device = std::true_type; static void register_children(device*); @@ -32,6 +39,8 @@ class device : public device_base static void* create(t_symbol*, long, t_atom*); static void destroy(ossia::max_binding::device*); static void class_setup(t_class* c); + + static void asio_timer(device* x); }; namespace protocol_settings diff --git a/src/ossia/protocols/oscquery/oscquery_server_asio.cpp b/src/ossia/protocols/oscquery/oscquery_server_asio.cpp index 7bb5f967e45..771cc36fc49 100644 --- a/src/ossia/protocols/oscquery/oscquery_server_asio.cpp +++ b/src/ossia/protocols/oscquery/oscquery_server_asio.cpp @@ -58,7 +58,8 @@ is_same(const oscquery_client& clt, const ossia::net::message_origin_identifier& } oscquery_server_protocol::oscquery_server_protocol( - ossia::net::network_context_ptr ctx, uint16_t osc_port, uint16_t ws_port) + ossia::net::network_context_ptr ctx, uint16_t osc_port, uint16_t ws_port, + bool forceWS) : protocol_base{flags{SupportsMultiplex}} , m_context{std::move(ctx)} , m_oscServer{std::make_unique( @@ -67,6 +68,7 @@ oscquery_server_protocol::oscquery_server_protocol( m_context->context)} , m_oscPort{osc_port} , m_wsPort{ws_port} + , m_forceWS{forceWS} { m_clients.reserve(2); m_websocketServer->set_open_handler( @@ -187,7 +189,7 @@ bool oscquery_server_protocol::push_impl(const T& addr, const ossia::value& v) if(val.valid()) { // Push to all clients - auto critical = addr.get_critical(); + auto critical = m_forceWS || addr.get_critical(); if(!critical) { lock_t lock(m_clientsMutex); diff --git a/src/ossia/protocols/oscquery/oscquery_server_asio.hpp b/src/ossia/protocols/oscquery/oscquery_server_asio.hpp index 627770d9d69..5feabb8d9f9 100644 --- a/src/ossia/protocols/oscquery/oscquery_server_asio.hpp +++ b/src/ossia/protocols/oscquery/oscquery_server_asio.hpp @@ -52,7 +52,7 @@ class OSSIA_EXPORT oscquery_server_protocol final : public ossia::net::protocol_ using connection_handler = std::weak_ptr; oscquery_server_protocol( ossia::net::network_context_ptr ctx, uint16_t osc_port = 1234, - uint16_t ws_port = 5678); + uint16_t ws_port = 5678, bool forceWS = false); ~oscquery_server_protocol() override; bool pull(net::parameter_base&) override; @@ -140,6 +140,9 @@ class OSSIA_EXPORT oscquery_server_protocol final : public ossia::net::protocol_ // The local ports uint16_t m_oscPort{}; uint16_t m_wsPort{}; + + // Will only send changes through WS + bool m_forceWS{}; }; } }