diff --git a/capture.c b/capture.c index 04ed6fc..8253022 100644 --- a/capture.c +++ b/capture.c @@ -14,12 +14,12 @@ static char* KEYBOARD = "k"; static char* MOUSE = "m"; -int dump_event(struct timespec* start, int fd, char* type); +int dump_event(struct timespec* start, struct input_event* event, char* type); int event_content_keyboard(char* buffer, int buffer_size, struct input_event* event); int event_content_mouse(char* buffer, int buffer_size, struct input_event* event); -int stream_events(char* mouse_path, char* keyboard_path); +int stream_events(char* mouse_path, char* keyboard_path, int hotkey_scancode); static inline void timespec_diff(struct timespec* a, struct timespec* b, struct timespec* result) { result->tv_sec = a->tv_sec - b->tv_sec; @@ -29,32 +29,44 @@ static inline void timespec_diff(struct timespec* a, struct timespec* b, struct result->tv_nsec += 1000000000L; } } + +static inline void timeval_diff(struct timeval* a, struct timeval* b, struct timeval* result) { + result->tv_sec = a->tv_sec - b->tv_sec; + result->tv_usec = a->tv_usec - b->tv_usec; + if (result->tv_usec < 0) { + --result->tv_sec; + result->tv_usec += 1000000L; + } +} + +static inline void time_diff(struct timeval* a, struct timespec* b, struct timeval* result) { + result->tv_sec = a->tv_sec - b->tv_sec; + result->tv_usec = a->tv_usec - (b->tv_nsec / 1000); + if (result->tv_usec < 0) { + --result->tv_sec; + result->tv_usec += 1000000L; + } +} -int dump_event(struct timespec* start, int fd, char* type) { - struct input_event event; +int dump_event(struct timespec* start, struct input_event* event, char* type) { struct timespec now; struct timespec diff; char content_buffer[CONTENT_BUFFER_SIZE]; - int result = read(fd, &event, sizeof(struct input_event)); - if(result < 0) { - fprintf(stderr, "Failed to read an event: %d", errno); - return 1; - } - clock_gettime(CLOCK_MONOTONIC, &now); timespec_diff(&now, start, &diff); + // time_diff(&(event.time), start, &diff); if(type == MOUSE) { - if(event_content_mouse(content_buffer, CONTENT_BUFFER_SIZE, &event)) { + if(event_content_mouse(content_buffer, CONTENT_BUFFER_SIZE, event)) { return 1; } } else if(type == KEYBOARD) { // Ignore all but EV_KEY events on keyboard, they have no useful content. - if(event.type != EV_KEY) { + if(event->type != EV_KEY) { return 0; } - if(event_content_keyboard(content_buffer, CONTENT_BUFFER_SIZE, &event)) { + if(event_content_keyboard(content_buffer, CONTENT_BUFFER_SIZE, event)) { return 1; } } else { @@ -98,6 +110,7 @@ int event_content_mouse(char* buffer, int buffer_size, struct input_event* event } int main(int argc, char* argv[]) { + int hotkey_scancode; if(argc < 2) { fprintf(stderr, "You must specify a mouse input to track like /dev/input/mouse1."); exit(EXIT_FAILURE); @@ -106,15 +119,25 @@ int main(int argc, char* argv[]) { fprintf(stderr, "You must specify a keyboard input to track like /dev/input/event3. If you're not sure which to use read through /proc/bus/input/devices and look for 'Handlers=eventX'"); exit(EXIT_FAILURE); } - int result = stream_events(argv[1], argv[2]); + if(argc < 4) { + fprintf(stderr, "You must specify a character to indicate when to start and stop capture. 53 for 'z'.\n"); + exit(EXIT_FAILURE); + } + int matched = sscanf(argv[3], "%d", &hotkey_scancode); + if(matched != 1) { + fprintf(stderr, "Failed to read hotkey scancode.\n"); + exit(EXIT_FAILURE); + } + int result = stream_events(argv[1], argv[2], hotkey_scancode); exit(result); } -int stream_events(char* mouse_path, char* keyboard_path) { +int stream_events(char* mouse_path, char* keyboard_path, int hotkey_scancode) { int keyboard_fd, mouse_fd; struct timespec start; - struct epoll_event event, events[MAX_EVENTS]; + struct epoll_event e_event, events[MAX_EVENTS]; + int has_seen_hotkey = 0; int running = 1; int epoll_fd = epoll_create1(0); if(epoll_fd < 0) { @@ -135,36 +158,54 @@ int stream_events(char* mouse_path, char* keyboard_path) { else { fprintf(stderr, "%s open OK\n", keyboard_path); } - event.events = EPOLLIN; + e_event.events = EPOLLIN; - event.data.fd = keyboard_fd; - if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, keyboard_fd, &event)) { + e_event.data.fd = keyboard_fd; + if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, keyboard_fd, &e_event)) { fprintf(stderr, "Failed to add keyboard file descriptor\n"); close(epoll_fd); return 1; } - event.data.fd = mouse_fd; - if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mouse_fd, &event)) { + e_event.data.fd = mouse_fd; + if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mouse_fd, &e_event)) { fprintf(stderr, "Failed to add mouse file descriptor\n"); close(epoll_fd); return 1; } - fprintf(stderr, "Waiting for events\n"); - clock_gettime(CLOCK_MONOTONIC, &start); + fprintf(stderr, "Waiting for hotkey\n"); + struct input_event i_event; while(running) { int event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); char* type; for(int i = 0; i < event_count; i++) { + int result = read(events[i].data.fd, &i_event, sizeof(struct input_event)); + if(result < 0) { + fprintf(stderr, "Failed to read an event: %d", errno); + return 1; + } + if(events[i].data.fd == keyboard_fd) { type = KEYBOARD; + if(i_event.type == EV_KEY && i_event.code == hotkey_scancode && i_event.value == 1) { + if(has_seen_hotkey) { + fprintf(stderr, "Stop capture\n"); + return 0; + } else { + has_seen_hotkey = 1; + fprintf(stderr, "Start capture\n"); + clock_gettime(CLOCK_MONOTONIC, &start); + continue; + } + } } else if (events[i].data.fd == mouse_fd) { type = MOUSE; } else { fprintf(stderr, "Unknown fd"); return 1; } - if(dump_event(&start, events[i].data.fd, type)) { + // Wait for the hotkey to start capture + if(has_seen_hotkey && dump_event(&start, &i_event, type)) { return 1; } }