diff -Nru sox.20050917/README.interactive sox.20050917-inst/README.interactive
--- sox.20050917/README.interactive	1970-01-01 01:00:00.000000000 +0100
+++ sox.20050917-inst/README.interactive	2005-09-17 18:34:23.000000000 +0200
@@ -0,0 +1,116 @@
+Interactive sox is a preliminary work. The main goal was to have an audio
+player which:
+- works interactively and is controlled with keys (not mouse)
+- can do smaller and bigger jumps, forward and reverse
+- can change speed
+- can change pitch _simultaneously_ with the change of speed (sox stretch effect)
+- can be controlled by scripts (as e.g. alsaplayer)
+Almost all these assumptions are fulfilled by sox - except the interactivity
+part (and the controll part which is trivial). The interactivity itself was
+easy to implement. More difficult was to handle changes of speed. It has been
+done by stopping the effects, changing parameters and restarting effects. On a
+modern 400 MHz CPU supercomputer these processing is fast enough to not to be
+noticed.
+
+
+To use interactivity sox should be started with  stretch x  effect, where x is
+stretch value the program starts with - it can be changes later interactively:
+
+sox -I rm20050513220001s.wav -t ossdsp /dev/dsp stretch 0.4
+
+To increase responsiveness try:
+echo "sox 1 256" > ! /proc/asound/card0/pcm0p/oss
+
+
+Time      0:56:53  94.8%        total:   0:59:59                      file time:  13:56:55
+Speed   2.6
+rm20050514130002s.wav -> /dev/dsp
+
+__________________________________________________________________________________________
+                                                                                     O
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+TODO
+
+- remove the need to specify dummy (not quite dummy but almost)  stretch  on
+  command line; check if stacking effects works correctly
+- with Linux kernel 2.6 there are problems with interactivity: it looks like
+  buffers are larger than in 2.4. I am not able to emulate 2.4 responsiveness.
+  It looks like
+  echo "sox 1 256" > ! /proc/asound/card0/pcm0p/oss
+  helps. Adding  -w -c 4  options helps too (uses more space in the buffer?).
+- interface for other effects
+- configure --with-interactive switch
+- --with-communication and a command line option to turn it on
+- seekable GSM - I would not have to uncompress my WAV/GSM do WAV before
+  playing. Just started:
+
+--- sox.20040708/wav.c	2002-12-31 04:19:22.000000000 +0100
++++ sox-12.17.5cvs/wav.c	2005-02-05 11:49:45.000000000 +0100
+@@ -1628,11 +1628,20 @@
+ 	{
+ 	case WAVE_FORMAT_IMA_ADPCM:
+ 	case WAVE_FORMAT_ADPCM:
++		st_fail_errno(ft,ST_ENOTSUP,"Only PCM Supported");
++	    break;
+ #ifdef ENABLE_GSM
+ 	case WAVE_FORMAT_GSM610:
+-#endif
+-		st_fail_errno(ft,ST_ENOTSUP,"Only PCM Supported");
++		{	st_size_t	gsmoff;
++			/* dwDataLength is divided by wav->blockAlign in line 859
++			   so let's assume blockAlign is in bytes */
++			/* rounding to blockAlign */
++			gsmoff = offset * ft->info.size + wav->blockAlign / 2;
++			gsmoff -= gsmoff % wav->blockAlign;
++			ft->st_errno = st_seek(ft, gsmoff + wav->dataStart, SEEK_SET);
++		}
+ 	    break;
++#endif
+ 	default:
+ 		ft->st_errno = st_seek(ft,offset*ft->info.size + wav->dataStart, SEEK_SET);
+ 	}
+
+
+Changes
+
+20031128 start - ncurses interface
+20031205 RZM specific display
+20031208 working on stop-start; functions parse_eff(), start_all_eff(),
+	resbuf_all_eff(), relbuf_all_eff(), drain_all_eff(), stop_all_eff(),
+	checkeffect(int *pneffects), restart_all_eff() make this easier
+	interactive() after insteadof before flow_effect_out()
+	ST_BUFSIZ in interactive mode lowered from 8 KB to 1 KB
+20031216 rzm_off_time() changes
+	util.c functions writing to buffer instead of screen in interactive mode
+20040708 -I option
+	rzm_off_time() changes
+	more keys, top row speed scale
+	making both -DINTERACTIVE and -I working
+2005xxxx separate interactive.[ch]
+	#define ST_BUFSIZ 128
+	wav.c - preliminary work on seekable GSM
+
+20050528
+- ported to CVS sox 20050207 (discovered that sound split into 2 or 4 channels loses beginnings of buffer [?])
+- added communication interface via ~/.soxi
+	The key as in src/interactive.c:interactive() can be sent via the
+	~/.soxi pipe. The codes are available in /usr/include/curses.h . E.g.
+		#define KEY_RIGHT       0405            /* right-arrow key */
+	can be sent with echo interpreting octal codes (0405 == 0x105, bytes in
+	octal: 01 05, also note swapped bytes):
+		echo -n '\05\01' >> ~/.soxi
+	Alternative way:
+	cat << EOF | uudecode >> ~rzm/.soxi
+	begin-base64 644 -
+	BQE=
+	====
+	EOF
+- added pause ("p", echo -n 'p\0')
+
+20050912 Chris Bagwell likes my patch
+
+20050917
+- repatching current version of sox
+- more general name for error messages buffering (CB request)
diff -Nru sox.20050917/src/interactive.c sox.20050917-inst/src/interactive.c
--- sox.20050917/src/interactive.c	1970-01-01 01:00:00.000000000 +0100
+++ sox.20050917-inst/src/interactive.c	2005-09-18 00:40:57.000000000 +0200
@@ -0,0 +1,322 @@
+#if defined(INTERACTIVE)
+
+#include "interactive.h"
+
+#define	PTRROW	5
+
+WINDOW		*win;
+extern int	optind;
+extern unsigned long read_samples;
+float		speed = 1;
+int		beinteractive = 0;	/* interactive mode */
+int		pfile = -1;		/* communication file descriptor */
+int		pausecount = 0;		/* total pause on 200000000 ns units */
+int		quit = 0;		/* quitting */
+
+#if defined(COMMUNICATION)
+int
+init_pipe() {
+	char		spfile[100], *home;
+	short		c;
+	int		pfile, err;
+	struct stat	fstat;
+
+	printf("sizeof(c): %d\n", sizeof(c));
+	home = getenv("HOME");
+	if (home); strncpy(spfile, home, sizeof(spfile)-1);
+	strcat(spfile, "/.soxi");
+
+	err = 0;
+	if ( ((err = stat(spfile, &fstat)) != 0) && (errno != ENOENT) )
+		printf("sox stat(%s, ) error: %s (%d)\n", spfile, strerror(errno), errno);
+	if ( (err = -1) && (errno == ENOENT) ) {
+		mkfifo(spfile, 0600);
+	} else {
+		if ( !S_ISFIFO(fstat.st_mode) ) printf("sox %s is not a pipe\n", spfile);
+	}
+
+	pfile = open(spfile, O_RDONLY|O_NONBLOCK);
+	if (pfile == -1) printf("sox cannot open(%s, O_RDONLY|O_NONBLOCK)\n", spfile);
+	return pfile;
+}
+
+
+short
+read_pipe(int pfile) {
+	short	c = 0;
+	int	err;
+
+	while (1) {
+		err = read(pfile, &c, 2);
+		if (err == -1) {
+			return -1;
+			if (errno != EAGAIN) printf("c: %04X, errno: %d - %s\n", c, errno, strerror(errno));
+		} else {
+			return c;
+			if (err > 0) printf("size: %d, c: %04X\n", err, c);
+		}
+	}
+}
+#endif
+
+
+void
+init_curses(WINDOW **pwin, ft_t informat0, ft_t outformat) {
+	*pwin = initscr();
+        cbreak();
+        noecho();
+	leaveok(*pwin, TRUE);	/* reducing cursor motions */
+	nodelay(*pwin, TRUE );	/* enable */
+	keypad(stdscr, TRUE);	/* KEY_LEFT etc. */
+	curs_set(0);
+	draw_fixed(win, 
+/*		st_filelength(informat0) / (informat0->info.rate * informat0->info.size * informat0->info.channels),	*/
+		informat0->length / informat0->info.rate /* / informat0->info.channels  ? */ ,
+		informat0, outformat);
+#if defined(COMMUNICATION)
+	pfile = init_pipe();
+#endif
+}
+
+void
+stop_curses(WINDOW *win) {
+	mvwprintw(win, Y0 + PTRROW+2, 0, "X");
+	mvwprintw(win, Y0 + PTRROW+5, 0, " ");
+	pauseprint(Y0 + PTRROW + 5);
+	mvwprintw(win, Y0 + PTRROW+6, 0, " ");
+	curs_set(1);
+	endwin();
+}
+
+char *
+hhmmss(int time) {
+	static char	stime[30];
+	struct tm	*tm;
+	time_t		timec = time;
+
+	tm = gmtime(&timec);
+	/* mday-1 cos it is Jan 1st '70 */
+	snprintf(stime, sizeof(stime), "%3d:%02d:%02d", (tm->tm_mday-1) * 24 + tm->tm_hour, tm->tm_min, tm->tm_sec);
+	return stime;
+}
+
+void
+draw_fixed(WINDOW *win, float ttime, ft_t informat0, ft_t outformat) {
+	int	col;
+
+	mvwprintw(win, Y0 + 0, 0, "Time				total: %s", hhmmss(ttime));
+	mvwprintw(win, Y0 + 1, 0, "Speed");
+	mvwprintw(win, Y0 + 2, 0, "%s -> %s", informat0->filename, outformat->filename);
+	for (col = 0; col <= COLS; col++) {
+		mvwprintw(win, Y0 + PTRROW-1, col, "_");
+		mvwprintw(win, Y0 + PTRROW+1, col, "^");
+	}
+}
+
+void
+draw_pos(WINDOW *win, float pos) {
+	static int	wpos = 0;
+	int		npos;
+
+	/* upper-left: (0,0) */
+	npos = (int)(pos * (COLS) + 0.0);
+/* mvwprintw(win, Y0 + 2, 60, "w/npos: %d->%d", wpos, npos); */
+	if ( (npos != wpos) || (npos == 0) ) {
+		mvwprintw(win, Y0 + PTRROW, wpos, " ");
+		wpos = npos;
+		mvwprintw(win, Y0 + PTRROW, wpos, "O");
+	}
+}
+
+/* rm20031122211133s.wav */
+/* 0123456789012345	 */
+/*   0123456789012345	 */
+
+/* 2004.10.27.rn18....	*/
+/* 0123 56 89   34	*/
+
+void
+rzm_off_time(WINDOW *win, float time, ft_t informat0) {
+	char	*name = informat0->filename, *nname;
+	int	ind, rmmp3ind[] = { 0, 1, 2, 3, 5, 6, 8, 9, 13, 14 }, mp3 = 1;
+
+	for (ind = 0; ind < sizeof(rmmp3ind)/sizeof(rmmp3ind[0]); ind++)
+		if ( !isdigit(name[rmmp3ind[ind]]) ) mp3 = 0;
+
+	if (mp3) {
+		int	hour, min = 00;	/* minutes after full hour */
+		hour = (name[14]-48) + (name[13]-48) * 10;
+		switch (hour) {
+			case 13:
+			case 18:	min = 10; break;
+			case 21:	min = 45; break;
+		}
+		time += min * 60 + hour * 3600;
+		/* modulo 1 day, e.g. do rn24... */
+		time -= 86400.0 * (int)(time / 86400);
+		mvwprintw(win, Y0 + 0, COLS-20, "file time: %s", hhmmss(time));
+		return;
+	}
+
+	/* not an mp3; get to the last slash */
+	while ( (nname = index(name, '/')) ) name = nname + 1;
+	
+	while ( !isdigit(name[0]) ) {
+		name++;
+		if (name[0] == '\0') return;
+	}
+
+	for (ind = 0; ind <= 13; ind++) if ( !isdigit(name[ind]) ) return;
+
+	time += (name[13]-48) + (name[12]-48) * 10 +
+		(name[11]-48) * 60 + (name[10]-48) * 600 +
+		(name[9]-48) * 3600 + (name[8]-48) * 36000 ;
+
+	mvwprintw(win, Y0 + 0, COLS-20, "file time: %s", hhmmss(time));
+}
+
+void
+restart_effect(float speed, struct st_effect efftab[]) {
+	char		buffer[100], *argv[2] = { buffer, NULL };
+
+	drain_effect(1);
+	(*efftab[1].h->stop)(&efftab[1]);
+	snprintf(buffer, sizeof(buffer), "%5.3f", 1/speed);
+	(*efftab[1].h->getopts)(&efftab[1], 1, &argv[0]);
+	(*efftab[1].h->start)(&efftab[1]);
+}
+
+
+void
+restart_all_eff(struct st_effect efftab[], struct st_effect efftabR[], int *pneffects, 
+	struct st_effect user_efftab[], int nuser_effects, int argc, char **argv) {
+	int neffects = *pneffects;
+
+	/* anything left - don't know if necessary */
+	drain_all_eff(neffects);
+	/* releasing output buffers */
+	release_effect_buf();
+	/* releasing effects' internal output buffers */
+	stop_effects();
+	optind = 0;
+	parse_effects(argc, argv);
+	/* build efftab */
+	check_effects();
+	/* Start all effects */
+	start_effects();
+	/* Reserve an output buffer for all effects */
+	reserve_effect_buf();
+
+	/* local into parameter */
+	*pneffects = neffects;
+}
+
+
+void
+pauseprint(int pos) {
+	mvwprintw(win, pos, 0, "Total pauses: %lf s\n", pausecount * 0.2);
+}
+
+
+short
+read_char(WINDOW *win, int pfile) {
+	short	c = 0;
+
+#if defined(COMMUNICATION)
+	if (pfile != -1) {
+		c = read_pipe(pfile);
+		if ( (c != -1) && (c != 0) ) return c;
+	}
+#endif
+	c = wgetch(win);
+	return c;
+}
+
+
+/* interactive control */
+int
+interactive(WINDOW *win, ft_t informat0, ft_t outformat, struct st_effect efftab[], struct st_effect efftabR[], int *pneffects,
+		struct st_effect user_efftab[], int nuser_effects, int *pquit) {
+	int		jump, c, chspeed;
+	static int	pause = 0;
+	char		buf[100], *argv[10];
+	float		tmpspeed;
+	static float	time = 0, ptime, pos = 0, oldspeed = -1;
+	static struct timespec	sl = { 0, 200000000 };
+
+	if (oldspeed == -1) oldspeed = speed;
+
+	time = (double)(read_samples) / (double)(informat0->info.rate);
+	pos = (double)(read_samples) / (double)(informat0->length);
+	draw_pos(win, pos);
+
+	chspeed = 0;
+	ptime = time;
+pause:
+	while ( (c = read_char(win, pfile)) != ERR) {
+		/* mvwprintw(win, Y0 + 0, COLS-20, "%c (%d)", c, c); */
+		switch (c) {
+			case '[':	time -= 2; if (time < 0) time = 0; break;
+			case ']':	time += 1; break;
+			case '{':	time -= 4; if (time < 0) time = 0; break;
+			case '}':	time += 3; break;
+			case KEY_LEFT:	time -= 30; if (time < 0) time = 0; break;
+			case KEY_RIGHT:	time += 30; break;
+			case KEY_SLEFT:	time -= 600; if (time < 0) time = 0; break;
+			case KEY_SRIGHT: time += 600; break;
+			case KEY_DOWN:	speed -= 0.1; if (speed <= 0) speed = 0.1; chspeed = 1; break;
+			case KEY_UP:	speed += 0.1; if (speed > 5) speed = 5; chspeed = 1; break;
+			case KEY_NPAGE:	speed -= 0.2; if (speed <= 0) speed = 0.1; chspeed = 1; break;
+			case KEY_PPAGE:	speed += 0.2; if (speed > 5) speed = 5; chspeed = 1; break;
+			case '\'':	tmpspeed = oldspeed; oldspeed = speed; speed = tmpspeed; chspeed = 1; break;
+			case 'p':	pause = !pause; break;
+
+			/* upper keys row scale - except SPACE */
+			case '`':	oldspeed = speed; speed = 0.6; chspeed = 1; break;
+			case '1':	oldspeed = speed; speed = 0.7; chspeed = 1; break;
+			case '2':	oldspeed = speed; speed = 0.9; chspeed = 1; break;
+			case ' ':	oldspeed = speed; speed = 1;   chspeed = 1; break;
+			case '3':	oldspeed = speed; speed = 1.1; chspeed = 1; break;
+			case '4':	oldspeed = speed; speed = 1.3; chspeed = 1; break;
+			case '5':	oldspeed = speed; speed = 1.6; chspeed = 1; break;
+			case '6':	oldspeed = speed; speed = 1.8; chspeed = 1; break;
+			case '7':	oldspeed = speed; speed = 2.0; chspeed = 1; break;
+			case '8':	oldspeed = speed; speed = 2.2; chspeed = 1; break;
+			case '9':	oldspeed = speed; speed = 2.4; chspeed = 1; break;
+			case '0':	oldspeed = speed; speed = 2.6; chspeed = 1; break;
+			case '-':	oldspeed = speed; speed = 2.8; chspeed = 1; break;
+			case '=':	oldspeed = speed; speed = 3.0; chspeed = 1; break;
+			case '\177':	oldspeed = speed; speed = 3.2; chspeed = 1; break;
+
+			case '':	/* redrawwin(win); */ init_curses(&win, informat0, outformat); break;
+			case 'q':	*pquit = 1; break;
+			default:	break;
+		}
+	}
+
+	if (pause) { nanosleep(&sl, NULL); pausecount++; goto pause; }
+
+	jump = (time != ptime);
+
+	if (jump) {
+		(*informat0->h->seek)(informat0, time*informat0->info.rate);
+		read_samples = time * (double)(informat0->info.rate);
+	}
+	if (chspeed) {
+		mvwprintw(win, Y0 + 1, 8, "%.1f", speed);
+		/* restart_effect(speed); */
+		argv[0] = "stretch";
+		snprintf(buf, sizeof(buf), "%f", 1/speed);
+		argv[1] = buf;
+		argv[2] = NULL;
+		restart_all_eff(efftab, efftabR, pneffects, user_efftab, nuser_effects, 2, argv);
+	}
+
+	mvwprintw(win, Y0 + 0, 8, "%s  %4.1f%%", hhmmss(time), 100*pos);
+#if defined(RZM)
+	rzm_off_time(win, time, informat0);
+#endif /* RZM */
+	return jump;
+}
+
+#endif	/* defined(INTERACTIVE) */
diff -Nru sox.20050917/src/interactive.h sox.20050917-inst/src/interactive.h
--- sox.20050917/src/interactive.h	1970-01-01 01:00:00.000000000 +0100
+++ sox.20050917-inst/src/interactive.h	2005-09-17 18:34:23.000000000 +0200
@@ -0,0 +1,48 @@
+/* interactive.h - various structures and defines used by interactive interface. */
+
+#ifndef INTERACTIVE_H_INCLUDED
+#define INTERACTIVE_H_INCLUDED
+
+#include "st.h"
+#include "st_i.h"
+
+#include <ncurses.h>
+#include <time.h>
+#include <sys/time.h>
+#include <strings.h>
+
+/* pipe */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <ctype.h>
+#define Y0      10      /* first row    */
+
+extern WINDOW  *win;
+extern int	beinteractive, quit;	/* interactive mode */
+
+void init_curses(WINDOW **pwin, ft_t informat0, ft_t outformat);
+void stop_curses(WINDOW *win);
+void draw_fixed(WINDOW *win, float ttime, ft_t informat0, ft_t outformat);
+void draw_pos(WINDOW *win, float pos);
+void pauseprint();
+int interactive(WINDOW *win, ft_t informat0, ft_t outformat, struct st_effect efftab[], struct st_effect efftabR[], int *pneffects,
+	struct st_effect user_efftab[], int nuser_effects, int *pquit);
+
+/* should be in sox.h ? */
+int drain_effect(int);
+void drain_all_eff(int neffects);
+void relbuf_all_eff(struct st_effect efftab[], struct st_effect efftabR[], int neffects);
+void stop_all_eff(struct st_effect efftab[], struct st_effect efftabR[], int neffects);
+void parse_eff(int argc, char **argv, struct st_effect user_efftab[], int *pnuser_effects);
+void checkeffect(int *pneffects);
+void start_all_eff(struct st_effect efftab[], struct st_effect efftabR[], int neffects);
+void resbuf_all_eff(struct st_effect efftab[], struct st_effect efftabR[], int neffects);
+
+#endif /* INTERACTIVE_H_INCLUDED */
+
diff -Nru sox.20050917/src/Makefile.in sox.20050917-inst/src/Makefile.in
--- sox.20050917/src/Makefile.in	2005-09-17 18:13:03.000000000 +0200
+++ sox.20050917-inst/src/Makefile.in	2005-09-17 18:34:23.000000000 +0200
@@ -25,10 +25,10 @@
 LN_S    = @LN_S@
 
 # Build macros.
