| @@ -17,8 +17,8 @@ struct BridgeMidiDriver : midi::Driver { | |||
| std::vector<int> getInputDeviceIds() override; | |||
| std::string getInputDeviceName(int deviceId) override; | |||
| midi::InputDevice *subscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInput(int deviceId, midi::Input *input) override; | |||
| }; | |||
| @@ -22,8 +22,8 @@ struct Driver : midi::Driver { | |||
| std::string getName() override {return "Gamepad";} | |||
| std::vector<int> getInputDeviceIds() override; | |||
| std::string getInputDeviceName(int deviceId) override; | |||
| midi::InputDevice *subscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInput(int deviceId, midi::Input *input) override; | |||
| }; | |||
| @@ -22,8 +22,8 @@ struct Driver : midi::Driver { | |||
| std::vector<int> getInputDeviceIds() override; | |||
| std::string getInputDeviceName(int deviceId) override; | |||
| midi::InputDevice *subscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInput(int deviceId, midi::Input *input) override; | |||
| }; | |||
| @@ -29,6 +29,30 @@ struct Message { | |||
| } | |||
| }; | |||
| //////////////////// | |||
| // Driver | |||
| //////////////////// | |||
| struct InputDevice; | |||
| struct Input; | |||
| struct OutputDevice; | |||
| struct Output; | |||
| struct Driver { | |||
| virtual ~Driver() {} | |||
| virtual std::string getName() {return "";} | |||
| virtual std::vector<int> getInputDeviceIds() {return {};} | |||
| virtual std::string getInputDeviceName(int deviceId) {return "";} | |||
| virtual InputDevice *subscribeInput(int deviceId, Input *input) {return NULL;} | |||
| virtual void unsubscribeInput(int deviceId, Input *input) {} | |||
| virtual std::vector<int> getOutputDeviceIds() {return {};} | |||
| virtual std::string getOutputDeviceName(int deviceId) {return "";} | |||
| virtual OutputDevice *subscribeOutput(int deviceId, Output *output) {return NULL;} | |||
| virtual void unsubscribeOutput(int deviceId, Output *output) {} | |||
| }; | |||
| //////////////////// | |||
| // Device | |||
| //////////////////// | |||
| @@ -37,8 +61,6 @@ struct Device { | |||
| virtual ~Device() {} | |||
| }; | |||
| struct Input; | |||
| struct InputDevice : Device { | |||
| std::set<Input*> subscribed; | |||
| void subscribe(Input *input); | |||
| @@ -47,26 +69,10 @@ struct InputDevice : Device { | |||
| }; | |||
| struct OutputDevice : Device { | |||
| // TODO | |||
| }; | |||
| //////////////////// | |||
| // Driver | |||
| //////////////////// | |||
| struct Driver { | |||
| virtual ~Driver() {} | |||
| virtual std::string getName() {return "";} | |||
| virtual std::vector<int> getInputDeviceIds() {return {};} | |||
| virtual std::string getInputDeviceName(int deviceId) {return "";} | |||
| virtual InputDevice *subscribeInputDevice(int deviceId, Input *input) {return NULL;} | |||
| virtual void unsubscribeInputDevice(int deviceId, Input *input) {} | |||
| // virtual std::vector<int> getOutputDeviceIds() = 0; | |||
| // virtual std::string getOutputDeviceName(int deviceId) = 0; | |||
| // virtual OutputDevice *subscribeOutputDevice(int deviceId, Output *midiOutput) = 0; | |||
| // virtual void unsubscribeOutputDevice(int deviceId, Output *midiOutput) = 0; | |||
| std::set<Output*> subscribed; | |||
| void subscribe(Output *input); | |||
| void unsubscribe(Output *input); | |||
| virtual void sendMessage(Message message) {} | |||
| }; | |||
| //////////////////// | |||
| @@ -85,7 +91,8 @@ struct IO { | |||
| /** Not owned */ | |||
| Driver *driver = NULL; | |||
| virtual ~IO(); | |||
| /** Remember to call setDriverId(-1) in subclass destructors. */ | |||
| virtual ~IO() {} | |||
| std::vector<int> getDriverIds(); | |||
| std::string getDriverName(int driverId); | |||
| @@ -96,12 +103,17 @@ struct IO { | |||
| virtual void setDeviceId(int deviceId) = 0; | |||
| std::string getChannelName(int channel); | |||
| void setChannel(int channel); | |||
| json_t *toJson(); | |||
| void fromJson(json_t *rootJ); | |||
| }; | |||
| struct Input : IO { | |||
| /** Not owned */ | |||
| InputDevice *inputDevice = NULL; | |||
| Input(); | |||
| ~Input(); | |||
| @@ -122,9 +134,17 @@ struct InputQueue : Input { | |||
| struct Output : IO { | |||
| /** Not owned */ | |||
| OutputDevice *outputDevice = NULL; | |||
| Output(); | |||
| ~Output(); | |||
| std::vector<int> getDeviceIds() override; | |||
| std::string getDeviceName(int deviceId) override; | |||
| void setDeviceId(int deviceId) override; | |||
| void sendMessage(Message message); | |||
| }; | |||
| @@ -34,8 +34,8 @@ struct RtMidiDriver : midi::Driver { | |||
| std::string getName() override; | |||
| std::vector<int> getInputDeviceIds() override; | |||
| std::string getInputDeviceName(int deviceId) override; | |||
| midi::InputDevice *subscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInputDevice(int deviceId, midi::Input *input) override; | |||
| midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override; | |||
| void unsubscribeInput(int deviceId, midi::Input *input) override; | |||
| }; | |||
| @@ -386,7 +386,7 @@ std::string BridgeMidiDriver::getInputDeviceName(int deviceId) { | |||
| return string::f("Port %d", deviceId + 1); | |||
| } | |||
| midi::InputDevice *BridgeMidiDriver::subscribeInputDevice(int deviceId, midi::Input *input) { | |||
| midi::InputDevice *BridgeMidiDriver::subscribeInput(int deviceId, midi::Input *input) { | |||
| if (!(0 <= deviceId && deviceId < 16)) | |||
| return NULL; | |||
| @@ -394,7 +394,7 @@ midi::InputDevice *BridgeMidiDriver::subscribeInputDevice(int deviceId, midi::In | |||
| return &devices[deviceId]; | |||
| } | |||
| void BridgeMidiDriver::unsubscribeInputDevice(int deviceId, midi::Input *input) { | |||
| void BridgeMidiDriver::unsubscribeInput(int deviceId, midi::Input *input) { | |||
| if (!(0 <= deviceId && deviceId < 16)) | |||
| return; | |||
| @@ -82,7 +82,7 @@ std::string Driver::getInputDeviceName(int deviceId) { | |||
| return string::f(" %d (unavailable)", deviceId + 1); | |||
| } | |||
| midi::InputDevice *Driver::subscribeInputDevice(int deviceId, midi::Input *input) { | |||
| midi::InputDevice *Driver::subscribeInput(int deviceId, midi::Input *input) { | |||
| if (!(0 <= deviceId && deviceId < 16)) | |||
| return NULL; | |||
| @@ -90,7 +90,7 @@ midi::InputDevice *Driver::subscribeInputDevice(int deviceId, midi::Input *input | |||
| return &devices[deviceId]; | |||
| } | |||
| void Driver::unsubscribeInputDevice(int deviceId, midi::Input *input) { | |||
| void Driver::unsubscribeInput(int deviceId, midi::Input *input) { | |||
| if (!(0 <= deviceId && deviceId < 16)) | |||
| return; | |||
| @@ -103,7 +103,7 @@ std::string Driver::getInputDeviceName(int deviceId) { | |||
| return ""; | |||
| } | |||
| midi::InputDevice *Driver::subscribeInputDevice(int deviceId, midi::Input *input) { | |||
| midi::InputDevice *Driver::subscribeInput(int deviceId, midi::Input *input) { | |||
| if (deviceId != 0) | |||
| return NULL; | |||
| @@ -111,7 +111,7 @@ midi::InputDevice *Driver::subscribeInputDevice(int deviceId, midi::Input *input | |||
| return &device; | |||
| } | |||
| void Driver::unsubscribeInputDevice(int deviceId, midi::Input *input) { | |||
| void Driver::unsubscribeInput(int deviceId, midi::Input *input) { | |||
| if (deviceId != 0) | |||
| return; | |||
| @@ -7,6 +7,7 @@ namespace rack { | |||
| namespace midi { | |||
| /** Preserves the order of IDs */ | |||
| static std::vector<int> driverIds; | |||
| static std::map<int, Driver*> drivers; | |||
| @@ -28,24 +29,28 @@ void InputDevice::unsubscribe(Input *input) { | |||
| void InputDevice::onMessage(Message message) { | |||
| for (Input *input : subscribed) { | |||
| input->onMessage(message); | |||
| // Filter channel | |||
| if (input->channel < 0 || message.status() == 0xf || message.channel() == input->channel) { | |||
| input->onMessage(message); | |||
| } | |||
| } | |||
| } | |||
| //////////////////// | |||
| // Driver | |||
| //////////////////// | |||
| void OutputDevice::subscribe(Output *output) { | |||
| subscribed.insert(output); | |||
| } | |||
| void OutputDevice::unsubscribe(Output *output) { | |||
| // Remove Output from subscriptions | |||
| auto it = subscribed.find(output); | |||
| if (it != subscribed.end()) | |||
| subscribed.erase(it); | |||
| } | |||
| //////////////////// | |||
| // IO | |||
| //////////////////// | |||
| IO::~IO() { | |||
| // Because of polymorphic destruction, descendants must call this in their own destructor | |||
| // setDriverId(-1); | |||
| } | |||
| std::vector<int> IO::getDriverIds() { | |||
| return driverIds; | |||
| } | |||
| @@ -59,7 +64,7 @@ std::string IO::getDriverName(int driverId) { | |||
| } | |||
| void IO::setDriverId(int driverId) { | |||
| // Destroy driver | |||
| // Unset device and driver | |||
| setDeviceId(-1); | |||
| if (driver) { | |||
| driver = NULL; | |||
| @@ -81,6 +86,10 @@ std::string IO::getChannelName(int channel) { | |||
| return string::f("Channel %d", channel + 1); | |||
| } | |||
| void IO::setChannel(int channel) { | |||
| this->channel = channel; | |||
| } | |||
| json_t *IO::toJson() { | |||
| json_t *rootJ = json_object(); | |||
| json_object_set_new(rootJ, "driver", json_integer(driverId)); | |||
| @@ -118,6 +127,7 @@ void IO::fromJson(json_t *rootJ) { | |||
| //////////////////// | |||
| Input::Input() { | |||
| // Set first driver as default | |||
| if (driverIds.size() >= 1) { | |||
| setDriverId(driverIds[0]); | |||
| } | |||
| @@ -144,24 +154,19 @@ std::string Input::getDeviceName(int deviceId) { | |||
| void Input::setDeviceId(int deviceId) { | |||
| // Destroy device | |||
| if (driver && this->deviceId >= 0) { | |||
| driver->unsubscribeInputDevice(this->deviceId, this); | |||
| driver->unsubscribeInput(this->deviceId, this); | |||
| inputDevice = NULL; | |||
| } | |||
| this->deviceId = -1; | |||
| // Create device | |||
| if (driver && deviceId >= 0) { | |||
| driver->subscribeInputDevice(deviceId, this); | |||
| inputDevice = driver->subscribeInput(deviceId, this); | |||
| this->deviceId = deviceId; | |||
| } | |||
| } | |||
| void InputQueue::onMessage(Message message) { | |||
| // Filter channel | |||
| if (channel >= 0) { | |||
| if (message.status() != 0xf && message.channel() != channel) | |||
| return; | |||
| } | |||
| // Push to queue | |||
| if ((int) queue.size() < queueMaxSize) | |||
| queue.push(message); | |||
| @@ -183,16 +188,52 @@ bool InputQueue::shift(Message *message) { | |||
| //////////////////// | |||
| Output::Output() { | |||
| // Set first driver as default | |||
| if (driverIds.size() >= 1) { | |||
| setDriverId(driverIds[0]); | |||
| } | |||
| } | |||
| Output::~Output() { | |||
| setDriverId(-1); | |||
| } | |||
| std::vector<int> Output::getDeviceIds() { | |||
| if (driver) { | |||
| return driver->getOutputDeviceIds(); | |||
| } | |||
| return {}; | |||
| } | |||
| std::string Output::getDeviceName(int deviceId) { | |||
| if (driver) { | |||
| return driver->getOutputDeviceName(deviceId); | |||
| } | |||
| return ""; | |||
| } | |||
| void Output::setDeviceId(int deviceId) { | |||
| // TODO | |||
| // Destroy device | |||
| if (driver && this->deviceId >= 0) { | |||
| driver->unsubscribeOutput(this->deviceId, this); | |||
| outputDevice = NULL; | |||
| } | |||
| this->deviceId = -1; | |||
| // Create device | |||
| if (driver && deviceId >= 0) { | |||
| outputDevice = driver->subscribeOutput(deviceId, this); | |||
| this->deviceId = deviceId; | |||
| } | |||
| } | |||
| void Output::sendMessage(Message message) { | |||
| if (outputDevice) { | |||
| outputDevice->sendMessage(message); | |||
| } | |||
| } | |||
| //////////////////// | |||
| // midi | |||
| //////////////////// | |||
| @@ -77,7 +77,7 @@ std::string RtMidiDriver::getInputDeviceName(int deviceId) { | |||
| return ""; | |||
| } | |||
| midi::InputDevice *RtMidiDriver::subscribeInputDevice(int deviceId, midi::Input *input) { | |||
| midi::InputDevice *RtMidiDriver::subscribeInput(int deviceId, midi::Input *input) { | |||
| if (!(0 <= deviceId && deviceId < (int) rtMidiIn->getPortCount())) | |||
| return NULL; | |||
| RtMidiInputDevice *device = devices[deviceId]; | |||
| @@ -89,7 +89,7 @@ midi::InputDevice *RtMidiDriver::subscribeInputDevice(int deviceId, midi::Input | |||
| return device; | |||
| } | |||
| void RtMidiDriver::unsubscribeInputDevice(int deviceId, midi::Input *input) { | |||
| void RtMidiDriver::unsubscribeInput(int deviceId, midi::Input *input) { | |||
| auto it = devices.find(deviceId); | |||
| if (it == devices.end()) | |||
| return; | |||