--- /dev/null
+Makefile.in
+configure
+keyrhythm.c
+keyrhythm.h
+man/keyrhythm.1
--- /dev/null
+#!/usr/bin/make -f
+#
+# Makefile skeleton
+#
+# Copyright © 2014 Martin Read
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include colophon.mk
+include dirs.mk
+include features.mk
+
+vpath %.o .
+
+GENERATED_MAKES:=dirs.mk features.mk colophon.mk Makefile
+HANDWRITTEN_OBJS:=keyrhythm.o
+MAIN_EXE_OBJS:=$(GENERATED_OBJS) $(HANDWRITTEN_OBJS)
+MAJVERS:=1
+MINVERS:=0
+PATCHVERS:=0
+INCPATH:=-I$(srcdir)
+DEFINES:=-DMAJVERS=$(MAJVERS) -DMINVERS=$(MINVERS) -DPATCHVERS=$(PATCHVERS) -D_FORTIFY_SOURCE=2
+COMMON_CFLAGS:=-Wall -Wwrite-strings -Wunreachable-code -Wformat -Wextra -Wno-unused-but-set-variable -Wno-unused-parameter -Wmissing-declarations -Wredundant-decls -Wdisabled-optimization -Werror=format-security -fstack-protector --param=ssp-buffer-size=4 -std=gnu11 $(DEFINES) $(INCPATH)
+COMMON_CXXFLAGS:=-Wall -Wextra -Wwrite-strings -Wno-unused-but-set-variable -Wredundant-decls -Wdisabled-optimization -Wunreachable-code -Wundef -Wredundant-decls -Wmissing-declarations -Wno-unused -Wno-unused-parameter -Werror=format-security -fstack-protector --param=ssp-buffer-size=4 -std=gnu++11 $(DEFINES) $(INCPATH)
+PRODUCTION_CFLAGS:=$(COMMON_CFLAGS) -O2
+DEVELOPMENT_CFLAGS:=$(COMMON_CFLAGS) -g -Werror
+PRODUCTION_CXXFLAGS:=$(COMMON_CXXFLAGS) -O2
+DEVELOPMENT_CXXFLAGS:=$(COMMON_CXXFLAGS) -g -Werror
+ARCHIVEDIR:=$(main_dirname)-$(MAJVERS).$(MINVERS).$(PATCHVERS)
+ARCHIVENAME:=$(main_dirname)_$(MAJVERS).$(MINVERS).$(PATCHVERS)
+COMMON_LDFLAGS:=-Wl,-z,relro
+DEVELOPMENT_LDFLAGS:=$(COMMON_LDFLAGS) -g
+SUBDIRS:=man
+
+## PHONY targets in this section, please
+
+.PHONY: all archive clean code-docs code-docs-clean debianize-archive install debworkflow debclean spotless distclean
+
+all: $(main_exename)
+
+archive: clean
+ mkdir $(ARCHIVEDIR)
+ for i in $(SUBDIRS) ; do mkdir -p $(ARCHIVEDIR)/"$$i" ; done
+ for i in `cat MANIFEST` ; do cp "$$i" $(ARCHIVEDIR)/"$$i" ; done
+ tar czf $(ARCHIVENAME).tar.gz $(ARCHIVEDIR)
+ rm -r $(ARCHIVEDIR)
+
+debianize-archive: archive
+ mv $(ARCHIVENAME).tar.gz $(ARCHIVENAME).orig.tar.gz
+
+debworkflow: debclean debianize-archive
+ mkdir archive-test
+ mv $(ARCHIVENAME).orig.tar.gz archive-test
+ (cd archive-test && tar xzf $(ARCHIVENAME).orig.tar.gz)
+ cp -R debian archive-test/$(ARCHIVEDIR)/debian
+ (cd archive-test/$(ARCHIVEDIR) && debuild -uc -us)
+
+debclean:
+ -rm -rf archive-test
+
+clean:
+ -rm -rf $(ARCHIVEDIR)
+ -rm -f *.o $(main_exename) *.tar.gz
+
+distclean: gitclean
+
+code-docs:
+ doxygen Doxyfile
+
+code-docs-clean:
+ -rm -rf html latex
+
+gitclean: spotless
+ -rm -rf $(GENERATED_MAKES)
+
+generated-clean:
+ -rm -f $(GENERATED_SOURCE)
+
+install: all
+ install -D $(main_exename) $(DESTDIR)$(bindir)/$(main_exename)
+ install -D $(srcdir)/man/$(main_exename).1 $(DESTDIR)$(man1dir)/$(main_exename).1
+
+install-assets:
+ rm -r $(DESTDIR)$(datadir)
+ install -D genbitmaps/floor-tiles.png $(DESTDIR)$(datadir)/bitmaps/floor-tiles.png
+ install -D genbitmaps/unique-walls.png $(DESTDIR)$(datadir)/bitmaps/unique-walls.png
+ install -D genbitmaps/unique-walls.png $(DESTDIR)$(datadir)/bitmaps/unique-walls.png
+ install -D $(srcdir)/main_frag.glsl $(DESTDIR)$(datadir)/shaders/main_frag.glsl
+ install -D $(srcdir)/main_vert.glsl $(DESTDIR)$(datadir)/shaders/main_vert.glsl
+
+spotless: clean code-docs-clean debclean generated-clean
+
+## pattern rules
+
+%.o: $(srcdir)/%.cc
+ $(CXX) -c $(DEVELOPMENT_CXXFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+%.o: $(srcdir)/%.c
+ $(CC) -c $(DEVELOPMENT_CFLAGS) $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+## "real" targets
+
+$(main_exename): $(MAIN_EXE_OBJS)
+ $(CC) $(DEVELOPMENT_LDFLAGS) $(LDFLAGS) $(MAIN_EXE_OBJS) -o $(main_exename)
+
+## Build dependencies
+keyrhythm.o: $(srcdir)/keyrhythm.c $(srcdir)/keyrhythm.h
+
+# vim:ts=8:sts=8:sw=8:noexpandtab
--- /dev/null
+#! /usr/bin/perl -w
+
+# Copyright © 2014 Martin Read
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+use strict;
+use Getopt::Long;
+use English;
+
+##### TODO move these into a configuration input file
+our $main_title = "Keyrhythm";
+our $main_header = "keyrhythm.h";
+our $main_exename = "keyrhythm";
+our $main_dirname = "keyrhythm";
+#####
+
+# Prefixes
+my $prefix='/usr/local';
+my $exec_prefix='$(prefix)';
+
+# Bin and lib dirs
+my $bindir='$(exec_prefix)/bin';
+my $sbindir='$(exec_prefix)/sbin';
+my $libdir='$(exec_prefix)/lib';
+my $libexecdir='$(exec_prefix)/libexec';
+my $gamesdir='$(prefix)/games';
+my $srcdir=undef;
+
+my $datarootdir='$(prefix)/share';
+my $datadir='$(datarootdir)/$(main_dirname)';
+my $sysconfdir='$(prefix)/etc';
+my $sharedstatedir='$(prefix)/com';
+my $localstatedir='$(prefix)/var';
+
+my $includedir='$(prefix)/include';
+my $oldincludedir='/usr/include';
+
+my $docdir='$(datarootdir)/doc/$(main_dirname)';
+my $htmldir='$(docdir)';
+my $dvidir='$(docdir)';
+my $pdfdir='$(docdir)';
+my $psdir='$(docdir)';
+
+my $localedir='$(datarootdir)/locale';
+
+my $infodir='$(datarootdir)/info';
+
+my $mandir='$(datarootdir)/man';
+my $man1dir='$(mandir)/man1';
+my $man3dir='$(mandir)/man3';
+my $man5dir='$(mandir)/man5';
+my $man6dir='$(mandir)/man6';
+my $man7dir='$(mandir)/man7';
+my $man1ext='.1';
+my $man3ext='.3';
+my $man5ext='.5';
+my $man6ext='.6';
+my $man7ext='.7';
+
+# feature control
+my $disable_statics='false';
+
+my $verbose=1;
+GetOptions(
+'prefix=s' => \$prefix, 'exec_prefix=s' => \$exec_prefix,
+'bindir=s' => \$bindir, 'libdir=s' => \$libdir,
+'srcdir=s' => \$srcdir,
+'libexecdir=s' => \$libexecdir, 'gamesdir=s' => \$gamesdir,
+'includedir=s' => \$includedir, 'oldincludedir=s' => \$oldincludedir,
+'datarootdir=s' => \$datarootdir, 'datadir=s' => \$datadir,
+'sysconfdir=s' => \$sysconfdir, 'sharedstatedir=s' => \$sharedstatedir,
+'localstatedir=s' => \$localstatedir, 'localedir=s' => \$localedir,
+'mandir=s' => \$mandir,
+'man1dir=s' => \$man1dir, 'man3dir=s' => \$man3dir,
+'man5dir=s' => \$man5dir, 'man6dir=s' => \$man6dir,
+'man7dir=s' => \$man7ext,
+'man1ext=s' => \$man1ext, 'man3ext=s' => \$man3ext,
+'man5ext=s' => \$man5ext, 'man6ext=s' => \$man6ext,
+'man7ext=s' => \$man7ext,
+'docdir=s' => \$docdir, 'htmldir=s' => \$htmldir,
+'dvidir=s' => \$dvidir, 'pdfdir=s' => \$pdfdir,
+'psdir=s' => \$psdir, 'infodir=s' => \$infodir,
+'verbose' => \$verbose,
+'disable-statics' => sub { $disable_statics='true' },
+'quiet' => sub { $verbose = 0; } );
+
+print STDOUT "Configuring ${main_title} build/install process...\n" if $verbose;
+
+my $cmdresults;
+my $probably_in_main_dir = 0;
+
+if (!defined($srcdir))
+{
+ # Heuristic check when srcdir undefined: If the main header file is here,
+ # srcdir should be "."; if the main header file is not here but is in the
+ # parent dir, srcdir should be "..".
+ if (-f "./${main_header}")
+ {
+ # We're probably in srcdir.
+ $srcdir = "."
+ }
+ elsif (-f "../${main_header}")
+ {
+ # We're probably in an immediate child of srcdir.
+ $srcdir = ".."
+ }
+ else
+ {
+ die "configure: couldn't identify location of source code. Please use --srcdir=/some/directory and try again\n";
+ }
+}
+print STDOUT "Testing 'mkdir -p' ...\n" if $verbose;
+rmdir "billy/bob";
+rmdir "billy";
+$cmdresults=`mkdir -p billy/bob 2>&1`;
+if ($CHILD_ERROR != 0) {
+ print STDERR "configure: mkdir -p billy/bob failed\n";
+ rmdir "billy";
+ die "Please install a POSIX-compliant mkdir.\n";
+}
+rmdir "billy/bob";
+rmdir "billy";
+
+if ($includedir eq $oldincludedir) { $oldincludedir = ''; }
+
+print STDOUT "Writing dirs.mk...\n" if $verbose;
+open(DIRS_MK, '>', "dirs.mk") or die $!;
+print DIRS_MK "prefix:=${prefix}\n";
+print DIRS_MK "exec_prefix:=${exec_prefix}\n";
+print DIRS_MK "bindir:=${bindir}\n";
+print DIRS_MK "sbindir:=${sbindir}\n";
+print DIRS_MK "libdir:=${libdir}\n";
+print DIRS_MK "libexecdir:=${libexecdir}\n";
+print DIRS_MK "gamesdir:=${gamesdir}\n";
+print DIRS_MK "srcdir:=${srcdir}\n";
+print DIRS_MK "datarootdir:=${datarootdir}\n";
+print DIRS_MK "datadir:=${datadir}\n";
+print DIRS_MK "sysconfdir:=${sysconfdir}\n";
+print DIRS_MK "sharedstatedir:=${sharedstatedir}\n";
+print DIRS_MK "localstatedir:=${localstatedir}\n";
+print DIRS_MK "localedir:=${localedir}\n";
+print DIRS_MK "includedir:=${includedir}\n";
+print DIRS_MK "oldincludedir:=${oldincludedir}\n";
+print DIRS_MK "mandir:=${mandir}\n";
+print DIRS_MK "man1dir:=${man1dir}\n";
+print DIRS_MK "man3dir:=${man3dir}\n";
+print DIRS_MK "man5dir:=${man5dir}\n";
+print DIRS_MK "man6dir:=${man6dir}\n";
+print DIRS_MK "man7dir:=${man7dir}\n";
+print DIRS_MK "man1ext:=${man1ext}\n";
+print DIRS_MK "man3ext:=${man3ext}\n";
+print DIRS_MK "man5ext:=${man5ext}\n";
+print DIRS_MK "man6ext:=${man6ext}\n";
+print DIRS_MK "man7ext:=${man7ext}\n";
+print DIRS_MK "docdir:=${docdir}\n";
+print DIRS_MK "htmldir:=${htmldir}\n";
+print DIRS_MK "dvidir:=${dvidir}\n";
+print DIRS_MK "pdfdir:=${pdfdir}\n";
+print DIRS_MK "psdir:=${psdir}\n";
+print DIRS_MK "infodir:=${infodir}\n";
+close(DIRS_MK);
+
+print STDOUT "Writing features.mk...\n" if $verbose;
+open(FEATURES_MK, '>', "features.mk") or die $!;
+print FEATURES_MK "# This file is automatically generated by the configure script. Do not edit.\n";
+print FEATURES_MK "DISABLE_STATICS:=${disable_statics}\n";
+close(FEATURES_MK);
+
+print STDOUT "Writing colophon.mk...\n" if $verbose;
+open(COLOPHON_MK, '>', "colophon.mk") or die $!;
+print COLOPHON_MK "# This file is automatically generated by the configure script. Do not edit.\n";
+print COLOPHON_MK "main_header:=${main_header}\n";
+print COLOPHON_MK "main_exename:=${main_exename}\n";
+print COLOPHON_MK "main_dirname:=${main_dirname}\n";
+print COLOPHON_MK "main_title:=${main_title}\n";
+close COLOPHON_MK;
+
+open MAKEFILE_IN, "<", "${srcdir}/Makefile.in";
+my @makefile = <MAKEFILE_IN>;
+close MAKEFILE_IN;
+print STDOUT "Writing Makefile...\n" if $verbose;
+open MAKEFILE_OUT, ">", "./Makefile";
+print MAKEFILE_OUT @makefile;
+close MAKEFILE_OUT;
--- /dev/null
+Copyright © 2014 Martin Read
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+
--- /dev/null
+keyrhythm (1.0.0-1) UNRELEASED; urgency=medium
+
+ * Initial release. (Closes: #XXXXXX)
+
+ -- Martin Read <martin@blackswordsonics.com> Sun, 30 Nov 2014 00:54:22 +0000
--- /dev/null
+Source: keyrhythm
+Maintainer: Martin Read <martin@blackswordsonics.com>
+Section: misc
+Priority: optional
+Standards-Version: 3.9.6
+Build-Depends: debhelper (>= 9)
+
+Package: keyrhythm
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Suggests: csound
+Description: keyboard input timing recorder
+ keyrhythm records the timing of the user's alphanumeric keystrokes; the
+ author envisages it as a useful tool for generating rhythm timings to put
+ into a Csound score file, hence the name.
+
--- /dev/null
+Copyright © 2014 Martin Read
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+
--- /dev/null
+#! /usr/bin/make -f
+%:
+ dh $@
--- /dev/null
+3.0 (quilt)
--- /dev/null
+/*! \file keyrhythm.cc
+ * \brief main source file for Keyrhythm
+ */
+
+/* Copyright © 2014 Martin Read
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+#include <termios.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+char *outfile_name = NULL;
+FILE *outfp;
+
+struct option options[] =
+{
+ {
+ "output-file",
+ required_argument,
+ NULL,
+ 'o'
+ },
+ {
+ NULL,
+ no_argument,
+ NULL,
+ 0
+ }
+};
+
+volatile bool quitflag = false;
+
+static void sigint_catcher(int unused)
+{
+ quitflag = true;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ if (!isatty(0))
+ {
+ fprintf(stderr, "keyrhythm: stdin is not a terminal\n");
+ exit(1);
+ }
+ do
+ {
+ i = getopt_long(argc, argv, "o:", options, NULL);
+ switch (i)
+ {
+ case -1:
+ break;
+ case 'o':
+ outfile_name = strdup(optarg);
+ break;
+ default:
+ fprintf(stderr, "keyrhythm: unrecognized command-line option\n");
+ exit(1);
+ }
+ } while (i != -1);
+ if (outfile_name == NULL)
+ {
+ outfile_name = strdup("keyrhythm.out");
+ }
+ puts("Keyrhythm recording. Press Ctrl-C to finish.");
+ outfp = fopen(outfile_name, "w");
+ struct termios ti_orig;
+ struct termios ti_new;
+ memset(&ti_orig, '\0', sizeof ti_orig);
+ tcgetattr(0, &ti_orig);
+ memcpy(&ti_new, &ti_orig, sizeof ti_orig);
+ ti_new.c_lflag &= ~(ICANON | ECHO);
+ tcsetattr(0, TCSANOW, &ti_new);
+ struct sigaction sa;
+ sa.sa_handler = sigint_catcher;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_restorer = NULL;
+ sigaction(SIGINT, &sa, NULL);
+ struct timeval launch_tv;
+ bool started = false;
+ do
+ {
+ int i;
+ struct timeval tv;
+ i = getchar();
+ if (i > 0)
+ {
+ gettimeofday(&tv, NULL);
+ if (isascii(i) && isalnum(i))
+ {
+ if (!started)
+ {
+ launch_tv = tv;
+ started = true;
+ }
+ unsigned long long secdiff;
+
+ unsigned long long usecdiff;
+ secdiff = tv.tv_sec - launch_tv.tv_sec;
+ usecdiff = secdiff * 1000000ull + tv.tv_usec - launch_tv.tv_usec;
+ fprintf(outfp, "%c %llu.%06llu\n", i, usecdiff / 1000000ull, usecdiff % 1000000ull);
+ }
+ }
+ } while (!quitflag);
+ tcsetattr(0, TCSANOW, &ti_orig);
+ fclose(outfp);
+ puts("Done.");
+ return 0;
+}
+
+/* keyrhythm.cc */
--- /dev/null
+/*! \file keyrhythm.hh
+ * \brief common header for Keyrhythm
+ */
+
+/* Copyright © 2014 Martin Read
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+
--- /dev/null
+.TH KEYRHYTHM 1 "November 30, 2014" "Keyrhythm Version 1.0.0" "Keyrhythm User Manual"
+.SH NAME
+keyrhythm \- a keyboard timing recorder
+.SH SYNOPSIS
+keyrhythm [-o NAME]
+
+.SH DESCRIPTION
+.I keyrhythm
+records the timing of incoming alphanumeric keystrokes relative to the time at
+which the program starts.
+
+.TP
+\fB-o\fR, \fB\-\-output\fR=\fINAME\fR
+record timings to this file (the default is "keyrhythm.out")
+
+.SH BUGS
+
+None identified yet.
+
+.SH AUTHOR
+Martin Read <martin@blackswordsonics.com>