add sysex support to MIDI binding maps, and a couple more functions

git-svn-id: svn://localhost/ardour2/branches/3.0@6410 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-12-28 23:55:33 +00:00
parent 679ece14a3
commit e10d0339cc
3 changed files with 120 additions and 18 deletions

View file

@ -20,6 +20,7 @@
#define __STDC_FORMAT_MACROS 1 #define __STDC_FORMAT_MACROS 1
#include <stdint.h> #include <stdint.h>
#include <sstream>
#include <algorithm> #include <algorithm>
#include "pbd/error.h" #include "pbd/error.h"
@ -469,6 +470,8 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath)
} else if (child->property ("function")) { } else if (child->property ("function")) {
cerr << "try to create a function from " << child->property ("function")->value() << endl;
/* function */ /* function */
MIDIFunction* mf; MIDIFunction* mf;
@ -541,18 +544,13 @@ MIDIFunction*
GenericMidiControlProtocol::create_function (const XMLNode& node) GenericMidiControlProtocol::create_function (const XMLNode& node)
{ {
const XMLProperty* prop; const XMLProperty* prop;
int detail; int intval;
int channel; MIDI::byte detail = 0;
MIDI::channel_t channel = 0;
string uri; string uri;
MIDI::eventType ev; MIDI::eventType ev;
MIDI::byte* sysex = 0;
if ((prop = node.property (X_("channel"))) == 0) { uint32_t sysex_size = 0;
return 0;
}
if (sscanf (prop->value().c_str(), "%d", &channel) != 1) {
return 0;
}
if ((prop = node.property (X_("ctl"))) != 0) { if ((prop = node.property (X_("ctl"))) != 0) {
ev = MIDI::controller; ev = MIDI::controller;
@ -560,19 +558,71 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
ev = MIDI::on; ev = MIDI::on;
} else if ((prop = node.property (X_("pgm"))) != 0) { } else if ((prop = node.property (X_("pgm"))) != 0) {
ev = MIDI::program; ev = MIDI::program;
} else { } else if ((prop = node.property (X_("sysex"))) != 0) {
ev = MIDI::sysex;
int val;
uint32_t cnt;
{
cnt = 0;
stringstream ss (prop->value());
ss << hex;
while (ss >> val) {
cnt++;
}
}
if (cnt == 0) {
return 0; return 0;
} }
if (sscanf (prop->value().c_str(), "%d", &detail) != 1) { sysex = new MIDI::byte[cnt];
sysex_size = cnt;
{
stringstream ss (prop->value());
ss << hex;
cnt = 0;
while (ss >> val) {
sysex[cnt++] = (MIDI::byte) val;
cerr << hex << (int) sysex[cnt-1] << dec << ' ' << endl;
}
}
} else {
warning << "Binding ignored - unknown type" << endmsg;
return 0; return 0;
} }
if (sysex_size == 0) {
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;
}
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
detail = (MIDI::byte) intval;
}
prop = node.property (X_("function")); prop = node.property (X_("function"));
MIDIFunction* mf = new MIDIFunction (*_port); MIDIFunction* mf = new MIDIFunction (*_port);
if (mf->init (*this, prop->value())) { if (mf->init (*this, prop->value(), sysex, sysex_size)) {
delete mf; delete mf;
return 0; return 0;
} }

View file

@ -28,14 +28,17 @@ using namespace MIDI;
MIDIFunction::MIDIFunction (MIDI::Port& p) MIDIFunction::MIDIFunction (MIDI::Port& p)
: _port (p) : _port (p)
{ {
sysex_size = 0;
sysex = 0;
} }
MIDIFunction::~MIDIFunction () MIDIFunction::~MIDIFunction ()
{ {
delete sysex;
} }
int int
MIDIFunction::init (BasicUI& ui, const std::string& function_name) MIDIFunction::init (BasicUI& ui, const std::string& function_name, MIDI::byte* sysex_data, size_t sysex_sz)
{ {
if (strcasecmp (function_name.c_str(), "transport-stop") == 0) { if (strcasecmp (function_name.c_str(), "transport-stop") == 0) {
_function = TransportStop; _function = TransportStop;
@ -47,11 +50,24 @@ MIDIFunction::init (BasicUI& ui, const std::string& function_name)
_function = TransportStart; _function = TransportStart;
} else if (strcasecmp (function_name.c_str(), "transport-end") == 0) { } else if (strcasecmp (function_name.c_str(), "transport-end") == 0) {
_function = TransportEnd; _function = TransportEnd;
} else if (strcasecmp (function_name.c_str(), "loop-toggle") == 0) {
_function = TransportLoopToggle;
} else if (strcasecmp (function_name.c_str(), "rec-enable") == 0) {
_function = TransportRecordEnable;
} else if (strcasecmp (function_name.c_str(), "rec-disable") == 0) {
_function = TransportRecordDisable;
} else { } else {
return -1; return -1;
} }
_ui = &ui; _ui = &ui;
if (sysex_sz) {
/* we take ownership of the sysex data */
sysex = sysex_data;
sysex_size = sysex_sz;
}
return 0; return 0;
} }
@ -78,6 +94,18 @@ MIDIFunction::execute ()
case TransportEnd: case TransportEnd:
_ui->goto_end (); _ui->goto_end ();
break; break;
case TransportLoopToggle:
_ui->loop_toggle ();
break;
case TransportRecordEnable:
_ui->set_record_enable (true);
break;
case TransportRecordDisable:
_ui->set_record_enable (false);
break;
} }
} }
@ -117,6 +145,20 @@ MIDIFunction::midi_sense_program_change (Parser &, byte msg)
} }
} }
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 void
MIDIFunction::bind_midi (channel_t chn, eventType ev, MIDI::byte additional) MIDIFunction::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
{ {
@ -156,6 +198,10 @@ MIDIFunction::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_program_change, this, _1, _2)); p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIFunction::midi_sense_program_change, this, _1, _2));
break; 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: default:
break; break;
} }
@ -173,3 +219,4 @@ MIDIFunction::set_state (const XMLNode& node, int version)
{ {
return 0; return 0;
} }

