summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-08-14 17:35:13 +0100
committerFrediano Ziglio <fziglio@redhat.com>2015-08-14 17:35:13 +0100
commit936104345884610f0af36b3cb5831ad9fafa0892 (patch)
tree6fc052e1c2080825e4de02c520f9700b2995e61a
parent392ca7209559f030500c13b9ebc9779c58ecbbb2 (diff)
Rewrite output formatHEADmaster
Use text format instead of binary one. Much easier to debug and you can add comments too. Do not use XI constants for the record. Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-rw-r--r--play.cpp10
-rw-r--r--rec.cpp177
-rw-r--r--rec.h27
-rw-r--r--record.cpp22
4 files changed, 164 insertions, 72 deletions
diff --git a/play.cpp b/play.cpp
index 8ee5b02..b1157e0 100644
--- a/play.cpp
+++ b/play.cpp
@@ -72,10 +72,10 @@ void play(const char *fn, Window win)
ev.xkey.root = DefaultRootWindow(dpy);
switch (rec.get_type()) {
- case XI_KeyPress:
+ case Record::KeyDown:
ev.type = KeyPress;
goto keyboard;
- case XI_KeyRelease:
+ case Record::KeyUp:
ev.type = KeyRelease;
keyboard:
if (rec.get_field(Record::Window, 0) != target_win)
@@ -91,19 +91,19 @@ void play(const char *fn, Window win)
XSendEvent(dpy, win, False, 0, &ev);
XFlush(dpy);
break;
- case XI_ButtonPress:
+ case Record::ButtonDown:
if (rec.get_field(Record::Window, 0) != target_win)
break;
xdo_mousedown(xdo, 0, rec.get_field(Record::Detail));
break;
- case XI_ButtonRelease:
+ case Record::ButtonUp:
if (rec.get_field(Record::Window, 0) != target_win)
break;
xdo_mouseup(xdo, 0, rec.get_field(Record::Detail));
break;
- case XI_Motion:
+ case Record::MouseMotion:
if (rec.get_field(Record::Window, 0) != target_win)
break;
xdo_mousemove_relative_to_window(xdo, win, rec.get_field(Record::X), rec.get_field(Record::Y));
diff --git a/rec.cpp b/rec.cpp
index 70c37cf..7f4fd83 100644
--- a/rec.cpp
+++ b/rec.cpp
@@ -1,9 +1,67 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "rec.h"
+#define FIELD_TYPES \
+ FIELD(X, "x") \
+ FIELD(Y, "y") \
+ FIELD(State, "state") \
+ FIELD(Detail, "detail") \
+ FIELD(Window, "win") \
+ FIELD(Width, "w") \
+ FIELD(Height, "h") \
+ FIELD(Keysym, "keysym")
+
+const char *Record::get_field_name(FieldsType type)
+{
+#define FIELD(t,n) case t: return n;
+ switch (type) {
+ FIELD_TYPES
+ }
+#undef FIELD
+ return "";
+}
+
+Record::FieldsType Record::get_field_type(const char *name)
+{
+#define FIELD(t,n) if (strcmp(name, n) == 0) return t;
+ FIELD_TYPES
+#undef FIELD
+ fprintf(stderr, "Invalid field type %s\n", name);
+ exit(EXIT_FAILURE);
+}
+
+#define RECORD_TYPES \
+ RECORD(KeyDown, "key_down") \
+ RECORD(KeyUp, "key_up") \
+ RECORD(ButtonDown, "button_down") \
+ RECORD(ButtonUp, "button_up") \
+ RECORD(MouseMotion, "mouse_move") \
+ RECORD(WindowMove, "window_move") \
+ RECORD(TargetWindow, "target_window")
+
+const char *Record::get_record_name(RecordType type)
+{
+#define RECORD(t,n) case t: return n;
+ switch (type) {
+ RECORD_TYPES
+ }
+#undef RECORD
+ return "";
+}
+
+Record::RecordType Record::get_record_type(const char *name)
+{
+#define RECORD(t,n) if (strcmp(name, n) == 0) return t;
+ RECORD_TYPES
+#undef RECORD
+ fprintf(stderr, "Invalid record type\n");
+ exit(EXIT_FAILURE);
+}
+
RecordsFile::RecordsFile(FILE *_f):
f(_f)
{
@@ -14,91 +72,100 @@ RecordsFile::RecordsFile(FILE *_f):
}
ReadRecordsFile::ReadRecordsFile(const char *fn):
- RecordsFile(fopen(fn, "rb")),
- eof(false), next(0)
+ RecordsFile(fopen(fn, "r")),
+ eof(false)
{
- get_number();
+ get_line();
}
-Record ReadRecordsFile::get()
-{
- get_number(START_RECORD);
- unsigned type = get_number();
- unsigned time = get_number();
-
- Record rec(type, time);
- for (;;) {
- type = get_number();
- if (type == END_RECORD)
- return rec;
- if (type != FIELD) {
- fprintf(stderr, "expected a field!\n");
- exit(EXIT_FAILURE);
- }
- type = get_number();
- if (type >= Record::MAX_FIELD) {
- fprintf(stderr, "invalid field type!\n");
- exit(EXIT_FAILURE);
- }
- rec.set_field((Record::FieldsType) type, get_number());
- }
-}
+#define SPACES " \t\v\r\n"
-unsigned
-ReadRecordsFile::get_number()
+void ReadRecordsFile::get_line()
{
if (eof) {
fprintf(stderr, "trying to read past EOF\n");
exit(EXIT_FAILURE);
}
- unsigned res = next;
- if (fread(&next, sizeof(next), 1, f) != 1) {
- if (!feof(f)) {
- fprintf (stderr, "end of file\n");
- exit(EXIT_FAILURE);
- }
- eof = true;
+ while (fgets(next_line, sizeof(next_line), f)) {
+ const char *p = next_line;
+
+ // skip initial spaces
+ p += strspn(p, SPACES);
+
+ // detect comments
+ if (!*p || *p == '#')
+ continue;
+
+ // got line
+ return;
}
- return res;
+
+ if (!feof(f)) {
+ fprintf (stderr, "error reading input file\n");
+ exit(EXIT_FAILURE);
+ }
+ eof = true;
}
-void
-ReadRecordsFile::get_number(unsigned n)
+Record ReadRecordsFile::get()
{
- if (get_number() != n) {
- fprintf (stderr, "expected %u in file position %lx\n", n, (unsigned long) ftell(f));
+ char *line = next_line;
+
+ // skip initial spaces
+ line += strspn(line, SPACES);
+
+ // read time and command
+ int got = 0;
+ unsigned time;
+ char cmd[64];
+ if (sscanf(line, "@%u %60[^" SPACES "]%n", &time, cmd, &got) < 2) {
+ fprintf (stderr, "error reading time: %s\n", next_line);
exit(EXIT_FAILURE);
}
-}
+ Record::RecordType type = Record::get_record_type(cmd);
+ Record rec(type, time);
+
+ char *p = line + got;
+ for (;;) {
+ char field[64];
+ unsigned value;
+
+ p += strspn(p, SPACES);
+ if (!*p)
+ break;
+ got = 0;
+ if (sscanf(p, "%60[^:]:%u%n", field, &value, &got) < 2 || got == 0) {
+ fprintf(stderr, "expected a field: %s\n", next_line);
+ exit(EXIT_FAILURE);
+ }
+ p += got;
+
+ Record::FieldsType type = Record::get_field_type(field);
+ rec.set_field(type, value);
+ }
+ get_line();
+ return rec;
+}
+
WriteRecordsFile::WriteRecordsFile(const char *fn):
- RecordsFile(fopen(fn, "wb"))
+ RecordsFile(fopen(fn, "w"))
{
}
void WriteRecordsFile::put(const Record &rec)
{
- add_number(START_RECORD);
- add_number(rec.get_type());
- add_number(rec.get_time());
+ fprintf(f, "@%u %s", rec.get_time(), rec.get_record_name(rec.get_type()));
for (unsigned n = 0; n < Record::MAX_FIELD; ++n) {
Record::FieldsType type = (Record::FieldsType) n;
if (!rec.has_field(type))
continue;
- add_number(FIELD);
- add_number(type);
- add_number(rec.get_field(type));
+ fprintf(f, " %s:%u", rec.get_field_name(type), rec.get_field(type));
}
- add_number(END_RECORD);
-}
-
-void WriteRecordsFile::add_number(unsigned num)
-{
- fwrite(&num, sizeof(num), 1, f);
+ fprintf(f, "\n");
}
-
diff --git a/rec.h b/rec.h
index 3406f02..ae63b79 100644
--- a/rec.h
+++ b/rec.h
@@ -5,13 +5,23 @@ class Record
{
public:
enum FieldsType { Nothing, X, Y, State, Detail, Window, Width, Height, Keysym, MAX_FIELD };
- enum RecordType { WindowMove = 256, TargetWindow };
- Record(unsigned _type, unsigned _time):
+ static const char *get_field_name(FieldsType type);
+ static FieldsType get_field_type(const char *name);
+
+ enum RecordType {
+ KeyDown, KeyUp,
+ ButtonDown, ButtonUp, MouseMotion,
+ WindowMove = 256, TargetWindow
+ };
+ static const char *get_record_name(RecordType type);
+ static RecordType get_record_type(const char *name);
+
+ Record(RecordType _type, unsigned _time):
fields_present(0), type(_type), time(_time)
{
}
~Record() { }
- unsigned get_type() const { return type; }
+ RecordType get_type() const { return type; }
unsigned get_time() const { return time; }
bool has_field(FieldsType type) const { return ((fields_present >> type) & 1) != 0; }
unsigned get_field(FieldsType type) const {
@@ -31,7 +41,8 @@ public:
fields[type] = value;
}
private:
- unsigned type, time;
+ RecordType type;
+ unsigned time;
unsigned fields_present;
unsigned fields[MAX_FIELD];
};
@@ -42,7 +53,6 @@ protected:
RecordsFile(FILE *_f);
~RecordsFile() { fclose(f); }
- enum { START_RECORD = 1, END_RECORD = 2, FIELD = 3 };
FILE *f;
};
@@ -53,11 +63,10 @@ public:
bool at_eof() const { return eof; }
Record get();
private:
- unsigned get_number();
- void get_number(unsigned num);
+ void get_line();
bool eof;
- unsigned next;
+ char next_line[1024];
};
class WriteRecordsFile: public RecordsFile
@@ -65,7 +74,5 @@ class WriteRecordsFile: public RecordsFile
public:
WriteRecordsFile(const char *fn);
void put(const Record &rec);
-private:
- void add_number(unsigned num);
};
diff --git a/record.cpp b/record.cpp
index 92da9e6..80c3846 100644
--- a/record.cpp
+++ b/record.cpp
@@ -107,6 +107,24 @@ DoRecord::record_move()
file.put(r);
}
+static Record::RecordType get_record_type(int evtype)
+{
+ switch (evtype) {
+ case XI_KeyPress:
+ return Record::KeyDown;
+ case XI_KeyRelease:
+ return Record::KeyUp;
+ case XI_ButtonPress:
+ return Record::ButtonDown;
+ case XI_ButtonRelease:
+ return Record::ButtonUp;
+ case XI_Motion:
+ return Record::MouseMotion;
+ }
+ fprintf (stderr, "unhandled event\n");
+ exit(EXIT_FAILURE);
+}
+
void
DoRecord::handle_xi_mouse(XIDeviceEvent* ev)
{
@@ -121,7 +139,7 @@ DoRecord::handle_xi_mouse(XIDeviceEvent* ev)
if (!inside)
return;
- Record r(ev->evtype, get_record_time());
+ Record r(get_record_type(ev->evtype), get_record_time());
r.set_field(Record::X, mouse_x - rc.x);
r.set_field(Record::Y, mouse_y - rc.y);
r.set_field(Record::State, ev->mods.effective);
@@ -136,7 +154,7 @@ DoRecord::handle_xi_mouse(XIDeviceEvent* ev)
void
DoRecord::handle_xi_keys(XIDeviceEvent* ev)
{
- Record r(ev->evtype, get_record_time());
+ Record r(get_record_type(ev->evtype), get_record_time());
r.set_field(Record::X, ev->root_x - rc.x);
r.set_field(Record::Y, ev->root_y - rc.y);
r.set_field(Record::State, ev->mods.effective);