diff -Nru wavplay-1.3/README-1.4pre1 wavplay-1.4/README-1.4pre1
--- wavplay-1.3/README-1.4pre1	Thu Jan  1 09:30:00 1970
+++ wavplay-1.4/README-1.4pre1	Wed Feb 24 20:01:34 1999
@@ -0,0 +1,37 @@
+This version of wavplay (1.4pre1) has a number of improvements and bugfixes
+over 1.3:
+
+ - an extra option was added to wavplay/wavrec: namely -d, which allows
+   specification of an alternative audio device.  This is to allow
+   reasonably quick access to a second soundcard via the command line rather
+   than the AUDIODEV environment variable.
+
+ - a small fix was applied to FilesDlgOKCB() so it ignored empty XmStrings
+   passed from the file selector dialog when a directory was selected:
+     static void
+     FilesDlgOKCB(Widget w,XtPointer client_data,XtPointer call_data) {
+       XmFileSelectionBoxCallbackStruct *ptr =
+         (XmFileSelectionBoxCallbackStruct *) call_data;
+       if (!XmStringEmpty(ptr->value))
+             PutFileSelection(ptr->value);
+     }
+
+ - some actions immediately after starting the program (eg: setting 8/16 bit
+   sample size) would not clear all of the help strings displayed in the
+   File/type/date/size fields.  This has been fixed.
+
+ - During record, the size, duration and number of samples is updated as the
+   recording progresses.
+
+ - a time display was added.  This allows a user to start playback from any
+   point in the file.  While playing, this display also tracks the current
+   position within the file.  The display is calibrated in 25 fps SMPTE
+   format.
+
+ - 24Feb1999: the block size request to the sounddriver now follows the
+   setting of sampling rate, sample size etc since doing it before these are
+   set results in undefined behaviour.
+
+Jonathan Woithe
+21 November 1998
+(Updated 24 February 1999)
diff -Nru wavplay-1.3/client.c wavplay-1.4/client.c
--- wavplay-1.3/client.c	Fri Sep 18 01:33:41 1998
+++ wavplay-1.4/client.c	Sat Nov  7 14:54:40 1998
@@ -262,6 +262,25 @@
 }
 
 /*
+ * Tell server to start at a new sample number:
+ */
+int
+tosvr_start_sample(int flags, ErrFunc erf, UInt32 sample) {
+	SVRMSG msg;
+	int z;
+
+	v_erf = erf;				/* Error reporting function */
+
+	msg.msg_type = ToSvr_StartSample;
+	msg.u.tosvr_start_sample.StartSample = sample;
+	msg.bytes = sizeof msg.u.tosvr_start_sample;
+
+	if ( (z = MsgToServer(svrIPC,&msg,flags)) != 0 && erf != NULL )
+		err("%s: Sending server message 'start_sample'",sys_errlist[errno]);
+
+	return z;
+}
+/*
  * Tell server to use new sampling rate:
  */
 int
diff -Nru wavplay-1.3/client.h wavplay-1.4/client.h
--- wavplay-1.3/client.h	Fri Sep 18 01:33:41 1998
+++ wavplay-1.4/client.h	Sat Nov  7 14:55:00 1998
@@ -60,6 +60,7 @@
 
 extern int tosvr_path(const char *path,int flags,ErrFunc erf);	/* Tell server a pathname */
 extern int tosvr_bits(int flags,ErrFunc erf,int bits);		/* Tell server bits override */
