diff --git a/libs/surfaces/websockets/ardour_websockets.cc b/libs/surfaces/websockets/ardour_websockets.cc index 61129dc1e8..adefb26174 100644 --- a/libs/surfaces/websockets/ardour_websockets.cc +++ b/libs/surfaces/websockets/ardour_websockets.cc @@ -39,8 +39,8 @@ ArdourWebsockets::ArdourWebsockets (Session& s) , AbstractUI (name ()) , _mixer (*this) , _transport (*this) - , _feedback (*this) , _server (*this) + , _feedback (*this) , _dispatcher (*this) { _components.push_back (&_mixer); diff --git a/libs/surfaces/websockets/ardour_websockets.h b/libs/surfaces/websockets/ardour_websockets.h index 53f64e10f5..2c71d09ed4 100644 --- a/libs/surfaces/websockets/ardour_websockets.h +++ b/libs/surfaces/websockets/ardour_websockets.h @@ -95,8 +95,8 @@ protected: private: ArdourMixer _mixer; ArdourTransport _transport; - ArdourFeedback _feedback; WebsocketsServer _server; + ArdourFeedback _feedback; WebsocketsDispatcher _dispatcher; std::vector _components; diff --git a/libs/surfaces/websockets/feedback.cc b/libs/surfaces/websockets/feedback.cc index 5fa42a7cca..9542c1beff 100644 --- a/libs/surfaces/websockets/feedback.cc +++ b/libs/surfaces/websockets/feedback.cc @@ -20,6 +20,8 @@ #include "ardour/session.h" #include "ardour/tempo.h" +#include "pbd/abstract_ui.cc" // instantiate template + #include "feedback.h" #include "transport.h" #include "server.h" @@ -28,9 +30,20 @@ // TO DO: make this configurable #define POLL_INTERVAL_MS 100 +#define OPTIONAL_CONNECT_HELPER(s,c) if (server ().should_request_write ()) \ + s.connect (c, MISSING_INVALIDATOR, boost::bind \ + (ServerWriteObserver (), &server ()), &_helper); + using namespace ARDOUR; using namespace ArdourSurface; +struct ServerWriteObserver { + void operator() (WebsocketsServer *server) + { + server->request_write (); + } +}; + struct TransportObserver { void operator() (ArdourFeedback* p) { @@ -97,6 +110,24 @@ struct PluginParamValueObserver { } }; +FeedbackHelperUI::FeedbackHelperUI() + : AbstractUI ("feedback_helper") +{ + pthread_set_name ("test_ui_thread"); // FIXME - needed? + run_loop_thread = Glib::Threads::Thread::self (); + set_event_loop_for_thread (this); + ARDOUR::SessionEvent::create_per_thread_pool ("test", 512); // FIXME - needed? +} + +void +FeedbackHelperUI::do_request (BaseUI::BaseRequestObject* req) { + if (req->type == CallSlot) { + call_slot (MISSING_INVALIDATOR, req->the_slot); + } else if (req->type == Quit) { + quit (); + } +}; + int ArdourFeedback::start () { @@ -107,7 +138,15 @@ ArdourFeedback::start () Glib::RefPtr periodic_timeout = Glib::TimeoutSource::create (POLL_INTERVAL_MS); _periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &ArdourFeedback::poll)); - periodic_timeout->attach (main_loop ()->get_context ()); + + // server must be started before feedback otherwise + // should_request_write() will always return false + if (!server ().should_request_write ()) { + periodic_timeout->attach (main_loop ()->get_context ()); + } else { + _helper.run(); + periodic_timeout->attach (_helper.main_loop()->get_context ()); + } return 0; } @@ -115,6 +154,10 @@ ArdourFeedback::start () int ArdourFeedback::stop () { + if (server ().should_request_write ()) { + _helper.quit(); + } + _periodic_connection.disconnect (); _transport_connections.drop_connections (); @@ -176,6 +219,10 @@ ArdourFeedback::poll () const update_all (Node::strip_meter, it->first, db); } + if (server ().should_request_write ()) { + server ().request_write (); + } + return true; } @@ -185,10 +232,15 @@ ArdourFeedback::observe_transport () ARDOUR::Session& sess = session (); sess.TransportStateChange.connect (_transport_connections, MISSING_INVALIDATOR, boost::bind (TransportObserver (), this), event_loop ()); + OPTIONAL_CONNECT_HELPER(sess.TransportStateChange, _transport_connections); + sess.RecordStateChanged.connect (_transport_connections, MISSING_INVALIDATOR, boost::bind (RecordStateObserver (), this), event_loop ()); + OPTIONAL_CONNECT_HELPER(sess.RecordStateChanged, _transport_connections); + sess.tempo_map ().PropertyChanged.connect (_transport_connections, MISSING_INVALIDATOR, boost::bind (TempoObserver (), this), event_loop ()); + OPTIONAL_CONNECT_HELPER(sess.tempo_map ().PropertyChanged, _transport_connections); } void @@ -202,14 +254,17 @@ ArdourFeedback::observe_mixer () stripable->gain_control ()->Changed.connect (*it->second, MISSING_INVALIDATOR, boost::bind (StripGainObserver (), this, strip_id), event_loop ()); + OPTIONAL_CONNECT_HELPER(stripable->gain_control ()->Changed, *it->second); if (stripable->pan_azimuth_control ()) { stripable->pan_azimuth_control ()->Changed.connect (*it->second, MISSING_INVALIDATOR, boost::bind (StripPanObserver (), this, strip_id), event_loop ()); + OPTIONAL_CONNECT_HELPER(stripable->pan_azimuth_control ()->Changed, *it->second); } stripable->mute_control ()->Changed.connect (*it->second, MISSING_INVALIDATOR, boost::bind (StripMuteObserver (), this, strip_id), event_loop ()); + OPTIONAL_CONNECT_HELPER(stripable->mute_control ()->Changed, *it->second); observe_strip_plugins (strip_id, strip->plugins ()); } @@ -229,6 +284,7 @@ ArdourFeedback::observe_strip_plugins (uint32_t strip_id, ArdourMixerStrip::Plug if (control) { control->Changed.connect (*plugin, MISSING_INVALIDATOR, boost::bind (PluginBypassObserver (), this, strip_id, plugin_id), event_loop ()); + OPTIONAL_CONNECT_HELPER(control->Changed, *plugin); } for (uint32_t param_id = 0; param_id < plugin->param_count (); ++param_id) { @@ -239,6 +295,7 @@ ArdourFeedback::observe_strip_plugins (uint32_t strip_id, ArdourMixerStrip::Plug boost::bind (PluginParamValueObserver (), this, strip_id, plugin_id, param_id, boost::weak_ptr(control)), event_loop ()); + OPTIONAL_CONNECT_HELPER(control->Changed, *plugin); } catch (ArdourMixerNotFoundException& e) { /* ignore */ } diff --git a/libs/surfaces/websockets/feedback.h b/libs/surfaces/websockets/feedback.h index 6cac0debdc..fdf600d3ee 100644 --- a/libs/surfaces/websockets/feedback.h +++ b/libs/surfaces/websockets/feedback.h @@ -21,7 +21,9 @@ #include #include -#include +#include + +#include "pbd/abstract_ui.h" #include "component.h" #include "typed_value.h" @@ -29,6 +31,17 @@ namespace ArdourSurface { +class FeedbackHelperUI : public AbstractUI +{ +public: + FeedbackHelperUI (); + ~FeedbackHelperUI () {}; + +protected: + virtual void do_request (BaseUI::BaseRequestObject*); + +}; + class ArdourFeedback : public SurfaceComponent { public: @@ -49,6 +62,9 @@ private: PBD::ScopedConnectionList _transport_connections; sigc::connection _periodic_connection; + // Only needed for server event loop integration method 3 + FeedbackHelperUI _helper; + bool poll () const; void observe_transport (); diff --git a/libs/surfaces/websockets/server.cc b/libs/surfaces/websockets/server.cc index 6c4c51fd4a..7dc6497a06 100644 --- a/libs/surfaces/websockets/server.cc +++ b/libs/surfaces/websockets/server.cc @@ -195,6 +195,7 @@ WebsocketsServer::stop () if (_g_source) { // Method 3 g_source_destroy (_g_source); + lws_cancel_service (_lws_context); } if (_lws_context) { diff --git a/libs/surfaces/websockets/server.h b/libs/surfaces/websockets/server.h index 204a58ec9b..2986914b5f 100644 --- a/libs/surfaces/websockets/server.h +++ b/libs/surfaces/websockets/server.h @@ -112,8 +112,11 @@ private: GSource* _g_source; - void request_write (); - static gboolean glib_idle_callback (void *data); + static gboolean glib_idle_callback (void *); + +public: + bool should_request_write () { return _g_source != 0; } + void request_write (); };