Initial commit
authorMartin Read <mpread@chiark.greenend.org.uk>
Sun, 30 Nov 2014 18:41:21 +0000 (18:41 +0000)
committerMartin Read <mpread@chiark.greenend.org.uk>
Sun, 30 Nov 2014 18:41:21 +0000 (18:41 +0000)
14 files changed:
.gitignore [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
configure [new file with mode: 0755]
copyright [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/source/format [new file with mode: 0644]
keyrhythm.c [new file with mode: 0644]
keyrhythm.h [new file with mode: 0644]
man/keyrhythm.1 [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c81d16b
--- /dev/null
@@ -0,0 +1 @@
+*.mk
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..27aa60f
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,5 @@
+Makefile.in
+configure
+keyrhythm.c
+keyrhythm.h
+man/keyrhythm.1
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..a25a9f0
--- /dev/null
@@ -0,0 +1,128 @@
+#!/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
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..9efbedf
--- /dev/null
+++ b/configure
@@ -0,0 +1,201 @@
+#! /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;
diff --git a/copyright b/copyright
new file mode 100644 (file)
index 0000000..196dd6b
--- /dev/null
+++ b/copyright
@@ -0,0 +1,20 @@
+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.
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..cd2e878
--- /dev/null
@@ -0,0 +1,5 @@
+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
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..ec63514
--- /dev/null
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..c0a6a74
--- /dev/null
@@ -0,0 +1,16 @@
+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.
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..196dd6b
--- /dev/null
@@ -0,0 +1,20 @@
+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.
+
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..78c7615
--- /dev/null
@@ -0,0 +1,3 @@
+#! /usr/bin/make -f
+%:
+       dh $@
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/keyrhythm.c b/keyrhythm.c
new file mode 100644 (file)
index 0000000..5927b10
--- /dev/null
@@ -0,0 +1,136 @@
+/*! \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 */
diff --git a/keyrhythm.h b/keyrhythm.h
new file mode 100644 (file)
index 0000000..df7af9a
--- /dev/null
@@ -0,0 +1,25 @@
+/*! \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.  */
+
+
diff --git a/man/keyrhythm.1 b/man/keyrhythm.1
new file mode 100644 (file)
index 0000000..2763e44
--- /dev/null
@@ -0,0 +1,21 @@
+.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>