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