#include "ardour/control_protocol_manager.h"
#include "ardour/search_paths.h"
-
+#include "ardour/selection.h"
+#include "ardour/session.h"
using namespace ARDOUR;
using namespace std;
ControlProtocolManager* ControlProtocolManager::_instance = 0;
const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
-
+PBD::Signal1<void,StripableNotificationListPtr> ControlProtocolManager::StripableSelectionChanged;
ControlProtocolInfo::~ControlProtocolInfo ()
{
ControlProtocolManager::~ControlProtocolManager()
{
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::WriterLock lm (protocols_lock);
for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
delete (*i);
for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
+ (*p)->protocol = 0; // protocol was already destroyed above.
delete (*p);
}
{
SessionHandlePtr::set_session (s);
- if (_session) {
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ if (!_session) {
+ return;
+ }
+
+ {
+ Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
if ((*i)->requested || (*i)->mandatory) {
}
}
}
+
+ CoreSelection::StripableAutomationControls sac;
+ _session->selection().get_stripables (sac);
+
+ if (!sac.empty()) {
+ StripableNotificationListPtr v (new StripableNotificationList);
+ for (CoreSelection::StripableAutomationControls::iterator i = sac.begin(); i != sac.end(); ++i) {
+ if ((*i).stripable) {
+ v->push_back (boost::weak_ptr<Stripable> ((*i).stripable));
+ }
+ }
+ if (!v->empty()) {
+ StripableSelectionChanged (v); /* EMIT SIGNAL */
+ }
+ }
}
int
* before the process cycle stops and ports vanish.
*/
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::WriterLock lm (protocols_lock);
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
delete *p;
cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
if (lock_required) {
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::WriterLock lm (protocols_lock);
list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
if (p != control_protocols.end()) {
control_protocols.erase (p);
cpi.protocol = 0;
- delete cpi.state;
- cpi.state = 0;
+ if (lock_required) {
+ /* the lock is only required when the protocol is torn down from the GUI.
+ * If a user disables a protocol, we take this as indicator to forget the
+ * state.
+ */
+ delete cpi.state;
+ cpi.state = 0;
+ }
delete (Glib::Module*) cpi.descriptor->module;
/* cpi->descriptor is now inaccessible since dlclose() or equivalent
* has been performed, and the descriptor is (or could be) a static
return;
}
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
if ((*i)->mandatory && ((*i)->protocol == 0)) {
XMLNodeList clist;
XMLNodeConstIterator citer;
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::WriterLock lm (protocols_lock);
clist = node.children();
ControlProtocolInfo* cpi = cpi_by_name (name);
if (cpi) {
- delete cpi->state;
- cpi->state = new XMLNode (**citer);
-
+#ifndef NDEBUG
std::cerr << "protocol " << name << " active ? " << active << std::endl;
+#endif
if (active) {
+ delete cpi->state;
+ cpi->state = new XMLNode (**citer);
if (_session) {
instantiate (*cpi);
} else {
cpi->requested = true;
}
} else {
+ if (!cpi->state) {
+ cpi->state = new XMLNode (**citer);
+ cpi->state->set_property (X_("active"), false);
+ }
+ cpi->requested = false;
if (_session) {
teardown (*cpi, false);
- } else {
- cpi->requested = false;
}
}
} else {
ControlProtocolManager::get_state ()
{
XMLNode* root = new XMLNode (state_node_name);
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
void
ControlProtocolManager::midi_connectivity_established ()
{
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
(*p)->midi_connectivity_established ();
void
ControlProtocolManager::register_request_buffer_factories ()
{
- Glib::Threads::Mutex::Lock lm (protocols_lock);
+ Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
}
}
}
+
+void
+ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp)
+{
+ /* this sets up the (static) data structures owned by ControlProtocol
+ that are "shared" across all control protocols.
+ */
+
+ DEBUG_TRACE (DEBUG::Selection, string_compose ("Surface manager: selection changed, now %1 stripables\n", sp ? sp->size() : -1));
+ StripableSelectionChanged (sp); /* EMIT SIGNAL */
+
+ /* now give each protocol the chance to respond to the selection change
+ */
+
+ {
+ Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
+
+ for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
+ DEBUG_TRACE (DEBUG::Selection, string_compose ("selection change notification for surface \"%1\"\n", (*p)->name()));
+ (*p)->stripable_selection_changed ();
+ }
+ }
+}