diff --git a/include/midi.hpp b/include/midi.hpp index 72e46a57..6800ca07 100644 --- a/include/midi.hpp +++ b/include/midi.hpp @@ -33,6 +33,8 @@ struct MidiMessage { // MidiIO //////////////////// +struct MidiInputDriver; +struct MidiOutputDriver; struct MidiInputDevice; struct MidiOutputDevice; @@ -51,7 +53,7 @@ struct MidiIO { std::vector 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 //////////////////// diff --git a/include/rtmidi.hpp b/include/rtmidi.hpp index f25789b6..987832d1 100644 --- a/include/rtmidi.hpp +++ b/include/rtmidi.hpp @@ -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 rtmidiGetDrivers(); -int rtmidiGetDeviceCount(int driver); -std::string rtmidiGetDeviceName(int driver, int device); -RtMidiInputDevice *rtmidiGetDevice(int driver, int device); +MidiInputDriver *rtmidiGetInputDriver(int driver); } // namespace rack diff --git a/src/midi.cpp b/src/midi.cpp index c68405e6..c62125f4 100644 --- a/src/midi.cpp +++ b/src/midi.cpp @@ -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); diff --git a/src/rtmidi.cpp b/src/rtmidi.cpp index cf067877..f870d23d 100644 --- a/src/rtmidi.cpp +++ b/src/rtmidi.cpp @@ -1,9 +1,36 @@ #include "rtmidi.hpp" +#include 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 *message, void *userData) { if (!message) return; if (!userData) return; @@ -21,14 +48,12 @@ static void midiInputCallback(double timeStamp, std::vector *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 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 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; }