diff -uN bplay-0.991/Makefile bplay.martin/Makefile
--- bplay-0.991/Makefile	Tue Nov  9 23:06:01 1999
+++ bplay.martin/Makefile	Wed Jan 17 11:46:41 2001
@@ -3,7 +3,7 @@
 SRCS = bplay.c sndfunc.o shmbuf.c
 
 CC = gcc
-CFLAGS = -Wall -O3 -DUSEBUFFLOCK #-DDEBUG
+CFLAGS = -Wall -O0 -DUSEBUFFLOCK -DDEBUG -g
 LDFLAGS = 
 LIBS =
 
diff -uN bplay-0.991/bplay.c bplay.martin/bplay.c
--- bplay-0.991/bplay.c	Mon Sep 18 23:57:05 2000
+++ bplay.martin/bplay.c	Sat Nov 30 11:49:07 2002
@@ -1,6 +1,9 @@
 /*
 ** brec/bplay.c (C) David Monro 1996
 **
+** 2001 Martin Renold
+** tries to add keyboard control
+**
 ** Copyright under the GPL - see the file COPYING in this directory
 **
 **
@@ -36,7 +39,7 @@
 /* Globals */
 char *progname;
 int forked;
-pid_t pid;
+pid_t pid, kbdpid;
 int recorder = 0;
 int debug = 0;
 
@@ -54,8 +57,10 @@
 
 void getbcount(int speed, int bits, int stereo, int *bcount,
 	int timelim, int samplim, int timejmp, int sampjmp, int *bjump);
-void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo);
-void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, int stereo);
+void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo, 
+	int jump, int secs);
+void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, 
+	int stereo, int jump, int secs);
 void playvoc(int thefd, char hd_buf[20]);
 
 /* extern globals */
@@ -69,10 +74,12 @@
 extern void init_shm(void);
 extern void shmrec(int outfd, int bcount, int terminate);
 extern void diskread(int outfd, int bcount, char hd_buf[20], int terminate,
-    int speed, int bits, int stereo);
+    int speed, int bits, int stereo, int jump);
 extern volatile void audiowrite(void);
+extern volatile void listenkeyboard(void);
 extern void initsems(int disks, int snds);
 extern void cleanupsems(void);
+extern void rl_ttyset (int Reset);
 
 
 int main(int argc, char *argv[])
@@ -91,6 +98,8 @@
 	int mods;			/* So user can override */
 	int optc;			/* For getopt */
 
+	pid = 0; kbdpid = 0;            /* not forked so far */
+
 	progname = basename(argv[0]);	/* For errors */
 
 	/* Ok, find out if we record or play */
@@ -104,11 +113,11 @@
 		recorder = 0;
 	}
 	/* Default values */
-	speed = 8000; bits = 8; stereo = 0;
+	speed = 44100; bits = 16; stereo = 1;
 	timelim = 0; samplim = 0; bcount = 0;
 	timejmp = 0; sampjmp = 0; bjump = 0;
 	filetype = F_UNKNOWN;
-	mods = 0;
+	mods = MSPEED | MBITS | MSTEREO; /* changed by Martin; was: 0 */
 	/* Parse the options */
 	while ((optc = getopt(argc, argv, "Ss:b:t:T:j:J:rvwd:B:D:")) != -1)
 	{
@@ -320,6 +329,7 @@
 	}
 	else
 	{
+	        //called as player
 		int count;
 		char hd_buf[20];	/* Holds first 20 bytes */
 
@@ -329,6 +339,14 @@
 
 		initsems(1, 0);
 
+		if (thefd > 1) {
+		  //keyboard listen thread
+		  rl_ttyset(0);
+		  kbdpid = fork();
+		  if (!kbdpid)
+		    listenkeyboard();
+		}
+
 		pid = fork();
 		if(!pid)
 			audiowrite();	/* Doesn't return */
@@ -338,9 +356,18 @@
 		if(strstr(hd_buf, VOC_MAGIC) != NULL)
 			playvoc(thefd, hd_buf);
 		else if(strstr(hd_buf, "RIFF") != NULL)
-			playwav(thefd, hd_buf, mods, speed, bits, stereo);
+      {
+          if (sampjmp)
+              playwav(thefd, hd_buf, mods, speed, bits, stereo, sampjmp, 0);
+          else
+              playwav(thefd, hd_buf, mods, speed, bits, stereo, timejmp, 1);
+      }
 		else /* Assume raw data */
-			playraw(thefd, hd_buf, speed, bits, stereo);
+          if (sampjmp)
+              playraw(thefd, hd_buf, speed, bits, stereo, sampjmp, 0);
+          else
+              playraw(thefd, hd_buf, speed, bits, stereo, timejmp, 1);
+			
 
 		wait(NULL);
 		cleanupsems();
@@ -367,6 +394,7 @@
 {
 	fprintf(stderr, "%s: %s\n", progname, err);
 	if (forked) { kill(pid,9); }
+	if (kbdpid) { kill(kbdpid,9); }
 	exit(-1);
 }
 
@@ -395,14 +423,18 @@
 	}
 }
 
