| @@ -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; | |||||
| } | } | ||||