diff options
author | Robin Gareus <robin@gareus.org> | 2019-03-23 02:09:39 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2019-03-23 02:09:39 +0100 |
commit | e9b36f2beab7d7c22d321291e5cfe39f5b0a4349 (patch) | |
tree | f39fcf5c0b867fcd373aa15c9f71b218793eb0b4 /libs/surfaces/generic_midi/generic_midi_control_protocol.cc | |
parent | 16fe286ed97e89a6768e0eb1e983ab55cc396eaf (diff) |
Update GenericMidiControlProtocol to use shared/weak Controllable pointers
This fixes a race-condition when a controllable is deleted
while sending feedback to the device.
Previously there was a race-condition MIDIControllable::write_feedback()
triggered from rt-thread, processed in Surface-thread and deleting
a route or processor.
This is a first step, currently state-restore is not fully functional
session->controllable_by_id() does not cover all Controllables.
Diffstat (limited to 'libs/surfaces/generic_midi/generic_midi_control_protocol.cc')
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index 6bc2fc813a..be835b7ffb 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -106,10 +106,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) * thread */ -#if 0 // XXX temp. disabled for API change -Controllab:le::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1)); - Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1)); -#endif + Controllable::StartLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1)); + Controllable::StopLearning.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1)); /* this signal is emitted by the process() callback, and if * send_feedback() is going to do anything, it should do it in the @@ -345,9 +343,10 @@ GenericMidiControlProtocol::_send_feedback () } bool -GenericMidiControlProtocol::start_learning (Controllable* c) +GenericMidiControlProtocol::start_learning (boost::weak_ptr <Controllable> wc) { - if (c == 0) { + boost::shared_ptr<Controllable> c = wc.lock (); + if (!c) { return false; } @@ -401,7 +400,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c) } if (!mc) { - mc = new MIDIControllable (this, *_input_port->parser(), *c, false); + mc = new MIDIControllable (this, *_input_port->parser(), c, false); own_mc = true; } @@ -443,8 +442,13 @@ GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc) } void -GenericMidiControlProtocol::stop_learning (Controllable* c) +GenericMidiControlProtocol::stop_learning (boost::weak_ptr<PBD::Controllable> wc) { + boost::shared_ptr<Controllable> c = wc.lock (); + if (!c) { + return; + } + Glib::Threads::Mutex::Lock lm (pending_lock); Glib::Threads::Mutex::Lock lm2 (controllables_lock); MIDIControllable* dptr = 0; @@ -627,10 +631,10 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version) if ((*niter)->get_property ("id", id)) { DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Relearned binding for session: Control ID: %1\n", id.to_s())); - Controllable* c = 0; // Controllable::by_id (id); // XXX temp. disabled for API change + boost::shared_ptr<PBD::Controllable> c = session->controllable_by_id (id); // XXX are these all? if (c) { - MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false); + MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), c, false); if (mc->set_state (**niter, version) == 0) { controllables.push_back (mc); @@ -1503,9 +1507,9 @@ GenericMidiControlProtocol::input_port() const } void -GenericMidiControlProtocol::maybe_start_touch (Controllable* controllable) +GenericMidiControlProtocol::maybe_start_touch (boost::shared_ptr<Controllable> controllable) { - AutomationControl *actl = dynamic_cast<AutomationControl*> (controllable); + boost::shared_ptr<AutomationControl> actl = boost::dynamic_pointer_cast<AutomationControl> (controllable); if (actl) { actl->start_touch (session->audible_sample ()); } |