+extern int tosvr_start_sample(int flags, ErrFunc eft, UInt32 sample);      /* Tell server to start at sample */
 extern int tosvr_sampling_rate(int flags,ErrFunc erf,UInt32 sampling_rate);
 extern int tosvr_chan(int flags,ErrFunc erf,Chan chan);		/* Override Mono/Stereo */
 extern int tosvr_record(int flags,ErrFunc erf,
diff -Nru wavplay-1.3/file.c wavplay-1.4/file.c
--- wavplay-1.3/file.c	Fri Sep 18 01:33:41 1998
+++ wavplay-1.4/file.c	Tue Mar 23 19:57:58 1999
@@ -68,6 +68,15 @@
 #include <linux/soundcard.h>
 #include "wavplay.h"
 
+extern int clntIPC;	/* Needed for message passing in PlayDSP */
+
+/* Number of updates sent to the client per second during playback and      */
+/* record.  For high sample rates in stereo, too many per second floods the */
+/* client.  3 is a compromise between update speed and smoothness; 4 tends  */
+/* to cause "jumpy" updates.  (The cause of the jumps probably lie in       */
+/* LessTif and/or X since the IPC messages are sent regularly). */
+#define RECPLAY_UPDATES_PER_SEC		3
+
 static ErrFunc v_erf;				/* This module's error reporting function */
 static char emsg[2048];
 
@@ -188,6 +197,7 @@
 	wfile->wavinfo.Samples = (UInt32) samples;
 	wfile->wavinfo.DataBits = (UInt16) sample_bits;
 	wfile->wavinfo.DataStart = (UInt32) datastart;
+	wfile->num_samples = wfile->wavinfo.Samples;
 	wfile->rw = 'R';			/* Read mode */
 
 	offset = wfile->wavinfo.DataStart - 4;
@@ -237,7 +247,7 @@
  */
 void
 WavReadOverrides(WAVFILE *wfile,WavPlayOpts *wavopts) {
-
+	UInt32 num_samples;
 	/*
 	 * Override sampling rate: -s sampling_rate
 	 */
@@ -263,10 +273,23 @@
 	}
 
 	/*
+	 * Set the first sample:
+	 */
+	wfile->StartSample = 0;
+	num_samples = wfile->wavinfo.Samples = wfile->num_samples;
+	if ( wavopts->StartSample != 0 ) {
+		wfile->StartSample = wavopts->StartSample;
+		wfile->wavinfo.Samples -= wfile->StartSample;
+	}
+
+	/*
 	 * Override # of samples if -t seconds option given:
 	 */
-	if ( wavopts->Seconds != 0 )
+	if ( wavopts->Seconds != 0 ) {
 		wfile->wavinfo.Samples = wavopts->Seconds * wfile->wavinfo.SamplingRate;
+		if (wfile->StartSample+wfile->wavinfo.Samples > num_samples)
+			wfile->wavinfo.Samples = num_samples-1;
+	}
 }
 
 /*
@@ -418,32 +441,7 @@
 		err("%s:\nOpening audio device %s",
 			sys_errlist[errno],
 			env_AUDIODEV);
-		goto errxit;
-	}
 
-	/*
-	 * Determine the audio device's block size:
-	 */
-	if ( ioctl(dfile->fd,SNDCTL_DSP_GETBLKSIZE,&dfile->dspblksiz) < 0 ) {
-		err("%s: Optaining DSP's block size",sys_errlist[errno]);
-		goto errxit;
-	}
-
-	/*
-	 * Check the range on the buffer sizes:
-	 */
-	if ( dfile->dspblksiz < 4096 || dfile->dspblksiz > 65536 ) {
-		err("%s: Audio block size (%d bytes)",
-			sys_errlist[errno=EINVAL],
-			(int)dfile->dspblksiz);
-		goto errxit;
-	} 
-
-	/*
-	 * Allocate a buffer to do the I/O through:
-	 */
-	if ( (dfile->dspbuf = (char *) malloc(dfile->dspblksiz)) == NULL ) {
-		err("%s: For DSP I/O buffer",sys_errlist[errno]);
 		goto errxit;
 	}
 
@@ -477,6 +475,35 @@
 	}
 
 	/*
+	 * Determine the audio device's block size.  Should be done after
+	 * setting sampling rate etc.
+	 */
+	if ( ioctl(dfile->fd,SNDCTL_DSP_GETBLKSIZE,&dfile->dspblksiz) < 0 ) {
+		err("%s: Optaining DSP's block size",sys_errlist[errno]);
+		goto errxit;
+	}
+
+	/*
+	 * Check the range on the buffer sizes:
+	 */
+	/* Minimum was 4096 but es1370 returns 1024 for 44.1kHz, 16 bit */
+	/* and 64 for 8130Hz, 8 bit */
+	if ( dfile->dspblksiz < 32 || dfile->dspblksiz > 65536 ) {
+		err("%s: Audio block size (%d bytes)",
+			sys_errlist[errno=EINVAL],
+			(int)dfile->dspblksiz);
+		goto errxit;
+	} 
+
+	/*
+	 * Allocate a buffer to do the I/O through:
+	 */
+	if ( (dfile->dspbuf = (char *) malloc(dfile->dspblksiz)) == NULL ) {
+		err("%s: For DSP I/O buffer",sys_errlist[errno]);
+		goto errxit;
+	}
+
+	/*
 	 * Return successfully opened device:
 	 */
 	return dfile;				/* Return file descriptor */
