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