diff --git a/cimditprofile.cpp b/cimditprofile.cpp index 78767e3..a2c3f45 100644 --- a/cimditprofile.cpp +++ b/cimditprofile.cpp @@ -12,6 +12,11 @@ #include #include #include + +#ifdef HAVE_MIDI +#include +#endif + #ifndef EXTERNAL_EEPROM #include #endif @@ -166,11 +171,14 @@ void CimditProfile::load(uint8_t num) { for (uint8_t i = 0; i < m_numMappedButtons ; ++i) { m_mappedButtons[i].m_number = nextUInt8(); m_mappedButtons[i].m_type = (MappingType)(nextUInt8()); - m_mappedButtons[i].m_value = nextUInt8(); + m_mappedButtons[i].m_value1 = nextUInt8(); + if (m_mappedButtons[i].m_type == MIDI_NOTE || m_mappedButtons[i].m_type == MIDI_CTRL || m_mappedButtons[i].m_type == MIDI_PITCH) { + m_mappedButtons[i].m_value2 = nextUInt8(); + m_mappedButtons[i].m_value3 = nextUInt8(); + } } } // end of mapped buttons - // mapped axis // number of mapped axis m_numMappedAxis = nextUInt8(); @@ -178,11 +186,13 @@ void CimditProfile::load(uint8_t num) { for (uint8_t i = 0; i < m_numMappedAxis ; ++i) { m_mappedAxis[i].m_number = nextUInt8(); m_mappedAxis[i].m_type = (MappingType)(nextUInt8()); - m_mappedAxis[i].m_value = nextUInt8(); + m_mappedAxis[i].m_value1 = nextUInt8(); + if (m_mappedAxis[i].m_type == MIDI_CTRL_AXIS) { + m_mappedAxis[i].m_value2 = nextUInt8(); + } } } // end of mapped axis - // mapped rotary // number of mapped rotary m_numMappedRotary = nextUInt8(); @@ -190,7 +200,7 @@ void CimditProfile::load(uint8_t num) { for (uint8_t i = 0; i < m_numMappedRotary ; ++i) { m_mappedRotary[i].m_number = nextUInt8(); m_mappedRotary[i].m_type = (MappingType)(nextUInt8()); - m_mappedRotary[i].m_value = nextUInt8(); + m_mappedRotary[i].m_value1 = nextUInt8(); } } // end of mapped rotary @@ -305,14 +315,14 @@ void CimditProfile::scanOrExecuteMacro(uint8_t macroNum, bool execute) { for (uint8_t i = 0; i < m_numMappedAxis; ++i) { if (m_mappedAxis[i].m_number == axis) { m_mappedAxis[i].m_type = MOUSE_REL_X_AXIS; - m_mappedAxis[i].m_value = value8; + m_mappedAxis[i].m_value1 = value8; found = true; } } if (!found) { m_mappedAxis[m_numMappedAxis].m_type = MOUSE_REL_X_AXIS; m_mappedAxis[m_numMappedAxis].m_number = axis; - m_mappedAxis[m_numMappedAxis++].m_value = value8; + m_mappedAxis[m_numMappedAxis++].m_value1 = value8; } } } else { @@ -337,14 +347,14 @@ void CimditProfile::scanOrExecuteMacro(uint8_t macroNum, bool execute) { for (uint8_t i = 0; i < m_numMappedAxis; ++i) { if (m_mappedAxis[i].m_number == axis) { m_mappedAxis[i].m_type = MOUSE_REL_Y_AXIS; - m_mappedAxis[i].m_value = value8; + m_mappedAxis[i].m_value1 = value8; found = true; } } if (!found) { m_mappedAxis[m_numMappedAxis].m_type = MOUSE_REL_Y_AXIS; m_mappedAxis[m_numMappedAxis].m_number = axis; - m_mappedAxis[m_numMappedAxis++].m_value = value8; + m_mappedAxis[m_numMappedAxis++].m_value1 = value8; } } } else { @@ -359,6 +369,61 @@ void CimditProfile::scanOrExecuteMacro(uint8_t macroNum, bool execute) { } } break; + case MACRO_MIDI_NOTEON: + { + uint8_t channel = nextUInt8(); + value8 = nextUInt8(); + uint8_t velocity = nextUInt8(); +#ifdef HAVE_MIDI + if (execute) { + midiEventPacket_t noteOn = {0x09, (uint8_t)(0x90 | channel), value8, velocity}; + MidiUSB.sendMIDI(noteOn); + MidiUSB.flush(); + } +#endif + } + break; + case MACRO_MIDI_NOTEOFF: + { + uint8_t channel = nextUInt8(); + value8 = nextUInt8(); + uint8_t velocity = nextUInt8(); +#ifdef HAVE_MIDI + if (execute) { + midiEventPacket_t noteOff = {0x08, (uint8_t)(0x80 | channel), value8, velocity}; + MidiUSB.sendMIDI(noteOff); + MidiUSB.flush(); + } +#endif + } + break; + case MACRO_MIDI_CTRL: + { + uint8_t channel = nextUInt8(); + uint8_t control = nextUInt8(); + value8 = nextUInt8(); +#ifdef HAVE_MIDI + if (execute) { + midiEventPacket_t event= {0x0B, (uint8_t)(0xB0 | channel), control, value8}; + MidiUSB.sendMIDI(event); + MidiUSB.flush(); + } +#endif + } + break; + case MACRO_MIDI_PITCH: + { + uint8_t channel = nextUInt8(); + uint16_t value = nextUInt16(); +#ifdef HAVE_MIDI + if (execute) { + midiEventPacket_t event = {0x0E, (uint8_t)(0xE0 | channel), (unsigned char)(value&127), (uint8_t)(value>>7)}; + MidiUSB.sendMIDI(event); + MidiUSB.flush(); + } +#endif + } + break; } } while (token != MACRO_NULL); } @@ -375,13 +440,13 @@ void CimditProfile::rotaryAction(uint8_t num, int8_t delta) { // rotary supports mouse rel axis, next/prev profile and macro switch (m_mappedRotary[i].m_type) { case MOUSE_REL_X_AXIS: - Mouse.move(m_mappedRotary[i].m_value * delta, 0, 0); + Mouse.move(m_mappedRotary[i].m_value1 * delta, 0, 0); break; case MOUSE_REL_Y_AXIS: - Mouse.move(0, m_mappedRotary[i].m_value * delta, 0); + Mouse.move(0, m_mappedRotary[i].m_value1 * delta, 0); break; case MOUSE_REL_WHEEL: - Mouse.move(0, 0, m_mappedRotary[i].m_value * delta); + Mouse.move(0, 0, m_mappedRotary[i].m_value1 * delta); break; case NEXT_PROFILE: case PREV_PROFILE: @@ -397,7 +462,7 @@ void CimditProfile::rotaryAction(uint8_t num, int8_t delta) { showActivate(); break; case MACRO_PRESS: - scanOrExecuteMacro(m_mappedRotary[i].m_value, true); + scanOrExecuteMacro(m_mappedRotary[i].m_value1, true); break; default: break; @@ -490,7 +555,7 @@ void CimditProfile::axisAction(uint8_t num, uint16_t state) { if (m_mappedAxis[i].m_number == num) { switch (m_mappedAxis[i].m_type) { case JOYSTICK_AXIS: - switch (m_mappedAxis[i].m_value) { + switch (m_mappedAxis[i].m_value1) { case 1: Gamepad.xAxis(map(state, 0, 1023, -32768, 32767)); break; @@ -514,9 +579,9 @@ void CimditProfile::axisAction(uint8_t num, uint16_t state) { case MOUSE_REL_X_AXIS: { int16_t pos = (int16_t)state - 512; if (pos > JOYSTICK_DEAD_ZONE_X) { - m_mouseMoveX = map(pos, JOYSTICK_DEAD_ZONE_X, 511, 0, m_mappedAxis[i].m_value); + m_mouseMoveX = map(pos, JOYSTICK_DEAD_ZONE_X, 511, 0, m_mappedAxis[i].m_value1); } else if (pos < -JOYSTICK_DEAD_ZONE_X) { - m_mouseMoveX = map(pos, -512, -JOYSTICK_DEAD_ZONE_X, -m_mappedAxis[i].m_value, 0); + m_mouseMoveX = map(pos, -512, -JOYSTICK_DEAD_ZONE_X, -m_mappedAxis[i].m_value1, 0); } else { m_mouseMoveX = 0; } @@ -525,16 +590,46 @@ void CimditProfile::axisAction(uint8_t num, uint16_t state) { case MOUSE_REL_Y_AXIS: { int16_t pos = (int16_t)state - 512; if (pos > JOYSTICK_DEAD_ZONE_Y) { - m_mouseMoveY = map(pos, JOYSTICK_DEAD_ZONE_Y, 511, 0, m_mappedAxis[i].m_value); + m_mouseMoveY = map(pos, JOYSTICK_DEAD_ZONE_Y, 511, 0, m_mappedAxis[i].m_value1); } else if (pos < -JOYSTICK_DEAD_ZONE_Y) { - m_mouseMoveY = map(pos, -512, -JOYSTICK_DEAD_ZONE_Y, -m_mappedAxis[i].m_value, 0); + m_mouseMoveY = map(pos, -512, -JOYSTICK_DEAD_ZONE_Y, -m_mappedAxis[i].m_value1, 0); } else { m_mouseMoveY = 0; } } - break; - default: + case MIDI_CTRL_AXIS: +#ifdef HAVE_MIDI + { + midiEventPacket_t event = {0x0B, (uint8_t)(0xB0 | m_mappedAxis[i].m_value1), m_mappedAxis[i].m_value2, (uint8_t)(state/8)}; + MidiUSB.sendMIDI(event); + MidiUSB.flush(); + } +#endif + break; + case MIDI_PITCH_AXIS: +#ifdef HAVE_MIDI + { + uint16_t val = (1023-state) * 16; + midiEventPacket_t event = {0x0E, (uint8_t)(0xE0 | m_mappedAxis[i].m_value1), (unsigned char)(val&127), (uint8_t)(val>>7)}; + MidiUSB.sendMIDI(event); + MidiUSB.flush(); + } +#endif + break; + case MAPPING_NONE: + case JOYSTICK_BUTTON: + case MOUSE_BUTTON: + case MOUSE_REL_WHEEL: + case NEXT_PROFILE: + case PREV_PROFILE: + case SWITCH_PROFILE: + case MACRO_PRESS: + case MACRO_RELEASE: + case KEYBOARD_BUTTON: + case MIDI_NOTE: + case MIDI_CTRL: + case MIDI_PITCH: break; } } @@ -550,27 +645,27 @@ void CimditProfile::buttonAction(uint8_t num, bool state) { switch (m_mappedButtons[i].m_type) { case JOYSTICK_BUTTON: if (state) { - Gamepad.press(m_mappedButtons[i].m_value); + Gamepad.press(m_mappedButtons[i].m_value1); } else { - Gamepad.release(m_mappedButtons[i].m_value); + Gamepad.release(m_mappedButtons[i].m_value1); } Gamepad.write(); break; case MOUSE_BUTTON: if (state) { - Mouse.press(m_mappedButtons[i].m_value); + Mouse.press(m_mappedButtons[i].m_value1); } else { - Mouse.release(m_mappedButtons[i].m_value); + Mouse.release(m_mappedButtons[i].m_value1); } break; case MOUSE_REL_X_AXIS: - Mouse.move(m_mappedButtons[i].m_value, 0, 0); + Mouse.move(m_mappedButtons[i].m_value1, 0, 0); break; case MOUSE_REL_Y_AXIS: - Mouse.move(0, m_mappedButtons[i].m_value, 0); + Mouse.move(0, m_mappedButtons[i].m_value1, 0); break; case MOUSE_REL_WHEEL: - Mouse.move(0, 0, m_mappedButtons[i].m_value); + Mouse.move(0, 0, m_mappedButtons[i].m_value1); break; case NEXT_PROFILE: case PREV_PROFILE: @@ -592,21 +687,57 @@ void CimditProfile::buttonAction(uint8_t num, bool state) { break; case MACRO_PRESS: if (state) - scanOrExecuteMacro(m_mappedButtons[i].m_value, true); + scanOrExecuteMacro(m_mappedButtons[i].m_value1, true); break; case MACRO_RELEASE: if (!state) - scanOrExecuteMacro(m_mappedButtons[i].m_value, true); + scanOrExecuteMacro(m_mappedButtons[i].m_value1, true); break; case KEYBOARD_BUTTON: if (state) { - Keyboard.press((KeyboardKeycode)m_mappedButtons[i].m_value); + Keyboard.press((KeyboardKeycode)m_mappedButtons[i].m_value1); } else { - Keyboard.release((KeyboardKeycode)m_mappedButtons[i].m_value); + Keyboard.release((KeyboardKeycode)m_mappedButtons[i].m_value1); } break; + case MIDI_NOTE: +#ifdef HAVE_MIDI + if (state) { + // send a midi note on message + midiEventPacket_t noteOn = {0x09, (uint8_t)(0x90 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3}; + MidiUSB.sendMIDI(noteOn); + } else { + // send a midi note on message + midiEventPacket_t noteOff = {0x08, (uint8_t)(0x80 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3}; + MidiUSB.sendMIDI(noteOff); + } + MidiUSB.flush(); +#endif + break; + case MIDI_CTRL: +#ifdef HAVE_MIDI + { + // send a midi note on message + midiEventPacket_t control = {0x0B, (uint8_t)(0xB0 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3}; + MidiUSB.sendMIDI(control); + MidiUSB.flush(); + } +#endif + break; + case MIDI_PITCH: +#ifdef HAVE_MIDI + { + // send a midi note on message + midiEventPacket_t event = {0x0E, (uint8_t)(0xE0 | m_mappedButtons[i].m_value1), m_mappedButtons[i].m_value2, m_mappedButtons[i].m_value3}; + MidiUSB.sendMIDI(event); + MidiUSB.flush(); + } +#endif + break; case MAPPING_NONE: case JOYSTICK_AXIS: + case MIDI_CTRL_AXIS: + case MIDI_PITCH_AXIS: break; } } @@ -736,7 +867,6 @@ void CimditProfile::writeFlash() { } m_displayState = DISPLAY_BLANK; // to enforce a redraw showActiveProfile(); - return false; } void CimditProfile::setUserString(uint8_t timeout, const char* input) { @@ -787,7 +917,7 @@ void CimditProfile::userDisplay() { buf = 0; uint16_t len = width * height; if (width != SCREEN_WIDTH || SCREEN_HEIGHT != 32) { - for (uint8_t i = 0; i < width * height; ++i) { + for (uint8_t i = 0; i < len; ++i) { buf = Serial.read(); if (buf == '\n') buf = Serial.read(); } diff --git a/cimditprofile.h b/cimditprofile.h index b080b6d..8422945 100644 --- a/cimditprofile.h +++ b/cimditprofile.h @@ -94,6 +94,16 @@ class CimditProfile { MACRO_RELEASE, /// mapping as keyboard button KEYBOARD_BUTTON, + /// mapping as MIDI note + MIDI_NOTE, + /// mapping as MIDI command + MIDI_CTRL, + /// mapping as MIDI pitch + MIDI_PITCH, + /// mapping axis as MIDI command + MIDI_CTRL_AXIS, + /// mapping axis as MIDI pitch + MIDI_PITCH_AXIS }; /// enums for use in macros @@ -134,6 +144,14 @@ class CimditProfile { MACRO_MOUSE_REL_X_AXIS, // 13 /// move mouse Y according to an analog axis MACRO_MOUSE_REL_Y_AXIS, // 14 + /// MIDI note on + MACRO_MIDI_NOTEON, // 15 + /// MIDI note off + MACRO_MIDI_NOTEOFF, // 16 + /// MIDI send control message + MACRO_MIDI_CTRL, // 17 + /// MIDI send pitch message + MACRO_MIDI_PITCH, // 18 }; private: @@ -212,7 +230,13 @@ class CimditProfile { MappingType m_type; /// optional value - int8_t m_value; + uint8_t m_value1; + + /// optional value 2 + uint8_t m_value2; + + /// optional value 2 + uint8_t m_value3; }; /// number of mapped buttons diff --git a/defines.h b/defines.h index 267337c..f702fdf 100644 --- a/defines.h +++ b/defines.h @@ -1,6 +1,9 @@ /// we have a display connected #define HAVE_DISPLAY +/// we want to create MIDI +#define HAVE_MIDI + /// use a custom keyboard layout #define HID_CUSTOM_LAYOUT diff --git a/profilegenerator/html/index.html b/profilegenerator/html/index.html index 80a773f..5e9b4db 100644 --- a/profilegenerator/html/index.html +++ b/profilegenerator/html/index.html @@ -194,10 +194,143 @@ "source": 1, "type": "NEXT_PROFILE" } + ], + "macros": [] + }, + { + "name": "MIDI", + "mappedbuttons": [ + { + "source": 62, + "type": "SWITCH_PROFILE" + }, + { + "source": 61, + "type": "MIDI_NOTE", + "channel": 0, + "note": 48, + "velocity": 64 + }, + { + "source": 53, + "type": "MIDI_NOTE", + "channel": 0, + "note": 49, + "velocity": 64 + }, + { + "source": 45, + "type": "MIDI_NOTE", + "channel": 0, + "note": 50, + "velocity": 64 + }, + { + "source": 37, + "type": "MIDI_NOTE", + "channel": 0, + "note": 51, + "velocity": 64 + }, + { + "source": 46, + "type": "MIDI_CTRL", + "channel": 0, + "control": 10, + "value": 0 + }, + { + "source": 38, + "type": "MIDI_CTRL", + "channel": 0, + "control": 10, + "value": 64 + }, + { + "source": 49, + "type": "MIDI_PITCH", + "channel": 0, + "value": 0 + }, + { + "source": 41, + "type": "MIDI_PITCH", + "channel": 0, + "value": 8192 + }, + { + "source": 33, + "type": "MACRO_PRESS", + "macro": 0 + } + ], + "mappedaxis": [ + { + "source": 0, + "type": "MIDI_CTRL_AXIS", + "channel": 0, + "control": 10 + }, + { + "source": 1, + "type": "MIDI_PITCH_AXIS", + "channel": 0 + }, + { + "source": 2, + "type": "MIDI_CTRL_AXIS", + "channel": 0, + "control": 1 + } + ], + "mappedrotary": [ + { + "source": 0, + "type": "PREV_PROFILE" + }, + { + "source": 1, + "type": "NEXT_PROFILE" + } + ], + "macros": [ + [ + "MACRO_MIDI_NOTEON", + 0, + 60, + 64, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_CTRL", + 0, + 10, + 0, + "MACRO_DELAY", + 2000, + "MACRO_MIDI_CTRL", + 0, + 10, + 64, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_PITCH", + 0, + 512, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_PITCH", + 0, + 8192, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_NOTEOFF", + 0, + 60, + 64 + ] ] } -] - +]

