mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 15:54:57 +01:00
provide limited momentary note on/off MIDI binding option; remove some debugging output; add bank selector to generic MIDI UI
git-svn-id: svn://localhost/ardour2/branches/3.0@6430 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
732ac7756a
commit
6572f421a4
8 changed files with 212 additions and 63 deletions
|
|
@ -2852,15 +2852,31 @@ void
|
||||||
Route::SoloControllable::set_value (float val)
|
Route::SoloControllable::set_value (float val)
|
||||||
{
|
{
|
||||||
bool bval = ((val >= 0.5f) ? true: false);
|
bool bval = ((val >= 0.5f) ? true: false);
|
||||||
|
# if 0
|
||||||
|
this is how it should be done
|
||||||
|
|
||||||
|
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||||
|
rl->push_back (route);
|
||||||
|
|
||||||
|
if (Config->get_solo_control_is_listen_control()) {
|
||||||
|
_session.set_listen (rl, bval);
|
||||||
|
} else {
|
||||||
|
_session.set_solo (rl, bval);
|
||||||
|
}
|
||||||
|
#else
|
||||||
route.set_solo (bval, this);
|
route.set_solo (bval, this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
Route::SoloControllable::get_value (void) const
|
Route::SoloControllable::get_value (void) const
|
||||||
{
|
{
|
||||||
|
if (Config->get_solo_control_is_listen_control()) {
|
||||||
|
return route.listening() ? 1.0f : 0.0f;
|
||||||
|
} else {
|
||||||
return route.self_soloed() ? 1.0f : 0.0f;
|
return route.self_soloed() ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Route::set_block_size (nframes_t nframes)
|
Route::set_block_size (nframes_t nframes)
|
||||||
|
|
|
||||||
|
|
@ -146,10 +146,8 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
|
if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
|
||||||
cerr << "Session non-writable based on " << _path << endl;
|
|
||||||
_writable = false;
|
_writable = false;
|
||||||
} else {
|
} else {
|
||||||
cerr << "Session writable based on " << _path << endl;
|
|
||||||
_writable = true;
|
_writable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2713,6 +2711,7 @@ Session::controllable_by_descriptor (const ControllableDescriptor& desc)
|
||||||
case ControllableDescriptor::Gain:
|
case ControllableDescriptor::Gain:
|
||||||
c = r->gain_control ();
|
c = r->gain_control ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ControllableDescriptor::Solo:
|
case ControllableDescriptor::Solo:
|
||||||
c = r->solo_control();
|
c = r->solo_control();
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -49,18 +49,6 @@ ControllableDescriptor::set (const std::string& str)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "Path: " << endl;
|
|
||||||
for (vector<string>::iterator x = path.begin(); x != path.end(); ++x) {
|
|
||||||
cerr << '[' << (*x) << "] ";
|
|
||||||
}
|
|
||||||
cerr << endl;
|
|
||||||
|
|
||||||
cerr << "Rest: " << endl;
|
|
||||||
for (vector<string>::iterator x = rest.begin(); x != rest.end(); ++x) {
|
|
||||||
cerr << '[' << (*x) << "] ";
|
|
||||||
}
|
|
||||||
cerr << endl;
|
|
||||||
|
|
||||||
if (path[0] == "route" || path[0] == "rid") {
|
if (path[0] == "route" || path[0] == "rid") {
|
||||||
|
|
||||||
_top_level_type = RemoteControlID;
|
_top_level_type = RemoteControlID;
|
||||||
|
|
|
||||||
|
|
@ -296,3 +296,98 @@ BasicUI::sample_to_timecode (nframes_t sample, Timecode::Time& timecode, bool us
|
||||||
session->sample_to_timecode (sample, *((Timecode::Time*)&timecode), use_offset, use_subframes);
|
session->sample_to_timecode (sample, *((Timecode::Time*)&timecode), use_offset, use_subframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
this stuff is waiting to go in so that all UI's can offer complex solo/mute functionality
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicUI::solo_release (boost::shared_ptr<Route> r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicUI::solo_press (boost::shared_ptr<Route> r, bool momentary, bool global, bool exclusive, bool isolate, bool solo_group)
|
||||||
|
{
|
||||||
|
if (momentary) {
|
||||||
|
_solo_release = new SoloMuteRelease (_route->soloed());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global) {
|
||||||
|
|
||||||
|
if (_solo_release) {
|
||||||
|
_solo_release->routes = _session->get_routes ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config->get_solo_control_is_listen_control()) {
|
||||||
|
_session->set_listen (_session->get_routes(), !_route->listening(), Session::rt_cleanup, true);
|
||||||
|
} else {
|
||||||
|
_session->set_solo (_session->get_routes(), !_route->soloed(), Session::rt_cleanup, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (exclusive) {
|
||||||
|
|
||||||
|
if (_solo_release) {
|
||||||
|
_solo_release->exclusive = true;
|
||||||
|
|
||||||
|
boost::shared_ptr<RouteList> routes = _session->get_routes();
|
||||||
|
|
||||||
|
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
|
||||||
|
if ((*i)->soloed ()) {
|
||||||
|
_solo_release->routes_on->push_back (*i);
|
||||||
|
} else {
|
||||||
|
_solo_release->routes_off->push_back (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config->get_solo_control_is_listen_control()) {
|
||||||
|
/* ??? we need a just_one_listen() method */
|
||||||
|
} else {
|
||||||
|
_session->set_just_one_solo (_route, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (isolate) {
|
||||||
|
|
||||||
|
// shift-click: toggle solo isolated status
|
||||||
|
|
||||||
|
_route->set_solo_isolated (!_route->solo_isolated(), this);
|
||||||
|
delete _solo_release;
|
||||||
|
_solo_release = 0;
|
||||||
|
|
||||||
|
} else if (solo_group) {
|
||||||
|
|
||||||
|
/* Primary-button1: solo mix group.
|
||||||
|
NOTE: Primary-button2 is MIDI learn.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (_route->route_group()) {
|
||||||
|
|
||||||
|
if (_solo_release) {
|
||||||
|
_solo_release->routes = _route->route_group()->route_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config->get_solo_control_is_listen_control()) {
|
||||||
|
_session->set_listen (_route->route_group()->route_list(), !_route->listening(), Session::rt_cleanup, true);
|
||||||
|
} else {
|
||||||
|
_session->set_solo (_route->route_group()->route_list(), !_route->soloed(), Session::rt_cleanup, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* click: solo this route */
|
||||||
|
|
||||||
|
boost::shared_ptr<RouteList> rl (new RouteList);
|
||||||
|
rl->push_back (route());
|
||||||
|
|
||||||
|
if (_solo_release) {
|
||||||
|
_solo_release->routes = rl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config->get_solo_control_is_listen_control()) {
|
||||||
|
_session->set_listen (rl, !_route->listening());
|
||||||
|
} else {
|
||||||
|
_session->set_solo (rl, !_route->soloed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -315,7 +315,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mc) {
|
if (!mc) {
|
||||||
mc = new MIDIControllable (*_port, *c);
|
mc = new MIDIControllable (*_port, *c, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -410,7 +410,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
|
||||||
MIDI::byte value = control_number;
|
MIDI::byte value = control_number;
|
||||||
|
|
||||||
// Create a MIDIControllable
|
// Create a MIDIControllable
|
||||||
MIDIControllable* mc = new MIDIControllable (*_port, *control);
|
MIDIControllable* mc = new MIDIControllable (*_port, *control, false);
|
||||||
|
|
||||||
// Remove any old binding for this midi channel/type/value pair
|
// 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
|
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
|
||||||
|
|
@ -520,7 +520,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
|
||||||
c = session->controllable_by_id (id);
|
c = session->controllable_by_id (id);
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
MIDIControllable* mc = new MIDIControllable (*_port, *c);
|
MIDIControllable* mc = new MIDIControllable (*_port, *c, false);
|
||||||
|
|
||||||
if (mc->set_state (**niter, version) == 0) {
|
if (mc->set_state (**niter, version) == 0) {
|
||||||
controllables.push_back (mc);
|
controllables.push_back (mc);
|
||||||
|
|
@ -655,6 +655,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
|
||||||
string uri;
|
string uri;
|
||||||
MIDI::eventType ev;
|
MIDI::eventType ev;
|
||||||
int intval;
|
int intval;
|
||||||
|
bool momentary;
|
||||||
|
|
||||||
if ((prop = node.property (X_("ctl"))) != 0) {
|
if ((prop = node.property (X_("ctl"))) != 0) {
|
||||||
ev = MIDI::controller;
|
ev = MIDI::controller;
|
||||||
|
|
@ -685,10 +686,16 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
|
||||||
channel -= 1;
|
channel -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((prop = node.property (X_("momentary"))) != 0) {
|
||||||
|
momentary = string_is_affirmative (prop->value());
|
||||||
|
} else {
|
||||||
|
momentary = false;
|
||||||
|
}
|
||||||
|
|
||||||
prop = node.property (X_("uri"));
|
prop = node.property (X_("uri"));
|
||||||
uri = prop->value();
|
uri = prop->value();
|
||||||
|
|
||||||
MIDIControllable* mc = new MIDIControllable (*_port, false);
|
MIDIControllable* mc = new MIDIControllable (*_port, momentary);
|
||||||
|
|
||||||
if (mc->init (uri)) {
|
if (mc->init (uri)) {
|
||||||
delete mc;
|
delete mc;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
#include <gtkmm/comboboxtext.h>
|
#include <gtkmm/comboboxtext.h>
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <gtkmm/box.h>
|
#include <gtkmm/box.h>
|
||||||
|
#include <gtkmm/adjustment.h>
|
||||||
|
#include <gtkmm/spinbutton.h>
|
||||||
|
|
||||||
#include "gtkmm2ext/utils.h"
|
#include "gtkmm2ext/utils.h"
|
||||||
|
|
||||||
|
|
@ -21,8 +23,11 @@ public:
|
||||||
private:
|
private:
|
||||||
GenericMidiControlProtocol& cp;
|
GenericMidiControlProtocol& cp;
|
||||||
Gtk::ComboBoxText map_combo;
|
Gtk::ComboBoxText map_combo;
|
||||||
|
Gtk::Adjustment bank_adjustment;
|
||||||
|
Gtk::SpinButton bank_spinner;
|
||||||
|
|
||||||
void binding_changed ();
|
void binding_changed ();
|
||||||
|
void bank_change ();
|
||||||
};
|
};
|
||||||
|
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
@ -56,6 +61,8 @@ GenericMidiControlProtocol::build_gui ()
|
||||||
|
|
||||||
GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
|
GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
|
||||||
: cp (p)
|
: cp (p)
|
||||||
|
, bank_adjustment (1, 1, 100, 1, 10)
|
||||||
|
, bank_spinner (bank_adjustment)
|
||||||
{
|
{
|
||||||
vector<string> popdowns;
|
vector<string> popdowns;
|
||||||
popdowns.push_back (_("Reset All"));
|
popdowns.push_back (_("Reset All"));
|
||||||
|
|
@ -74,6 +81,7 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
|
||||||
|
|
||||||
map_combo.signal_changed().connect (sigc::mem_fun (*this, &GMCPGUI::binding_changed));
|
map_combo.signal_changed().connect (sigc::mem_fun (*this, &GMCPGUI::binding_changed));
|
||||||
|
|
||||||
|
set_spacing (6);
|
||||||
set_border_width (12);
|
set_border_width (12);
|
||||||
|
|
||||||
Label* label = manage (new Label (_("Available MIDI bindings:")));
|
Label* label = manage (new Label (_("Available MIDI bindings:")));
|
||||||
|
|
@ -83,17 +91,42 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
|
||||||
hpack->pack_start (*label, false, false);
|
hpack->pack_start (*label, false, false);
|
||||||
hpack->pack_start (map_combo, false, false);
|
hpack->pack_start (map_combo, false, false);
|
||||||
|
|
||||||
pack_start (*hpack, false, false);
|
|
||||||
|
|
||||||
map_combo.show ();
|
map_combo.show ();
|
||||||
label->show ();
|
label->show ();
|
||||||
hpack->show ();
|
hpack->show ();
|
||||||
|
|
||||||
|
pack_start (*hpack, false, false);
|
||||||
|
|
||||||
|
|
||||||
|
bank_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &GMCPGUI::bank_change));
|
||||||
|
|
||||||
|
label = manage (new Label (_("Current Bank:")));
|
||||||
|
hpack = manage (new HBox);
|
||||||
|
|
||||||
|
hpack->set_spacing (6);
|
||||||
|
hpack->pack_start (*label, false, false);
|
||||||
|
hpack->pack_start (bank_spinner, false, false);
|
||||||
|
|
||||||
|
|
||||||
|
bank_spinner.show ();
|
||||||
|
label->show ();
|
||||||
|
hpack->show ();
|
||||||
|
|
||||||
|
pack_start (*hpack, false, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GMCPGUI::~GMCPGUI ()
|
GMCPGUI::~GMCPGUI ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMCPGUI::bank_change ()
|
||||||
|
{
|
||||||
|
int new_bank = bank_adjustment.get_value() - 1;
|
||||||
|
cp.set_current_bank (new_bank);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GMCPGUI::binding_changed ()
|
GMCPGUI::binding_changed ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@
|
||||||
|
|
||||||
#define __STDC_FORMAT_MACROS 1
|
#define __STDC_FORMAT_MACROS 1
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <cmath>
|
||||||
#include <cstdio> /* for sprintf, sigh */
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
|
@ -40,11 +39,11 @@ using namespace MIDI;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
MIDIControllable::MIDIControllable (Port& p, bool is_bistate)
|
MIDIControllable::MIDIControllable (Port& p, bool m)
|
||||||
: controllable (0)
|
: controllable (0)
|
||||||
, _descriptor (0)
|
, _descriptor (0)
|
||||||
, _port (p)
|
, _port (p)
|
||||||
, bistate (is_bistate)
|
, _momentary (m)
|
||||||
{
|
{
|
||||||
_learned = false; /* from URI */
|
_learned = false; /* from URI */
|
||||||
setting = false;
|
setting = false;
|
||||||
|
|
@ -55,12 +54,11 @@ MIDIControllable::MIDIControllable (Port& p, bool is_bistate)
|
||||||
feedback = true; // for now
|
feedback = true; // for now
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool is_bistate)
|
MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool m)
|
||||||
: controllable (&c)
|
: controllable (&c)
|
||||||
, _descriptor (0)
|
, _descriptor (0)
|
||||||
, _port (p)
|
, _port (p)
|
||||||
, bistate (is_bistate)
|
, _momentary (m)
|
||||||
|
|
||||||
{
|
{
|
||||||
_learned = true; /* from controllable */
|
_learned = true; /* from controllable */
|
||||||
setting = false;
|
setting = false;
|
||||||
|
|
@ -187,23 +185,23 @@ MIDIControllable::midi_sense_note_off (Parser &p, EventTwoBytes *tb)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MIDIControllable::midi_sense_note (Parser &, EventTwoBytes *msg, bool is_on)
|
MIDIControllable::midi_sense_note (Parser &, EventTwoBytes *msg, bool /* is_on */)
|
||||||
{
|
{
|
||||||
if (!controllable) {
|
if (!controllable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bistate) {
|
|
||||||
|
if (!controllable->is_toggle()) {
|
||||||
controllable->set_value (msg->note_number/127.0);
|
controllable->set_value (msg->note_number/127.0);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (control_additional == msg->note_number) {
|
||||||
/* Note: parser handles the use of zero velocity to
|
/* Note: parser handles the use of zero velocity to
|
||||||
mean note off. if we get called with is_on=true, then we
|
mean note off. if we get called with is_on=true, then we
|
||||||
got a *real* note on.
|
got a *real* note on.
|
||||||
*/
|
*/
|
||||||
|
controllable->set_value (controllable->get_value() > 0.5f ? 0.0f : 1.0f);
|
||||||
if (msg->note_number == control_additional) {
|
|
||||||
controllable->set_value (is_on ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,10 +220,11 @@ MIDIControllable::midi_sense_controller (Parser &, EventTwoBytes *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control_additional == msg->controller_number) {
|
if (control_additional == msg->controller_number) {
|
||||||
if (!bistate) {
|
|
||||||
|
if (!controllable->is_toggle()) {
|
||||||
controllable->set_value (midi_to_control (msg->value));
|
controllable->set_value (midi_to_control (msg->value));
|
||||||
} else {
|
} else {
|
||||||
if (msg->value > 64.0) {
|
if (msg->value > 64.0f) {
|
||||||
controllable->set_value (1);
|
controllable->set_value (1);
|
||||||
} else {
|
} else {
|
||||||
controllable->set_value (0);
|
controllable->set_value (0);
|
||||||
|
|
@ -242,12 +241,14 @@ MIDIControllable::midi_sense_program_change (Parser &, byte msg)
|
||||||
if (!controllable) {
|
if (!controllable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* XXX program change messages make no sense for bistates */
|
|
||||||
|
|
||||||
if (!bistate) {
|
if (!controllable->is_toggle()) {
|
||||||
controllable->set_value (msg/127.0);
|
controllable->set_value (msg/127.0);
|
||||||
last_value = (MIDI::byte) (controllable->get_value() * 127.0); // to prevent feedback fights
|
} else {
|
||||||
|
controllable->set_value (controllable->get_value() > 0.5f ? 0.0f : 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_value = (MIDI::byte) (controllable->get_value() * 127.0); // to prevent feedback fights
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -257,11 +258,14 @@ MIDIControllable::midi_sense_pitchbend (Parser &, pitchbend_t pb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pitchbend messages make no sense for bistates */
|
|
||||||
|
|
||||||
|
if (!controllable->is_toggle()) {
|
||||||
/* XXX gack - get rid of assumption about typeof pitchbend_t */
|
/* XXX gack - get rid of assumption about typeof pitchbend_t */
|
||||||
|
|
||||||
controllable->set_value ((pb/(float) SHRT_MAX));
|
controllable->set_value ((pb/(float) SHRT_MAX));
|
||||||
|
} else {
|
||||||
|
controllable->set_value (controllable->get_value() > 0.5f ? 0.0f : 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
last_value = (MIDI::byte) (controllable->get_value() * 127.0); // to prevent feedback fights
|
last_value = (MIDI::byte) (controllable->get_value() * 127.0); // to prevent feedback fights
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,11 +311,11 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
|
||||||
case MIDI::off:
|
case MIDI::off:
|
||||||
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
||||||
|
|
||||||
/* if this is a bistate, connect to noteOn as well,
|
/* if this is a togglee, connect to noteOn as well,
|
||||||
and we'll toggle back and forth between the two.
|
and we'll toggle back and forth between the two.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (bistate) {
|
if (_momentary) {
|
||||||
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -320,7 +324,7 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
|
||||||
|
|
||||||
case MIDI::on:
|
case MIDI::on:
|
||||||
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
||||||
if (bistate) {
|
if (_momentary) {
|
||||||
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
||||||
}
|
}
|
||||||
_control_description = "MIDI control: NoteOn";
|
_control_description = "MIDI control: NoteOn";
|
||||||
|
|
@ -333,17 +337,13 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::program:
|
case MIDI::program:
|
||||||
if (!bistate) {
|
|
||||||
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
|
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
|
||||||
_control_description = "MIDI control: ProgramChange";
|
_control_description = "MIDI control: ProgramChange";
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::pitchbend:
|
case MIDI::pitchbend:
|
||||||
if (!bistate) {
|
|
||||||
p.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
|
p.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
|
||||||
_control_description = "MIDI control: Pitchbend";
|
_control_description = "MIDI control: Pitchbend";
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -356,13 +356,18 @@ MIDIControllable::send_feedback ()
|
||||||
{
|
{
|
||||||
byte msg[3];
|
byte msg[3];
|
||||||
|
|
||||||
if (setting || !feedback || control_type == none) {
|
if (!_learned || setting || !feedback || control_type == none) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg[0] = (control_type & 0xF0) | (control_channel & 0xF);
|
msg[0] = (control_type & 0xF0) | (control_channel & 0xF);
|
||||||
msg[1] = control_additional;
|
msg[1] = control_additional;
|
||||||
|
|
||||||
|
if (controllable->is_gain_like()) {
|
||||||
|
msg[2] = (byte) lrintf (gain_to_slider_position (controllable->get_value()) * 127.0f);
|
||||||
|
} else {
|
||||||
msg[2] = (byte) (control_to_midi(controllable->get_value()));
|
msg[2] = (byte) (control_to_midi(controllable->get_value()));
|
||||||
|
}
|
||||||
|
|
||||||
_port.write (msg, 3, 0);
|
_port.write (msg, 3, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +377,13 @@ MIDIControllable::write_feedback (MIDI::byte* buf, int32_t& bufsize, bool /*forc
|
||||||
{
|
{
|
||||||
if (control_type != none && feedback && bufsize > 2) {
|
if (control_type != none && feedback && bufsize > 2) {
|
||||||
|
|
||||||
MIDI::byte gm = (MIDI::byte) (control_to_midi(controllable->get_value()));
|
MIDI::byte gm;
|
||||||
|
|
||||||
|
if (controllable->is_gain_like()) {
|
||||||
|
gm = (byte) lrintf (gain_to_slider_position (controllable->get_value()) * 127.0f);
|
||||||
|
} else {
|
||||||
|
gm = (byte) (control_to_midi(controllable->get_value()));
|
||||||
|
}
|
||||||
|
|
||||||
if (gm != last_value) {
|
if (gm != last_value) {
|
||||||
*buf++ = (0xF0 & control_type) | (0xF & control_channel);
|
*buf++ = (0xF0 & control_type) | (0xF & control_channel);
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ namespace MIDI {
|
||||||
class MIDIControllable : public PBD::Stateful
|
class MIDIControllable : public PBD::Stateful
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDIControllable (MIDI::Port&, PBD::Controllable&, bool bistate = false);
|
MIDIControllable (MIDI::Port&, PBD::Controllable&, bool momentary);
|
||||||
MIDIControllable (MIDI::Port&, bool bistate = false);
|
MIDIControllable (MIDI::Port&, bool momentary = false);
|
||||||
virtual ~MIDIControllable ();
|
virtual ~MIDIControllable ();
|
||||||
|
|
||||||
int init (const std::string&);
|
int init (const std::string&);
|
||||||
|
|
@ -95,7 +95,7 @@ class MIDIControllable : public PBD::Stateful
|
||||||
MIDI::Port& _port;
|
MIDI::Port& _port;
|
||||||
bool setting;
|
bool setting;
|
||||||
MIDI::byte last_value;
|
MIDI::byte last_value;
|
||||||
bool bistate;
|
bool _momentary;
|
||||||
bool _is_gain_controller;
|
bool _is_gain_controller;
|
||||||
bool _learned;
|
bool _learned;
|
||||||
int midi_msg_id; /* controller ID or note number */
|
int midi_msg_id; /* controller ID or note number */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue