From 2a1aded43a864ce00ad16195d21d22bb55d1dd4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Wed, 21 Feb 2024 10:01:00 -0500 Subject: [PATCH] [dmx] Refactor common behaviour across a base class --- .../protocols/artnet/artnet_protocol.cpp | 48 +-------- .../protocols/artnet/artnet_protocol.hpp | 28 +---- .../protocols/artnet/dmx_protocol_base.cpp | 67 ++++++++++++ .../protocols/artnet/dmx_protocol_base.hpp | 45 ++++++++ .../protocols/artnet/dmxusbpro_protocol.cpp | 101 ++++++------------ .../protocols/artnet/dmxusbpro_protocol.hpp | 29 +---- src/ossia/protocols/artnet/e131_protocol.cpp | 61 ++--------- src/ossia/protocols/artnet/e131_protocol.hpp | 45 ++++---- src/ossia/protocols/midi/midi_node.cpp | 1 - src/ossia_sources.cmake | 2 + 10 files changed, 180 insertions(+), 247 deletions(-) create mode 100644 src/ossia/protocols/artnet/dmx_protocol_base.cpp create mode 100644 src/ossia/protocols/artnet/dmx_protocol_base.hpp diff --git a/src/ossia/protocols/artnet/artnet_protocol.cpp b/src/ossia/protocols/artnet/artnet_protocol.cpp index 40b849b936c..de1dfe2fcdf 100644 --- a/src/ossia/protocols/artnet/artnet_protocol.cpp +++ b/src/ossia/protocols/artnet/artnet_protocol.cpp @@ -25,10 +25,7 @@ dmx_buffer::~dmx_buffer() = default; static constexpr int artnet_port_id = 0; artnet_protocol::artnet_protocol( ossia::net::network_context_ptr ctx, const dmx_config& conf) - : protocol_base{flags{}} - , m_context{ctx} - , m_timer{ctx->context} - , m_conf{conf} + : dmx_protocol_base{ctx, conf} { if(conf.frequency < 1 || conf.frequency > 44) throw std::runtime_error("DMX 512 update frequency must be in the range [1, 44] Hz"); @@ -60,56 +57,17 @@ artnet_protocol::artnet_protocol( artnet_protocol::~artnet_protocol() { - m_timer.stop(); + stop_processing(); artnet_destroy(m_node); } void artnet_protocol::set_device(ossia::net::device_base& dev) { - m_device = &dev; - - if(m_conf.autocreate != m_conf.no_auto) - { - auto& root = dev.get_root_node(); - for(unsigned int i = 0; i < DMX_CHANNEL_COUNT; ++i) - { - auto name = m_conf.autocreate == m_conf.channel_index - ? fmt::format("Channel-{}", i + 1) - : std::to_string(i + 1); - - device_parameter::create_device_parameter( - root, name, 0, m_buffer, i); - } - } + dmx_protocol_base::set_device(dev); m_timer.start([this] { this->update_function(); }); } -bool artnet_protocol::pull(net::parameter_base& param) -{ - return true; -} - -bool artnet_protocol::push(const net::parameter_base& param, const ossia::value& v) -{ - return true; -} - -bool artnet_protocol::observe(net::parameter_base& param, bool enable) -{ - return false; -} - -bool artnet_protocol::push_raw(const ossia::net::full_parameter_data& data) -{ - return false; -} - -bool artnet_protocol::update(ossia::net::node_base&) -{ - return true; -} - void artnet_protocol::update_function() { if(m_buffer.dirty) diff --git a/src/ossia/protocols/artnet/artnet_protocol.hpp b/src/ossia/protocols/artnet/artnet_protocol.hpp index ddbdd0102c8..e95661b68ab 100644 --- a/src/ossia/protocols/artnet/artnet_protocol.hpp +++ b/src/ossia/protocols/artnet/artnet_protocol.hpp @@ -1,22 +1,14 @@ #pragma once #include #if defined(OSSIA_PROTOCOL_ARTNET) -#include -#include -#include -#include -#include -#include - -#include -#include +#include using artnet_node = void*; namespace ossia::net { struct dmx_config; -class OSSIA_EXPORT artnet_protocol final : public ossia::net::protocol_base +class OSSIA_EXPORT artnet_protocol final : public dmx_protocol_base { public: artnet_protocol(ossia::net::network_context_ptr, const dmx_config& conf); @@ -24,26 +16,10 @@ class OSSIA_EXPORT artnet_protocol final : public ossia::net::protocol_base void set_device(ossia::net::device_base& dev) override; - bool pull(ossia::net::parameter_base& param) override; - bool push(const ossia::net::parameter_base& param, const ossia::value& v) override; - bool push_raw(const ossia::net::full_parameter_data&) override; - bool observe(ossia::net::parameter_base& param, bool enable) override; - - bool update(ossia::net::node_base&) override; - - dmx_buffer& buffer() noexcept { return m_buffer; } - private: void update_function(); - ossia::net::network_context_ptr m_context; - - ossia::timer m_timer; - dmx_buffer m_buffer; - - ossia::net::device_base* m_device{}; artnet_node m_node; - dmx_config m_conf{}; }; } diff --git a/src/ossia/protocols/artnet/dmx_protocol_base.cpp b/src/ossia/protocols/artnet/dmx_protocol_base.cpp new file mode 100644 index 00000000000..e27d3d157b4 --- /dev/null +++ b/src/ossia/protocols/artnet/dmx_protocol_base.cpp @@ -0,0 +1,67 @@ +#include "dmx_protocol_base.hpp" + +#include +#include + +namespace ossia::net +{ + +dmx_protocol_base::dmx_protocol_base( + ossia::net::network_context_ptr ctx, const dmx_config& conf) + : protocol_base{flags{}} + , m_context{ctx} + , m_timer{ctx->context} + , m_conf{conf} +{ +} + +dmx_protocol_base::~dmx_protocol_base() { } +bool dmx_protocol_base::pull(net::parameter_base& param) +{ + return true; +} + +bool dmx_protocol_base::push(const net::parameter_base& param, const ossia::value& v) +{ + return true; +} + +bool dmx_protocol_base::observe(net::parameter_base& param, bool enable) +{ + return false; +} + +bool dmx_protocol_base::push_raw(const ossia::net::full_parameter_data& data) +{ + return false; +} + +bool dmx_protocol_base::update(ossia::net::node_base&) +{ + return true; +} + +void dmx_protocol_base::stop_processing() +{ + m_timer.stop(); +} + +void dmx_protocol_base::set_device(ossia::net::device_base& dev) +{ + m_device = &dev; + + if(m_conf.autocreate != m_conf.no_auto) + { + auto& root = dev.get_root_node(); + for(unsigned int i = 0; i < DMX_CHANNEL_COUNT; ++i) + { + auto name = m_conf.autocreate == m_conf.channel_index + ? fmt::format("Channel-{}", i + 1) + : std::to_string(i + 1); + + device_parameter::create_device_parameter( + root, name, 0, m_buffer, i); + } + } +} +} diff --git a/src/ossia/protocols/artnet/dmx_protocol_base.hpp b/src/ossia/protocols/artnet/dmx_protocol_base.hpp new file mode 100644 index 00000000000..c08a95e82c4 --- /dev/null +++ b/src/ossia/protocols/artnet/dmx_protocol_base.hpp @@ -0,0 +1,45 @@ +#pragma once +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace ossia::net +{ +struct dmx_config; +class OSSIA_EXPORT dmx_protocol_base : public ossia::net::protocol_base +{ +public: + dmx_protocol_base(ossia::net::network_context_ptr, const dmx_config& conf); + ~dmx_protocol_base(); + + void set_device(ossia::net::device_base& dev) override; + + bool pull(ossia::net::parameter_base& param) override; + bool push(const ossia::net::parameter_base& param, const ossia::value& v) override; + bool push_raw(const ossia::net::full_parameter_data&) override; + bool observe(ossia::net::parameter_base& param, bool enable) override; + + bool update(ossia::net::node_base&) override; + + dmx_buffer& buffer() noexcept { return m_buffer; } + void stop_processing(); + +protected: + ossia::net::network_context_ptr m_context; + + ossia::timer m_timer; + dmx_buffer m_buffer; + + ossia::net::device_base* m_device{}; + dmx_config m_conf{}; +}; + +} diff --git a/src/ossia/protocols/artnet/dmxusbpro_protocol.cpp b/src/ossia/protocols/artnet/dmxusbpro_protocol.cpp index b2573b119e9..c8b2236a7e3 100644 --- a/src/ossia/protocols/artnet/dmxusbpro_protocol.cpp +++ b/src/ossia/protocols/artnet/dmxusbpro_protocol.cpp @@ -7,27 +7,23 @@ namespace ossia::net dmxusbpro_protocol::dmxusbpro_protocol( ossia::net::network_context_ptr ctx, const dmx_config& conf, const ossia::net::serial_configuration& socket) - : protocol_base{flags{}} - , m_context{ctx} - , m_timer{ctx->context} + : dmx_protocol_base{ctx, conf} , m_port{ctx->context} - , m_conf{conf} { if(conf.frequency < 1 || conf.frequency > 44) throw std::runtime_error("DMX 512 update frequency must be in the range [1, 44] Hz"); { - auto& m_conf = socket; using proto = boost::asio::serial_port; - m_port.open(m_conf.port); + m_port.open(socket.port); - m_port.set_option(proto::baud_rate(m_conf.baud_rate)); - m_port.set_option(proto::character_size(m_conf.character_size)); + m_port.set_option(proto::baud_rate(socket.baud_rate)); + m_port.set_option(proto::character_size(socket.character_size)); m_port.set_option(proto::flow_control( - static_cast(m_conf.flow_control))); - m_port.set_option(proto::parity(static_cast(m_conf.parity))); + static_cast(socket.flow_control))); + m_port.set_option(proto::parity(static_cast(socket.parity))); m_port.set_option( - proto::stop_bits(static_cast(m_conf.stop_bits))); + proto::stop_bits(static_cast(socket.stop_bits))); } m_timer.set_delay(std::chrono::milliseconds{ @@ -36,83 +32,46 @@ dmxusbpro_protocol::dmxusbpro_protocol( dmxusbpro_protocol::~dmxusbpro_protocol() { - m_timer.stop(); + stop_processing(); } void dmxusbpro_protocol::set_device(ossia::net::device_base& dev) { - m_device = &dev; - - if(m_conf.autocreate) - { - auto& root = dev.get_root_node(); - for(unsigned int i = 0; i < 512; ++i) - device_parameter::create_device_parameter( - root, fmt::format("{}", i + 1), 0, m_buffer, i); - } - + dmx_protocol_base::set_device(dev); m_timer.start([this] { this->update_function(); }); } -bool dmxusbpro_protocol::pull(net::parameter_base& param) -{ - return true; -} - -bool dmxusbpro_protocol::push(const net::parameter_base& param, const ossia::value& v) -{ - return true; -} - -bool dmxusbpro_protocol::observe(net::parameter_base& param, bool enable) -{ - return false; -} - -bool dmxusbpro_protocol::push_raw(const ossia::net::full_parameter_data& data) -{ - return false; -} - -bool dmxusbpro_protocol::update(ossia::net::node_base&) -{ - return true; -} - void dmxusbpro_protocol::update_function() { try { - if(true || m_buffer.dirty) - { - // https://cdn.enttec.com/pdf/assets/70304/70304_DMX_USB_PRO_API.pdf - // 1: 0x7E - // 1: message code (0x6 for DMX send) - // 1: size LSB - // 1: size MSB - // N: message data: [ - // 1: start code (0x0 for DMX) - // N-1: DMX channels - // ] - // 1: 0xE7 + // https://cdn.enttec.com/pdf/assets/70304/70304_DMX_USB_PRO_API.pdf + // 1: 0x7E + // 1: message code (0x6 for DMX send) + // 1: size LSB + // 1: size MSB + // N: message data: [ + // 1: start code (0x0 for DMX) + // N-1: DMX channels + // ] + // 1: 0xE7 - constexpr uint32_t channels = 512; - constexpr uint32_t data_size = channels + 1; - constexpr uint32_t buffer_size = 4 + data_size + 1; + constexpr uint32_t channels = 512; + constexpr uint32_t data_size = channels + 1; + constexpr uint32_t buffer_size = 4 + data_size + 1; - constexpr uint8_t data_size_lsb = data_size & 0x00FF; - constexpr uint8_t data_size_msb = (data_size & 0xFF00) >> 8; + constexpr uint8_t data_size_lsb = data_size & 0x00FF; + constexpr uint8_t data_size_msb = (data_size & 0xFF00) >> 8; - unsigned char buf[buffer_size]{0x7E, 0x6, data_size_lsb, data_size_msb, 0}; + unsigned char buf[buffer_size]{0x7E, 0x6, data_size_lsb, data_size_msb, 0}; - for(uint32_t i = 0; i < channels; i++) - buf[5 + i] = m_buffer.data[i]; - buf[buffer_size - 1] = 0xE7; + for(uint32_t i = 0; i < channels; i++) + buf[5 + i] = m_buffer.data[i]; + buf[buffer_size - 1] = 0xE7; - boost::asio::write(m_port, boost::asio::buffer(buf)); + boost::asio::write(m_port, boost::asio::buffer(buf)); - m_buffer.dirty = false; - } + m_buffer.dirty = false; } catch(std::exception& e) { diff --git a/src/ossia/protocols/artnet/dmxusbpro_protocol.hpp b/src/ossia/protocols/artnet/dmxusbpro_protocol.hpp index ad07053a6ea..a79ac970348 100644 --- a/src/ossia/protocols/artnet/dmxusbpro_protocol.hpp +++ b/src/ossia/protocols/artnet/dmxusbpro_protocol.hpp @@ -2,22 +2,14 @@ #include #if defined(OSSIA_PROTOCOL_ARTNET) -#include -#include -#include -#include -#include #include -#include +#include #include -#include -#include - namespace ossia::net { -class OSSIA_EXPORT dmxusbpro_protocol final : public ossia::net::protocol_base +class OSSIA_EXPORT dmxusbpro_protocol final : public dmx_protocol_base { public: dmxusbpro_protocol( @@ -28,27 +20,10 @@ class OSSIA_EXPORT dmxusbpro_protocol final : public ossia::net::protocol_base void set_device(ossia::net::device_base& dev) override; - bool pull(ossia::net::parameter_base& param) override; - bool push(const ossia::net::parameter_base& param, const ossia::value& v) override; - bool push_raw(const ossia::net::full_parameter_data&) override; - bool observe(ossia::net::parameter_base& param, bool enable) override; - - bool update(ossia::net::node_base&) override; - - dmx_buffer& buffer() noexcept { return m_buffer; } - private: void update_function(); - ossia::net::network_context_ptr m_context; - - ossia::timer m_timer; - dmx_buffer m_buffer; - - ossia::net::device_base* m_device{}; - boost::asio::serial_port m_port; - dmx_config m_conf{}; }; } #endif diff --git a/src/ossia/protocols/artnet/e131_protocol.cpp b/src/ossia/protocols/artnet/e131_protocol.cpp index 3cba6fb0544..a0ab6e6c9ef 100644 --- a/src/ossia/protocols/artnet/e131_protocol.cpp +++ b/src/ossia/protocols/artnet/e131_protocol.cpp @@ -83,11 +83,8 @@ e131_host(const dmx_config& conf, const ossia::net::socket_configuration& socket e131_protocol::e131_protocol( ossia::net::network_context_ptr ctx, const dmx_config& conf, const ossia::net::socket_configuration& socket) - : protocol_base{flags{}} - , m_context{ctx} - , m_timer{ctx->context} + : dmx_protocol_base{ctx, conf} , m_socket{e131_host(conf, socket), socket.port, ctx->context} - , m_conf{conf} { if(conf.frequency < 1 || conf.frequency > 44) throw std::runtime_error("DMX 512 update frequency must be in the range [1, 44] Hz"); @@ -106,49 +103,15 @@ e131_protocol::e131_protocol( e131_protocol::~e131_protocol() { - m_timer.stop(); + stop_processing(); } void e131_protocol::set_device(ossia::net::device_base& dev) { - m_device = &dev; - - if(m_conf.autocreate) - { - auto& root = dev.get_root_node(); - for(unsigned int i = 0; i < DMX_CHANNEL_COUNT; ++i) - device_parameter::create_device_parameter( - root, fmt::format("{}", i + 1), 0, m_buffer, i); - } - + dmx_protocol_base::set_device(dev); m_timer.start([this] { this->update_function(); }); } -bool e131_protocol::pull(net::parameter_base& param) -{ - return true; -} - -bool e131_protocol::push(const net::parameter_base& param, const ossia::value& v) -{ - return true; -} - -bool e131_protocol::observe(net::parameter_base& param, bool enable) -{ - return false; -} - -bool e131_protocol::push_raw(const ossia::net::full_parameter_data& data) -{ - return false; -} - -bool e131_protocol::update(ossia::net::node_base&) -{ - return true; -} - /* Initialize an E1.31 packet using a universe and a number of slots */ static int e131_pkt_init(e131_packet* packet, const uint16_t universe, const uint16_t num_slots) @@ -216,20 +179,16 @@ void e131_protocol::update_function() static std::atomic_int seq = 0; try { - if(true || m_buffer.dirty) - { - e131_packet pkt; - e131_pkt_init(&pkt, this->m_conf.universe, 512); + e131_packet pkt; + e131_pkt_init(&pkt, this->m_conf.universe, 512); - for(size_t pos = 0; pos < 512; pos++) - pkt.dmp.prop_val[pos + 1] = m_buffer.data[pos]; - pkt.frame.seq_number = seq; + for(size_t pos = 0; pos < 512; pos++) + pkt.dmp.prop_val[pos + 1] = m_buffer.data[pos]; + pkt.frame.seq_number = seq.fetch_add(1, std::memory_order_relaxed); - m_socket.write(reinterpret_cast(&pkt), sizeof(pkt)); + m_socket.write(reinterpret_cast(&pkt), sizeof(pkt)); - seq++; - m_buffer.dirty = false; - } + m_buffer.dirty = false; } catch(std::exception& e) { diff --git a/src/ossia/protocols/artnet/e131_protocol.hpp b/src/ossia/protocols/artnet/e131_protocol.hpp index 76ae5ed9585..91615bb1576 100644 --- a/src/ossia/protocols/artnet/e131_protocol.hpp +++ b/src/ossia/protocols/artnet/e131_protocol.hpp @@ -2,22 +2,14 @@ #pragma once #include #if defined(OSSIA_PROTOCOL_ARTNET) -#include -#include -#include -#include -#include #include -#include - -#include -#include +#include namespace ossia::net { // Implementation mostly based on https://github.com/hhromic/libe131 -class OSSIA_EXPORT e131_protocol final : public ossia::net::protocol_base +class OSSIA_EXPORT e131_protocol final : public ossia::net::dmx_protocol_base { public: static constexpr uint16_t default_port = 5568; @@ -31,28 +23,29 @@ class OSSIA_EXPORT e131_protocol final : public ossia::net::protocol_base void set_device(ossia::net::device_base& dev) override; - bool pull(ossia::net::parameter_base& param) override; - bool push(const ossia::net::parameter_base& param, const ossia::value& v) override; - bool push_raw(const ossia::net::full_parameter_data&) override; - bool observe(ossia::net::parameter_base& param, bool enable) override; - - bool update(ossia::net::node_base&) override; - - dmx_buffer& buffer() noexcept { return m_buffer; } - private: void update_function(); + ossia::net::udp_send_socket m_socket; +}; - ossia::net::network_context_ptr m_context; +class OSSIA_EXPORT e131_input_protocol final : public ossia::net::dmx_protocol_base +{ +public: + static constexpr uint16_t default_port = 5568; + static constexpr uint8_t default_priority = 100; - ossia::timer m_timer; - dmx_buffer m_buffer; + e131_input_protocol( + ossia::net::network_context_ptr, const dmx_config& conf, + const ossia::net::socket_configuration& socket); - ossia::net::device_base* m_device{}; + ~e131_input_protocol(); - ossia::net::udp_send_socket m_socket; - dmx_config m_conf{}; -}; + void set_device(ossia::net::device_base& dev) override; +private: + void update_function(); + + ossia::net::udp_receive_socket m_socket; +}; } #endif diff --git a/src/ossia/protocols/midi/midi_node.cpp b/src/ossia/protocols/midi/midi_node.cpp index 5ef9b377796..944b077897f 100644 --- a/src/ossia/protocols/midi/midi_node.cpp +++ b/src/ossia/protocols/midi/midi_node.cpp @@ -56,7 +56,6 @@ node_base& midi_node::set_name(std::string) { return *this; } - parameter_base* midi_node::get_parameter() const { return m_parameter.get(); diff --git a/src/ossia_sources.cmake b/src/ossia_sources.cmake index 64c1f02483e..fa65a7616b4 100644 --- a/src/ossia_sources.cmake +++ b/src/ossia_sources.cmake @@ -520,6 +520,7 @@ set(OSSIA_WIIMOTE_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/wiimote/wiimote_protocol.cpp") set(OSSIA_ARTNET_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/dmx_protocol_base.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/dmx_parameter.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/dmx_buffer.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/e131_protocol.hpp" @@ -528,6 +529,7 @@ set(OSSIA_ARTNET_HEADERS ) set(OSSIA_ARTNET_SRCS + "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/dmx_protocol_base.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/dmx_parameter.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/e131_protocol.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ossia/protocols/artnet/dmxusbpro_protocol.cpp"