diff --git a/profilegenerator/ts/ProfileGenerator.ts b/profilegenerator/ts/ProfileGenerator.ts index ace49f5..e4f0316 100644 --- a/profilegenerator/ts/ProfileGenerator.ts +++ b/profilegenerator/ts/ProfileGenerator.ts @@ -14,6 +14,10 @@ type EntityJson = { axis?: number; value?: number; macro?: number; + channel?: number; + note?: number; + velocity?: number; + control?: number; } type EntityProfileString = { @@ -48,6 +52,11 @@ class ProfileGenerator { "MACRO_PRESS", "MACRO_RELEASE", "KEYBOARD_BUTTON", + "MIDI_NOTE", + "MIDI_CTRL", + "MIDI_PITCH", + "MIDI_CTRL_AXIS", + "MIDI_PITCH_AXIS", ]; private macroEnum: Array = [ "MACRO_NULL", @@ -64,7 +73,11 @@ class ProfileGenerator { "MACRO_MOUSE_REL_X", "MACRO_MOUSE_REL_Y", "MACRO_MOUSE_REL_X_AXIS", - "MACRO_MOUSE_REL_Y_AXIS" + "MACRO_MOUSE_REL_Y_AXIS", + "MACRO_MIDI_NOTEON", + "MACRO_MIDI_NOTEOFF", + "MACRO_MIDI_CTRL", + "MACRO_MIDI_PITCH", ]; private keyLookup = { @@ -424,7 +437,6 @@ class ProfileGenerator { map(entities: Array) : EntityProfileString { var out =""; - var bytes = 0 var count = 0; for (var i = 0; i < entities.length; ++i) { var entity = entities[i]; @@ -437,8 +449,27 @@ class ProfileGenerator { } else { tmp += this.hexString(this.keyLookup[entity.target]); } + } else if (entity.channel !== undefined && entity.note !== undefined && entity.velocity !== undefined && entity.type === 'MIDI_NOTE') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.note); + tmp += this.hexString(entity.velocity); + } else if (entity.channel !== undefined && entity.control !== undefined && entity.value !== undefined && entity.type === 'MIDI_CTRL') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.control); + tmp += this.hexString(entity.value); + } else if (entity.channel !== undefined && entity.value !== undefined && entity.type === 'MIDI_PITCH') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.value >> 8); + tmp += this.hexString(entity.value & 255); + } else if (entity.channel !== undefined && entity.control !== undefined && entity.type === 'MIDI_CTRL_AXIS') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.control); + } else if (entity.channel !== undefined && entity.type === 'MIDI_PITCH_AXIS') { + tmp += this.hexString(entity.channel); } else if (entity.axis !== undefined) { tmp += this.hexString(entity.axis); + } else if (entity.control !== undefined) { + tmp += this.hexString(entity.control); } else if (entity.value !== undefined) { tmp += this.hexString(entity.value); } else if (entity.macro !== undefined) { @@ -447,14 +478,13 @@ class ProfileGenerator { tmp += "00"; } out += tmp; - bytes += 3; ++count; } catch(e) { // print error console.log(e); } } - return {bytes: bytes, count: count, string: out}; + return {bytes: out.length / 2, count: count, string: out}; } createMacroString(macros: any[][]) : EntityProfileString { @@ -512,6 +542,17 @@ class ProfileGenerator { out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]); bytes +=3; } + } else if (token === "MACRO_MIDI_NOTEON" || token === "MACRO_MIDI_NOTEOFF") { // expect three integer values, channel, note and velocity + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]); + bytes += 4; + } else if (token === "MACRO_MIDI_CTRL") { // expect three integer values, channel, control and value + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]); + bytes += 4; + } else if (token === "MACRO_MIDI_PITCH") { // expect two integer values, channel and value (16 bit) + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]); + const value = macro[++j] + out += this.hexString(value >> 8) + this.hexString(value & 255); + bytes += 4; } else { if (typeof(token) === "number") { out += this.hexString(token); @@ -624,6 +665,22 @@ class ProfileGenerator { entity.value = this.fromHexS(tokens.shift()); } else if (entity.type === 'MACRO_PRESS' || entity.type === 'MACRO_RELEASE') { entity.macro = this.fromHexU(tokens.shift()); + } else if (entity.type === 'MIDI_NOTE') { + entity.channel = this.fromHexU(tokens.shift()); + entity.note = this.fromHexU(tokens.shift()); + entity.velocity = this.fromHexU(tokens.shift()); + } else if (entity.type === 'MIDI_CTRL') { + entity.channel = this.fromHexU(tokens.shift()); + entity.control = this.fromHexU(tokens.shift()); + entity.value = this.fromHexU(tokens.shift()); + } else if (entity.type === 'MIDI_PITCH') { + entity.channel = this.fromHexU(tokens.shift()); + entity.value = this.fromHexU(tokens.shift())<<8 + this.fromHexU(tokens.shift()); + } else if (entity.type === 'MIDI_CTRL_AXIS') { + entity.channel = this.fromHexU(tokens.shift()); + entity.control = this.fromHexU(tokens.shift()); + } else if (entity.type === 'MIDI_PITCH_AXIS') { + entity.channel = this.fromHexU(tokens.shift()); } else { tokens.shift(); } @@ -691,6 +748,21 @@ class ProfileGenerator { macro.push(this.fromHexS(tokens.shift())); } break; + case "MACRO_MIDI_NOTEON": + case "MACRO_MIDI_NOTEOFF": + macro.push(this.fromHexS(tokens.shift())); // channel + macro.push(this.fromHexS(tokens.shift())); // note + macro.push(this.fromHexS(tokens.shift())); // velocity + break; + case "MACRO_MIDI_CTRL": + macro.push(this.fromHexS(tokens.shift())); // channel + macro.push(this.fromHexS(tokens.shift())); // control + macro.push(this.fromHexS(tokens.shift())); // value + break; + case "MACRO_MIDI_PITCH": + macro.push(this.fromHexS(tokens.shift())); // channel + macro.push(this.fromHexU(tokens.shift())<<8 + this.fromHexU(tokens.shift())); // value + break; } } while (token !== "MACRO_NULL" && tokens.length > 0); return macro; diff --git a/profilegenerator/webroot/index.html b/profilegenerator/webroot/index.html index dc53a37..773fb4c 100644 --- a/profilegenerator/webroot/index.html +++ b/profilegenerator/webroot/index.html @@ -194,10 +194,143 @@ textarea{width:100%}#string{height:5vh}.codeEditor,.lineCounter{font-family:cour "source": 1, "type": "NEXT_PROFILE" } + ], + "macros": [] + }, + { + "name": "MIDI", + "mappedbuttons": [ + { + "source": 62, + "type": "SWITCH_PROFILE" + }, + { + "source": 61, + "type": "MIDI_NOTE", + "channel": 0, + "note": 48, + "velocity": 64 + }, + { + "source": 53, + "type": "MIDI_NOTE", + "channel": 0, + "note": 49, + "velocity": 64 + }, + { + "source": 45, + "type": "MIDI_NOTE", + "channel": 0, + "note": 50, + "velocity": 64 + }, + { + "source": 37, + "type": "MIDI_NOTE", + "channel": 0, + "note": 51, + "velocity": 64 + }, + { + "source": 46, + "type": "MIDI_CTRL", + "channel": 0, + "control": 10, + "value": 0 + }, + { + "source": 38, + "type": "MIDI_CTRL", + "channel": 0, + "control": 10, + "value": 64 + }, + { + "source": 49, + "type": "MIDI_PITCH", + "channel": 0, + "value": 0 + }, + { + "source": 41, + "type": "MIDI_PITCH", + "channel": 0, + "value": 8192 + }, + { + "source": 33, + "type": "MACRO_PRESS", + "macro": 0 + } + ], + "mappedaxis": [ + { + "source": 0, + "type": "MIDI_CTRL_AXIS", + "channel": 0, + "control": 10 + }, + { + "source": 1, + "type": "MIDI_PITCH_AXIS", + "channel": 0 + }, + { + "source": 2, + "type": "MIDI_CTRL_AXIS", + "channel": 0, + "control": 1 + } + ], + "mappedrotary": [ + { + "source": 0, + "type": "PREV_PROFILE" + }, + { + "source": 1, + "type": "NEXT_PROFILE" + } + ], + "macros": [ + [ + "MACRO_MIDI_NOTEON", + 0, + 60, + 64, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_CTRL", + 0, + 10, + 0, + "MACRO_DELAY", + 2000, + "MACRO_MIDI_CTRL", + 0, + 10, + 64, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_PITCH", + 0, + 512, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_PITCH", + 0, + 8192, + "MACRO_DELAY", + 1000, + "MACRO_MIDI_NOTEOFF", + 0, + 60, + 64 + ] ] } -] - +]

@@ -227,6 +360,11 @@ var ProfileGenerator = (function () { "MACRO_PRESS", "MACRO_RELEASE", "KEYBOARD_BUTTON", + "MIDI_NOTE", + "MIDI_CTRL", + "MIDI_PITCH", + "MIDI_CTRL_AXIS", + "MIDI_PITCH_AXIS", ]; this.macroEnum = [ "MACRO_NULL", @@ -243,7 +381,11 @@ var ProfileGenerator = (function () { "MACRO_MOUSE_REL_X", "MACRO_MOUSE_REL_Y", "MACRO_MOUSE_REL_X_AXIS", - "MACRO_MOUSE_REL_Y_AXIS" + "MACRO_MOUSE_REL_Y_AXIS", + "MACRO_MIDI_NOTEON", + "MACRO_MIDI_NOTEOFF", + "MACRO_MIDI_CTRL", + "MACRO_MIDI_PITCH", ]; this.keyLookup = { "KEY_RESERVED": 0, @@ -597,7 +739,6 @@ var ProfileGenerator = (function () { }; ProfileGenerator.prototype.map = function (entities) { var out = ""; - var bytes = 0; var count = 0; for (var i = 0; i < entities.length; ++i) { var entity = entities[i]; @@ -612,9 +753,34 @@ var ProfileGenerator = (function () { tmp += this.hexString(this.keyLookup[entity.target]); } } + else if (entity.channel !== undefined && entity.note !== undefined && entity.velocity !== undefined && entity.type === 'MIDI_NOTE') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.note); + tmp += this.hexString(entity.velocity); + } + else if (entity.channel !== undefined && entity.control !== undefined && entity.value !== undefined && entity.type === 'MIDI_CTRL') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.control); + tmp += this.hexString(entity.value); + } + else if (entity.channel !== undefined && entity.value !== undefined && entity.type === 'MIDI_PITCH') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.value >> 8); + tmp += this.hexString(entity.value & 255); + } + else if (entity.channel !== undefined && entity.control !== undefined && entity.type === 'MIDI_CTRL_AXIS') { + tmp += this.hexString(entity.channel); + tmp += this.hexString(entity.control); + } + else if (entity.channel !== undefined && entity.type === 'MIDI_PITCH_AXIS') { + tmp += this.hexString(entity.channel); + } else if (entity.axis !== undefined) { tmp += this.hexString(entity.axis); } + else if (entity.control !== undefined) { + tmp += this.hexString(entity.control); + } else if (entity.value !== undefined) { tmp += this.hexString(entity.value); } @@ -625,14 +791,13 @@ var ProfileGenerator = (function () { tmp += "00"; } out += tmp; - bytes += 3; ++count; } catch (e) { console.log(e); } } - return { bytes: bytes, count: count, string: out }; + return { bytes: out.length / 2, count: count, string: out }; }; ProfileGenerator.prototype.createMacroString = function (macros) { var bytes = 0; @@ -695,6 +860,20 @@ var ProfileGenerator = (function () { bytes += 3; } } + else if (token === "MACRO_MIDI_NOTEON" || token === "MACRO_MIDI_NOTEOFF") { + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]); + bytes += 4; + } + else if (token === "MACRO_MIDI_CTRL") { + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]) + this.hexString(macro[++j]); + bytes += 4; + } + else if (token === "MACRO_MIDI_PITCH") { + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]); + const value = macro[++j]; + out += this.hexString(value >> 8) + this.hexString(value & 255); + bytes += 4; + } else { if (typeof (token) === "number") { out += this.hexString(token); @@ -811,6 +990,27 @@ var ProfileGenerator = (function () { else if (entity.type === 'MACRO_PRESS' || entity.type === 'MACRO_RELEASE') { entity.macro = this.fromHexU(tokens.shift()); } + else if (entity.type === 'MIDI_NOTE') { + entity.channel = this.fromHexU(tokens.shift()); + entity.note = this.fromHexU(tokens.shift()); + entity.velocity = this.fromHexU(tokens.shift()); + } + else if (entity.type === 'MIDI_CTRL') { + entity.channel = this.fromHexU(tokens.shift()); + entity.control = this.fromHexU(tokens.shift()); + entity.value = this.fromHexU(tokens.shift()); + } + else if (entity.type === 'MIDI_PITCH') { + entity.channel = this.fromHexU(tokens.shift()); + entity.value = this.fromHexU(tokens.shift()) << 8 + this.fromHexU(tokens.shift()); + } + else if (entity.type === 'MIDI_CTRL_AXIS') { + entity.channel = this.fromHexU(tokens.shift()); + entity.control = this.fromHexU(tokens.shift()); + } + else if (entity.type === 'MIDI_PITCH_AXIS') { + entity.channel = this.fromHexU(tokens.shift()); + } else { tokens.shift(); } @@ -878,6 +1078,21 @@ var ProfileGenerator = (function () { macro.push(this.fromHexS(tokens.shift())); } break; + case "MACRO_MIDI_NOTEON": + case "MACRO_MIDI_NOTEOFF": + macro.push(this.fromHexS(tokens.shift())); + macro.push(this.fromHexS(tokens.shift())); + macro.push(this.fromHexS(tokens.shift())); + break; + case "MACRO_MIDI_CTRL": + macro.push(this.fromHexS(tokens.shift())); + macro.push(this.fromHexS(tokens.shift())); + macro.push(this.fromHexS(tokens.shift())); + break; + case "MACRO_MIDI_PITCH": + macro.push(this.fromHexS(tokens.shift())); + macro.push(this.fromHexU(tokens.shift()) << 8 + this.fromHexU(tokens.shift())); + break; } } while (token !== "MACRO_NULL" && tokens.length > 0); return macro;