-void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo)
+void playraw(int thefd, char hd_buf[20], int speed, int bits, int stereo, int jump, int secs)
 {
     fprintf(stderr, "Playing raw data : %d bit, Speed %d %s ...\n",
 	bits, speed, (stereo)? "Stereo" : "Mono");
-    diskread(thefd, 0, hd_buf, 1, speed, bits, stereo);
+
+    if (secs == 0)
+        jump = jump / speed;
+
+    diskread(thefd, 0, hd_buf, 1, speed, bits, stereo, jump);
 }
 
-void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, int stereo)
+void playwav(int thefd, char hd_buf[20], int mods, int speed, int bits, int stereo, int jump, int secs)
 {
     wavhead wavhd;
     int count;
@@ -437,7 +469,11 @@
       stereo = wavhd.modus - 1;
     fprintf(stderr, "Playing WAVE : %d bit, Speed %d %s ...\n", 
 	    bits, speed, (stereo)? "Stereo" : "Mono");
-    diskread(thefd, 0, NULL, 1, speed, bits, stereo);
+
+    if (secs == 0)
+        jump = jump / speed;
+    
+    diskread(thefd, 0, NULL, 1, speed, bits, stereo, jump);
 }
 
 void playvoc(int thefd, char hd_buf[20])
@@ -473,7 +509,7 @@
         if (debug)
 	    fprintf(stderr, "Terminating\n");
 
-	diskread(thefd, -1, NULL, 1, speed, bits, stereo);
+	diskread(thefd, -1, NULL, 1, speed, bits, stereo, 0);
 	quit = 1;
 	continue;
     }
@@ -494,7 +530,7 @@
 	    stereo = 0;
 	}
 	bytecount = DATALEN(ccblock) -2;
-	diskread(thefd, bytecount, NULL, 0, speed, bits, stereo);
+	diskread(thefd, bytecount, NULL, 0, speed, bits, stereo, 0);
 	lastblocktype = 1;
 	}
 	break;
@@ -520,7 +556,7 @@
 	bits = tblock.BitsPerSample;
 	stereo = tblock.Channels - 1;
 	bytecount = DATALEN(ccblock) - 12;
-	diskread(thefd, bytecount, NULL, 0, speed, bits, stereo);
+	diskread(thefd, bytecount, NULL, 0, speed, bits, stereo, 0);
 	lastblocktype = 9;
 	}
 	break;
@@ -528,7 +564,7 @@
         if (debug)
 	    fprintf(stderr, "Terminating\n");
 
-	diskread(thefd, -1, NULL, 1, speed, bits, stereo);
+	diskread(thefd, -1, NULL, 1, speed, bits, stereo, 0);
 	quit = 1;
 	break;
     case 6:
