@@ -11,7 +11,7 @@ const int GAMEPAD_DRIVER = -10; | |||
struct GamepadInputDevice : MidiInputDevice { | |||
int device; | |||
int deviceId; | |||
}; | |||
@@ -19,9 +19,9 @@ struct GamepadInputDriver : MidiInputDriver { | |||
GamepadInputDevice gamepadInputDevices[16]; | |||
GamepadInputDriver(); | |||
int getDeviceCount() override; | |||
std::string getDeviceName(int device) override; | |||
MidiInputDevice *getDevice(int device) override; | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
MidiInputDevice *getDevice(int deviceId) override; | |||
}; | |||
@@ -56,16 +56,16 @@ struct MidiOutputDevice : MidiIODevice { | |||
struct MidiIODriver { | |||
virtual ~MidiIODriver() {} | |||
virtual int getDeviceCount() = 0; | |||
virtual std::string getDeviceName(int device) = 0; | |||
virtual std::vector<int> getDeviceIds() = 0; | |||
virtual std::string getDeviceName(int deviceId) = 0; | |||
}; | |||
struct MidiInputDriver : MidiIODriver { | |||
virtual MidiInputDevice *getDevice(int device) = 0; | |||
virtual MidiInputDevice *getDevice(int deviceId) = 0; | |||
}; | |||
struct MidiOutputDriver : MidiIODriver { | |||
virtual MidiOutputDevice *getDevice(int device) = 0; | |||
virtual MidiOutputDevice *getDevice(int deviceId) = 0; | |||
}; | |||
//////////////////// | |||
@@ -73,8 +73,8 @@ struct MidiOutputDriver : MidiIODriver { | |||
//////////////////// | |||
struct MidiIO { | |||
int driver = -1; | |||
int device = -1; | |||
int driverId = -1; | |||
int deviceId = -1; | |||
/* For MIDI output, the channel to output messages. | |||
For MIDI input, the channel to filter. | |||
Set to -1 to allow all MIDI channels (for input). | |||
@@ -84,13 +84,13 @@ struct MidiIO { | |||
virtual ~MidiIO() {} | |||
std::vector<int> getDrivers(); | |||
std::string getDriverName(int driver); | |||
virtual void setDriver(int driver) = 0; | |||
std::vector<int> getDriverIds(); | |||
std::string getDriverName(int driverId); | |||
virtual void setDriverId(int driverId) = 0; | |||
virtual int getDeviceCount() = 0; | |||
virtual std::string getDeviceName(int device) = 0; | |||
virtual void setDevice(int device) = 0; | |||
virtual std::vector<int> getDeviceIds() = 0; | |||
virtual std::string getDeviceName(int deviceId) = 0; | |||
virtual void setDeviceId(int deviceId) = 0; | |||
std::string getChannelName(int channel); | |||
json_t *toJson(); | |||
@@ -100,17 +100,17 @@ struct MidiIO { | |||
struct MidiInput : MidiIO { | |||
/** Not owned */ | |||
MidiInputDriver *midiInputDriver = NULL; | |||
MidiInputDriver *driver = NULL; | |||
/** Not owned, must unsubscribe when destructed */ | |||
MidiInputDevice *midiInputDevice = NULL; | |||
MidiInputDevice *device = NULL; | |||
MidiInput(); | |||
~MidiInput(); | |||
void setDriver(int driver) override; | |||
int getDeviceCount() override; | |||
std::string getDeviceName(int device) override; | |||
void setDevice(int device) override; | |||
void setDriverId(int driverId) override; | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
void setDeviceId(int deviceId) override; | |||
virtual void onMessage(MidiMessage message) {} | |||
}; | |||
@@ -128,13 +128,13 @@ struct MidiInputQueue : MidiInput { | |||
struct MidiOutput : MidiIO { | |||
/** Not owned */ | |||
MidiOutputDriver *midiOutputDriver = NULL; | |||
MidiOutputDriver *driver = NULL; | |||
/** Not owned, must unsubscribe when destructed */ | |||
MidiOutputDevice *midiOutputDevice = NULL; | |||
MidiOutputDevice *device = NULL; | |||
MidiOutput(); | |||
~MidiOutput(); | |||
void setDriver(int driver) override; | |||
void setDevice(int device) override; | |||
void setDriverId(int driverId) override; | |||
void setDeviceId(int deviceId) override; | |||
}; | |||
@@ -18,11 +18,11 @@ struct RtMidiInputDriver : MidiInputDriver { | |||
/** Just for querying MIDI driver information */ | |||
RtMidiIn *rtMidiIn; | |||
RtMidiInputDriver(int driver); | |||
RtMidiInputDriver(int driverId); | |||
~RtMidiInputDriver(); | |||
int getDeviceCount() override; | |||
std::string getDeviceName(int device) override; | |||
MidiInputDevice *getDevice(int device) override; | |||
std::vector<int> getDeviceIds() override; | |||
std::string getDeviceName(int deviceId) override; | |||
MidiInputDevice *getDevice(int deviceId) override; | |||
}; | |||
@@ -31,13 +31,13 @@ struct RtMidiInputDevice : MidiInputDevice { | |||
/** Cached */ | |||
std::string deviceName; | |||
RtMidiInputDevice(int driver, int device); | |||
RtMidiInputDevice(int driverId, int deviceId); | |||
~RtMidiInputDevice(); | |||
}; | |||
std::vector<int> rtmidiGetDrivers(); | |||
MidiInputDriver *rtmidiGetInputDriver(int driver); | |||
MidiInputDriver *rtmidiGetInputDriver(int driverId); | |||
} // namespace rack |
@@ -7,9 +7,9 @@ namespace rack { | |||
struct MidiDriverItem : MenuItem { | |||
MidiIO *midiIO; | |||
int driver; | |||
int driverId; | |||
void onAction(EventAction &e) override { | |||
midiIO->setDriver(driver); | |||
midiIO->setDriverId(driverId); | |||
} | |||
}; | |||
@@ -18,25 +18,25 @@ struct MidiDriverChoice : LedDisplayChoice { | |||
void onAction(EventAction &e) override { | |||
Menu *menu = gScene->createMenu(); | |||
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "MIDI driver")); | |||
for (int driver : midiWidget->midiIO->getDrivers()) { | |||
for (int driverId : midiWidget->midiIO->getDriverIds()) { | |||
MidiDriverItem *item = new MidiDriverItem(); | |||
item->midiIO = midiWidget->midiIO; | |||
item->driver = driver; | |||
item->text = midiWidget->midiIO->getDriverName(driver); | |||
item->rightText = CHECKMARK(item->driver == midiWidget->midiIO->driver); | |||
item->driverId = driverId; | |||
item->text = midiWidget->midiIO->getDriverName(driverId); | |||
item->rightText = CHECKMARK(item->driverId == midiWidget->midiIO->driverId); | |||
menu->addChild(item); | |||
} | |||
} | |||
void step() override { | |||
text = midiWidget->midiIO->getDriverName(midiWidget->midiIO->driver); | |||
text = midiWidget->midiIO->getDriverName(midiWidget->midiIO->driverId); | |||
} | |||
}; | |||
struct MidiDeviceItem : MenuItem { | |||
MidiIO *midiIO; | |||
int device; | |||
int deviceId; | |||
void onAction(EventAction &e) override { | |||
midiIO->setDevice(device); | |||
midiIO->setDeviceId(deviceId); | |||
} | |||
}; | |||
@@ -48,23 +48,22 @@ struct MidiDeviceChoice : LedDisplayChoice { | |||
{ | |||
MidiDeviceItem *item = new MidiDeviceItem(); | |||
item->midiIO = midiWidget->midiIO; | |||
item->device = -1; | |||
item->deviceId = -1; | |||
item->text = "(No device)"; | |||
item->rightText = CHECKMARK(item->device == midiWidget->midiIO->device); | |||
item->rightText = CHECKMARK(item->deviceId == midiWidget->midiIO->deviceId); | |||
menu->addChild(item); | |||
} | |||
int driverCount = midiWidget->midiIO->getDeviceCount(); | |||
for (int device = 0; device < driverCount; device++) { | |||
for (int deviceId : midiWidget->midiIO->getDeviceIds()) { | |||
MidiDeviceItem *item = new MidiDeviceItem(); | |||
item->midiIO = midiWidget->midiIO; | |||
item->device = device; | |||
item->text = midiWidget->midiIO->getDeviceName(device); | |||
item->rightText = CHECKMARK(item->device == midiWidget->midiIO->device); | |||
item->deviceId = deviceId; | |||
item->text = midiWidget->midiIO->getDeviceName(deviceId); | |||
item->rightText = CHECKMARK(item->deviceId == midiWidget->midiIO->deviceId); | |||
menu->addChild(item); | |||
} | |||
} | |||
void step() override { | |||
text = midiWidget->midiIO->getDeviceName(midiWidget->midiIO->device); | |||
text = midiWidget->midiIO->getDeviceName(midiWidget->midiIO->deviceId); | |||
if (text.empty()) { | |||
text = "(No device)"; | |||
color.a = 0.5f; | |||
@@ -8,26 +8,36 @@ namespace rack { | |||
GamepadInputDriver::GamepadInputDriver() { | |||
for (int i = 0; i < 16; i++) { | |||
gamepadInputDevices[i].device = i; | |||
gamepadInputDevices[i].deviceId = i; | |||
} | |||
} | |||
int GamepadInputDriver::getDeviceCount() { | |||
return 16; | |||
std::vector<int> GamepadInputDriver::getDeviceIds() { | |||
std::vector<int> deviceIds; | |||
for (int i = 0; i < 16; i++) { | |||
if (glfwJoystickPresent(i)) { | |||
deviceIds.push_back(i); | |||
} | |||
} | |||
return deviceIds; | |||
} | |||
std::string GamepadInputDriver::getDeviceName(int device) { | |||
assert(0 <= device && device < 16); | |||
const char *name = glfwGetJoystickName(device); | |||
std::string GamepadInputDriver::getDeviceName(int deviceId) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return ""; | |||
const char *name = glfwGetJoystickName(deviceId); | |||
if (name) { | |||
return name; | |||
} | |||
return stringf("Gamepad %d (unavailable)", device + 1); | |||
return stringf("Gamepad %d (unavailable)", deviceId + 1); | |||
} | |||
MidiInputDevice *GamepadInputDriver::getDevice(int device) { | |||
assert(0 <= device && device < 16); | |||
return &gamepadInputDevices[device]; | |||
MidiInputDevice *GamepadInputDriver::getDevice(int deviceId) { | |||
if (!(0 <= deviceId && deviceId < 16)) | |||
return NULL; | |||
return &gamepadInputDevices[deviceId]; | |||
} | |||
@@ -40,16 +40,16 @@ void MidiInputDevice::onMessage(MidiMessage message) { | |||
// MidiIO | |||
//////////////////// | |||
std::vector<int> MidiIO::getDrivers() { | |||
std::vector<int> drivers = rtmidiGetDrivers(); | |||
// Add custom drivers | |||
drivers.push_back(BRIDGE_DRIVER); | |||
drivers.push_back(GAMEPAD_DRIVER); | |||
return drivers; | |||
std::vector<int> MidiIO::getDriverIds() { | |||
std::vector<int> driverIds = rtmidiGetDrivers(); | |||
// Add custom driverIds | |||
driverIds.push_back(BRIDGE_DRIVER); | |||
driverIds.push_back(GAMEPAD_DRIVER); | |||
return driverIds; | |||
} | |||
std::string MidiIO::getDriverName(int driver) { | |||
switch (driver) { | |||
std::string MidiIO::getDriverName(int driverId) { | |||
switch (driverId) { | |||
case RtMidi::UNSPECIFIED: return "Unspecified"; | |||
case RtMidi::MACOSX_CORE: return "Core MIDI"; | |||
case RtMidi::LINUX_ALSA: return "ALSA"; | |||
@@ -71,8 +71,8 @@ std::string MidiIO::getChannelName(int channel) { | |||
json_t *MidiIO::toJson() { | |||
json_t *rootJ = json_object(); | |||
json_object_set_new(rootJ, "driver", json_integer(driver)); | |||
std::string deviceName = getDeviceName(device); | |||
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)); | |||
@@ -82,16 +82,15 @@ json_t *MidiIO::toJson() { | |||
void MidiIO::fromJson(json_t *rootJ) { | |||
json_t *driverJ = json_object_get(rootJ, "driver"); | |||
if (driverJ) | |||
setDriver(json_integer_value(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 | |||
int deviceCount = getDeviceCount(); | |||
for (int device = 0; device < deviceCount; device++) { | |||
if (getDeviceName(device) == deviceName) { | |||
setDevice(device); | |||
for (int deviceId : getDeviceIds()) { | |||
if (getDeviceName(deviceId) == deviceName) { | |||
setDeviceId(deviceId); | |||
break; | |||
} | |||
} | |||
@@ -111,52 +110,66 @@ MidiInput::MidiInput() { | |||
} | |||
MidiInput::~MidiInput() { | |||
setDriver(-1); | |||
setDriverId(-1); | |||
} | |||
void MidiInput::setDriver(int driver) { | |||
setDevice(-1); | |||
if (midiInputDriver) { | |||
midiInputDriver = NULL; | |||
void MidiInput::setDriverId(int driverId) { | |||
// Destroy driver | |||
setDeviceId(-1); | |||
if (driver) { | |||
driver = NULL; | |||
} | |||
this->driverId = -1; | |||
if (driver >= 0) { | |||
midiInputDriver = rtmidiGetInputDriver(driver); | |||
// Create driver | |||
if (driverId >= 0) { | |||
driver = rtmidiGetInputDriver(driverId); | |||
} | |||
else if (driver == BRIDGE_DRIVER) { | |||
else if (driverId == BRIDGE_DRIVER) { | |||
// TODO | |||
} | |||
else if (driver == GAMEPAD_DRIVER) { | |||
midiInputDriver = gamepadGetInputDriver(); | |||
else if (driverId == GAMEPAD_DRIVER) { | |||
driver = gamepadGetInputDriver(); | |||
} | |||
// Set driverId | |||
if (driver) { | |||
this->driverId = driverId; | |||
} | |||
this->driver = driver; | |||
} | |||
int MidiInput::getDeviceCount() { | |||
if (midiInputDriver) { | |||
return midiInputDriver->getDeviceCount(); | |||
std::vector<int> MidiInput::getDeviceIds() { | |||
if (driver) { | |||
return driver->getDeviceIds(); | |||
} | |||
return 0; | |||
return {}; | |||
} | |||
std::string MidiInput::getDeviceName(int device) { | |||
if (midiInputDriver) { | |||
return midiInputDriver->getDeviceName(device); | |||
std::string MidiInput::getDeviceName(int deviceId) { | |||
if (driver) { | |||
return driver->getDeviceName(deviceId); | |||
} | |||
return ""; | |||
} | |||
void MidiInput::setDevice(int device) { | |||
if (midiInputDevice) { | |||
midiInputDevice->unsubscribe(this); | |||
midiInputDevice = NULL; | |||
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); | |||
} | |||
if (midiInputDriver && device >= 0) { | |||
midiInputDevice = midiInputDriver->getDevice(device); | |||
midiInputDevice->subscribe(this); | |||
// Set deviceId | |||
if (device) { | |||
this->deviceId = deviceId; | |||
} | |||
this->device = device; | |||
} | |||
void MidiInputQueue::onMessage(MidiMessage message) { | |||
@@ -192,11 +205,11 @@ MidiOutput::~MidiOutput() { | |||
// TODO | |||
} | |||
void MidiOutput::setDriver(int driver) { | |||
void MidiOutput::setDriverId(int driverId) { | |||
// TODO | |||
} | |||
void MidiOutput::setDevice(int device) { | |||
void MidiOutput::setDeviceId(int deviceId) { | |||
// TODO | |||
} | |||
@@ -5,8 +5,8 @@ | |||
namespace rack { | |||
RtMidiInputDriver::RtMidiInputDriver(int driver) { | |||
rtMidiIn = new RtMidiIn((RtMidi::Api) driver); | |||
RtMidiInputDriver::RtMidiInputDriver(int driverId) { | |||
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId); | |||
assert(rtMidiIn); | |||
} | |||
@@ -14,20 +14,24 @@ RtMidiInputDriver::~RtMidiInputDriver() { | |||
delete rtMidiIn; | |||
} | |||
int RtMidiInputDriver::getDeviceCount() { | |||
return rtMidiIn->getPortCount(); | |||
std::vector<int> RtMidiInputDriver::getDeviceIds() { | |||
int count = rtMidiIn->getPortCount();; | |||
std::vector<int> deviceIds; | |||
for (int i = 0; i < count; i++) | |||
deviceIds.push_back(i); | |||
return deviceIds; | |||
} | |||
std::string RtMidiInputDriver::getDeviceName(int device) { | |||
if (device >= 0) { | |||
return rtMidiIn->getPortName(device); | |||
std::string RtMidiInputDriver::getDeviceName(int deviceId) { | |||
if (deviceId >= 0) { | |||
return rtMidiIn->getPortName(deviceId); | |||
} | |||
return ""; | |||
} | |||
MidiInputDevice *RtMidiInputDriver::getDevice(int device) { | |||
MidiInputDevice *RtMidiInputDriver::getDevice(int deviceId) { | |||
// TODO Get from cache | |||
return new RtMidiInputDevice(rtMidiIn->getCurrentApi(), device); | |||
return new RtMidiInputDevice(rtMidiIn->getCurrentApi(), deviceId); | |||
} | |||
@@ -48,8 +52,8 @@ 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"); | |||
RtMidiInputDevice::RtMidiInputDevice(int driverId, int deviceId) { | |||
rtMidiIn = new RtMidiIn((RtMidi::Api) driverId, "VCV Rack"); | |||
rtMidiIn->ignoreTypes(false, false, false); | |||
rtMidiIn->setCallback(midiInputCallback, this); | |||
} | |||
@@ -73,11 +77,11 @@ std::vector<int> rtmidiGetDrivers() { | |||
static std::map<int, RtMidiInputDriver*> rtmidiInputDrivers; | |||
MidiInputDriver *rtmidiGetInputDriver(int driver) { | |||
MidiInputDriver *rtmidiGetInputDriver(int driverId) { | |||
// Lazily create RtMidiInputDriver | |||
RtMidiInputDriver *d = rtmidiInputDrivers[driver]; | |||
RtMidiInputDriver *d = rtmidiInputDrivers[driverId]; | |||
if (!d) { | |||
rtmidiInputDrivers[driver] = d = new RtMidiInputDriver(driver); | |||
rtmidiInputDrivers[driverId] = d = new RtMidiInputDriver(driverId); | |||
} | |||
return d; | |||
} | |||