-CFLAGS	= @CFLAGS@ -I$(srcdir) -I$(builddir)
+CFLAGS	= @CFLAGS@ -I$(srcdir) -I$(builddir) -DINTERACTIVE -DRZM -DCOMMUNICATION
 CPPFLAGS = @CPPFLAGS@
 LDFLAGS	= -L. @LDFLAGS@
-LIBS	= -lst @LIBS@
+LIBS	= -lst @LIBS@ -lncurses
 
 # Other macros.
 
@@ -67,7 +67,7 @@
 SUNAUOBJ_1  = sunaudio.o
 ALSAOBJ_0   =
 ALSAOBJ_1   = alsa.o
-EXTRAOBJS   = $(OSSOBJ_$(NEED_OSS)) $(SUNAUOBJ_$(NEED_SUNAU)) $(ALSAOBJ_$(NEED_ALSA)) $(GSMOBJ_$(GSM_SUPPORT))
+EXTRAOBJS   = $(OSSOBJ_$(NEED_OSS)) $(SUNAUOBJ_$(NEED_SUNAU)) $(ALSAOBJ_$(NEED_ALSA)) $(GSMOBJ_$(GSM_SUPPORT)) interactive.o
 
 LIBOBJS = $(FOBJ) $(EOBJ) handlers.o stio.o misc.o util.o getopt.o $(EXTRAOBJS)
 
