#include "midi.hpp" #include "rtmidi.hpp" #include "bridge.hpp" #include "gamepad.hpp" #include "keyboard.hpp" namespace rack { //////////////////// // MidiIODevice //////////////////// void MidiInputDevice::subscribe(MidiInput *midiInput) { subscribed.insert(midiInput); } void MidiInputDevice::unsubscribe(MidiInput *midiInput) { auto it = subscribed.find(midiInput); if (it != subscribed.end()) subscribed.erase(it); if (subscribed.size() == 0) { warn("TODO: Fix memory leak"); } } void MidiInputDevice::onMessage(MidiMessage message) { for (MidiInput *midiInput : subscribed) { midiInput->onMessage(message); } } //////////////////// // MidiIODriver //////////////////// //////////////////// // MidiIO //////////////////// std::vector MidiIO::getDriverIds() { std::vector driverIds = rtmidiGetDrivers(); // Add custom driverIds driverIds.push_back(BRIDGE_DRIVER); driverIds.push_back(GAMEPAD_DRIVER); driverIds.push_back(KEYBOARD_DRIVER); return driverIds; } std::string MidiIO::getDriverName(int driverId) { switch (driverId) { case -1: return "None"; case RtMidi::UNSPECIFIED: return "Unspecified"; case RtMidi::MACOSX_CORE: return "Core MIDI"; case RtMidi::LINUX_ALSA: return "ALSA"; case RtMidi::UNIX_JACK: return "JACK"; case RtMidi::WINDOWS_MM: return "Windows MIDI"; case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI"; case BRIDGE_DRIVER: return "Bridge"; case GAMEPAD_DRIVER: return "Gamepad"; case KEYBOARD_DRIVER: return "Computer keyboard"; default: return "Unknown"; } } std::string MidiIO::getChannelName(int channel) { if (channel == -1) return "All channels"; else return stringf("Channel %d", channel + 1); } json_t *MidiIO::toJson() { json_t *rootJ = json_object(); json_object_set_new(rootJ, "driver", json_integer(driverId)); std::string deviceName = getDeviceName(deviceId); if (!deviceName.empty()) json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str())); json_object_set_new(rootJ, "channel", json_integer(channel)); return rootJ; } void MidiIO::fromJson(json_t *rootJ) { json_t *driverJ = json_object_get(rootJ, "driver"); if (driverJ) setDriverId(json_integer_value(driverJ)); json_t *deviceNameJ = json_object_get(rootJ, "deviceName"); if (deviceNameJ) { std::string deviceName = json_string_value(deviceNameJ); // Search for device with equal name for (int deviceId : getDeviceIds()) { if (getDeviceName(deviceId) == deviceName) { setDeviceId(deviceId); break; } } } json_t *channelJ = json_object_get(rootJ, "channel"); if (channelJ) channel = json_integer_value(channelJ); } //////////////////// // MidiInput //////////////////// MidiInput::MidiInput() { } MidiInput::~MidiInput() { setDriverId(-1); } void MidiInput::setDriverId(int driverId) { // Destroy driver setDeviceId(-1); if (driver) { driver = NULL; } this->driverId = -1; // Create driver if (driverId >= 0) { driver = rtmidiGetInputDriver(driverId); } else if (driverId == BRIDGE_DRIVER) { // TODO } else if (driverId == GAMEPAD_DRIVER) { driver = gamepadGetInputDriver(); } else if (driverId == KEYBOARD_DRIVER) { driver = keyboardGetInputDriver(); } // Set driverId if (driver) { this->driverId = driverId; } } std::vector MidiInput::getDeviceIds() { if (driver) { return driver->getDeviceIds(); } return {}; } std::string MidiInput::getDeviceName(int deviceId) { if (driver) { return driver->getDeviceName(deviceId); } return ""; } void MidiInput::setDeviceId(int deviceId) { // Destroy device if (device) { device->unsubscribe(this); device = NULL; } this->deviceId = -1; // Create device if (driver && deviceId >= 0) { device = driver->getDevice(deviceId); device->subscribe(this); } // Set deviceId if (device) { this->deviceId = deviceId; } } void MidiInputQueue::onMessage(MidiMessage message) { // Filter channel if (channel >= 0) { if (message.status() != 0xf && message.channel() != channel) return; } // Push to queue if ((int) queue.size() < queueSize) queue.push(message); } bool MidiInputQueue::shift(MidiMessage *message) { if (!message) return false; if (!queue.empty()) { *message = queue.front(); queue.pop(); return true; } return false; } //////////////////// // MidiOutput //////////////////// MidiOutput::MidiOutput() { } MidiOutput::~MidiOutput() { // TODO } void MidiOutput::setDriverId(int driverId) { // TODO } void MidiOutput::setDeviceId(int deviceId) { // TODO } } // namespace rack