optional libudev support for auto update devices
This commit is contained in:
@ -8,14 +8,31 @@ set(QJOYPAD_PATCH 0)
|
|||||||
|
|
||||||
find_package(Qt4 REQUIRED)
|
find_package(Qt4 REQUIRED)
|
||||||
|
|
||||||
|
set(WITH_LIBUDEV ON CACHE PATH "Use libudev for automatically updating joypad devices.")
|
||||||
|
|
||||||
|
if(WITH_LIBUDEV)
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
pkg_check_modules(LIBUDEV libudev)
|
||||||
|
|
||||||
|
if(LIBUDEV_FOUND)
|
||||||
|
message(STATUS "libudev found")
|
||||||
|
else()
|
||||||
|
message(ERROR "libudev not found. If you don't want to compile with libudev support use -DWITH_LIBUDEV=OFF")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
link_directories(${LIBUDEV_LIBRARY_DIRS})
|
||||||
|
include_directories(${LIBUDEV_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
set(DEVICE_DIR "/dev/input" CACHE PATH "Set the path where QJoyPad will look for your joystick devices. If your devices are /dev/js0, /dev/js1, etc., this should be just \"/dev\". By default, this is /dev/input.")
|
set(DEVICE_DIR "/dev/input" CACHE PATH "Set the path where QJoyPad will look for your joystick devices. If your devices are /dev/js0, /dev/js1, etc., this should be just \"/dev\". By default, this is /dev/input.")
|
||||||
|
|
||||||
set(PLAIN_KEYS OFF CACHE BOOL "Force QJoyPad to use standard XWindows keynames without filtering them for appearance. This will make displays less attractive and readable, but will save processor power and ensure that you see the right names for keys you press.")
|
set(PLAIN_KEYS OFF CACHE BOOL "Force QJoyPad to use standard XWindows keynames without filtering them for appearance. This will make displays less attractive and readable, but will save processor power and ensure that you see the right names for keys you press.")
|
||||||
|
|
||||||
message("-- Using device directory: ${DEVICE_DIR}")
|
message(STATUS "Using device directory: ${DEVICE_DIR}")
|
||||||
|
|
||||||
if(PLAIN_KEYS)
|
if(PLAIN_KEYS)
|
||||||
message("-- Using regular XWindows key names.")
|
message(STATUS "Using regular XWindows key names.")
|
||||||
add_definitions(-DPLAIN_KEYS)
|
add_definitions(-DPLAIN_KEYS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -23,25 +23,25 @@ set(qjoypad_SOURCES
|
|||||||
quickset.cpp)
|
quickset.cpp)
|
||||||
|
|
||||||
set(qjoypad_QOBJECT_HEADERS
|
set(qjoypad_QOBJECT_HEADERS
|
||||||
axis_edit.h
|
axis_edit.h
|
||||||
axis.h
|
axis.h
|
||||||
axisw.h
|
axisw.h
|
||||||
button_edit.h
|
button_edit.h
|
||||||
button.h
|
button.h
|
||||||
buttonw.h
|
buttonw.h
|
||||||
flash.h
|
flash.h
|
||||||
getkey.h
|
getkey.h
|
||||||
icon.h
|
icon.h
|
||||||
joypad.h
|
joypad.h
|
||||||
joypadw.h
|
joypadw.h
|
||||||
joyslider.h
|
joyslider.h
|
||||||
keycode.h
|
keycode.h
|
||||||
layout_edit.h
|
layout_edit.h
|
||||||
layout.h
|
layout.h
|
||||||
quickset.h)
|
quickset.h)
|
||||||
|
|
||||||
QT4_WRAP_CPP(qjoypad_HEADERS_MOC ${qjoypad_QOBJECT_HEADERS})
|
QT4_WRAP_CPP(qjoypad_HEADERS_MOC ${qjoypad_QOBJECT_HEADERS})
|
||||||
add_executable(qjoypad ${qjoypad_SOURCES} ${qjoypad_HEADERS_MOC})
|
add_executable(qjoypad ${qjoypad_SOURCES} ${qjoypad_HEADERS_MOC})
|
||||||
target_link_libraries(qjoypad ${QT_LIBRARIES} Xtst X11)
|
target_link_libraries(qjoypad ${QT_LIBRARIES} Xtst X11 ${LIBUDEV_LIBRARIES})
|
||||||
|
|
||||||
install(TARGETS qjoypad RUNTIME DESTINATION "bin")
|
install(TARGETS qjoypad RUNTIME DESTINATION "bin")
|
||||||
|
@ -12,4 +12,6 @@
|
|||||||
#define QJOYPAD_ICON24 "@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/24x24/apps/qjoypad.png"
|
#define QJOYPAD_ICON24 "@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/24x24/apps/qjoypad.png"
|
||||||
#define QJOYPAD_ICON64 "@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/64x64/apps/qjoypad.png"
|
#define QJOYPAD_ICON64 "@CMAKE_INSTALL_PREFIX@/share/icons/hicolor/64x64/apps/qjoypad.png"
|
||||||
|
|
||||||
|
#cmakedefine WITH_LIBUDEV
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
172
src/layout.cpp
172
src/layout.cpp
@ -15,6 +15,18 @@ LayoutManager::LayoutManager( bool useTrayIcon, const QString &devdir, const QSt
|
|||||||
updateLayoutsAction(new QAction(QIcon::fromTheme("view-refresh"),"Update &Layout List",this)),
|
updateLayoutsAction(new QAction(QIcon::fromTheme("view-refresh"),"Update &Layout List",this)),
|
||||||
quitAction(new QAction(QIcon::fromTheme("application-exit"),"&Quit",this)),
|
quitAction(new QAction(QIcon::fromTheme("application-exit"),"&Quit",this)),
|
||||||
le(0) {
|
le(0) {
|
||||||
|
|
||||||
|
#ifdef WITH_LIBUDEV
|
||||||
|
udevNotifier = 0;
|
||||||
|
udev = 0;
|
||||||
|
monitor = 0;
|
||||||
|
|
||||||
|
if (!initUDev()) {
|
||||||
|
errorBox("UDev Error", "Error creating udev monitor. "
|
||||||
|
"QJoyPad will still work, but it won't automatically update the joypad device list.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//prepare the popup first.
|
//prepare the popup first.
|
||||||
titleAction->setEnabled(false);
|
titleAction->setEnabled(false);
|
||||||
fillPopup();
|
fillPopup();
|
||||||
@ -49,8 +61,99 @@ LayoutManager::~LayoutManager() {
|
|||||||
le->close();
|
le->close();
|
||||||
le = 0;
|
le = 0;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_LIBUDEV
|
||||||
|
if (udevNotifier) {
|
||||||
|
udevNotifier->blockSignals(true);
|
||||||
|
}
|
||||||
|
if (monitor) {
|
||||||
|
udev_monitor_unref(monitor);
|
||||||
|
monitor = 0;
|
||||||
|
}
|
||||||
|
if (udev) {
|
||||||
|
udev_unref(udev);
|
||||||
|
udev = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_LIBUDEV
|
||||||
|
bool LayoutManager::initUDev() {
|
||||||
|
udev = udev_new();
|
||||||
|
debug_mesg("init udev\n");
|
||||||
|
|
||||||
|
if (udev) {
|
||||||
|
debug_mesg("udev ok\n");
|
||||||
|
monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||||
|
|
||||||
|
if (monitor) {
|
||||||
|
debug_mesg("monitor ok\n");
|
||||||
|
int errnum = udev_monitor_filter_add_match_subsystem_devtype(
|
||||||
|
monitor, "input", NULL);
|
||||||
|
if (errnum != 0) {
|
||||||
|
debug_mesg("udev_monitor_filter_add_match_subsystem_devtype: %s\n",
|
||||||
|
strerror(errnum));
|
||||||
|
udev_monitor_unref(monitor);
|
||||||
|
udev_unref(udev);
|
||||||
|
monitor = 0;
|
||||||
|
udev = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
errnum = udev_monitor_enable_receiving(monitor);
|
||||||
|
if (errnum != 0) {
|
||||||
|
debug_mesg("udev_monitor_enable_receiving: %s\n",
|
||||||
|
strerror(errnum));
|
||||||
|
udev_monitor_unref(monitor);
|
||||||
|
udev_unref(udev);
|
||||||
|
monitor = 0;
|
||||||
|
udev = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
udevNotifier = new QSocketNotifier(udev_monitor_get_fd(monitor), QSocketNotifier::Read, this);
|
||||||
|
connect(udevNotifier, SIGNAL(activated(int)), this, SLOT(udevUpdate()));
|
||||||
|
debug_mesg("notifier ok\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
udev_unref(udev);
|
||||||
|
udev = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return udev != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayoutManager::udevUpdate() {
|
||||||
|
struct udev_device *dev = udev_monitor_receive_device(monitor);
|
||||||
|
if (dev) {
|
||||||
|
QRegExp devicename("/js(\\d+)$");
|
||||||
|
QString path = QString("/sys%1").arg(udev_device_get_devpath(dev));
|
||||||
|
const char *action = udev_device_get_action(dev);
|
||||||
|
|
||||||
|
if (devicename.indexIn(path) >= 0) {
|
||||||
|
int index = devicename.cap(1).toInt();
|
||||||
|
|
||||||
|
if (strcmp(action,"add") == 0 || strcmp(action,"online") == 0) {
|
||||||
|
addJoyPad(index, path);
|
||||||
|
}
|
||||||
|
else if (strcmp(action,"remove") == 0 || strcmp(action,"offline") == 0) {
|
||||||
|
removeJoyPad(index);
|
||||||
|
}
|
||||||
|
else if (strcmp(action,"change") == 0) {
|
||||||
|
removeJoyPad(index);
|
||||||
|
addJoyPad(index, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillPopup();
|
||||||
|
if (le) {
|
||||||
|
le->updateJoypadWidgets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
udev_device_unref(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QString LayoutManager::getFileName(const QString& layoutname ) {
|
QString LayoutManager::getFileName(const QString& layoutname ) {
|
||||||
return QString("%1%2.lyt").arg(settingsDir, layoutname);
|
return QString("%1%2.lyt").arg(settingsDir, layoutname);
|
||||||
}
|
}
|
||||||
@ -390,42 +493,57 @@ void LayoutManager::updateJoyDevs() {
|
|||||||
QDir deviceDir(devdir);
|
QDir deviceDir(devdir);
|
||||||
QStringList devices = deviceDir.entryList(QStringList("js*"), QDir::System);
|
QStringList devices = deviceDir.entryList(QStringList("js*"), QDir::System);
|
||||||
QRegExp devicename("js(\\d+)");
|
QRegExp devicename("js(\\d+)");
|
||||||
int joydev = -1;
|
|
||||||
int index = -1;
|
|
||||||
//for every joystick device in the directory listing...
|
//for every joystick device in the directory listing...
|
||||||
//(note, with devfs, only available devices are listed)
|
//(note, with devfs, only available devices are listed)
|
||||||
foreach (const QString &device, devices) {
|
foreach (const QString &device, devices) {
|
||||||
QString devpath = QString("%1/%2").arg(devdir, device);
|
if (devicename.indexIn(device) >= 0) {
|
||||||
debug_mesg("found a device file, %s\n", qPrintable(devpath));
|
int index = devicename.cap(1).toInt();
|
||||||
//try opening the device.
|
QString devpath = QString("%1/%2").arg(devdir, device);
|
||||||
joydev = open( qPrintable(devpath), O_RDONLY | O_NONBLOCK);
|
addJoyPad(index, devpath);
|
||||||
//if it worked, then we have a live joystick! Make sure it's properly
|
|
||||||
//setup.
|
|
||||||
if (joydev >= 0) {
|
|
||||||
devicename.indexIn(device);
|
|
||||||
index = devicename.cap(1).toInt();
|
|
||||||
JoyPad* joypad = joypads[index];
|
|
||||||
//if we've never seen this device before, make a new one!
|
|
||||||
if (joypad == 0) {
|
|
||||||
joypad = new JoyPad( index, joydev, this );
|
|
||||||
joypads.insert(index,joypad);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
debug_mesg("found previously open joypad with index %d, ignoring", index);
|
|
||||||
joypad->open(joydev);
|
|
||||||
}
|
|
||||||
//make this joystick device available.
|
|
||||||
available.insert(index,joypad);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
perror(qPrintable(devpath));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//when it's all done, rebuild the popup menu so it displays the correct
|
//when it's all done, rebuild the popup menu so it displays the correct
|
||||||
//information.
|
//information.
|
||||||
fillPopup();
|
fillPopup();
|
||||||
if(le) {
|
if (le) {
|
||||||
le->updateJoypadWidgets();
|
le->updateJoypadWidgets();
|
||||||
}
|
}
|
||||||
debug_mesg("done updating joydevs\n");
|
debug_mesg("done updating joydevs\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayoutManager::addJoyPad(int index) {
|
||||||
|
addJoyPad(index, QString("%1/js%2").arg(devdir, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayoutManager::addJoyPad(int index, const QString& devpath) {
|
||||||
|
debug_mesg("opening %s\n", qPrintable(devpath));
|
||||||
|
//try opening the device.
|
||||||
|
int joydev = open(qPrintable(devpath), O_RDONLY | O_NONBLOCK);
|
||||||
|
//if it worked, then we have a live joystick! Make sure it's properly
|
||||||
|
//setup.
|
||||||
|
if (joydev >= 0) {
|
||||||
|
JoyPad* joypad = joypads[index];
|
||||||
|
//if we've never seen this device before, make a new one!
|
||||||
|
if (joypad == 0) {
|
||||||
|
joypad = new JoyPad( index, joydev, this );
|
||||||
|
joypads.insert(index,joypad);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
debug_mesg("found previously open joypad with index %d, ignoring", index);
|
||||||
|
joypad->open(joydev);
|
||||||
|
}
|
||||||
|
//make this joystick device available.
|
||||||
|
available.insert(index,joypad);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
perror(qPrintable(devpath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayoutManager::removeJoyPad(int index) {
|
||||||
|
JoyPad *joypad = available[index];
|
||||||
|
if (joypad) {
|
||||||
|
joypad->close();
|
||||||
|
available.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
20
src/layout.h
20
src/layout.h
@ -17,6 +17,12 @@
|
|||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef WITH_LIBUDEV
|
||||||
|
#include <libudev.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
//a layout handles several joypads
|
//a layout handles several joypads
|
||||||
#include "joypad.h"
|
#include "joypad.h"
|
||||||
//for errors
|
//for errors
|
||||||
@ -66,7 +72,10 @@ class LayoutManager : public QObject {
|
|||||||
private slots:
|
private slots:
|
||||||
//when the user selects an item on the tray's popup menu
|
//when the user selects an item on the tray's popup menu
|
||||||
void layoutTriggered();
|
void layoutTriggered();
|
||||||
private:
|
private:
|
||||||
|
void addJoyPad(int index);
|
||||||
|
void addJoyPad(int index, const QString& devpath);
|
||||||
|
void removeJoyPad(int index);
|
||||||
//change to the given layout name and make all the necesary adjustments
|
//change to the given layout name and make all the necesary adjustments
|
||||||
void setLayoutName(const QString& name);
|
void setLayoutName(const QString& name);
|
||||||
//get the file name for a layout name
|
//get the file name for a layout name
|
||||||
@ -90,6 +99,15 @@ class LayoutManager : public QObject {
|
|||||||
|
|
||||||
QHash<int, JoyPad*> available;
|
QHash<int, JoyPad*> available;
|
||||||
QHash<int, JoyPad*> joypads;
|
QHash<int, JoyPad*> joypads;
|
||||||
|
|
||||||
|
#ifdef WITH_LIBUDEV
|
||||||
|
bool initUDev();
|
||||||
|
QSocketNotifier *udevNotifier;
|
||||||
|
struct udev *udev;
|
||||||
|
struct udev_monitor *monitor;
|
||||||
|
private slots:
|
||||||
|
void udevUpdate();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user