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