Browse Source

Added preliminary computer keyboard MIDI support

tags/v0.6.1
Andrew Belt 6 years ago
parent
commit
6829aab3d5
6 changed files with 171 additions and 7 deletions
  1. +1
    -1
      include/gamepad.hpp
  2. +33
    -0
      include/keyboard.hpp
  3. +5
    -6
      src/gamepad.cpp
  4. +115
    -0
      src/keyboard.cpp
  5. +6
    -0
      src/midi.cpp
  6. +11
    -0
      src/window.cpp

+ 1
- 1
include/gamepad.hpp View File

@@ -13,7 +13,7 @@ const int GAMEPAD_DRIVER = -10;
struct GamepadInputDevice : MidiInputDevice {
int deviceId;
std::vector<uint8_t> ccs;
std::vector<bool> notes;
std::vector<bool> states;
void step();
};



+ 33
- 0
include/keyboard.hpp View File

@@ -0,0 +1,33 @@
#pragma once

#include "util/common.hpp"
#include "midi.hpp"


namespace rack {


const int KEYBOARD_DRIVER = -11;


struct KeyboardInputDevice : MidiInputDevice {
int octave = 5;
void processKey(int key, bool released);
};


struct KeyboardInputDriver : MidiInputDriver {
KeyboardInputDevice device;

std::vector<int> getDeviceIds() override;
std::string getDeviceName(int deviceId) override;
MidiInputDevice *getDevice(int deviceId) override;
};


void keyboardPress(int key);
void keyboardRelease(int key);
KeyboardInputDriver *keyboardGetInputDriver();


} // namespace rack

+ 5
- 6
src/gamepad.cpp View File

@@ -1,5 +1,4 @@
#include "gamepad.hpp"
#include "util/common.hpp"
#include <GLFW/glfw3.h>


@@ -34,14 +33,14 @@ void GamepadInputDevice::step() {
}

