diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2015-04-10 15:37:15 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2015-04-11 10:44:13 +1000 |
commit | ae1ede741d033d7040afca6c902f7161500b8c16 (patch) | |
tree | de8e1d9f940bd02270c707618f284d5c7f7f085b /tools/ptraccel-debug.c | |
parent | 76adf39ab39e8a99f3e4901b23b01a8d4b1f93f3 (diff) | |
download | libinput-ae1ede741d033d7040afca6c902f7161500b8c16.tar.gz |
tools: add a tool for printing pointer acceleration parameters
Prints the various pointer accel behaviors into a format understood by
gnuplot, which then provides prettiness.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'tools/ptraccel-debug.c')
-rw-r--r-- | tools/ptraccel-debug.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c new file mode 100644 index 00000000..d00e8f37 --- /dev/null +++ b/tools/ptraccel-debug.c @@ -0,0 +1,299 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#define _GNU_SOURCE + +#include <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <filter.h> +#include <getopt.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static void +print_ptraccel_deltas(struct motion_filter *filter, double step) +{ + struct normalized_coords motion; + uint64_t time = 0; + double i; + + printf("# gnuplot:\n"); + printf("# set xlabel dx unaccelerated\n"); + printf("# set ylabel dx accelerated\n"); + printf("# set style data lines\n"); + printf("# plot \"gnuplot.data\" using 1:2 title \"step %.2f\"\n", step); + printf("#\n"); + + /* Accel flattens out after 15 and becomes linear */ + for (i = 0.0; i < 15.0; i += step) { + motion.x = i; + motion.y = 0; + time += 12; /* pretend 80Hz data */ + + motion = filter_dispatch(filter, &motion, NULL, time); + + printf("%.2f %.3f\n", i, motion.x); + } +} + +static void +print_ptraccel_movement(struct motion_filter *filter, + int nevents, + double max_dx, + double step) +{ + struct normalized_coords motion; + uint64_t time = 0; + double dx; + int i; + + printf("# gnuplot:\n"); + printf("# set xlabel \"event number\"\n"); + printf("# set ylabel \"delta motion\"\n"); + printf("# set style data lines\n"); + printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n"); + printf("# \"gnuplot.data\" using 1:3 title \"dx in\"\n"); + printf("#\n"); + + if (nevents == 0) { + if (step > 1.0) + nevents = max_dx; + else + nevents = 1.0 * max_dx/step + 0.5; + + /* Print more events than needed so we see the curve + * flattening out */ + nevents *= 1.5; + } + + dx = 0; + + for (i = 0; i < nevents; i++) { + motion.x = dx; + motion.y = 0; + time += 12; /* pretend 80Hz data */ + + filter_dispatch(filter, &motion, NULL, time); + + printf("%d %.3f %.3f\n", i, motion.x, dx); + + if (dx < max_dx) + dx += step; + } +} + +static void +print_ptraccel_sequence(struct motion_filter *filter, + int nevents, + double *deltas) +{ + struct normalized_coords motion; + uint64_t time = 0; + double *dx; + int i; + + printf("# gnuplot:\n"); + printf("# set xlabel \"event number\"\n"); + printf("# set ylabel \"delta motion\"\n"); + printf("# set style data lines\n"); + printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n"); + printf("# \"gnuplot.data\" using 1:3 title \"dx in\"\n"); + printf("#\n"); + + dx = deltas; + + for (i = 0; i < nevents; i++, dx++) { + motion.x = *dx; + motion.y = 0; + time += 12; /* pretend 80Hz data */ + + filter_dispatch(filter, &motion, NULL, time); + + printf("%d %.3f %.3f\n", i, motion.x, *dx); + } +} + +static void +print_accel_func(struct motion_filter *filter) +{ + double vel; + + printf("# gnuplot:\n"); + printf("# set xlabel \"speed\"\n"); + printf("# set ylabel \"raw accel factor\"\n"); + printf("# set style data lines\n"); + printf("# plot \"gnuplot.data\" using 1:2\n"); + for (vel = 0.0; vel < 3.0; vel += .0001) { + double result = pointer_accel_profile_linear(filter, + NULL, + vel, + 0 /* time */); + printf("%.4f\t%.4f\n", vel, result); + } +} + +static void +usage(void) +{ + printf("Usage: %s [options] [dx1] [dx2] [...] > gnuplot.data\n", program_invocation_short_name); + printf("\n" + "Options:\n" + "--mode=<motion|accel|delta|sequence> \n" + " motion ... print motion to accelerated motion (default)\n" + " delta ... print delta to accelerated delta\n" + " accel ... print accel factor\n" + " sequence ... print motion for custom delta sequence\n" + "--maxdx=<double>\n ... in motion mode only. Stop increasing dx at maxdx\n" + "--steps=<double>\n ... in motion and delta modes only. Increase dx by step each round\n" + "--speed=<double>\n ... accel speed [-1, 1], default 0\n" + "\n" + "If extra arguments are present and mode is not given, mode defaults to 'sequence'\n" + "and the arguments are interpreted as sequence of delta x coordinates\n" + "\n" + "If stdin is a pipe, mode defaults to 'sequence' and the pipe is read \n" + "for delta coordinates\n" + "\n" + "Output best viewed with gnuplot. See output for gnuplot commands\n"); +} + +int +main(int argc, char **argv) { + struct motion_filter *filter; + double step = 0.1, + max_dx = 10; + int nevents = 0; + bool print_accel = false, + print_motion = true, + print_delta = false, + print_sequence = false; + double custom_deltas[1024]; + double speed = 0.0; + enum { + OPT_MODE = 1, + OPT_NEVENTS, + OPT_MAXDX, + OPT_STEP, + OPT_SPEED, + }; + + filter = create_pointer_accelerator_filter(pointer_accel_profile_linear); + assert(filter != NULL); + + while (1) { + int c; + int option_index = 0; + static struct option long_options[] = { + {"mode", 1, 0, OPT_MODE }, + {"nevents", 1, 0, OPT_NEVENTS }, + {"maxdx", 1, 0, OPT_MAXDX }, + {"step", 1, 0, OPT_STEP }, + {"speed", 1, 0, OPT_SPEED }, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case OPT_MODE: + if (strcmp(optarg, "accel") == 0) + print_accel = true; + else if (strcmp(optarg, "motion") == 0) + print_motion = true; + else if (strcmp(optarg, "delta") == 0) + print_delta = true; + else if (strcmp(optarg, "sequence") == 0) + print_sequence = true; + else { + usage(); + return 1; + } + break; + case OPT_NEVENTS: + nevents = atoi(optarg); + if (nevents == 0) { + usage(); + return 1; + } + break; + case OPT_MAXDX: + max_dx = strtod(optarg, NULL); + if (max_dx == 0.0) { + usage(); + return 1; + } + break; + case OPT_STEP: + step = strtod(optarg, NULL); + if (step == 0.0) { + usage(); + return 1; + } + break; + case OPT_SPEED: + speed = strtod(optarg, NULL); + break; + default: + usage(); + exit(1); + break; + } + } + + filter_set_speed(filter, speed); + + if (!isatty(STDIN_FILENO)) { + char buf[12]; + print_sequence = true; + print_motion = false; + nevents = 0; + memset(custom_deltas, 0, sizeof(custom_deltas)); + + while(fgets(buf, sizeof(buf), stdin) && nevents < 1024) { + custom_deltas[nevents++] = strtod(buf, NULL); + } + } else if (optind < argc) { + print_sequence = true; + print_motion = false; + nevents = 0; + memset(custom_deltas, 0, sizeof(custom_deltas)); + while (optind < argc) + custom_deltas[nevents++] = strtod(argv[optind++], NULL); + } + + if (print_accel) + print_accel_func(filter); + else if (print_delta) + print_ptraccel_deltas(filter, step); + else if (print_motion) + print_ptraccel_movement(filter, nevents, max_dx, step); + else if (print_sequence) + print_ptraccel_sequence(filter, nevents, custom_deltas); + + filter_destroy(filter); + + return 0; +} |