(scan_lists): Follow coding convention.
[bpt/emacs.git] / src / sound.c
index af23690..0b15399 100644 (file)
@@ -1,12 +1,12 @@
 /* sound.c -- sound support.
    Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -74,8 +74,12 @@ Boston, MA 02110-1301, USA.  */
 #include <soundcard.h>
 #endif
 #ifdef HAVE_ALSA
+#ifdef ALSA_SUBDIR_INCLUDE
+#include <alsa/asoundlib.h>
+#else
 #include <asoundlib.h>
-#endif
+#endif /* ALSA_SUBDIR_INCLUDE */
+#endif /* HAVE_ALSA */
 
 /* END: Non Windows Includes */
 
@@ -93,7 +97,6 @@ Boston, MA 02110-1301, USA.  */
 #endif /* WINDOWSNT */
 
 /* BEGIN: Common Definitions */
-#define abs(X)    ((X) < 0 ? -(X) : (X))
 
 /* Symbols.  */
 
@@ -617,12 +620,18 @@ wav_play (s, sd)
       char *buffer;
       int nbytes;
       int blksize = sd->period_size ? sd->period_size (sd) : 2048;
+      int data_left = header->data_length;
 
       buffer = (char *) alloca (blksize);
       lseek (s->fd, sizeof *header, SEEK_SET);
-
-      while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
-       sd->write (sd, buffer, nbytes);
+      while (data_left > 0
+             && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
+        {
+          /* Don't play possible garbage at the end of file */
+          if (data_left < nbytes) nbytes = data_left;
+          data_left -= nbytes;
+          sd->write (sd, buffer, nbytes);
+        }
 
       if (nbytes < 0)
        sound_perror ("Error reading sound file");
@@ -982,7 +991,8 @@ alsa_period_size (sd)
        struct sound_device *sd;
 {
   struct alsa_params *p = (struct alsa_params *) sd->data;
-  return p->period_size;
+  int fact = snd_pcm_format_size (sd->format, 1) * sd->channels;
+  return p->period_size * (fact > 0 ? fact : 1);
 }
 
 static void
@@ -990,6 +1000,7 @@ alsa_configure (sd)
      struct sound_device *sd;
 {
   int val, err, dir;
+  unsigned uval;
   struct alsa_params *p = (struct alsa_params *) sd->data;
   snd_pcm_uframes_t buffer_size;
 
@@ -1014,14 +1025,14 @@ alsa_configure (sd)
 
   val = sd->format;
   err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val);
-  if (err < 0) 
+  if (err < 0)
     alsa_sound_perror ("Could not set sound format", err);
 
-  val = sd->sample_rate;
-  err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &val, 0);
+  uval = sd->sample_rate;
+  err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0);
   if (err < 0)
     alsa_sound_perror ("Could not set sample rate", err);
-  
+
   val = sd->channels;
   err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val);
   if (err < 0)
@@ -1071,11 +1082,11 @@ alsa_configure (sd)
   p->hwparams = NULL;
   snd_pcm_sw_params_free (p->swparams);
   p->swparams = NULL;
-  
+
   err = snd_pcm_prepare (p->handle);
   if (err < 0)
     alsa_sound_perror ("Could not prepare audio interface for use", err);
-  
+
   if (sd->volume > 0)
     {
       int chn;
@@ -1097,7 +1108,7 @@ alsa_configure (sd)
                     long pmin, pmax;
                     snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax);
                     long vol = pmin + (sd->volume * (pmax - pmin)) / 100;
-                    
+
                     for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++)
                       snd_mixer_selem_set_playback_volume (e, chn, vol);
                   }
@@ -1123,7 +1134,7 @@ alsa_close (sd)
         snd_pcm_sw_params_free (p->swparams);
       if (p->handle)
         {
-          snd_pcm_drain(p->handle);
+          snd_pcm_drain (p->handle);
           snd_pcm_close (p->handle);
         }
       free (p);
@@ -1204,9 +1215,10 @@ alsa_write (sd, buffer, nbytes)
 
   while (nwritten < nbytes)
     {
-      err = snd_pcm_writei (p->handle,
-                            buffer + nwritten,
-                            (nbytes - nwritten)/fact);
+      snd_pcm_uframes_t frames = (nbytes - nwritten)/fact;
+      if (frames == 0) break;
+      
+      err = snd_pcm_writei (p->handle, buffer + nwritten, frames);
       if (err < 0)
         {
           if (err == -EPIPE)
@@ -1229,9 +1241,9 @@ alsa_write (sd, buffer, nbytes)
                                        err);
                 }
             }
-          else 
+          else
             alsa_sound_perror ("Error writing to sound device", err);
-          
+
         }
       else
         nwritten += err * fact;
@@ -1269,7 +1281,8 @@ alsa_init (sd)
   err = snd_pcm_open (&handle, file, SND_PCM_STREAM_PLAYBACK, 0);
   snd_lib_error_set_handler (NULL);
   if (err < 0)
-    return 0;
+      return 0;
+  snd_pcm_close (handle);
 
   sd->fd = -1;
   sd->open = alsa_open;
@@ -1372,7 +1385,7 @@ do_play_sound (psz_file, ui_volume)
 DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
        doc: /* Play sound SOUND.
 
-Internal use only, use `play-sound' instead.\n  */)
+Internal use only, use `play-sound' instead.  */)
      (sound)
      Lisp_Object sound;
 {