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