@@ -7,12 +7,26 @@ | |||
namespace rack { | |||
struct BridgeMidiInputDevice : MidiInputDevice { | |||
}; | |||
struct BridgeMidiDriver : MidiDriver { | |||
BridgeMidiInputDevice devices[16]; | |||
std::string getName() override {return "Bridge";} | |||
std::vector<int> getInputDeviceIds() override; | |||
std::string getInputDeviceName(int deviceId) override; | |||
MidiInputDevice *subscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
void unsubscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
}; | |||
void bridgeInit(); | |||
void bridgeDestroy(); | |||
void bridgeMidiSubscribe(int channel, MidiInput *midi); | |||
void bridgeMidiUnsubscribe(int channel, MidiInput *midi); | |||
void bridgeAudioSubscribe(int channel, AudioIO *audio); | |||
void bridgeAudioUnsubscribe(int channel, AudioIO *audio); | |||
BridgeMidiDriver *bridgeGetMidiDriver(); | |||
} // namespace rack |
@@ -18,18 +18,20 @@ struct GamepadInputDevice : MidiInputDevice { | |||
}; | |||
struct GamepadInputDriver : MidiInputDriver { | |||
struct GamepadDriver : MidiDriver { | |||
GamepadInputDevice devices[16]; | |||
GamepadInputDriver(); | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
MidiInputDevice *getDevice(int deviceId) override; | |||
GamepadDriver(); | |||
std::string getName() override {return "Gamepad";} | |||
std::vector<int> getInputDeviceIds() override; | |||
std::string getInputDeviceName(int deviceId) override; | |||
MidiInputDevice *subscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
void unsubscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
}; | |||
void gamepadStep(); | |||
MidiInputDriver *gamepadGetInputDriver(); | |||
GamepadDriver *gamepadGetDriver(); | |||
} // namespace rack |
@@ -16,18 +16,20 @@ struct KeyboardInputDevice : MidiInputDevice { | |||
}; | |||
struct KeyboardInputDriver : MidiInputDriver { | |||
struct KeyboardDriver : MidiDriver { | |||
KeyboardInputDevice device; | |||
std::string getName() override {return "Computer keyboard";} | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
MidiInputDevice *getDevice(int deviceId) override; | |||
std::vector<int> getInputDeviceIds() override; | |||
std::string getInputDeviceName(int deviceId) override; | |||
MidiInputDevice *subscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
void unsubscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
}; | |||
void keyboardPress(int key); | |||
void keyboardRelease(int key); | |||
KeyboardInputDriver *keyboardGetInputDriver(); | |||
KeyboardDriver *keyboardGetDriver(); | |||
} // namespace rack |
@@ -30,42 +30,43 @@ struct MidiMessage { | |||
}; | |||
//////////////////// | |||
// MidiIODevice | |||
// MidiDevice | |||
//////////////////// | |||
struct MidiIODevice { | |||
virtual ~MidiIODevice() {} | |||
struct MidiDevice { | |||
virtual ~MidiDevice() {} | |||
}; | |||
struct MidiInput; | |||
struct MidiInputDevice : MidiIODevice { | |||
struct MidiInputDevice : MidiDevice { | |||
std::set<MidiInput*> subscribed; | |||
void subscribe(MidiInput *midiInput); | |||
void unsubscribe(MidiInput *midiInput); | |||
void onMessage(MidiMessage message); | |||
}; | |||
struct MidiOutputDevice : MidiIODevice { | |||
struct MidiOutputDevice : MidiDevice { | |||
// TODO | |||
}; | |||
//////////////////// | |||
// MidiIODriver | |||
// MidiDriver | |||
//////////////////// | |||
struct MidiIODriver { | |||
virtual ~MidiIODriver() {} | |||
virtual std::vector<int> getDeviceIds() = 0; | |||
virtual std::string getDeviceName(int deviceId) = 0; | |||
}; | |||
struct MidiDriver { | |||
virtual ~MidiDriver() {} | |||
virtual std::string getName() {return "";} | |||
struct MidiInputDriver : MidiIODriver { | |||
virtual MidiInputDevice *getDevice(int deviceId) = 0; | |||
}; | |||
virtual std::vector<int> getInputDeviceIds() {return {};} | |||
virtual std::string getInputDeviceName(int deviceId) {return "";} | |||
virtual MidiInputDevice *subscribeInputDevice(int deviceId, MidiInput *midiInput) {return NULL;} | |||
virtual void unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {} | |||
struct MidiOutputDriver : MidiIODriver { | |||
virtual MidiOutputDevice *getDevice(int deviceId) = 0; | |||
// virtual std::vector<int> getOutputDeviceIds() = 0; | |||
// virtual std::string getOutputDeviceName(int deviceId) = 0; | |||
// virtual MidiOutputDevice *subscribeOutputDevice(int deviceId, MidiOutput *midiOutput) = 0; | |||
// virtual void unsubscribeOutputDevice(int deviceId, MidiOutput *midiOutput) = 0; | |||
}; | |||
//////////////////// | |||
@@ -81,12 +82,14 @@ struct MidiIO { | |||
Zero indexed. | |||
*/ | |||
int channel = -1; | |||
/** Not owned */ | |||
MidiDriver *driver = NULL; | |||
virtual ~MidiIO() {} | |||
virtual ~MidiIO(); | |||
std::vector<int> getDriverIds(); | |||
std::string getDriverName(int driverId); | |||
virtual void setDriverId(int driverId) = 0; | |||
void setDriverId(int driverId); | |||
virtual std::vector<int> getDeviceIds() = 0; | |||
virtual std::string getDeviceName(int deviceId) = 0; | |||
@@ -99,26 +102,17 @@ struct MidiIO { | |||
struct MidiInput : MidiIO { | |||
/** Not owned */ | |||
MidiInputDriver *driver = NULL; | |||
/** Not owned, must unsubscribe when destructed */ | |||
MidiInputDevice *device = NULL; | |||
MidiInput(); | |||
~MidiInput(); | |||
void setDriverId(int driverId) override; | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
void setDeviceId(int deviceId) override; | |||
virtual void onMessage(MidiMessage message) {} | |||
}; | |||
struct MidiInputQueue : MidiInput { | |||
int queueSize = 8192; | |||
// TODO Switch to RingBuffer | |||
int queueMaxSize = 8192; | |||
std::queue<MidiMessage> queue; | |||
void onMessage(MidiMessage message) override; | |||
/** If a MidiMessage is available, writes `message` and return true */ | |||
@@ -127,15 +121,13 @@ struct MidiInputQueue : MidiInput { | |||
struct MidiOutput : MidiIO { | |||
/** Not owned */ | |||
MidiOutputDriver *driver = NULL; | |||
/** Not owned, must unsubscribe when destructed */ | |||
MidiOutputDevice *device = NULL; | |||
MidiOutput(); | |||
~MidiOutput(); | |||
void setDriverId(int driverId) override; | |||
void setDeviceId(int deviceId) override; | |||
}; | |||
void midiInit(); | |||
} // namespace rack |
@@ -2,6 +2,7 @@ | |||
#include "util/common.hpp" | |||
#include "midi.hpp" | |||
#include <map> | |||
#pragma GCC diagnostic push | |||
#ifndef __clang__ | |||
@@ -14,30 +15,33 @@ | |||
namespace rack { | |||
struct RtMidiInputDriver : MidiInputDriver { | |||
/** Just for querying MIDI driver information */ | |||
struct RtMidiInputDevice : MidiInputDevice { | |||
RtMidiIn *rtMidiIn; | |||
RtMidiInputDriver(int driverId); | |||
~RtMidiInputDriver(); | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
MidiInputDevice *getDevice(int deviceId) override; | |||
RtMidiInputDevice(int driverId, int deviceId); | |||
~RtMidiInputDevice(); | |||
}; | |||
struct RtMidiInputDevice : MidiInputDevice { | |||
struct RtMidiDriver : MidiDriver { | |||
int driverId; | |||
/** Just for querying MIDI driver information */ | |||
RtMidiIn *rtMidiIn; | |||
/** Cached */ | |||
std::string deviceName; | |||
RtMidiInputDevice(int driverId, int deviceId); | |||
~RtMidiInputDevice(); | |||
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; | |||
MidiInputDevice *subscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
void unsubscribeInputDevice(int deviceId, MidiInput *midiInput) override; | |||
}; | |||
std::vector<int> rtmidiGetDrivers(); | |||
MidiInputDriver *rtmidiGetInputDriver(int driverId); | |||
RtMidiDriver *rtmidiCreateDriver(int driverId); | |||
} // namespace rack |
@@ -23,9 +23,9 @@ namespace rack { | |||
struct BridgeClientConnection; | |||
static BridgeClientConnection *connections[BRIDGE_NUM_PORTS] = {}; | |||
static AudioIO *audioListeners[BRIDGE_NUM_PORTS] = {}; | |||
static MidiInput *midiListeners[BRIDGE_NUM_PORTS] = {}; | |||
static std::thread serverThread; | |||
static bool serverRunning = false; | |||
static BridgeMidiDriver driver; | |||
struct BridgeClientConnection { | |||
@@ -206,9 +206,7 @@ struct BridgeClientConnection { | |||
void processMidi(MidiMessage message) { | |||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||
return; | |||
if (!midiListeners[port]) | |||
return; | |||
midiListeners[port]->onMessage(message); | |||
driver.devices[port].onMessage(message); | |||
} | |||
void setSampleRate(int sampleRate) { | |||
@@ -372,6 +370,35 @@ 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) { | |||
return stringf("Port %d", deviceId + 1); | |||
} | |||
MidiInputDevice *BridgeMidiDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return NULL; | |||
devices[deviceId].subscribe(midiInput); | |||
return &devices[deviceId]; | |||
} | |||
void BridgeMidiDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return; | |||
devices[deviceId].unsubscribe(midiInput); | |||
} | |||
void bridgeInit() { | |||
serverRunning = true; | |||
serverThread = std::thread(serverRun); | |||
@@ -382,23 +409,6 @@ void bridgeDestroy() { | |||
serverThread.join(); | |||
} | |||
void bridgeMidiSubscribe(int port, MidiInput *midi) { | |||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||
return; | |||
// Check if a Midi is already subscribed on the port | |||
if (midiListeners[port]) | |||
return; | |||
midiListeners[port] = midi; | |||
} | |||
void bridgeMidiUnsubscribe(int port, MidiInput *midi) { | |||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||
return; | |||
if (midiListeners[port] != midi) | |||
return; | |||
midiListeners[port] = NULL; | |||
} | |||
void bridgeAudioSubscribe(int port, AudioIO *audio) { | |||
if (!(0 <= port && port < BRIDGE_NUM_PORTS)) | |||
return; | |||
@@ -418,5 +428,9 @@ void bridgeAudioUnsubscribe(int port, AudioIO *audio) { | |||
audioListeners[port] = NULL; | |||
} | |||
BridgeMidiDriver *bridgeGetMidiDriver() { | |||
return &driver; | |||
} | |||
} // namespace rack |
@@ -49,13 +49,13 @@ void GamepadInputDevice::step() { | |||
} | |||
GamepadInputDriver::GamepadInputDriver() { | |||
GamepadDriver::GamepadDriver() { | |||
for (int i = 0; i < 16; i++) { | |||
devices[i].deviceId = i; | |||
} | |||
} | |||
std::vector<int> GamepadInputDriver::getDeviceIds() { | |||
std::vector<int> GamepadDriver::getInputDeviceIds() { | |||
std::vector<int> deviceIds; | |||
for (int i = 0; i < 16; i++) { | |||
if (glfwJoystickPresent(i)) { | |||
@@ -65,7 +65,7 @@ std::vector<int> GamepadInputDriver::getDeviceIds() { | |||
return deviceIds; | |||
} | |||
std::string GamepadInputDriver::getDeviceName(int deviceId) { | |||
std::string GamepadDriver::getInputDeviceName(int deviceId) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return ""; | |||
@@ -76,34 +76,35 @@ std::string GamepadInputDriver::getDeviceName(int deviceId) { | |||
return stringf("Gamepad %d (unavailable)", deviceId + 1); | |||
} | |||
MidiInputDevice *GamepadInputDriver::getDevice(int deviceId) { | |||
MidiInputDevice *GamepadDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return NULL; | |||
devices[deviceId].subscribe(midiInput); | |||
return &devices[deviceId]; | |||
} | |||
void GamepadDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return; | |||
static GamepadInputDriver *driver = NULL; | |||
devices[deviceId].unsubscribe(midiInput); | |||
} | |||
void gamepadStep() { | |||
// Check if the driver has been instantiated | |||
if (!driver) | |||
return; | |||
static GamepadDriver driver; | |||
void gamepadStep() { | |||
for (int i = 0; i < 16; i++) { | |||
if (glfwJoystickPresent(i)) { | |||
driver->devices[i].step(); | |||
driver.devices[i].step(); | |||
} | |||
} | |||
} | |||
MidiInputDriver *gamepadGetInputDriver() { | |||
if (!driver) { | |||
driver = new GamepadInputDriver(); | |||
} | |||
return driver; | |||
GamepadDriver *gamepadGetDriver() { | |||
return &driver; | |||
} | |||
@@ -74,41 +74,44 @@ void KeyboardInputDevice::processKey(int key, bool released) { | |||
} | |||
std::vector<int> KeyboardInputDriver::getDeviceIds() { | |||
std::vector<int> KeyboardDriver::getInputDeviceIds() { | |||
return {0}; | |||
} | |||
std::string KeyboardInputDriver::getDeviceName(int deviceId) { | |||
std::string KeyboardDriver::getInputDeviceName(int deviceId) { | |||
if (deviceId == 0) | |||
return "QWERTY keyboard (US)"; | |||
return ""; | |||
} | |||
MidiInputDevice *KeyboardInputDriver::getDevice(int deviceId) { | |||
MidiInputDevice *KeyboardDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
if (deviceId != 0) | |||
return NULL; | |||
device.subscribe(midiInput); | |||
return &device; | |||
} | |||
void KeyboardDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
if (deviceId != 0) | |||
return; | |||
device.unsubscribe(midiInput); | |||
} | |||
static KeyboardInputDriver *driver = NULL; | |||
static KeyboardDriver driver; | |||
void keyboardPress(int key) { | |||
if (!driver) | |||
return; | |||
driver->device.processKey(key, false); | |||
driver.device.processKey(key, false); | |||
} | |||
void keyboardRelease(int key) { | |||
if (!driver) | |||
return; | |||
driver->device.processKey(key, true); | |||
driver.device.processKey(key, true); | |||
} | |||
KeyboardInputDriver *keyboardGetInputDriver() { | |||
// Lazily create driver | |||
if (!driver) { | |||
driver = new KeyboardInputDriver(); | |||
} | |||
return driver; | |||
KeyboardDriver *keyboardGetDriver() { | |||
return &driver; | |||
} | |||
@@ -6,6 +6,7 @@ | |||
#include "settings.hpp" | |||
#include "asset.hpp" | |||
#include "bridge.hpp" | |||
#include "midi.hpp" | |||
#include "osdialog.h" | |||
#include <unistd.h> | |||
@@ -36,6 +37,7 @@ int main(int argc, char* argv[]) { | |||
pluginInit(); | |||
engineInit(); | |||
midiInit(); | |||
bridgeInit(); | |||
windowInit(); | |||
appInit(); | |||
@@ -8,8 +8,11 @@ | |||
namespace rack { | |||
static std::map<int, MidiDriver*> drivers; | |||
//////////////////// | |||
// MidiIODevice | |||
// MidiDevice | |||
//////////////////// | |||
void MidiInputDevice::subscribe(MidiInput *midiInput) { | |||
@@ -17,13 +20,10 @@ void MidiInputDevice::subscribe(MidiInput *midiInput) { | |||
} | |||
void MidiInputDevice::unsubscribe(MidiInput *midiInput) { | |||
// Remove MidiInput from subscriptions | |||
auto it = subscribed.find(midiInput); | |||
if (it != subscribed.end()) | |||
subscribed.erase(it); | |||
if (subscribed.size() == 0) { | |||
warn("TODO: Fix memory leak"); | |||
} | |||
} | |||
void MidiInputDevice::onMessage(MidiMessage message) { | |||
@@ -33,7 +33,7 @@ void MidiInputDevice::onMessage(MidiMessage message) { | |||
} | |||
//////////////////// | |||
// MidiIODriver | |||
// MidiDriver | |||
//////////////////// | |||
@@ -41,28 +41,40 @@ void MidiInputDevice::onMessage(MidiMessage message) { | |||
// MidiIO | |||
//////////////////// | |||
MidiIO::~MidiIO() { | |||
// Because of polymorphic destruction, descendants must call this in their own destructor | |||
// setDriverId(-1); | |||
} | |||
std::vector<int> MidiIO::getDriverIds() { | |||
std::vector<int> driverIds = rtmidiGetDrivers(); | |||
// Add custom driverIds | |||
driverIds.push_back(BRIDGE_DRIVER); | |||
driverIds.push_back(GAMEPAD_DRIVER); | |||
driverIds.push_back(KEYBOARD_DRIVER); | |||
std::vector<int> driverIds; | |||
for (auto pair : drivers) { | |||
driverIds.push_back(pair.first); | |||
} | |||
return driverIds; | |||
} | |||
std::string MidiIO::getDriverName(int driverId) { | |||
switch (driverId) { | |||
case -1: return "None"; | |||
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"; | |||
case BRIDGE_DRIVER: return "Bridge"; | |||
case GAMEPAD_DRIVER: return "Gamepad"; | |||
case KEYBOARD_DRIVER: return "Computer keyboard"; | |||
default: return "Unknown"; | |||
MidiDriver *driver = drivers[driverId]; | |||
if (driver) { | |||
return driver->getName(); | |||
} | |||
return ""; | |||
} | |||
void MidiIO::setDriverId(int driverId) { | |||
// Destroy driver | |||
setDeviceId(-1); | |||
if (driver) { | |||
driver = NULL; | |||
} | |||
this->driverId = -1; | |||
// Set driver | |||
auto it = drivers.find(driverId); | |||
if (it != drivers.end()) { | |||
driver = it->second; | |||
this->driverId = driverId; | |||
} | |||
} | |||
@@ -109,72 +121,34 @@ void MidiIO::fromJson(json_t *rootJ) { | |||
// MidiInput | |||
//////////////////// | |||
MidiInput::MidiInput() { | |||
} | |||
MidiInput::~MidiInput() { | |||
setDriverId(-1); | |||
} | |||
void MidiInput::setDriverId(int driverId) { | |||
// Destroy driver | |||
setDeviceId(-1); | |||
if (driver) { | |||
driver = NULL; | |||
} | |||
this->driverId = -1; | |||
// Create driver | |||
if (driverId >= 0) { | |||
driver = rtmidiGetInputDriver(driverId); | |||
} | |||
else if (driverId == BRIDGE_DRIVER) { | |||
// TODO | |||
} | |||
else if (driverId == GAMEPAD_DRIVER) { | |||
driver = gamepadGetInputDriver(); | |||
} | |||
else if (driverId == KEYBOARD_DRIVER) { | |||
driver = keyboardGetInputDriver(); | |||
} | |||
// Set driverId | |||
if (driver) { | |||
this->driverId = driverId; | |||
} | |||
} | |||
std::vector<int> MidiInput::getDeviceIds() { | |||
if (driver) { | |||
return driver->getDeviceIds(); | |||
return driver->getInputDeviceIds(); | |||
} | |||
return {}; | |||
} | |||
std::string MidiInput::getDeviceName(int deviceId) { | |||
if (driver) { | |||
return driver->getDeviceName(deviceId); | |||
return driver->getInputDeviceName(deviceId); | |||
} | |||
return ""; | |||
} | |||
void MidiInput::setDeviceId(int deviceId) { | |||
// Destroy device | |||
if (device) { | |||
device->unsubscribe(this); | |||
device = NULL; | |||
if (driver && deviceId >= 0) { | |||
driver->unsubscribeInputDevice(deviceId, this); | |||
} | |||
this->deviceId = -1; | |||
// Create device | |||
if (driver && deviceId >= 0) { | |||
device = driver->getDevice(deviceId); | |||
device->subscribe(this); | |||
} | |||
// Set deviceId | |||
if (device) { | |||
driver->subscribeInputDevice(deviceId, this); | |||
this->deviceId = deviceId; | |||
} | |||
} | |||
@@ -187,12 +161,13 @@ void MidiInputQueue::onMessage(MidiMessage message) { | |||
} | |||
// Push to queue | |||
if ((int) queue.size() < queueSize) | |||
if ((int) queue.size() < queueMaxSize) | |||
queue.push(message); | |||
} | |||
bool MidiInputQueue::shift(MidiMessage *message) { | |||
if (!message) return false; | |||
if (!message) | |||
return false; | |||
if (!queue.empty()) { | |||
*message = queue.front(); | |||
queue.pop(); | |||
@@ -201,7 +176,6 @@ bool MidiInputQueue::shift(MidiMessage *message) { | |||
return false; | |||
} | |||
//////////////////// | |||
// MidiOutput | |||
//////////////////// | |||
@@ -210,15 +184,24 @@ MidiOutput::MidiOutput() { | |||
} | |||
MidiOutput::~MidiOutput() { | |||
// TODO | |||
setDriverId(-1); | |||
} | |||
void MidiOutput::setDriverId(int driverId) { | |||
void MidiOutput::setDeviceId(int deviceId) { | |||
// TODO | |||
} | |||
void MidiOutput::setDeviceId(int deviceId) { | |||
// TODO | |||
//////////////////// | |||
// midi | |||
//////////////////// | |||
void midiInit() { | |||
for (int driverId : rtmidiGetDrivers()) { | |||
drivers[driverId] = rtmidiCreateDriver(driverId); | |||
} | |||
// drivers[BRIDGE_DRIVER] = bridgeCreateDriver(); | |||
drivers[GAMEPAD_DRIVER] = gamepadGetDriver(); | |||
drivers[KEYBOARD_DRIVER] = keyboardGetDriver(); | |||
} | |||
@@ -5,36 +5,6 @@ | |||
namespace rack { | |||
RtMidiInputDriver::RtMidiInputDriver(int driverId) { | |||
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId); | |||
assert(rtMidiIn); | |||
} | |||
RtMidiInputDriver::~RtMidiInputDriver() { | |||
delete rtMidiIn; | |||
} | |||
std::vector<int> RtMidiInputDriver::getDeviceIds() { | |||
int count = rtMidiIn->getPortCount();; | |||
std::vector<int> deviceIds; | |||
for (int i = 0; i < count; i++) | |||
deviceIds.push_back(i); | |||
return deviceIds; | |||
} | |||
std::string RtMidiInputDriver::getDeviceName(int deviceId) { | |||
if (deviceId >= 0) { | |||
return rtMidiIn->getPortName(deviceId); | |||
} | |||
return ""; | |||
} | |||
MidiInputDevice *RtMidiInputDriver::getDevice(int deviceId) { | |||
// TODO Get from cache | |||
return new RtMidiInputDevice(rtMidiIn->getCurrentApi(), deviceId); | |||
} | |||
static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) { | |||
if (!message) return; | |||
if (!userData) return; | |||
@@ -54,6 +24,7 @@ static void midiInputCallback(double timeStamp, std::vector<unsigned char> *mess | |||
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); | |||
} | |||
@@ -64,6 +35,72 @@ RtMidiInputDevice::~RtMidiInputDevice() { | |||
} | |||
RtMidiDriver::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; | |||
} | |||
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::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 RtMidiDriver::getInputDeviceName(int deviceId) { | |||
if (deviceId >= 0) { | |||
return rtMidiIn->getPortName(deviceId); | |||
} | |||
return ""; | |||
} | |||
MidiInputDevice *RtMidiDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
RtMidiInputDevice *device = devices[deviceId]; | |||
if (!device) { | |||
devices[deviceId] = device = new RtMidiInputDevice(driverId, deviceId); | |||
} | |||
device->subscribe(midiInput); | |||
return device; | |||
} | |||
void RtMidiDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) { | |||
RtMidiInputDevice *device = devices[deviceId]; | |||
assert(device); | |||
device->unsubscribe(midiInput); | |||
// Destroy device if nothing else is subscribed | |||
if (device->subscribed.empty()) { | |||
auto it = devices.find(deviceId); | |||
assert(it != devices.end()); | |||
devices.erase(it); | |||
delete device; | |||
} | |||
} | |||
std::vector<int> rtmidiGetDrivers() { | |||
std::vector<RtMidi::Api> rtApis; | |||
RtMidi::getCompiledApi(rtApis); | |||
@@ -75,15 +112,8 @@ std::vector<int> rtmidiGetDrivers() { | |||
return drivers; | |||
} | |||
static std::map<int, RtMidiInputDriver*> rtmidiInputDrivers; | |||
MidiInputDriver *rtmidiGetInputDriver(int driverId) { | |||
// Lazily create RtMidiInputDriver | |||
RtMidiInputDriver *d = rtmidiInputDrivers[driverId]; | |||
if (!d) { | |||
rtmidiInputDrivers[driverId] = d = new RtMidiInputDriver(driverId); | |||
} | |||
return d; | |||
RtMidiDriver *rtmidiCreateDriver(int driverId) { | |||
return new RtMidiDriver(driverId); | |||
} | |||