@@ -530,6 +557,8 @@
 	int bytes;
 	int n;
 	int byte_modulo;
+	int total_bytes, update_bytes;
+	SVRMSG msg;
 
 	v_erf = erf;				/* Set error reporting function */
 
@@ -571,10 +600,19 @@
 
 	byte_modulo = byte_count;				/* This many bytes per sample */
 	byte_count  = wfile->wavinfo.Samples * byte_modulo;	/* Total bytes to process */
+	total_bytes = byte_count;
+	
+	/* Number of bytes to write between client updates.  Must be */
+	/* a multiple of dspblksiz.  */
+	update_bytes = ((wfile->wavinfo.SamplingRate*byte_modulo)/
+		(RECPLAY_UPDATES_PER_SEC*dfile->dspblksiz))*dfile->dspblksiz;
 
 	if ( ioctl(dfile->fd,SNDCTL_DSP_SYNC,0) != 0 )
 		err("%s: ioctl(%d,SNDCTL_DSP_SYNC,0)",sys_errlist[errno]);
 
+	/* Seek to requested start sample */
+	lseek(wfile->fd,wfile->StartSample*byte_modulo,SEEK_CUR);
+
 	for ( ; byte_count > 0 && wfile->wavinfo.DataBytes > 0; byte_count -= (UInt32) n ) {
 
 		bytes = (int) ( byte_count > dfile->dspblksiz ? dfile->dspblksiz : byte_count );
@@ -589,6 +627,14 @@
 			goto errxit;
 		}
 
+		if ((clntIPC >= 0) && !((total_bytes-byte_count) % update_bytes)) {
+			msg.msg_type = ToClnt_PlayState;
+			msg.bytes = sizeof(msg.u.toclnt_playstate);
+			msg.u.toclnt_playstate.SamplesLeft = byte_count / byte_modulo;
+			msg.u.toclnt_playstate.CurrentSample = 
+			  wfile->num_samples - msg.u.toclnt_playstate.SamplesLeft;
+			MsgToClient(clntIPC,&msg,0);	/* Tell client playback status */
+		}
 		if ( write(dfile->fd,dfile->dspbuf,n) != n ) {
 			err("Writing samples to audio device",sys_errlist[errno]);
 			goto errxit;
@@ -608,6 +654,15 @@
 	if ( ioctl(dfile->fd,SNDCTL_DSP_SYNC,0) != 0 )
 		err("%s: ioctl(%d,SNDCTL_DSP_SYNC,0)",sys_errlist[errno]);
 #endif
+	/* Update client time display at end of sucessful play */
+	if (clntIPC >= 0) {
+		msg.msg_type = ToClnt_PlayState;
+		msg.bytes = sizeof(msg.u.toclnt_playstate);
+		msg.u.toclnt_playstate.SamplesLeft = byte_count / byte_modulo;
+		msg.u.toclnt_playstate.CurrentSample = 
+		  wfile->num_samples - msg.u.toclnt_playstate.SamplesLeft;
+		MsgToClient(clntIPC,&msg,0);	/* Tell client playback status */
+	}
 	return 0;	/* All samples played successfully */
 
 errxit:	return -1;	/* Indicate error return */
@@ -625,9 +680,10 @@
 	int n;
 	UInt32 bytes_per_sample = 0;
 	UInt32 bytes_written = 0;
+	int update_bytes;
+	SVRMSG msg;
 
 	v_erf = erf;				/* Set error reporting function */
-
 	/*
 	 * Check that the WAVFILE is open for writing:
 	 */
@@ -674,6 +730,11 @@
 		byte_count = (chunk + (byte_count-1)) & ~(byte_count-1);
 	}
 