diff -Nru sox.20050917/src/sox.c sox.20050917-inst/src/sox.c
--- sox.20050917/src/sox.c	2005-09-17 18:13:04.000000000 +0200
+++ sox.20050917-inst/src/sox.c	2005-09-18 00:55:11.000000000 +0200
@@ -59,6 +59,10 @@
 #define strdup _strdup
 #endif
 
+#if defined(INTERACTIVE)
+#include <interactive.h>
+#endif
+
 /*
  * SOX main program.
  *
@@ -71,11 +75,12 @@
 static int clipped = 0;         /* Volume change clipping errors */
 static int writing = 1;         /* are we writing to a file? assume yes. */
 static int soxpreview = 0;      /* preview mode */
+int bufferr = 0;		/* buffer error messages */
 
-static int quite = 0;
+static int quiet = 0;
 static int status = 0;
 static unsigned long input_samples = 0;
-static unsigned long read_samples = 0;
+unsigned long read_samples = 0;
 static unsigned long output_samples = 0;
 
 static st_sample_t ibufl[ST_BUFSIZ/2];    /* Left/right interleave buffers */
@@ -102,16 +107,9 @@
 static void update_status(void);
 static void statistics(void);
 static st_sample_t volumechange(st_sample_t *buf, st_ssize_t ct, double vol);