diff -uN bplay-0.991/kbdcontrol.c bplay.martin/kbdcontrol.c
--- bplay-0.991/kbdcontrol.c	Thu Jan  1 01:00:00 1970
+++ bplay.martin/kbdcontrol.c	Wed Jul 10 20:12:18 2002
@@ -0,0 +1,150 @@
+/*
+**
+** bplay/kbdcontrol.c (C) Martin Renold 2001
+**
+** Copyright under the GPL - see the file COPYING in this directory
+**
+** Keyboard jumping support by Martin Renold
+**
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+*/
+#include <termios.h>
+
+/* extern prototypes */
+//extern int get_pos();
+//extern set_pos(int newpos, int whence);
+
+void saveregion(char*sourcefile, char*destfile, size_t startpos, size_t endpos);
+
+volatile void listenkeyboard()
+{
+  char s;
+  int startmark = -1;
+  int endmark = -1;
+  off_t tmp;
+
+  /* Uncatch the signals, so we don't clean up twice */
+  signal(SIGINT, SIG_DFL);
+
+  fprintf(stdout, "\nUse the numpad keys to navigate:\n");
+  fprintf(stdout, "1 / 3 : jump by 10 seconds\n");
+  fprintf(stdout, "4 / 6 : jump by 60 seconds\n");
+  fprintf(stdout, "7 / 9 : jump by 6 minutes\n\n");
+
+  fprintf(stdout, "+ / - : set start / end mark\n");
+  fprintf(stdout, "* / / : jump to start / end mark\n");
+  fprintf(stdout, "return: save marked region\n\n");
+
+  fprintf(stdout, "Quit: Ctrl-C\n");
+
+  while (1) {
+    //    fd_set rset;
+    //fgetc(stdin);
+
+    //    FD_ZERO (&rset);
+    //    FD_SET (STDIN_FILENO, &rset);
+    /* if key was pressed, parse it and do function */
+    read (0, &s, 1);
+
+    tmp = 0;
+    switch (s & 255)
+      {
+      case '1': tmp = -10; break;
+      case '3': tmp = +10; break;
+      case '4': tmp = -60; break;
+      case '6': tmp = +60; break;
+      case '7': tmp = -60*6; break;
+      case '9': tmp = +60*6; break;
+      case '2': 
+      case '5':
+      case '8':
+	fprintf(stderr, "Position: %li (%lis)\n", request->filepos, request->filepos / request->bytespersecond);
+	break;
+      case '+':
+	startmark = request->filepos;
+	break;
+      case '-':
+	endmark = request->filepos;
+	break;
+      case '*':
+	if (startmark < 0) {
+	  fprintf(stdout, "Start mark is unset.\n");
+	} else {
+	  request->jumpwhence = SEEK_SET; 
+	  request->jump = startmark;
+	}
+	break;
+      case '/':
+	if (endmark < 0) {
+	  fprintf(stdout, "End mark is unset.\n");
+	} else {
+	  request->jumpwhence = SEEK_SET; 
+	  request->jump = endmark;
+	}
+	break;
+      case '\n':
+	fprintf(stdout, "Saving region as 001.raw...");
+	//SaveRegion
+	fprintf(stdout, "not yet implemented --- done\n");	
+	break;
+      case 0x1b:
+	read (0, &s, 1);
+	read (0, &s, 1);
+	fprintf(stdout, "Turn ON Num Lock!\n");
+	break;
+      default:
+	break;
+      }
+    if (tmp != 0) {
+      request->jumpwhence = SEEK_CUR; 
+      request->jump += tmp * request->bytespersecond;
+      tmp = 0;
+      stop_audio();
+    }
+  }
+
+  //TODO: cleanly catch signals for this:
+  rl_ttyset(1);
+
+  exit(0);
+}
+
+/* takes terminal in and out of raw mode */
+/* stolen from workbone :-) - Martin */
+void rl_ttyset (int Reset)
+{
+  static struct termios old;
+  struct termios new;
+
+  if (Reset == 0)
+    {
+      (void) tcgetattr (0, &old);
+      new = old;
+      new.c_lflag &= ~(ECHO | ICANON);
+      new.c_iflag &= ~(ISTRIP | INPCK);
+      (void) tcsetattr (0, TCSANOW, &new);
+      terminalset = 1;
+    }
+  else
+    {
+      if (terminalset != 0) 
+	(void) tcsetattr (0, TCSANOW, &old);
+    }
+}
+
+void saveregion(char*sourcefile, char*destfile, size_t startpos, size_t endpos)
+{
+  int src, dest;
+  //  open(
+}
diff -uN bplay-0.991/shmbuf.c bplay.martin/shmbuf.c
--- bplay-0.991/shmbuf.c	Sat Feb  5 12:26:14 2000
+++ bplay.martin/shmbuf.c	Wed Jan 17 15:08:10 2001
@@ -21,6 +21,7 @@
 #include <sys/shm.h>
 #include <sys/wait.h>
 
+
 #ifdef __GLIBC__
 /* Nasty hack */
 #ifndef SEMMSL
@@ -38,6 +39,7 @@
     int count;	/* How many bytes in this buffer */
     int last;	/* Should we terminate after this buffer? */
     int setit;	/* Should we re-set the audio parameters to be the ones here? */
+    off_t filepos;
     int speed;
     int bits;
     int stereo;
