summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-12-28 23:55:33 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-12-28 23:55:33 +0000
commite10d0339ccd3659e0de58db29131e528571bc8c4 (patch)
treeb64e5f98da755f189e9b8ea43a6ed693700b5ef0 /libs
parent679ece14a3dda8dd1bc0c1a0a65abfcde9aeb0cd (diff)
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
Diffstat (limited to 'libs')
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc78
-rw-r--r--libs/surfaces/generic_midi/midifunction.cc49
-rw-r--r--libs/surfaces/generic_midi/midifunction.h11
3 files changed, 120 insertions, 18 deletions
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 67e940d905..d0d74f4c12 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -20,6 +20,7 @@
#define __STDC_FORMAT_MACROS 1
#include <stdint.h>
+#include <sstream>
#include <algorithm>
#include "pbd/error.h"
@@ -469,6 +470,8 @@ GenericMidiControlProtocol::load_bindings (const string& xmlpath)
} else if (child->property ("function")) {
+ cerr << "try to create a function from " << child->property ("function")->value() << endl;
+
/* function */
MIDIFunction* mf;
@@ -541,18 +544,13 @@ MIDIFunction*
GenericMidiControlProtocol::create_function (const XMLNode& node)
{
const XMLProperty* prop;
- int detail;
- int channel;
+ int intval;
+ MIDI::byte detail = 0;
+ MIDI::channel_t channel = 0;
string uri;
MIDI::eventType ev;
-
- if ((prop = node.property (X_("channel"))) == 0) {
- return 0;
- }
-
- if (sscanf (prop->value().c_str(), "%d", &channel) != 1) {
- return 0;
- }
+ MIDI::byte* sysex = 0;
+ uint32_t sysex_size = 0;
if ((prop = node.property (X_("ctl"))) != 0) {
ev = MIDI::controller;
@@ -560,25 +558,77 @@ 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) {
+
+ 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;
+ }
+
+ 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;
}
- if (sscanf (prop->value().c_str(), "%d", &detail) != 1) {
- 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"));
MIDIFunction* mf = new MIDIFunction (*_port);
- if (mf->init (*this, prop->value())) {
+ if (mf->init (*this, prop->value(), sysex, sysex_size)) {
delete mf;
return 0;
}
mf->bind_midi (channel, ev, detail);
-
+
cerr << "New MF with function = " << prop->value() << endl;
return mf;
diff --git a/libs/surfaces/generic_midi/midifunction.cc b/libs/surfaces/generic_midi/midifunction.cc
index e36af93ab3..609aca3bbc 100644
--- a/libs/surfaces/generic_midi/midifunction.cc
+++ b/libs/surfaces/generic_midi/midifunction.cc
@@ -28,14 +28,17 @@ using namespace MIDI;
MIDIFunction::MIDIFunction (MIDI::Port& p)
: _port (p)
{
+ sysex_size = 0;
+ sysex = 0;
}
MIDIFunction::~MIDIFunction ()
{
+ delete sysex;
}
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) {
_function = TransportStop;
@@ -47,11 +50,24 @@ MIDIFunction::init (BasicUI& ui, const std::string& function_name)
_function = TransportStart;
} else if (strcasecmp (function_name.c_str(), "transport-end") == 0) {
_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 {
return -1;
}
_ui = &ui;
+
+ if (sysex_sz) {
+ /* we take ownership of the sysex data */
+ sysex = sysex_data;
+ sysex_size = sysex_sz;
+ }
+
return 0;
}
@@ -78,6 +94,18 @@ MIDIFunction::execute ()
case TransportEnd:
_ui->goto_end ();
break;
+
+ case TransportLoopToggle:
+ _ui->loop_toggle ();
+ break;
+
+ case TransportRecordEnable:
+ _ui->set_record_enable (true);
+ break;
+
+ case TransportRecordDisable:
+ _ui->set_record_enable (false);
+ break;
}
}
@@ -118,6 +146,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
MIDIFunction::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
{
midi_sense_connection[0].disconnect ();
@@ -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));
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;
}
@@ -173,3 +219,4 @@ MIDIFunction::set_state (const XMLNode& node, int version)
{
return 0;
}
+
diff --git a/libs/surfaces/generic_midi/midifunction.h b/libs/surfaces/generic_midi/midifunction.h
index 5374d94157..8931e2c9eb 100644
--- a/libs/surfaces/generic_midi/midifunction.h
+++ b/libs/surfaces/generic_midi/midifunction.h
@@ -45,13 +45,16 @@ class MIDIFunction : public PBD::Stateful
TransportStop,
TransportZero,
TransportStart,
- TransportEnd
+ TransportEnd,
+ TransportLoopToggle,
+ TransportRecordEnable,
+ TransportRecordDisable
};
MIDIFunction (MIDI::Port&);
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; }
const std::string& function_name() const { return _function_name; }
@@ -73,8 +76,9 @@ class MIDIFunction : public PBD::Stateful
MIDI::eventType control_type;
MIDI::byte control_additional;
MIDI::channel_t control_channel;
+ MIDI::byte* sysex;
+ size_t sysex_size;
- void init (const std::string& function_name);
void execute ();
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_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__