Update for font-backend changes.
[bpt/emacs.git] / src / sound.c
CommitLineData
7840ced1 1/* sound.c -- sound support.
0b5538bd 2 Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004,
8cabe764 3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
7840ced1
GM
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
684d6f5b 9the Free Software Foundation; either version 3, or (at your option)
7840ced1
GM
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
4fc5845f
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
7840ced1
GM
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
f60ae425
BK
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
06c3eeed 37 waveOutSetVolume which are exported by Winmm.dll.
f60ae425
BK
38*/
39
7840ced1
GM
40#include <config.h>
41
42#if defined HAVE_SOUND
43
f60ae425 44/* BEGIN: Common Includes */
7840ced1
GM
45#include <fcntl.h>
46#include <unistd.h>
47#include <sys/types.h>
7840ced1 48#include <errno.h>
53fab6e2
GM
49#include "lisp.h"
50#include "dispextern.h"
51#include "atimer.h"
bb6e8cee
GM
52#include <signal.h>
53#include "syssignal.h"
f60ae425
BK
54/* END: Common Includes */
55
56
57/* BEGIN: Non Windows Includes */
58#ifndef WINDOWSNT
7840ced1 59
502150e5
PJ
60#ifndef MSDOS
61#include <sys/ioctl.h>
62#endif
63
7840ced1
GM
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
80fcd514 73#ifdef HAVE_SOUNDCARD_H
80fcd514
KR
74#include <soundcard.h>
75#endif
2d2643f6 76#ifdef HAVE_ALSA
1d30a597
JD
77#ifdef ALSA_SUBDIR_INCLUDE
78#include <alsa/asoundlib.h>
79#else
2d2643f6 80#include <asoundlib.h>
1d30a597
JD
81#endif /* ALSA_SUBDIR_INCLUDE */
82#endif /* HAVE_ALSA */
2d2643f6 83
f60ae425
BK
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 */
f60ae425
BK
100
101/* Symbols. */
102
103extern Lisp_Object QCfile, QCdata;
104Lisp_Object QCvolume, QCdevice;
105Lisp_Object Qsound;
106Lisp_Object Qplay_sound_functions;
107
108/* Indices of attributes in a sound attributes vector. */
109
110enum sound_attr
111{
112 SOUND_FILE,
113 SOUND_DATA,
114 SOUND_DEVICE,
115 SOUND_VOLUME,
116 SOUND_ATTR_SENTINEL
117};
118
01d09305
DN
119static void alsa_sound_perror P_ ((char *, int)) NO_RETURN;
120static void sound_perror P_ ((char *)) NO_RETURN;
f60ae425
BK
121static void sound_warning P_ ((char *));
122static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
123
124/* END: Common Definitions */
125
126/* BEGIN: Non Windows Definitions */
127#ifndef WINDOWSNT
80fcd514
KR
128
129#ifndef DEFAULT_SOUND_DEVICE
130#define DEFAULT_SOUND_DEVICE "/dev/dsp"
131#endif
2d2643f6
JD
132#ifndef DEFAULT_ALSA_SOUND_DEVICE
133#define DEFAULT_ALSA_SOUND_DEVICE "default"
134#endif
7840ced1 135
7840ced1
GM
136
137/* Structure forward declarations. */
138
d1299cde 139struct sound;
7840ced1
GM
140struct sound_device;
141
142/* The file header of RIFF-WAVE files (*.wav). Files are always in
143 little-endian byte-order. */
144
145struct 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
165struct au_header
166{
167 /* ASCII ".snd" */
168 u_int32_t magic_number;
a4ff5d67 169
7840ced1
GM
170 /* Offset of data part from start of file. Minimum value is 24. */
171 u_int32_t data_offset;
a4ff5d67 172
7840ced1
GM
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
202struct 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;
a4ff5d67 227
7840ced1
GM
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));
a4ff5d67 236
d1299cde 237 /* Choose a device-dependent format for outputting sound S. */
7840ced1 238 void (* choose_format) P_ ((struct sound_device *sd,
d1299cde 239 struct sound *s));
7840ced1 240
2d2643f6
JD
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
7840ced1 245 /* Write NYBTES bytes from BUFFER to device SD. */
dca0fc1c
KR
246 void (* write) P_ ((struct sound_device *sd, const char *buffer,
247 int nbytes));
7840ced1
GM
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
255enum sound_type
256{
257 RIFF,
258 SUN_AUDIO
259};
260
261/* Interface structure for sound files. */
262
d1299cde 263struct sound
7840ced1
GM
264{
265 /* The type of the file. */
266 enum sound_type type;
267
d1299cde 268 /* File descriptor of a sound file. */
7840ced1
GM
269 int fd;
270
d1299cde
GM
271 /* Pointer to sound file header. This contains header_size bytes
272 read from the start of a sound file. */
7840ced1
GM
273 char *header;
274
d1299cde
GM
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. */
a4ff5d67 283 void (* play) P_ ((struct sound *s, struct sound_device *sd));
7840ced1
GM
284};
285
14e415e7 286/* These are set during `play-sound-internal' so that sound_cleanup has
7840ced1
GM
287 access to them. */
288
d1299cde
GM
289struct sound_device *current_sound_device;
290struct sound *current_sound;
7840ced1
GM
291
292/* Function prototypes. */
293
294static void vox_open P_ ((struct sound_device *));
295static void vox_configure P_ ((struct sound_device *));
296static void vox_close P_ ((struct sound_device *sd));
d1299cde 297static void vox_choose_format P_ ((struct sound_device *, struct sound *));
2d2643f6 298static int vox_init P_ ((struct sound_device *));
dca0fc1c 299static void vox_write P_ ((struct sound_device *, const char *, int));
d1299cde 300static void find_sound_type P_ ((struct sound *));
7840ced1
GM
301static u_int32_t le2hl P_ ((u_int32_t));
302static u_int16_t le2hs P_ ((u_int16_t));
303static u_int32_t be2hl P_ ((u_int32_t));
d1299cde
GM
304static int wav_init P_ ((struct sound *));
305static void wav_play P_ ((struct sound *, struct sound_device *));
306static int au_init P_ ((struct sound *));
307static void au_play P_ ((struct sound *, struct sound_device *));
7840ced1 308
9680b9d0
GM
309#if 0 /* Currently not used. */
310static u_int16_t be2hs P_ ((u_int16_t));
311#endif
312
f60ae425
BK
313/* END: Non Windows Definitions */
314#else /* WINDOWSNT */
315
316/* BEGIN: Windows Specific Definitions */
317static int do_play_sound P_ ((const char *, unsigned long));
318/*
319 END: Windows Specific Definitions */
320#endif /* WINDOWSNT */
7840ced1
GM
321
322\f
323/***********************************************************************
324 General
325 ***********************************************************************/
326
f60ae425
BK
327/* BEGIN: Common functions */
328
7840ced1
GM
329/* Like perror, but signals an error. */
330
331static void
332sound_perror (msg)
333 char *msg;
334{
3297e2a1
AS
335 int saved_errno = errno;
336
62725a92
GM
337 turn_on_atimers (1);
338#ifdef SIGIO
339 sigunblock (sigmask (SIGIO));
340#endif
3297e2a1
AS
341 if (saved_errno != 0)
342 error ("%s: %s", msg, strerror (saved_errno));
62725a92
GM
343 else
344 error ("%s", msg);
345}
346
347
348/* Display a warning message. */
349
350static void
351sound_warning (msg)
352 char *msg;
353{
354 message (msg);
7840ced1
GM
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
d1299cde
GM
369 - `:data DATA'
370
371 DATA is a string containing sound data. Either :file or :data
372 may be present, but not both.
373
7840ced1
GM
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
2a53558d
GM
381 VOL must be an integer in the range [0, 100], or a float in the
382 range [0, 1]. */
7840ced1
GM
383
384static int
385parse_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);
d1299cde 395 attrs[SOUND_DATA] = Fplist_get (sound, QCdata);
7840ced1
GM
396 attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
397 attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
398
f60ae425 399#ifndef WINDOWSNT
d1299cde
GM
400 /* File name or data must be specified. */
401 if (!STRINGP (attrs[SOUND_FILE])
402 && !STRINGP (attrs[SOUND_DATA]))
7840ced1 403 return 0;
f60ae425
BK
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 */
7840ced1
GM
414
415 /* Volume must be in the range 0..100 or unspecified. */
416 if (!NILP (attrs[SOUND_VOLUME]))
417 {
2a53558d
GM
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
7840ced1
GM
431 return 0;
432 }
433
f60ae425 434#ifndef WINDOWSNT
7840ced1
GM
435 /* Device must be a string or unspecified. */
436 if (!NILP (attrs[SOUND_DEVICE])
437 && !STRINGP (attrs[SOUND_DEVICE]))
438 return 0;
f60ae425
BK
439#endif /* WINDOWSNT */
440 /*
441 Since device is ignored in Windows, it does not matter
442 what it is.
443 */
7840ced1
GM
444 return 1;
445}
446
f60ae425
BK
447/* END: Common functions */
448
449/* BEGIN: Non Windows functions */
450#ifndef WINDOWSNT
7840ced1
GM
451
452/* Find out the type of the sound file whose file descriptor is FD.
d1299cde 453 S is the sound file structure to fill in. */
7840ced1
GM
454
455static void
d1299cde
GM
456find_sound_type (s)
457 struct sound *s;
7840ced1 458{
d1299cde
GM
459 if (!wav_init (s) && !au_init (s))
460 error ("Unknown sound format");
7840ced1
GM
461}
462
463
14e415e7 464/* Function installed by play-sound-internal with record_unwind_protect. */
7840ced1
GM
465
466static Lisp_Object
467sound_cleanup (arg)
468 Lisp_Object arg;
469{
8e6ec322
RS
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);
3887b449
GM
476
477 return Qnil;
7840ced1
GM
478}
479
7840ced1
GM
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
487static u_int32_t
488le2hl (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
502static u_int16_t
503le2hs (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
517static u_int32_t
518be2hl (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
9680b9d0
GM
529#if 0 /* Currently not used. */
530
7840ced1
GM
531/* Convert 16-bit value VALUE which is in big-endian byte-order
532 to host byte-order. */
533
534static u_int16_t
535be2hs (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
9680b9d0 545#endif /* 0 */
7840ced1 546
7840ced1
GM
547/***********************************************************************
548 RIFF-WAVE (*.wav)
549 ***********************************************************************/
550
d1299cde 551/* Try to initialize sound file S from S->header. S->header
7840ced1
GM
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
d1299cde 554 functions in S and convert header fields to host byte-order.
7840ced1
GM
555 Value is non-zero if the file is a WAV file. */
556
557static int
d1299cde
GM
558wav_init (s)
559 struct sound *s;
7840ced1 560{
d1299cde
GM
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)
7840ced1
GM
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. */
d1299cde
GM
584 s->type = RIFF;
585 s->play = wav_play;
7840ced1
GM
586
587 return 1;
a4ff5d67 588}
7840ced1
GM
589
590
d1299cde 591/* Play RIFF-WAVE audio file S on sound device SD. */
7840ced1
GM
592
593static void
d1299cde
GM
594wav_play (s, sd)
595 struct sound *s;
7840ced1
GM
596 struct sound_device *sd;
597{
d1299cde 598 struct wav_header *header = (struct wav_header *) s->header;
7840ced1
GM
599
600 /* Let the device choose a suitable device-dependent format
601 for the file. */
d1299cde 602 sd->choose_format (sd, s);
a4ff5d67 603
7840ced1
GM
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. */
d1299cde 615 if (STRINGP (s->data))
d5db4077
KR
616 sd->write (sd, SDATA (s->data) + sizeof *header,
617 SBYTES (s->data) - sizeof *header);
d1299cde
GM
618 else
619 {
620 char *buffer;
621 int nbytes;
2d2643f6 622 int blksize = sd->period_size ? sd->period_size (sd) : 2048;
a28de257 623 int data_left = header->data_length;
a4ff5d67 624
d1299cde
GM
625 buffer = (char *) alloca (blksize);
626 lseek (s->fd, sizeof *header, SEEK_SET);
a28de257
JD
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 }
7840ced1 635
d1299cde 636 if (nbytes < 0)
62725a92 637 sound_perror ("Error reading sound file");
d1299cde 638 }
7840ced1
GM
639}
640
641
7840ced1
GM
642/***********************************************************************
643 Sun Audio (*.au)
644 ***********************************************************************/
645
a4ff5d67 646/* Sun audio file encodings. */
7840ced1
GM
647
648enum 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,
2d2643f6
JD
657 AU_COMPRESSED = 23,
658 AU_ENCODING_ALAW_8 = 27
7840ced1
GM
659};
660
661
d1299cde 662/* Try to initialize sound file S from S->header. S->header
7840ced1
GM
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
d1299cde 665 functions in S and convert header fields to host byte-order.
7840ced1
GM
666 Value is non-zero if the file is an AU file. */
667
668static int
d1299cde
GM
669au_init (s)
670 struct sound *s;
7840ced1 671{
d1299cde 672 struct au_header *header = (struct au_header *) s->header;
a4ff5d67 673
d1299cde
GM
674 if (s->header_size < sizeof *header
675 || bcmp (s->header, ".snd", 4) != 0)
7840ced1 676 return 0;
a4ff5d67 677
7840ced1
GM
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);
a4ff5d67 684
7840ced1 685 /* Set up the interface functions for AU. */
d1299cde
GM
686 s->type = SUN_AUDIO;
687 s->play = au_play;
7840ced1
GM
688
689 return 1;
690}
691
692
d1299cde 693/* Play Sun audio file S on sound device SD. */
7840ced1
GM
694
695static void
d1299cde
GM
696au_play (s, sd)
697 struct sound *s;
7840ced1
GM
698 struct sound_device *sd;
699{
d1299cde 700 struct au_header *header = (struct au_header *) s->header;
7840ced1
GM
701
702 sd->sample_size = 0;
703 sd->sample_rate = header->sample_rate;
704 sd->bps = 0;
705 sd->channels = header->channels;
d1299cde 706 sd->choose_format (sd, s);
7840ced1 707 sd->configure (sd);
d1299cde
GM
708
709 if (STRINGP (s->data))
d5db4077
KR
710 sd->write (sd, SDATA (s->data) + header->data_offset,
711 SBYTES (s->data) - header->data_offset);
d1299cde
GM
712 else
713 {
2d2643f6 714 int blksize = sd->period_size ? sd->period_size (sd) : 2048;
d1299cde
GM
715 char *buffer;
716 int nbytes;
a4ff5d67 717
d1299cde
GM
718 /* Seek */
719 lseek (s->fd, header->data_offset, SEEK_SET);
a4ff5d67 720
d1299cde
GM
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);
a4ff5d67 725
d1299cde 726 if (nbytes < 0)
62725a92 727 sound_perror ("Error reading sound file");
d1299cde 728 }
7840ced1
GM
729}
730
731
7840ced1
GM
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
743static void
744vox_open (sd)
745 struct sound_device *sd;
746{
747 char *file;
a4ff5d67 748
7840ced1
GM
749 /* Open the sound device. Default is /dev/dsp. */
750 if (sd->file)
751 file = sd->file;
752 else
80fcd514 753 file = DEFAULT_SOUND_DEVICE;
a4ff5d67 754
68c45bf0 755 sd->fd = emacs_open (file, O_WRONLY, 0);
7840ced1
GM
756 if (sd->fd < 0)
757 sound_perror (file);
758}
759
760
761/* Configure device SD from parameters in it. */
762
763static void
764vox_configure (sd)
765 struct sound_device *sd;
766{
28fcb7dc 767 int val;
a4ff5d67 768
7840ced1
GM
769 xassert (sd->fd >= 0);
770
bb6e8cee
GM
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. */
b5cb1ada 774 turn_on_atimers (0);
bb6e8cee
GM
775#ifdef SIGIO
776 sigblock (sigmask (SIGIO));
777#endif
b5cb1ada 778
28fcb7dc
GM
779 val = sd->format;
780 if (ioctl (sd->fd, SNDCTL_DSP_SETFMT, &sd->format) < 0
781 || val != sd->format)
62725a92 782 sound_perror ("Could not set sound format");
7840ced1 783
28fcb7dc
GM
784 val = sd->channels != 1;
785 if (ioctl (sd->fd, SNDCTL_DSP_STEREO, &val) < 0
786 || val != (sd->channels != 1))
62725a92 787 sound_perror ("Could not set stereo/mono");
7840ced1 788
28fcb7dc
GM
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;
62725a92
GM
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");
28fcb7dc 798 }
7840ced1 799
3887b449
GM
800 if (sd->volume > 0)
801 {
802 int volume = sd->volume & 0xff;
803 volume |= volume << 8;
28fcb7dc
GM
804 /* This may fail if there is no mixer. Ignore the failure. */
805 ioctl (sd->fd, SOUND_MIXER_WRITE_PCM, &volume);
3887b449 806 }
a4ff5d67 807
b5cb1ada 808 turn_on_atimers (1);
bb6e8cee
GM
809#ifdef SIGIO
810 sigunblock (sigmask (SIGIO));
811#endif
7840ced1
GM
812}
813
814
815/* Close device SD if it is open. */
816
817static void
818vox_close (sd)
819 struct sound_device *sd;
820{
821 if (sd->fd >= 0)
822 {
bb6e8cee
GM
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
b5cb1ada 829 turn_on_atimers (0);
a4ff5d67 830
bb6e8cee 831 /* Flush sound data, and reset the device. */
7840ced1 832 ioctl (sd->fd, SNDCTL_DSP_SYNC, NULL);
a4ff5d67 833
b5cb1ada 834 turn_on_atimers (1);
bb6e8cee
GM
835#ifdef SIGIO
836 sigunblock (sigmask (SIGIO));
837#endif
7840ced1
GM
838
839 /* Close the device. */
68c45bf0 840 emacs_close (sd->fd);
7840ced1
GM
841 sd->fd = -1;
842 }
843}
844
845
d1299cde 846/* Choose device-dependent format for device SD from sound file S. */
7840ced1
GM
847
848static void
d1299cde 849vox_choose_format (sd, s)
7840ced1 850 struct sound_device *sd;
d1299cde 851 struct sound *s;
7840ced1 852{
d1299cde 853 if (s->type == RIFF)
7840ced1 854 {
d1299cde 855 struct wav_header *h = (struct wav_header *) s->header;
7840ced1
GM
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 }
d1299cde 863 else if (s->type == SUN_AUDIO)
7840ced1 864 {
d1299cde 865 struct au_header *header = (struct au_header *) s->header;
7840ced1
GM
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;
a4ff5d67 873
7840ced1
GM
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
2d2643f6 893static int
7840ced1
GM
894vox_init (sd)
895 struct sound_device *sd;
896{
2d2643f6
JD
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
7840ced1
GM
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;
2d2643f6
JD
917 sd->period_size = NULL;
918
919 return 1;
7840ced1
GM
920}
921
7840ced1
GM
922/* Write NBYTES bytes from BUFFER to device SD. */
923
924static void
925vox_write (sd, buffer, nbytes)
926 struct sound_device *sd;
dca0fc1c 927 const char *buffer;
7840ced1
GM
928 int nbytes;
929{
68c45bf0 930 int nwritten = emacs_write (sd->fd, buffer, nbytes);
7840ced1 931 if (nwritten < 0)
62725a92 932 sound_perror ("Error writing to sound device");
7840ced1
GM
933}
934
2d2643f6
JD
935#ifdef HAVE_ALSA
936/***********************************************************************
937 ALSA Driver Interface
938 ***********************************************************************/
939
940/* This driver is available on GNU/Linux. */
941
942static void
943alsa_sound_perror (msg, err)
944 char *msg;
945 int err;
946{
947 error ("%s: %s", msg, snd_strerror (err));
948}
949
950struct 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
961static void
962alsa_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
3fc7a865
JD
984 err = snd_pcm_open (&p->handle, file, SND_PCM_STREAM_PLAYBACK, 0);
985 if (err < 0)
2d2643f6
JD
986 alsa_sound_perror (file, err);
987}
988
989static int
990alsa_period_size (sd)
991 struct sound_device *sd;
992{
993 struct alsa_params *p = (struct alsa_params *) sd->data;
a28de257
JD
994 int fact = snd_pcm_format_size (sd->format, 1) * sd->channels;
995 return p->period_size * (fact > 0 ? fact : 1);
2d2643f6
JD
996}
997
998static void
999alsa_configure (sd)
1000 struct sound_device *sd;
1001{
1002 int val, err, dir;
dcc88121 1003 unsigned uval;
2d2643f6
JD
1004 struct alsa_params *p = (struct alsa_params *) sd->data;
1005 snd_pcm_uframes_t buffer_size;
1006
1007 xassert (p->handle != 0);
1008
3fc7a865
JD
1009 err = snd_pcm_hw_params_malloc (&p->hwparams);
1010 if (err < 0)
2d2643f6
JD
1011 alsa_sound_perror ("Could not allocate hardware parameter structure", err);
1012
3fc7a865
JD
1013 err = snd_pcm_sw_params_malloc (&p->swparams);
1014 if (err < 0)
2d2643f6
JD
1015 alsa_sound_perror ("Could not allocate software parameter structure", err);
1016
3fc7a865
JD
1017 err = snd_pcm_hw_params_any (p->handle, p->hwparams);
1018 if (err < 0)
2d2643f6
JD
1019 alsa_sound_perror ("Could not initialize hardware parameter structure", err);
1020
3fc7a865
JD
1021 err = snd_pcm_hw_params_set_access (p->handle, p->hwparams,
1022 SND_PCM_ACCESS_RW_INTERLEAVED);
1023 if (err < 0)
2d2643f6
JD
1024 alsa_sound_perror ("Could not set access type", err);
1025
1026 val = sd->format;
3fc7a865 1027 err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val);
ed1f0a45 1028 if (err < 0)
2d2643f6
JD
1029 alsa_sound_perror ("Could not set sound format", err);
1030
dcc88121
JD
1031 uval = sd->sample_rate;
1032 err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0);
3fc7a865 1033 if (err < 0)
2d2643f6 1034 alsa_sound_perror ("Could not set sample rate", err);
ed1f0a45 1035
2d2643f6 1036 val = sd->channels;
3fc7a865
JD
1037 err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val);
1038 if (err < 0)
2d2643f6
JD
1039 alsa_sound_perror ("Could not set channel count", err);
1040
3fc7a865
JD
1041 err = snd_pcm_hw_params (p->handle, p->hwparams);
1042 if (err < 0)
07a7837c
JD
1043 alsa_sound_perror ("Could not set parameters", err);
1044
2d2643f6
JD
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
2d2643f6
JD
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;
ed1f0a45 1085
3fc7a865
JD
1086 err = snd_pcm_prepare (p->handle);
1087 if (err < 0)
2d2643f6 1088 alsa_sound_perror ("Could not prepare audio interface for use", err);
ed1f0a45 1089
2d2643f6
JD
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 {
646d0d12 1108 long pmin, pmax, vol;
2d2643f6 1109 snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax);
646d0d12 1110 vol = pmin + (sd->volume * (pmax - pmin)) / 100;
ed1f0a45 1111
2d2643f6
JD
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
1124static void
1125alsa_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 {
dcc88121 1137 snd_pcm_drain (p->handle);
2d2643f6
JD
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
1146static void
1147alsa_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
1203static void
1204alsa_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 {
a28de257
JD
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);
3fc7a865 1222 if (err < 0)
2d2643f6 1223 {
2d2643f6
JD
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 }
ed1f0a45 1244 else
2d2643f6 1245 alsa_sound_perror ("Error writing to sound device", err);
ed1f0a45 1246
2d2643f6
JD
1247 }
1248 else
1249 nwritten += err * fact;
1250 }
1251}
1252
1253static void
1254snd_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
1266static int
1267alsa_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)
dcc88121
JD
1284 return 0;
1285 snd_pcm_close (handle);
2d2643f6
JD
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
f60ae425
BK
1301/* END: Non Windows functions */
1302#else /* WINDOWSNT */
1303
1304/* BEGIN: Windows specific functions */
1305
1306static int
1307do_play_sound (psz_file, ui_volume)
06c3eeed
JB
1308 const char *psz_file;
1309 unsigned long ui_volume;
f60ae425 1310{
06c3eeed
JB
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
f60ae425
BK
1319 memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
1320 memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
06c3eeed
JB
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);
f60ae425
BK
1325 if (mci_error != 0)
1326 {
06c3eeed
JB
1327 sound_warning ("The open mciSendString command failed to open\n"
1328 "the specified sound file");
1329 i_result = (int) mci_error;
f60ae425
BK
1330 return i_result;
1331 }
1332 if ((ui_volume > 0) && (ui_volume != UINT_MAX))
1333 {
06c3eeed 1334 mm_result = waveOutGetVolume ((HWAVEOUT) WAVE_MAPPER, &ui_volume_org);
f60ae425
BK
1335 if (mm_result == MMSYSERR_NOERROR)
1336 {
06c3eeed
JB
1337 b_reset_volume = TRUE;
1338 mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume);
f60ae425
BK
1339 if ( mm_result != MMSYSERR_NOERROR)
1340 {
06c3eeed
JB
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.");
f60ae425
BK
1345 }
1346 }
1347 else
1348 {
06c3eeed
JB
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.");
f60ae425
BK
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");
06c3eeed 1358 mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
f60ae425
BK
1359 if (mci_error != 0)
1360 {
06c3eeed
JB
1361 sound_warning ("The play mciSendString command failed to play the\n"
1362 "opened sound file.");
1363 i_result = (int) mci_error;
f60ae425
BK
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");
06c3eeed 1368 mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
f60ae425
BK
1369 if (b_reset_volume == TRUE)
1370 {
06c3eeed 1371 mm_result=waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org);
f60ae425
BK
1372 if (mm_result != MMSYSERR_NOERROR)
1373 {
06c3eeed
JB
1374 sound_warning ("waveOutSetVolume failed to reset the original volume\n"
1375 "level of the WAVE_MAPPER device.");
f60ae425
BK
1376 }
1377 }
1378 return i_result;
1379}
1380
1381/* END: Windows specific functions */
1382
1383#endif /* WINDOWSNT */
1384
f60ae425
BK
1385DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
1386 doc: /* Play sound SOUND.
1387
ed1f0a45 1388Internal use only, use `play-sound' instead. */)
f60ae425
BK
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;
f60ae425
BK
1398 Lisp_Object args[2];
1399#else /* WINDOWSNT */
06c3eeed
JB
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;
f60ae425
BK
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);
8e6ec322
RS
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));
f60ae425 1419 record_unwind_protect (sound_cleanup, Qnil);
8e6ec322 1420 current_sound->header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
f60ae425
BK
1421
1422 if (STRINGP (attrs[SOUND_FILE]))
1423 {
1424 /* Open the sound file. */
8e6ec322
RS
1425 current_sound->fd = openp (Fcons (Vdata_directory, Qnil),
1426 attrs[SOUND_FILE], Qnil, &file, Qnil);
1427 if (current_sound->fd < 0)
f60ae425
BK
1428 sound_perror ("Could not open sound file");
1429
1430 /* Read the first bytes from the file. */
8e6ec322
RS
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)
f60ae425
BK
1435 sound_perror ("Invalid sound file header");
1436 }
1437 else
1438 {
8e6ec322
RS
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);
f60ae425
BK
1442 }
1443
1444 /* Find out the type of sound. Give up if we can't tell. */
8e6ec322 1445 find_sound_type (current_sound);
f60ae425
BK
1446
1447 /* Set up a device. */
1448 if (STRINGP (attrs[SOUND_DEVICE]))
1449 {
1450 int len = SCHARS (attrs[SOUND_DEVICE]);
8e6ec322
RS
1451 current_sound_device->file = (char *) alloca (len + 1);
1452 strcpy (current_sound_device->file, SDATA (attrs[SOUND_DEVICE]));
f60ae425
BK
1453 }
1454
1455 if (INTEGERP (attrs[SOUND_VOLUME]))
8e6ec322 1456 current_sound_device->volume = XFASTINT (attrs[SOUND_VOLUME]);
f60ae425 1457 else if (FLOATP (attrs[SOUND_VOLUME]))
8e6ec322 1458 current_sound_device->volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
7840ced1 1459
f60ae425
BK
1460 args[0] = Qplay_sound_functions;
1461 args[1] = sound;
1462 Frun_hook_with_args (2, args);
1463
2d2643f6
JD
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");
f60ae425
BK
1469
1470 /* Open the device. */
8e6ec322 1471 current_sound_device->open (current_sound_device);
f60ae425
BK
1472
1473 /* Play the sound. */
8e6ec322 1474 current_sound->play (current_sound, current_sound_device);
f60ae425
BK
1475
1476 /* Clean up. */
f60ae425 1477 UNGCPRO;
06c3eeed 1478
f60ae425 1479#else /* WINDOWSNT */
06c3eeed
JB
1480
1481 lo_file = Fexpand_file_name (attrs[SOUND_FILE], Qnil);
1482 len = XSTRING (lo_file)->size;
1483 psz_file = (char *) alloca (len + 1);
f60ae425
BK
1484 strcpy (psz_file, XSTRING (lo_file)->data);
1485 if (INTEGERP (attrs[SOUND_VOLUME]))
1486 {
06c3eeed 1487 ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]);
f60ae425
BK
1488 }
1489 else if (FLOATP (attrs[SOUND_VOLUME]))
1490 {
06c3eeed 1491 ui_volume_tmp = (unsigned long) XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
f60ae425
BK
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
06c3eeed 1499 (and thus to waveOutSetVolume) must be some fraction of UINT_MAX.
f60ae425 1500 The following code adjusts the user specified volume level appropriately.
06c3eeed 1501 */
f60ae425
BK
1502 if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100))
1503 {
06c3eeed 1504 ui_volume = ui_volume_tmp * (UINT_MAX / 100);
f60ae425 1505 }
06c3eeed
JB
1506 i_result = do_play_sound (psz_file, ui_volume);
1507
f60ae425 1508#endif /* WINDOWSNT */
06c3eeed 1509
f60ae425
BK
1510 unbind_to (count, Qnil);
1511 return Qnil;
1512}
7840ced1
GM
1513\f
1514/***********************************************************************
1515 Initialization
1516 ***********************************************************************/
1517
1518void
1519syms_of_sound ()
1520{
1521 QCdevice = intern (":device");
1522 staticpro (&QCdevice);
1523 QCvolume = intern (":volume");
1524 staticpro (&QCvolume);
1525 Qsound = intern ("sound");
1526 staticpro (&Qsound);
2a53558d
GM
1527 Qplay_sound_functions = intern ("play-sound-functions");
1528 staticpro (&Qplay_sound_functions);
7840ced1 1529
14e415e7 1530 defsubr (&Splay_sound_internal);
7840ced1
GM
1531}
1532
1533
1534void
1535init_sound ()
1536{
1537}
1538
1539#endif /* HAVE_SOUND */
ab5796a9
MB
1540
1541/* arch-tag: dd850ad8-0433-4e2c-9cba-b7aeeccc0dbd
1542 (do not change this comment) */