+	/* Number of bytes to write between client updates.  Must be */
+	/* a multiple of dspblksiz. */
+	update_bytes = ((wfile->wavinfo.SamplingRate*bytes_per_sample)/
+		(RECPLAY_UPDATES_PER_SEC*dfile->dspblksiz))*dfile->dspblksiz;
+
 	while ( 1 ) {
 		/*
 		 * Determine how many samples to read:
@@ -705,6 +766,13 @@
 		}
 
 		bytes_written += bytes;
+		if ((clntIPC >= 0) && !(bytes_written % update_bytes)) {
+			msg.msg_type = ToClnt_RecState;
+			msg.bytes = sizeof(msg.u.toclnt_recstate);
+			msg.u.toclnt_recstate.bytes_written = bytes_written;
+			msg.u.toclnt_recstate.num_samples = bytes_written / bytes_per_sample;
+			MsgToClient(clntIPC,&msg,0);	/* Tell client playback status */
+		}
 
 		if ( samples > 0 )
 			if ( (byte_count -= (unsigned) n) < 1 )
diff -Nru wavplay-1.3/msg.c wavplay-1.4/msg.c
--- wavplay-1.3/msg.c	Fri Sep 18 01:33:41 1998
+++ wavplay-1.4/msg.c	Fri Nov 13 19:45:13 1998
@@ -162,6 +162,9 @@
 		"ToSvr_Debug",			/* Tell server debug mode setting */
 		"ToClnt_ErrMsg",		/* Tell client an error message from server */
 		"ToSvr_SemReset",		/* Tell server to reset its locking semaphores */
+		"ToSvr_StartSample",		/* Tell server where to start playback from */
+		"ToClnt_PlayState",		/* Tell client state of playback */
+		"ToClnt_RecState"		/* Tell client state of recording */
 	};
 	static char buf[16];
 
diff -Nru wavplay-1.3/recplay.c wavplay-1.4/recplay.c
--- wavplay-1.3/recplay.c	Fri Sep 18 01:33:41 1998
+++ wavplay-1.4/recplay.c	Fri Nov 13 18:47:21 1998
@@ -183,7 +183,6 @@
 		Pathname = svr.path;		/* so this is the pathname.. */
 		wfile = svr.wfile;		/* And the file is already opened */
 	}
-
 	if ( (dfile = OpenDSP(wfile,O_RDWR,v_erf)) == NULL )
 		goto errxit;
 
diff -Nru wavplay-1.3/server.c wavplay-1.4/server.c
--- wavplay-1.3/server.c	Fri Sep 18 01:33:41 1998
+++ wavplay-1.4/server.c	Sat Nov  7 21:21:49 1998
@@ -173,6 +173,7 @@
 		/*
 		 * Reset any overrides:
 		 */
+		svr.opts.StartSample = 0;
 		svr.opts.SamplingRate.optChar = 0;
 		svr.opts.Channels.optChar = 0;
 		svr.opts.DataBits.optChar = 0;
@@ -234,6 +235,7 @@
 		/*
 		 * Reset all overrides:
 		 */
+		svr.opts.StartSample = 0;
 		svr.opts.SamplingRate.optChar = 0;
 		svr.opts.Channels.optChar = 0;
 		svr.opts.DataBits.optChar = 0;
@@ -288,6 +290,11 @@
 			UnlockDSP(svr.lockIPCID,0,x_erf);
 		return 0;
 
