| @@ -34,6 +34,10 @@ struct Driver { | |||
| virtual std::vector<int> getDeviceIds() { | |||
| return {}; | |||
| } | |||
| /** Returns the default device to use when the driver is selected, or -1 for none. */ | |||
| virtual int getDefaultDeviceId() { | |||
| return -1; | |||
| } | |||
| /** Returns the name of a device without obtaining it. */ | |||
| virtual std::string getDeviceName(int deviceId) { | |||
| return ""; | |||
| @@ -194,7 +198,9 @@ struct Port { | |||
| void init(); | |||
| void destroy(); | |||
| /** Registers a new audio driver. Takes pointer ownership. */ | |||
| /** Registers a new audio driver. Takes pointer ownership. | |||
| Driver ID is stored in patches and must be unique. -1 is reserved. | |||
| */ | |||
| void addDriver(int driverId, Driver* driver); | |||
| std::vector<int> getDriverIds(); | |||
| Driver* getDriver(int driverId); | |||
| @@ -104,6 +104,10 @@ struct Driver { | |||
| virtual std::vector<int> getInputDeviceIds() { | |||
| return {}; | |||
| } | |||
| /** Returns the default device to use when the driver is selected, or -1 for none. */ | |||
| virtual int getDefaultInputDeviceId() { | |||
| return -1; | |||
| } | |||
| /** Returns the name of an input device without obtaining it. */ | |||
| virtual std::string getInputDeviceName(int deviceId) { | |||
| return ""; | |||
| @@ -124,6 +128,9 @@ struct Driver { | |||
| virtual std::vector<int> getOutputDeviceIds() { | |||
| return {}; | |||
| } | |||
| virtual int getDefaultOutputDeviceId() { | |||
| return -1; | |||
| } | |||
| virtual std::string getOutputDeviceName(int deviceId) { | |||
| return ""; | |||
| } | |||
| @@ -207,6 +214,7 @@ struct Port { | |||
| Device* getDevice(); | |||
| virtual std::vector<int> getDeviceIds() = 0; | |||
| virtual int getDefaultDeviceId() = 0; | |||
| int getDeviceId(); | |||
| virtual void setDeviceId(int deviceId) = 0; | |||
| virtual std::string getDeviceName(int deviceId) = 0; | |||
| @@ -230,6 +238,7 @@ struct Input : Port { | |||
| void reset(); | |||
| std::vector<int> getDeviceIds() override; | |||
| int getDefaultDeviceId() override; | |||
| void setDeviceId(int deviceId) override; | |||
| std::string getDeviceName(int deviceId) override; | |||
| @@ -255,6 +264,7 @@ struct Output : Port { | |||
| void reset(); | |||
| std::vector<int> getDeviceIds() override; | |||
| int getDefaultDeviceId() override; | |||
| void setDeviceId(int deviceId) override; | |||
| std::string getDeviceName(int deviceId) override; | |||
| @@ -70,17 +70,12 @@ Port::Port() { | |||
| } | |||
| Port::~Port() { | |||
| setDriverId(-1); | |||
| setDeviceId(-1); | |||
| } | |||
| void Port::reset() { | |||
| // Get default driver | |||
| int firstDriverId = -1; | |||
| std::vector<int> driverIds = getDriverIds(); | |||
| if (!driverIds.empty()) | |||
| firstDriverId = driverIds[0]; | |||
| setDriverId(firstDriverId); | |||
| // Set default driver | |||
| setDriverId(-1); | |||
| } | |||
| Driver* Port::getDriver() { | |||
| @@ -92,8 +87,6 @@ int Port::getDriverId() { | |||
| } | |||
| void Port::setDriverId(int driverId) { | |||
| if (driverId == this->driverId) | |||
| return; | |||
| // Unset device and driver | |||
| setDeviceId(-1); | |||
| driver = NULL; | |||
| @@ -104,11 +97,20 @@ void Port::setDriverId(int driverId) { | |||
| if (driver) { | |||
| this->driverId = driverId; | |||
| } | |||
| else { | |||
| else if (!drivers.empty()) { | |||
| // Set first driver as default | |||
| driver = drivers[0].second; | |||
| this->driverId = drivers[0].first; | |||
| } | |||
| else { | |||
| // No fallback drivers | |||
| return; | |||
| } | |||
| // Set default device if exists | |||
| int defaultDeviceId = driver->getDefaultDeviceId(); | |||
| if (defaultDeviceId >= 0) | |||
| setDeviceId(defaultDeviceId); | |||
| } | |||
| std::string Port::getDriverName() { | |||
| @@ -165,8 +167,10 @@ void Port::setDeviceId(int deviceId) { | |||
| if (deviceId >= 0) { | |||
| try { | |||
| device = driver->subscribe(deviceId, this); | |||
| this->deviceId = deviceId; | |||
| onStartStream(); | |||
| if (device) { | |||
| this->deviceId = deviceId; | |||
| onStartStream(); | |||
| } | |||
| } | |||
| catch (Exception& e) { | |||
| WARN("Audio port could not subscribe to device: %s", e.what()); | |||
| @@ -375,6 +379,7 @@ void destroy() { | |||
| void addDriver(int driverId, Driver* driver) { | |||
| assert(driver); | |||
| assert(driverId != -1); | |||
| drivers.push_back(std::make_pair(driverId, driver)); | |||
| } | |||
| @@ -387,6 +392,8 @@ std::vector<int> getDriverIds() { | |||
| } | |||
| Driver* getDriver(int driverId) { | |||
| if (driverId == -1) | |||
| return NULL; | |||
| // Search for driver by ID | |||
| for (auto& pair : drivers) { | |||
| if (pair.first == driverId) | |||
| @@ -100,20 +100,25 @@ struct Driver : midi::Driver { | |||
| return deviceIds; | |||
| } | |||
| int getDefaultInputDeviceId() override { | |||
| return 0; | |||
| } | |||
| std::string getInputDeviceName(int deviceId) override { | |||
| if (!(0 <= deviceId && deviceId < 16)) | |||
| return ""; | |||
| const char* name = glfwGetJoystickName(deviceId); | |||
| if (name) { | |||
| return name; | |||
| } | |||
| return string::f(" %d (unavailable)", deviceId + 1); | |||
| if (!name) | |||
| return string::f("#%d (unavailable)", deviceId + 1); | |||
| return name; | |||
| } | |||
| midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override { | |||
| if (!(0 <= deviceId && deviceId < 16)) | |||
| return NULL; | |||
| if (!glfwJoystickPresent(deviceId)) | |||
| return NULL; | |||
| devices[deviceId].subscribe(input); | |||
| return &devices[deviceId]; | |||
| @@ -230,6 +230,11 @@ struct Driver : midi::Driver { | |||
| return deviceIds; | |||
| } | |||
| int getDefaultInputDeviceId() override { | |||
| // QWERTY keyboard device | |||
| return 0; | |||
| } | |||
| midi::InputDevice* getInputDevice(int deviceId) { | |||
| if (deviceId == MOUSE_DEVICE_ID) | |||
| return &mouseDevice; | |||
| @@ -112,11 +112,20 @@ void Port::setDriverId(int driverId) { | |||
| if (driver) { | |||
| this->driverId = driverId; | |||
| } | |||
| else { | |||
| else if (!drivers.empty()) { | |||
| // Set first driver as default | |||
| driver = drivers[0].second; | |||
| this->driverId = drivers[0].first; | |||
| } | |||
| else { | |||
| // No fallback drivers | |||
| return; | |||
| } | |||
| // Set default device if exists | |||
| int defaultDeviceId = getDefaultDeviceId(); | |||
| if (defaultDeviceId >= 0) | |||
| setDeviceId(defaultDeviceId); | |||
| } | |||
| Device* Port::getDevice() { | |||
| @@ -191,7 +200,7 @@ Input::Input() { | |||
| } | |||
| Input::~Input() { | |||
| setDriverId(-1); | |||
| setDeviceId(-1); | |||
| } | |||
| void Input::reset() { | |||
| @@ -211,6 +220,12 @@ std::vector<int> Input::getDeviceIds() { | |||
| } | |||
| } | |||
| int Input::getDefaultDeviceId() { | |||
| if (!driver) | |||
| return -1; | |||
| return driver->getDefaultInputDeviceId(); | |||
| } | |||
| void Input::setDeviceId(int deviceId) { | |||
| // Destroy device | |||
| if (driver && this->deviceId >= 0) { | |||
| @@ -228,7 +243,9 @@ void Input::setDeviceId(int deviceId) { | |||
| if (driver && deviceId >= 0) { | |||
| try { | |||
| device = inputDevice = driver->subscribeInput(deviceId, this); | |||
| this->deviceId = deviceId; | |||
| if (device) { | |||
| this->deviceId = deviceId; | |||
| } | |||
| } | |||
| catch (Exception& e) { | |||
| WARN("MIDI port could not subscribe to input: %s", e.what()); | |||
| @@ -272,7 +289,7 @@ Output::Output() { | |||
| } | |||
| Output::~Output() { | |||
| setDriverId(-1); | |||
| setDeviceId(-1); | |||
| } | |||
| void Output::reset() { | |||
| @@ -309,7 +326,9 @@ void Output::setDeviceId(int deviceId) { | |||
| if (driver && deviceId >= 0) { | |||
| try { | |||
| device = outputDevice = driver->subscribeOutput(deviceId, this); | |||
| this->deviceId = deviceId; | |||
| if (device) { | |||
| this->deviceId = deviceId; | |||
| } | |||
| } | |||
| catch (Exception& e) { | |||
| WARN("MIDI port could not subscribe to output: %s", e.what()); | |||
| @@ -317,6 +336,12 @@ void Output::setDeviceId(int deviceId) { | |||
| } | |||
| } | |||
| int Output::getDefaultDeviceId() { | |||
| if (!driver) | |||
| return -1; | |||
| return driver->getDefaultOutputDeviceId(); | |||
| } | |||
| std::string Output::getDeviceName(int deviceId) { | |||
| if (!driver) | |||
| return ""; | |||