diff options
Diffstat (limited to 'libs/surfaces/generic_midi')
3 files changed, 55 insertions, 70 deletions
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index e9f12638b6..c3d7aabfaf 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -30,6 +30,7 @@ #include "ardour/session.h" #include "ardour/route.h" +#include "ardour/midi_ui.h" #include "generic_midi_control_protocol.h" #include "midicontrollable.h" @@ -39,8 +40,11 @@ using namespace PBD; #include "i18n.h" +#define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */ +#define ui_bind(x) boost::protect (boost::bind ((x))) + GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) - : ControlProtocol (s, _("Generic MIDI")) + : ControlProtocol (s, _("Generic MIDI"), MidiControlUI::instance()) { MIDI::Manager* mm = MIDI::Manager::instance(); @@ -59,16 +63,14 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) _feedback_interval = 10000; // microseconds last_feedback_time = 0; - auto_binding = FALSE; + /* XXX is it right to do all these in the same thread as whatever emits the signal? */ - Controllable::StartLearning.connect (*this, boost::bind (&GenericMidiControlProtocol::start_learning, this, _1)); - Controllable::StopLearning.connect (*this, boost::bind (&GenericMidiControlProtocol::stop_learning, this, _1)); - Controllable::CreateBinding.connect (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3)); - Controllable::DeleteBinding.connect (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1)); + 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)); + Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3)); + Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1)); - Session::SendFeedback.connect (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this)); - Session::AutoBindingOn.connect (*this, boost::bind (&GenericMidiControlProtocol::auto_binding_on, this)); - Session::AutoBindingOff.connect (*this, boost::bind (&GenericMidiControlProtocol::auto_binding_off, this)); + Session::SendFeedback.connect (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());; } GenericMidiControlProtocol::~GenericMidiControlProtocol () @@ -177,7 +179,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c) MIDIPendingControllable* element = new MIDIPendingControllable; element->first = mc; - c->LearningFinished.connect (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc)); + c->LearningFinished.connect_same_thread (element->second, boost::bind (&GenericMidiControlProtocol::learning_stopped, this, mc)); pending_controllables.push_back (element); } @@ -289,18 +291,6 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, } } -void -GenericMidiControlProtocol::auto_binding_on() -{ - auto_binding = TRUE; -} - -void -GenericMidiControlProtocol::auto_binding_off() -{ - auto_binding = FALSE; -} - XMLNode& GenericMidiControlProtocol::get_state () { @@ -345,46 +335,43 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version) _feedback_interval = 10000; } - if ( !auto_binding ) { - - boost::shared_ptr<Controllable> c; - - { - Glib::Mutex::Lock lm (pending_lock); - for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) { - delete *i; - } - pending_controllables.clear (); - } - - Glib::Mutex::Lock lm2 (controllables_lock); - controllables.clear (); - nlist = node.children(); // "controls" - - if (nlist.empty()) { - return 0; + boost::shared_ptr<Controllable> c; + + { + Glib::Mutex::Lock lm (pending_lock); + for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) { + delete *i; } + pending_controllables.clear (); + } + + Glib::Mutex::Lock lm2 (controllables_lock); + controllables.clear (); + nlist = node.children(); // "controls" + + if (nlist.empty()) { + return 0; + } + + nlist = nlist.front()->children (); - nlist = nlist.front()->children (); + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + if ((prop = (*niter)->property ("id")) != 0) { - if ((prop = (*niter)->property ("id")) != 0) { - - ID id = prop->value (); - c = session->controllable_by_id (id); - - if (c) { - MIDIControllable* mc = new MIDIControllable (*_port, *c); - if (mc->set_state (**niter, version) == 0) { - controllables.insert (mc); - } - - } else { - warning << string_compose ( - _("Generic MIDI control: controllable %1 not found in session (ignored)"), - id) << endmsg; + ID id = prop->value (); + c = session->controllable_by_id (id); + + if (c) { + MIDIControllable* mc = new MIDIControllable (*_port, *c); + if (mc->set_state (**niter, version) == 0) { + controllables.insert (mc); } + + } else { + warning << string_compose ( + _("Generic MIDI control: controllable %1 not found in session (ignored)"), + id) << endmsg; } } } diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index c42d796e81..39958bcf26 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -44,7 +44,6 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { ARDOUR::microseconds_t last_feedback_time; bool do_feedback; - bool auto_binding; void _send_feedback (); void send_feedback (); @@ -64,10 +63,6 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { void create_binding (PBD::Controllable*, int, int); void delete_binding (PBD::Controllable*); - - void auto_binding_on(); - void auto_binding_off(); - }; #endif /* ardour_generic_midi_control_protocol_h */ diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc index a1f5abf3b0..d6b4007194 100644 --- a/libs/surfaces/generic_midi/midicontrollable.cc +++ b/libs/surfaces/generic_midi/midicontrollable.cc @@ -19,10 +19,13 @@ #include <cstdio> /* for sprintf, sigh */ #include <climits> + #include "pbd/error.h" #include "pbd/xml++.h" + #include "midi++/port.h" #include "midi++/channel.h" + #include "ardour/automation_control.h" #include "midicontrollable.h" @@ -111,7 +114,7 @@ void MIDIControllable::learn_about_external_control () { drop_external_control (); - _port.input()->any.connect (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3)); + _port.input()->any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3)); } void @@ -285,43 +288,43 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional) int chn_i = chn; switch (ev) { case MIDI::off: - p.channel_note_off[chn_i].connect (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2)); + p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2)); /* if this is a bistate, connect to noteOn as well, and we'll toggle back and forth between the two. */ if (bistate) { - p.channel_note_on[chn_i].connect (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2)); + p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2)); } _control_description = "MIDI control: NoteOff"; break; case MIDI::on: - p.channel_note_on[chn_i].connect (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2)); + p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2)); if (bistate) { - p.channel_note_off[chn_i].connect (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2)); + p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2)); } _control_description = "MIDI control: NoteOn"; break; case MIDI::controller: - p.channel_controller[chn_i].connect (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2)); + p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2)); snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional); _control_description = buf; break; case MIDI::program: if (!bistate) { - p.channel_program_change[chn_i].connect (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2)); + p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2)); _control_description = "MIDI control: ProgramChange"; } break; case MIDI::pitchbend: if (!bistate) { - p.channel_pitchbend[chn_i].connect (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2)); + p.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2)); _control_description = "MIDI control: Pitchbend"; } break; |