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