}
_model->reorder (neworder);
-
- _session->sync_order_keys (N_ ("editor"));
}
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;
}
{
// 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;
}
{
/* this could require an order sync */
if (_session && !_session->deletion_in_progress()) {
- _session->set_remote_control_ids();
redisplay_track_list ();
}
}
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;
#include "pbd/xml++.h"
#include "pbd/enumwriter.h"
#include "pbd/memento_command.h"
+#include "pbd/stacktrace.h"
#include "evoral/Curve.hpp"
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)
if (id != _remote_control_id) {
_remote_control_id = id;
RemoteControlIDChanged ();
+ RemoteControlIDChange ();
}
}
}
RouteAdded (new_routes); /* EMIT SIGNAL */
+ Route::RemoteControlIDChange (); /* EMIT SIGNAL */
}
void
}
Route::SyncOrderKeys (base); // EMIT SIGNAL
+ Route::RemoteControlIDChange (); // EMIT SIGNAL
}
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 ();
}
// 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) {
// 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);
}
if (c) {
MIDIControllable* mc = new MIDIControllable (*_port, *c);
+
if (mc->set_state (**niter, version) == 0) {
controllables.push_back (mc);
}
} else if (child->property ("function")) {
- cerr << "try to create a function from " << child->property ("function")->value() << endl;
-
/* function */
MIDIFunction* mf;
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;
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());
}
}
*/
+#define __STDC_FORMAT_MACROS 1
+#include <stdint.h>
+
#include <cstdio> /* for sprintf, sigh */
#include <climits>
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 ()
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
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;
}
{
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 ();
+ 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);
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; }
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);