]> code.delx.au - gnu-emacs/blobdiff - src/sound.c
Fix two typos.
[gnu-emacs] / src / sound.c
index 965285a9c5f2e5263906c83b4cb785f955106fc5..e5c800596565e159c284f050188b5a2f3cc85f3f 100644 (file)
@@ -1,5 +1,5 @@
 /* sound.c -- sound support.
-   Copyright (C) 1998, 1999 Free Software Foundation.
+   Copyright (C) 1998, 1999, 2001 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -25,12 +25,15 @@ Boston, MA 02111-1307, USA.  */
 
 #if defined HAVE_SOUND
 
-#include <lisp.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <dispextern.h>
 #include <errno.h>
+#include "lisp.h"
+#include "dispextern.h"
+#include "atimer.h"
+#include <signal.h>
+#include "syssignal.h"
 
 /* FreeBSD has machine/soundcard.h.  Voxware sound driver docs mention
    sys/soundcard.h.  So, let's try whatever's there.  */
@@ -41,6 +44,14 @@ Boston, MA 02111-1307, USA.  */
 #ifdef HAVE_SYS_SOUNDCARD_H
 #include <sys/soundcard.h>
 #endif
+#ifdef HAVE_SOUNDCARD_H
+#include <sys/ioctl.h>
+#include <soundcard.h>
+#endif
+
+#ifndef DEFAULT_SOUND_DEVICE
+#define DEFAULT_SOUND_DEVICE "/dev/dsp"
+#endif
 
 #define max(X, Y) ((X) > (Y) ? (X) : (Y))
 #define min(X, Y) ((X) < (Y) ? (X) : (Y))
@@ -352,6 +363,8 @@ sound_cleanup (arg)
       if (current_sound->fd > 0)
        emacs_close (current_sound->fd);
     }
+
+  return Qnil;
 }
 
 
@@ -360,7 +373,7 @@ DEFUN ("play-sound", Fplay_sound, Splay_sound, 1, 1, 0,
 SOUND is a list of the form `(sound KEYWORD VALUE...)'.\n\
 The following keywords are recognized:\n\
 \n\
-  :file FILE.- read sound data from FILE.  If FILE Isn't an\n\
+  :file FILE.- read sound data from FILE.  If FILE isn't an\n\
 absolute file name, it is searched in `data-directory'.\n\
 \n\
   :data DATA - read sound data from string DATA.\n\
@@ -401,7 +414,7 @@ a system-dependent default device name is used.")
     {
       /* Open the sound file.  */
       s.fd = openp (Fcons (Vdata_directory, Qnil),
-                    attrs[SOUND_FILE], "", &file, 0);
+                   attrs[SOUND_FILE], "", &file, 0);
       if (s.fd < 0)
        sound_perror ("Open sound file");
 
@@ -736,7 +749,7 @@ vox_open (sd)
   if (sd->file)
     file = sd->file;
   else
-    file = "/dev/dsp";
+    file = DEFAULT_SOUND_DEVICE;
   
   sd->fd = emacs_open (file, O_WRONLY, 0);
   if (sd->fd < 0)
@@ -750,38 +763,50 @@ static void
 vox_configure (sd)
      struct sound_device *sd;
 {
-  int requested;
+  int val;
   
   xassert (sd->fd >= 0);
 
-  /* Device parameters apparently depend on each other in undocumented
-     ways (not to imply that there is any real documentation).  Be
-     careful when reordering the calls below.  */
-  if (sd->sample_size > 0
-      && ioctl (sd->fd, SNDCTL_DSP_SAMPLESIZE, &sd->sample_size) < 0)
-    sound_perror ("Setting sample size");
+  /* On GNU/Linux, it seems that the device driver doesn't like to be
+     interrupted by a signal.  Block the ones we know to cause
+     troubles.  */
+  turn_on_atimers (0);
+#ifdef SIGIO
+  sigblock (sigmask (SIGIO));
+#endif
+
+  val = sd->format;
+  if (ioctl (sd->fd, SNDCTL_DSP_SETFMT, &sd->format) < 0
+      || val != sd->format)
+    sound_perror ("Set sound format");
+
+  val = sd->channels != 1;
+  if (ioctl (sd->fd, SNDCTL_DSP_STEREO, &val) < 0
+      || val != (sd->channels != 1))
+    sound_perror ("Set stereo/mono");
+
+  /* I think bps and sampling_rate are the same, but who knows.
+     Check this. and use SND_DSP_SPEED for both.  */
+  if (sd->sample_rate > 0)
+    {
+      val = sd->sample_rate;
+      if (ioctl (sd->fd, SNDCTL_DSP_SPEED, &sd->sample_rate) < 0
+         || val != sd->sample_rate)
+       sound_perror ("Set sound speed");
+    }
+
+  if (sd->volume > 0)
+    {
+      int volume = sd->volume & 0xff;
+      volume |= volume << 8;
+      /* This may fail if there is no mixer.  Ignore the failure.  */
+      ioctl (sd->fd, SOUND_MIXER_WRITE_PCM, &volume);
+    }
   
-  if (sd->bps > 0
-      && ioctl (sd->fd, SNDCTL_DSP_SPEED, &sd->bps) < 0)
-    sound_perror ("Setting speed");
-
-  if (sd->sample_rate > 0
-      && ioctl (sd->fd, SOUND_PCM_WRITE_RATE, &sd->sample_rate) < 0)
-    sound_perror ("Setting sample rate");
-
-  requested = sd->format;
-  if (ioctl (sd->fd, SNDCTL_DSP_SETFMT, &sd->format) < 0)
-    sound_perror ("Setting format");
-  else if (requested != sd->format)
-    error ("Setting format");
-
-  if (sd->channels > 1
-      && ioctl (sd->fd, SNDCTL_DSP_STEREO, &sd->channels) < 0)
-    sound_perror ("Setting channels");
-
-  if (sd->volume > 0
-      && ioctl (sd->fd, SOUND_MIXER_WRITE_PCM, &sd->volume) < 0)
-    sound_perror ("Setting volume");
+  turn_on_atimers (1);
+#ifdef SIGIO
+  sigunblock (sigmask (SIGIO));
+#endif
 }
 
 
@@ -793,9 +818,21 @@ vox_close (sd)
 {
   if (sd->fd >= 0)
     {
+      /* On GNU/Linux, it seems that the device driver doesn't like to
+        be interrupted by a signal.  Block the ones we know to cause
+        troubles.  */
+#ifdef SIGIO
+      sigblock (sigmask (SIGIO));
+#endif
+      turn_on_atimers (0);
+      
       /* Flush sound data, and reset the device.  */
       ioctl (sd->fd, SNDCTL_DSP_SYNC, NULL);
-      ioctl (sd->fd, SNDCTL_DSP_RESET, NULL);
+      
+      turn_on_atimers (1);
+#ifdef SIGIO
+      sigunblock (sigmask (SIGIO));
+#endif
 
       /* Close the device.  */
       emacs_close (sd->fd);