+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 (*_input_port->parser());
+
+ if (ma->init (*this, prop->value(), data, data_size)) {
+ delete ma;
+ return 0;
+ }
+
+ ma->bind_midi (channel, ev, detail);
+
+ return ma;
+}
+