-static void parse_effects(int argc, char **argv);
-static void check_effects(void);
-static void start_effects(void);
-static void reserve_effect_buf(void);
 static int flow_effect_out(void);
 static int flow_effect(int);
 static int drain_effect_out(void);
-static int drain_effect(int);
-static void release_effect_buf(void);
-static void stop_effects(void);
 
 #define MAX_INPUT_FILES 32
 #define MAX_FILES MAX_INPUT_FILES + 1
@@ -245,6 +243,8 @@
     }
 
     /* Loop through the reset of the arguments looking for effects */
+    /* in interactive mode assure that there is  stretch 1  effect ?
+       and add it if missing - otherwise we need to have always on the command line */
     parse_effects(argc, argv);
 
     process();
@@ -260,9 +260,9 @@
 }
 
 #ifdef HAVE_GETOPT_H
-static char *getoptstr = "+r:v:t:c:phsuUAaigbwlfdxVSq";
+static char *getoptstr = "+r:v:t:c:phsuUAaigbwlfdxVSqI";
 #else
-static char *getoptstr = "r:v:t:c:phsuUAaigbwlfdxVSq";
+static char *getoptstr = "r:v:t:c:phsuUAaigbwlfdxVSqI";
 #endif
 
 static void doopts(file_options_t *fo, int argc, char **argv)
