@@ -33,6 +33,8 @@ struct MidiMessage { | |||
// MidiIO | |||
//////////////////// | |||
struct MidiInputDriver; | |||
struct MidiOutputDriver; | |||
struct MidiInputDevice; | |||
struct MidiOutputDevice; | |||
@@ -51,7 +53,7 @@ struct MidiIO { | |||
std::vector<int> getDrivers(); | |||
std::string getDriverName(int driver); | |||
void setDriver(int driver); | |||
virtual void setDriver(int driver) = 0; | |||
virtual int getDeviceCount() = 0; | |||
virtual std::string getDeviceName(int device) = 0; | |||
@@ -64,11 +66,15 @@ struct MidiIO { | |||
struct MidiInput : MidiIO { | |||
/** Not owned */ | |||
MidiInputDriver *midiInputDriver = NULL; | |||
/** Not owned, must unsubscribe when destructed */ | |||
MidiInputDevice *midiInputDevice = NULL; | |||
MidiInput(); | |||
~MidiInput(); | |||
void setDriver(int driver) override; | |||
int getDeviceCount() override; | |||
std::string getDeviceName(int device) override; | |||
void setDevice(int device) override; | |||
@@ -88,12 +94,34 @@ struct MidiInputQueue : MidiInput { | |||
struct MidiOutput : MidiIO { | |||
/** Not owned */ | |||
MidiOutputDriver *midiOutputDriver = NULL; | |||
/** Not owned, must unsubscribe when destructed */ | |||
MidiOutputDevice *midiOutputDevice = NULL; | |||
MidiOutput(); | |||
~MidiOutput(); | |||
void setDriver(int driver) override; | |||
void setDevice(int device) override; | |||
}; | |||
//////////////////// | |||
// MidiIODriver | |||
//////////////////// | |||
struct MidiIODriver { | |||
virtual ~MidiIODriver() {} | |||
virtual int getDeviceCount() = 0; | |||
virtual std::string getDeviceName(int device) = 0; | |||
}; | |||
struct MidiInputDriver : MidiIODriver { | |||
virtual MidiInputDevice *getDevice(int device) = 0; | |||
}; | |||
struct MidiOutputDriver : MidiIODriver { | |||
virtual MidiOutputDevice *getDevice(int device) = 0; | |||
}; | |||
//////////////////// | |||
// MidiIODevice | |||
//////////////////// | |||
@@ -14,6 +14,18 @@ | |||
namespace rack { | |||
struct RtMidiInputDriver : MidiInputDriver { | |||
/** Just for querying MIDI driver information */ | |||
RtMidiIn *rtMidiIn; | |||
RtMidiInputDriver(int driver); | |||
~RtMidiInputDriver(); | |||
int getDeviceCount() override; | |||
std::string getDeviceName(int device) override; | |||
MidiInputDevice *getDevice(int device) override; | |||
}; | |||
struct RtMidiInputDevice : MidiInputDevice { | |||
RtMidiIn *rtMidiIn; | |||
/** Cached */ | |||
@@ -25,9 +37,7 @@ struct RtMidiInputDevice : MidiInputDevice { | |||
std::vector<int> rtmidiGetDrivers(); | |||
int rtmidiGetDeviceCount(int driver); | |||
std::string rtmidiGetDeviceName(int driver, int device); | |||
RtMidiInputDevice *rtmidiGetDevice(int driver, int device); | |||
MidiInputDriver *rtmidiGetInputDriver(int driver); | |||
} // namespace rack |
@@ -33,11 +33,6 @@ std::string MidiIO::getDriverName(int driver) { | |||
} | |||
} | |||
void MidiIO::setDriver(int driver) { | |||
setDevice(-1); | |||
this->driver = driver; | |||
} | |||
std::string MidiIO::getChannelName(int channel) { | |||
if (channel == -1) | |||
return "All channels"; | |||
@@ -90,28 +85,28 @@ MidiInput::~MidiInput() { | |||
setDriver(-1); | |||
} | |||
int MidiInput::getDeviceCount() { | |||
if (driver >= 0) { | |||
return rtmidiGetDeviceCount(driver); | |||
void MidiInput::setDriver(int driver) { | |||
setDevice(-1); | |||
if (midiInputDriver) { | |||
midiInputDriver = NULL; | |||
} | |||
else if (driver == BRIDGE_DRIVER) { | |||
// TODO | |||
if (driver >= 0) { | |||
midiInputDriver = rtmidiGetInputDriver(driver); | |||
} | |||
else if (driver == GAMEPAD_DRIVER) { | |||
// TODO | |||
this->driver = driver; | |||
} | |||
int MidiInput::getDeviceCount() { | |||
if (midiInputDriver) { | |||
return midiInputDriver->getDeviceCount(); | |||
} | |||
return 0; | |||
} | |||
std::string MidiInput::getDeviceName(int device) { | |||
if (driver >= 0) { | |||
return rtmidiGetDeviceName(driver, device); | |||
} | |||
else if (driver == BRIDGE_DRIVER) { | |||
// TODO | |||
} | |||
else if (driver == GAMEPAD_DRIVER) { | |||
// TODO | |||
if (midiInputDriver) { | |||
return midiInputDriver->getDeviceName(device); | |||
} | |||
return ""; | |||
} | |||
@@ -122,16 +117,11 @@ void MidiInput::setDevice(int device) { | |||
midiInputDevice = NULL; | |||
} | |||
if (driver >= 0) { | |||
midiInputDevice = rtmidiGetDevice(driver, device); | |||
if (midiInputDriver && device >= 0) { | |||
midiInputDevice = midiInputDriver->getDevice(device); | |||
midiInputDevice->subscribe(this); | |||
} | |||
else if (driver == BRIDGE_DRIVER) { | |||
// TODO | |||
} | |||
else if (driver == GAMEPAD_DRIVER) { | |||
// TODO | |||
} | |||
this->device = device; | |||
} | |||
void MidiInputQueue::onMessage(MidiMessage message) { | |||
@@ -167,11 +157,17 @@ MidiOutput::~MidiOutput() { | |||
// TODO | |||
} | |||
void MidiOutput::setDriver(int driver) { | |||
// TODO | |||
} | |||
void MidiOutput::setDevice(int device) { | |||
// TODO | |||
} | |||
//////////////////// | |||
// MidiIODevice | |||
//////////////////// | |||
void MidiInputDevice::subscribe(MidiInput *midiInput) { | |||
subscribed.insert(midiInput); | |||
@@ -1,9 +1,36 @@ | |||
#include "rtmidi.hpp" | |||
#include <map> | |||
namespace rack { | |||
RtMidiInputDriver::RtMidiInputDriver(int driver) { | |||
rtMidiIn = new RtMidiIn((RtMidi::Api) driver); | |||
assert(rtMidiIn); | |||
} | |||
RtMidiInputDriver::~RtMidiInputDriver() { | |||
delete rtMidiIn; | |||
} | |||
int RtMidiInputDriver::getDeviceCount() { | |||
return rtMidiIn->getPortCount(); | |||
} | |||
std::string RtMidiInputDriver::getDeviceName(int device) { | |||
if (device >= 0) { | |||
return rtMidiIn->getPortName(device); | |||
} | |||
return ""; | |||
} | |||
MidiInputDevice *RtMidiInputDriver::getDevice(int device) { | |||
// TODO Get from cache | |||
return new RtMidiInputDevice(rtMidiIn->getCurrentApi(), device); | |||
} | |||
static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) { | |||
if (!message) return; | |||
if (!userData) return; | |||
@@ -21,14 +48,12 @@ static void midiInputCallback(double timeStamp, std::vector<unsigned char> *mess | |||
midiInputDevice->onMessage(msg); | |||
} | |||
RtMidiInputDevice::RtMidiInputDevice(int driver, int device) { | |||
rtMidiIn = new RtMidiIn((RtMidi::Api) driver, "VCV Rack"); | |||
rtMidiIn->ignoreTypes(false, false, false); | |||
rtMidiIn->setCallback(midiInputCallback, this); | |||
} | |||
RtMidiInputDevice::~RtMidiInputDevice() { | |||
rtMidiIn->closePort(); | |||
delete rtMidiIn; | |||
@@ -46,23 +71,15 @@ std::vector<int> rtmidiGetDrivers() { | |||
return drivers; | |||
} | |||
int rtmidiGetDeviceCount(int driver) { | |||
RtMidiIn *rtMidiIn = new RtMidiIn((RtMidi::Api) driver); | |||
int count = rtMidiIn->getPortCount(); | |||
delete rtMidiIn; | |||
return count; | |||
} | |||
std::string rtmidiGetDeviceName(int driver, int device) { | |||
RtMidiIn *rtMidiIn = new RtMidiIn((RtMidi::Api) driver); | |||
std::string name = rtMidiIn->getPortName(device); | |||
delete rtMidiIn; | |||
return name; | |||
} | |||
static std::map<int, RtMidiInputDriver*> rtmidiInputDrivers; | |||
RtMidiInputDevice *rtmidiGetDevice(int driver, int device) { | |||
// TODO Pull from cache | |||
return new RtMidiInputDevice(driver, device); | |||
MidiInputDriver *rtmidiGetInputDriver(int driver) { | |||
// Lazily create RtMidiInputDriver | |||
RtMidiInputDriver *d = rtmidiInputDrivers[driver]; | |||
if (!d) { | |||
rtmidiInputDrivers[driver] = d = new RtMidiInputDriver(driver); | |||
} | |||
return d; | |||
} | |||