@@ -55,23 +57,34 @@
 
 /* Globals */
 int bigbuffsize = DEFAULTBUFFSIZE;
+int terminalset = 0;
 
 /* Statics - mostly shared memory etc */
-static int shmid, shmid2, *disksemid, *sndsemid;
+static int shmid, shmid2, shmid3, *disksemid, *sndsemid;
 static char *bigbuff;
 static char **buffarr;
 static int numbuffs, numsemblks;
 static blockinf_t *buffinf;
 
+/* shared memory for process communication */
+static struct {
+  off_t jump;       /* jump by / to ... bytes in the file */
+  int jumpwhence; /* SEEK_SET, SEEK_CUR, SEEK_END */
+  int overjump;   /* 1 = filepos changed, don't play old data */
+  off_t filepos;    /* currently played position in bytes */
+  int bytespersecond; /* just to let the kbd process know too */
+} *request;
+
 /* prototypes */
 void cleanupsems(void);
 static void sighandler(int i);
+void rl_ttyset (int Reset);
 
 /* Extern globals */
 extern int abuf_size;
 extern int audio;
 extern char *progname;
-extern pid_t pid;
+extern pid_t pid, kbdpid;
 extern int recorder;
 extern int debug;
 
@@ -80,6 +93,7 @@
 extern void snd_parm(int speed, int bits, int stereo);
 extern void sync_audio(void);
 extern void cleanup_audio(void);
+extern void stop_audio();
 
 void init_shm(void)
 {
@@ -177,6 +191,26 @@
 	    IPC_EXCL | IPC_CREAT | 0600)) == -1)
 	    ErrDie("semget");
     }
+
+    //Create some shared memory. Just copied - Martin.
+    shmid3 = shmget(IPC_PRIVATE, sizeof(request),
+	IPC_EXCL | IPC_CREAT | 0600);
+    if (shmid3 == -1)
+	ErrDie("shmget");
+    request = shmat(shmid3, IPC_RMID, SHM_RND);
+    if ((char*)request == (char*)-1)
+    {
+	perror("shmat");
+	if(shmctl(shmid3, IPC_RMID, NULL))
+		perror("shmctl");
+	exit(-1);
+    }
+    if(shmctl(shmid3, IPC_RMID, NULL))
+	ErrDie("shmctl");
+    request->jump = 0;
+
+    terminalset = 0;
+
     /* Catch some signals, so we clean up semaphores */
     signal(SIGINT, sighandler);
 }
@@ -298,7 +332,7 @@
 }
 
 void diskread(int infd, int totalplay, char hd_buf[20], int terminate,
-    int speed, int bits, int stereo)
+    int speed, int bits, int stereo, int jump)
 {
 
     int count, i, limited = 0;
@@ -309,6 +343,16 @@
     static int triggered = 0;	/* Have we let the writer go? */
     static int cbuff = 0;	/* Which buffer */
 
+    request->bytespersecond = speed * (bits/8) * (stereo * 2);
+
+    if (jump)
+    {
+      jump = jump * request->bytespersecond;
+
+      if (lseek (infd, jump, SEEK_CUR) < jump)
+	fprintf(stderr, "couldn't jump %d bytes\n", jump);
+    }
+
     if (totalplay) limited = 1;
     if (totalplay == -1)
     {
@@ -322,6 +366,21 @@
 
 	/* Wait for a clean buffer */
 	down(disksemid, cbuff);
+
+	/* Check for a jump request */
+	if (request->jump != 0) {
+	  /* the audiowrite process should overjump what's in the queue */
+	  request->overjump = 1;
+
+	  lseek(infd, request->jump, request->jumpwhence
+);
+	  if (debug)
+	    fprintf(stderr, "Jumped by %li bytes (%li seconds)\n", request->jump, request->jump / request->bytespersecond);
+	  request->jump = 0;
+
+	  buffinf[cbuff].setit = 2; /* mark */
+	}
+
 	/* Read from the input */
 	numread = 0;
 	trgt = abuf_size;
@@ -341,6 +400,9 @@
 	    }
 	    first = 0; 
 	}
