diff --git a/src/SFML/Window/Unix/JoystickImpl.cpp b/src/SFML/Window/Unix/JoystickImpl.cpp index 7bd1b9608..f262bef9a 100644 --- a/src/SFML/Window/Unix/JoystickImpl.cpp +++ b/src/SFML/Window/Unix/JoystickImpl.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -43,8 +44,34 @@ namespace { -udev* udevContext = nullptr; -udev_monitor* udevMonitor = nullptr; +struct UdevDeleter +{ + void operator()(udev_device* device) const + { + udev_device_unref(device); + } + + void operator()(udev_monitor* monitor) const + { + udev_monitor_unref(monitor); + } + + void operator()(udev_enumerate* enumerate) const + { + udev_enumerate_unref(enumerate); + } + + void operator()(udev* context) const + { + udev_unref(context); + } +}; + +template +using UdevPtr = std::unique_ptr; + +UdevPtr udevContext; +UdevPtr udevMonitor; struct JoystickRecord { @@ -181,7 +208,7 @@ void updatePluggedList(udev_device* udevDevice = nullptr) for (JoystickRecord& record : joystickList) record.plugged = false; - udev_enumerate* udevEnumerator = udev_enumerate_new(udevContext); + const auto udevEnumerator = UdevPtr(udev_enumerate_new(udevContext.get())); if (!udevEnumerator) { @@ -189,36 +216,30 @@ void updatePluggedList(udev_device* udevDevice = nullptr) return; } - int result = 0; - - result = udev_enumerate_add_match_subsystem(udevEnumerator, "input"); - - if (result < 0) + if (udev_enumerate_add_match_subsystem(udevEnumerator.get(), "input") < 0) { sf::err() << "Error while adding udev enumerator match" << std::endl; return; } - result = udev_enumerate_scan_devices(udevEnumerator); - - if (result < 0) + if (udev_enumerate_scan_devices(udevEnumerator.get()) < 0) { sf::err() << "Error while enumerating udev devices" << std::endl; return; } - udev_list_entry* devices = udev_enumerate_get_list_entry(udevEnumerator); + udev_list_entry* devices = udev_enumerate_get_list_entry(udevEnumerator.get()); udev_list_entry* device = nullptr; udev_list_entry_foreach(device, devices) { - const char* syspath = udev_list_entry_get_name(device); - udev_device* newUdevDevice = udev_device_new_from_syspath(udevContext, syspath); + const char* syspath = udev_list_entry_get_name(device); + const auto newUdevDevice = UdevPtr(udev_device_new_from_syspath(udevContext.get(), syspath)); - if (newUdevDevice && isJoystick(newUdevDevice)) + if (newUdevDevice && isJoystick(newUdevDevice.get())) { // Since isJoystick returned true, this has to succeed - const char* devnode = udev_device_get_devnode(newUdevDevice); + const char* devnode = udev_device_get_devnode(newUdevDevice.get()); JoystickList::iterator recordIt; @@ -243,17 +264,13 @@ void updatePluggedList(udev_device* udevDevice = nullptr) joystickList.push_back(newRecord); } } - - udev_device_unref(newUdevDevice); } - - udev_enumerate_unref(udevEnumerator); } bool hasMonitorEvent() { // This will not fail since we make sure udevMonitor is valid - const int monitorFd = udev_monitor_get_fd(udevMonitor); + const int monitorFd = udev_monitor_get_fd(udevMonitor.get()); pollfd fds{monitorFd, POLLIN, 0}; @@ -316,7 +333,8 @@ unsigned int getJoystickVendorId(unsigned int index) return 0; } - udev_device* udevDevice = udev_device_new_from_syspath(udevContext, joystickList[index].systemPath.c_str()); + const auto udevDevice = UdevPtr( + udev_device_new_from_syspath(udevContext.get(), joystickList[index].systemPath.c_str())); if (!udevDevice) { @@ -324,23 +342,12 @@ unsigned int getJoystickVendorId(unsigned int index) return 0; } - unsigned int id = 0; - // First try using udev - id = getUdevAttributeUint(udevDevice, "ID_VENDOR_ID"); - - if (id) - { - udev_device_unref(udevDevice); + if (const unsigned int id = getUdevAttributeUint(udevDevice.get(), "ID_VENDOR_ID")) return id; - } // Fall back to using USB attribute - id = getUsbAttributeUint(udevDevice, "idVendor"); - - udev_device_unref(udevDevice); - - if (id) + if (const unsigned int id = getUsbAttributeUint(udevDevice.get(), "idVendor")) return id; sf::err() << "Failed to get vendor ID of joystick " << joystickList[index].deviceNode << std::endl; @@ -357,7 +364,8 @@ unsigned int getJoystickProductId(unsigned int index) return 0; } - udev_device* udevDevice = udev_device_new_from_syspath(udevContext, joystickList[index].systemPath.c_str()); + const auto udevDevice = UdevPtr( + udev_device_new_from_syspath(udevContext.get(), joystickList[index].systemPath.c_str())); if (!udevDevice) { @@ -365,23 +373,12 @@ unsigned int getJoystickProductId(unsigned int index) return 0; } - unsigned int id = 0; - // First try using udev - id = getUdevAttributeUint(udevDevice, "ID_MODEL_ID"); - - if (id) - { - udev_device_unref(udevDevice); + if (const unsigned int id = getUdevAttributeUint(udevDevice.get(), "ID_MODEL_ID")) return id; - } // Fall back to using USB attribute - id = getUsbAttributeUint(udevDevice, "idProduct"); - - udev_device_unref(udevDevice); - - if (id) + if (const unsigned int id = getUsbAttributeUint(udevDevice.get(), "idProduct")) return id; sf::err() << "Failed to get product ID of joystick " << joystickList[index].deviceNode << std::endl; @@ -412,16 +409,12 @@ std::string getJoystickName(unsigned int index) // Fall back to manual USB chain walk via udev if (udevContext) { - udev_device* udevDevice = udev_device_new_from_syspath(udevContext, joystickList[index].systemPath.c_str()); + const auto udevDevice = UdevPtr( + udev_device_new_from_syspath(udevContext.get(), joystickList[index].systemPath.c_str())); if (udevDevice) - { - const char* product = getUsbAttribute(udevDevice, "product"); - udev_device_unref(udevDevice); - - if (product) + if (const char* product = getUsbAttribute(udevDevice.get(), "product")) return {product}; - } } sf::err() << "Unable to get name for joystick " << devnode << std::endl; @@ -436,7 +429,7 @@ namespace sf::priv //////////////////////////////////////////////////////////// void JoystickImpl::initialize() { - udevContext = udev_new(); + udevContext = UdevPtr(udev_new()); if (!udevContext) { @@ -444,7 +437,7 @@ void JoystickImpl::initialize() return; } - udevMonitor = udev_monitor_new_from_netlink(udevContext, "udev"); + udevMonitor = UdevPtr(udev_monitor_new_from_netlink(udevContext.get(), "udev")); if (!udevMonitor) { @@ -452,27 +445,25 @@ void JoystickImpl::initialize() } else { - int error = udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, "input", nullptr); + int error = udev_monitor_filter_add_match_subsystem_devtype(udevMonitor.get(), "input", nullptr); if (error < 0) { err() << "Failed to add udev monitor filter, joystick connections and disconnections won't be notified: " << error << std::endl; - udev_monitor_unref(udevMonitor); - udevMonitor = nullptr; + udevMonitor.reset(); } else { - error = udev_monitor_enable_receiving(udevMonitor); + error = udev_monitor_enable_receiving(udevMonitor.get()); if (error < 0) { err() << "Failed to enable udev monitor, joystick connections and disconnections won't be notified: " << error << std::endl; - udev_monitor_unref(udevMonitor); - udevMonitor = nullptr; + udevMonitor.reset(); } } } @@ -486,18 +477,10 @@ void JoystickImpl::initialize() void JoystickImpl::cleanup() { // Unreference the udev monitor to destroy it - if (udevMonitor) - { - udev_monitor_unref(udevMonitor); - udevMonitor = nullptr; - } + udevMonitor.reset(); // Unreference the udev context to destroy it - if (udevContext) - { - udev_unref(udevContext); - udevContext = nullptr; - } + udevContext.reset(); } @@ -513,14 +496,11 @@ bool JoystickImpl::isConnected(unsigned int index) else if (hasMonitorEvent()) { // Check if new joysticks were added/removed since last update - udev_device* udevDevice = udev_monitor_receive_device(udevMonitor); + const auto udevDevice = UdevPtr(udev_monitor_receive_device(udevMonitor.get())); // If we can get the specific device, we check that, // otherwise just do a full scan if udevDevice == nullptr - updatePluggedList(udevDevice); - - if (udevDevice) - udev_device_unref(udevDevice); + updatePluggedList(udevDevice.get()); } if (index >= joystickList.size())