mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-08 06:35:46 +01:00
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:
parent
59a61c4357
commit
8a17b0fb90
8 changed files with 107 additions and 85 deletions
|
|
@ -892,8 +892,6 @@ EditorRoutes::move_selected_tracks (bool up)
|
|||
}
|
||||
|
||||
_model->reorder (neworder);
|
||||
|
||||
_session->sync_order_keys (N_ ("editor"));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue