tolga9009 / sidewinderd

Linux support for Microsoft SideWinder X4 / X6 and Logitech G103 / G105 / G710+.

Home Page:http://cevel.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

store config files in standard location

nikmartin opened this issue · comments

./sidewinderd is a nonstandard location for config files the XDG spec states that ~/.config/sidewinderd is the proper place

I will patch and do a pull request

Thank you for the suggestion! I've already looked into a solution for it. We need to read $XDG_CONFIG_HOME using std::getenv and append it to workdir in sidewinderd.cpp between lines 293 - 300:

/* creating sidewinderd directory in user's home directory */

/* user's home directory (user is defined in /etc/sidewinderd.conf) */
std::string workdir = pw->pw_dir;

/* check for $XDG_CONFIG_HOME here, using std::getenv.
 * If empty, or not set, default to "/.config". Append result to workdir.
 */

/* append sidewinderd-specific config folder */
workdir.append("/.sidewinderd");

/* create folder, if necessary */
mkdir(workdir.c_str(), S_IRWXU);

I think that's a way to do it. If you have any alternative solutions, please feel free to share. I will patch it this weekend.

Cheers,
Tolga

Yes, that is one variable to check, but be aware it doesn't seem to be set very often. It is up to each distribution to set that. On debian for example, it is NOT set. If not set, the next step is to check if workdir.append(".config") exists, and if so, create sidewinderd there.

One thing I cannot figure out from the code is once workdir is set, how does anything in keyboard.cpp find the xml macro files? workdir is only set once on startup, and the files are created there, but recording macros magically knows how to find the xml files. In debugging sidewinderd, it records macros fine, but is not playing them back. I'm not getting file not found errors, but no keys are sent.

About the XML macro files: after creating the .sidewinder config (workdir) directory, calling chdir(workdir) changes the daemon's working directory to that path. So we're able to use relative paths.

Next, the daemon is listening to the keyboard's interface. It is efficiently polling for keypresses. If a macro key has been pressed, Keyboard::process_input() (line 263 in keyboard.cpp) is creating a new object Key (key.hpp).

Key::GetMacroPath() (line 14 in key.cpp) then returns an XML file. It is using int profile (active profile LED) and kd->Index (pressed macro key; struct KeyData *kd) to build the XML path.

About the playback issue: it is a major issue, I have been working on countless times. Are you using the latest version?

The core problem: uinput (needed to send keypresses to the system from user-land) needs about 1 - 5 seconds time for initialization. Because of the long initialization time, I can't do the following:

Listen to keyboard -> Get key -> Create uinput device -> Play macro -> Destroy uinput device

Due to the long initialization time and VirtualInput::create_uidev() beeing non-blocking, Keyboard::play_macro() skips the first seconds of each XML file, leading to a laggy, unwanted behaviour.

Instead, I need to create the uinput device as soon as possible and need a pointer pointing to it, so I don't have to create and destroy it all the time. Something like this:

  1. Create uinput device during keyboard constructor
  2. Listen to keyboard -> Get key -> Play macro
  3. Destroy uinput device on keyboard destructor (when program exits or keyboard gets disconnected)

In the second example, I'm creating and destroying the uinput device only once, critically reducing initialization time. However, there seems to be a problem with passing the pointer. Extremely weird things are happening to the uinput device pointer, after calling ioctl(uifd, UI_DEV_CREATE). I've tried using shared_ptr and unique_ptr, but couldn't fix the issue. I have to admit, that this is my first C++ project and still couldn't find a definitive fix for this. I'm working on it.