// Convert buttons to MIDI notes
notes.resize(numButtons);
states.resize(numButtons);
for (int i = 0; i < numButtons; i++) {
bool note = !!buttons[i];
if (note != notes[i]) {
notes[i] = note;
bool state = !!buttons[i];
if (state != states[i]) {
states[i] = state;

MidiMessage msg;
msg.cmd = ((note ? 0x9 : 0x8) << 4);
msg.cmd = ((state ? 0x9 : 0x8) << 4);
msg.data1 = i;
msg.data2 = 127;
onMessage(msg);


+ 115
- 0
src/keyboard.cpp View File

@@ -0,0 +1,115 @@
#include "keyboard.hpp"
#include <GLFW/glfw3.h>


namespace rack {


void KeyboardInputDevice::processKey(int key, bool released) {
int note = -1;
switch (key) {
case GLFW_KEY_Z: note = 0; break;
case GLFW_KEY_S: note = 1; break;
case GLFW_KEY_X: note = 2; break;
case GLFW_KEY_D: note = 3; break;
case GLFW_KEY_C: note = 4; break;
case GLFW_KEY_V: note = 5; break;
case GLFW_KEY_G: note = 6; break;
case GLFW_KEY_B: note = 7; break;
case GLFW_KEY_H: note = 8; break;
case GLFW_KEY_N: note = 9; break;
case GLFW_KEY_J: note = 10; break;
case GLFW_KEY_M: note = 11; break;
case GLFW_KEY_COMMA: note = 12; break;
case GLFW_KEY_L: note = 13; break;
case GLFW_KEY_PERIOD: note = 14; break;
case GLFW_KEY_SEMICOLON: note = 15; break;
case GLFW_KEY_SLASH: note = 16; break;

case GLFW_KEY_Q: note = 12; break;
case GLFW_KEY_2: note = 13; break;
case GLFW_KEY_W: note = 14; break;
case GLFW_KEY_3: note = 15; break;
case GLFW_KEY_E: note = 16; break;
case GLFW_KEY_R: note = 17; break;
case GLFW_KEY_5: note = 18; break;
case GLFW_KEY_T: note = 19; break;
case GLFW_KEY_6: note = 20; break;
case GLFW_KEY_Y: note = 21; break;
case GLFW_KEY_7: note = 22; break;
case GLFW_KEY_U: note = 23; break;
case GLFW_KEY_I: note = 24; break;
case GLFW_KEY_9: note = 25; break;
case GLFW_KEY_O: note = 26; break;
case GLFW_KEY_0: note = 27; break;
case GLFW_KEY_P: note = 28; break;
case GLFW_KEY_LEFT_BRACKET: note = 29; break;
case GLFW_KEY_EQUAL: note = 30; break;
case GLFW_KEY_RIGHT_BRACKET: note = 31; break;

case GLFW_KEY_GRAVE_ACCENT: {
if (!released)
octave--;
} break;
case GLFW_KEY_1: {
if (!released)
octave++;
} break;
default: break;
}

octave = clamp(octave, 0, 9);
if (note < 0)
return;
note += 12 * octave;

if (note > 127)
return;

MidiMessage msg;
msg.cmd = ((!released ? 0x9 : 0x8) << 4);
msg.data1 = note;
msg.data2 = 127;
onMessage(msg);
}


std::vector<int> KeyboardInputDriver::getDeviceIds() {
return {0};
}

std::string KeyboardInputDriver::getDeviceName(int deviceId) {
if (deviceId == 0)
return "QWERTY keyboard (US)";
return "";
}

MidiInputDevice *KeyboardInputDriver::getDevice(int deviceId) {
return &device;
}


static KeyboardInputDriver *driver = NULL;

void keyboardPress(int key) {
if (!driver)
return;
driver->device.processKey(key, false);
}

void keyboardRelease(int key) {
if (!driver)
return;
driver->device.processKey(key, true);
}

KeyboardInputDriver *keyboardGetInputDriver() {
// Lazily create driver
if (!driver) {
driver = new KeyboardInputDriver();
}
return driver;
}


} // namespace rack

+ 6
- 0
src/midi.cpp View File

@@ -2,6 +2,7 @@
#include "rtmidi.hpp"
#include "bridge.hpp"
#include "gamepad.hpp"
#include "keyboard.hpp"


namespace rack {
@@ -45,6 +46,7 @@ std::vector<int> MidiIO::getDriverIds() {
// Add custom driverIds
driverIds.push_back(BRIDGE_DRIVER);
driverIds.push_back(GAMEPAD_DRIVER);
driverIds.push_back(KEYBOARD_DRIVER);
return driverIds;
}

@@ -59,6 +61,7 @@ std::string MidiIO::getDriverName(int driverId) {
case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI";
case BRIDGE_DRIVER: return "Bridge";
case GAMEPAD_DRIVER: return "Gamepad";
case KEYBOARD_DRIVER: return "Computer keyboard";
default: return "Unknown";
}
}
@@ -132,6 +135,9 @@ void MidiInput::setDriverId(int driverId) {
else if (driverId == GAMEPAD_DRIVER) {
driver = gamepadGetInputDriver();
}
else if (driverId == KEYBOARD_DRIVER) {
driver = keyboardGetInputDriver();
}

// Set driverId
if (driver) {


+ 11
- 0
src/window.cpp View File

@@ -2,6 +2,7 @@
#include "app.hpp"
#include "asset.hpp"
#include "gamepad.hpp"
#include "keyboard.hpp"
#include "util/color.hpp"

#include <map>
@@ -262,6 +263,16 @@ void charCallback(GLFWwindow *window, unsigned int codepoint) {
}

void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
// Keyboard MIDI driver
if (1 || glfwGetInputMode(gWindow, GLFW_LOCK_KEY_MODS) & GLFW_MOD_CAPS_LOCK) {
if (action == GLFW_PRESS) {
keyboardPress(key);
}
else if (action == GLFW_RELEASE) {
keyboardRelease(key);
}
}

if (action == GLFW_PRESS || action == GLFW_REPEAT) {
if (gFocusedWidget) {
// onKey


Loading…
Cancel
Save