+	} else if ( pmsg->msg_type == ToSvr_StartSample ) {
+		if ( bWorkProc )				/* In a work proc? */
+			return 1;				/* Tell DSP play to exit */
+		svr.opts.StartSample = pmsg->u.tosvr_start_sample.StartSample;
+		goto rfrsh;
 	} else if ( pmsg->msg_type == ToSvr_SamplingRate ) {
 
 		if ( pmsg->u.tosvr_sampling_rate.SamplingRate >= DSP_MIN ) {
Binary files wavplay-1.3/wavplay and wavplay-1.4/wavplay differ
diff -Nru wavplay-1.3/wavplay.h wavplay-1.4/wavplay.h
--- wavplay-1.3/wavplay.h	Thu Nov  5 19:36:39 1998
+++ wavplay-1.4/wavplay.h	Sat Nov 21 18:18:04 1998
@@ -53,7 +53,7 @@
 #ifndef _wavplay_h_
 #define _wavplay_h_ "@(#)wavplay.h $Revision: 1.4 $"
 
-#define WAVPLAY_VERSION		"1.3"
+#define WAVPLAY_VERSION		"1.4pre1"
 
 #include <stdarg.h>
 #include <sys/types.h>
@@ -206,6 +206,7 @@
 	ChnOpt	Channels;			/* -S ; or no -S option (stereo/mono respectively) */
 	U16Opt	DataBits;			/* -b bits ; number of bits per sample */
 	UInt32	Seconds;			/* Time limited to this many seconds, else zero */
+	UInt32	StartSample;			/* Sample to start playback with */
 	int	ipc;				/* Semaphore IPC ID */
 } WavPlayOpts;
 
@@ -233,6 +234,8 @@
 	char	*Pathname;			/* Pathname of wav file */
 	int	fd;				/* Open file descriptor or -1 */
 	WAVINF	wavinfo;			/* WAV file hdr info */
+	UInt32	num_samples;			/* Total number of samples */
+	UInt32	StartSample;			/* First sample to play */
 } WAVFILE;
 
 /*
@@ -296,7 +299,10 @@
 	ToSvr_Debug=17,				/* Tell server debug mode setting */
 	ToClnt_ErrMsg=18,			/* Pass back to client, an error message string */
 	ToSvr_SemReset=19,			/* Reset locking semaphores */
-	MSGTYP_Last=20,				/* This is not really a message type */
+	ToSvr_StartSample=20,			/* Start playback at requested sample */
+	ToClnt_PlayState=21,			/* Playback status */
+	ToClnt_RecState=22,			/* Record status */
+	MSGTYP_Last=23,				/* This is not really a message type */
 } MSGTYP;
 
 /*
@@ -398,6 +404,14 @@
 		} tosvr_chan;
 
 		/*
+		 * Message from X client, to server, indicating the sample to
+		 * start playback at (request).
+		 */
+		struct	{
+			UInt32	StartSample;	/* New origin */
+		} tosvr_start_sample;
+
+		/*
 		 * Message from X client, to server, indicating the
 		 * channels to use, the sampling rate to use, and
 		 * the data bits per channel to use (request).
@@ -425,6 +439,20 @@
 			char	msg[512];	/* Error message text */
 		} toclnt_errmsg;
 
+		/*
+		 * Message from server to client with playback status.
+		 */
+		struct {
+			int	CurrentSample;	/* Currently playing sample */
+			int	SamplesLeft;	/* Samples left */
+		} toclnt_playstate;
+		/*
+		 * Message from server to client with record status.
+		 */
+		struct {
+			int	bytes_written;	/* Number of bytes sampled */
+			int	num_samples;	/* Samples taken */
+		} toclnt_recstate;
 	} u;					/* The message union of all message types */
 } SVRMSG;
 
Binary files wavplay-1.3/wavrec and wavplay-1.4/wavrec differ
Binary files wavplay-1.3/xltwavplay and wavplay-1.4/xltwavplay differ
diff -Nru wavplay-1.3/xltwavplay.c wavplay-1.4/xltwavplay.c
--- wavplay-1.3/xltwavplay.c	Thu Nov  5 21:07:28 1998
+++ wavplay-1.4/xltwavplay.c	Sat Nov 21 18:18:33 1998
@@ -158,6 +158,7 @@
 	"xltwavplay*SamplingRateLbl0.labelString: Sampling Rate:",
 	"xltwavplay*SamplesLbl0.labelString: Samples:",
 	"xltwavplay*TimeLbl0.labelString: Duration:",
+	"xltwavplay*TimeDisplayLbl0.labelString: SMPTE Time:",
 
 	"xltwavplay*FileLbl1.labelString: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 	"xltwavplay*FileLbl1.foreground: black",
@@ -173,6 +174,7 @@
 	"xltwavplay*SamplesLbl1.foreground: black",
 	"xltwavplay*TimeLbl1.labelString: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 	"xltwavplay*TimeLbl1.foreground: black",
+	"xltwavplay*TimeDisplayLbl1.labelString: 00:00:00.00",
 
 	"xltwavplay*Play.labelString: Play",
 	"xltwavplay*StopPlay.labelString: Stop",
@@ -237,6 +239,12 @@
 Widget wListForm;					/* Form within Selections List Box */
 Widget wSelectionsLbl;					/* Label for Selections List Box */
 Widget wSelectionsListBox;				/* The selections List Box */
