summaryrefslogtreecommitdiff
path: root/libs/surfaces
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-12-28 10:14:17 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2015-12-28 10:14:17 -0500
commit0d9efc11484c901795ff4e9549a1a39715d0474d (patch)
tree956ab3cd570670bcb1ff68856553f5aec4a8e470 /libs/surfaces
parentdb4834027858b10f313c822c7fb3fad1617f11aa (diff)
redesign cross-thread registration/signalling system
This new design will work even when threads that need to receive messages from RT threads are created *after* the RT threads. The existing design would fail because the RT thread(s) would never be known the later created threads, and so signals emitted by the RT thread and causing call_slot() in the receiver would end up being enqueued using a lock-protected list. The new design ensures that communication always uses a lock-free FIFO instead
Diffstat (limited to 'libs/surfaces')
-rw-r--r--libs/surfaces/control_protocol/control_protocol/control_protocol.h28
-rw-r--r--libs/surfaces/faderport/faderport.cc19
-rw-r--r--libs/surfaces/faderport/faderport.h3
-rw-r--r--libs/surfaces/faderport/faderport_interface.cc9
-rw-r--r--libs/surfaces/mackie/interface.cc10
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc19
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h1
-rw-r--r--libs/surfaces/osc/interface.cc9
-rw-r--r--libs/surfaces/osc/osc.cc19
-rw-r--r--libs/surfaces/osc/osc.h2
-rw-r--r--libs/surfaces/wiimote/wiimote.cc2
11 files changed, 93 insertions, 28 deletions
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
index 8edb3f39a7..71e875419a 100644
--- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h
+++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
@@ -154,16 +154,24 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
extern "C" {
class ControlProtocolDescriptor {
public:
- const char* name; /* descriptive */
- const char* id; /* unique and version-specific */
- void* ptr; /* protocol can store a value here */
- void* module; /* not for public access */
- int mandatory; /* if non-zero, always load and do not make optional */
- bool supports_feedback; /* if true, protocol has toggleable feedback mechanism */
- bool (*probe)(ControlProtocolDescriptor*);
- ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
- void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
-
+ const char* name; /* descriptive */
+ const char* id; /* unique and version-specific */
+ void* ptr; /* protocol can store a value here */
+ void* module; /* not for public access */
+ int mandatory; /* if non-zero, always load and do not make optional */
+ bool supports_feedback; /* if true, protocol has toggleable feedback mechanism */
+ bool (*probe)(ControlProtocolDescriptor*);
+ ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
+ void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
+ /* this is required if the control protocol connects to signals
+ from libardour. they all do. It should allocate a
+ type-specific request buffer for the calling thread, and
+ store it in a thread-local location that will be used to
+ find it when sending the event loop a message
+ (e.g. call_slot()). It should also return the allocated
+ buffer as a void*.
+ */
+ void* (*request_buffer_factory)(uint32_t);
};
}
diff --git a/libs/surfaces/faderport/faderport.cc b/libs/surfaces/faderport/faderport.cc
index 135943d34f..f10f70dce5 100644
--- a/libs/surfaces/faderport/faderport.cc
+++ b/libs/surfaces/faderport/faderport.cc
@@ -66,7 +66,7 @@ using namespace std;
FaderPort::FaderPort (Session& s)
: ControlProtocol (s, _("Faderport"))
- , AbstractUI<FaderPortRequest> ("faderport")
+ , AbstractUI<FaderPortRequest> (name())
, gui (0)
, connection_state (ConnectionState (0))
, _device_active (false)
@@ -210,6 +210,17 @@ FaderPort::~FaderPort ()
tear_down_gui ();
}
+void*
+FaderPort::request_factory (uint32_t num_requests)
+{
+ /* AbstractUI<T>::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);
+}
+
void
FaderPort::start_midi_handling ()
{
@@ -267,10 +278,10 @@ FaderPort::thread_init ()
{
struct sched_param rtparam;
- pthread_set_name (X_("FaderPort"));
+ pthread_set_name (event_loop_name().c_str());
- PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("FaderPort"), 2048);
- ARDOUR::SessionEvent::create_per_thread_pool (X_("FaderPort"), 128);
+ PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+ ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
memset (&rtparam, 0, sizeof (rtparam));
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
diff --git a/libs/surfaces/faderport/faderport.h b/libs/surfaces/faderport/faderport.h
index 6643e22369..025cf09e00 100644
--- a/libs/surfaces/faderport/faderport.h
+++ b/libs/surfaces/faderport/faderport.h
@@ -85,6 +85,7 @@ class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortReq
there's no way to know if the device exists or not.
*/
static bool probe() { return true; }
+ static void* request_factory (uint32_t);
XMLNode& get_state ();
int set_state (const XMLNode&, int version);
@@ -160,7 +161,7 @@ class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortReq
std::string get_action (ButtonID, bool on_press, FaderPort::ButtonState = ButtonState (0));
std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
-
+
private:
boost::shared_ptr<ARDOUR::Route> _current_route;
boost::weak_ptr<ARDOUR::Route> pre_master_route;
diff --git a/libs/surfaces/faderport/faderport_interface.cc b/libs/surfaces/faderport/faderport_interface.cc
index dcfebff190..e7ea5af396 100644
--- a/libs/surfaces/faderport/faderport_interface.cc
+++ b/libs/surfaces/faderport/faderport_interface.cc
@@ -56,6 +56,12 @@ probe_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/)
return FaderPort::probe ();
}
+static void*
+faderport_request_buffer_factory (uint32_t num_requests)
+{
+ return FaderPort::request_factory (num_requests);
+}
+
static ControlProtocolDescriptor faderport_midi_descriptor = {
/*name : */ "Faderport",
/*id : */ "uri://ardour.org/surfaces/faderport:0",
@@ -65,7 +71,8 @@ static ControlProtocolDescriptor faderport_midi_descriptor = {
/*supports_feedback : */ true,
/*probe : */ probe_faderport_midi_protocol,
/*initialize : */ new_faderport_midi_protocol,
- /*destroy : */ delete_faderport_midi_protocol
+ /*destroy : */ delete_faderport_midi_protocol,
+ /*request_buffer_factory */ faderport_request_buffer_factory
};
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &faderport_midi_descriptor; }
diff --git a/libs/surfaces/mackie/interface.cc b/libs/surfaces/mackie/interface.cc
index 1a9760bcbe..3b04770660 100644
--- a/libs/surfaces/mackie/interface.cc
+++ b/libs/surfaces/mackie/interface.cc
@@ -74,6 +74,12 @@ probe_mackie_protocol (ControlProtocolDescriptor*)
return MackieControlProtocol::probe();
}
+static void*
+mackie_request_buffer_factory (uint32_t num_requests)
+{
+ return MackieControlProtocol::request_factory (num_requests);
+}
+
// Field names commented out by JE - 06-01-2010
static ControlProtocolDescriptor mackie_descriptor = {
/*name : */ "Mackie",
@@ -88,8 +94,8 @@ static ControlProtocolDescriptor mackie_descriptor = {
/*supports_feedback : */ false,
/*probe : */ probe_mackie_protocol,
/*initialize : */ new_mackie_protocol,
- /*destroy : */ delete_mackie_protocol
+ /*destroy : */ delete_mackie_protocol,
+ /*request_buffer_factory */ mackie_request_buffer_factory
};
-
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &mackie_descriptor; }
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index dfd3fe6334..ea5e43d2ba 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -105,7 +105,7 @@ bool MackieControlProtocol::probe()
MackieControlProtocol::MackieControlProtocol (Session& session)
: ControlProtocol (session, X_("Mackie"))
- , AbstractUI<MackieControlUIRequest> ("mackie")
+ , AbstractUI<MackieControlUIRequest> (name())
, _current_initial_bank (0)
, _frame_last (0)
, _timecode_type (ARDOUR::AnyTime::BBT)
@@ -183,10 +183,10 @@ MackieControlProtocol::thread_init ()
{
struct sched_param rtparam;
- pthread_set_name (X_("MackieControl"));
+ pthread_set_name (event_loop_name().c_str());
- PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
- ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
+ PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+ ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
memset (&rtparam, 0, sizeof (rtparam));
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
@@ -2251,3 +2251,14 @@ MackieControlProtocol::global_index (Strip& strip)
return global;
}
+
+void*
+MackieControlProtocol::request_factory (uint32_t num_requests)
+{
+ /* AbstractUI<T>::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);
+}
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index a1cee8ec7f..802d5a6235 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -178,6 +178,7 @@ class MackieControlProtocol
*/
static bool probe();
+ static void* request_factory (uint32_t);
mutable Glib::Threads::Mutex surfaces_lock;
typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces;
diff --git a/libs/surfaces/osc/interface.cc b/libs/surfaces/osc/interface.cc
index d26a31788e..35b313945d 100644
--- a/libs/surfaces/osc/interface.cc
+++ b/libs/surfaces/osc/interface.cc
@@ -46,6 +46,12 @@ probe_osc_protocol (ControlProtocolDescriptor* /*descriptor*/)
return true; // we can always do OSC
}
+static void*
+osc_request_buffer_factory (uint32_t num_requests)
+{
+ return OSC::request_factory (num_requests);
+}
+
static ControlProtocolDescriptor osc_descriptor = {
/*name : */ "Open Sound Control (OSC)",
/*id : */ "uri://ardour.org/surfaces/osc:0",
@@ -55,7 +61,8 @@ static ControlProtocolDescriptor osc_descriptor = {
/*supports_feedback : */ true,
/*probe : */ probe_osc_protocol,
/*initialize : */ new_osc_protocol,
- /*destroy : */ delete_osc_protocol
+ /*destroy : */ delete_osc_protocol,
+ /*request_buffer_factory */ osc_request_buffer_factory
};
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &osc_descriptor; }
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index 13261feffa..49c8bcc57c 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -73,7 +73,7 @@ static void error_callback(int, const char *, const char *)
OSC::OSC (Session& s, uint32_t port)
: ControlProtocol (s, X_("Open Sound Control (OSC)"))
- , AbstractUI<OSCUIRequest> ("osc")
+ , AbstractUI<OSCUIRequest> (name())
, local_server (0)
, remote_server (0)
, _port(port)
@@ -96,6 +96,17 @@ OSC::~OSC()
_instance = 0;
}
+void*
+OSC::request_factory (uint32_t num_requests)
+{
+ /* AbstractUI<T>::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);
+}
+
void
OSC::do_request (OSCUIRequest* req)
{
@@ -226,7 +237,7 @@ OSC::start ()
void
OSC::thread_init ()
{
- pthread_set_name (X_("OSC"));
+ pthread_set_name (event_loop_name().c_str());
if (_osc_unix_server) {
Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
@@ -244,8 +255,8 @@ OSC::thread_init ()
g_source_ref (remote_server);
}
- PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("OSC"), 2048);
- SessionEvent::create_per_thread_pool (X_("OSC"), 128);
+ PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+ SessionEvent::create_per_thread_pool (event_loop_name(), 128);
}
int
diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h
index 7c24869a00..3718d25525 100644
--- a/libs/surfaces/osc/osc.h
+++ b/libs/surfaces/osc/osc.h
@@ -79,6 +79,8 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
int start ();
int stop ();
+ static void* request_factory (uint32_t);
+
protected:
void thread_init ();
void do_request (OSCUIRequest*);
diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc
index aa36cdf300..db5fb55c2a 100644
--- a/libs/surfaces/wiimote/wiimote.cc
+++ b/libs/surfaces/wiimote/wiimote.cc
@@ -164,7 +164,7 @@ WiimoteControlProtocol::thread_init ()
pthread_set_name (X_("wiimote"));
// allow to make requests to the GUI and RT thread(s)
- PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self (), X_("wiimote"), 2048);
+ PBD::notify_event_loops_about_thread_creation (pthread_self (), X_("wiimote"), 2048);
BasicUI::register_thread ("wiimote");
// connect a Wiimote