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 #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 #include @@ -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);