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