+Widget wTimeFrame;					/* Frame for Time control */
+Widget wTimeRC;						/* Row Col widget for Time control */
+Widget wTimeDisplayRC;					/* Keeps display next to label */
+Widget wTimeDisplayLbl0;				/* Label for the time */
+Widget wTimeDisplayLbl1;				/* Actual time display */
+Widget wTimeScrollBar;					/* Time scrollbar */
 Widget wRateSBFrame;					/* Frame for the scroll bar */
 Widget wRateRC;						/* Row Col widget for Rate scroll bar */
 Widget wRateLbl;					/* Label for the scroll bar */
@@ -295,6 +303,20 @@
 
 XmString sRecorded_wav;					/* XmString() of RECORD_PATH */
 
+/* Info required by the time display */
+#define SMPTE_FPS 25
+
+typedef struct TimeDisplayInfo {
+	UInt32 sampling_rate;
+	UInt32 sample_num;
+	char sample_info_str[16];
+} TimeDisplayInfo;
+
+TimeDisplayInfo time_display;
+
+/* Flag to show when the help text is displayed */
+int help_text_showing = 1;
+
 /*
  * This is an internal conveniance routine:
  * In order for EditRes to function, we must register all shell widgets.
@@ -433,6 +455,9 @@
 Restore_CB(Widget w,XtPointer client_data,XtPointer call_data) {
 
 	tosvr_restore(0,v_erf);						/* Tell server to "restore" */
+	XtVaSetValues(wTimeScrollBar,XmNvalue,0,NULL);			/* Fix time slider */
+	time_display.sample_num = 0;
+	XmSprintfLabel(wTimeDisplayLbl1,"00:00:00.00");
 	XtVaSetValues(wRateScrollBar,XmNvalue,0,NULL);			/* Fix slider */
 	SampleRateChg_Show(0);						/* Update sampling rate etc. */
 }
@@ -453,12 +478,21 @@
 		ReportErrorf("Please set a Sampling Rate\nand try again.");
 		return;
 	}
-
 	ac = 0;
 	XtSetArg(al[ac],XmNset,&b); ++ac;
 	XtGetValues(wStereoCB,al,ac);				/* Get Stereo toggle setting */
-
 	chan_mode = b ? Stereo : Mono;				/* Channels now known */
+
+	time_display.sampling_rate = RecRate;			/* Store for use during record */
+	sprintf(time_display.sample_info_str,"%u-bit %s",
+		data_bits,
+		chan_mode == Stereo ? "stereo" : "mono");
+		
+	/* Update a few fields */
+	XmSprintfLabel(wDateLbl1,"");	/* Don't need for rec; blank if help msg still there */
+ 	XmSprintfLabel(wSamplingRateLbl1,"%lu Hz",
+		(unsigned long)RecRate);
+
 	tosvr_record(0,v_erf,chan_mode,RecRate,data_bits);	/* Tell server to start recording */
 }
 
@@ -503,6 +537,19 @@
 }
 
 /*
+ * This callback is entered when the time has changed (via scroll bar):
+ */
+static void
+TimeChg_CB(Widget w,XtPointer client_data,XtPointer call_data) {
+	XmScrollBarCallbackStruct *ptr = (XmScrollBarCallbackStruct *)call_data;
+	time_display.sample_num = (UInt32)ptr->value;
+
+	/* wTimeDisplayLbl1 is updated as a result of the this server msg */
+	/* (since the server refreshes the client in response */
+	tosvr_start_sample(0,v_erf,(UInt32)ptr->value);
+}
+
+/*
  * This callback is entered when the sampling rate has changed (via scroll bar):
  */
 static void