View file

@ -45,13 +45,16 @@ class MIDIFunction : public PBD::Stateful
TransportStop, TransportStop,
TransportZero, TransportZero,
TransportStart, TransportStart,
TransportEnd TransportEnd,
TransportLoopToggle,
TransportRecordEnable,
TransportRecordDisable
}; };
MIDIFunction (MIDI::Port&); MIDIFunction (MIDI::Port&);
virtual ~MIDIFunction (); virtual ~MIDIFunction ();
int init (BasicUI&, const std::string&); int init (BasicUI&, const std::string& function_name, MIDI::byte* sysex = 0, size_t ssize = 0);
MIDI::Port& get_port() const { return _port; } MIDI::Port& get_port() const { return _port; }
const std::string& function_name() const { return _function_name; } const std::string& function_name() const { return _function_name; }
@ -73,8 +76,9 @@ class MIDIFunction : public PBD::Stateful
MIDI::eventType control_type; MIDI::eventType control_type;
MIDI::byte control_additional; MIDI::byte control_additional;
MIDI::channel_t control_channel; MIDI::channel_t control_channel;
MIDI::byte* sysex;
size_t sysex_size;
void init (const std::string& function_name);
void execute (); void execute ();
void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on); void midi_sense_note (MIDI::Parser &, MIDI::EventTwoBytes *, bool is_on);
@ -82,6 +86,7 @@ class MIDIFunction : public PBD::Stateful
void midi_sense_note_off (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_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
void midi_sense_program_change (MIDI::Parser &, MIDI::byte); void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
void midi_sense_sysex (MIDI::Parser &, MIDI::byte*, size_t);
}; };
#endif // __gm_midicontrollable_h__ #endif // __gm_midicontrollable_h__