diff --git a/libs/surfaces/websockets/ardour_websockets.cc b/libs/surfaces/websockets/ardour_websockets.cc index e02bd84d28..38c7849839 100644 --- a/libs/surfaces/websockets/ardour_websockets.cc +++ b/libs/surfaces/websockets/ardour_websockets.cc @@ -35,7 +35,7 @@ using namespace ArdourSurface; #include "pbd/abstract_ui.cc" // instantiate template ArdourWebsockets::ArdourWebsockets (Session& s) - : ControlProtocol (s, X_(SURFACE_NAME)) + : ControlProtocol (s, X_ (SURFACE_NAME)) , AbstractUI (name ()) , _strips (*this) , _globals (*this) @@ -43,94 +43,95 @@ ArdourWebsockets::ArdourWebsockets (Session& s) , _server (*this) , _dispatcher (*this) { - _components.push_back (&_strips); - _components.push_back (&_globals); - _components.push_back (&_server); - _components.push_back (&_feedback); - _components.push_back (&_dispatcher); + _components.push_back (&_strips); + _components.push_back (&_globals); + _components.push_back (&_server); + _components.push_back (&_feedback); + _components.push_back (&_dispatcher); } ArdourWebsockets::~ArdourWebsockets () { - stop(); + stop (); } void* ArdourWebsockets::request_factory (uint32_t num_requests) { - /* AbstractUI::request_buffer_factory() is a template method only + /* AbstractUI::request_buffer_factory() is a template method only instantiated in this source module. To provide something visible for use in the interface/descriptor, we have this static method that is template-free. */ - return request_buffer_factory (num_requests); + return request_buffer_factory (num_requests); } int ArdourWebsockets::set_active (bool yn) { - if (yn != active ()) { - if (yn) { - if (start ()) { - return -1; - } - } else { - if (stop ()) { - return -1; - } - } - } + if (yn != active ()) { + if (yn) { + if (start ()) { + return -1; + } + } else { + if (stop ()) { + return -1; + } + } + } - return ControlProtocol::set_active (yn); + return ControlProtocol::set_active (yn); } void ArdourWebsockets::thread_init () { - pthread_set_name (event_loop_name ().c_str ()); - PBD::notify_event_loops_about_thread_creation (pthread_self (), event_loop_name (), 2048); - SessionEvent::create_per_thread_pool (event_loop_name (), 128); + pthread_set_name (event_loop_name ().c_str ()); + PBD::notify_event_loops_about_thread_creation (pthread_self (), event_loop_name (), 2048); + SessionEvent::create_per_thread_pool (event_loop_name (), 128); } void ArdourWebsockets::do_request (ArdourWebsocketsUIRequest* req) { - if (req->type == CallSlot) { - call_slot (MISSING_INVALIDATOR, req->the_slot); - } else if (req->type == Quit) { - stop (); - } + if (req->type == CallSlot) { + call_slot (MISSING_INVALIDATOR, req->the_slot); + } else if (req->type == Quit) { + stop (); + } } int ArdourWebsockets::start () { - // startup the event loop thread - BaseUI::run (); + /* startup the event loop thread */ + BaseUI::run (); - for (std::vector::iterator it = _components.begin (); - it != _components.end (); ++it) { - int rc = (*it)->start (); - if (rc != 0) { - return -1; - } - } + for (std::vector::iterator it = _components.begin (); + it != _components.end (); ++it) { + int rc = (*it)->start (); + if (rc != 0) { + return -1; + } + } - PBD::info << "ArdourWebsockets: started" << endmsg; + PBD::info << "ArdourWebsockets: started" << endmsg; - return 0; + return 0; } int -ArdourWebsockets::stop () { - for (std::vector::iterator it = _components.begin (); - it != _components.end (); ++it) { - (*it)->stop (); - } +ArdourWebsockets::stop () +{ + for (std::vector::iterator it = _components.begin (); + it != _components.end (); ++it) { + (*it)->stop (); + } - BaseUI::quit (); - - PBD::info << "ArdourWebsockets: stopped" << endmsg; + BaseUI::quit (); - return 0; + PBD::info << "ArdourWebsockets: stopped" << endmsg; + + return 0; } diff --git a/libs/surfaces/websockets/ardour_websockets.h b/libs/surfaces/websockets/ardour_websockets.h index 8837cc367d..78d72c0d46 100644 --- a/libs/surfaces/websockets/ardour_websockets.h +++ b/libs/surfaces/websockets/ardour_websockets.h @@ -33,66 +33,77 @@ #include "control_protocol/control_protocol.h" #include "component.h" -#include "strips.h" +#include "dispatcher.h" +#include "feedback.h" #include "globals.h" #include "server.h" -#include "feedback.h" -#include "dispatcher.h" +#include "strips.h" -#define SURFACE_NAME "WebSockets Server (Experimental)" -#define SURFACE_ID "uri://ardour.org/surfaces/ardour_websockets:0" - -namespace ArdourSurface { +#define SURFACE_NAME "WebSockets Server (Experimental)" +#define SURFACE_ID "uri://ardour.org/surfaces/ardour_websockets:0" +namespace ArdourSurface +{ struct ArdourWebsocketsUIRequest : public BaseUI::BaseRequestObject { - public: - ArdourWebsocketsUIRequest () {} - ~ArdourWebsocketsUIRequest () {} +public: + ArdourWebsocketsUIRequest () {} + ~ArdourWebsocketsUIRequest () {} }; class ArdourWebsockets : public ARDOUR::ControlProtocol, - public AbstractUI + public AbstractUI { - public: - - ArdourWebsockets (ARDOUR::Session&); - virtual ~ArdourWebsockets (); +public: + ArdourWebsockets (ARDOUR::Session&); + virtual ~ArdourWebsockets (); - static void* request_factory (uint32_t); + static void* request_factory (uint32_t); - int set_active (bool); + int set_active (bool); - ARDOUR::Session& ardour_session () { return *session; } - ArdourStrips& strips_component () { return _strips; } - ArdourGlobals& globals_component () { return _globals; } - WebsocketsServer& server_component () { return _server; } - WebsocketsDispatcher& dispatcher_component () { return _dispatcher; } + ARDOUR::Session& ardour_session () + { + return *session; + } + ArdourStrips& strips_component () + { + return _strips; + } + ArdourGlobals& globals_component () + { + return _globals; + } + WebsocketsServer& server_component () + { + return _server; + } + WebsocketsDispatcher& dispatcher_component () + { + return _dispatcher; + } - // ControlProtocol - void stripable_selection_changed () {} + /* ControlProtocol */ + void stripable_selection_changed () {} - protected: +protected: + /* BaseUI */ + void thread_init (); - // BaseUI - void thread_init (); - - // AbstractUI - void do_request (ArdourWebsocketsUIRequest*); + /* AbstractUI */ + void do_request (ArdourWebsocketsUIRequest*); - private: - - ArdourStrips _strips; - ArdourGlobals _globals; - ArdourFeedback _feedback; - WebsocketsServer _server; - WebsocketsDispatcher _dispatcher; - std::vector _components; - - int start (); - int stop (); +private: + ArdourStrips _strips; + ArdourGlobals _globals; + ArdourFeedback _feedback; + WebsocketsServer _server; + WebsocketsDispatcher _dispatcher; + std::vector _components; + int start (); + int stop (); }; -} // namespace +} // namespace ArdourSurface #endif // ardour_websockets_h diff --git a/libs/surfaces/websockets/client.cc b/libs/surfaces/websockets/client.cc index 745596e17a..2d0668fee1 100644 --- a/libs/surfaces/websockets/client.cc +++ b/libs/surfaces/websockets/client.cc @@ -23,49 +23,49 @@ bool ClientContext::has_state (const NodeState& node_state) { - ClientState::iterator it = _state.find (node_state); + ClientState::iterator it = _state.find (node_state); - if (it == _state.end ()) { - return false; - } + if (it == _state.end ()) { + return false; + } - int n_val = node_state.n_val (); + int n_val = node_state.n_val (); - if (it->n_val () != n_val) { - return false; - } + if (it->n_val () != n_val) { + return false; + } - for (int i = 0; i < n_val; i++) { - if (it->nth_val (i) != node_state.nth_val (i)) { - return false; - } - } + for (int i = 0; i < n_val; i++) { + if (it->nth_val (i) != node_state.nth_val (i)) { + return false; + } + } - return true; + return true; } void ClientContext::update_state (const NodeState& node_state) { - ClientState::iterator it = _state.find (node_state); + ClientState::iterator it = _state.find (node_state); - if (it != _state.end ()) { - _state.erase (it); - } + if (it != _state.end ()) { + _state.erase (it); + } - _state.insert (node_state); + _state.insert (node_state); } std::string ClientContext::debug_str () { - std::stringstream ss; + std::stringstream ss; - ss << "client = " << std::hex << _wsi << std::endl; - - for (ClientState::iterator it = _state.begin (); it != _state.end (); ++it) { - ss << " - " << it->debug_str () << std::endl; - } + ss << "client = " << std::hex << _wsi << std::endl; - return ss.str (); + for (ClientState::iterator it = _state.begin (); it != _state.end (); ++it) { + ss << " - " << it->debug_str () << std::endl; + } + + return ss.str (); } diff --git a/libs/surfaces/websockets/client.h b/libs/surfaces/websockets/client.h index bf90fb5ad0..89167d9949 100644 --- a/libs/surfaces/websockets/client.h +++ b/libs/surfaces/websockets/client.h @@ -22,37 +22,41 @@ #include #include -#include "state.h" #include "message.h" +#include "state.h" -typedef struct lws* Client; +typedef struct lws* Client; typedef std::list ClientOutputBuffer; class ClientContext { - public: +public: + ClientContext (Client wsi) + : _wsi (wsi){}; + virtual ~ClientContext (){}; - ClientContext (Client wsi) : _wsi(wsi) {}; - virtual ~ClientContext () {}; + Client wsi () const + { + return _wsi; + } - Client wsi () const { return _wsi; } + bool has_state (const NodeState&); + void update_state (const NodeState&); - bool has_state (const NodeState&); - void update_state (const NodeState&); + ClientOutputBuffer& output_buf () + { + return _output_buf; + } - ClientOutputBuffer& output_buf () { return _output_buf; } - - std::string debug_str (); + std::string debug_str (); - private: +private: + Client _wsi; - Client _wsi; - - typedef boost::unordered_set ClientState; - ClientState _state; - - ClientOutputBuffer _output_buf; + typedef boost::unordered_set ClientState; + ClientState _state; + ClientOutputBuffer _output_buf; }; #endif // client_context_h diff --git a/libs/surfaces/websockets/component.cc b/libs/surfaces/websockets/component.cc index 2c1d8b9fe0..9294539697 100644 --- a/libs/surfaces/websockets/component.cc +++ b/libs/surfaces/websockets/component.cc @@ -22,41 +22,41 @@ PBD::EventLoop* SurfaceComponent::event_loop () const { - return static_cast(&_surface); + return static_cast (&_surface); } Glib::RefPtr SurfaceComponent::main_loop () const { - return _surface.main_loop (); + return _surface.main_loop (); } ARDOUR::Session& SurfaceComponent::session () const { - return _surface.ardour_session (); + return _surface.ardour_session (); } ArdourStrips& SurfaceComponent::strips () const { - return _surface.strips_component (); + return _surface.strips_component (); } ArdourGlobals& SurfaceComponent::globals () const { - return _surface.globals_component (); + return _surface.globals_component (); } WebsocketsServer& SurfaceComponent::server () const { - return _surface.server_component (); + return _surface.server_component (); } WebsocketsDispatcher& SurfaceComponent::dispatcher () const { - return _surface.dispatcher_component (); + return _surface.dispatcher_component (); } diff --git a/libs/surfaces/websockets/component.h b/libs/surfaces/websockets/component.h index 5ee3900a4c..47abc3fdf3 100644 --- a/libs/surfaces/websockets/component.h +++ b/libs/surfaces/websockets/component.h @@ -24,8 +24,9 @@ #include "ardour/session.h" #include "pbd/event_loop.h" -namespace ArdourSurface { - class ArdourWebsockets; +namespace ArdourSurface +{ +class ArdourWebsockets; } class ArdourStrips; @@ -35,27 +36,31 @@ class WebsocketsDispatcher; class SurfaceComponent { - public: +public: + SurfaceComponent (ArdourSurface::ArdourWebsockets& surface) + : _surface (surface){}; - SurfaceComponent (ArdourSurface::ArdourWebsockets& surface) : _surface (surface) {}; + virtual ~SurfaceComponent (){}; - virtual ~SurfaceComponent () {}; + virtual int start () + { + return 0; + } + virtual int stop () + { + return 0; + } - virtual int start () { return 0; } - virtual int stop () { return 0; } - - PBD::EventLoop* event_loop () const; - Glib::RefPtr main_loop() const; - ARDOUR::Session& session () const; - ArdourStrips& strips () const; - ArdourGlobals& globals () const; - WebsocketsServer& server () const; - WebsocketsDispatcher& dispatcher () const; - - protected: - - ArdourSurface::ArdourWebsockets& _surface; + PBD::EventLoop* event_loop () const; + Glib::RefPtr main_loop () const; + ARDOUR::Session& session () const; + ArdourStrips& strips () const; + ArdourGlobals& globals () const; + WebsocketsServer& server () const; + WebsocketsDispatcher& dispatcher () const; +protected: + ArdourSurface::ArdourWebsockets& _surface; }; #endif // surface_component_h diff --git a/libs/surfaces/websockets/dispatcher.cc b/libs/surfaces/websockets/dispatcher.cc index 8d612bd9b2..b497c24081 100644 --- a/libs/surfaces/websockets/dispatcher.cc +++ b/libs/surfaces/websockets/dispatcher.cc @@ -20,234 +20,233 @@ #include "ardour/plugin_insert.h" -#include "dispatcher.h" #include "ardour_websockets.h" +#include "dispatcher.h" #include "state.h" using namespace ARDOUR; -#define NODE_METHOD_PAIR(x) (Node::x, &WebsocketsDispatcher::x ## _handler) +#define NODE_METHOD_PAIR(x) (Node::x, &WebsocketsDispatcher::x##_handler) WebsocketsDispatcher::NodeMethodMap -WebsocketsDispatcher::_node_to_method = boost::assign::map_list_of - NODE_METHOD_PAIR(tempo) - NODE_METHOD_PAIR(strip_gain) - NODE_METHOD_PAIR(strip_pan) - NODE_METHOD_PAIR(strip_mute) - NODE_METHOD_PAIR(strip_plugin_enable) - NODE_METHOD_PAIR(strip_plugin_param_value) - ; + WebsocketsDispatcher::_node_to_method = boost::assign::map_list_of + NODE_METHOD_PAIR (tempo) + NODE_METHOD_PAIR (strip_gain) + NODE_METHOD_PAIR (strip_pan) + NODE_METHOD_PAIR (strip_mute) + NODE_METHOD_PAIR (strip_plugin_enable) + NODE_METHOD_PAIR (strip_plugin_param_value); void WebsocketsDispatcher::dispatch (Client client, const NodeStateMessage& msg) { - NodeMethodMap::iterator it = _node_to_method.find (msg.state ().node ()); - if (it != _node_to_method.end ()) { - try { - (this->*it->second) (client, msg); - } catch (const std::exception& e) { - std::cerr << e.what() << std::endl; - } - } + NodeMethodMap::iterator it = _node_to_method.find (msg.state ().node ()); + if (it != _node_to_method.end ()) { + try { + (this->*it->second) (client, msg); + } catch (const std::exception& e) { + std::cerr << e.what () << std::endl; + } + } } void WebsocketsDispatcher::update_all_nodes (Client client) { - update (client, Node::tempo, globals ().tempo ()); + update (client, Node::tempo, globals ().tempo ()); - for (uint32_t strip_n = 0; strip_n < strips ().strip_count (); ++strip_n) { - boost::shared_ptr strip = strips ().nth_strip (strip_n); - boost::shared_ptr route = boost::dynamic_pointer_cast (strip); - if (!route) { - continue; - } + for (uint32_t strip_n = 0; strip_n < strips ().strip_count (); ++strip_n) { + boost::shared_ptr strip = strips ().nth_strip (strip_n); + boost::shared_ptr route = boost::dynamic_pointer_cast (strip); + if (!route) { + continue; + } - update (client, Node::strip_desc, strip_n, strip->name ()); - update (client, Node::strip_gain, strip_n, strips ().strip_gain (strip_n)); - update (client, Node::strip_pan, strip_n, strips ().strip_pan (strip_n)); - update (client, Node::strip_mute, strip_n, strips ().strip_mute (strip_n)); + update (client, Node::strip_desc, strip_n, strip->name ()); + update (client, Node::strip_gain, strip_n, strips ().strip_gain (strip_n)); + update (client, Node::strip_pan, strip_n, strips ().strip_pan (strip_n)); + update (client, Node::strip_mute, strip_n, strips ().strip_mute (strip_n)); - for (uint32_t plugin_n = 0 ; ; ++plugin_n) { - boost::shared_ptr insert = strips () - .strip_plugin_insert (strip_n, plugin_n); - if (!insert) { - break; - } + for (uint32_t plugin_n = 0;; ++plugin_n) { + boost::shared_ptr insert = strips () + .strip_plugin_insert (strip_n, plugin_n); + if (!insert) { + break; + } - boost::shared_ptr plugin = insert->plugin (); - update (client, Node::strip_plugin_desc, strip_n, plugin_n, - static_cast(plugin->name ())); + boost::shared_ptr plugin = insert->plugin (); + update (client, Node::strip_plugin_desc, strip_n, plugin_n, + static_cast (plugin->name ())); - update (client, Node::strip_plugin_enable, strip_n, plugin_n, - strips ().strip_plugin_enabled (strip_n, plugin_n)); + update (client, Node::strip_plugin_enable, strip_n, plugin_n, + strips ().strip_plugin_enabled (strip_n, plugin_n)); - for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) { - boost::shared_ptr a_ctrl = - strips ().strip_plugin_param_control (strip_n, plugin_n, param_n); - if (!a_ctrl) { - continue; - } + for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) { + boost::shared_ptr a_ctrl = + strips ().strip_plugin_param_control (strip_n, plugin_n, param_n); + if (!a_ctrl) { + continue; + } - AddressVector addr = AddressVector (); - addr.push_back (strip_n); - addr.push_back (plugin_n); - addr.push_back (param_n); + AddressVector addr = AddressVector (); + addr.push_back (strip_n); + addr.push_back (plugin_n); + addr.push_back (param_n); - ValueVector val = ValueVector (); - val.push_back (a_ctrl->name ()); + ValueVector val = ValueVector (); + val.push_back (a_ctrl->name ()); - // possible flags: enumeration, integer_step, logarithmic, sr_dependent, toggled - ParameterDescriptor pd = a_ctrl->desc (); + // possible flags: enumeration, integer_step, logarithmic, sr_dependent, toggled + ParameterDescriptor pd = a_ctrl->desc (); - if (pd.toggled) { - val.push_back (std::string("b")); - } else if (pd.enumeration || pd.integer_step) { - val.push_back (std::string("i")); - val.push_back (pd.lower); - val.push_back (pd.upper); - val.push_back (pd.integer_step); - } else { - val.push_back (std::string("d")); - val.push_back (pd.lower); - val.push_back (pd.upper); - val.push_back (pd.logarithmic); - } + if (pd.toggled) { + val.push_back (std::string ("b")); + } else if (pd.enumeration || pd.integer_step) { + val.push_back (std::string ("i")); + val.push_back (pd.lower); + val.push_back (pd.upper); + val.push_back (pd.integer_step); + } else { + val.push_back (std::string ("d")); + val.push_back (pd.lower); + val.push_back (pd.upper); + val.push_back (pd.logarithmic); + } - update (client, Node::strip_plugin_param_desc, addr, val); + update (client, Node::strip_plugin_param_desc, addr, val); - TypedValue value = strips ().strip_plugin_param_value (strip_n, plugin_n, param_n); - update (client, Node::strip_plugin_param_value, strip_n, plugin_n, param_n, value); - } - } - } + TypedValue value = strips ().strip_plugin_param_value (strip_n, plugin_n, param_n); + update (client, Node::strip_plugin_param_value, strip_n, plugin_n, param_n, value); + } + } + } } void WebsocketsDispatcher::tempo_handler (Client client, const NodeStateMessage& msg) { - if (msg.is_write ()) { - globals ().set_tempo (msg.state ().nth_val (0)); - } else { - update (client, Node::tempo, globals ().tempo ()); - } + if (msg.is_write ()) { + globals ().set_tempo (msg.state ().nth_val (0)); + } else { + update (client, Node::tempo, globals ().tempo ()); + } } void WebsocketsDispatcher::strip_gain_handler (Client client, const NodeStateMessage& msg) { - uint32_t strip_id = msg.state ().nth_addr (0); + uint32_t strip_id = msg.state ().nth_addr (0); - if (msg.is_write ()) { - strips ().set_strip_gain (strip_id, msg.state ().nth_val (0)); - } else { - update (client, Node::strip_gain, strip_id, strips ().strip_gain (strip_id)); - } + if (msg.is_write ()) { + strips ().set_strip_gain (strip_id, msg.state ().nth_val (0)); + } else { + update (client, Node::strip_gain, strip_id, strips ().strip_gain (strip_id)); + } } void WebsocketsDispatcher::strip_pan_handler (Client client, const NodeStateMessage& msg) { - uint32_t strip_id = msg.state ().nth_addr (0); + uint32_t strip_id = msg.state ().nth_addr (0); - if (msg.is_write ()) { - strips ().set_strip_pan (strip_id, msg.state ().nth_val (0)); - } else { - update (client, Node::strip_pan, strip_id, strips ().strip_pan(strip_id)); - } + if (msg.is_write ()) { + strips ().set_strip_pan (strip_id, msg.state ().nth_val (0)); + } else { + update (client, Node::strip_pan, strip_id, strips ().strip_pan (strip_id)); + } } void WebsocketsDispatcher::strip_mute_handler (Client client, const NodeStateMessage& msg) { - uint32_t strip_id = msg.state ().nth_addr (0); + uint32_t strip_id = msg.state ().nth_addr (0); - if (msg.is_write ()) { - strips ().set_strip_mute (strip_id, msg.state ().nth_val (0)); - } else { - update (client, Node::strip_mute, strip_id, strips ().strip_mute (strip_id)); - } + if (msg.is_write ()) { + strips ().set_strip_mute (strip_id, msg.state ().nth_val (0)); + } else { + update (client, Node::strip_mute, strip_id, strips ().strip_mute (strip_id)); + } } void WebsocketsDispatcher::strip_plugin_enable_handler (Client client, const NodeStateMessage& msg) { - uint32_t strip_id = msg.state ().nth_addr (0); - uint32_t plugin_id = msg.state ().nth_addr (1); + uint32_t strip_id = msg.state ().nth_addr (0); + uint32_t plugin_id = msg.state ().nth_addr (1); - if (msg.is_write ()) { - strips ().set_strip_plugin_enabled (strip_id, plugin_id, msg.state ().nth_val (0)); - } else { - update (client, Node::strip_plugin_enable, strip_id, plugin_id, - strips ().strip_plugin_enabled (strip_id, plugin_id)); - } + if (msg.is_write ()) { + strips ().set_strip_plugin_enabled (strip_id, plugin_id, msg.state ().nth_val (0)); + } else { + update (client, Node::strip_plugin_enable, strip_id, plugin_id, + strips ().strip_plugin_enabled (strip_id, plugin_id)); + } } void WebsocketsDispatcher::strip_plugin_param_value_handler (Client client, const NodeStateMessage& msg) { - uint32_t strip_id = msg.state ().nth_addr (0); - uint32_t plugin_id = msg.state ().nth_addr (1); - uint32_t param_id = msg.state ().nth_addr (2); + uint32_t strip_id = msg.state ().nth_addr (0); + uint32_t plugin_id = msg.state ().nth_addr (1); + uint32_t param_id = msg.state ().nth_addr (2); - if (msg.is_write ()) { - strips ().set_strip_plugin_param_value (strip_id, plugin_id, param_id, - msg.state ().nth_val (0)); - } else { - TypedValue value = strips ().strip_plugin_param_value (strip_id, plugin_id, param_id); - update (client, Node::strip_plugin_param_value, strip_id, plugin_id, param_id, value); - } + if (msg.is_write ()) { + strips ().set_strip_plugin_param_value (strip_id, plugin_id, param_id, + msg.state ().nth_val (0)); + } else { + TypedValue value = strips ().strip_plugin_param_value (strip_id, plugin_id, param_id); + update (client, Node::strip_plugin_param_value, strip_id, plugin_id, param_id, value); + } } void WebsocketsDispatcher::update (Client client, std::string node, TypedValue val1) { - update (client, node, ADDR_NONE, ADDR_NONE, ADDR_NONE, val1); + update (client, node, ADDR_NONE, ADDR_NONE, ADDR_NONE, val1); } void WebsocketsDispatcher::update (Client client, std::string node, uint32_t strip_n, TypedValue val1) { - update (client, node, strip_n, ADDR_NONE, ADDR_NONE, val1); + update (client, node, strip_n, ADDR_NONE, ADDR_NONE, val1); } void WebsocketsDispatcher::update (Client client, std::string node, uint32_t strip_n, uint32_t plugin_n, - TypedValue val1) + TypedValue val1) { - update (client, node, strip_n, plugin_n, ADDR_NONE, val1); + update (client, node, strip_n, plugin_n, ADDR_NONE, val1); } void WebsocketsDispatcher::update (Client client, std::string node, uint32_t strip_n, uint32_t plugin_n, - uint32_t param_n, TypedValue val1) + uint32_t param_n, TypedValue val1) { - AddressVector addr = AddressVector (); + AddressVector addr = AddressVector (); - if (strip_n != ADDR_NONE) { - addr.push_back (strip_n); - } + if (strip_n != ADDR_NONE) { + addr.push_back (strip_n); + } - if (plugin_n != ADDR_NONE) { - addr.push_back (plugin_n); - } + if (plugin_n != ADDR_NONE) { + addr.push_back (plugin_n); + } - if (param_n != ADDR_NONE) { - addr.push_back (param_n); - } + if (param_n != ADDR_NONE) { + addr.push_back (param_n); + } - ValueVector val = ValueVector (); + ValueVector val = ValueVector (); - if (!val1.empty ()) { - val.push_back (val1); - } + if (!val1.empty ()) { + val.push_back (val1); + } - update (client, node, addr, val); + update (client, node, addr, val); } void WebsocketsDispatcher::update (Client client, std::string node, const AddressVector& addr, - const ValueVector& val) + const ValueVector& val) { - server ().update_client (client, NodeState (node, addr, val), true); + server ().update_client (client, NodeState (node, addr, val), true); } diff --git a/libs/surfaces/websockets/dispatcher.h b/libs/surfaces/websockets/dispatcher.h index 032f6ec9d2..23951e5771 100644 --- a/libs/surfaces/websockets/dispatcher.h +++ b/libs/surfaces/websockets/dispatcher.h @@ -21,41 +21,38 @@ #include -#include "component.h" #include "client.h" +#include "component.h" #include "message.h" class WebsocketsDispatcher : public SurfaceComponent { +public: + WebsocketsDispatcher (ArdourSurface::ArdourWebsockets& surface) + : SurfaceComponent (surface){}; + virtual ~WebsocketsDispatcher (){}; - public: + void dispatch (Client, const NodeStateMessage&); + void update_all_nodes (Client); - WebsocketsDispatcher (ArdourSurface::ArdourWebsockets& surface) : SurfaceComponent (surface) {}; - virtual ~WebsocketsDispatcher () {}; - - void dispatch (Client, const NodeStateMessage&); - void update_all_nodes (Client); +private: + typedef void (WebsocketsDispatcher::*DispatcherMethod) (Client, const NodeStateMessage&); + typedef boost::unordered_map NodeMethodMap; - private: + static NodeMethodMap _node_to_method; - typedef void (WebsocketsDispatcher::*DispatcherMethod) (Client, const NodeStateMessage&); - typedef boost::unordered_map NodeMethodMap; - - static NodeMethodMap _node_to_method; - - void tempo_handler (Client, const NodeStateMessage&); - void strip_gain_handler (Client, const NodeStateMessage&); - void strip_pan_handler (Client, const NodeStateMessage&); - void strip_mute_handler (Client, const NodeStateMessage&); - void strip_plugin_enable_handler (Client, const NodeStateMessage&); - void strip_plugin_param_value_handler (Client, const NodeStateMessage&); - - void update (Client, std::string, TypedValue); - void update (Client, std::string, uint32_t, TypedValue); - void update (Client, std::string, uint32_t, uint32_t, TypedValue); - void update (Client, std::string, uint32_t, uint32_t, uint32_t, TypedValue); - void update (Client, std::string, const AddressVector&, const ValueVector&); + void tempo_handler (Client, const NodeStateMessage&); + void strip_gain_handler (Client, const NodeStateMessage&); + void strip_pan_handler (Client, const NodeStateMessage&); + void strip_mute_handler (Client, const NodeStateMessage&); + void strip_plugin_enable_handler (Client, const NodeStateMessage&); + void strip_plugin_param_value_handler (Client, const NodeStateMessage&); + void update (Client, std::string, TypedValue); + void update (Client, std::string, uint32_t, TypedValue); + void update (Client, std::string, uint32_t, uint32_t, TypedValue); + void update (Client, std::string, uint32_t, uint32_t, uint32_t, TypedValue); + void update (Client, std::string, const AddressVector&, const ValueVector&); }; #endif // websockets_dispatcher_h diff --git a/libs/surfaces/websockets/feedback.cc b/libs/surfaces/websockets/feedback.cc index 2d09b93513..f7591fb33d 100644 --- a/libs/surfaces/websockets/feedback.cc +++ b/libs/surfaces/websockets/feedback.cc @@ -16,205 +16,212 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "ardour/meter.h" +#include "ardour/plugin_insert.h" #include "ardour/session.h" #include "ardour/tempo.h" -#include "ardour/plugin_insert.h" -#include "ardour/meter.h" #include "feedback.h" -#include "strips.h" #include "globals.h" -#include "state.h" #include "server.h" +#include "state.h" +#include "strips.h" using namespace ARDOUR; struct TempoObserver { - void operator() (ArdourFeedback* p) { - p->update_all (Node::tempo, p->globals ().tempo ()); - } + void operator() (ArdourFeedback* p) + { + p->update_all (Node::tempo, p->globals ().tempo ()); + } }; struct StripGainObserver { - void operator() (ArdourFeedback* p, uint32_t strip_n) { - // fires multiple times (4x as of ardour 6.0) - p->update_all (Node::strip_gain, strip_n, p->strips ().strip_gain (strip_n)); - } + void operator() (ArdourFeedback* p, uint32_t strip_n) + { + // fires multiple times (4x as of ardour 6.0) + p->update_all (Node::strip_gain, strip_n, p->strips ().strip_gain (strip_n)); + } }; struct StripPanObserver { - void operator() (ArdourFeedback* p, uint32_t strip_n) { - p->update_all (Node::strip_pan, strip_n, p->strips ().strip_pan (strip_n)); - } + void operator() (ArdourFeedback* p, uint32_t strip_n) + { + p->update_all (Node::strip_pan, strip_n, p->strips ().strip_pan (strip_n)); + } }; struct StripMuteObserver { - void operator() (ArdourFeedback* p, uint32_t strip_n) { - p->update_all (Node::strip_mute, strip_n, p->strips ().strip_mute (strip_n)); - } + void operator() (ArdourFeedback* p, uint32_t strip_n) + { + p->update_all (Node::strip_mute, strip_n, p->strips ().strip_mute (strip_n)); + } }; struct PluginBypassObserver { - void operator() (ArdourFeedback* p, uint32_t strip_n, uint32_t plugin_n) { - p->update_all (Node::strip_plugin_enable, strip_n, plugin_n, - p->strips ().strip_plugin_enabled (strip_n, plugin_n)); - } + void operator() (ArdourFeedback* p, uint32_t strip_n, uint32_t plugin_n) + { + p->update_all (Node::strip_plugin_enable, strip_n, plugin_n, + p->strips ().strip_plugin_enabled (strip_n, plugin_n)); + } }; struct PluginParamValueObserver { - void operator() (ArdourFeedback* p, uint32_t strip_n, uint32_t plugin_n, - uint32_t param_n, boost::shared_ptr control) { - p->update_all (Node::strip_plugin_param_value, strip_n, plugin_n, param_n, - ArdourStrips::plugin_param_value (control)); - } + void operator() (ArdourFeedback* p, uint32_t strip_n, uint32_t plugin_n, + uint32_t param_n, boost::shared_ptr control) + { + p->update_all (Node::strip_plugin_param_value, strip_n, plugin_n, param_n, + ArdourStrips::plugin_param_value (control)); + } }; int ArdourFeedback::start () { - observe_globals (); - observe_strips (); + observe_globals (); + observe_strips (); - // some things need polling like the strip meters - Glib::RefPtr periodic_timeout = Glib::TimeoutSource::create (100); // ms - _periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, - &ArdourFeedback::poll)); - periodic_timeout->attach (main_loop ()->get_context ()); + // some things need polling like the strip meters + Glib::RefPtr periodic_timeout = Glib::TimeoutSource::create (100); // ms + _periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, + &ArdourFeedback::poll)); + periodic_timeout->attach (main_loop ()->get_context ()); - return 0; + return 0; } int ArdourFeedback::stop () { - _periodic_connection.disconnect (); - _signal_connections.drop_connections (); - return 0; + _periodic_connection.disconnect (); + _signal_connections.drop_connections (); + return 0; } void ArdourFeedback::update_all (std::string node, TypedValue value) const { - update_all (node, ADDR_NONE, ADDR_NONE, ADDR_NONE, value); + update_all (node, ADDR_NONE, ADDR_NONE, ADDR_NONE, value); } void ArdourFeedback::update_all (std::string node, uint32_t strip_n, TypedValue value) const { - update_all (node, strip_n, ADDR_NONE, ADDR_NONE, value); + update_all (node, strip_n, ADDR_NONE, ADDR_NONE, value); } void ArdourFeedback::update_all (std::string node, uint32_t strip_n, uint32_t plugin_n, - TypedValue value) const + TypedValue value) const { - update_all (node, strip_n, plugin_n, ADDR_NONE, value); + update_all (node, strip_n, plugin_n, ADDR_NONE, value); } void ArdourFeedback::update_all (std::string node, uint32_t strip_n, uint32_t plugin_n, uint32_t param_n, - TypedValue value) const + TypedValue value) const { - AddressVector addr = AddressVector (); + AddressVector addr = AddressVector (); - if (strip_n != ADDR_NONE) { - addr.push_back (strip_n); - } + if (strip_n != ADDR_NONE) { + addr.push_back (strip_n); + } - if (plugin_n != ADDR_NONE) { - addr.push_back (plugin_n); - } + if (plugin_n != ADDR_NONE) { + addr.push_back (plugin_n); + } - if (param_n != ADDR_NONE) { - addr.push_back (param_n); - } + if (param_n != ADDR_NONE) { + addr.push_back (param_n); + } - ValueVector val = ValueVector (); - val.push_back (value); + ValueVector val = ValueVector (); + val.push_back (value); - server ().update_all_clients (NodeState (node, addr, val), false); + server ().update_all_clients (NodeState (node, addr, val), false); } bool ArdourFeedback::poll () const { - for (uint32_t strip_n = 0; strip_n < strips ().strip_count (); ++strip_n) { - // meters - boost::shared_ptr strip = strips ().nth_strip (strip_n); - boost::shared_ptr meter = strip->peak_meter (); - float db = meter ? meter->meter_level (0, MeterMCP) : -193; - update_all (Node::strip_meter, strip_n, static_cast(db)); - } + for (uint32_t strip_n = 0; strip_n < strips ().strip_count (); ++strip_n) { + // meters + boost::shared_ptr strip = strips ().nth_strip (strip_n); + boost::shared_ptr meter = strip->peak_meter (); + float db = meter ? meter->meter_level (0, MeterMCP) : -193; + update_all (Node::strip_meter, strip_n, static_cast (db)); + } - return true; + return true; } void ArdourFeedback::observe_globals () { - session ().tempo_map ().PropertyChanged.connect (_signal_connections, MISSING_INVALIDATOR, - boost::bind (TempoObserver (), this), event_loop ()); + session ().tempo_map ().PropertyChanged.connect (_signal_connections, MISSING_INVALIDATOR, + boost::bind (TempoObserver (), this), event_loop ()); } void ArdourFeedback::observe_strips () { - for (uint32_t strip_n = 0; strip_n < strips ().strip_count (); ++strip_n) { - boost::shared_ptr strip = strips ().nth_strip (strip_n); + for (uint32_t strip_n = 0; strip_n < strips ().strip_count (); ++strip_n) { + boost::shared_ptr strip = strips ().nth_strip (strip_n); - strip->gain_control ()->Changed.connect (_signal_connections, MISSING_INVALIDATOR, - boost::bind (StripGainObserver (), this, strip_n), event_loop ()); + strip->gain_control ()->Changed.connect (_signal_connections, MISSING_INVALIDATOR, + boost::bind (StripGainObserver (), this, strip_n), event_loop ()); - if (strip->pan_azimuth_control ()) { - strip->pan_azimuth_control ()->Changed.connect (_signal_connections, MISSING_INVALIDATOR, - boost::bind (StripPanObserver (), this, strip_n), event_loop ()); + if (strip->pan_azimuth_control ()) { + strip->pan_azimuth_control ()->Changed.connect (_signal_connections, MISSING_INVALIDATOR, + boost::bind (StripPanObserver (), this, strip_n), event_loop ()); + } + + strip->mute_control ()->Changed.connect (_signal_connections, MISSING_INVALIDATOR, + boost::bind (StripMuteObserver (), this, strip_n), event_loop ()); + + observe_strip_plugins (strip_n, strip); } - - strip->mute_control ()->Changed.connect (_signal_connections, MISSING_INVALIDATOR, - boost::bind (StripMuteObserver (), this, strip_n), event_loop ()); - - observe_strip_plugins (strip_n, strip); - } } void ArdourFeedback::observe_strip_plugins (uint32_t strip_n, boost::shared_ptr strip) { - for (uint32_t plugin_n = 0 ; ; ++plugin_n) { - boost::shared_ptr insert = strips ().strip_plugin_insert (strip_n, plugin_n); - if (!insert) { - break; - } + for (uint32_t plugin_n = 0;; ++plugin_n) { + boost::shared_ptr insert = strips ().strip_plugin_insert (strip_n, plugin_n); + if (!insert) { + break; + } - uint32_t bypass = insert->plugin ()->designated_bypass_port (); - Evoral::Parameter param = Evoral::Parameter (PluginAutomation, 0, bypass); - boost::shared_ptr control = insert->automation_control (param); + uint32_t bypass = insert->plugin ()->designated_bypass_port (); + Evoral::Parameter param = Evoral::Parameter (PluginAutomation, 0, bypass); + boost::shared_ptr control = insert->automation_control (param); - if (control) { - control->Changed.connect (_signal_connections, MISSING_INVALIDATOR, - boost::bind (PluginBypassObserver (), this, strip_n, plugin_n), event_loop ()); - } + if (control) { + control->Changed.connect (_signal_connections, MISSING_INVALIDATOR, + boost::bind (PluginBypassObserver (), this, strip_n, plugin_n), event_loop ()); + } - observe_strip_plugin_param_values (strip_n, plugin_n, insert); - } + observe_strip_plugin_param_values (strip_n, plugin_n, insert); + } } void ArdourFeedback::observe_strip_plugin_param_values (uint32_t strip_n, - uint32_t plugin_n, boost::shared_ptr insert) + uint32_t plugin_n, boost::shared_ptr insert) { - boost::shared_ptr plugin = insert->plugin (); + boost::shared_ptr plugin = insert->plugin (); - for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) { - boost::shared_ptr control = strips ().strip_plugin_param_control ( - strip_n, plugin_n, param_n); + for (uint32_t param_n = 0; param_n < plugin->parameter_count (); ++param_n) { + boost::shared_ptr control = strips ().strip_plugin_param_control ( + strip_n, plugin_n, param_n); - if (!control) { - continue; - } + if (!control) { + continue; + } - control->Changed.connect (_signal_connections, MISSING_INVALIDATOR, - boost::bind (PluginParamValueObserver (), this, strip_n, plugin_n, param_n, - control), event_loop ()); - } + control->Changed.connect (_signal_connections, MISSING_INVALIDATOR, + boost::bind (PluginParamValueObserver (), this, strip_n, plugin_n, param_n, + control), + event_loop ()); + } } diff --git a/libs/surfaces/websockets/feedback.h b/libs/surfaces/websockets/feedback.h index 1b939d32c6..968c770485 100644 --- a/libs/surfaces/websockets/feedback.h +++ b/libs/surfaces/websockets/feedback.h @@ -19,41 +19,39 @@ #ifndef ardour_feedback_h #define ardour_feedback_h -#include #include +#include #include "component.h" #include "typed_value.h" class ArdourFeedback : public SurfaceComponent { - public: +public: + ArdourFeedback (ArdourSurface::ArdourWebsockets& surface) + : SurfaceComponent (surface){}; + virtual ~ArdourFeedback (){}; - ArdourFeedback (ArdourSurface::ArdourWebsockets& surface) : SurfaceComponent (surface) {}; - virtual ~ArdourFeedback () {}; + int start (); + int stop (); - int start (); - int stop (); + void update_all (std::string, TypedValue) const; + void update_all (std::string, uint32_t, TypedValue) const; + void update_all (std::string, uint32_t, uint32_t, TypedValue) const; + void update_all (std::string, uint32_t, uint32_t, uint32_t, TypedValue) const; - void update_all (std::string, TypedValue) const; - void update_all (std::string, uint32_t, TypedValue) const; - void update_all (std::string, uint32_t, uint32_t, TypedValue) const; - void update_all (std::string, uint32_t, uint32_t, uint32_t, TypedValue) const; - - private: +private: + Glib::Threads::Mutex _client_state_lock; + PBD::ScopedConnectionList _signal_connections; + sigc::connection _periodic_connection; - Glib::Threads::Mutex _client_state_lock; - PBD::ScopedConnectionList _signal_connections; - sigc::connection _periodic_connection; - - bool poll () const; - - void observe_globals (); - void observe_strips (); - void observe_strip_plugins (uint32_t, boost::shared_ptr); - void observe_strip_plugin_param_values (uint32_t, uint32_t, - boost::shared_ptr); + bool poll () const; + void observe_globals (); + void observe_strips (); + void observe_strip_plugins (uint32_t, boost::shared_ptr); + void observe_strip_plugin_param_values (uint32_t, uint32_t, + boost::shared_ptr); }; #endif // ardour_feedback_h diff --git a/libs/surfaces/websockets/globals.cc b/libs/surfaces/websockets/globals.cc index decd9ad6c2..4a78475350 100644 --- a/libs/surfaces/websockets/globals.cc +++ b/libs/surfaces/websockets/globals.cc @@ -25,15 +25,15 @@ using namespace ARDOUR; double ArdourGlobals::tempo () const { - Tempo tempo = session ().tempo_map ().tempo_at_sample (0); - return tempo.note_type () * tempo.pulses_per_minute (); + Tempo tempo = session ().tempo_map ().tempo_at_sample (0); + return tempo.note_type () * tempo.pulses_per_minute (); } void ArdourGlobals::set_tempo (double bpm) { - bpm = max (0.01, bpm); - TempoMap& tempo_map = session ().tempo_map (); - Tempo tempo (bpm, tempo_map.tempo_at_sample (0).note_type (), bpm); - tempo_map.add_tempo (tempo, 0.0, 0, AudioTime); + bpm = max (0.01, bpm); + TempoMap& tempo_map = session ().tempo_map (); + Tempo tempo (bpm, tempo_map.tempo_at_sample (0).note_type (), bpm); + tempo_map.add_tempo (tempo, 0.0, 0, AudioTime); } diff --git a/libs/surfaces/websockets/globals.h b/libs/surfaces/websockets/globals.h index 270e3d0652..c52d2cfc64 100644 --- a/libs/surfaces/websockets/globals.h +++ b/libs/surfaces/websockets/globals.h @@ -23,14 +23,13 @@ class ArdourGlobals : public SurfaceComponent { - public: - - ArdourGlobals (ArdourSurface::ArdourWebsockets& surface) : SurfaceComponent (surface) {}; - virtual ~ArdourGlobals () {}; - - double tempo () const; - void set_tempo (double); +public: + ArdourGlobals (ArdourSurface::ArdourWebsockets& surface) + : SurfaceComponent (surface){}; + virtual ~ArdourGlobals (){}; + double tempo () const; + void set_tempo (double); }; #endif // ardour_globals_h diff --git a/libs/surfaces/websockets/interface.cc b/libs/surfaces/websockets/interface.cc index 5bdd16754b..462ac79cb8 100644 --- a/libs/surfaces/websockets/interface.cc +++ b/libs/surfaces/websockets/interface.cc @@ -27,47 +27,49 @@ using namespace ArdourSurface; static ControlProtocol* new_ardour_websockets_protocol (ControlProtocolDescriptor* /*descriptor*/, - Session* s) + Session* s) { - ArdourWebsockets* surface = new ArdourWebsockets (*s); + ArdourWebsockets* surface = new ArdourWebsockets (*s); - surface->set_active (true); + surface->set_active (true); - return surface; + return surface; } static void delete_ardour_websockets_protocol (ControlProtocolDescriptor* /*descriptor*/, - ControlProtocol* cp) + ControlProtocol* cp) { - delete cp; + delete cp; } static bool probe_ardour_websockets_protocol (ControlProtocolDescriptor* /*descriptor*/) { - return true; + return true; } static void* ardour_websockets_request_buffer_factory (uint32_t num_requests) { - return ArdourWebsockets::request_factory (num_requests); + return ArdourWebsockets::request_factory (num_requests); } static ControlProtocolDescriptor ardour_websockets_descriptor = { - /*name : */ SURFACE_NAME, - /*id : */ SURFACE_ID, - /*ptr : */ 0, - /*module : */ 0, - /*mandatory : */ 0, - /*supports_feedback : */ true, - /*probe : */ probe_ardour_websockets_protocol, - /*initialize : */ new_ardour_websockets_protocol, - /*destroy : */ delete_ardour_websockets_protocol, - /*request_buffer_factory */ ardour_websockets_request_buffer_factory + /*name : */ SURFACE_NAME, + /*id : */ SURFACE_ID, + /*ptr : */ 0, + /*module : */ 0, + /*mandatory : */ 0, + /*supports_feedback : */ true, + /*probe : */ probe_ardour_websockets_protocol, + /*initialize : */ new_ardour_websockets_protocol, + /*destroy : */ delete_ardour_websockets_protocol, + /*request_buffer_factory */ ardour_websockets_request_buffer_factory }; -extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { - return &ardour_websockets_descriptor; +extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* +protocol_descriptor () +{ + return &ardour_websockets_descriptor; } diff --git a/libs/surfaces/websockets/message.cc b/libs/surfaces/websockets/message.cc index b82291d245..0c7b127287 100644 --- a/libs/surfaces/websockets/message.cc +++ b/libs/surfaces/websockets/message.cc @@ -20,18 +20,18 @@ #include #endif -#include #include #include #include +#include #include "message.h" // JSON does not support Infinity or NaN -#define XSTR(s) STR(s) +#define XSTR(s) STR (s) #define STR(s) #s #define JSON_INF 1.0e+128 -#define JSON_INF_STR XSTR(JSON_INF) +#define JSON_INF_STR XSTR (JSON_INF) namespace pt = boost::property_tree; @@ -39,155 +39,154 @@ NodeStateMessage::NodeStateMessage (const NodeState& state) : _valid (true) , _state (state) { - _write = state.n_val () > 0; + _write = state.n_val () > 0; } -NodeStateMessage::NodeStateMessage (void *buf, size_t len) +NodeStateMessage::NodeStateMessage (void* buf, size_t len) : _valid (false) , _write (false) { - try { - std::string s (static_cast(buf), len); + try { + std::string s (static_cast (buf), len); - std::istringstream is (s); - pt::ptree root; - pt::read_json (is, root); + std::istringstream is (s); + pt::ptree root; + pt::read_json (is, root); - _state = NodeState (root.get ("node")); + _state = NodeState (root.get ("node")); - pt::ptree addr = root.get_child ("addr", pt::ptree ()); + pt::ptree addr = root.get_child ("addr", pt::ptree ()); - for (pt::ptree::iterator it = addr.begin (); it != addr.end (); ++it) { - // throws if datatype not uint32_t - _state.add_addr (boost::lexical_cast(it->second.data ())); - } + for (pt::ptree::iterator it = addr.begin (); it != addr.end (); ++it) { + // throws if datatype not uint32_t + _state.add_addr (boost::lexical_cast (it->second.data ())); + } - pt::ptree val = root.get_child ("val", pt::ptree ()); + pt::ptree val = root.get_child ("val", pt::ptree ()); - for (pt::ptree::iterator it = val.begin (); it != val.end (); ++it) { + for (pt::ptree::iterator it = val.begin (); it != val.end (); ++it) { + std::string val = it->second.data (); - std::string val = it->second.data (); + try { + _state.add_val (boost::lexical_cast (val)); + } catch (const boost::bad_lexical_cast&) { + try { + double d = boost::lexical_cast (val); + if (d >= JSON_INF) { + d = std::numeric_limits::infinity (); + } else if (d <= -JSON_INF) { + d = -std::numeric_limits::infinity (); + } + _state.add_val (d); + } catch (const boost::bad_lexical_cast&) { + if (val == "false") { + _state.add_val (false); + } else if (val == "true") { + _state.add_val (true); + } else { + _state.add_val (val); + } + } + } + } - try { - _state.add_val (boost::lexical_cast(val)); - } catch (const boost::bad_lexical_cast&) { - try { - double d = boost::lexical_cast(val); - if (d >= JSON_INF) { - d = std::numeric_limits::infinity (); - } else if (d <= -JSON_INF) { - d = -std::numeric_limits::infinity (); - } - _state.add_val (d); - } catch (const boost::bad_lexical_cast&) { - if (val == "false") { - _state.add_val (false); - } else if (val == "true") { - _state.add_val (true); - } else { - _state.add_val (val); - } - } - } - } + if (_state.n_val () > 0) { + _write = true; + } - if (_state.n_val () > 0) { - _write = true; - } + _valid = true; - _valid = true; - - } catch (const std::exception& exc) { + } catch (const std::exception& exc) { #ifdef DEBUG - std::cerr << "cannot parse message - " << exc.what () << std::endl; + std::cerr << "cannot parse message - " << exc.what () << std::endl; #endif - } + } } size_t -NodeStateMessage::serialize (void *buf, size_t len) const +NodeStateMessage::serialize (void* buf, size_t len) const { - // boost json writes all values as strings, we do not want that + // boost json writes all values as strings, we do not want that - if (len == 0) { - return -1; - } + if (len == 0) { + return -1; + } - std::stringstream ss; + std::stringstream ss; - ss << "{\"node\":\"" << _state.node () << "\""; + ss << "{\"node\":\"" << _state.node () << "\""; - int n_addr = _state.n_addr (); + int n_addr = _state.n_addr (); - if (n_addr > 0) { - ss << ",\"addr\":["; + if (n_addr > 0) { + ss << ",\"addr\":["; - for (int i = 0; i < n_addr; i++) { - if (i > 0) { - ss << ','; - } + for (int i = 0; i < n_addr; i++) { + if (i > 0) { + ss << ','; + } - ss << _state.nth_addr (i); - } + ss << _state.nth_addr (i); + } - ss << "]"; - } + ss << "]"; + } - int n_val = _state.n_val (); + int n_val = _state.n_val (); - if (n_val > 0) { - ss << ",\"val\":["; + if (n_val > 0) { + ss << ",\"val\":["; - for (int i = 0; i < n_val; i++) { - if (i > 0) { - ss << ','; - } + for (int i = 0; i < n_val; i++) { + if (i > 0) { + ss << ','; + } - TypedValue val = _state.nth_val (i); + TypedValue val = _state.nth_val (i); - switch (val.type ()) { - case TypedValue::Empty: - ss << "null"; - break; - case TypedValue::Bool: - ss << (static_cast(val) ? "true" : "false"); - break; - case TypedValue::Int: - ss << static_cast(val); - break; - case TypedValue::Double: { - double d = static_cast(val); - if (d == std::numeric_limits::infinity ()) { - ss << JSON_INF_STR; - } else if (d == -std::numeric_limits::infinity ()) { - ss << "-" JSON_INF_STR; - } else { - ss << d; - } - break; - } - case TypedValue::String: - ss << '"' << static_cast(val) << '"'; - break; - default: - break; - } - } + switch (val.type ()) { + case TypedValue::Empty: + ss << "null"; + break; + case TypedValue::Bool: + ss << (static_cast (val) ? "true" : "false"); + break; + case TypedValue::Int: + ss << static_cast (val); + break; + case TypedValue::Double: { + double d = static_cast (val); + if (d == std::numeric_limits::infinity ()) { + ss << JSON_INF_STR; + } else if (d == -std::numeric_limits::infinity ()) { + ss << "-" JSON_INF_STR; + } else { + ss << d; + } + break; + } + case TypedValue::String: + ss << '"' << static_cast (val) << '"'; + break; + default: + break; + } + } - ss << "]"; - } + ss << "]"; + } - ss << '}'; + ss << '}'; - std::string s = ss.str (); - const char *cs = s.c_str (); - size_t cs_sz = strlen (cs); + std::string s = ss.str (); + const char* cs = s.c_str (); + size_t cs_sz = strlen (cs); - if (len < cs_sz) { - return -1; - } + if (len < cs_sz) { + return -1; + } - memcpy (buf, cs, cs_sz); + memcpy (buf, cs, cs_sz); - return cs_sz; + return cs_sz; } diff --git a/libs/surfaces/websockets/message.h b/libs/surfaces/websockets/message.h index eb11617697..b2ab948a7e 100644 --- a/libs/surfaces/websockets/message.h +++ b/libs/surfaces/websockets/message.h @@ -23,23 +23,29 @@ class NodeStateMessage { - public: +public: + NodeStateMessage (const NodeState& state); + NodeStateMessage (void*, size_t); - NodeStateMessage (const NodeState& state); - NodeStateMessage (void *, size_t); + size_t serialize (void*, size_t) const; - size_t serialize (void *, size_t) const; - - bool is_valid () const { return _valid; } - bool is_write () const { return _write; } - const NodeState& state () const { return _state; } - - private: - - bool _valid; - bool _write; - NodeState _state; + bool is_valid () const + { + return _valid; + } + bool is_write () const + { + return _write; + } + const NodeState& state () const + { + return _state; + } +private: + bool _valid; + bool _write; + NodeState _state; }; #endif // websockets_message_h diff --git a/libs/surfaces/websockets/server.cc b/libs/surfaces/websockets/server.cc index b4f599d949..8eee8d1d0f 100644 --- a/libs/surfaces/websockets/server.cc +++ b/libs/surfaces/websockets/server.cc @@ -20,22 +20,22 @@ #include #endif -#include "server.h" #include "dispatcher.h" +#include "server.h" /* backport from libwebsockets 3.0, * allow to compile on GNU/Linux with libwebsockets 2.x */ #ifndef PLATFORM_WINDOWS -# ifndef LWS_POLLHUP -# define LWS_POLLHUP (POLLHUP|POLLERR) -# endif -# ifndef LWS_POLLIN -# define LWS_POLLIN (POLLIN) -# endif -# ifndef LWS_POLLOUT -# define LWS_POLLOUT (POLLOUT) -# endif +#ifndef LWS_POLLHUP +#define LWS_POLLHUP (POLLHUP | POLLERR) +#endif +#ifndef LWS_POLLIN +#define LWS_POLLIN (POLLIN) +#endif +#ifndef LWS_POLLOUT +#define LWS_POLLOUT (POLLOUT) +#endif #endif using namespace Glib; @@ -44,350 +44,353 @@ WebsocketsServer::WebsocketsServer (ArdourSurface::ArdourWebsockets& surface) : SurfaceComponent (surface) , _lws_context (0) { - // keep references to all config for libwebsockets 2 - lws_protocols proto; - memset (&proto, 0, sizeof(lws_protocols)); - proto.name = "lws-ardour"; - proto.callback = WebsocketsServer::lws_callback; - proto.per_session_data_size = 0; - proto.rx_buffer_size = 0; - proto.id = 0; - proto.user = 0; + /* keep references to all config for libwebsockets 2 */ + lws_protocols proto; + memset (&proto, 0, sizeof (lws_protocols)); + proto.name = "lws-ardour"; + proto.callback = WebsocketsServer::lws_callback; + proto.per_session_data_size = 0; + proto.rx_buffer_size = 0; + proto.id = 0; + proto.user = 0; #if LWS_LIBRARY_VERSION_MAJOR >= 3 - proto.tx_packet_size = 0; + proto.tx_packet_size = 0; #endif - _lws_proto[0] = proto; - memset (&_lws_proto[1], 0, sizeof(lws_protocols)); + _lws_proto[0] = proto; + memset (&_lws_proto[1], 0, sizeof (lws_protocols)); - memset (&_lws_info, 0, sizeof(lws_context_creation_info)); - _lws_info.port = WEBSOCKET_LISTEN_PORT; - _lws_info.protocols = _lws_proto; - _lws_info.uid = -1; - _lws_info.gid = -1; - _lws_info.user = this; + memset (&_lws_info, 0, sizeof (lws_context_creation_info)); + _lws_info.port = WEBSOCKET_LISTEN_PORT; + _lws_info.protocols = _lws_proto; + _lws_info.uid = -1; + _lws_info.gid = -1; + _lws_info.user = this; } int WebsocketsServer::start () { - _lws_context = lws_create_context (&_lws_info); + _lws_context = lws_create_context (&_lws_info); - if (!_lws_context) { - PBD::error << "ArdourWebsockets: could not create libwebsockets context" << endmsg; - return -1; - } + if (!_lws_context) { + PBD::error << "ArdourWebsockets: could not create libwebsockets context" << endmsg; + return -1; + } - // add_poll_fd() should have been called once during lws_create_context() - // if _fd_ctx is empty then LWS_CALLBACK_ADD_POLL_FD was not called - // this means libwesockets was not compiled with LWS_WITH_EXTERNAL_POLL - // - macos homebrew libwebsockets: disabled (3.2.2 as of Feb 2020) - // - linux ubuntu libwebsockets-dev: enabled (2.0.3 as of Feb 2020) but - // #if defined(LWS_WITH_EXTERNAL_POLL) check is not reliable -- constant - // missing from /usr/include/lws_config.h + /* add_poll_fd() should have been called once during lws_create_context() + * if _fd_ctx is empty then LWS_CALLBACK_ADD_POLL_FD was not called + * this means libwesockets was not compiled with LWS_WITH_EXTERNAL_POLL + * - macos homebrew libwebsockets: disabled (3.2.2 as of Feb 2020) + * - linux ubuntu libwebsockets-dev: enabled (2.0.3 as of Feb 2020) but + * #if defined(LWS_WITH_EXTERNAL_POLL) check is not reliable -- constant + * missing from /usr/include/lws_config.h + */ - if (_fd_ctx.empty ()) { - PBD::error << "ArdourWebsockets: check your libwebsockets was compiled" - " with LWS_WITH_EXTERNAL_POLL enabled" << endmsg; - return -1; - } + if (_fd_ctx.empty ()) { + PBD::error << "ArdourWebsockets: check your libwebsockets was compiled" + " with LWS_WITH_EXTERNAL_POLL enabled" + << endmsg; + return -1; + } - return 0; + return 0; } int WebsocketsServer::stop () { - for (LwsPollFdGlibSourceMap::iterator it = _fd_ctx.begin (); it != _fd_ctx.end (); ++it) { - it->second.rg_iosrc->destroy (); + for (LwsPollFdGlibSourceMap::iterator it = _fd_ctx.begin (); it != _fd_ctx.end (); ++it) { + it->second.rg_iosrc->destroy (); - if (it->second.wg_iosrc) { - it->second.wg_iosrc->destroy (); - } - } + if (it->second.wg_iosrc) { + it->second.wg_iosrc->destroy (); + } + } - _fd_ctx.clear (); + _fd_ctx.clear (); - if (_lws_context) { - lws_context_destroy (_lws_context); - _lws_context = 0; - } + if (_lws_context) { + lws_context_destroy (_lws_context); + _lws_context = 0; + } - return 0; + return 0; } void WebsocketsServer::update_client (Client wsi, const NodeState& state, bool force) { - ClientContextMap::iterator it = _client_ctx.find (wsi); - if (it == _client_ctx.end ()) { - return; - } + ClientContextMap::iterator it = _client_ctx.find (wsi); + if (it == _client_ctx.end ()) { + return; + } - if (force || !it->second.has_state (state)) { - // write to client only if state was updated - it->second.update_state (state); - it->second.output_buf ().push_back (NodeStateMessage (state)); - lws_callback_on_writable (wsi); - } + if (force || !it->second.has_state (state)) { + /* write to client only if state was updated */ + it->second.update_state (state); + it->second.output_buf ().push_back (NodeStateMessage (state)); + lws_callback_on_writable (wsi); + } } void WebsocketsServer::update_all_clients (const NodeState& state, bool force) -{ - for (ClientContextMap::iterator it = _client_ctx.begin (); it != _client_ctx.end (); ++it) { - update_client (it->second.wsi (), state, force); - } +{ + for (ClientContextMap::iterator it = _client_ctx.begin (); it != _client_ctx.end (); ++it) { + update_client (it->second.wsi (), state, force); + } } void -WebsocketsServer::add_poll_fd (struct lws_pollargs *pa) +WebsocketsServer::add_poll_fd (struct lws_pollargs* pa) { - // fd can be SOCKET or int depending platform - lws_sockfd_type fd = pa->fd; + /* fd can be SOCKET or int depending platform */ + lws_sockfd_type fd = pa->fd; #ifdef PLATFORM_WINDOWS - RefPtr g_channel = IOChannel::create_from_win32_socket (fd); + RefPtr g_channel = IOChannel::create_from_win32_socket (fd); #else - RefPtr g_channel = IOChannel::create_from_fd (fd); + RefPtr g_channel = IOChannel::create_from_fd (fd); #endif - RefPtr rg_iosrc (IOSource::create (g_channel, events_to_ioc (pa->events))); - rg_iosrc->connect (sigc::bind (sigc::mem_fun (*this, &WebsocketsServer::io_handler), fd)); - rg_iosrc->attach (main_loop ()->get_context ()); + RefPtr rg_iosrc (IOSource::create (g_channel, events_to_ioc (pa->events))); + rg_iosrc->connect (sigc::bind (sigc::mem_fun (*this, &WebsocketsServer::io_handler), fd)); + rg_iosrc->attach (main_loop ()->get_context ()); - struct lws_pollfd lws_pfd; - lws_pfd.fd = pa->fd; - lws_pfd.events = pa->events; - lws_pfd.revents = 0; + struct lws_pollfd lws_pfd; + lws_pfd.fd = pa->fd; + lws_pfd.events = pa->events; + lws_pfd.revents = 0; - LwsPollFdGlibSource ctx; - ctx.lws_pfd = lws_pfd; - ctx.g_channel = g_channel; - ctx.rg_iosrc = rg_iosrc; - ctx.wg_iosrc = Glib::RefPtr(0); + LwsPollFdGlibSource ctx; + ctx.lws_pfd = lws_pfd; + ctx.g_channel = g_channel; + ctx.rg_iosrc = rg_iosrc; + ctx.wg_iosrc = Glib::RefPtr (0); - _fd_ctx[fd] = ctx; + _fd_ctx[fd] = ctx; } void -WebsocketsServer::mod_poll_fd (struct lws_pollargs *pa) +WebsocketsServer::mod_poll_fd (struct lws_pollargs* pa) { - LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd); - if (it == _fd_ctx.end ()) { - return; - } + LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd); + if (it == _fd_ctx.end ()) { + return; + } - it->second.lws_pfd.events = pa->events; + it->second.lws_pfd.events = pa->events; - if (pa->events & LWS_POLLOUT) { - // libwebsockets wants to write but cannot find a way to update - // an existing glib::iosource event flags using glibmm, - // create another iosource and set to IO_OUT, it will be destroyed - // after clearing POLLOUT (see 'else' body below) + if (pa->events & LWS_POLLOUT) { + /* libwebsockets wants to write but cannot find a way to update + * an existing glib::iosource event flags using glibmm, + * create another iosource and set to IO_OUT, it will be destroyed + * after clearing POLLOUT (see 'else' body below) + */ - if (it->second.wg_iosrc) { - // already polling for write - return; - } + if (it->second.wg_iosrc) { + /* already polling for write */ + return; + } - RefPtr wg_iosrc = it->second.g_channel->create_watch (Glib::IO_OUT); - wg_iosrc->connect (sigc::bind (sigc::mem_fun (*this, &WebsocketsServer::io_handler), pa->fd)); - wg_iosrc->attach (main_loop ()->get_context ()); - it->second.wg_iosrc = wg_iosrc; - } else { - if (it->second.wg_iosrc) { - it->second.wg_iosrc->destroy (); - it->second.wg_iosrc = Glib::RefPtr(0); - } - } + RefPtr wg_iosrc = it->second.g_channel->create_watch (Glib::IO_OUT); + wg_iosrc->connect (sigc::bind (sigc::mem_fun (*this, &WebsocketsServer::io_handler), pa->fd)); + wg_iosrc->attach (main_loop ()->get_context ()); + it->second.wg_iosrc = wg_iosrc; + } else { + if (it->second.wg_iosrc) { + it->second.wg_iosrc->destroy (); + it->second.wg_iosrc = Glib::RefPtr (0); + } + } } void -WebsocketsServer::del_poll_fd (struct lws_pollargs *pa) +WebsocketsServer::del_poll_fd (struct lws_pollargs* pa) { - LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd); - if (it == _fd_ctx.end ()) { - return; - } + LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (pa->fd); + if (it == _fd_ctx.end ()) { + return; + } - it->second.rg_iosrc->destroy (); + it->second.rg_iosrc->destroy (); - if (it->second.wg_iosrc) { - it->second.wg_iosrc->destroy (); - } + if (it->second.wg_iosrc) { + it->second.wg_iosrc->destroy (); + } - _fd_ctx.erase (it); + _fd_ctx.erase (it); } void WebsocketsServer::add_client (Client wsi) { - _client_ctx.emplace (wsi, ClientContext (wsi)); - dispatcher ().update_all_nodes (wsi); // send all state + _client_ctx.emplace (wsi, ClientContext (wsi)); + dispatcher ().update_all_nodes (wsi); // send all state } void WebsocketsServer::del_client (Client wsi) { - ClientContextMap::iterator it = _client_ctx.find (wsi); - if (it != _client_ctx.end ()) { - _client_ctx.erase (it); - } + ClientContextMap::iterator it = _client_ctx.find (wsi); + if (it != _client_ctx.end ()) { + _client_ctx.erase (it); + } } void -WebsocketsServer::recv_client (Client wsi, void *buf, size_t len) +WebsocketsServer::recv_client (Client wsi, void* buf, size_t len) { - NodeStateMessage msg (buf, len); - if (!msg.is_valid ()) { - return; - } + NodeStateMessage msg (buf, len); + if (!msg.is_valid ()) { + return; + } #ifdef DEBUG - std::cerr << "RX " << msg.state ().debug_str () << std::endl; + std::cerr << "RX " << msg.state ().debug_str () << std::endl; #endif - ClientContextMap::iterator it = _client_ctx.find (wsi); - if (it == _client_ctx.end ()) { - return; - } + ClientContextMap::iterator it = _client_ctx.find (wsi); + if (it == _client_ctx.end ()) { + return; + } - // avoid echo - it->second.update_state (msg.state ()); + /* avoid echo */ + it->second.update_state (msg.state ()); - dispatcher ().dispatch (wsi, msg); + dispatcher ().dispatch (wsi, msg); } void WebsocketsServer::write_client (Client wsi) { - ClientContextMap::iterator it = _client_ctx.find (wsi); - if (it == _client_ctx.end ()) { - return; - } + ClientContextMap::iterator it = _client_ctx.find (wsi); + if (it == _client_ctx.end ()) { + return; + } - ClientOutputBuffer& pending = it->second.output_buf (); - if (pending.empty ()) { - return; - } + ClientOutputBuffer& pending = it->second.output_buf (); + if (pending.empty ()) { + return; + } - // one lws_write() call per LWS_CALLBACK_SERVER_WRITEABLE callback + /* one lws_write() call per LWS_CALLBACK_SERVER_WRITEABLE callback */ - NodeStateMessage msg = pending.front (); - pending.pop_front (); + NodeStateMessage msg = pending.front (); + pending.pop_front (); - unsigned char out_buf[1024]; - size_t len = msg.serialize (out_buf + LWS_PRE, 1024 - LWS_PRE); + unsigned char out_buf[1024]; + size_t len = msg.serialize (out_buf + LWS_PRE, 1024 - LWS_PRE); - if (len > 0) { + if (len > 0) { #ifdef DEBUG - std::cerr << "TX " << msg.state ().debug_str () << std::endl; + std::cerr << "TX " << msg.state ().debug_str () << std::endl; #endif - lws_write (wsi, out_buf + LWS_PRE, len, LWS_WRITE_TEXT); - } else { - PBD::error << "ArdourWebsockets: cannot serialize message" << endmsg; - } + lws_write (wsi, out_buf + LWS_PRE, len, LWS_WRITE_TEXT); + } else { + PBD::error << "ArdourWebsockets: cannot serialize message" << endmsg; + } - if (!pending.empty ()) { - lws_callback_on_writable (wsi); - } + if (!pending.empty ()) { + lws_callback_on_writable (wsi); + } } bool WebsocketsServer::io_handler (Glib::IOCondition ioc, lws_sockfd_type fd) { - // IO_IN=1, IO_PRI=2, IO_ERR=8, IO_HUP=16 - //printf ("io_handler ioc = %d\n", ioc); + /* IO_IN=1, IO_PRI=2, IO_ERR=8, IO_HUP=16 */ + //printf ("io_handler ioc = %d\n", ioc); - LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (fd); - if (it == _fd_ctx.end ()) { - return false; - } + LwsPollFdGlibSourceMap::iterator it = _fd_ctx.find (fd); + if (it == _fd_ctx.end ()) { + return false; + } - struct lws_pollfd *lws_pfd = &it->second.lws_pfd; - lws_pfd->revents = ioc_to_events (ioc); + struct lws_pollfd* lws_pfd = &it->second.lws_pfd; + lws_pfd->revents = ioc_to_events (ioc); - if (lws_service_fd (_lws_context, lws_pfd) < 0) { - return false; - } + if (lws_service_fd (_lws_context, lws_pfd) < 0) { + return false; + } - return ioc & (Glib::IO_IN | Glib::IO_OUT); + return ioc & (Glib::IO_IN | Glib::IO_OUT); } IOCondition WebsocketsServer::events_to_ioc (int events) { - IOCondition ioc; + IOCondition ioc; - if (events & LWS_POLLIN) { - ioc = Glib::IO_IN; - } else if (events & LWS_POLLOUT) { - ioc = Glib::IO_OUT; - } else if (events & LWS_POLLHUP) { - ioc = Glib::IO_HUP; - } + if (events & LWS_POLLIN) { + ioc = Glib::IO_IN; + } else if (events & LWS_POLLOUT) { + ioc = Glib::IO_OUT; + } else if (events & LWS_POLLHUP) { + ioc = Glib::IO_HUP; + } - return ioc; -} - -int -WebsocketsServer::ioc_to_events (IOCondition ioc) -{ - int events = 0; - - if (ioc & Glib::IO_IN) { - events |= LWS_POLLIN; - } - - if (ioc & Glib::IO_OUT) { - events |= LWS_POLLOUT; - } - - if (ioc & (Glib::IO_HUP | Glib::IO_ERR)) { - events |= LWS_POLLHUP; - } - - return events; + return ioc; } int -WebsocketsServer::lws_callback(struct lws* wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) +WebsocketsServer::ioc_to_events (IOCondition ioc) { - void *ctx_userdata = lws_context_user (lws_get_context (wsi)); - WebsocketsServer *server = static_cast(ctx_userdata); + int events = 0; - switch (reason) { - case LWS_CALLBACK_ADD_POLL_FD: - server->add_poll_fd (static_cast(in)); - break; - - case LWS_CALLBACK_CHANGE_MODE_POLL_FD: - server->mod_poll_fd (static_cast(in)); - break; + if (ioc & Glib::IO_IN) { + events |= LWS_POLLIN; + } - case LWS_CALLBACK_DEL_POLL_FD: - server->del_poll_fd (static_cast(in)); - break; + if (ioc & Glib::IO_OUT) { + events |= LWS_POLLOUT; + } - case LWS_CALLBACK_ESTABLISHED: - server->add_client (wsi); - break; + if (ioc & (Glib::IO_HUP | Glib::IO_ERR)) { + events |= LWS_POLLHUP; + } - case LWS_CALLBACK_CLOSED: - server->del_client (wsi); - break; - - case LWS_CALLBACK_RECEIVE: - server->recv_client (wsi, in, len); - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - server->write_client (wsi); - break; - - default: - break; - } - - return 0; + return events; +} + +int +WebsocketsServer::lws_callback (struct lws* wsi, enum lws_callback_reasons reason, + void* user, void* in, size_t len) +{ + void* ctx_userdata = lws_context_user (lws_get_context (wsi)); + WebsocketsServer* server = static_cast (ctx_userdata); + + switch (reason) { + case LWS_CALLBACK_ADD_POLL_FD: + server->add_poll_fd (static_cast (in)); + break; + + case LWS_CALLBACK_CHANGE_MODE_POLL_FD: + server->mod_poll_fd (static_cast (in)); + break; + + case LWS_CALLBACK_DEL_POLL_FD: + server->del_poll_fd (static_cast (in)); + break; + + case LWS_CALLBACK_ESTABLISHED: + server->add_client (wsi); + break; + + case LWS_CALLBACK_CLOSED: + server->del_client (wsi); + break; + + case LWS_CALLBACK_RECEIVE: + server->recv_client (wsi, in, len); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + server->write_client (wsi); + break; + + default: + break; + } + + return 0; } diff --git a/libs/surfaces/websockets/server.h b/libs/surfaces/websockets/server.h index 0831b59edc..cc116367e7 100644 --- a/libs/surfaces/websockets/server.h +++ b/libs/surfaces/websockets/server.h @@ -19,9 +19,9 @@ #ifndef websockets_server_h #define websockets_server_h +#include #include #include -#include #if LWS_LIBRARY_VERSION_MAJOR < 3 // includes which in turn includes @@ -34,63 +34,60 @@ // version 3 in order to keep things simpler for the end user #endif -#include "component.h" #include "client.h" -#include "state.h" +#include "component.h" #include "message.h" +#include "state.h" -#define WEBSOCKET_LISTEN_PORT 9000 +#define WEBSOCKET_LISTEN_PORT 9000 struct LwsPollFdGlibSource { - struct lws_pollfd lws_pfd; - Glib::RefPtr g_channel; - Glib::RefPtr rg_iosrc; - Glib::RefPtr wg_iosrc; + struct lws_pollfd lws_pfd; + Glib::RefPtr g_channel; + Glib::RefPtr rg_iosrc; + Glib::RefPtr wg_iosrc; }; class WebsocketsServer : public SurfaceComponent { - public: +public: + WebsocketsServer (ArdourSurface::ArdourWebsockets&); + virtual ~WebsocketsServer (){}; - WebsocketsServer (ArdourSurface::ArdourWebsockets&); - virtual ~WebsocketsServer () {}; + int start (); + int stop (); - int start (); - int stop (); + void update_client (Client, const NodeState&, bool); + void update_all_clients (const NodeState&, bool); - void update_client (Client, const NodeState&, bool); - void update_all_clients (const NodeState&, bool); +private: + struct lws_protocols _lws_proto[2]; + struct lws_context_creation_info _lws_info; + struct lws_context* _lws_context; - private: + Glib::RefPtr _channel; - struct lws_protocols _lws_proto[2]; - struct lws_context_creation_info _lws_info; - struct lws_context *_lws_context; + typedef boost::unordered_map LwsPollFdGlibSourceMap; + LwsPollFdGlibSourceMap _fd_ctx; - Glib::RefPtr _channel; + typedef boost::unordered_map ClientContextMap; + ClientContextMap _client_ctx; - typedef boost::unordered_map LwsPollFdGlibSourceMap; - LwsPollFdGlibSourceMap _fd_ctx; + void add_poll_fd (struct lws_pollargs*); + void mod_poll_fd (struct lws_pollargs*); + void del_poll_fd (struct lws_pollargs*); - typedef boost::unordered_map ClientContextMap; - ClientContextMap _client_ctx; + void add_client (Client); + void del_client (Client); + void recv_client (Client, void* buf, size_t len); + void write_client (Client); - void add_poll_fd (struct lws_pollargs*); - void mod_poll_fd (struct lws_pollargs*); - void del_poll_fd (struct lws_pollargs*); - - void add_client (Client); - void del_client (Client); - void recv_client (Client, void *buf, size_t len); - void write_client (Client); + bool io_handler (Glib::IOCondition, lws_sockfd_type); - bool io_handler (Glib::IOCondition, lws_sockfd_type); - - Glib::IOCondition events_to_ioc (int); - int ioc_to_events (Glib::IOCondition); - - static int lws_callback(struct lws*, enum lws_callback_reasons, void *, void *, size_t); + Glib::IOCondition events_to_ioc (int); + int ioc_to_events (Glib::IOCondition); + static int lws_callback (struct lws*, enum lws_callback_reasons, void*, void*, size_t); }; #endif // websockets_server_h diff --git a/libs/surfaces/websockets/state.cc b/libs/surfaces/websockets/state.cc index f0074db8fa..18bf289951 100644 --- a/libs/surfaces/websockets/state.cc +++ b/libs/surfaces/websockets/state.cc @@ -16,98 +16,105 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include +#include #include "state.h" -NodeState::NodeState () { } +NodeState::NodeState () {} NodeState::NodeState (std::string node) - : _node (node) { } + : _node (node) +{ +} NodeState::NodeState (std::string node, AddressVector addr, ValueVector val) : _node (node) , _addr (addr) - , _val (val) { } + , _val (val) +{ +} -std::string +std::string NodeState::debug_str () const { - std::stringstream s; - s << "node = " << _node; + std::stringstream s; + s << "node = " << _node; - if (!_addr.empty ()) { - s << std::endl << " addr = "; + if (!_addr.empty ()) { + s << std::endl + << " addr = "; - for (AddressVector::const_iterator it = _addr.begin (); it != _addr.end (); ++it) { - s << *it << ";"; - } - } + for (AddressVector::const_iterator it = _addr.begin (); it != _addr.end (); ++it) { + s << *it << ";"; + } + } - for (ValueVector::const_iterator it = _val.begin (); it != _val.end (); ++it) { - s << std::endl << " val " << it->debug_str (); - } - - return s.str (); + for (ValueVector::const_iterator it = _val.begin (); it != _val.end (); ++it) { + s << std::endl + << " val " << it->debug_str (); + } + + return s.str (); } int NodeState::n_addr () const { - return static_cast(_addr.size ()); + return static_cast (_addr.size ()); } uint32_t NodeState::nth_addr (int n) const { - return _addr[n]; + return _addr[n]; } void NodeState::add_addr (uint32_t addr) { - _addr.push_back (addr); + _addr.push_back (addr); } int NodeState::n_val () const { - return static_cast(_val.size ()); + return static_cast (_val.size ()); } TypedValue NodeState::nth_val (int n) const { - if (n_val () < n) { - return TypedValue (); - } + if (n_val () < n) { + return TypedValue (); + } - return _val[n]; + return _val[n]; } void NodeState::add_val (TypedValue val) { - _val.push_back (val); + _val.push_back (val); } std::size_t NodeState::node_addr_hash () const { - std::size_t seed = 0; - boost::hash_combine (seed, _node); - boost::hash_combine (seed, _addr); - return seed; + std::size_t seed = 0; + boost::hash_combine (seed, _node); + boost::hash_combine (seed, _addr); + return seed; } bool NodeState::operator== (const NodeState& other) const { - return node_addr_hash () == other.node_addr_hash (); + return node_addr_hash () == other.node_addr_hash (); } -std::size_t hash_value (const NodeState &state) +std::size_t +hash_value (const NodeState& state) { - return state.node_addr_hash (); + return state.node_addr_hash (); } diff --git a/libs/surfaces/websockets/state.h b/libs/surfaces/websockets/state.h index 0c1762c41b..b4510b02f1 100644 --- a/libs/surfaces/websockets/state.h +++ b/libs/surfaces/websockets/state.h @@ -19,64 +19,66 @@ #ifndef node_state_h #define node_state_h -#include #include #include #include +#include #include #include "typed_value.h" -#define ADDR_NONE UINT_MAX +#define ADDR_NONE UINT_MAX -namespace Node { - const std::string tempo = "tempo"; - const std::string strip_desc = "strip_desc"; - const std::string strip_meter = "strip_meter"; - const std::string strip_gain = "strip_gain"; - const std::string strip_pan = "strip_pan"; - const std::string strip_mute = "strip_mute"; - const std::string strip_plugin_desc = "strip_plugin_desc"; - const std::string strip_plugin_enable = "strip_plugin_enable"; - const std::string strip_plugin_param_desc = "strip_plugin_param_desc"; - const std::string strip_plugin_param_value = "strip_plugin_param_value"; -} +namespace Node +{ + const std::string tempo = "tempo"; + const std::string strip_desc = "strip_desc"; + const std::string strip_meter = "strip_meter"; + const std::string strip_gain = "strip_gain"; + const std::string strip_pan = "strip_pan"; + const std::string strip_mute = "strip_mute"; + const std::string strip_plugin_desc = "strip_plugin_desc"; + const std::string strip_plugin_enable = "strip_plugin_enable"; + const std::string strip_plugin_param_desc = "strip_plugin_param_desc"; + const std::string strip_plugin_param_value = "strip_plugin_param_value"; +} // namespace Node -typedef std::vector AddressVector; +typedef std::vector AddressVector; typedef std::vector ValueVector; -class NodeState { +class NodeState +{ +public: + NodeState (); + NodeState (std::string); + NodeState (std::string, AddressVector, ValueVector = ValueVector ()); - public: + std::string debug_str () const; - NodeState (); - NodeState (std::string); - NodeState (std::string, AddressVector, ValueVector = ValueVector()); + std::string node () const + { + return _node; + } - std::string debug_str () const; + int n_addr () const; + uint32_t nth_addr (int) const; + void add_addr (uint32_t); - std::string node () const { return _node; } + int n_val () const; + TypedValue nth_val (int) const; + void add_val (TypedValue); - int n_addr () const; - uint32_t nth_addr (int) const; - void add_addr (uint32_t); + std::size_t node_addr_hash () const; - int n_val () const; - TypedValue nth_val (int) const; - void add_val (TypedValue); - - std::size_t node_addr_hash () const; - - bool operator== (const NodeState& other) const; - - private: - - std::string _node; - AddressVector _addr; - ValueVector _val; + bool operator== (const NodeState& other) const; +private: + std::string _node; + AddressVector _addr; + ValueVector _val; }; -std::size_t hash_value (const NodeState&); +std::size_t +hash_value (const NodeState&); #endif // node_state_h diff --git a/libs/surfaces/websockets/strips.cc b/libs/surfaces/websockets/strips.cc index 80ce78ac14..4c73a4e00b 100644 --- a/libs/surfaces/websockets/strips.cc +++ b/libs/surfaces/websockets/strips.cc @@ -16,9 +16,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "ardour/session.h" -#include "ardour/plugin_insert.h" #include "ardour/dB.h" +#include "ardour/plugin_insert.h" +#include "ardour/session.h" #include "pbd/controllable.h" #include "strips.h" @@ -28,65 +28,65 @@ using namespace ARDOUR; int ArdourStrips::start () { - // take an indexed snapshot of current strips - StripableList strips; - session ().get_stripables (strips, PresentationInfo::AllStripables); + /* take an indexed snapshot of current strips */ + StripableList strips; + session ().get_stripables (strips, PresentationInfo::AllStripables); - for (StripableList::iterator strip = strips.begin (); strip != strips.end (); ++strip) { - _strips.push_back (*strip); - } + for (StripableList::iterator strip = strips.begin (); strip != strips.end (); ++strip) { + _strips.push_back (*strip); + } - return 0; + return 0; } int ArdourStrips::stop () { - _strips.clear (); - return 0; + _strips.clear (); + return 0; } double ArdourStrips::to_db (double k) { - if (k == 0) { - return -std::numeric_limits::infinity (); - } + if (k == 0) { + return -std::numeric_limits::infinity (); + } - float db = accurate_coefficient_to_dB (static_cast(k)); + float db = accurate_coefficient_to_dB (static_cast (k)); - return static_cast(db); + return static_cast (db); } double ArdourStrips::from_db (double db) { - if (db < -192) { - return 0; - } - - float k = dB_to_coefficient (static_cast(db)); + if (db < -192) { + return 0; + } - return static_cast(k); + float k = dB_to_coefficient (static_cast (db)); + + return static_cast (k); } double ArdourStrips::strip_gain (uint32_t strip_n) const { - return to_db (nth_strip (strip_n)->gain_control ()->get_value ()); + return to_db (nth_strip (strip_n)->gain_control ()->get_value ()); } void ArdourStrips::set_strip_gain (uint32_t strip_n, double db) { - nth_strip (strip_n)->gain_control ()->set_value (from_db (db), PBD::Controllable::NoGroup); + nth_strip (strip_n)->gain_control ()->set_value (from_db (db), PBD::Controllable::NoGroup); } double ArdourStrips::strip_pan (uint32_t strip_n) const { - // scale from [0.0 ; 1.0] to [-1.0 ; 1.0] - return 2.0 * nth_strip (strip_n)->pan_azimuth_control ()->get_value () - 1.0; + /* scale from [0.0 ; 1.0] to [-1.0 ; 1.0] */ + return 2.0 * nth_strip (strip_n)->pan_azimuth_control ()->get_value () - 1.0; } void @@ -103,129 +103,129 @@ ArdourStrips::set_strip_pan (uint32_t strip_n, double value) bool ArdourStrips::strip_mute (uint32_t strip_n) const { - return nth_strip (strip_n)->mute_control ()->muted (); + return nth_strip (strip_n)->mute_control ()->muted (); } void ArdourStrips::set_strip_mute (uint32_t strip_n, bool mute) { - nth_strip (strip_n)->mute_control ()->set_value (mute ? 1.0 : 0.0, PBD::Controllable::NoGroup); + nth_strip (strip_n)->mute_control ()->set_value (mute ? 1.0 : 0.0, PBD::Controllable::NoGroup); } bool ArdourStrips::strip_plugin_enabled (uint32_t strip_n, uint32_t plugin_n) const { - return strip_plugin_insert (strip_n, plugin_n)->enabled (); + return strip_plugin_insert (strip_n, plugin_n)->enabled (); } void ArdourStrips::set_strip_plugin_enabled (uint32_t strip_n, uint32_t plugin_n, bool enabled) { - strip_plugin_insert (strip_n, plugin_n)->enable (enabled); + strip_plugin_insert (strip_n, plugin_n)->enable (enabled); } TypedValue ArdourStrips::strip_plugin_param_value (uint32_t strip_n, uint32_t plugin_n, - uint32_t param_n) const + uint32_t param_n) const { - return plugin_param_value (strip_plugin_param_control (strip_n, plugin_n, param_n)); + return plugin_param_value (strip_plugin_param_control (strip_n, plugin_n, param_n)); } void ArdourStrips::set_strip_plugin_param_value (uint32_t strip_n, uint32_t plugin_n, - uint32_t param_n, TypedValue value) + uint32_t param_n, TypedValue value) { - boost::shared_ptr control = strip_plugin_param_control ( - strip_n, plugin_n, param_n); + boost::shared_ptr control = strip_plugin_param_control ( + strip_n, plugin_n, param_n); - if (control) { - ParameterDescriptor pd = control->desc (); - double dbl_val; + if (control) { + ParameterDescriptor pd = control->desc (); + double dbl_val; - if (pd.toggled) { - dbl_val = static_cast(static_cast(value)); - } else if (pd.enumeration || pd.integer_step) { - dbl_val = static_cast(static_cast(value)); - } else { - dbl_val = static_cast(value); - } + if (pd.toggled) { + dbl_val = static_cast (static_cast (value)); + } else if (pd.enumeration || pd.integer_step) { + dbl_val = static_cast (static_cast (value)); + } else { + dbl_val = static_cast (value); + } - control->set_value (dbl_val, PBD::Controllable::NoGroup); - } + control->set_value (dbl_val, PBD::Controllable::NoGroup); + } } uint32_t ArdourStrips::strip_count () const { - return _strips.size (); + return _strips.size (); } boost::shared_ptr ArdourStrips::nth_strip (uint32_t strip_n) const { - if (strip_n < _strips.size ()) { - return _strips[strip_n]; - } + if (strip_n < _strips.size ()) { + return _strips[strip_n]; + } - return boost::shared_ptr(); + return boost::shared_ptr (); } TypedValue ArdourStrips::plugin_param_value (boost::shared_ptr control) { - TypedValue value = TypedValue (); + TypedValue value = TypedValue (); - if (control) { - ParameterDescriptor pd = control->desc (); - - if (pd.toggled) { - value = TypedValue (static_cast(control->get_value ())); - } else if (pd.enumeration || pd.integer_step) { - value = TypedValue (static_cast(control->get_value ())); - } else { - value = TypedValue (control->get_value ()); - } - } + if (control) { + ParameterDescriptor pd = control->desc (); - return value; + if (pd.toggled) { + value = TypedValue (static_cast (control->get_value ())); + } else if (pd.enumeration || pd.integer_step) { + value = TypedValue (static_cast (control->get_value ())); + } else { + value = TypedValue (control->get_value ()); + } + } + + return value; } boost::shared_ptr ArdourStrips::strip_plugin_insert (uint32_t strip_n, uint32_t plugin_n) const { - boost::shared_ptr strip = nth_strip (strip_n); - boost::shared_ptr route = boost::dynamic_pointer_cast (strip); - boost::shared_ptr processor = route->nth_plugin (plugin_n); + boost::shared_ptr strip = nth_strip (strip_n); + boost::shared_ptr route = boost::dynamic_pointer_cast (strip); + boost::shared_ptr processor = route->nth_plugin (plugin_n); - if (processor) { - boost::shared_ptr insert = - boost::static_pointer_cast (processor); - - if (insert) { - return insert; - } - } + if (processor) { + boost::shared_ptr insert = + boost::static_pointer_cast (processor); - return boost::shared_ptr(); + if (insert) { + return insert; + } + } + + return boost::shared_ptr (); } boost::shared_ptr ArdourStrips::strip_plugin_param_control (uint32_t strip_n, uint32_t plugin_n, - uint32_t param_n) const + uint32_t param_n) const { - boost::shared_ptr insert = strip_plugin_insert (strip_n, plugin_n); + boost::shared_ptr insert = strip_plugin_insert (strip_n, plugin_n); - if (insert) { - bool ok = false; - boost::shared_ptr plugin = insert->plugin (); - uint32_t control_id = plugin->nth_parameter (param_n, ok); + if (insert) { + bool ok = false; + boost::shared_ptr plugin = insert->plugin (); + uint32_t control_id = plugin->nth_parameter (param_n, ok); - if (ok && plugin->parameter_is_input (control_id)) { - boost::shared_ptr control = - insert->automation_control (Evoral::Parameter(PluginAutomation, 0, control_id)); - return control; - } - } + if (ok && plugin->parameter_is_input (control_id)) { + boost::shared_ptr control = + insert->automation_control (Evoral::Parameter (PluginAutomation, 0, control_id)); + return control; + } + } - return boost::shared_ptr(); + return boost::shared_ptr (); } diff --git a/libs/surfaces/websockets/strips.h b/libs/surfaces/websockets/strips.h index 264ce85eb2..dea3a3acb0 100644 --- a/libs/surfaces/websockets/strips.h +++ b/libs/surfaces/websockets/strips.h @@ -24,47 +24,45 @@ class ArdourStrips : public SurfaceComponent { - public: +public: + ArdourStrips (ArdourSurface::ArdourWebsockets& surface) + : SurfaceComponent (surface){}; + virtual ~ArdourStrips (){}; - ArdourStrips (ArdourSurface::ArdourWebsockets& surface) : SurfaceComponent (surface) {}; - virtual ~ArdourStrips () {}; + int start (); + int stop (); - int start (); - int stop (); + static double to_db (double); + static double from_db (double); - static double to_db (double); - static double from_db (double); + double strip_gain (uint32_t) const; + void set_strip_gain (uint32_t, double); - double strip_gain (uint32_t) const; - void set_strip_gain (uint32_t, double); + double strip_pan (uint32_t) const; + void set_strip_pan (uint32_t, double); - double strip_pan (uint32_t) const; - void set_strip_pan (uint32_t, double); + bool strip_mute (uint32_t) const; + void set_strip_mute (uint32_t, bool); - bool strip_mute (uint32_t) const; - void set_strip_mute (uint32_t, bool); - - bool strip_plugin_enabled (uint32_t, uint32_t) const; - void set_strip_plugin_enabled (uint32_t, uint32_t, bool); + bool strip_plugin_enabled (uint32_t, uint32_t) const; + void set_strip_plugin_enabled (uint32_t, uint32_t, bool); - TypedValue strip_plugin_param_value (uint32_t, uint32_t, uint32_t) const; - void set_strip_plugin_param_value (uint32_t, uint32_t, uint32_t, TypedValue); + TypedValue strip_plugin_param_value (uint32_t, uint32_t, uint32_t) const; + void set_strip_plugin_param_value (uint32_t, uint32_t, uint32_t, TypedValue); - uint32_t strip_count () const; - boost::shared_ptr nth_strip (uint32_t) const; + uint32_t strip_count () const; + boost::shared_ptr nth_strip (uint32_t) const; - boost::shared_ptr strip_plugin_insert (uint32_t, uint32_t) const; - - boost::shared_ptr strip_plugin_param_control( - uint32_t, uint32_t, uint32_t) const; + boost::shared_ptr strip_plugin_insert (uint32_t, uint32_t) const; - static TypedValue plugin_param_value (boost::shared_ptr); + boost::shared_ptr strip_plugin_param_control ( + uint32_t, uint32_t, uint32_t) const; - private: - - typedef std::vector > StripableVector; - StripableVector _strips; + static TypedValue plugin_param_value (boost::shared_ptr); +private: + typedef std::vector > StripableVector; + StripableVector _strips; }; #endif // ardour_strips_h diff --git a/libs/surfaces/websockets/typed_value.cc b/libs/surfaces/websockets/typed_value.cc index 3c44c66d4e..8e01da9bf9 100644 --- a/libs/surfaces/websockets/typed_value.cc +++ b/libs/surfaces/websockets/typed_value.cc @@ -16,10 +16,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include #include -#include #include "typed_value.h" @@ -29,156 +29,161 @@ TypedValue::TypedValue () : _type (Empty) , _b (false) , _i (0) - , _d (0) { } + , _d (0) +{ +} TypedValue::TypedValue (bool value) : _type (Bool) , _b (value) , _i (0) - , _d (0) { } + , _d (0) +{ +} TypedValue::TypedValue (int value) : _type (Int) , _b (false) , _i (value) - , _d (0) { } + , _d (0) +{ +} TypedValue::TypedValue (double value) : _type (Double) , _b (false) , _i (0) - , _d (value) { } + , _d (value) +{ +} TypedValue::TypedValue (std::string value) : _type (String) , _b (false) , _i (0) , _d (0) - , _s (value) { } - -TypedValue::operator -bool () const + , _s (value) { - switch (_type) { - case Bool: - return _b; - case Int: - return _i != 0; - case Double: - return _d != 0; - case String: - return _s == "true"; - default: - return false; - } } -TypedValue::operator -int () const +TypedValue::operator bool () const { - switch (_type) { - case Int: - return _i; - case Bool: - return _b ? 1 : 0; - case Double: - return static_cast(_d); - case String: - try { - return boost::lexical_cast (_s); - } catch (const boost::bad_lexical_cast&) { - return 0; - } - default: - return 0; - } + switch (_type) { + case Bool: + return _b; + case Int: + return _i != 0; + case Double: + return _d != 0; + case String: + return _s == "true"; + default: + return false; + } } -TypedValue::operator -double () const +TypedValue::operator int () const { - switch (_type) { - case Double: - return _d; - case Bool: - return _b ? 1.f : 0; - case Int: - return static_cast(_i); - case String: - try { - return boost::lexical_cast (_s); - } catch (const boost::bad_lexical_cast&) { - return 0; - } - default: - return 0; - } + switch (_type) { + case Int: + return _i; + case Bool: + return _b ? 1 : 0; + case Double: + return static_cast (_d); + case String: + try { + return boost::lexical_cast (_s); + } catch (const boost::bad_lexical_cast&) { + return 0; + } + default: + return 0; + } } -TypedValue::operator -std::string () const +TypedValue::operator double () const { - switch (_type) { - case String: - return _s; - case Bool: - return _b ? "true" : "false"; - case Int: - return boost::lexical_cast (_i); - case Double: - return boost::lexical_cast (_d); - default: - return ""; - } + switch (_type) { + case Double: + return _d; + case Bool: + return _b ? 1.f : 0; + case Int: + return static_cast (_i); + case String: + try { + return boost::lexical_cast (_s); + } catch (const boost::bad_lexical_cast&) { + return 0; + } + default: + return 0; + } } - + +TypedValue::operator std::string () const +{ + switch (_type) { + case String: + return _s; + case Bool: + return _b ? "true" : "false"; + case Int: + return boost::lexical_cast (_i); + case Double: + return boost::lexical_cast (_d); + default: + return ""; + } +} + bool TypedValue::operator== (const TypedValue& other) const { - if (_type != other._type) { - // make an exception when comparing doubles and ints - // for example browser json implementations will send - // 1 instead of 1.0 removing any type hint - if ((_type == Int) && (other._type == Double)) { - return fabs (static_cast(_i) - other._d) < DBL_TOLERANCE; - } else if ((_type == Double) && (other._type == Int)) { - return fabs (_d - static_cast(other._i)) < DBL_TOLERANCE; - } + if (_type != other._type) { + /* make an exception when comparing doubles and ints + * for example browser json implementations will send + * 1 instead of 1.0 removing any type hint + */ + if ((_type == Int) && (other._type == Double)) { + return fabs (static_cast (_i) - other._d) < DBL_TOLERANCE; + } else if ((_type == Double) && (other._type == Int)) { + return fabs (_d - static_cast (other._i)) < DBL_TOLERANCE; + } - return false; - } + return false; + } - switch (_type) { - case Bool: - return _b == other._b; - case Int: - return _i == other._i; - case Double: { - double inf = std::numeric_limits::infinity (); - return ((_d == inf) && (other._d == inf)) - || ((_d == -inf) && (other._d == -inf)) - || (fabs (_d - other._d) < DBL_TOLERANCE); - } - case String: - return _s == other._s; - default: - return false; - } + switch (_type) { + case Bool: + return _b == other._b; + case Int: + return _i == other._i; + case Double: { + double inf = std::numeric_limits::infinity (); + return ((_d == inf) && (other._d == inf)) || ((_d == -inf) && (other._d == -inf)) || (fabs (_d - other._d) < DBL_TOLERANCE); + } + case String: + return _s == other._s; + default: + return false; + } } bool TypedValue::operator!= (const TypedValue& other) const { - return !(*this == other); + return !(*this == other); } std::string TypedValue::debug_str () const { - char s[256]; + char s[256]; - sprintf(s, "type = %d; b = %d; i = %d; d = %f; s = \"%s\"", - _type, _b, _i, _d, _s.c_str ()); + sprintf (s, "type = %d; b = %d; i = %d; d = %f; s = \"%s\"", + _type, _b, _i, _d, _s.c_str ()); - return s; + return s; } diff --git a/libs/surfaces/websockets/typed_value.h b/libs/surfaces/websockets/typed_value.h index a30ef3e940..b79f17792f 100644 --- a/libs/surfaces/websockets/typed_value.h +++ b/libs/surfaces/websockets/typed_value.h @@ -23,43 +23,46 @@ class TypedValue { - public: +public: + enum Type { + Empty, + Bool, + Int, + Double, + String + }; - enum Type { - Empty, - Bool, - Int, - Double, - String - }; + TypedValue (); + TypedValue (bool); + TypedValue (int); + TypedValue (double); + TypedValue (std::string); - TypedValue (); - TypedValue (bool); - TypedValue (int); - TypedValue (double); - TypedValue (std::string); + bool empty () const + { + return _type == Empty; + }; + Type type () const + { + return _type; + }; - bool empty () const { return _type == Empty; }; - Type type () const { return _type; }; + operator bool () const; + operator int () const; + operator double () const; + operator std::string () const; - operator bool () const; - operator int () const; - operator double () const; - operator std::string () const; + bool operator== (const TypedValue& other) const; + bool operator!= (const TypedValue& other) const; - bool operator== (const TypedValue& other) const; - bool operator!= (const TypedValue& other) const; - - std::string debug_str () const; - - private: - - Type _type; - bool _b; - int _i; - double _d; - std::string _s; + std::string debug_str () const; +private: + Type _type; + bool _b; + int _i; + double _d; + std::string _s; }; #endif // typed_value_h