mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
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:
parent
679ece14a3
commit
e10d0339cc
3 changed files with 120 additions and 18 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue