summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2016-06-27 14:41:45 +1000
committerBenjamin Tissoires <benjamin.tissoires@gmail.com>2016-07-01 11:25:37 +0200
commitbdae638e12c8fa1a1d6cc9d22cd654cb31a4d9b4 (patch)
tree8516dbd399c1e1e3e83556fb9b374ccf4469a659
parenteafbf5dcc647958eba85f9aa57d2c3f6fb915ea2 (diff)
tools: make evemu-play create devices and re-run recordings
$ evemu-play touchpad.evemu will create the device from the recording and prompt the user to hit enter before replaying the sequence. Re-playing the same sequence multiple times just requires hitting enter again. https://bugs.freedesktop.org/show_bug.cgi?id=96688 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
-rw-r--r--tools/evemu-device.txt3
-rw-r--r--tools/evemu-play.c138
2 files changed, 122 insertions, 19 deletions
diff --git a/tools/evemu-device.txt b/tools/evemu-device.txt
index 081355f..9f3c86b 100644
--- a/tools/evemu-device.txt
+++ b/tools/evemu-device.txt
@@ -12,6 +12,7 @@ SYNOPSIS
evemu-device [description-file]
evemu-play /dev/input/eventX < event-sequence
+ evemu-play event-sequence.txt
evemu-event /dev/input/eventX [--sync] --type <type> --code <code> --value <value>
@@ -25,6 +26,8 @@ stdout.
evemu-play replays the event sequence given on stdin through the input
device. The event sequence must be in the form created by evemu-record(1).
+If the argument is a file containing a recording, evemu-play creates the device
+and prompts the user for an interactive replay of the events.
evemu-event plays exactly one event with the current time. If *--sync* is
given, evemu-event generates an *EV_SYN* event after the event. The event
diff --git a/tools/evemu-play.c b/tools/evemu-play.c
index fe43f4d..989d973 100644
--- a/tools/evemu-play.c
+++ b/tools/evemu-play.c
@@ -45,42 +45,53 @@
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
-/*
- * Finds the newly created device node and holds it open.
- */
-static void hold_device(struct evemu_device *dev)
+static int open_evemu_device(struct evemu_device *dev)
{
- char data[256];
- int ret;
int fd;
const char *device_node = evemu_get_devnode(dev);
if (!device_node) {
fprintf(stderr, "can not determine device node\n");
- return;
+ return -1;
}
- fd = open(device_node, O_RDONLY);
+ fd = open(device_node, O_RDWR);
if (fd < 0) {
fprintf(stderr, "error %d opening %s: %s\n",
errno, device_node, strerror(errno));
- return;
+ return -1;
}
fprintf(stdout, "%s: %s\n", evemu_get_name(dev), device_node);
fflush(stdout);
+ return fd;
+}
+
+static void open_and_hold_device(struct evemu_device *dev)
+{
+ char data[256];
+ int ret;
+ int fd;
+
+ fd = open_evemu_device(dev);
+ if (fd < 0)
+ return;
+
while ((ret = read(fd, data, sizeof(data))) > 0)
;
close(fd);
}
-static int evemu_device(FILE *fp)
+static struct evemu_device* create_device(FILE *fp)
{
struct evemu_device *dev;
int ret = -ENOMEM;
+ int saved_errno;
dev = evemu_new(NULL);
if (!dev)
@@ -98,13 +109,29 @@ static int evemu_device(FILE *fp)
ret = evemu_create_managed(dev);
if (ret < 0)
goto out;
- hold_device(dev);
- evemu_destroy(dev);
out:
+ if (ret && dev) {
+ saved_errno = errno;
+ evemu_destroy(dev);
+ dev = NULL;
+ errno = saved_errno;
+ }
+ return dev;
+}
+
+static int evemu_device(FILE *fp)
+{
+ struct evemu_device *dev;
+
+ dev = create_device(fp);
+ if (dev == NULL)
+ return -1;
+
+ open_and_hold_device(dev);
evemu_delete(dev);
- return ret;
+ return 0;
}
static int device(int argc, char *argv[])
@@ -129,24 +156,97 @@ static int device(int argc, char *argv[])
return 0;
}
+static int play_from_stdin(int fd)
+{
+ int ret;
+
+ ret = evemu_play(stdin, fd);
+
+ if (ret != 0)
+ fprintf(stderr, "error: could not replay device\n");
+
+ return ret;
+}
+
+static int play_from_file(int recording_fd)
+{
+ FILE *fp;
+ struct evemu_device *dev = NULL;
+ int fd;
+
+ fp = fdopen(recording_fd, "r");
+ if (!fp) {
+ fprintf(stderr, "error: could not open file (%m)\n");
+ return -1;
+ }
+
+ dev = create_device(fp);
+ if (!dev) {
+ fprintf(stderr, "error: could not create device: %m\n");
+ fclose(fp);
+ return -1;
+ }
+
+ fd = open_evemu_device(dev);
+ if (fd < 0)
+ goto out;
+
+ while (1) {
+ int ret;
+ char line[32];
+
+ printf("Hit enter to start replaying");
+ fflush(stdout);
+ fgets(line, sizeof(line), stdin);
+
+ fseek(fp, 0, SEEK_SET);
+ ret = evemu_play(fp, fd);
+ if (ret != 0) {
+ fprintf(stderr, "error: could not replay device\n");
+ break;
+ }
+ }
+
+out:
+ evemu_delete(dev);
+ fclose(fp);
+ close(fd);
+ return 0;
+}
+
static int play(int argc, char *argv[])
{
int fd;
+ struct stat st;
if (argc != 2) {
- fprintf(stderr, "Usage: %s <device>\n", argv[0]);
+ fprintf(stderr, "Usage: %s <device>|<recording>\n", argv[0]);
fprintf(stderr, "\n");
- fprintf(stderr, "Event data is read from standard input.\n");
+ fprintf(stderr, "If the argument is an input event node,\n"
+ "event data is read from standard input.\n");
+ fprintf(stderr, "If the argument is an evemu recording,\n"
+ "the device is created and the event data is"
+ "read from the same device.\n");
return -1;
}
- fd = open(argv[1], O_WRONLY);
+
+ fd = open(argv[1], O_RDWR);
if (fd < 0) {
- fprintf(stderr, "error: could not open device (%m)\n");
+ fprintf(stderr, "error: could not open file or device (%m)\n");
return -1;
}
- if (evemu_play(stdin, fd)) {
- fprintf(stderr, "error: could not describe device\n");
+
+ if (fstat(fd, &st) == -1) {
+ fprintf(stderr, "error: failed to look at file (%m)\n");
+ return -1;
}
+
+ if (S_ISCHR(st.st_mode))
+ play_from_stdin(fd);
+ else
+ play_from_file(fd);
+
+
close(fd);
return 0;
}