Subject: bin/9134: audioplay should quit immediately on ^C
To: None <gnats-bugs@gnats.netbsd.org>
From: Ben Wong <hackerb9@u.washington.edu>
List: netbsd-bugs
Date: 01/08/2000 05:49:56
>Number:         9134
>Category:       bin
>Synopsis:       audioplay waits for buffer to drain even on a SIGINT
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Jan  6 09:09:00 2000
>Last-Modified:
>Originator:     Ben Wong
>Organization:
	
>Release:        NetBSD-1.4.1
>Environment:
	
System: NetBSD ursula.wongs.net 1.4.1 NetBSD 1.4.1 (AMNESIAC) #7: Thu Oct 14 22:00:19 EDT 1999 hackerb9@ursula.wongs.net:/usr/src/sys/arch/i386/compile/AMNESIAC i386


>Description:
When using audioplay to play a sound, if the user hits ^C the sound
keeps playing for about five seconds while the buffer drains. This is
annoying but easily fixed.

>How-To-Repeat:

Assuming a largish sound file called "large.au" try this:

	 # Hit ^C shortly after starting to play the sound.
	 # Audioplay will not quit for another five seconds.
	 > audioplay large.au
	 ^C

>Fix:

This can be fixed by watching for relevant signals and calling a
cleanup function to flush the audio buffer. Here is a patch which does
that.

% diff -u play.c.orig play.c  
--- play.c.orig Tue Apr 13 03:13:41 1999
+++ play.c      Thu Jan  6 12:00:18 2000
@@ -40,6 +40,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <signal.h>
 
 #include <paths.h>
 
@@ -48,6 +49,7 @@
 int main __P((int, char *[]));
 void usage __P((void));
 ssize_t audioctl_write_fromhdr __P((void *, size_t, int));
+void cleanup(int);
 
 audio_info_t   info;
 int    volume;
@@ -62,6 +64,9 @@
 
 char   const *play_errstring = NULL;
 
+int    audiofd;                /* Usually open to "/dev/audio"  */
+
+
 int
 main(argc, argv)
        int argc;
@@ -70,13 +75,18 @@
        size_t  len, bufsize;
        ssize_t hdrlen;
        off_t   filesize;
-       int     ch, audiofd, ctlfd;
+       int     ch, ctlfd;
        int     iflag = 0;
        int     qflag = 0;
        int     verbose = 0;
        char    *device = 0;
        char    *ctldev = 0;
 
+       /* Cleanup quickly if the user wants us to die. */
+       signal(SIGHUP, cleanup);
+       signal(SIGINT, cleanup);
+       signal(SIGTERM, cleanup);
+
        while ((ch = getopt(argc, argv, "b:C:c:d:e:fhip:P:qs:Vv:")) != -1) {
                switch (ch) {
                case 'b':
@@ -368,3 +378,15 @@
            "-v volume\n");
        exit(0);
 }
+
+
+/* Signal handler for HUP, INT, and TERM that flushes the audio buffer
+   immediately instead of waiting five seconds for it to drain. */
+void cleanup(int x)
+{
+  ioctl(audiofd, AUDIO_FLUSH, NULL); /* Purge all data from audio buffer. */
+  close(audiofd);              /* Close the device */
+  exit(0);
+}
+
+
>Audit-Trail:
>Unformatted: