If we want to record multiple events, let's just specify multiple event nodes.
No need for a specific extra argument here.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
static inline void
usage(void)
{
- printf("Usage: %s [--help] [--multiple|--all] [--autorestart] [--output-file filename] [/dev/input/event0] [...]\n"
+ printf("Usage: %s [--help] [--all] [--autorestart] [--output-file filename] [/dev/input/event0] [...]\n"
"Common use-cases:\n"
"\n"
" sudo %s -o recording.yml\n"
" As above, but restarts after 2s of inactivity on the device.\n"
" Note, the output file is only the prefix.\n"
"\n"
- " sudo %s --multiple -o recording.yml /dev/input/event3 /dev/input/event4\n"
+ " sudo %s -o recording.yml /dev/input/event3 /dev/input/event4\n"
" Records the two devices into the same recordings file.\n"
"\n"
"For more information, see the %s(1) man page\n",
};
struct record_device *d, *tmp;
const char *output_arg = NULL;
- bool multiple = false, all = false, with_libinput = false;
+ bool all = false, with_libinput = false;
int ndevices;
int rc = EXIT_FAILURE;
case OPT_KEYCODES:
ctx.show_keycodes = true;
break;
- case OPT_MULTIPLE:
- multiple = true;
+ case OPT_MULTIPLE: /* deprecated */
break;
case OPT_ALL:
all = true;
}
}
- if (all && multiple) {
- fprintf(stderr,
- "Only one of --multiple and --all allowed.\n");
- goto out;
- }
-
if (ctx.timeout > 0 && output_arg == NULL) {
fprintf(stderr,
"Option --autorestart requires --output-file\n");
ndevices = argc - optind;
- if (multiple) {
- if (output_arg == NULL) {
- fprintf(stderr,
- "Option --multiple requires --output-file\n");
- goto out;
- }
-
- if (ndevices <= 1) {
- fprintf(stderr,
- "Option --multiple requires all device nodes on the commandline\n");
- goto out;
- }
-
- for (int i = ndevices; i > 0; i -= 1) {
- char *devnode = safe_strdup(argv[optind + i - 1]);
-
- if (!init_device(&ctx, devnode))
- goto out;
- }
- } else if (all) {
+ if (all) {
char **devices; /* NULL-terminated */
char **d;
if (output_arg == NULL) {
fprintf(stderr,
"Option --all requires --output-file\n");
+ rc = EXIT_INVALID_USAGE;
goto out;
}
}
strv_free(devices);
- } else {
- char *path;
-
- if (ndevices > 1) {
- fprintf(stderr, "More than one device, do you want --multiple?\n");
+ } else if (ndevices > 1) {
+ if (ndevices > 1 && output_arg == NULL) {
+ fprintf(stderr,
+ "Recording multiple devices requires --output-file\n");
+ rc = EXIT_INVALID_USAGE;
goto out;
}
+ for (int i = ndevices; i > 0; i -= 1) {
+ char *devnode = safe_strdup(argv[optind + i - 1]);
+
+ if (!init_device(&ctx, devnode))
+ goto out;
+ }
+ } else {
+ char *path;
+
path = ndevices <= 0 ? select_device() : safe_strdup(argv[optind++]);
if (path == NULL) {
goto out;
.SH NAME
libinput\-record \- record kernel events
.SH SYNOPSIS
-.B libinput record [options] [\fI/dev/input/event0\fB]
+.B libinput record [options] [\fI/dev/input/event0\fB [\fI/dev/input/event1\fB ...]]
.SH DESCRIPTION
.PP
The \fBlibinput record\fR tool records kernel events from a device and
The events recorded are independent of libinput itself, updating or
removing libinput will not change the event stream.
.SH OPTIONS
-If a device node is given, this tool opens that device node. Otherwise,
-a list of devices is presented and the user can select the device to record.
-If unsure, run without any arguments.
+If one or more device nodes are given, this tool opens those device nodes.
+Otherwise, a list of devices is presented and the user can select the device
+to record. If unsure, run without any arguments.
.TP 8
.B \-\-help
Print help
.B \-\-all
Record all \fI/dev/input/event*\fR devices available on the system. This
option should be used in exceptional cases only, the output file is almost
-always too noisy and replaying the recording may not be possible. Use
-\fB\-\-multiple\fR instead.
-This option requires that a \fB\-\-output-file\fR is specified and may not
-be used together with \fB\-\-multiple\fR.
+always too noisy and replaying the recording may not be possible.
+This option requires \fB\-\-output-file\fR and no device
+nodes may be provided on the commandline.
.TP 8
.B \-\-autorestart=s
Terminate the current recording after
.TP 8
.B \-\-output-file=filename.yml
.PD 1
-Specifies the output file to use. If \fB\-\-autorestart\fR or
-\fB\-\-multiple\fR is given, the filename is used as prefix only.
-.TP 8
-.B \-\-multiple
-Record multiple devices at once, see section
-.B RECORDING MULTIPLE DEVICES
-This option requires that a
-\fB\-\-output-file\fR is specified and that all devices to be recorded are
-given on the commandline.
+Specifies the output file to use. If \fB\-\-autorestart\fR is given,
+the filename is used as prefix only.
.TP 8
.B \-\-show\-keycodes
Show keycodes as-is in the recording. By default, common keys are obfuscated
.SH RECORDING MULTIPLE DEVICES
Sometimes it is necessary to record the events from multiple devices
simultaneously, e.g. when an interaction between a touchpad and a keyboard
-causes a bug. The \fB\-\-multiple\fR option records multiple devices with
+causes a bug. \fBlibinput record\fR records multiple devices with
an identical time offset, allowing for correct replay of the interaction.
.PP
-The \fB\-\-multiple\fR option requires that an output filename is given.
-This filename is used as prefix, with the event node number appended.
+If multiple devices are recorded, an output filename must be provided.
.PP
All devices to be recorded must be provided on the commandline, an example
invocation is:
-.B libinput record \-\-multiple \-o tap-bug /dev/input/event3 /dev/input/event7
+.B libinput record \-o tap-bug /dev/input/event3 /dev/input/event7
Note that when recording multiple devices, only the first device is printed
immediately, all other devices and their events are printed on exit.
import resource
import sys
import subprocess
-import time
+import tempfile
+from pathlib import Path
def _disable_coredump():
self.run_command_unrecognized_option(['--version'])
+class TestRecord(TestLibinputTool):
+ subtool = 'record'
+
+ def setUp(self):
+ self.tmpdir = tempfile.TemporaryDirectory()
+ self.outfile = Path(self.tmpdir.name, 'record.out')
+
+ def tearDown(self):
+ self.tmpdir.cleanup()
+
+ def test_args(self):
+ self.run_command_success(['--help'])
+ self.run_command_success(['--show-keycodes'])
+ self.run_command_success(['--with-libinput'])
+
+ def test_multiple_deprecated(self):
+ # this arg is deprecated and a noop
+ self.run_command_success(['--multiple'])
+
+ def test_all(self):
+ self.run_command_success(['--all', '-o', self.outfile])
+
+ def test_autorestart(self):
+ self.run_command_success(['--autorestart=2'])
+
+ def test_outfile(self):
+ self.run_command_success(['-o', self.outfile])
+ self.run_command_success(['--output-file', self.outfile])
+ self.run_command_success(['--output-file={}'.format(self.outfile)])
+
+ def test_device_single(self):
+ self.run_command_success(['/dev/input/event0'])
+
+ def test_device_multiple(self):
+ self.run_command_success(['-o', self.outfile, '/dev/input/event0', '/dev/input/event1'])
+
+
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Verify a libinput tool\'s option parsing')
parser.add_argument('--tool-path', metavar='/path/to/builddir/libinput',