Browse Source

Update midi API to behave similarly to audio API.

tags/v2.0.0
Andrew Belt 5 years ago
parent
commit
dccdacf3bc
11 changed files with 237 additions and 181 deletions
  1. +4
    -1
      include/audio.hpp
  2. +56
    -14
      include/midi.hpp
  3. +1
    -1
      src/app/AudioWidget.cpp
  4. +10
    -10
      src/app/MidiWidget.cpp
  5. +6
    -1
      src/audio.cpp
  6. +1
    -0
      src/core/CV_CC.cpp
  7. +2
    -1
      src/core/CV_Gate.cpp
  8. +1
    -1
      src/core/CV_MIDI.cpp
  9. +81
    -70
      src/keyboard.cpp
  10. +63
    -82
      src/midi.cpp
  11. +12
    -0
      src/rtmidi.cpp

+ 4
- 1
include/audio.hpp View File

@@ -16,8 +16,8 @@ namespace audio {
// Driver // Driver
//////////////////// ////////////////////


struct Port;
struct Device; struct Device;
struct Port;


struct Driver { struct Driver {
virtual ~Driver() {} virtual ~Driver() {}
@@ -95,7 +95,9 @@ struct Device {
//////////////////// ////////////////////


struct Port { struct Port {
/** The first channel index of the device to process. */
int offset = 0; int offset = 0;
/** Maximum number of channels to process. */
int maxChannels = 8; int maxChannels = 8;


// private // private
@@ -107,6 +109,7 @@ struct Port {


Port(); Port();
virtual ~Port(); virtual ~Port();
void reset();


Driver* getDriver() { Driver* getDriver() {
return driver; return driver;


+ 56
- 14
include/midi.hpp View File

@@ -18,6 +18,9 @@ struct Message {
uint8_t size = 3; uint8_t size = 3;
uint8_t bytes[3] = {}; uint8_t bytes[3] = {};


uint8_t getSize() {
return size;
}
void setSize(uint8_t size) { void setSize(uint8_t size) {
assert(size <= 3); assert(size <= 3);
this->size = size; this->size = size;
@@ -91,6 +94,9 @@ struct Driver {


struct Device { struct Device {
virtual ~Device() {} virtual ~Device() {}
virtual std::string getName() {
return "";
}
}; };


struct InputDevice : Device { struct InputDevice : Device {
@@ -112,31 +118,47 @@ struct OutputDevice : Device {
//////////////////// ////////////////////


struct Port { struct Port {
int driverId = -1;
int deviceId = -1;
/* For MIDI output, the channel to output messages. /* For MIDI output, the channel to output messages.
For MIDI input, the channel to filter. For MIDI input, the channel to filter.
Set to -1 to allow all MIDI channels (for input). Set to -1 to allow all MIDI channels (for input).
Zero indexed. Zero indexed.
*/ */
int channel = -1; int channel = -1;

// private
int driverId = -1;
int deviceId = -1;
/** Not owned */ /** Not owned */
Driver* driver = NULL; Driver* driver = NULL;
Device* device = NULL;


/** Remember to call setDriverId(-1) in subclass destructors. */
virtual ~Port() {}
Port();
virtual ~Port();


std::vector<int> getDriverIds();
std::string getDriverName(int driverId);
Driver* getDriver() {
return driver;
}
int getDriverId() {
return driverId;
}
void setDriverId(int driverId); void setDriverId(int driverId);


Device* getDevice() {
return device;
}
virtual std::vector<int> getDeviceIds() = 0; virtual std::vector<int> getDeviceIds() = 0;
virtual std::string getDeviceName(int deviceId) = 0;
int getDeviceId() {
return deviceId;
}
virtual void setDeviceId(int deviceId) = 0; virtual void setDeviceId(int deviceId) = 0;
virtual std::string getDeviceName(int deviceId) = 0;


virtual std::vector<int> getChannels() = 0; virtual std::vector<int> getChannels() = 0;
std::string getChannelName(int channel);
int getChannel() {
return channel;
}
void setChannel(int channel); void setChannel(int channel);
std::string getChannelName(int channel);


json_t* toJson(); json_t* toJson();
void fromJson(json_t* rootJ); void fromJson(json_t* rootJ);
@@ -149,11 +171,20 @@ struct Input : Port {


Input(); Input();
~Input(); ~Input();

void reset(); void reset();
std::vector<int> getDeviceIds() override;
std::string getDeviceName(int deviceId) override;

std::vector<int> getDeviceIds() override {
if (driver)
return driver->getInputDeviceIds();
return {};
}
void setDeviceId(int deviceId) override; void setDeviceId(int deviceId) override;
std::string getDeviceName(int deviceId) override {
if (driver)
return driver->getInputDeviceName(deviceId);
return "";
}

std::vector<int> getChannels() override; std::vector<int> getChannels() override;


virtual void onMessage(Message message) {} virtual void onMessage(Message message) {}
@@ -175,11 +206,20 @@ struct Output : Port {


Output(); Output();
~Output(); ~Output();

void reset(); void reset();
std::vector<int> getDeviceIds() override;
std::string getDeviceName(int deviceId) override;

std::vector<int> getDeviceIds() override {
if (driver)
return driver->getOutputDeviceIds();
return {};
}
void setDeviceId(int deviceId) override; void setDeviceId(int deviceId) override;
std::string getDeviceName(int deviceId) override {
if (driver)
return driver->getInputDeviceName(deviceId);
return "";
}

std::vector<int> getChannels() override; std::vector<int> getChannels() override;


void sendMessage(Message message); void sendMessage(Message message);
@@ -190,6 +230,8 @@ void init();
void destroy(); void destroy();
/** Registers a new MIDI driver. Takes pointer ownership. */ /** Registers a new MIDI driver. Takes pointer ownership. */
void addDriver(int driverId, Driver* driver); void addDriver(int driverId, Driver* driver);
std::vector<int> getDriverIds();
Driver* getDriver(int driverId);




} // namespace midi } // namespace midi


+ 1
- 1
src/app/AudioWidget.cpp View File

@@ -80,7 +80,7 @@ static void appendAudioDeviceMenu(ui::Menu* menu, audio::Port* port) {
item->port = port; item->port = port;
item->deviceId = -1; item->deviceId = -1;
item->text = "(No device)"; item->text = "(No device)";
item->rightText = CHECKMARK(port->getDeviceId() == -1);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId());
menu->addChild(item); menu->addChild(item);
} }




+ 10
- 10
src/app/MidiWidget.cpp View File

@@ -18,12 +18,12 @@ static void appendMidiDriverMenu(ui::Menu* menu, midi::Port* port) {
if (!port) if (!port)
return; return;


for (int driverId : port->getDriverIds()) {
for (int driverId : midi::getDriverIds()) {
MidiDriverValueItem* item = new MidiDriverValueItem; MidiDriverValueItem* item = new MidiDriverValueItem;
item->port = port; item->port = port;
item->driverId = driverId; item->driverId = driverId;
item->text = port->getDriverName(driverId);
item->rightText = CHECKMARK(item->driverId == port->driverId);
item->text = midi::getDriver(driverId)->getName();
item->rightText = CHECKMARK(item->driverId == port->getDriverId());
menu->addChild(item); menu->addChild(item);
} }
} }
@@ -36,7 +36,7 @@ struct MidiDriverChoice : LedDisplayChoice {
appendMidiDriverMenu(menu, port); appendMidiDriverMenu(menu, port);
} }
void step() override { void step() override {
text = port ? port->getDriverName(port->driverId) : "";
text = (port && port->driver) ? port->getDriver()->getName() : "";
if (text.empty()) { if (text.empty()) {
text = "(No driver)"; text = "(No driver)";
color.a = 0.5f; color.a = 0.5f;
@@ -74,7 +74,7 @@ static void appendMidiDeviceMenu(ui::Menu* menu, midi::Port* port) {
item->port = port; item->port = port;
item->deviceId = -1; item->deviceId = -1;
item->text = "(No device)"; item->text = "(No device)";
item->rightText = CHECKMARK(item->deviceId == port->deviceId);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId());
menu->addChild(item); menu->addChild(item);
} }


@@ -83,7 +83,7 @@ static void appendMidiDeviceMenu(ui::Menu* menu, midi::Port* port) {
item->port = port; item->port = port;
item->deviceId = deviceId; item->deviceId = deviceId;
item->text = port->getDeviceName(deviceId); item->text = port->getDeviceName(deviceId);
item->rightText = CHECKMARK(item->deviceId == port->deviceId);
item->rightText = CHECKMARK(item->deviceId == port->getDeviceId());
menu->addChild(item); menu->addChild(item);
} }
} }
@@ -96,7 +96,7 @@ struct MidiDeviceChoice : LedDisplayChoice {
appendMidiDeviceMenu(menu, port); appendMidiDeviceMenu(menu, port);
} }
void step() override { void step() override {
text = port ? port->getDeviceName(port->deviceId) : "";
text = (port && port->device) ? port->getDevice()->getName() : "";
if (text.empty()) { if (text.empty()) {
text = "(No device)"; text = "(No device)";
color.a = 0.5f; color.a = 0.5f;
@@ -121,7 +121,7 @@ struct MidiChannelValueItem : ui::MenuItem {
midi::Port* port; midi::Port* port;
int channel; int channel;
void onAction(const event::Action& e) override { void onAction(const event::Action& e) override {
port->channel = channel;
port->setChannel(channel);
} }
}; };


@@ -134,7 +134,7 @@ static void appendMidiChannelMenu(ui::Menu* menu, midi::Port* port) {
item->port = port; item->port = port;
item->channel = channel; item->channel = channel;
item->text = port->getChannelName(channel); item->text = port->getChannelName(channel);
item->rightText = CHECKMARK(item->channel == port->channel);
item->rightText = CHECKMARK(item->channel == port->getChannel());
menu->addChild(item); menu->addChild(item);
} }
} }
@@ -147,7 +147,7 @@ struct MidiChannelChoice : LedDisplayChoice {
appendMidiChannelMenu(menu, port); appendMidiChannelMenu(menu, port);
} }
void step() override { void step() override {
text = port ? port->getChannelName(port->channel) : "Channel 1";
text = port ? port->getChannelName(port->getChannel()) : "Channel 1";
} }
}; };




+ 6
- 1
src/audio.cpp View File

@@ -81,13 +81,18 @@ void Device::onCloseStream() {
//////////////////// ////////////////////


Port::Port() { Port::Port() {
setDriverId(-1);
reset();
} }


Port::~Port() { Port::~Port() {
setDriverId(-1); setDriverId(-1);
} }


void Port::reset() {
setDriverId(-1);
offset = 0;
}

void Port::setDriverId(int driverId) { void Port::setDriverId(int driverId) {
// Unset device and driver // Unset device and driver
setDeviceId(-1); setDeviceId(-1);


+ 1
- 0
src/core/CV_CC.cpp View File

@@ -16,6 +16,7 @@ struct CCMidiOutput : midi::Output {
for (int n = 0; n < 128; n++) { for (int n = 0; n < 128; n++) {
lastValues[n] = -1; lastValues[n] = -1;
} }
Output::reset();
} }


void setValue(int value, int cc) { void setValue(int value, int cc) {


+ 2
- 1
src/core/CV_Gate.cpp View File

@@ -18,10 +18,10 @@ struct GateMidiOutput : midi::Output {
vels[note] = 100; vels[note] = 100;
lastGates[note] = false; lastGates[note] = false;
} }
Output::reset();
} }


void panic() { void panic() {
reset();
// Send all note off commands // Send all note off commands
for (int note = 0; note < 128; note++) { for (int note = 0; note < 128; note++) {
// Note off // Note off
@@ -30,6 +30,7 @@ struct GateMidiOutput : midi::Output {
m.setNote(note); m.setNote(note);
m.setValue(0); m.setValue(0);
sendMessage(m); sendMessage(m);
lastGates[note] = false;
} }
} }




+ 1
- 1
src/core/CV_MIDI.cpp View File

@@ -7,7 +7,7 @@ namespace core {


struct MidiOutput : dsp::MidiGenerator<PORT_MAX_CHANNELS>, midi::Output { struct MidiOutput : dsp::MidiGenerator<PORT_MAX_CHANNELS>, midi::Output {
void onMessage(midi::Message message) override { void onMessage(midi::Message message) override {
midi::Output::sendMessage(message);
Output::sendMessage(message);
} }


void reset() { void reset() {


+ 81
- 70
src/keyboard.cpp View File

@@ -19,73 +19,84 @@ enum {
CMD_OCTAVE_UP = -2, CMD_OCTAVE_UP = -2,
}; };


struct DeviceInfo {
std::string name;
std::map<int, int> keyMap;
};

static const int deviceCount = 2; static const int deviceCount = 2;


static const std::vector<std::map<int, int>> deviceKeyNote = {
static const std::vector<DeviceInfo> deviceInfos = {
{ {
{GLFW_KEY_GRAVE_ACCENT, CMD_OCTAVE_DOWN},
{GLFW_KEY_1, CMD_OCTAVE_UP},

{GLFW_KEY_Z, 0},
{GLFW_KEY_S, 1},
{GLFW_KEY_X, 2},
{GLFW_KEY_D, 3},
{GLFW_KEY_C, 4},
{GLFW_KEY_V, 5},
{GLFW_KEY_G, 6},
{GLFW_KEY_B, 7},
{GLFW_KEY_H, 8},
{GLFW_KEY_N, 9},
{GLFW_KEY_J, 10},
{GLFW_KEY_M, 11},
{GLFW_KEY_COMMA, 12},
{GLFW_KEY_L, 13},
{GLFW_KEY_PERIOD, 14},
{GLFW_KEY_SEMICOLON, 15},
{GLFW_KEY_SLASH, 16},

{GLFW_KEY_Q, 12},
{GLFW_KEY_2, 13},
{GLFW_KEY_W, 14},
{GLFW_KEY_3, 15},
{GLFW_KEY_E, 16},
{GLFW_KEY_R, 17},
{GLFW_KEY_5, 18},
{GLFW_KEY_T, 19},
{GLFW_KEY_6, 20},
{GLFW_KEY_Y, 21},
{GLFW_KEY_7, 22},
{GLFW_KEY_U, 23},
{GLFW_KEY_I, 24},
{GLFW_KEY_9, 25},
{GLFW_KEY_O, 26},
{GLFW_KEY_0, 27},
{GLFW_KEY_P, 28},
{GLFW_KEY_LEFT_BRACKET, 29},
{GLFW_KEY_EQUAL, 30},
{GLFW_KEY_RIGHT_BRACKET, 31},
"QWERTY keyboard (US)",
{
{GLFW_KEY_GRAVE_ACCENT, CMD_OCTAVE_DOWN},
{GLFW_KEY_1, CMD_OCTAVE_UP},

{GLFW_KEY_Z, 0},
{GLFW_KEY_S, 1},
{GLFW_KEY_X, 2},
{GLFW_KEY_D, 3},
{GLFW_KEY_C, 4},
{GLFW_KEY_V, 5},
{GLFW_KEY_G, 6},
{GLFW_KEY_B, 7},
{GLFW_KEY_H, 8},
{GLFW_KEY_N, 9},
{GLFW_KEY_J, 10},
{GLFW_KEY_M, 11},
{GLFW_KEY_COMMA, 12},
{GLFW_KEY_L, 13},
{GLFW_KEY_PERIOD, 14},
{GLFW_KEY_SEMICOLON, 15},
{GLFW_KEY_SLASH, 16},

{GLFW_KEY_Q, 12},
{GLFW_KEY_2, 13},
{GLFW_KEY_W, 14},
{GLFW_KEY_3, 15},
{GLFW_KEY_E, 16},
{GLFW_KEY_R, 17},
{GLFW_KEY_5, 18},
{GLFW_KEY_T, 19},
{GLFW_KEY_6, 20},
{GLFW_KEY_Y, 21},
{GLFW_KEY_7, 22},
{GLFW_KEY_U, 23},
{GLFW_KEY_I, 24},
{GLFW_KEY_9, 25},
{GLFW_KEY_O, 26},
{GLFW_KEY_0, 27},
{GLFW_KEY_P, 28},
{GLFW_KEY_LEFT_BRACKET, 29},
{GLFW_KEY_EQUAL, 30},
{GLFW_KEY_RIGHT_BRACKET, 31},
},
}, },
{ {
{GLFW_KEY_KP_DIVIDE, CMD_OCTAVE_DOWN},
{GLFW_KEY_KP_MULTIPLY, CMD_OCTAVE_UP},

{GLFW_KEY_KP_0, 0},
{GLFW_KEY_KP_DECIMAL, 2},
{GLFW_KEY_KP_ENTER, 3},

{GLFW_KEY_KP_1, 4},
{GLFW_KEY_KP_2, 5},
{GLFW_KEY_KP_3, 6},

{GLFW_KEY_KP_4, 8},
{GLFW_KEY_KP_5, 9},
{GLFW_KEY_KP_6, 10},
{GLFW_KEY_KP_ADD, 11},

{GLFW_KEY_KP_7, 12},
{GLFW_KEY_KP_8, 13},
{GLFW_KEY_KP_9, 14},
},
"Numpad keyboard (US)",
{
{GLFW_KEY_KP_DIVIDE, CMD_OCTAVE_DOWN},
{GLFW_KEY_KP_MULTIPLY, CMD_OCTAVE_UP},

{GLFW_KEY_KP_0, 0},
{GLFW_KEY_KP_DECIMAL, 2},
{GLFW_KEY_KP_ENTER, 3},

{GLFW_KEY_KP_1, 4},
{GLFW_KEY_KP_2, 5},
{GLFW_KEY_KP_3, 6},

{GLFW_KEY_KP_4, 8},
{GLFW_KEY_KP_5, 9},
{GLFW_KEY_KP_6, 10},
{GLFW_KEY_KP_ADD, 11},

{GLFW_KEY_KP_7, 12},
{GLFW_KEY_KP_8, 13},
{GLFW_KEY_KP_9, 14},
},
}
}; };




@@ -94,13 +105,17 @@ struct InputDevice : midi::InputDevice {
int octave = 5; int octave = 5;
std::map<int, int> pressedNotes; std::map<int, int> pressedNotes;


std::string getName() override {
return deviceInfos[deviceId].name;
}

void onKeyPress(int key) { void onKeyPress(int key) {
// Do nothing if no ports are subscribed // Do nothing if no ports are subscribed
if (subscribed.empty()) if (subscribed.empty())
return; return;
auto keyNote = deviceKeyNote[deviceId];
auto it = keyNote.find(key);
if (it == keyNote.end())
auto keyMap = deviceInfos[deviceId].keyMap;
auto it = keyMap.find(key);
if (it == keyMap.end())
return; return;
int note = it->second; int note = it->second;


@@ -171,11 +186,7 @@ struct Driver : midi::Driver {
} }


std::string getInputDeviceName(int deviceId) override { std::string getInputDeviceName(int deviceId) override {
if (deviceId == 0)
return "QWERTY keyboard (US)";
else if (deviceId == 1)
return "Numpad keyboard (US)";
return "";
return deviceInfos[deviceId].name;
} }


midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override { midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override {


+ 63
- 82
src/midi.cpp View File

@@ -10,7 +10,6 @@ namespace midi {


static std::vector<std::pair<int, Driver*>> drivers; static std::vector<std::pair<int, Driver*>> drivers;



//////////////////// ////////////////////
// Device // Device
//////////////////// ////////////////////
@@ -49,21 +48,10 @@ void OutputDevice::unsubscribe(Output* output) {
// Port // Port
//////////////////// ////////////////////


std::vector<int> Port::getDriverIds() {
std::vector<int> driverIds;
for (auto& pair : drivers) {
driverIds.push_back(pair.first);
}
return driverIds;
Port::Port() {
} }


std::string Port::getDriverName(int driverId) {
for (auto& pair : drivers) {
if (pair.first == driverId) {
return pair.second->getName();
}
}
return "";
Port::~Port() {
} }


void Port::setDriverId(int driverId) { void Port::setDriverId(int driverId) {
@@ -72,50 +60,60 @@ void Port::setDriverId(int driverId) {
driver = NULL; driver = NULL;
this->driverId = -1; this->driverId = -1;


// Set driver
for (auto& pair : drivers) {
if (pair.first == driverId) {
driver = pair.second;
this->driverId = driverId;
break;
}
// Find driver by ID
driver = midi::getDriver(driverId);
if (driver) {
this->driverId = driverId;
} }
else {
// Set first driver as default
driver = drivers[0].second;
this->driverId = drivers[0].first;
}
}

void Port::setChannel(int channel) {
this->channel = channel;
} }


std::string Port::getChannelName(int channel) { std::string Port::getChannelName(int channel) {
if (channel == -1)
if (channel < 0)
return "All channels"; return "All channels";
else else
return string::f("Channel %d", channel + 1); return string::f("Channel %d", channel + 1);
} }


void Port::setChannel(int channel) {
this->channel = channel;
}

json_t* Port::toJson() { json_t* Port::toJson() {
json_t* rootJ = json_object(); json_t* rootJ = json_object();
json_object_set_new(rootJ, "driver", json_integer(driverId));
std::string deviceName = getDeviceName(deviceId);
if (!deviceName.empty())
json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
json_object_set_new(rootJ, "channel", json_integer(channel));
json_object_set_new(rootJ, "driver", json_integer(getDriverId()));

if (device) {
std::string deviceName = device->getName();
if (!deviceName.empty())
json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
}

json_object_set_new(rootJ, "channel", json_integer(getChannel()));
return rootJ; return rootJ;
} }


void Port::fromJson(json_t* rootJ) { void Port::fromJson(json_t* rootJ) {
setDriverId(-1);

json_t* driverJ = json_object_get(rootJ, "driver"); json_t* driverJ = json_object_get(rootJ, "driver");
if (driverJ) if (driverJ)
setDriverId(json_integer_value(driverJ)); setDriverId(json_integer_value(driverJ));


json_t* deviceNameJ = json_object_get(rootJ, "deviceName");
if (deviceNameJ) {
std::string deviceName = json_string_value(deviceNameJ);
// Search for device with equal name
for (int deviceId : getDeviceIds()) {
if (getDeviceName(deviceId) == deviceName) {
setDeviceId(deviceId);
break;
if (driver) {
json_t* deviceNameJ = json_object_get(rootJ, "deviceName");
if (deviceNameJ) {
std::string deviceName = json_string_value(deviceNameJ);
// Search for device ID with equal name
for (int deviceId : getDeviceIds()) {
if (getDeviceName(deviceId) == deviceName) {
setDeviceId(deviceId);
break;
}
} }
} }
} }
@@ -138,25 +136,8 @@ Input::~Input() {
} }


void Input::reset() { void Input::reset() {
setDriverId(-1);
channel = -1; channel = -1;
// Set first driver as default
if (drivers.size() >= 1) {
setDriverId(drivers[0].first);
}
}

std::vector<int> Input::getDeviceIds() {
if (driver) {
return driver->getInputDeviceIds();
}
return {};
}

std::string Input::getDeviceName(int deviceId) {
if (driver) {
return driver->getInputDeviceName(deviceId);
}
return "";
} }


void Input::setDeviceId(int deviceId) { void Input::setDeviceId(int deviceId) {
@@ -164,12 +145,12 @@ void Input::setDeviceId(int deviceId) {
if (driver && this->deviceId >= 0) { if (driver && this->deviceId >= 0) {
driver->unsubscribeInput(this->deviceId, this); driver->unsubscribeInput(this->deviceId, this);
} }
inputDevice = NULL;
device = inputDevice = NULL;
this->deviceId = -1; this->deviceId = -1;


// Create device // Create device
if (driver && deviceId >= 0) { if (driver && deviceId >= 0) {
inputDevice = driver->subscribeInput(deviceId, this);
device = inputDevice = driver->subscribeInput(deviceId, this);
this->deviceId = deviceId; this->deviceId = deviceId;
} }
} }
@@ -212,25 +193,8 @@ Output::~Output() {
} }


void Output::reset() { void Output::reset() {
setDriverId(-1);
channel = 0; channel = 0;
// Set first driver as default
if (drivers.size() >= 1) {
setDriverId(drivers[0].first);
}
}

std::vector<int> Output::getDeviceIds() {
if (driver) {
return driver->getOutputDeviceIds();
}
return {};
}

std::string Output::getDeviceName(int deviceId) {
if (driver) {
return driver->getOutputDeviceName(deviceId);
}
return "";
} }


void Output::setDeviceId(int deviceId) { void Output::setDeviceId(int deviceId) {
@@ -238,12 +202,12 @@ void Output::setDeviceId(int deviceId) {
if (driver && this->deviceId >= 0) { if (driver && this->deviceId >= 0) {
driver->unsubscribeOutput(this->deviceId, this); driver->unsubscribeOutput(this->deviceId, this);
} }
outputDevice = NULL;
device = outputDevice = NULL;
this->deviceId = -1; this->deviceId = -1;


// Create device // Create device
if (driver && deviceId >= 0) { if (driver && deviceId >= 0) {
outputDevice = driver->subscribeOutput(deviceId, this);
device = outputDevice = driver->subscribeOutput(deviceId, this);
this->deviceId = deviceId; this->deviceId = deviceId;
} }
} }
@@ -257,14 +221,15 @@ std::vector<int> Output::getChannels() {
} }


void Output::sendMessage(Message message) { void Output::sendMessage(Message message) {
if (!outputDevice)
return;

// Set channel // Set channel
if (message.getStatus() != 0xf) { if (message.getStatus() != 0xf) {
message.setChannel(channel); message.setChannel(channel);
} }
// DEBUG("sendMessage %02x %02x %02x", message.cmd, message.data1, message.data2); // DEBUG("sendMessage %02x %02x %02x", message.cmd, message.data1, message.data2);
if (outputDevice) {
outputDevice->sendMessage(message);
}
outputDevice->sendMessage(message);
} }




@@ -287,6 +252,22 @@ void addDriver(int driverId, Driver* driver) {
drivers.push_back(std::make_pair(driverId, driver)); drivers.push_back(std::make_pair(driverId, driver));
} }


std::vector<int> getDriverIds() {
std::vector<int> driverIds;
for (auto& pair : drivers) {
driverIds.push_back(pair.first);
}
return driverIds;
}

Driver* getDriver(int driverId) {
for (auto& pair : drivers) {
if (pair.first == driverId)
return pair.second;
}
return NULL;
}



} // namespace midi } // namespace midi
} // namespace rack } // namespace rack

+ 12
- 0
src/rtmidi.cpp View File

@@ -15,12 +15,14 @@ namespace rack {


struct RtMidiInputDevice : midi::InputDevice { struct RtMidiInputDevice : midi::InputDevice {
RtMidiIn* rtMidiIn; RtMidiIn* rtMidiIn;
std::string name;


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


@@ -29,6 +31,10 @@ struct RtMidiInputDevice : midi::InputDevice {
delete rtMidiIn; delete rtMidiIn;
} }


std::string getName() override {
return name;
}

static void midiInputCallback(double timeStamp, std::vector<unsigned char>* message, void* userData) { static void midiInputCallback(double timeStamp, std::vector<unsigned char>* message, void* userData) {
if (!message) if (!message)
return; return;
@@ -55,10 +61,12 @@ struct RtMidiInputDevice : midi::InputDevice {


struct RtMidiOutputDevice : midi::OutputDevice { struct RtMidiOutputDevice : midi::OutputDevice {
RtMidiOut* rtMidiOut; RtMidiOut* rtMidiOut;
std::string name;


RtMidiOutputDevice(int driverId, int deviceId) { RtMidiOutputDevice(int driverId, int deviceId) {
rtMidiOut = new RtMidiOut((RtMidi::Api) driverId, "VCV Rack"); rtMidiOut = new RtMidiOut((RtMidi::Api) driverId, "VCV Rack");
assert(rtMidiOut); assert(rtMidiOut);
name = rtMidiOut->getPortName(deviceId);
rtMidiOut->openPort(deviceId, "VCV Rack output"); rtMidiOut->openPort(deviceId, "VCV Rack output");
} }


@@ -67,6 +75,10 @@ struct RtMidiOutputDevice : midi::OutputDevice {
delete rtMidiOut; delete rtMidiOut;
} }


std::string getName() override {
return name;
}

void sendMessage(midi::Message message) override { void sendMessage(midi::Message message) override {
rtMidiOut->sendMessage(message.bytes, message.size); rtMidiOut->sendMessage(message.bytes, message.size);
} }


Loading…
Cancel
Save