@@ -366,13 +366,23 @@
 
             case 'S':
                 status = 1;
-                quite = 0;
+                quiet = 0;
                 break;
 
             case 'q':
                 status = 0;
-                quite = 1;
+                quiet = 1;
                 break;
+
+#if defined(INTERACTIVE)
+	    case 'I':
+		beinteractive = 1;
+		bufferr = 1;
+                status = 0;
+                quiet = 1;
+		break;
+#endif
+
         }
     }
 }
@@ -391,6 +401,38 @@
     return ST_SUCCESS;
 }
 
+/* Drain all effects */
+void drain_all_eff(int neffects) {
+    int f;
+    /* Drain the effects out first to last,
+     * pushing residue through subsequent effects */
+    /* oh, what a tangled web we weave */
+    for(f = 1; f < neffects; f++)
+    {
+        while (1) {
+
+            if (drain_effect(f) == 0)
+                break;          /* out of while (1) */
+
+            /* Change the volume of this output data if needed. */
+            if (writing && file_opts[file_count-1]->volume != 1.0)
+                clipped += volumechange(efftab[neffects-1].obuf, 
+                                        efftab[neffects-1].olen,
+                                        file_opts[file_count-1]->volume);
+
+            /* FIXME: Need to look at return code and abort on failure */
+            if (writing && efftab[neffects-1].olen > 0)
+                (*file_desc[file_count-1]->h->write)(file_desc[file_count-1], 
+                                                     efftab[neffects-1].obuf,
+                                                     (st_ssize_t)efftab[neffects-1].olen);
+
+            if (efftab[f].olen != ST_BUFSIZ)
+                break;
+        }
+    }
+}
+
+
 void optimize_trim(void)
 {
     /* Speed hack.  If the "trim" effect is the first effect then
@@ -478,7 +520,7 @@
             strcmp(file_desc[file_count-1]->filetype, "ossdsp") == 0 ||
             strcmp(file_desc[file_count-1]->filetype, "sunau") == 0)
         {
-            if (!quite)
+            if (!quiet)
                 status = 1;
         }
 
@@ -544,10 +586,15 @@
     for(e = 1; e < neffects; e++)
         efftab[e].odone = efftab[e].olen = 0;
 
+#if defined(INTERACTIVE)
+    if (beinteractive) init_curses(&win, file_desc[0], file_desc[file_count-1]);
+#endif
+
     /* Run input data through effects and get more until olen == 0 
      * (or ST_EOF).
      */
     do {
+	int	jump = 0;
 #ifndef SOXMIX
         efftab[0].olen = 
         ilen = (*file_desc[current_input]->h->read)(file_desc[current_input],
@@ -664,7 +711,7 @@
 
         /* If not writing and no effects are occuring then not much
          * reason to continue reading.  This allows this case.  Mainly
-         * useful to print out info about input file header and quite.
+         * useful to print out info about input file header and quit.
          */
         if (!writing && neffects == 1)
             efftab[0].olen = 0;
@@ -672,18 +719,30 @@
         if (efftab[0].olen == 0)
             break;
 
-        flowstatus = flow_effect_out();
+	/* play only if we do not skip just now */
+	if (!jump) flowstatus = flow_effect_out();
+
+#if defined(INTERACTIVE)
+	if (beinteractive) jump = interactive(win, file_desc[0], file_desc[file_count-1], efftab, efftabR, &neffects, user_efftab, nuser_effects, &quit);
+#endif
 
         if (status)
             update_status();
 
         /* Negative flowstatus says no more output will ever be generated. */
         if (flowstatus == ST_EOF || 
-            (writing && file_desc[file_count-1]->st_errno))
+	    (writing && file_desc[file_count-1]->st_errno) || quit)
             break;
 
     } while (1); 
 
+#if defined(INTERACTIVE)
+    if (beinteractive) {
+	interactive(win, file_desc[0], file_desc[file_count-1], efftab, efftabR, &neffects, user_efftab, nuser_effects, &quit);
+	stop_curses(win);
+    }
+#endif
+
     /* This will drain the effects */
     drain_effect_out();
 
@@ -723,7 +782,7 @@
     }
 }
 
