1/* sound.c -- sound support.
2   Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004,
3                 2005, 2006, 2007 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING.  If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.  */
21
22/* Written by Gerd Moellmann <gerd@gnu.org>.  Tested with Luigi's
23   driver on FreeBSD 2.2.7 with a SoundBlaster 16.  */
24
25/*
26  Modified by Ben Key <Bkey1@tampabay.rr.com> to add a partial
27  implementation of the play-sound specification for Windows.
28
29  Notes:
30  In the Windows implementation of play-sound-internal only the
31  :file and :volume keywords are supported.  The :device keyword,
32  if present, is ignored.  The :data keyword, if present, will
33  cause an error to be generated.
34
35  The Windows implementation of play-sound is implemented via the
36  Win32 API functions mciSendString, waveOutGetVolume, and
37  waveOutSetVolume which are exported by Winmm.dll.
38*/
39
40#include <config.h>
41
42#if defined HAVE_SOUND
43
44/* BEGIN: Common Includes */
45#include <fcntl.h>
46#include <unistd.h>
47#include <sys/types.h>
48#include <errno.h>
49#include "lisp.h"
50#include "dispextern.h"
51#include "atimer.h"
52#include <signal.h>
53#include "syssignal.h"
54/* END: Common Includes */
55
56
57/* BEGIN: Non Windows Includes */
58#ifndef WINDOWSNT
59
60#ifndef MSDOS
61#include <sys/ioctl.h>
62#endif
63
64/* FreeBSD has machine/soundcard.h.  Voxware sound driver docs mention
65   sys/soundcard.h.  So, let's try whatever's there.  */
66
67#ifdef HAVE_MACHINE_SOUNDCARD_H
68#include <machine/soundcard.h>
69#endif
70#ifdef HAVE_SYS_SOUNDCARD_H
71#include <sys/soundcard.h>
72#endif
73#ifdef HAVE_SOUNDCARD_H
74#include <soundcard.h>
75#endif
76#ifdef HAVE_ALSA
77#ifdef ALSA_SUBDIR_INCLUDE
78#include <alsa/asoundlib.h>
79#else
80#include <asoundlib.h>
81#endif /* ALSA_SUBDIR_INCLUDE */
82#endif /* HAVE_ALSA */
83
84/* END: Non Windows Includes */
85
86#else /* WINDOWSNT */
87
88/* BEGIN: Windows Specific Includes */
89#include <stdio.h>
90#include <stdlib.h>
91#include <string.h>
92#include <limits.h>
93#include <windows.h>
94#include <mmsystem.h>
95/* END: Windows Specific Includes */
96
97#endif /* WINDOWSNT */
98
99/* BEGIN: Common Definitions */
100#define abs(X)    ((X) < 0 ? -(X) : (X))
101
102/* Symbols.  */
103
104extern Lisp_Object QCfile, QCdata;
105Lisp_Object QCvolume, QCdevice;
106Lisp_Object Qsound;
107Lisp_Object Qplay_sound_functions;
108
109/* Indices of attributes in a sound attributes vector.  */
110
111enum sound_attr
112{
113  SOUND_FILE,
114  SOUND_DATA,
115  SOUND_DEVICE,
116  SOUND_VOLUME,
117  SOUND_ATTR_SENTINEL
118};
119
120static void alsa_sound_perror P_ ((char *, int)) NO_RETURN;
121static void sound_perror P_ ((char *)) NO_RETURN;
122static void sound_warning P_ ((char *));
123static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
124
125/* END: Common Definitions */
126
127/* BEGIN: Non Windows Definitions */
128#ifndef WINDOWSNT
129
130#ifndef DEFAULT_SOUND_DEVICE
131#define DEFAULT_SOUND_DEVICE "/dev/dsp"
132#endif
133#ifndef DEFAULT_ALSA_SOUND_DEVICE
134#define DEFAULT_ALSA_SOUND_DEVICE "default"
135#endif
136
137
138/* Structure forward declarations.  */
139
140struct sound;
141struct sound_device;
142
143/* The file header of RIFF-WAVE files (*.wav).  Files are always in
144   little-endian byte-order.  */
145
146struct wav_header
147{
148  u_int32_t magic;
149  u_int32_t length;
150  u_int32_t chunk_type;
151  u_int32_t chunk_format;
152  u_int32_t chunk_length;
153  u_int16_t format;
154  u_int16_t channels;
155  u_int32_t sample_rate;
156  u_int32_t bytes_per_second;
157  u_int16_t sample_size;
158  u_int16_t precision;
159  u_int32_t chunk_data;
160  u_int32_t data_length;
161};
162
163/* The file header of Sun adio files (*.au).  Files are always in
164   big-endian byte-order.  */
165
166struct au_header
167{
168  /* ASCII ".snd" */
169  u_int32_t magic_number;
170
171  /* Offset of data part from start of file. Minimum value is 24.  */
172  u_int32_t data_offset;
173
174  /* Size of data part, 0xffffffff if unknown.  */
175  u_int32_t data_size;
176
177  /* Data encoding format.
178     1	8-bit ISDN u-law
179     2  8-bit linear PCM (REF-PCM)
180     3  16-bit linear PCM
181     4	24-bit linear PCM
182     5	32-bit linear PCM
183     6	32-bit IEEE floating-point
184     7	64-bit IEEE floating-point
185     23 8-bit u-law compressed using CCITT 0.721 ADPCM voice data
186     encoding scheme.  */
187  u_int32_t encoding;
188
189  /* Number of samples per second.  */
190  u_int32_t sample_rate;
191
192  /* Number of interleaved channels.  */
193  u_int32_t channels;
194};
195
196/* Maximum of all sound file headers sizes.  */
197
198#define MAX_SOUND_HEADER_BYTES \
199     max (sizeof (struct wav_header), sizeof (struct au_header))
200
201/* Interface structure for sound devices.  */
202
203struct sound_device
204{
205  /* The name of the device or null meaning use a default device name.  */
206  char *file;
207
208  /* File descriptor of the device.  */
209  int fd;
210
211  /* Device-dependent format.  */
212  int format;
213
214  /* Volume (0..100).  Zero means unspecified.  */
215  int volume;
216
217  /* Sample size.  */
218  int sample_size;
219
220  /* Sample rate.  */
221  int sample_rate;
222
223  /* Bytes per second.  */
224  int bps;
225
226  /* 1 = mono, 2 = stereo, 0 = don't set.  */
227  int channels;
228
229  /* Open device SD.  */
230  void (* open) P_ ((struct sound_device *sd));
231
232  /* Close device SD.  */
233  void (* close) P_ ((struct sound_device *sd));
234
235  /* Configure SD accoring to device-dependent parameters.  */
236  void (* configure) P_ ((struct sound_device *device));
237
238  /* Choose a device-dependent format for outputting sound S.  */
239  void (* choose_format) P_ ((struct sound_device *sd,
240			      struct sound *s));
241
242  /* Return a preferred data size in bytes to be sent to write (below)
243     each time.  2048 is used if this is NULL.  */
244  int (* period_size) P_ ((struct sound_device *sd));
245
246  /* Write NYBTES bytes from BUFFER to device SD.  */
247  void (* write) P_ ((struct sound_device *sd, const char *buffer,
248		      int nbytes));
249
250  /* A place for devices to store additional data.  */
251  void *data;
252};
253
254/* An enumerator for each supported sound file type.  */
255
256enum sound_type
257{
258  RIFF,
259  SUN_AUDIO
260};
261
262/* Interface structure for sound files.  */
263
264struct sound
265{
266  /* The type of the file.  */
267  enum sound_type type;
268
269  /* File descriptor of a sound file.  */
270  int fd;
271
272  /* Pointer to sound file header.  This contains header_size bytes
273     read from the start of a sound file.  */
274  char *header;
275
276  /* Number of bytes raed from sound file.  This is always <=
277     MAX_SOUND_HEADER_BYTES.  */
278  int header_size;
279
280  /* Sound data, if a string.  */
281  Lisp_Object data;
282
283  /* Play sound file S on device SD.  */
284  void (* play) P_ ((struct sound *s, struct sound_device *sd));
285};
286
287/* These are set during `play-sound-internal' so that sound_cleanup has
288   access to them.  */
289
290struct sound_device *current_sound_device;
291struct sound *current_sound;
292
293/* Function prototypes.  */
294
295static void vox_open P_ ((struct sound_device *));
296static void vox_configure P_ ((struct sound_device *));
297static void vox_close P_ ((struct sound_device *sd));
298static void vox_choose_format P_ ((struct sound_device *, struct sound *));
299static int vox_init P_ ((struct sound_device *));
300static void vox_write P_ ((struct sound_device *, const char *, int));
301static void find_sound_type P_ ((struct sound *));
302static u_int32_t le2hl P_ ((u_int32_t));
303static u_int16_t le2hs P_ ((u_int16_t));
304static u_int32_t be2hl P_ ((u_int32_t));
305static int wav_init P_ ((struct sound *));
306static void wav_play P_ ((struct sound *, struct sound_device *));
307static int au_init P_ ((struct sound *));
308static void au_play P_ ((struct sound *, struct sound_device *));
309
310#if 0 /* Currently not used.  */
311static u_int16_t be2hs P_ ((u_int16_t));
312#endif
313
314/* END: Non Windows Definitions */
315#else /* WINDOWSNT */
316
317/* BEGIN: Windows Specific Definitions */
318static int do_play_sound P_ ((const char *, unsigned long));
319/*
320  END: Windows Specific Definitions */
321#endif /* WINDOWSNT */
322
323
324/***********************************************************************
325			       General
326 ***********************************************************************/
327
328/* BEGIN: Common functions */
329
330/* Like perror, but signals an error.  */
331
332static void
333sound_perror (msg)
334     char *msg;
335{
336  int saved_errno = errno;
337
338  turn_on_atimers (1);
339#ifdef SIGIO
340  sigunblock (sigmask (SIGIO));
341#endif
342  if (saved_errno != 0)
343    error ("%s: %s", msg, strerror (saved_errno));
344  else
345    error ("%s", msg);
346}
347
348
349/* Display a warning message.  */
350
351static void
352sound_warning (msg)
353     char *msg;
354{
355  message (msg);
356}
357
358
359/* Parse sound specification SOUND, and fill ATTRS with what is
360   found.  Value is non-zero if SOUND Is a valid sound specification.
361   A valid sound specification is a list starting with the symbol
362   `sound'.  The rest of the list is a property list which may
363   contain the following key/value pairs:
364
365   - `:file FILE'
366
367   FILE is the sound file to play.  If it isn't an absolute name,
368   it's searched under `data-directory'.
369
370   - `:data DATA'
371
372   DATA is a string containing sound data.  Either :file or :data
373   may be present, but not both.
374
375   - `:device DEVICE'
376
377   DEVICE is the name of the device to play on, e.g. "/dev/dsp2".
378   If not specified, a default device is used.
379
380   - `:volume VOL'
381
382   VOL must be an integer in the range [0, 100], or a float in the
383   range [0, 1].  */
384
385static int
386parse_sound (sound, attrs)
387     Lisp_Object sound;
388     Lisp_Object *attrs;
389{
390  /* SOUND must be a list starting with the symbol `sound'.  */
391  if (!CONSP (sound) || !EQ (XCAR (sound), Qsound))
392    return 0;
393
394  sound = XCDR (sound);
395  attrs[SOUND_FILE] = Fplist_get (sound, QCfile);
396  attrs[SOUND_DATA] = Fplist_get (sound, QCdata);
397  attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
398  attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
399
400#ifndef WINDOWSNT
401  /* File name or data must be specified.  */
402  if (!STRINGP (attrs[SOUND_FILE])
403      && !STRINGP (attrs[SOUND_DATA]))
404    return 0;
405#else /* WINDOWSNT */
406  /*
407    Data is not supported in Windows.  Therefore a
408    File name MUST be supplied.
409  */
410  if (!STRINGP (attrs[SOUND_FILE]))
411    {
412      return 0;
413    }
414#endif /* WINDOWSNT */
415
416  /* Volume must be in the range 0..100 or unspecified.  */
417  if (!NILP (attrs[SOUND_VOLUME]))
418    {
419      if (INTEGERP (attrs[SOUND_VOLUME]))
420	{
421	  if (XINT (attrs[SOUND_VOLUME]) < 0
422	      || XINT (attrs[SOUND_VOLUME]) > 100)
423	    return 0;
424	}
425      else if (FLOATP (attrs[SOUND_VOLUME]))
426	{
427	  if (XFLOAT_DATA (attrs[SOUND_VOLUME]) < 0
428	      || XFLOAT_DATA (attrs[SOUND_VOLUME]) > 1)
429	    return 0;
430	}
431      else
432	return 0;
433    }
434
435#ifndef WINDOWSNT
436  /* Device must be a string or unspecified.  */
437  if (!NILP (attrs[SOUND_DEVICE])
438      && !STRINGP (attrs[SOUND_DEVICE]))
439    return 0;
440#endif  /* WINDOWSNT */
441  /*
442    Since device is ignored in Windows, it does not matter
443    what it is.
444   */
445  return 1;
446}
447
448/* END: Common functions */
449
450/* BEGIN: Non Windows functions */
451#ifndef WINDOWSNT
452
453/* Find out the type of the sound file whose file descriptor is FD.
454   S is the sound file structure to fill in.  */
455
456static void
457find_sound_type (s)
458     struct sound *s;
459{
460  if (!wav_init (s) && !au_init (s))
461    error ("Unknown sound format");
462}
463
464
465/* Function installed by play-sound-internal with record_unwind_protect.  */
466
467static Lisp_Object
468sound_cleanup (arg)
469     Lisp_Object arg;
470{
471  if (current_sound_device->close)
472    current_sound_device->close (current_sound_device);
473  if (current_sound->fd > 0)
474    emacs_close (current_sound->fd);
475  free (current_sound_device);
476  free (current_sound);
477
478  return Qnil;
479}
480
481/***********************************************************************
482			Byte-order Conversion
483 ***********************************************************************/
484
485/* Convert 32-bit value VALUE which is in little-endian byte-order
486   to host byte-order.  */
487
488static u_int32_t
489le2hl (value)
490     u_int32_t value;
491{
492#ifdef WORDS_BIG_ENDIAN
493  unsigned char *p = (unsigned char *) &value;
494  value = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
495#endif
496  return value;
497}
498
499
500/* Convert 16-bit value VALUE which is in little-endian byte-order
501   to host byte-order.  */
502
503static u_int16_t
504le2hs (value)
505     u_int16_t value;
506{
507#ifdef WORDS_BIG_ENDIAN
508  unsigned char *p = (unsigned char *) &value;
509  value = p[0] + (p[1] << 8);
510#endif
511  return value;
512}
513
514
515/* Convert 32-bit value VALUE which is in big-endian byte-order
516   to host byte-order.  */
517
518static u_int32_t
519be2hl (value)
520     u_int32_t value;
521{
522#ifndef WORDS_BIG_ENDIAN
523  unsigned char *p = (unsigned char *) &value;
524  value = p[3] + (p[2] << 8) + (p[1] << 16) + (p[0] << 24);
525#endif
526  return value;
527}
528
529
530#if 0 /* Currently not used.  */
531
532/* Convert 16-bit value VALUE which is in big-endian byte-order
533   to host byte-order.  */
534
535static u_int16_t
536be2hs (value)
537     u_int16_t value;
538{
539#ifndef WORDS_BIG_ENDIAN
540  unsigned char *p = (unsigned char *) &value;
541  value = p[1] + (p[0] << 8);
542#endif
543  return value;
544}
545
546#endif /* 0 */
547
548/***********************************************************************
549			  RIFF-WAVE (*.wav)
550 ***********************************************************************/
551
552/* Try to initialize sound file S from S->header.  S->header
553   contains the first MAX_SOUND_HEADER_BYTES number of bytes from the
554   sound file.  If the file is a WAV-format file, set up interface
555   functions in S and convert header fields to host byte-order.
556   Value is non-zero if the file is a WAV file.  */
557
558static int
559wav_init (s)
560     struct sound *s;
561{
562  struct wav_header *header = (struct wav_header *) s->header;
563
564  if (s->header_size < sizeof *header
565      || bcmp (s->header, "RIFF", 4) != 0)
566    return 0;
567
568  /* WAV files are in little-endian order.  Convert the header
569     if on a big-endian machine.  */
570  header->magic = le2hl (header->magic);
571  header->length = le2hl (header->length);
572  header->chunk_type = le2hl (header->chunk_type);
573  header->chunk_format = le2hl (header->chunk_format);
574  header->chunk_length = le2hl (header->chunk_length);
575  header->format = le2hs (header->format);
576  header->channels = le2hs (header->channels);
577  header->sample_rate = le2hl (header->sample_rate);
578  header->bytes_per_second = le2hl (header->bytes_per_second);
579  header->sample_size = le2hs (header->sample_size);
580  header->precision = le2hs (header->precision);
581  header->chunk_data = le2hl (header->chunk_data);
582  header->data_length = le2hl (header->data_length);
583
584  /* Set up the interface functions for WAV.  */
585  s->type = RIFF;
586  s->play = wav_play;
587
588  return 1;
589}
590
591
592/* Play RIFF-WAVE audio file S on sound device SD.  */
593
594static void
595wav_play (s, sd)
596     struct sound *s;
597     struct sound_device *sd;
598{
599  struct wav_header *header = (struct wav_header *) s->header;
600
601  /* Let the device choose a suitable device-dependent format
602     for the file.  */
603  sd->choose_format (sd, s);
604
605  /* Configure the device.  */
606  sd->sample_size = header->sample_size;
607  sd->sample_rate = header->sample_rate;
608  sd->bps = header->bytes_per_second;
609  sd->channels = header->channels;
610  sd->configure (sd);
611
612  /* Copy sound data to the device.  The WAV file specification is
613     actually more complex.  This simple scheme worked with all WAV
614     files I found so far.  If someone feels inclined to implement the
615     whole RIFF-WAVE spec, please do.  */
616  if (STRINGP (s->data))
617    sd->write (sd, SDATA (s->data) + sizeof *header,
618	       SBYTES (s->data) - sizeof *header);
619  else
620    {
621      char *buffer;
622      int nbytes;
623      int blksize = sd->period_size ? sd->period_size (sd) : 2048;
624      int data_left = header->data_length;
625
626      buffer = (char *) alloca (blksize);
627      lseek (s->fd, sizeof *header, SEEK_SET);
628      while (data_left > 0
629             && (nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
630        {
631          /* Don't play possible garbage at the end of file */
632          if (data_left < nbytes) nbytes = data_left;
633          data_left -= nbytes;
634          sd->write (sd, buffer, nbytes);
635        }
636
637      if (nbytes < 0)
638	sound_perror ("Error reading sound file");
639    }
640}
641
642
643/***********************************************************************
644			   Sun Audio (*.au)
645 ***********************************************************************/
646
647/* Sun audio file encodings.  */
648
649enum au_encoding
650{
651  AU_ENCODING_ULAW_8 = 1,
652  AU_ENCODING_8,
653  AU_ENCODING_16,
654  AU_ENCODING_24,
655  AU_ENCODING_32,
656  AU_ENCODING_IEEE32,
657  AU_ENCODING_IEEE64,
658  AU_COMPRESSED = 23,
659  AU_ENCODING_ALAW_8 = 27
660};
661
662
663/* Try to initialize sound file S from S->header.  S->header
664   contains the first MAX_SOUND_HEADER_BYTES number of bytes from the
665   sound file.  If the file is a AU-format file, set up interface
666   functions in S and convert header fields to host byte-order.
667   Value is non-zero if the file is an AU file.  */
668
669static int
670au_init (s)
671     struct sound *s;
672{
673  struct au_header *header = (struct au_header *) s->header;
674
675  if (s->header_size < sizeof *header
676      || bcmp (s->header, ".snd", 4) != 0)
677    return 0;
678
679  header->magic_number = be2hl (header->magic_number);
680  header->data_offset = be2hl (header->data_offset);
681  header->data_size = be2hl (header->data_size);
682  header->encoding = be2hl (header->encoding);
683  header->sample_rate = be2hl (header->sample_rate);
684  header->channels = be2hl (header->channels);
685
686  /* Set up the interface functions for AU.  */
687  s->type = SUN_AUDIO;
688  s->play = au_play;
689
690  return 1;
691}
692
693
694/* Play Sun audio file S on sound device SD.  */
695
696static void
697au_play (s, sd)
698     struct sound *s;
699     struct sound_device *sd;
700{
701  struct au_header *header = (struct au_header *) s->header;
702
703  sd->sample_size = 0;
704  sd->sample_rate = header->sample_rate;
705  sd->bps = 0;
706  sd->channels = header->channels;
707  sd->choose_format (sd, s);
708  sd->configure (sd);
709
710  if (STRINGP (s->data))
711    sd->write (sd, SDATA (s->data) + header->data_offset,
712	       SBYTES (s->data) - header->data_offset);
713  else
714    {
715      int blksize = sd->period_size ? sd->period_size (sd) : 2048;
716      char *buffer;
717      int nbytes;
718
719      /* Seek */
720      lseek (s->fd, header->data_offset, SEEK_SET);
721
722      /* Copy sound data to the device.  */
723      buffer = (char *) alloca (blksize);
724      while ((nbytes = emacs_read (s->fd, buffer, blksize)) > 0)
725	sd->write (sd, buffer, nbytes);
726
727      if (nbytes < 0)
728	sound_perror ("Error reading sound file");
729    }
730}
731
732
733/***********************************************************************
734		       Voxware Driver Interface
735 ***********************************************************************/
736
737/* This driver is available on GNU/Linux, and the free BSDs.  FreeBSD
738   has a compatible own driver aka Luigi's driver.  */
739
740
741/* Open device SD.  If SD->file is non-null, open that device,
742   otherwise use a default device name.  */
743
744static void
745vox_open (sd)
746     struct sound_device *sd;
747{
748  char *file;
749
750  /* Open the sound device.  Default is /dev/dsp.  */
751  if (sd->file)
752    file = sd->file;
753  else
754    file = DEFAULT_SOUND_DEVICE;
755
756  sd->fd = emacs_open (file, O_WRONLY, 0);
757  if (sd->fd < 0)
758    sound_perror (file);
759}
760
761
762/* Configure device SD from parameters in it.  */
763
764static void
765vox_configure (sd)
766     struct sound_device *sd;
767{
768  int val;
769
770  xassert (sd->fd >= 0);
771
772  /* On GNU/Linux, it seems that the device driver doesn't like to be
773     interrupted by a signal.  Block the ones we know to cause
774     troubles.  */
775  turn_on_atimers (0);
776#ifdef SIGIO
777  sigblock (sigmask (SIGIO));
778#endif
779
780  val = sd->format;
781  if (ioctl (sd->fd, SNDCTL_DSP_SETFMT, &sd->format) < 0
782      || val != sd->format)
783    sound_perror ("Could not set sound format");
784
785  val = sd->channels != 1;
786  if (ioctl (sd->fd, SNDCTL_DSP_STEREO, &val) < 0
787      || val != (sd->channels != 1))
788    sound_perror ("Could not set stereo/mono");
789
790  /* I think bps and sampling_rate are the same, but who knows.
791     Check this. and use SND_DSP_SPEED for both.  */
792  if (sd->sample_rate > 0)
793    {
794      val = sd->sample_rate;
795      if (ioctl (sd->fd, SNDCTL_DSP_SPEED, &sd->sample_rate) < 0)
796	sound_perror ("Could not set sound speed");
797      else if (val != sd->sample_rate)
798	sound_warning ("Could not set sample rate");
799    }
800
801  if (sd->volume > 0)
802    {
803      int volume = sd->volume & 0xff;
804      volume |= volume << 8;
805      /* This may fail if there is no mixer.  Ignore the failure.  */
806      ioctl (sd->fd, SOUND_MIXER_WRITE_PCM, &volume);
807    }
808
809  turn_on_atimers (1);
810#ifdef SIGIO
811  sigunblock (sigmask (SIGIO));
812#endif
813}
814
815
816/* Close device SD if it is open.  */
817
818static void
819vox_close (sd)
820     struct sound_device *sd;
821{
822  if (sd->fd >= 0)
823    {
824      /* On GNU/Linux, it seems that the device driver doesn't like to
825	 be interrupted by a signal.  Block the ones we know to cause
826	 troubles.  */
827#ifdef SIGIO
828      sigblock (sigmask (SIGIO));
829#endif
830      turn_on_atimers (0);
831
832      /* Flush sound data, and reset the device.  */
833      ioctl (sd->fd, SNDCTL_DSP_SYNC, NULL);
834
835      turn_on_atimers (1);
836#ifdef SIGIO
837      sigunblock (sigmask (SIGIO));
838#endif
839
840      /* Close the device.  */
841      emacs_close (sd->fd);
842      sd->fd = -1;
843    }
844}
845
846
847/* Choose device-dependent format for device SD from sound file S.  */
848
849static void
850vox_choose_format (sd, s)
851     struct sound_device *sd;
852     struct sound *s;
853{
854  if (s->type == RIFF)
855    {
856      struct wav_header *h = (struct wav_header *) s->header;
857      if (h->precision == 8)
858	sd->format = AFMT_U8;
859      else if (h->precision == 16)
860	sd->format = AFMT_S16_LE;
861      else
862	error ("Unsupported WAV file format");
863    }
864  else if (s->type == SUN_AUDIO)
865    {
866      struct au_header *header = (struct au_header *) s->header;
867      switch (header->encoding)
868	{
869	case AU_ENCODING_ULAW_8:
870	case AU_ENCODING_IEEE32:
871	case AU_ENCODING_IEEE64:
872	  sd->format = AFMT_MU_LAW;
873	  break;
874
875	case AU_ENCODING_8:
876	case AU_ENCODING_16:
877	case AU_ENCODING_24:
878	case AU_ENCODING_32:
879	  sd->format = AFMT_S16_LE;
880	  break;
881
882	default:
883	  error ("Unsupported AU file format");
884	}
885    }
886  else
887    abort ();
888}
889
890
891/* Initialize device SD.  Set up the interface functions in the device
892   structure.  */
893
894static int
895vox_init (sd)
896     struct sound_device *sd;
897{
898  char *file;
899  int fd;
900
901  /* Open the sound device.  Default is /dev/dsp.  */
902  if (sd->file)
903    file = sd->file;
904  else
905    file = DEFAULT_SOUND_DEVICE;
906  fd = emacs_open (file, O_WRONLY, 0);
907  if (fd >= 0)
908    emacs_close (fd);
909  else
910    return 0;
911
912  sd->fd = -1;
913  sd->open = vox_open;
914  sd->close = vox_close;
915  sd->configure = vox_configure;
916  sd->choose_format = vox_choose_format;
917  sd->write = vox_write;
918  sd->period_size = NULL;
919
920  return 1;
921}
922
923/* Write NBYTES bytes from BUFFER to device SD.  */
924
925static void
926vox_write (sd, buffer, nbytes)
927     struct sound_device *sd;
928     const char *buffer;
929     int nbytes;
930{
931  int nwritten = emacs_write (sd->fd, buffer, nbytes);
932  if (nwritten < 0)
933    sound_perror ("Error writing to sound device");
934}
935
936#ifdef HAVE_ALSA
937/***********************************************************************
938		       ALSA Driver Interface
939 ***********************************************************************/
940
941/* This driver is available on GNU/Linux. */
942
943static void
944alsa_sound_perror (msg, err)
945     char *msg;
946     int err;
947{
948  error ("%s: %s", msg, snd_strerror (err));
949}
950
951struct alsa_params
952{
953  snd_pcm_t *handle;
954  snd_pcm_hw_params_t *hwparams;
955  snd_pcm_sw_params_t *swparams;
956  snd_pcm_uframes_t period_size;
957};
958
959/* Open device SD.  If SD->file is non-null, open that device,
960   otherwise use a default device name.  */
961
962static void
963alsa_open (sd)
964     struct sound_device *sd;
965{
966  char *file;
967  struct alsa_params *p;
968  int err;
969
970  /* Open the sound device.  Default is "default".  */
971  if (sd->file)
972    file = sd->file;
973  else
974    file = DEFAULT_ALSA_SOUND_DEVICE;
975
976  p = xmalloc (sizeof (*p));
977  p->handle = NULL;
978  p->hwparams = NULL;
979  p->swparams = NULL;
980
981  sd->fd = -1;
982  sd->data = p;
983
984
985  err = snd_pcm_open (&p->handle, file, SND_PCM_STREAM_PLAYBACK, 0);
986  if (err < 0)
987    alsa_sound_perror (file, err);
988}
989
990static int
991alsa_period_size (sd)
992       struct sound_device *sd;
993{
994  struct alsa_params *p = (struct alsa_params *) sd->data;
995  int fact = snd_pcm_format_size (sd->format, 1) * sd->channels;
996  return p->period_size * (fact > 0 ? fact : 1);
997}
998
999static void
1000alsa_configure (sd)
1001     struct sound_device *sd;
1002{
1003  int val, err, dir;
1004  unsigned uval;
1005  struct alsa_params *p = (struct alsa_params *) sd->data;
1006  snd_pcm_uframes_t buffer_size;
1007
1008  xassert (p->handle != 0);
1009
1010  err = snd_pcm_hw_params_malloc (&p->hwparams);
1011  if (err < 0)
1012    alsa_sound_perror ("Could not allocate hardware parameter structure", err);
1013
1014  err = snd_pcm_sw_params_malloc (&p->swparams);
1015  if (err < 0)
1016    alsa_sound_perror ("Could not allocate software parameter structure", err);
1017
1018  err = snd_pcm_hw_params_any (p->handle, p->hwparams);
1019  if (err < 0)
1020    alsa_sound_perror ("Could not initialize hardware parameter structure", err);
1021
1022  err = snd_pcm_hw_params_set_access (p->handle, p->hwparams,
1023                                      SND_PCM_ACCESS_RW_INTERLEAVED);
1024  if (err < 0)
1025    alsa_sound_perror ("Could not set access type", err);
1026
1027  val = sd->format;
1028  err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val);
1029  if (err < 0)
1030    alsa_sound_perror ("Could not set sound format", err);
1031
1032  uval = sd->sample_rate;
1033  err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0);
1034  if (err < 0)
1035    alsa_sound_perror ("Could not set sample rate", err);
1036
1037  val = sd->channels;
1038  err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val);
1039  if (err < 0)
1040    alsa_sound_perror ("Could not set channel count", err);
1041
1042  err = snd_pcm_hw_params (p->handle, p->hwparams);
1043  if (err < 0)
1044    alsa_sound_perror ("Could not set parameters", err);
1045
1046
1047  err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir);
1048  if (err < 0)
1049    alsa_sound_perror ("Unable to get period size for playback", err);
1050
1051  err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size);
1052  if (err < 0)
1053    alsa_sound_perror("Unable to get buffer size for playback", err);
1054
1055  err = snd_pcm_sw_params_current (p->handle, p->swparams);
1056  if (err < 0)
1057    alsa_sound_perror ("Unable to determine current swparams for playback",
1058                       err);
1059
1060  /* Start the transfer when the buffer is almost full */
1061  err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams,
1062                                               (buffer_size / p->period_size)
1063                                               * p->period_size);
1064  if (err < 0)
1065    alsa_sound_perror ("Unable to set start threshold mode for playback", err);
1066
1067  /* Allow the transfer when at least period_size samples can be processed */
1068  err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size);
1069  if (err < 0)
1070    alsa_sound_perror ("Unable to set avail min for playback", err);
1071
1072  /* Align all transfers to 1 period */
1073  err = snd_pcm_sw_params_set_xfer_align (p->handle, p->swparams,
1074                                          p->period_size);
1075  if (err < 0)
1076    alsa_sound_perror ("Unable to set transfer align for playback", err);
1077
1078  err = snd_pcm_sw_params (p->handle, p->swparams);
1079  if (err < 0)
1080    alsa_sound_perror ("Unable to set sw params for playback\n", err);
1081
1082  snd_pcm_hw_params_free (p->hwparams);
1083  p->hwparams = NULL;
1084  snd_pcm_sw_params_free (p->swparams);
1085  p->swparams = NULL;
1086
1087  err = snd_pcm_prepare (p->handle);
1088  if (err < 0)
1089    alsa_sound_perror ("Could not prepare audio interface for use", err);
1090
1091  if (sd->volume > 0)
1092    {
1093      int chn;
1094      snd_mixer_t *handle;
1095      snd_mixer_elem_t *e;
1096      char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE;
1097
1098      if (snd_mixer_open (&handle, 0) >= 0)
1099        {
1100          if (snd_mixer_attach (handle, file) >= 0
1101              && snd_mixer_load (handle) >= 0
1102              && snd_mixer_selem_register (handle, NULL, NULL) >= 0)
1103            for (e = snd_mixer_first_elem (handle);
1104                 e;
1105                 e = snd_mixer_elem_next (e))
1106              {
1107                if (snd_mixer_selem_has_playback_volume (e))
1108                  {
1109                    long pmin, pmax;
1110                    snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax);
1111                    long vol = pmin + (sd->volume * (pmax - pmin)) / 100;
1112
1113                    for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++)
1114                      snd_mixer_selem_set_playback_volume (e, chn, vol);
1115                  }
1116              }
1117          snd_mixer_close(handle);
1118        }
1119    }
1120}
1121
1122
1123/* Close device SD if it is open.  */
1124
1125static void
1126alsa_close (sd)
1127     struct sound_device *sd;
1128{
1129  struct alsa_params *p = (struct alsa_params *) sd->data;
1130  if (p)
1131    {
1132      if (p->hwparams)
1133        snd_pcm_hw_params_free (p->hwparams);
1134      if (p->swparams)
1135        snd_pcm_sw_params_free (p->swparams);
1136      if (p->handle)
1137        {
1138          snd_pcm_drain (p->handle);
1139          snd_pcm_close (p->handle);
1140        }
1141      free (p);
1142    }
1143}
1144
1145/* Choose device-dependent format for device SD from sound file S.  */
1146
1147static void
1148alsa_choose_format (sd, s)
1149     struct sound_device *sd;
1150     struct sound *s;
1151{
1152  struct alsa_params *p = (struct alsa_params *) sd->data;
1153  if (s->type == RIFF)
1154    {
1155      struct wav_header *h = (struct wav_header *) s->header;
1156      if (h->precision == 8)
1157	sd->format = SND_PCM_FORMAT_U8;
1158      else if (h->precision == 16)
1159          sd->format = SND_PCM_FORMAT_S16_LE;
1160      else
1161	error ("Unsupported WAV file format");
1162    }
1163  else if (s->type == SUN_AUDIO)
1164    {
1165      struct au_header *header = (struct au_header *) s->header;
1166      switch (header->encoding)
1167	{
1168	case AU_ENCODING_ULAW_8:
1169	  sd->format = SND_PCM_FORMAT_MU_LAW;
1170          break;
1171	case AU_ENCODING_ALAW_8:
1172	  sd->format = SND_PCM_FORMAT_A_LAW;
1173          break;
1174	case AU_ENCODING_IEEE32:
1175          sd->format = SND_PCM_FORMAT_FLOAT_BE;
1176          break;
1177	case AU_ENCODING_IEEE64:
1178	  sd->format = SND_PCM_FORMAT_FLOAT64_BE;
1179	  break;
1180	case AU_ENCODING_8:
1181	  sd->format = SND_PCM_FORMAT_S8;
1182	  break;
1183	case AU_ENCODING_16:
1184	  sd->format = SND_PCM_FORMAT_S16_BE;
1185	  break;
1186	case AU_ENCODING_24:
1187	  sd->format = SND_PCM_FORMAT_S24_BE;
1188	  break;
1189	case AU_ENCODING_32:
1190	  sd->format = SND_PCM_FORMAT_S32_BE;
1191	  break;
1192
1193	default:
1194	  error ("Unsupported AU file format");
1195	}
1196    }
1197  else
1198    abort ();
1199}
1200
1201
1202/* Write NBYTES bytes from BUFFER to device SD.  */
1203
1204static void
1205alsa_write (sd, buffer, nbytes)
1206     struct sound_device *sd;
1207     const char *buffer;
1208     int nbytes;
1209{
1210  struct alsa_params *p = (struct alsa_params *) sd->data;
1211
1212  /* The the third parameter to snd_pcm_writei is frames, not bytes. */
1213  int fact = snd_pcm_format_size (sd->format, 1) * sd->channels;
1214  int nwritten = 0;
1215  int err;
1216
1217  while (nwritten < nbytes)
1218    {
1219      snd_pcm_uframes_t frames = (nbytes - nwritten)/fact;
1220      if (frames == 0) break;
1221
1222      err = snd_pcm_writei (p->handle, buffer + nwritten, frames);
1223      if (err < 0)
1224        {
1225          if (err == -EPIPE)
1226            {	/* under-run */
1227              err = snd_pcm_prepare (p->handle);
1228              if (err < 0)
1229                alsa_sound_perror ("Can't recover from underrun, prepare failed",
1230                                   err);
1231            }
1232          else if (err == -ESTRPIPE)
1233            {
1234              while ((err = snd_pcm_resume (p->handle)) == -EAGAIN)
1235                sleep(1);	/* wait until the suspend flag is released */
1236              if (err < 0)
1237                {
1238                  err = snd_pcm_prepare (p->handle);
1239                  if (err < 0)
1240                    alsa_sound_perror ("Can't recover from suspend, "
1241                                       "prepare failed",
1242                                       err);
1243                }
1244            }
1245          else
1246            alsa_sound_perror ("Error writing to sound device", err);
1247
1248        }
1249      else
1250        nwritten += err * fact;
1251    }
1252}
1253
1254static void
1255snd_error_quiet (file, line, function, err, fmt)
1256     const char *file;
1257     int line;
1258     const char *function;
1259     int err;
1260     const char *fmt;
1261{
1262}
1263
1264/* Initialize device SD.  Set up the interface functions in the device
1265   structure.  */
1266
1267static int
1268alsa_init (sd)
1269     struct sound_device *sd;
1270{
1271  char *file;
1272  snd_pcm_t *handle;
1273  int err;
1274
1275  /* Open the sound device.  Default is "default".  */
1276  if (sd->file)
1277    file = sd->file;
1278  else
1279    file = DEFAULT_ALSA_SOUND_DEVICE;
1280
1281  snd_lib_error_set_handler ((snd_lib_error_handler_t) snd_error_quiet);
1282  err = snd_pcm_open (&handle, file, SND_PCM_STREAM_PLAYBACK, 0);
1283  snd_lib_error_set_handler (NULL);
1284  if (err < 0)
1285      return 0;
1286  snd_pcm_close (handle);
1287
1288  sd->fd = -1;
1289  sd->open = alsa_open;
1290  sd->close = alsa_close;
1291  sd->configure = alsa_configure;
1292  sd->choose_format = alsa_choose_format;
1293  sd->write = alsa_write;
1294  sd->period_size = alsa_period_size;
1295
1296  return 1;
1297}
1298
1299#endif /* HAVE_ALSA */
1300
1301
1302/* END: Non Windows functions */
1303#else /* WINDOWSNT */
1304
1305/* BEGIN: Windows specific functions */
1306
1307static int
1308do_play_sound (psz_file, ui_volume)
1309     const char *psz_file;
1310     unsigned long ui_volume;
1311{
1312  int i_result = 0;
1313  MCIERROR mci_error = 0;
1314  char sz_cmd_buf[520] = {0};
1315  char sz_ret_buf[520] = {0};
1316  MMRESULT mm_result = MMSYSERR_NOERROR;
1317  unsigned long ui_volume_org = 0;
1318  BOOL b_reset_volume = FALSE;
1319
1320  memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
1321  memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
1322  sprintf (sz_cmd_buf,
1323           "open \"%s\" alias GNUEmacs_PlaySound_Device wait",
1324           psz_file);
1325  mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
1326  if (mci_error != 0)
1327    {
1328      sound_warning ("The open mciSendString command failed to open\n"
1329                     "the specified sound file");
1330      i_result = (int) mci_error;
1331      return i_result;
1332    }
1333  if ((ui_volume > 0) && (ui_volume != UINT_MAX))
1334    {
1335      mm_result = waveOutGetVolume ((HWAVEOUT) WAVE_MAPPER, &ui_volume_org);
1336      if (mm_result == MMSYSERR_NOERROR)
1337        {
1338          b_reset_volume = TRUE;
1339          mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume);
1340          if ( mm_result != MMSYSERR_NOERROR)
1341            {
1342              sound_warning ("waveOutSetVolume failed to set the volume level\n"
1343                             "of the WAVE_MAPPER device.\n"
1344                             "As a result, the user selected volume level will\n"
1345                             "not be used.");
1346            }
1347        }
1348      else
1349        {
1350          sound_warning ("waveOutGetVolume failed to obtain the original\n"
1351                         "volume level of the WAVE_MAPPER device.\n"
1352                         "As a result, the user selected volume level will\n"
1353                         "not be used.");
1354        }
1355    }
1356  memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
1357  memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
1358  strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait");
1359  mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
1360  if (mci_error != 0)
1361    {
1362      sound_warning ("The play mciSendString command failed to play the\n"
1363                     "opened sound file.");
1364      i_result = (int) mci_error;
1365    }
1366  memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
1367  memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
1368  strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait");
1369  mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
1370  if (b_reset_volume == TRUE)
1371    {
1372      mm_result=waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org);
1373      if (mm_result != MMSYSERR_NOERROR)
1374        {
1375          sound_warning ("waveOutSetVolume failed to reset the original volume\n"
1376                         "level of the WAVE_MAPPER device.");
1377        }
1378    }
1379  return i_result;
1380}
1381
1382/* END: Windows specific functions */
1383
1384#endif /* WINDOWSNT */
1385
1386DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
1387       doc: /* Play sound SOUND.
1388
1389Internal use only, use `play-sound' instead.  */)
1390     (sound)
1391     Lisp_Object sound;
1392{
1393  Lisp_Object attrs[SOUND_ATTR_SENTINEL];
1394  int count = SPECPDL_INDEX ();
1395
1396#ifndef WINDOWSNT
1397  Lisp_Object file;
1398  struct gcpro gcpro1, gcpro2;
1399  Lisp_Object args[2];
1400#else /* WINDOWSNT */
1401  int len = 0;
1402  Lisp_Object lo_file = {0};
1403  char * psz_file = NULL;
1404  unsigned long ui_volume_tmp = UINT_MAX;
1405  unsigned long ui_volume = UINT_MAX;
1406  int i_result = 0;
1407#endif /* WINDOWSNT */
1408
1409  /* Parse the sound specification.  Give up if it is invalid.  */
1410  if (!parse_sound (sound, attrs))
1411    error ("Invalid sound specification");
1412
1413#ifndef WINDOWSNT
1414  file = Qnil;
1415  GCPRO2 (sound, file);
1416  current_sound_device = (struct sound_device *) xmalloc (sizeof (struct sound_device));
1417  bzero (current_sound_device, sizeof (struct sound_device));
1418  current_sound = (struct sound *) xmalloc (sizeof (struct sound));
1419  bzero (current_sound, sizeof (struct sound));
1420  record_unwind_protect (sound_cleanup, Qnil);
1421  current_sound->header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
1422
1423  if (STRINGP (attrs[SOUND_FILE]))
1424    {
1425      /* Open the sound file.  */
1426      current_sound->fd = openp (Fcons (Vdata_directory, Qnil),
1427				 attrs[SOUND_FILE], Qnil, &file, Qnil);
1428      if (current_sound->fd < 0)
1429	sound_perror ("Could not open sound file");
1430
1431      /* Read the first bytes from the file.  */
1432      current_sound->header_size
1433	= emacs_read (current_sound->fd, current_sound->header,
1434		      MAX_SOUND_HEADER_BYTES);
1435      if (current_sound->header_size < 0)
1436	sound_perror ("Invalid sound file header");
1437    }
1438  else
1439    {
1440      current_sound->data = attrs[SOUND_DATA];
1441      current_sound->header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (current_sound->data));
1442      bcopy (SDATA (current_sound->data), current_sound->header, current_sound->header_size);
1443    }
1444
1445  /* Find out the type of sound.  Give up if we can't tell.  */
1446  find_sound_type (current_sound);
1447
1448  /* Set up a device.  */
1449  if (STRINGP (attrs[SOUND_DEVICE]))
1450    {
1451      int len = SCHARS (attrs[SOUND_DEVICE]);
1452      current_sound_device->file = (char *) alloca (len + 1);
1453      strcpy (current_sound_device->file, SDATA (attrs[SOUND_DEVICE]));
1454    }
1455
1456  if (INTEGERP (attrs[SOUND_VOLUME]))
1457    current_sound_device->volume = XFASTINT (attrs[SOUND_VOLUME]);
1458  else if (FLOATP (attrs[SOUND_VOLUME]))
1459    current_sound_device->volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
1460
1461  args[0] = Qplay_sound_functions;
1462  args[1] = sound;
1463  Frun_hook_with_args (2, args);
1464
1465#ifdef HAVE_ALSA
1466  if (!alsa_init (current_sound_device))
1467#endif
1468    if (!vox_init (current_sound_device))
1469      error ("No usable sound device driver found");
1470
1471  /* Open the device.  */
1472  current_sound_device->open (current_sound_device);
1473
1474  /* Play the sound.  */
1475  current_sound->play (current_sound, current_sound_device);
1476
1477  /* Clean up.  */
1478  UNGCPRO;
1479
1480#else /* WINDOWSNT */
1481
1482  lo_file = Fexpand_file_name (attrs[SOUND_FILE], Qnil);
1483  len = XSTRING (lo_file)->size;
1484  psz_file = (char *) alloca (len + 1);
1485  strcpy (psz_file, XSTRING (lo_file)->data);
1486  if (INTEGERP (attrs[SOUND_VOLUME]))
1487    {
1488      ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]);
1489    }
1490  else if (FLOATP (attrs[SOUND_VOLUME]))
1491    {
1492      ui_volume_tmp = (unsigned long) XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
1493    }
1494  /*
1495    Based on some experiments I have conducted, a value of 100 or less
1496    for the sound volume is much too low.  You cannot even hear it.
1497    A value of UINT_MAX indicates that you wish for the sound to played
1498    at the maximum possible volume.  A value of UINT_MAX/2 plays the
1499    sound at 50% maximum volume.  Therefore the value passed to do_play_sound
1500    (and thus to waveOutSetVolume) must be some fraction of UINT_MAX.
1501    The following code adjusts the user specified volume level appropriately.
1502  */
1503  if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100))
1504    {
1505      ui_volume = ui_volume_tmp * (UINT_MAX / 100);
1506    }
1507  i_result = do_play_sound (psz_file, ui_volume);
1508
1509#endif /* WINDOWSNT */
1510
1511  unbind_to (count, Qnil);
1512  return Qnil;
1513}
1514
1515/***********************************************************************
1516			    Initialization
1517 ***********************************************************************/
1518
1519void
1520syms_of_sound ()
1521{
1522  QCdevice = intern (":device");
1523  staticpro (&QCdevice);
1524  QCvolume = intern (":volume");
1525  staticpro (&QCvolume);
1526  Qsound = intern ("sound");
1527  staticpro (&Qsound);
1528  Qplay_sound_functions = intern ("play-sound-functions");
1529  staticpro (&Qplay_sound_functions);
1530
1531  defsubr (&Splay_sound_internal);
1532}
1533
1534
1535void
1536init_sound ()
1537{
1538}
1539
1540#endif /* HAVE_SOUND */
1541
1542/* arch-tag: dd850ad8-0433-4e2c-9cba-b7aeeccc0dbd
1543   (do not change this comment) */
1544