@@ -690,7 +737,16 @@
 static void
 DispatchMsg(SVRMSG *msg) {
 	XmString s;
+	double seconds;
 
+	/* Erase the help text on receipt of first server message */
+	if (help_text_showing) {
+		help_text_showing = 0;
+		XmSprintfLabel(wFileLbl1,"");
+		XmSprintfLabel(wTypeLbl1,"");
+		XmSprintfLabel(wDateLbl1,"");
+		XmSprintfLabel(wSizeLbl1,"");
+	}
 	if ( msg->msg_type == ToClnt_Bits ) {
 		/*
 		 * Server has responded with a new bits per sample setting:
@@ -724,6 +780,8 @@
 			SampleRateChg_Show(0);
 			XtVaSetValues(wRateScrollBar,XmNvalue,0,NULL);
 		}
+		/* Store this for the time display */
+		time_display.sampling_rate = (int)msg->u.toclnt_settings.SamplingRate;
 
 		/*
 		 * Currently, this value should be "PCM" (wav file type)
@@ -734,12 +792,15 @@
 		/*
 		 * Update samples, bits and channels:
 		 */
-		XmSprintfLabel(wSamplesLbl1,"%lu %u-bit%s %s%s",
-			(unsigned long)msg->u.toclnt_settings.Samples,
+		sprintf(time_display.sample_info_str,"%u-bit%s %s%s",
 			(unsigned)msg->u.toclnt_settings.DataBits,
 			msg->u.toclnt_settings.bOvrBits ? "*" : "",
 			msg->u.toclnt_settings.Channels == Stereo ? "stereo" : "mono",
 			msg->u.toclnt_settings.bOvrMode ? "*" : "");
+		
+		XmSprintfLabel(wSamplesLbl1,"%lu %s",
+			(unsigned long)msg->u.toclnt_settings.Samples,
+			time_display.sample_info_str);
 
 		/*
 		 * Update duration time:
@@ -748,6 +809,16 @@
 			(double)msg->u.toclnt_settings.Samples
 				/ (double)msg->u.toclnt_settings.SamplingRate);
 
+		/* Update time display if required */
+		seconds = time_display.sample_num / (double)time_display.sampling_rate;
+		XmSprintfLabel(wTimeDisplayLbl1,"%02d:%02d:%02d.%02d",
+			(int)seconds/3600,((int)seconds/60)%60,
+			(int)seconds%60,
+			(int)((seconds-(int)seconds)*SMPTE_FPS));
+		XtVaSetValues(wTimeScrollBar,XmNincrement,
+			time_display.sampling_rate/SMPTE_FPS,
+			XmNpageIncrement,time_display.sampling_rate,NULL);
+
 	} else if ( msg->msg_type == ToClnt_WavInfo ) {
 
 		if ( msg->u.toclnt_wavinfo.Errno != 0 ) {
@@ -783,6 +854,24 @@
 			XmSprintfLabel(wTimeLbl1,"%.2lf seconds",
 				(double)msg->u.toclnt_wavinfo.wavinfo.Samples
 					/ (double)msg->u.toclnt_wavinfo.wavinfo.SamplingRate);
+			/*
+			 * Update time slider details:
+			 */
+			time_display.sample_num = 0;
+			time_display.sampling_rate = msg->u.toclnt_wavinfo.wavinfo.SamplingRate;
+			XmSprintfLabel(wTimeDisplayLbl1,"00:00:00.00");
+			{
+			Arg al[5];
+			int size = msg->u.toclnt_wavinfo.wavinfo.Samples;
+			XtSetArg(al[0],XmNmaximum,size + (size/10));
+			XtSetArg(al[1],XmNsliderSize,size/10);
+			XtSetArg(al[2],XmNincrement,
+			  time_display.sampling_rate/SMPTE_FPS);
+			XtSetArg(al[3],XmNpageIncrement,
+			  time_display.sampling_rate);
+			XtSetArg(al[4],XmNvalue,0);
+			XtSetValues(wTimeScrollBar,al,5);
+			}
 		}
 	} else if ( msg->msg_type == ToClnt_Stat ) {
 		/*
@@ -825,6 +914,35 @@
 			XmStringFree(s);
 			bRecorded = 1;
 		}
+	} else if ( msg->msg_type == ToClnt_PlayState ) {
+		/*
+		 * Update time, duration and samples left during playback.
+		 */
+		XmSprintfLabel(wSamplesLbl1,"%lu %s",
+			(unsigned long)msg->u.toclnt_playstate.SamplesLeft,
+			time_display.sample_info_str);
+
+		XmSprintfLabel(wTimeLbl1,"%.2lf seconds",
+			(double)msg->u.toclnt_playstate.SamplesLeft
+				/ (double)time_display.sampling_rate);
+		time_display.sample_num = msg->u.toclnt_playstate.CurrentSample;
+		seconds = time_display.sample_num / (double)time_display.sampling_rate;
+		XmSprintfLabel(wTimeDisplayLbl1,"%02d:%02d:%02d.%02d",
+			(int)seconds/3600,((int)seconds/60)%60,
+			(int)seconds%60,
+			(int)((seconds-(int)seconds)*SMPTE_FPS));
+		XtVaSetValues(wTimeScrollBar,XmNvalue,time_display.sample_num);
+	} else if ( msg->msg_type == ToClnt_RecState ) {
+		/* 
+		 * Update size, number of samples and duration during record.
+		 */
+		XmSprintfLabel(wSizeLbl1,"%lu bytes",(unsigned long)msg->u.toclnt_recstate.bytes_written);
+		XmSprintfLabel(wSamplesLbl1,"%lu %s",
+			(unsigned long)msg->u.toclnt_recstate.num_samples,
+			time_display.sample_info_str);
+		XmSprintfLabel(wTimeLbl1,"%.2lf seconds",
+			(double)msg->u.toclnt_recstate.num_samples
+				/ (double)time_display.sampling_rate);
 	} else if ( msg->msg_type == ToClnt_ErrMsg )
 		ReportError(msg->u.toclnt_errmsg.msg);
 }
@@ -1063,7 +1181,8 @@
 		NULL);
 
 	XtVaSetValues(XtParent(wSelectionsListBox),
-		XmNtopAttachment,XmATTACH_WIDGET,		XmNtopWidget,wSelectionsLbl,
+		XmNtopAttachment,XmATTACH_WIDGET,
+		XmNtopWidget,wSelectionsLbl,
 		XmNleftAttachment,XmATTACH_FORM,
 		NULL);
 
