diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index b35a99dcf4..62cc93263b 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -41,6 +41,7 @@ #include "generic_midi_control_protocol.h" #include "midicontrollable.h" #include "midifunction.h" +#include "midiaction.h" using namespace ARDOUR; using namespace PBD; @@ -193,6 +194,11 @@ GenericMidiControlProtocol::drop_all () delete *i; } functions.clear (); + + for (MIDIActions::iterator i = actions.begin(); i != actions.end(); ++i) { + delete *i; + } + actions.clear (); } void @@ -640,7 +646,14 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath) if ((mf = create_function (*child)) != 0) { functions.push_back (mf); } - } + + } else if (child->property ("action")) { + MIDIAction* ma; + + if ((ma = create_action (*child)) != 0) { + actions.push_back (ma); + } + } } } @@ -744,8 +757,8 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) MIDI::channel_t channel = 0; string uri; MIDI::eventType ev; - MIDI::byte* sysex = 0; - uint32_t sysex_size = 0; + MIDI::byte* data = 0; + uint32_t data_size = 0; if ((prop = node.property (X_("ctl"))) != 0) { ev = MIDI::controller; @@ -753,9 +766,14 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) ev = MIDI::on; } else if ((prop = node.property (X_("pgm"))) != 0) { ev = MIDI::program; - } else if ((prop = node.property (X_("sysex"))) != 0) { + } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) { + + if (prop->name() == X_("sysex")) { + ev = MIDI::sysex; + } else { + ev = MIDI::any; + } - ev = MIDI::sysex; int val; uint32_t cnt; @@ -773,8 +791,8 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) return 0; } - sysex = new MIDI::byte[cnt]; - sysex_size = cnt; + data = new MIDI::byte[cnt]; + data_size = cnt; { stringstream ss (prop->value()); @@ -782,16 +800,16 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) cnt = 0; while (ss >> val) { - sysex[cnt++] = (MIDI::byte) val; + data[cnt++] = (MIDI::byte) val; } } - + } else { warning << "Binding ignored - unknown type" << endmsg; return 0; } - if (sysex_size == 0) { + if (data_size == 0) { if (sscanf (prop->value().c_str(), "%d", &intval) != 1) { return 0; } @@ -816,7 +834,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) MIDIFunction* mf = new MIDIFunction (*_port); - if (mf->init (*this, prop->value(), sysex, sysex_size)) { + if (mf->init (*this, prop->value(), data, data_size)) { delete mf; return 0; } @@ -826,6 +844,102 @@ GenericMidiControlProtocol::create_function (const XMLNode& node) return mf; } +MIDIAction* +GenericMidiControlProtocol::create_action (const XMLNode& node) +{ + const XMLProperty* prop; + int intval; + MIDI::byte detail = 0; + MIDI::channel_t channel = 0; + string uri; + MIDI::eventType ev; + MIDI::byte* data = 0; + uint32_t data_size = 0; + + if ((prop = node.property (X_("ctl"))) != 0) { + ev = MIDI::controller; + } else if ((prop = node.property (X_("note"))) != 0) { + ev = MIDI::on; + } else if ((prop = node.property (X_("pgm"))) != 0) { + ev = MIDI::program; + } else if ((prop = node.property (X_("sysex"))) != 0 || (prop = node.property (X_("msg"))) != 0) { + + if (prop->name() == X_("sysex")) { + ev = MIDI::sysex; + } else { + ev = MIDI::any; + } + + int val; + uint32_t cnt; + + { + cnt = 0; + stringstream ss (prop->value()); + ss << hex; + + while (ss >> val) { + cnt++; + } + } + + if (cnt == 0) { + return 0; + } + + data = new MIDI::byte[cnt]; + data_size = cnt; + + { + stringstream ss (prop->value()); + ss << hex; + cnt = 0; + + while (ss >> val) { + data[cnt++] = (MIDI::byte) val; + } + } + + } else { + warning << "Binding ignored - unknown type" << endmsg; + return 0; + } + + if (data_size == 0) { + if (sscanf (prop->value().c_str(), "%d", &intval) != 1) { + return 0; + } + + detail = (MIDI::byte) intval; + + if ((prop = node.property (X_("channel"))) == 0) { + return 0; + } + + if (sscanf (prop->value().c_str(), "%d", &intval) != 1) { + return 0; + } + channel = (MIDI::channel_t) intval; + /* adjust channel to zero-based counting */ + if (channel > 0) { + channel -= 1; + } + } + + prop = node.property (X_("action")); + + MIDIAction* ma = new MIDIAction (*_port); + + if (ma->init (*this, prop->value(), data, data_size)) { + delete ma; + return 0; + } + + ma->bind_midi (channel, ev, detail); + + return ma; +} + void GenericMidiControlProtocol::set_current_bank (uint32_t b) { diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index e0867fad78..1ad2c681d4 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -40,6 +40,7 @@ namespace ARDOUR { class MIDIControllable; class MIDIFunction; +class MIDIAction; class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { public: @@ -94,6 +95,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { typedef std::list MIDIFunctions; MIDIFunctions functions; + typedef std::list MIDIActions; + MIDIActions actions; + typedef std::pair MIDIPendingControllable; typedef std::list MIDIPendingControllables; MIDIPendingControllables pending_controllables; @@ -110,6 +114,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { MIDIControllable* create_binding (const XMLNode&); MIDIFunction* create_function (const XMLNode&); + MIDIAction* create_action (const XMLNode&); void reset_controllables (); void drop_all (); diff --git a/libs/surfaces/generic_midi/midiaction.cc b/libs/surfaces/generic_midi/midiaction.cc new file mode 100644 index 0000000000..f432b7dffb --- /dev/null +++ b/libs/surfaces/generic_midi/midiaction.cc @@ -0,0 +1,62 @@ +/* + Copyright (C) 2009-2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include "midi++/port.h" + +#include "midiaction.h" +#include "generic_midi_control_protocol.h" + +using namespace MIDI; + +MIDIAction::MIDIAction (MIDI::Port& p) + : MIDIInvokable (p) +{ +} + +MIDIAction::~MIDIAction () +{ +} + +int +MIDIAction::init (GenericMidiControlProtocol& ui, const std::string& invokable_name, MIDI::byte* msg_data, size_t data_sz) +{ + MIDIInvokable::init (ui, invokable_name, msg_data, data_sz); + return 0; +} + +void +MIDIAction::execute () +{ + _ui->access_action (_invokable_name); +} + +XMLNode& +MIDIAction::get_state () +{ + XMLNode* node = new XMLNode ("MIDIAction"); + return *node; +} + +int +MIDIAction::set_state (const XMLNode& node, int version) +{ + return 0; +} + diff --git a/libs/surfaces/generic_midi/midiaction.h b/libs/surfaces/generic_midi/midiaction.h new file mode 100644 index 0000000000..521f59f26d --- /dev/null +++ b/libs/surfaces/generic_midi/midiaction.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __gm_midiaction_h__ +#define __gm_midiaction_h__ + +#include + +#include "midi++/types.h" + +#include "pbd/signals.h" +#include "pbd/stateful.h" + +#include "ardour/types.h" + +#include "midiinvokable.h" + +namespace Gtk { + class Action; +} + +namespace MIDI { + class Channel; + class Port; + class Parser; +} + +class GenericMidiControlProtocol; + +class MIDIAction : public MIDIInvokable +{ + public: + MIDIAction (MIDI::Port&); + virtual ~MIDIAction (); + + int init (GenericMidiControlProtocol&, const std::string& action_name, MIDI::byte* sysex = 0, size_t ssize = 0); + + const std::string& action_name() const { return _invokable_name; } + + XMLNode& get_state (void); + int set_state (const XMLNode&, int version); + + private: + Gtk::Action* _action; + void execute (); +}; + +#endif // __gm_midicontrollable_h__ + diff --git a/libs/surfaces/generic_midi/midifunction.cc b/libs/surfaces/generic_midi/midifunction.cc index 3ce447b799..3d407b4c76 100644 --- a/libs/surfaces/generic_midi/midifunction.cc +++ b/libs/surfaces/generic_midi/midifunction.cc @@ -26,52 +26,43 @@ using namespace MIDI; MIDIFunction::MIDIFunction (MIDI::Port& p) - : _port (p) + : MIDIInvokable (p) { - sysex_size = 0; - sysex = 0; } MIDIFunction::~MIDIFunction () { - delete [] sysex; } int -MIDIFunction::init (GenericMidiControlProtocol& ui, const std::string& function_name, MIDI::byte* sysex_data, size_t sysex_sz) +MIDIFunction::init (GenericMidiControlProtocol& ui, const std::string& invokable_name, MIDI::byte* msg_data, size_t data_sz) { - if (strcasecmp (function_name.c_str(), "transport-stop") == 0) { + MIDIInvokable::init (ui, invokable_name, msg_data, data_sz); + + if (strcasecmp (_invokable_name.c_str(), "transport-stop") == 0) { _function = TransportStop; - } else if (strcasecmp (function_name.c_str(), "transport-roll") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "transport-roll") == 0) { _function = TransportRoll; - } else if (strcasecmp (function_name.c_str(), "transport-zero") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "transport-zero") == 0) { _function = TransportZero; - } else if (strcasecmp (function_name.c_str(), "transport-start") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "transport-start") == 0) { _function = TransportStart; - } else if (strcasecmp (function_name.c_str(), "transport-end") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "transport-end") == 0) { _function = TransportEnd; - } else if (strcasecmp (function_name.c_str(), "loop-toggle") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "loop-toggle") == 0) { _function = TransportLoopToggle; - } else if (strcasecmp (function_name.c_str(), "rec-enable") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "rec-enable") == 0) { _function = TransportRecordEnable; - } else if (strcasecmp (function_name.c_str(), "rec-disable") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "rec-disable") == 0) { _function = TransportRecordDisable; - } else if (strcasecmp (function_name.c_str(), "next-bank") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "next-bank") == 0) { _function = NextBank; - } else if (strcasecmp (function_name.c_str(), "prev-bank") == 0) { + } else if (strcasecmp (_invokable_name.c_str(), "prev-bank") == 0) { _function = PrevBank; } else { return -1; } - _ui = &ui; - - if (sysex_sz) { - /* we take ownership of the sysex data */ - sysex = sysex_data; - sysex_size = sysex_sz; - } - return 0; } @@ -121,104 +112,6 @@ MIDIFunction::execute () } } -void -MIDIFunction::midi_sense_note_on (Parser &p, EventTwoBytes *tb) -{ - midi_sense_note (p, tb, true); -} - -void -MIDIFunction::midi_sense_note_off (Parser &p, EventTwoBytes *tb) -{ - midi_sense_note (p, tb, false); -} - -void -MIDIFunction::midi_sense_note (Parser &, EventTwoBytes *msg, bool /* is_on */) -{ - if (msg->note_number == control_additional) { - execute (); - } -} - -void -MIDIFunction::midi_sense_controller (Parser &, EventTwoBytes *msg) -{ - if (control_additional == msg->controller_number) { - execute (); - } -} - -void -MIDIFunction::midi_sense_program_change (Parser &, byte msg) -{ - if (msg == control_additional) { - execute (); - } -} - -void -MIDIFunction::midi_sense_sysex (Parser &, byte* msg, size_t sz) -{ - if (sz != sysex_size) { - return; - } - - if (memcmp (msg, sysex, sysex_size) != 0) { - return; - } - - execute (); -} - -void -MIDIFunction::bind_midi (channel_t chn, eventType ev, MIDI::byte additional) -{ - midi_sense_connection[0].disconnect (); - midi_sense_connection[1].disconnect (); - - control_type = ev; - control_channel = chn; - control_additional = additional; - - if (_port.input() == 0) { - return; - } - - Parser& p = *_port.input(); - - int chn_i = chn; - - /* incoming MIDI is parsed by Ardour' MidiUI event loop/thread, and we want our handlers to execute in that context, so we use - Signal::connect_same_thread() here. - */ - - switch (ev) { - case MIDI::off: - p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_note_off, this, _1, _2)); - break; - - case MIDI::on: - p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_note_on, this, _1, _2)); - break; - - case MIDI::controller: - p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_controller, this, _1, _2)); - break; - - case MIDI::program: - p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_program_change, this, _1, _2)); - break; - - case MIDI::sysex: - p.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_sysex, this, _1, _2, _3)); - break; - - default: - break; - } -} - XMLNode& MIDIFunction::get_state () { diff --git a/libs/surfaces/generic_midi/midifunction.h b/libs/surfaces/generic_midi/midifunction.h index bc019cfb3c..73ba21434e 100644 --- a/libs/surfaces/generic_midi/midifunction.h +++ b/libs/surfaces/generic_midi/midifunction.h @@ -29,6 +29,8 @@ #include "ardour/types.h" +#include "midiinvokable.h" + namespace MIDI { class Channel; class Port; @@ -37,7 +39,7 @@ namespace MIDI { class GenericMidiControlProtocol; -class MIDIFunction : public PBD::Stateful +class MIDIFunction : public MIDIInvokable { public: enum Function { @@ -58,37 +60,14 @@ class MIDIFunction : public PBD::Stateful int init (GenericMidiControlProtocol&, const std::string& function_name, MIDI::byte* sysex = 0, size_t ssize = 0); - MIDI::Port& get_port() const { return _port; } - const std::string& function_name() const { return _function_name; } + const std::string& function_name() const { return _invokable_name; } XMLNode& get_state (void); int set_state (const XMLNode&, int version); - void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte); - MIDI::channel_t get_control_channel () { return control_channel; } - MIDI::eventType get_control_type () { return control_type; } - MIDI::byte get_control_additional () { return control_additional; } - private: Function _function; - GenericMidiControlProtocol* _ui; - std::string _function_name; - MIDI::Port& _port; - PBD::ScopedConnection midi_sense_connection[2]; - MIDI::eventType control_type; - MIDI::byte control_additional; - MIDI::channel_t control_channel; - MIDI::byte* sysex; - size_t sysex_size; - void execute (); - - void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on); - void midi_sense_note_on (MIDI::Parser &p, MIDI::EventTwoBytes *tb); - void midi_sense_note_off (MIDI::Parser &p, MIDI::EventTwoBytes *tb); - void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *); - void midi_sense_program_change (MIDI::Parser &, MIDI::byte); - void midi_sense_sysex (MIDI::Parser &, MIDI::byte*, size_t); }; #endif // __gm_midicontrollable_h__ diff --git a/libs/surfaces/generic_midi/midiinvokable.cc b/libs/surfaces/generic_midi/midiinvokable.cc new file mode 100644 index 0000000000..a77335fa7a --- /dev/null +++ b/libs/surfaces/generic_midi/midiinvokable.cc @@ -0,0 +1,171 @@ +/* + Copyright (C) 2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +#include "midi++/port.h" + +#include "midifunction.h" +#include "generic_midi_control_protocol.h" + +using namespace MIDI; + +MIDIInvokable::MIDIInvokable (MIDI::Port& p) + : _port (p) +{ + data_size = 0; + data = 0; +} + +MIDIInvokable::~MIDIInvokable () +{ + delete [] data; +} + +int +MIDIInvokable::init (GenericMidiControlProtocol& ui, const std::string& name, MIDI::byte* msg_data, size_t data_sz) +{ + _ui = &ui; + _invokable_name = name; + + if (data_sz) { + /* we take ownership of the sysex data */ + data = msg_data; + data_size = data_sz; + } + + return 0; +} + +void +MIDIInvokable::midi_sense_note_on (Parser &p, EventTwoBytes *tb) +{ + midi_sense_note (p, tb, true); +} + +void +MIDIInvokable::midi_sense_note_off (Parser &p, EventTwoBytes *tb) +{ + midi_sense_note (p, tb, false); +} + +void +MIDIInvokable::midi_sense_note (Parser &, EventTwoBytes *msg, bool /* is_on */) +{ + if (msg->note_number == control_additional) { + execute (); + } +} + +void +MIDIInvokable::midi_sense_controller (Parser &, EventTwoBytes *msg) +{ + if (control_additional == msg->controller_number) { + execute (); + } +} + +void +MIDIInvokable::midi_sense_program_change (Parser &, byte msg) +{ + if (msg == control_additional) { + execute (); + } +} + +void +MIDIInvokable::midi_sense_sysex (Parser &, byte* msg, size_t sz) +{ + if (sz != data_size) { + return; + } + + if (memcmp (msg, data, data_size) != 0) { + return; + } + + execute (); +} + +void +MIDIInvokable::midi_sense_any (Parser &, byte* msg, size_t sz) +{ + if (sz != data_size) { + return; + } + + if (memcmp (msg, data, data_size) != 0) { + return; + } + + execute (); +} + + +void +MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional) +{ + midi_sense_connection[0].disconnect (); + midi_sense_connection[1].disconnect (); + + control_type = ev; + control_channel = chn; + control_additional = additional; + + if (_port.input() == 0) { + return; + } + + Parser& p = *_port.input(); + + int chn_i = chn; + + /* incoming MIDI is parsed by Ardour' MidiUI event loop/thread, and we want our handlers to execute in that context, so we use + Signal::connect_same_thread() here. + */ + + switch (ev) { + case MIDI::off: + p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2)); + break; + + case MIDI::on: + p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2)); + break; + + case MIDI::controller: + p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2)); + break; + + case MIDI::program: + p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2)); + break; + + case MIDI::sysex: + p.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3)); + break; + + case MIDI::any: + p.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3)); + break; + + default: + break; + } +} + diff --git a/libs/surfaces/generic_midi/midiinvokable.h b/libs/surfaces/generic_midi/midiinvokable.h new file mode 100644 index 0000000000..b86bdb858b --- /dev/null +++ b/libs/surfaces/generic_midi/midiinvokable.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __gm_midiinvokable_h__ +#define __gm_midiinvokable_h__ + +#include + +#include "midi++/types.h" + +#include "pbd/signals.h" +#include "pbd/stateful.h" + +#include "ardour/types.h" + +namespace MIDI { + class Channel; + class Port; + class Parser; +} + +class GenericMidiControlProtocol; + +class MIDIInvokable : public PBD::Stateful +{ + public: + MIDIInvokable (MIDI::Port&); + virtual ~MIDIInvokable (); + + virtual int init (GenericMidiControlProtocol&, const std::string&, MIDI::byte* data = 0, size_t dsize = 0); + + MIDI::Port& get_port() const { return _port; } + + void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte); + MIDI::channel_t get_control_channel () { return control_channel; } + MIDI::eventType get_control_type () { return control_type; } + MIDI::byte get_control_additional () { return control_additional; } + + protected: + GenericMidiControlProtocol* _ui; + std::string _invokable_name; + MIDI::Port& _port; + PBD::ScopedConnection midi_sense_connection[2]; + MIDI::eventType control_type; + MIDI::byte control_additional; + MIDI::channel_t control_channel; + MIDI::byte* data; + size_t data_size; + + void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on); + void midi_sense_note_on (MIDI::Parser &p, MIDI::EventTwoBytes *tb); + void midi_sense_note_off (MIDI::Parser &p, MIDI::EventTwoBytes *tb); + void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *); + void midi_sense_program_change (MIDI::Parser &, MIDI::byte); + void midi_sense_sysex (MIDI::Parser &, MIDI::byte*, size_t); + void midi_sense_any (MIDI::Parser &, MIDI::byte*, size_t); + + virtual void execute () = 0; +}; + +#endif // __gm_midicontrollable_h__ + diff --git a/libs/surfaces/generic_midi/wscript b/libs/surfaces/generic_midi/wscript index 5926e0e9da..8471830766 100644 --- a/libs/surfaces/generic_midi/wscript +++ b/libs/surfaces/generic_midi/wscript @@ -24,8 +24,10 @@ def build(bld): generic_midi_control_protocol.cc gmcp_gui.cc interface.cc + midiinvokable.cc midicontrollable.cc midifunction.cc + midiaction.cc ''' obj.export_incdirs = ['.'] obj.cxxflags = '-DPACKAGE="ardour_genericmidi"'