+
+	buffinf[cbuff].filepos = lseek(infd, 0, SEEK_CUR);
+
 	while ( (numread < trgt) &&
 	    ((count = read(infd, tmppt, trgt - numread)) != 0) )
 	{
@@ -413,26 +475,48 @@
     {
 	/* Wait for dirty buffer */
 	down(sndsemid, cbuff);
+
 	/* Spit to the audio device */
-	if(buffinf[cbuff].setit)
+	if(buffinf[cbuff].setit == 1)
 	{
 	    snd_parm(buffinf[cbuff].speed, buffinf[cbuff].bits,
 		buffinf[cbuff].stereo);
 	    buffinf[cbuff].setit = 0;
 	}
-	trgt = buffinf[cbuff].count;
-	numwr = 0;
-	tmpptr = buffarr[cbuff];
-	while ( (numwr < trgt) &&
-	    ((count = write(audio, tmpptr, trgt - numwr)) > 0) )
-	{
-	    if (count == -1)
+
+	if(buffinf[cbuff].setit == 2) {
+	  /* mark */
+	  buffinf[cbuff].setit = 0;
+	  if (request->overjump == 0)
+	    fprintf(stderr, "internal error: setit == 2 without overjump request\n");
+	  if (debug)
+	    fprintf(stderr, "Jump completed\n");
+	  request->overjump = 0;
+	  stop_audio();
+	}
+
+	if (request->overjump == 0) {
+	  trgt = buffinf[cbuff].count;
+	  numwr = 0;
+	  tmpptr = buffarr[cbuff];
+	  while ( (numwr < trgt) &&
+		  ((count = write(audio, tmpptr, (trgt - numwr) > 256 ? 256 : (trgt - numwr) )) > 0) &&
+		  request->overjump == 0)
+	    {
+	      if (count == -1)
 		ErrDie("write");
-	    numwr += count;
-	    tmpptr += count;
-	}
-	if (debug >= 2)
+	      numwr += count;
+	      tmpptr += count;
+	    }
+	  if (debug >= 2)
             fprintf(stderr, "out:%d, %d\n", cbuff, numwr);
+	  if (request->overjump != 0 && debug)
+	    fprintf(stderr, "Overjump detected\n");
+
+	} else {
+	  if (debug >= 2) 
+	    fprintf(stderr, "jumped once\n");
+	}
 
 	/* Was it the last buffer? */
 	if (buffinf[cbuff].last)
@@ -440,6 +524,12 @@
 	    up(disksemid, cbuff);	/* Not really needed */
 	    break;
 	}
+
+	/* keep the filepos up to date */
+	/* FIXME: the value is read at any time by another thread
+	 * - is this clean or will I need locking? */
+	request->filepos = buffinf[cbuff].filepos;
+
 	/* Mark as clean */
 	up(disksemid, cbuff);
 	/* Update counter */
@@ -481,16 +571,25 @@
 	semctl(disksemid[i], 0, IPC_RMID, s);
 	semctl(sndsemid[i], 0, IPC_RMID, s);
     }
+
+    //FIXME: that's a bad place
+    rl_ttyset(1);
 }
 
 static void sighandler(int i)
 {
     if (debug)
-        fprintf(stderr, "signal %d received, cleaning up.\n", i);
-
+        fprintf(stderr, "signal %d received, cleaning up...\n", i);
     if (!recorder && pid)
-        kill(pid,9);
+      kill(pid,9);
+    if (kbdpid) {
+      kill(kbdpid,9);
+      rl_ttyset(1);
+    }
+      
     cleanup_audio();
     cleanupsems();
     exit(1);
 }
+
+#include "kbdcontrol.c"
diff -uN bplay-0.991/sndfunc.c bplay.martin/sndfunc.c
--- bplay-0.991/sndfunc.c	Wed Mar  1 18:48:53 2000
+++ bplay.martin/sndfunc.c	Wed Jan 17 14:56:40 2001
@@ -63,9 +63,8 @@
     if ((speed != oldspeed) || (bits != oldbits) || (stereo != oldstereo))
     {
 	/* Sync the dsp - otherwise strange things may happen */
-#ifdef DEBUG
-	fprintf(stderr, " - syncing - ");
-#endif
+        if (debug) 
+	  fprintf(stderr, " - syncing - ");
 	sync_audio();
 
 	/* Set the sample speed, size and stereoness */
@@ -83,6 +82,11 @@
 {
     if (ioctl (audio, SNDCTL_DSP_SYNC, NULL) < 0)
 	ErrDie(audev);
+}
+
+void stop_audio(void)
+{
+  SNDCTL_COPR_HALT;
 }
 
 void cleanup_audio(void)