@@ -1147,9 +1266,46 @@
 	XtManageChild(wTimeLbl1);
 	
 	/*
-	 * Create the sampling rate scroll bar:
+	 * Create the time scroll bar:
 	 */
 	ac = 0;
+	XtSetArg(al[ac],XmNmarginHeight,6); ++ac;
+	XtSetArg(al[ac],XmNmarginWidth,6); ++ac;
+	wTimeFrame = XmCreateFrame(wLeftRC,"timeframe",al,ac);
+	XtManageChild(wTimeFrame);
+
+	ac = 0;
+	wTimeRC = XmCreateRowColumn(wTimeFrame,"time_rolcol",al,ac);
+	XtManageChild(wTimeRC);
+
+	ac = 0;
+	XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ++ac;
+	wTimeDisplayRC = XmCreateRowColumn(wTimeRC,"timedisplay_rolcol",al,ac);
+	XtManageChild(wTimeDisplayRC);
+
+	ac = 0;
+	wTimeDisplayLbl0 = XmCreateLabel(wTimeDisplayRC,"TimeDisplayLbl0",al,ac);
+	XtManageChild(wTimeDisplayLbl0);
+
+	ac = 0;
+	wTimeDisplayLbl1 = XmCreateLabel(wTimeDisplayRC,"TimeDisplayLbl1",al,ac);
+	XtManageChild(wTimeDisplayLbl1);
+
+	ac = 0;
+	XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ++ac;
+	XtSetArg(al[ac],XmNminimum,0); ++ac;
+	XtSetArg(al[ac],XmNsliderSize,4000); ++ac;
+	XtSetArg(al[ac],XmNmaximum,0+4000); ++ac;
+	XtSetArg(al[ac],XmNincrement,1); ++ac;
+	wTimeScrollBar = XmCreateScrollBar(wTimeRC,"time_scrollbar",al,ac);
+	XtManageChild(wTimeScrollBar);
+	XtAddCallback(wTimeScrollBar,XmNvalueChangedCallback,TimeChg_CB,NULL);
+
+	/*
+	 * Create the sampling rate scroll bar:
+	 */
+	ac = time_display.sample_num = 0;
+	time_display.sampling_rate = 1;
 	XtSetArg(al[ac],XmNmarginHeight,6); ++ac;
 	XtSetArg(al[ac],XmNmarginWidth,6); ++ac;
 	wRateSBFrame = XmCreateFrame(wLeftRC,"rateSBframe",al,ac);
