From 8a17b0fb9073bb21ef2c718113f9e41359faf4fe Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 30 Dec 2009 12:41:10 +0000 Subject: [PATCH] make generic MIDI control track remote control ID changes; fixup messes in the editor+mixer that caused excessive calls to SyncOrderKey stuff. generic MIDI still doesn't track editor/mixer order changes if we're not syncing both windows git-svn-id: svn://localhost/ardour2/branches/3.0@6413 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor_routes.cc | 2 - gtk2_ardour/mixer_ui.cc | 6 +- libs/ardour/ardour/route.h | 7 ++ libs/ardour/route.cc | 3 + libs/ardour/session.cc | 2 + .../generic_midi_control_protocol.cc | 67 +++----------- .../surfaces/generic_midi/midicontrollable.cc | 88 ++++++++++++++----- libs/surfaces/generic_midi/midicontrollable.h | 17 ++-- 8 files changed, 107 insertions(+), 85 deletions(-) diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index 2ee8927fd2..1a55d91573 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -892,8 +892,6 @@ EditorRoutes::move_selected_tracks (bool up) } _model->reorder (neworder); - - _session->sync_order_keys (N_ ("editor")); } void diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index b750f8a470..87c48a4348 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -689,7 +689,9 @@ void Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/) { strip_redisplay_does_not_sync_order_keys = true; - _session->set_remote_control_ids(); + if (!strip_redisplay_does_not_reset_order_keys) { + _session->set_remote_control_ids(); + } redisplay_track_list (); strip_redisplay_does_not_sync_order_keys = false; } @@ -699,7 +701,6 @@ Mixer_UI::track_list_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel:: { // never reset order keys because of a property change strip_redisplay_does_not_reset_order_keys = true; - _session->set_remote_control_ids(); redisplay_track_list (); strip_redisplay_does_not_reset_order_keys = false; } @@ -709,7 +710,6 @@ Mixer_UI::track_list_delete (const Gtk::TreeModel::Path&) { /* this could require an order sync */ if (_session && !_session->deletion_in_progress()) { - _session->set_remote_control_ids(); redisplay_track_list (); } } diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 9630975d1f..bb02396773 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -306,8 +306,15 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void set_remote_control_id (uint32_t id); uint32_t remote_control_id () const; + + /* for things concerned about *this* route's RID */ + PBD::Signal0 RemoteControlIDChanged; + /* for things concerned about any route's RID changes */ + + static PBD::Signal0 RemoteControlIDChange; + void sync_order_keys (std::string const &); static PBD::Signal1 SyncOrderKeys; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 09e38eaa86..9c08080d2d 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -25,6 +25,7 @@ #include "pbd/xml++.h" #include "pbd/enumwriter.h" #include "pbd/memento_command.h" +#include "pbd/stacktrace.h" #include "evoral/Curve.hpp" @@ -64,6 +65,7 @@ using namespace PBD; uint32_t Route::order_key_cnt = 0; PBD::Signal1 Route::SyncOrderKeys; +PBD::Signal0 Route::RemoteControlIDChange; Route::Route (Session& sess, string name, Flag flg, DataType default_type) : SessionObject (sess, name) @@ -177,6 +179,7 @@ Route::set_remote_control_id (uint32_t id) if (id != _remote_control_id) { _remote_control_id = id; RemoteControlIDChanged (); + RemoteControlIDChange (); } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 19aca23c34..1f61322b4b 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2170,6 +2170,7 @@ Session::add_routes (RouteList& new_routes, bool save) } RouteAdded (new_routes); /* EMIT SIGNAL */ + Route::RemoteControlIDChange (); /* EMIT SIGNAL */ } void @@ -4183,6 +4184,7 @@ Session::sync_order_keys (std::string const & base) } Route::SyncOrderKeys (base); // EMIT SIGNAL + Route::RemoteControlIDChange (); // EMIT SIGNAL } diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index e7fa9018c9..6a29c27684 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -82,6 +82,7 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1)); Session::SendFeedback.connect (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());; + Route::RemoteControlIDChange.connect (*this, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context()); reload_maps (); } @@ -407,7 +408,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, // Create a MIDIControllable MIDIControllable* mc = new MIDIControllable (*_port, *control); - + // Remove any old binding for this midi channel/type/value pair // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) { @@ -426,7 +427,6 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, // Update the MIDI Controllable based on the the pos param // Here is where a table lookup for user mappings could go; for now we'll just wing it... mc->bind_midi(channel, MIDI::controller, value); - mc->set_learned (true); controllables.push_back (mc); } @@ -518,6 +518,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version) if (c) { MIDIControllable* mc = new MIDIControllable (*_port, *c); + if (mc->set_state (**niter, version) == 0) { controllables.push_back (mc); } @@ -623,8 +624,6 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath) } else if (child->property ("function")) { - cerr << "try to create a function from " << child->property ("function")->value() << endl; - /* function */ MIDIFunction* mf; @@ -686,7 +685,13 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node) prop = node.property (X_("uri")); uri = prop->value(); - MIDIControllable* mc = new MIDIControllable (*_port, uri, false); + MIDIControllable* mc = new MIDIControllable (*_port, false); + + if (mc->init (uri)) { + delete mc; + return 0; + } + mc->bind_midi (channel, ev, detail); cerr << "New MC with URI " << uri << " on channel " << (int) channel << " detail = " << (int) detail << endl; @@ -703,55 +708,11 @@ GenericMidiControlProtocol::reset_controllables () MIDIControllable* existingBinding = (*iter); if (!existingBinding->learned()) { - cerr << "Look for " << existingBinding->current_uri() << endl; - - /* parse URI to get remote control ID and "what" is to be controlled */ - - std::string uri = existingBinding->current_uri(); - string::size_type last_slash; - string useful_part; - - if ((last_slash = uri.find_last_of ('/')) == string::npos) { - existingBinding->set_controllable (0); - continue; + uint32_t rid = existingBinding->rid(); + if (existingBinding->bank_relative()) { + rid += _current_bank * _bank_size; } - - useful_part = uri.substr (last_slash+1); - - char ridstr[64]; - char what[64]; - - if (sscanf (useful_part.c_str(), "rid=%63[^?]?%63s", ridstr, what) != 2) { - existingBinding->set_controllable (0); - continue; - } - - /* now parse RID string and determine if its a bank-driven ID */ - - uint32_t rid; - - if (strncmp (ridstr, "B-", 2) == 0) { - - if (sscanf (&ridstr[2], "%" PRIu32, &rid) != 1) { - existingBinding->set_controllable (0); - continue; - } - - rid += _bank_size * _current_bank; - - } else { - if (sscanf (&ridstr[2], "%" PRIu32, &rid) != 1) { - existingBinding->set_controllable (0); - continue; - } - } - - /* go get it (allowed to fail) */ - - cerr << "Look for controllable via " << rid << " and " << what << endl; - - boost::shared_ptr c = session->controllable_by_rid_and_name (rid, what); - cerr << "\tgot " << c << endl; + boost::shared_ptr c = session->controllable_by_rid_and_name (rid, existingBinding->what().c_str()); existingBinding->set_controllable (c.get()); } } diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc index 6b0a08b620..0cebabd80b 100644 --- a/libs/surfaces/generic_midi/midicontrollable.cc +++ b/libs/surfaces/generic_midi/midicontrollable.cc @@ -17,6 +17,9 @@ */ +#define __STDC_FORMAT_MACROS 1 +#include + #include /* for sprintf, sigh */ #include @@ -35,16 +38,32 @@ using namespace MIDI; using namespace PBD; using namespace ARDOUR; -MIDIControllable::MIDIControllable (Port& p, const string& c, bool is_bistate) - : controllable (0), _current_uri (c), _port (p), bistate (is_bistate) +MIDIControllable::MIDIControllable (Port& p, bool is_bistate) + : controllable (0) + , _port (p) + , bistate (is_bistate) { - init (); + _learned = false; /* from URI */ + setting = false; + last_value = 0; // got a better idea ? + control_type = none; + _control_description = "MIDI Control: none"; + control_additional = (byte) -1; + feedback = true; // for now } MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool is_bistate) - : controllable (&c), _current_uri (c.uri()), _port (p), bistate (is_bistate) + : controllable (&c) + , _port (p) + , bistate (is_bistate) { - init (); + _learned = true; /* from controllable */ + setting = false; + last_value = 0; // got a better idea ? + control_type = none; + _control_description = "MIDI Control: none"; + control_additional = (byte) -1; + feedback = true; // for now } MIDIControllable::~MIDIControllable () @@ -52,20 +71,52 @@ MIDIControllable::~MIDIControllable () drop_external_control (); } -void -MIDIControllable::init () +int +MIDIControllable::init (const std::string& s) { - _learned = false; - setting = false; - last_value = 0; // got a better idea ? - control_type = none; - _control_description = "MIDI Control: none"; - control_additional = (byte) -1; - feedback = true; // for now + _current_uri = s; - /* use channel 0 ("1") as the initial channel */ + if (!_current_uri.empty()) { - midi_rebind (0); + /* parse URI to get remote control ID and "what" is to be controlled */ + + string::size_type last_slash; + string useful_part; + + if ((last_slash = _current_uri.find_last_of ('/')) == string::npos) { + return -1; + } + + useful_part = _current_uri.substr (last_slash+1); + + char ridstr[64]; + char what[64]; + + if (sscanf (useful_part.c_str(), "rid=%63[^?]?%63s", ridstr, what) != 2) { + return -1; + } + + _what = what; + + /* now parse RID string and determine if its a bank-driven ID */ + + if (strncmp (ridstr, "B-", 2) == 0) { + + if (sscanf (&ridstr[2], "%" PRIu32, &_rid) != 1) { + return -1; + } + + _bank_relative = true; + + } else { + if (sscanf (&ridstr[2], "%" PRIu32, &_rid) != 1) { + return -1; + } + _bank_relative = false; + } + } + + return 0; } void @@ -83,10 +134,7 @@ MIDIControllable::midi_forget () void MIDIControllable::drop_external_control () { - midi_sense_connection[0].disconnect (); - midi_sense_connection[1].disconnect (); - midi_learn_connection.disconnect (); - + midi_forget (); control_type = none; control_additional = (byte) -1; } diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h index cd42afde56..b5aa115fee 100644 --- a/libs/surfaces/generic_midi/midicontrollable.h +++ b/libs/surfaces/generic_midi/midicontrollable.h @@ -42,13 +42,16 @@ class MIDIControllable : public PBD::Stateful { public: MIDIControllable (MIDI::Port&, PBD::Controllable&, bool bistate = false); - MIDIControllable (MIDI::Port&, const std::string& uri, bool bistate = false); + MIDIControllable (MIDI::Port&, bool bistate = false); virtual ~MIDIControllable (); - void rediscover_controllable (); + int init (const std::string&); + + void rediscover_controllable (); + bool bank_relative() const { return _bank_relative; } + uint32_t rid() const { return _rid; } + std::string what() const { return _what; } - bool ok() const { return !_current_uri.empty(); } - void send_feedback (); MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool force = false); @@ -64,7 +67,6 @@ class MIDIControllable : public PBD::Stateful float control_to_midi(float val); float midi_to_control(float val); - void set_learned (bool yn) { _learned = yn; } bool learned() const { return _learned; } MIDI::Port& get_port() const { return _port; } @@ -98,8 +100,9 @@ class MIDIControllable : public PBD::Stateful MIDI::channel_t control_channel; std::string _control_description; bool feedback; - - void init (); + uint32_t _rid; + std::string _what; + bool _bank_relative; void midi_receiver (MIDI::Parser &p, MIDI::byte *, size_t); void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on);