-static void parse_effects(int argc, char **argv)
+void parse_effects(int argc, char **argv)
 {
     int argc_effect;
 
@@ -769,7 +828,7 @@
  * Smart ruleset for multiple effects in sequence.
  *      Puts user-specified effect in right place.
  */
-static void check_effects(void)
+void check_effects(void)
 {
     int i;
     int needchan = 0, needrate = 0, haschan = 0, hasrate = 0;
@@ -951,7 +1010,7 @@
     }
 }
 
-static void start_effects(void)
+void start_effects(void)
 {
     int e;
 
@@ -962,7 +1021,7 @@
     }
 }
 
-static void reserve_effect_buf(void)
+void reserve_effect_buf(void)
 {
     int e;
 
@@ -1230,7 +1289,7 @@
     return flow_effect_out();
 }
 
-static int drain_effect(int e)
+int drain_effect(int e)
 {
     st_ssize_t i, olen, olenl, olenr;
     st_sample_t *obuf;
@@ -1277,7 +1336,7 @@
     return rc;
 }
 
-static void release_effect_buf(void)
+void release_effect_buf(void)
 {
     int e;
     
@@ -1289,7 +1348,7 @@
     }
 }
 
-static void stop_effects(void)
+void stop_effects(void)
 {
     int e;
 
@@ -1427,7 +1486,11 @@
         if (opt)
                 fprintf(stderr, "Failed: %s\n", opt);
         else {
-            fprintf(stderr,"gopts: -e -h -p -q -S -V\n\n");
+	    fprintf(stderr,"gopts: -e -h -p -q -S -V");
+#if defined(INTERACTIVE)
+	    fprintf(stderr," -I");
+#endif
+	    fprintf(stderr,"\n\n");
             fprintf(stderr,"fopts: -r rate -c channels -s/-u/-U/-A/-a/-i/-g/-f -b/-w/-l/-d -v volume -x\n\n");
             fprintf(stderr, "effect: ");
             for (i = 0; st_effects[i].name != NULL; i++) {
Pliki binarne sox.20050917/src/.sox.c.swp i sox.20050917-inst/src/.sox.c.swp się różnią
diff -Nru sox.20050917/src/st.h sox.20050917-inst/src/st.h
--- sox.20050917/src/st.h	2005-09-17 18:13:04.000000000 +0200
+++ sox.20050917-inst/src/st.h	2005-09-18 00:54:10.000000000 +0200
@@ -295,6 +295,16 @@
 #define ST_ENOTSUP 2005         /* Operation not supported */
 #define ST_EINVAL 2006          /* Invalid argument */
 
+/* here or elsewhere? - rzm */
+int drain_effect(int e);
+void parse_effects(int argc, char **argv);
+void check_effects(void);
+void start_effects(void);
+void reserve_effect_buf(void);
+void release_effect_buf(void);
+void stop_effects(void);
+
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif
diff -Nru sox.20050917/src/st_i.h sox.20050917-inst/src/st_i.h
--- sox.20050917/src/st_i.h	2005-09-17 18:13:04.000000000 +0200
+++ sox.20050917-inst/src/st_i.h	2005-09-17 18:34:24.000000000 +0200
@@ -1,7 +1,7 @@
 #ifndef ST_I_H
 #define ST_I_H
 /*
- * Sound Tools Interal - October 11, 2001
+ * Sound Tools Internal - October 11, 2001
  *
  *   This file is meant for libst internal use only
  *
@@ -140,7 +140,13 @@
  * to perform file I/O.  It can be useful to pass in similar sized
  * data to get max performance.
  */
+#if defined(INTERACTIVE)
+/* the buffer size is  compromise between ability to quickly skip to next position and performance+clicking noise */
+/* #define ST_BUFSIZ 128	*/	/* not catching up */
+#define ST_BUFSIZ (1*1024)
+#else
 #define ST_BUFSIZ 8192
+#endif
 
 /*=============================================================================
  * File Handlers
diff -Nru sox.20050917/src/util.c sox.20050917-inst/src/util.c
--- sox.20050917/src/util.c	2005-09-17 18:13:04.000000000 +0200
+++ sox.20050917-inst/src/util.c	2005-09-17 18:34:24.000000000 +0200
@@ -34,6 +34,10 @@
  * the ST library.
  */
 char *myname = 0;
+extern int bufferr;
+int namelen;
+
+char	bufrep[100];
 
 void st_report(const char *fmt, ...)
 {
@@ -42,36 +46,73 @@
         if (! verbose)
                 return;
 
-        fprintf(stderr, "%s: ", myname);
-        va_start(args, fmt);
-        vfprintf(stderr, fmt, args);
-        va_end(args);
-        fprintf(stderr, "\n");
+	if (!bufferr) {
+            fprintf(stderr, "%s: ", myname);
+            va_start(args, fmt);
+            vfprintf(stderr, fmt, args);
+            va_end(args);
+            fprintf(stderr, "\n");
+	} else {
+	    namelen = 0;
+	    if (myname) {
+		snprintf(bufrep, sizeof(bufrep), "%s: ", myname);
+		namelen = strlen(myname);
+	    }
+            va_start(args, fmt);
+	    vsnprintf(bufrep + namelen, sizeof(bufrep) - namelen, fmt, args);
+            va_end(args);
+	}
 }
 
+
+char	bufwarn[100];
+
 void st_warn(const char *fmt, ...)
 {
         va_list args;
 
-        fprintf(stderr, "%s: ", myname);
-        va_start(args, fmt);
-
-        vfprintf(stderr, fmt, args);
-        va_end(args);
-        fprintf(stderr, "\n");
+	if (!bufferr) {
+            fprintf(stderr, "%s: ", myname);
+            va_start(args, fmt);
+            vfprintf(stderr, fmt, args);
+            va_end(args);
+            fprintf(stderr, "\n");
+	} else {
+	    namelen = 0;
+	    if (myname) {
+		snprintf(bufrep, sizeof(bufrep), "%s: ", myname);
+		namelen = strlen(myname);
+	    }
+            va_start(args, fmt);
+	    vsnprintf(bufrep + namelen, sizeof(bufrep) - namelen, fmt, args);
+            va_end(args);
+	}
 }
 
+
+char	buffail[100];
+
 void st_fail(const char *fmt, ...)
 {
         va_list args;
         extern void cleanup();
 
-        fprintf(stderr, "%s: ", myname);
-
-        va_start(args, fmt);
-        vfprintf(stderr, fmt, args);
-        va_end(args);
-        fprintf(stderr, "\n");
+	if (!bufferr) {
+            fprintf(stderr, "%s: ", myname);
+            va_start(args, fmt);
+            vfprintf(stderr, fmt, args);
+            va_end(args);
+            fprintf(stderr, "\n");
+	} else {
+	    namelen = 0;
+	    if (myname) {
+		snprintf(bufrep, sizeof(bufrep), "%s: ", myname);
+		namelen = strlen(myname);
+	    }
+            va_start(args, fmt);
+	    vsnprintf(bufrep + namelen, sizeof(bufrep) - namelen, fmt, args);
+            va_end(args);
+	}
         cleanup();
         exit(2);
 }
