@@ -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 ""; | ||||