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
This commit is contained in:
Paul Davis 2009-12-30 12:41:10 +00:00
parent 59a61c4357
commit 8a17b0fb90
8 changed files with 107 additions and 85 deletions

View file

@ -892,8 +892,6 @@ EditorRoutes::move_selected_tracks (bool up)
}
_model->reorder (neworder);
_session->sync_order_keys (N_ ("editor"));
}
void

View file

@ -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 ();
}
}

View file

@ -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<void> RemoteControlIDChanged;
/* for things concerned about any route's RID changes */
static PBD::Signal0<void> RemoteControlIDChange;
void sync_order_keys (std::string const &);
static PBD::Signal1<void,std::string const &> SyncOrderKeys;

View file

@ -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<void,string const&> Route::SyncOrderKeys;
PBD::Signal0<void> 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 ();
}
}

View file

@ -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
}

View file

@ -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<Controllable> c = session->controllable_by_rid_and_name (rid, what);
cerr << "\tgot " << c << endl;
boost::shared_ptr<Controllable> c = session->controllable_by_rid_and_name (rid, existingBinding->what().c_str());
existingBinding->set_controllable (c.get());
}
}

View file

@ -17,6 +17,9 @@
*/
#define __STDC_FORMAT_MACROS 1
#include <stdint.h>
#include <cstdio> /* for sprintf, sigh */
#include <climits>
@ -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;
}

View file

@ -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);