mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
add Ctl_Dial to get better behaviour when binding a MIDI controller KNOB/DIAL to a toggled controllable.
No intent to change Ctl_Momentary or Ctl_Toggle behaviour, plus I tried to document what they are intended to support
This commit is contained in:
parent
870625973e
commit
8725ed5bd1
3 changed files with 42 additions and 26 deletions
|
|
@ -836,6 +836,9 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
|
||||||
} else if ((prop = node.property (X_("ctl-toggle"))) !=0) {
|
} else if ((prop = node.property (X_("ctl-toggle"))) !=0) {
|
||||||
ctltype = MIDIControllable::Ctl_Toggle;
|
ctltype = MIDIControllable::Ctl_Toggle;
|
||||||
ev = MIDI::controller;
|
ev = MIDI::controller;
|
||||||
|
} else if ((prop = node.property (X_("ctl-dial"))) !=0) {
|
||||||
|
ctltype = MIDIControllable::Ctl_Dial;
|
||||||
|
ev = MIDI::controller;
|
||||||
} else if ((prop = node.property (X_("note"))) != 0) {
|
} else if ((prop = node.property (X_("note"))) != 0) {
|
||||||
ev = MIDI::on;
|
ev = MIDI::on;
|
||||||
} else if ((prop = node.property (X_("pgm"))) != 0) {
|
} else if ((prop = node.property (X_("pgm"))) != 0) {
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser&
|
||||||
_encoder = No_enc;
|
_encoder = No_enc;
|
||||||
setting = false;
|
setting = false;
|
||||||
last_value = 0; // got a better idea ?
|
last_value = 0; // got a better idea ?
|
||||||
|
last_incoming = 256; // any out of band value
|
||||||
last_controllable_value = 0.0f;
|
last_controllable_value = 0.0f;
|
||||||
control_type = none;
|
control_type = none;
|
||||||
control_rpn = -1;
|
control_rpn = -1;
|
||||||
|
|
@ -135,6 +136,8 @@ MIDIControllable::set_controllable (Controllable* c)
|
||||||
last_controllable_value = 0.0f; // is there a better value?
|
last_controllable_value = 0.0f; // is there a better value?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_incoming = 256;
|
||||||
|
|
||||||
if (controllable) {
|
if (controllable) {
|
||||||
controllable->Destroyed.connect (controllable_death_connection, MISSING_INVALIDATOR,
|
controllable->Destroyed.connect (controllable_death_connection, MISSING_INVALIDATOR,
|
||||||
boost::bind (&MIDIControllable::drop_controllable, this, _1),
|
boost::bind (&MIDIControllable::drop_controllable, this, _1),
|
||||||
|
|
@ -372,32 +375,40 @@ MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* toggle control: make the toggle flip only if the
|
switch (get_ctltype()) {
|
||||||
* incoming control value exceeds 0.5 (0x40), so that
|
case Ctl_Dial:
|
||||||
* the typical button which sends "CC N=0x7f" on press
|
/* toggle value whenever direction of knob motion changes */
|
||||||
* and "CC N=0x0" on release can be used to drive
|
if (last_incoming > 127) {
|
||||||
* toggles on press.
|
/* relax ... first incoming message */
|
||||||
*
|
} else {
|
||||||
* No other arrangement really makes sense for a toggle
|
if (msg->value > last_incoming) {
|
||||||
* controllable. Acting on the press+release makes the
|
controllable->set_value (1.0, Controllable::UseGroup);
|
||||||
* action momentary, which is almost never
|
} else {
|
||||||
* desirable. If the physical button only sends a
|
controllable->set_value (0.0, Controllable::UseGroup);
|
||||||
* message on press (or release), then it will be
|
}
|
||||||
* expected to send a controller value >= 0.5
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("dial Midi CC %1 value 1 %2\n", (int) msg->controller_number, current_uri()));
|
||||||
* (0x40). It is hard to imagine why anyone would make
|
}
|
||||||
* a MIDI controller button that sent 0x0 when pressed.
|
last_incoming = msg->value;
|
||||||
*/
|
break;
|
||||||
if (msg->value >= 0x40) {
|
case Ctl_Momentary:
|
||||||
controllable->set_value (controllable->get_value() >= 0.5 ? 0.0 : 1.0, Controllable::UseGroup);
|
/* toggle it if over 64, otherwise leave it alone. This behaviour that works with buttons which send a value > 64 each
|
||||||
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi CC %1 value 1 %2\n", (int) msg->controller_number, current_uri()));
|
* time they are pressed.
|
||||||
} else {
|
*/
|
||||||
switch (get_ctltype()) {
|
if (msg->value >= 0x40) {
|
||||||
case Ctl_Momentary:
|
controllable->set_value (controllable->get_value() >= 0.5 ? 0.0 : 1.0, Controllable::UseGroup);
|
||||||
break;
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("toggle Midi CC %1 value 1 %2\n", (int) msg->controller_number, current_uri()));
|
||||||
case Ctl_Toggle:
|
}
|
||||||
controllable->set_value (0.0, Controllable::NoGroup);
|
break;
|
||||||
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi CC %1 value 0 %2\n", (int) msg->controller_number, current_uri()));
|
case Ctl_Toggle:
|
||||||
break;
|
/* toggle if value is over 64, otherwise turn it off. This is behaviour designed for buttons which send a value > 64 when pressed,
|
||||||
|
maintain state (i.e. they know they were pressed) and then send zero the next time.
|
||||||
|
*/
|
||||||
|
if (msg->value >= 0x40) {
|
||||||
|
controllable->set_value (controllable->get_value() >= 0.5 ? 0.0 : 1.0, Controllable::UseGroup);
|
||||||
|
} else {
|
||||||
|
controllable->set_value (0.0, Controllable::NoGroup);
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Midi CC %1 value 0 %2\n", (int) msg->controller_number, current_uri()));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ class MIDIControllable : public PBD::Stateful
|
||||||
enum CtlType {
|
enum CtlType {
|
||||||
Ctl_Momentary,
|
Ctl_Momentary,
|
||||||
Ctl_Toggle,
|
Ctl_Toggle,
|
||||||
|
Ctl_Dial,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Encoder {
|
enum Encoder {
|
||||||
|
|
@ -119,6 +120,7 @@ class MIDIControllable : public PBD::Stateful
|
||||||
MIDI::Parser& _parser;
|
MIDI::Parser& _parser;
|
||||||
bool setting;
|
bool setting;
|
||||||
int last_value;
|
int last_value;
|
||||||
|
int last_incoming;
|
||||||
float last_controllable_value;
|
float last_controllable_value;
|
||||||
bool _momentary;
|
bool _momentary;
|
||||||
bool _is_gain_controller;
|
bool _is_gain_controller;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue