diff --git a/NEWS b/NEWS index 780829e..9732b5d 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ xboxdrv 0.7.1 - (??/???/2011) * fixed --dpad-only * added support for Playstation button names (triangle, circle, square, cross, L1, L2, L3, R1, R2, R3) +* added --on-connect and --on-disconnect to xboxdrv --daemon xboxdrv 0.7.0 - (28/Jan/2011) diff --git a/TODO b/TODO index 10df7dc..b29d742 100644 --- a/TODO +++ b/TODO @@ -56,6 +56,7 @@ Stuff to do before 0.7.1 release: * fix device name of mimic_xpad + * allow multiple controllers in non-daemon mode * improve output in daemon mode, when --quiet is not given print the @@ -89,11 +90,6 @@ Stuff to do before 0.7.1 release: * remember controllers that couldn't be used when all slots where full and use them when a slot got free -* implement --on-connect and --on-disconnect for the daemon - - maybe have a more general event interface that allows to run stuff - on configuration changes, controller plug-ins, etc. (notifiy area as example) - - also supply useful information as argument - * improve output on which uinput devices are created (even with udev there doesn't seem to be a bullet proof way to detect what gets created) @@ -105,6 +101,8 @@ Stuff to do before 0.7.1 release: Stuff to do before 0.7.2 release: ================================= +* add extra arguments to --on-connect and --on-disconnect (controller name, usb path, etc.) + * boost::lexical_cast<> error messages are useless, make some better ones * couldn't convert 'XK_Page_Up' to enum, not a member of X11Keysym diff --git a/src/command_line_options.cpp b/src/command_line_options.cpp index f35988f..706a848 100644 --- a/src/command_line_options.cpp +++ b/src/command_line_options.cpp @@ -180,8 +180,8 @@ CommandLineParser::init_argp() .add_option(OPTION_DAEMON, 'D', "daemon", "", "Run as daemon") .add_option(OPTION_DAEMON_DETACH, 0, "detach", "", "Detach the daemon from the current shell") .add_option(OPTION_DAEMON_PID_FILE, 0, "pid-file", "FILE", "Write daemon pid to FILE") - .add_option(OPTION_DAEMON_ON_CONNECT, 0, "on-connect", "FILE", "Launch EXE when a new controller is connected", false) - .add_option(OPTION_DAEMON_ON_DISCONNECT, 0, "on-disconnect", "FILE", "Launch EXE when a controller is disconnected", false) + .add_option(OPTION_DAEMON_ON_CONNECT, 0, "on-connect", "FILE", "Launch EXE when a new controller is connected") + .add_option(OPTION_DAEMON_ON_DISCONNECT, 0, "on-disconnect", "FILE", "Launch EXE when a controller is disconnected") .add_newline() .add_text("Device Options: ") diff --git a/src/helper.cpp b/src/helper.cpp index c4f17de..8f0bbdb 100644 --- a/src/helper.cpp +++ b/src/helper.cpp @@ -18,12 +18,15 @@ #include "helper.hpp" +#include <assert.h> #include <boost/format.hpp> #include <boost/tokenizer.hpp> #include <boost/lexical_cast.hpp> #include <stdio.h> #include <sys/time.h> #include <sys/ioctl.h> +#include <unistd.h> +#include <errno.h> #include <iostream> #include "raise_exception.hpp" @@ -175,5 +178,34 @@ int get_terminal_width() return w.ws_col; } } + +void spawn_exe(const std::string& arg0) +{ + std::vector<std::string> args; + args.push_back(arg0); + spawn_exe(args); +} + +void spawn_exe(const std::vector<std::string>& args) +{ + assert(!args.empty()); + + pid_t pid = fork(); + if (pid == 0) + { + char** argv = static_cast<char**>(malloc(sizeof(char*) * (args.size() + 1))); + for(size_t i = 0; i < args.size(); ++i) + { + argv[i] = strdup(args[i].c_str()); + } + argv[args.size()] = NULL; + + if (execvp(args[0].c_str(), argv) == -1) + { + log_error(args[0] << ": exec failed: " << strerror(errno)); + _exit(EXIT_FAILURE); + } + } +} /* EOF */ diff --git a/src/helper.hpp b/src/helper.hpp index 237ba04..5dd78e6 100644 --- a/src/helper.hpp +++ b/src/helper.hpp @@ -21,6 +21,7 @@ #include <boost/function.hpp> #include <stdint.h> +#include <vector> int hexstr2int(const std::string& str); @@ -73,6 +74,8 @@ float to_float_no_range_check(int value, int min, int max); int from_float(float value, int min, int max); int get_terminal_width(); +void spawn_exe(const std::vector<std::string>& args); +void spawn_exe(const std::string& arg0); #endif diff --git a/src/xboxdrv.cpp b/src/xboxdrv.cpp index d2fb3c9..a29d1d0 100644 --- a/src/xboxdrv.cpp +++ b/src/xboxdrv.cpp @@ -600,7 +600,7 @@ Xboxdrv::run_daemon(const Options& opts) if (!opts.detach) { - XboxdrvDaemon daemon; + XboxdrvDaemon daemon(opts); daemon.run(opts); } else @@ -637,7 +637,7 @@ Xboxdrv::run_daemon(const Options& opts) } else { - XboxdrvDaemon daemon; + XboxdrvDaemon daemon(opts); daemon.run(opts); } } diff --git a/src/xboxdrv_daemon.cpp b/src/xboxdrv_daemon.cpp index f17004e..e505e95 100644 --- a/src/xboxdrv_daemon.cpp +++ b/src/xboxdrv_daemon.cpp @@ -87,8 +87,9 @@ bool get_usb_path(udev_device* device, int* bus, int* dev) } } // namespace - -XboxdrvDaemon::XboxdrvDaemon() : + +XboxdrvDaemon::XboxdrvDaemon(const Options& opts) : + m_opts(opts), m_udev(0), m_monitor(0), m_controller_slots(), @@ -122,6 +123,8 @@ XboxdrvDaemon::cleanup_threads() delete i->thread; i->thread = 0; count += 1; + + on_disconnect(); } } } @@ -495,6 +498,8 @@ XboxdrvDaemon::launch_xboxdrv(const XPadDevice& dev_type, const Options& opts, thread->start_thread(opts); slot.thread = thread.release(); + on_connect(); + log_info("launched XboxdrvThread for " << boost::format("%03d:%03d") % static_cast<int>(busnum) % static_cast<int>(devnum) @@ -519,4 +524,18 @@ XboxdrvDaemon::get_free_slot_count() const return slot_count; } +void +XboxdrvDaemon::on_connect() +{ + log_info("launching connect script"); + spawn_exe(m_opts.on_connect); +} + +void +XboxdrvDaemon::on_disconnect() +{ + log_info("launching disconnect script"); + spawn_exe(m_opts.on_disconnect); +} + /* EOF */ diff --git a/src/xboxdrv_daemon.hpp b/src/xboxdrv_daemon.hpp index d2127cd..8d38a8e 100644 --- a/src/xboxdrv_daemon.hpp +++ b/src/xboxdrv_daemon.hpp @@ -31,6 +31,7 @@ struct XPadDevice; class XboxdrvDaemon { private: + const Options& m_opts; struct udev* m_udev; struct udev_monitor* m_monitor; @@ -84,7 +85,7 @@ private: std::auto_ptr<UInput> m_uinput; public: - XboxdrvDaemon(); + XboxdrvDaemon(const Options& opts); ~XboxdrvDaemon(); void run(const Options& opts); @@ -107,6 +108,9 @@ private: ControllerSlot& slot); int get_free_slot_count() const; + void on_connect(); + void on_disconnect(); + private: XboxdrvDaemon(const XboxdrvDaemon&); XboxdrvDaemon& operator=(const XboxdrvDaemon&);