Browse Source

Move MIDI subclasses to source files

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
f312191e0a
9 changed files with 396 additions and 359 deletions
  1. +0
    -16
      include/bridge.hpp
  2. +0
    -21
      include/gamepad.hpp
  3. +0
    -21
      include/keyboard.hpp
  4. +0
    -34
      include/rtmidi.hpp
  5. +44
    -30
      src/bridge.cpp
  6. +84
    -68
      src/gamepad.cpp
  7. +108
    -93
      src/keyboard.cpp
  8. +1
    -0
      src/main.cpp
  9. +159
    -76
      src/rtmidi.cpp

+ 0
- 16
include/bridge.hpp View File

@@ -1,27 +1,11 @@
#pragma once
#include "bridgeprotocol.hpp"
#include "audio.hpp"
#include "midi.hpp"


namespace rack {


struct BridgeMidiInputDevice : midi::InputDevice {
};


struct BridgeMidiDriver : midi::Driver {
BridgeMidiInputDevice devices[16];
std::string getName() override {return "Bridge";}

std::vector<int> getInputDeviceIds() override;
std::string getInputDeviceName(int deviceId) override;
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override;
void unsubscribeInput(int deviceId, midi::Input *input) override;
};


void bridgeInit();
void bridgeDestroy();
void bridgeAudioSubscribe(int channel, audio::IO *audio);


+ 0
- 21
include/gamepad.hpp View File

@@ -1,32 +1,11 @@
#pragma once
#include "common.hpp"
#include "midi.hpp"


namespace rack {
namespace gamepad {


struct InputDevice : midi::InputDevice {
int deviceId;
std::vector<uint8_t> ccs;
std::vector<bool> states;
void step();
};


struct Driver : midi::Driver {
InputDevice devices[16];

Driver();
std::string getName() override {return "Gamepad";}
std::vector<int> getInputDeviceIds() override;
std::string getInputDeviceName(int deviceId) override;
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override;
void unsubscribeInput(int deviceId, midi::Input *input) override;
};


void init();
void step();



+ 0
- 21
include/keyboard.hpp View File

@@ -1,32 +1,11 @@
#pragma once
#include "common.hpp"
#include "midi.hpp"
#include <map>


namespace rack {
namespace keyboard {


struct InputDevice : midi::InputDevice {
int octave = 5;
std::map<int, int> pressedNotes;
void onKeyPress(int key);
void onKeyRelease(int key);
};


struct Driver : midi::Driver {
InputDevice device;
std::string getName() override {return "Computer keyboard";}

std::vector<int> getInputDeviceIds() override;
std::string getInputDeviceName(int deviceId) override;
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override;
void unsubscribeInput(int deviceId, midi::Input *input) override;
};


void init();
void press(int key);
void release(int key);


+ 0
- 34
include/rtmidi.hpp View File

@@ -1,44 +1,10 @@
#pragma once
#include "common.hpp"
#include "midi.hpp"
#include <map>

#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif
#include <rtmidi/RtMidi.h>
#pragma GCC diagnostic pop


namespace rack {


struct RtMidiInputDevice : midi::InputDevice {
RtMidiIn *rtMidiIn;

RtMidiInputDevice(int driverId, int deviceId);
~RtMidiInputDevice();
};


struct RtMidiDriver : midi::Driver {
int driverId;
/** Just for querying MIDI driver information */
RtMidiIn *rtMidiIn;
RtMidiOut *rtMidiOut;
std::map<int, RtMidiInputDevice*> devices;

RtMidiDriver(int driverId);
~RtMidiDriver();
std::string getName() override;
std::vector<int> getInputDeviceIds() override;
std::string getInputDeviceName(int deviceId) override;
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override;
void unsubscribeInput(int deviceId, midi::Input *input) override;
};


void rtmidiInit();




+ 44
- 30
src/bridge.cpp View File

@@ -1,4 +1,5 @@
#include "bridge.hpp"
#include "midi.hpp"
#include "string.hpp"
#include "dsp/ringbuffer.hpp"

@@ -19,6 +20,9 @@
namespace rack {


struct BridgeMidiDriver;


struct BridgeClientConnection;
static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {};
static audio::IO *audioListeners[BRIDGE_NUM_PORTS] = {};
@@ -27,6 +31,46 @@ static bool serverRunning = false;
static BridgeMidiDriver *driver = NULL;


struct BridgeMidiInputDevice : midi::InputDevice {
};


struct BridgeMidiDriver : midi::Driver {
BridgeMidiInputDevice devices[16];

std::string getName() override {return "Bridge";}

std::vector<int> getInputDeviceIds() override {
std::vector<int> deviceIds;
for (int i = 0; i < 16; i++) {
deviceIds.push_back(i);
}
return deviceIds;
}

std::string getInputDeviceName(int deviceId) override {
if (deviceId < 0)
return "";
return string::f("Port %d", deviceId + 1);
}

midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
if (!(0 <= deviceId && deviceId < 16))
return NULL;

devices[deviceId].subscribe(input);
return &devices[deviceId];
}

void unsubscribeInput(int deviceId, midi::Input *input) override {
if (!(0 <= deviceId && deviceId < 16))
return;

devices[deviceId].unsubscribe(input);
}
};


struct BridgeClientConnection {
int client;
bool ready = false;
@@ -372,36 +416,6 @@ static void serverRun() {
}


std::vector<int> BridgeMidiDriver::getInputDeviceIds() {
std::vector<int> deviceIds;
for (int i = 0; i < 16; i++) {
deviceIds.push_back(i);
}
return deviceIds;
}

std::string BridgeMidiDriver::getInputDeviceName(int deviceId) {
if (deviceId < 0)
return "";
return string::f("Port %d", deviceId + 1);
}

midi::InputDevice *BridgeMidiDriver::subscribeInput(int deviceId, midi::Input *input) {
if (!(0 <= deviceId && deviceId < 16))
return NULL;

devices[deviceId].subscribe(input);
return &devices[deviceId];
}

void BridgeMidiDriver::unsubscribeInput(int deviceId, midi::Input *input) {
if (!(0 <= deviceId && deviceId < 16))
return;

devices[deviceId].unsubscribe(input);
}


void bridgeInit() {
serverRunning = true;
serverThread = std::thread(serverRun);


+ 84
- 68
src/gamepad.cpp View File

@@ -1,4 +1,5 @@
#include "gamepad.hpp"
#include "midi.hpp"
#include "string.hpp"
#include "window.hpp"

@@ -7,95 +8,110 @@ namespace rack {
namespace gamepad {


struct Driver;


static const int DRIVER = -10;
static Driver *driver = NULL;


void InputDevice::step() {
if (!glfwJoystickPresent(deviceId))
return;
// Get gamepad state
int numAxes;
const float *axes = glfwGetJoystickAxes(deviceId, &numAxes);
int numButtons;
const unsigned char *buttons = glfwGetJoystickButtons(deviceId, &numButtons);

// Convert axes to MIDI CC
ccs.resize(numAxes);
for (int i = 0; i < numAxes; i++) {
// Allow CC value to go negative, but clamp at -127 instead of -128 for symmetry
int8_t cc = math::clamp((int) std::round(axes[i] * 127), -127, 127);
if (cc != ccs[i]) {
ccs[i] = cc;

// Send MIDI message
midi::Message msg;
// MIDI channel 1
msg.cmd = (0xb << 4) | 0;
msg.data1 = i;
msg.data2 = ccs[i];
onMessage(msg);
struct InputDevice : midi::InputDevice {
int deviceId;
std::vector<uint8_t> ccs;
std::vector<bool> states;

void step() {
if (!glfwJoystickPresent(deviceId))
return;
// Get gamepad state
int numAxes;
const float *axes = glfwGetJoystickAxes(deviceId, &numAxes);
int numButtons;
const unsigned char *buttons = glfwGetJoystickButtons(deviceId, &numButtons);

// Convert axes to MIDI CC
ccs.resize(numAxes);
for (int i = 0; i < numAxes; i++) {
// Allow CC value to go negative, but clamp at -127 instead of -128 for symmetry
int8_t cc = math::clamp((int) std::round(axes[i] * 127), -127, 127);
if (cc != ccs[i]) {
ccs[i] = cc;

// Send MIDI message
midi::Message msg;
// MIDI channel 1
msg.cmd = (0xb << 4) | 0;
msg.data1 = i;
msg.data2 = ccs[i];
onMessage(msg);
}
}
}

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

midi::Message msg;
msg.cmd = ((state ? 0x9 : 0x8) << 4);
msg.data1 = i;
msg.data2 = 127;
onMessage(msg);
// Convert buttons to MIDI notes
states.resize(numButtons);
for (int i = 0; i < numButtons; i++) {
bool state = !!buttons[i];
if (state != states[i]) {
states[i] = state;

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


Driver::Driver() {
for (int i = 0; i < 16; i++) {
devices[i].deviceId = i;
struct Driver : midi::Driver {
InputDevice devices[16];

Driver() {
for (int i = 0; i < 16; i++) {
devices[i].deviceId = i;
}
}
}

std::vector<int> Driver::getInputDeviceIds() {
std::vector<int> deviceIds;
for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(i)) {
deviceIds.push_back(i);
std::string getName() override {return "Gamepad";}

std::vector<int> getInputDeviceIds() override {
std::vector<int> deviceIds;
for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(i)) {
deviceIds.push_back(i);
}
}
return deviceIds;
}
return deviceIds;
}

std::string Driver::getInputDeviceName(int deviceId) {
if (!(0 <= deviceId && deviceId < 16))
return "";
std::string getInputDeviceName(int deviceId) override {
if (!(0 <= deviceId && deviceId < 16))
return "";

const char *name = glfwGetJoystickName(deviceId);
if (name) {
return name;
const char *name = glfwGetJoystickName(deviceId);
if (name) {
return name;
}
return string::f(" %d (unavailable)", deviceId + 1);
}
return string::f(" %d (unavailable)", deviceId + 1);
}

midi::InputDevice *Driver::subscribeInput(int deviceId, midi::Input *input) {
if (!(0 <= deviceId && deviceId < 16))
return NULL;
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
if (!(0 <= deviceId && deviceId < 16))
return NULL;

devices[deviceId].subscribe(input);
return &devices[deviceId];
}
devices[deviceId].subscribe(input);
return &devices[deviceId];
}

void Driver::unsubscribeInput(int deviceId, midi::Input *input) {
if (!(0 <= deviceId && deviceId < 16))
return;
void unsubscribeInput(int deviceId, midi::Input *input) override {
if (!(0 <= deviceId && deviceId < 16))
return;

devices[deviceId].unsubscribe(input);
}
devices[deviceId].unsubscribe(input);
}
};


void init() {


+ 108
- 93
src/keyboard.cpp View File

@@ -1,122 +1,137 @@
#include "keyboard.hpp"
#include "midi.hpp"
#include "window.hpp"
#include <map>


namespace rack {
namespace keyboard {


static const int DRIVER = -11;
static Driver *driver = NULL;

struct Driver;

void InputDevice::onKeyPress(int key) {
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: {
octave--;
} break;
case GLFW_KEY_1: {
octave++;
} break;
default: break;
}

octave = math::clamp(octave, 0, 9);
if (note < 0)
return;

note += 12 * octave;
if (note > 127)
return;
static const int DRIVER = -11;
static Driver *driver = NULL;

midi::Message msg;
msg.cmd = 0x9 << 4;
msg.data1 = note;
msg.data2 = 127;
onMessage(msg);

pressedNotes[key] = note;
}
struct InputDevice : midi::InputDevice {
int octave = 5;
std::map<int, int> pressedNotes;

void onKeyPress(int key) {
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: {
octave--;
} break;
case GLFW_KEY_1: {
octave++;
} break;
default: break;
}

octave = math::clamp(octave, 0, 9);
if (note < 0)
return;

note += 12 * octave;
if (note > 127)
return;

void InputDevice::onKeyRelease(int key) {
auto it = pressedNotes.find(key);
if (it != pressedNotes.end()) {
int note = it->second;
midi::Message msg;
msg.cmd = 0x8 << 4;
msg.cmd = 0x9 << 4;
msg.data1 = note;
msg.data2 = 127;
onMessage(msg);

pressedNotes.erase(it);
pressedNotes[key] = note;
}
}

void onKeyRelease(int key) {
auto it = pressedNotes.find(key);
if (it != pressedNotes.end()) {
int note = it->second;
midi::Message msg;
msg.cmd = 0x8 << 4;
msg.data1 = note;
msg.data2 = 127;
onMessage(msg);

pressedNotes.erase(it);
}
}
};

std::vector<int> Driver::getInputDeviceIds() {
return {0};
}

std::string Driver::getInputDeviceName(int deviceId) {
if (deviceId == 0)
return "QWERTY keyboard (US)";
return "";
}
struct Driver : midi::Driver {
InputDevice device;
std::string getName() override {return "Computer keyboard";}

midi::InputDevice *Driver::subscribeInput(int deviceId, midi::Input *input) {
if (deviceId != 0)
return NULL;
std::vector<int> getInputDeviceIds() override {
return {0};
}

device.subscribe(input);
return &device;
}
std::string getInputDeviceName(int deviceId) override {
if (deviceId == 0)
return "QWERTY keyboard (US)";
return "";
}

void Driver::unsubscribeInput(int deviceId, midi::Input *input) {
if (deviceId != 0)
return;
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
if (deviceId != 0)
return NULL;

device.unsubscribe(input);
}
device.subscribe(input);
return &device;
}

void unsubscribeInput(int deviceId, midi::Input *input) override {
if (deviceId != 0)
return;

device.unsubscribe(input);
}
};


void init() {


+ 1
- 0
src/main.cpp View File

@@ -1,6 +1,7 @@
#include "common.hpp"
#include "random.hpp"
#include "asset.hpp"
#include "midi.hpp"
#include "rtmidi.hpp"
#include "keyboard.hpp"
#include "gamepad.hpp"


+ 159
- 76
src/rtmidi.cpp View File

@@ -1,107 +1,190 @@
#include "rtmidi.hpp"
#include "midi.hpp"
#include <map>

#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif
#include <rtmidi/RtMidi.h>
#pragma GCC diagnostic pop


namespace rack {


static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) {
if (!message) return;
if (!userData) return;
struct RtMidiInputDevice : midi::InputDevice {
RtMidiIn *rtMidiIn;

RtMidiInputDevice(int driverId, int deviceId) {
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId, "VCV Rack");
assert(rtMidiIn);
rtMidiIn->ignoreTypes(false, false, false);
rtMidiIn->setCallback(midiInputCallback, this);
rtMidiIn->openPort(deviceId, "VCV Rack input");
}

~RtMidiInputDevice() {
rtMidiIn->closePort();
delete rtMidiIn;
}

static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) {
if (!message) return;
if (!userData) return;

RtMidiInputDevice *midiInputDevice = (RtMidiInputDevice*) userData;
if (!midiInputDevice) return;
if (message->size() < 3) return;

RtMidiInputDevice *midiInputDevice = (RtMidiInputDevice*) userData;
if (!midiInputDevice) return;
midi::Message msg;
if (message->size() >= 1)
midi::Message msg;
msg.cmd = (*message)[0];
if (message->size() >= 2)
msg.data1 = (*message)[1];
if (message->size() >= 3)
msg.data2 = (*message)[2];
midiInputDevice->onMessage(msg);
}
};

midiInputDevice->onMessage(msg);
}

RtMidiInputDevice::RtMidiInputDevice(int driverId, int deviceId) {
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId, "VCV Rack");
assert(rtMidiIn);
rtMidiIn->ignoreTypes(false, false, false);
rtMidiIn->setCallback(midiInputCallback, this);
rtMidiIn->openPort(deviceId, "VCV Rack input");
}
struct RtMidiOutputDevice : midi::OutputDevice {
RtMidiOut *rtMidiOut;

RtMidiInputDevice::~RtMidiInputDevice() {
rtMidiIn->closePort();
delete rtMidiIn;
}
RtMidiOutputDevice(int driverId, int deviceId) {
rtMidiOut = new RtMidiOut((RtMidi::Api) driverId, "VCV Rack");
assert(rtMidiOut);
rtMidiOut->openPort(deviceId, "VCV Rack output");
}

~RtMidiOutputDevice() {
rtMidiOut->closePort();
delete rtMidiOut;
}

RtMidiDriver::RtMidiDriver(int driverId) {
this->driverId = driverId;
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId);
assert(rtMidiIn);
rtMidiOut = new RtMidiOut((RtMidi::Api) driverId);
assert(rtMidiOut);
}
void sendMessage(midi::Message message) override {
unsigned char msg[3];
msg[0] = message.cmd;
msg[0] = message.data1;
msg[0] = message.data2;
rtMidiOut->sendMessage(msg, 3);
}
};


struct RtMidiDriver : midi::Driver {
int driverId;
/** Just for querying MIDI driver information */
RtMidiIn *rtMidiIn;
RtMidiOut *rtMidiOut;
std::map<int, RtMidiInputDevice*> inputDevices;
std::map<int, RtMidiOutputDevice*> outputDevices;

RtMidiDriver(int driverId) {
this->driverId = driverId;
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId);
assert(rtMidiIn);
rtMidiOut = new RtMidiOut((RtMidi::Api) driverId);
assert(rtMidiOut);
}

RtMidiDriver::~RtMidiDriver() {
delete rtMidiIn;
delete rtMidiOut;
}
~RtMidiDriver() {
delete rtMidiIn;
delete rtMidiOut;
}

std::string RtMidiDriver::getName() {
switch (driverId) {
case RtMidi::UNSPECIFIED: return "Unspecified";
case RtMidi::MACOSX_CORE: return "Core MIDI";
case RtMidi::LINUX_ALSA: return "ALSA";
case RtMidi::UNIX_JACK: return "JACK";
case RtMidi::WINDOWS_MM: return "Windows MIDI";
case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI";
default: return "";
std::string getName() override {
switch (driverId) {
case RtMidi::UNSPECIFIED: return "Unspecified";
case RtMidi::MACOSX_CORE: return "Core MIDI";
case RtMidi::LINUX_ALSA: return "ALSA";
case RtMidi::UNIX_JACK: return "JACK";
case RtMidi::WINDOWS_MM: return "Windows MIDI";
case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI";
default: return "";
}
}
std::vector<int> getInputDeviceIds() override {
// TODO The IDs unfortunately jump around in RtMidi. Is there a way to keep them constant when a MIDI device is added/removed?
int count = rtMidiIn->getPortCount();
std::vector<int> deviceIds;
for (int i = 0; i < count; i++)
deviceIds.push_back(i);
return deviceIds;
}
}

std::vector<int> RtMidiDriver::getInputDeviceIds() {
// TODO The IDs unfortunately jump around in RtMidi. Is there a way to keep them constant when a MIDI device is added/removed?
int count = rtMidiIn->getPortCount();
std::vector<int> deviceIds;
for (int i = 0; i < count; i++)
deviceIds.push_back(i);
return deviceIds;
}
std::string getInputDeviceName(int deviceId) override {
if (deviceId >= 0) {
return rtMidiIn->getPortName(deviceId);
}
return "";
}

std::string RtMidiDriver::getInputDeviceName(int deviceId) {
if (deviceId >= 0) {
return rtMidiIn->getPortName(deviceId);
midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
if (!(0 <= deviceId && deviceId < (int) rtMidiIn->getPortCount()))
return NULL;
RtMidiInputDevice *device = inputDevices[deviceId];
if (!device) {
inputDevices[deviceId] = device = new RtMidiInputDevice(driverId, deviceId);
}

device->subscribe(input);
return device;
}
return "";
}

midi::InputDevice *RtMidiDriver::subscribeInput(int deviceId, midi::Input *input) {
if (!(0 <= deviceId && deviceId < (int) rtMidiIn->getPortCount()))
return NULL;
RtMidiInputDevice *device = devices[deviceId];
if (!device) {
devices[deviceId] = device = new RtMidiInputDevice(driverId, deviceId);
void unsubscribeInput(int deviceId, midi::Input *input) override {
auto it = inputDevices.find(deviceId);
if (it == inputDevices.end())
return;
RtMidiInputDevice *device = it->second;
device->unsubscribe(input);

// Destroy device if nothing is subscribed anymore
if (device->subscribed.empty()) {
inputDevices.erase(it);
delete device;
}
}

device->subscribe(input);
return device;
}
std::vector<int> getOutputDeviceIds() override {
int count = rtMidiOut->getPortCount();
std::vector<int> deviceIds;
for (int i = 0; i < count; i++)
deviceIds.push_back(i);
return deviceIds;
}

std::string getOutputDeviceName(int deviceId) override {
if (deviceId >= 0) {
return rtMidiOut->getPortName(deviceId);
}
return "";
}

void RtMidiDriver::unsubscribeInput(int deviceId, midi::Input *input) {
auto it = devices.find(deviceId);
if (it == devices.end())
return;
RtMidiInputDevice *device = it->second;
device->unsubscribe(input);
midi::OutputDevice *subscribeOutput(int deviceId, midi::Output *output) override {
if (!(0 <= deviceId && deviceId < (int) rtMidiOut->getPortCount()))
return NULL;
RtMidiOutputDevice *device = outputDevices[deviceId];
if (!device) {
outputDevices[deviceId] = device = new RtMidiOutputDevice(driverId, deviceId);
}

// Destroy device if nothing is subscribed anymore
if (device->subscribed.empty()) {
devices.erase(it);
delete device;
device->subscribe(output);
return device;
}
}

void unsubscribeOutput(int deviceId, midi::Output *output) override {
auto it = outputDevices.find(deviceId);
if (it == outputDevices.end())
return;
RtMidiOutputDevice *device = it->second;
device->unsubscribe(output);

// Destroy device if nothing is subscribed anymore
if (device->subscribed.empty()) {
outputDevices.erase(it);
delete device;
}
}
};


void rtmidiInit() {


Loading…
Cancel
Save