Mercurial > hg > xemacs-beta
annotate src/sound.c @ 4522:fc7067b7f407
Backout last patch; forgot to specify file.
author | Stephen J. Turnbull <stephen@xemacs.org> |
---|---|
date | Wed, 29 Oct 2008 03:37:16 +0900 |
parents | fb73a2046d3e |
children | 19a72041c5ed |
rev | line source |
---|---|
428 | 1 /* Sound functions. |
2 Copyright (C) 1992, 1993, 1994 Lucid Inc. | |
3 Copyright (C) 1994, 1995 Free Software Foundation, Inc. | |
2526 | 4 Copyright (C) 2002, 2004 Ben Wing. |
428 | 5 |
6 This file is part of XEmacs. | |
7 | |
8 XEmacs is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: Not in FSF. */ | |
24 | |
563 | 25 /* This file Mule-ized by Ben Wing, 5-15-01. */ |
26 | |
428 | 27 /* Originally written by Jamie Zawinski. |
28 Hacked on quite a bit by various others. */ | |
29 | |
30 #include <config.h> | |
31 #include <time.h> | |
32 #include "lisp.h" | |
33 | |
34 #include "buffer.h" | |
35 #ifdef HAVE_X_WINDOWS | |
872 | 36 #include "console-x-impl.h" |
428 | 37 #endif |
872 | 38 #include "device-impl.h" |
428 | 39 #include "redisplay.h" |
563 | 40 #include "sound.h" |
41 | |
428 | 42 #include "sysdep.h" |
43 | |
442 | 44 #include "sysfile.h" |
428 | 45 |
46 #ifdef HAVE_NATIVE_SOUND | |
442 | 47 # include "sysproc.h" |
428 | 48 #endif |
49 | |
872 | 50 #ifdef WIN32_NATIVE |
51 #include "syswindows.h" | |
52 #endif | |
53 | |
3072 | 54 #ifdef HAVE_NAS_SOUND |
55 #define USED_IF_HAVE_NAS(decl) decl | |
56 #else | |
57 #define USED_IF_HAVE_NAS(decl) UNUSED (decl) | |
58 #endif | |
59 | |
60 #if defined(HAVE_NATIVE_SOUND) || defined(HAVE_NAS_SOUND) | |
61 #define USED_IF_HAVE_NATIVE_OR_NAS(decl) decl | |
62 #else | |
63 #define USED_IF_HAVE_NATIVE_OR_NAS(decl) UNUSED (decl) | |
64 #endif | |
65 | |
66 #if defined(HAVE_NATIVE_SOUND) || defined(HAVE_NAS_SOUND) \ | |
4343
fb73a2046d3e
Fix unused parameter warnings when compiling with ALSA sound support.
Jerry James <james@xemacs.org>
parents:
3731
diff
changeset
|
67 || defined(HAVE_ALSA_SOUND) || defined(HAVE_ESD_SOUND) |
3072 | 68 #define USED_IF_HAVE_ANY(decl) decl |
69 #else | |
70 #define USED_IF_HAVE_ANY(decl) UNUSED (decl) | |
71 #endif | |
72 | |
3308 | 73 #ifdef HAVE_ALSA_SOUND |
74 extern int alsa_play_sound_file (const Extbyte *file, int vol); | |
75 extern int alsa_play_sound_data (const Binbyte *data, int length, int vol); | |
76 # define DEVICE_CONNECTED_TO_ALSA_P(x) 1 /* #### better check */ | |
77 #endif | |
78 | |
428 | 79 #ifdef HAVE_ESD_SOUND |
563 | 80 extern int esd_play_sound_file (Extbyte *file, int vol); |
2367 | 81 extern int esd_play_sound_data (Binbyte *data, size_t length, int vol); |
563 | 82 # define DEVICE_CONNECTED_TO_ESD_P(x) 1 /* #### better check */ |
428 | 83 #endif |
84 | |
3308 | 85 #ifdef HAVE_NAS_SOUND |
86 extern int nas_play_sound_file (Extbyte *name, int volume); | |
87 extern int nas_play_sound_data (Binbyte *data, int length, int volume); | |
88 extern int nas_wait_for_sounds (void); | |
89 extern Extbyte *nas_init_play (Display *); | |
90 #endif | |
91 | |
458 | 92 Fixnum bell_volume; |
93 Fixnum bell_inhibit_time; | |
428 | 94 Lisp_Object Vsound_alist; |
95 Lisp_Object Vsynchronous_sounds; | |
96 Lisp_Object Vnative_sound_only_on_console; | |
97 Lisp_Object Q_volume, Q_pitch, Q_duration, Q_sound; | |
563 | 98 Lisp_Object Qsound_error; |
428 | 99 |
563 | 100 DOESNT_RETURN |
2367 | 101 report_sound_error (const Ascbyte *string, Lisp_Object data) |
563 | 102 { |
103 report_error_with_errno (Qsound_error, string, data); | |
104 } | |
428 | 105 |
106 DEFUN ("play-sound-file", Fplay_sound_file, 1, 3, "fSound file name: ", /* | |
107 Play the named sound file on DEVICE's speaker at the specified volume | |
108 \(0-100, default specified by the `bell-volume' variable). | |
109 On Unix machines the sound file must be in the Sun/NeXT U-LAW format | |
110 except under Linux where WAV files are also supported. On Microsoft | |
111 Windows the sound file must be in WAV format. | |
112 DEVICE defaults to the selected device. | |
113 */ | |
3072 | 114 (file, volume, USED_IF_HAVE_ANY (device))) |
428 | 115 { |
116 /* This function can call lisp */ | |
117 int vol; | |
3308 | 118 #if defined (HAVE_NATIVE_SOUND) || defined (HAVE_ALSA_SOUND) || \ |
119 defined (HAVE_NAS_SOUND) || defined (HAVE_ESD_SOUND) | |
428 | 120 struct device *d = decode_device (device); |
121 #endif | |
122 struct gcpro gcpro1; | |
123 | |
124 CHECK_STRING (file); | |
125 if (NILP (volume)) | |
126 vol = bell_volume; | |
127 else | |
128 { | |
129 CHECK_INT (volume); | |
130 vol = XINT (volume); | |
131 } | |
132 | |
133 GCPRO1 (file); | |
134 while (1) | |
135 { | |
136 file = Fexpand_file_name (file, Qnil); | |
137 if (!NILP(Ffile_readable_p (file))) | |
138 break; | |
139 else | |
140 { | |
141 /* #### This is crockish. It might be a better idea to try | |
142 to open the file, and use report_file_error() if it | |
143 fails. --hniksic */ | |
144 if (NILP (Ffile_exists_p (file))) | |
145 file = | |
563 | 146 signal_continuable_error (Qfile_error, |
147 "File does not exist", file); | |
428 | 148 else |
149 file = | |
563 | 150 signal_continuable_error (Qfile_error, |
151 "File is unreadable", file); | |
428 | 152 } |
153 } | |
154 UNGCPRO; | |
155 | |
3308 | 156 #ifdef HAVE_ALSA_SOUND |
157 if (DEVICE_CONNECTED_TO_ALSA_P (d)) | |
158 { | |
159 Extbyte *fileext; | |
160 | |
161 LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); | |
162 /* #### ALSA code should allow specification of a device. */ | |
163 if (alsa_play_sound_file (fileext, vol)) | |
164 return Qnil; | |
165 } | |
166 #endif | |
167 | |
428 | 168 #ifdef HAVE_NAS_SOUND |
169 if (DEVICE_CONNECTED_TO_NAS_P (d)) | |
170 { | |
563 | 171 Extbyte *fileext; |
428 | 172 |
442 | 173 LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); |
428 | 174 /* #### NAS code should allow specification of a device. */ |
175 if (nas_play_sound_file (fileext, vol)) | |
176 return Qnil; | |
177 } | |
178 #endif /* HAVE_NAS_SOUND */ | |
179 | |
180 #ifdef HAVE_ESD_SOUND | |
181 if (DEVICE_CONNECTED_TO_ESD_P (d)) | |
182 { | |
563 | 183 Extbyte *fileext; |
442 | 184 int result; |
428 | 185 |
442 | 186 LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); |
187 | |
188 /* #### ESD uses alarm(). But why should we also stop SIGIO? */ | |
189 stop_interrupts (); | |
190 result = esd_play_sound_file (fileext, vol); | |
191 start_interrupts (); | |
192 if (result) | |
428 | 193 return Qnil; |
194 } | |
195 #endif /* HAVE_ESD_SOUND */ | |
196 | |
197 #ifdef HAVE_NATIVE_SOUND | |
198 if (NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) | |
199 { | |
2526 | 200 #ifdef WIN32_ANY |
201 nt_play_sound_file (file, vol); | |
202 #else | |
563 | 203 Extbyte *fileext; |
2526 | 204 LISP_PATHNAME_CONVERT_OUT (file, fileext); |
428 | 205 /* The sound code doesn't like getting SIGIO interrupts. |
206 Unix sucks! */ | |
207 stop_interrupts (); | |
563 | 208 play_sound_file (fileext, vol); |
428 | 209 start_interrupts (); |
2526 | 210 #endif /* WIN32_NATIVE */ |
428 | 211 QUIT; |
212 } | |
213 #endif /* HAVE_NATIVE_SOUND */ | |
214 | |
215 return Qnil; | |
216 } | |
217 | |
218 static void | |
219 parse_sound_alist_elt (Lisp_Object elt, | |
220 Lisp_Object *volume, | |
221 Lisp_Object *pitch, | |
222 Lisp_Object *duration, | |
223 Lisp_Object *sound) | |
224 { | |
225 *volume = Qnil; | |
226 *pitch = Qnil; | |
227 *duration = Qnil; | |
228 *sound = Qnil; | |
229 if (! CONSP (elt)) | |
230 return; | |
231 | |
232 /* The things we do for backward compatibility... | |
233 I wish I had just forced this to be a plist to begin with. | |
234 */ | |
235 | |
236 if (SYMBOLP (elt) || STRINGP (elt)) /* ( name . <sound> ) */ | |
237 { | |
238 *sound = elt; | |
239 } | |
240 else if (!CONSP (elt)) | |
241 { | |
242 return; | |
243 } | |
244 else if (NILP (XCDR (elt)) && /* ( name <sound> ) */ | |
245 (SYMBOLP (XCAR (elt)) || | |
246 STRINGP (XCAR (elt)))) | |
247 { | |
248 *sound = XCAR (elt); | |
249 } | |
250 else if (INT_OR_FLOATP (XCAR (elt)) && /* ( name <vol> . <sound> ) */ | |
251 (SYMBOLP (XCDR (elt)) || | |
252 STRINGP (XCDR (elt)))) | |
253 { | |
254 *volume = XCAR (elt); | |
255 *sound = XCDR (elt); | |
256 } | |
257 else if (INT_OR_FLOATP (XCAR (elt)) && /* ( name <vol> <sound> ) */ | |
258 CONSP (XCDR (elt)) && | |
259 NILP (XCDR (XCDR (elt))) && | |
260 (SYMBOLP (XCAR (XCDR (elt))) || | |
261 STRINGP (XCAR (XCDR (elt))))) | |
262 { | |
263 *volume = XCAR (elt); | |
264 *sound = XCAR (XCDR (elt)); | |
265 } | |
266 else if ((SYMBOLP (XCAR (elt)) || /* ( name <sound> . <vol> ) */ | |
267 STRINGP (XCAR (elt))) && | |
268 INT_OR_FLOATP (XCDR (elt))) | |
269 { | |
270 *sound = XCAR (elt); | |
271 *volume = XCDR (elt); | |
272 } | |
273 #if 0 /* this one is ambiguous with the plist form */ | |
274 else if ((SYMBOLP (XCAR (elt)) || /* ( name <sound> <vol> ) */ | |
275 STRINGP (XCAR (elt))) && | |
276 CONSP (XCDR (elt)) && | |
277 NILP (XCDR (XCDR (elt))) && | |
278 INT_OR_FLOATP (XCAR (XCDR (elt)))) | |
279 { | |
280 *sound = XCAR (elt); | |
281 *volume = XCAR (XCDR (elt)); | |
282 } | |
283 #endif /* 0 */ | |
284 else /* ( name [ keyword <value> ]* ) */ | |
285 { | |
286 while (CONSP (elt)) | |
287 { | |
288 Lisp_Object key, val; | |
289 key = XCAR (elt); | |
290 val = XCDR (elt); | |
291 if (!CONSP (val)) | |
292 return; | |
293 elt = XCDR (val); | |
294 val = XCAR (val); | |
295 if (EQ (key, Q_volume)) | |
296 { | |
297 if (INT_OR_FLOATP (val)) *volume = val; | |
298 } | |
299 else if (EQ (key, Q_pitch)) | |
300 { | |
301 if (INT_OR_FLOATP (val)) *pitch = val; | |
302 if (NILP (*sound)) *sound = Qt; | |
303 } | |
304 else if (EQ (key, Q_duration)) | |
305 { | |
306 if (INT_OR_FLOATP (val)) *duration = val; | |
307 if (NILP (*sound)) *sound = Qt; | |
308 } | |
309 else if (EQ (key, Q_sound)) | |
310 { | |
311 if (SYMBOLP (val) || STRINGP (val)) *sound = val; | |
312 } | |
313 } | |
314 } | |
315 } | |
316 | |
317 DEFUN ("play-sound", Fplay_sound, 1, 3, 0, /* | |
318 Play a sound of the provided type. | |
793 | 319 |
320 SOUND can a symbol, specifying a sound to be looked up in `sound-alist' | |
321 \(generally, either the symbol directly maps to a sound or is an "abstract" | |
322 symbol that maps to another symbol and is used to specify the sound that is | |
323 played when a particular behavior occurs. `ding' lists the built-in | |
324 abstract sounds and their intended purpose. | |
325 | |
326 SOUND can also be a string, which directly encodes the sound data to be played. | |
327 | |
328 If SOUND is nil, the abstract sound `default' will be used. | |
329 | |
330 VOLUME controls the volume (max is around 150? not sure). | |
331 | |
332 DEVICE is the device to play the sound on (defaults to the selected device). | |
609 | 333 |
334 If the sound cannot be played in any other way, the standard "bell" will sound. | |
428 | 335 */ |
336 (sound, volume, device)) | |
337 { | |
338 int looking_for_default = 0; | |
339 /* variable `sound' is anything that can be a cdr in sound-alist */ | |
340 Lisp_Object new_volume, pitch, duration, data; | |
341 int loop_count = 0; | |
342 int vol, pit, dur; | |
343 struct device *d = decode_device (device); | |
344 | |
345 /* NOTE! You'd better not signal an error in here. */ | |
346 | |
347 | |
348 try_it_again: | |
349 while (1) | |
350 { | |
351 if (SYMBOLP (sound)) | |
352 sound = Fcdr (Fassq (sound, Vsound_alist)); | |
353 parse_sound_alist_elt (sound, &new_volume, &pitch, &duration, &data); | |
354 sound = data; | |
355 if (NILP (volume)) volume = new_volume; | |
356 if (EQ (sound, Qt) || EQ (sound, Qnil) || STRINGP (sound)) | |
357 break; | |
358 if (loop_count++ > 500) /* much bogosity has occurred */ | |
359 break; | |
360 } | |
361 | |
362 if (NILP (sound) && !looking_for_default) | |
363 { | |
364 looking_for_default = 1; | |
365 loop_count = 0; | |
366 sound = Qdefault; | |
367 goto try_it_again; | |
368 } | |
369 | |
370 | |
371 vol = (INT_OR_FLOATP (volume) ? (int) XFLOATINT (volume) : bell_volume); | |
372 pit = (INT_OR_FLOATP (pitch) ? (int) XFLOATINT (pitch) : -1); | |
373 dur = (INT_OR_FLOATP (duration) ? (int) XFLOATINT (duration) : -1); | |
374 | |
3308 | 375 /* If the sound is a string, and we're connected to ALSA, NAS, or ESD, do |
376 that. Else if the sound is a string, and we're on console, play it | |
377 natively. Else just beep. | |
428 | 378 */ |
3308 | 379 #ifdef HAVE_ALSA_SOUND |
380 if (DEVICE_CONNECTED_TO_ALSA_P (d) && STRINGP (sound)) | |
381 { | |
382 Binbyte *soundext; | |
383 Bytecount soundextlen; | |
384 | |
385 TO_EXTERNAL_FORMAT (LISP_STRING, sound, | |
386 ALLOCA, (soundext, soundextlen), | |
387 Qbinary); | |
388 if (alsa_play_sound_data (soundext, soundextlen, vol)) | |
389 return Qnil; | |
390 } | |
391 #endif /* HAVE_ALSA_SOUND */ | |
392 | |
428 | 393 #ifdef HAVE_NAS_SOUND |
394 if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound)) | |
395 { | |
2367 | 396 Binbyte *soundext; |
665 | 397 Bytecount soundextlen; |
428 | 398 |
440 | 399 TO_EXTERNAL_FORMAT (LISP_STRING, sound, |
400 ALLOCA, (soundext, soundextlen), | |
401 Qbinary); | |
563 | 402 if (nas_play_sound_data (soundext, soundextlen, vol)) |
428 | 403 return Qnil; |
404 } | |
405 #endif /* HAVE_NAS_SOUND */ | |
406 | |
407 #ifdef HAVE_ESD_SOUND | |
408 if (DEVICE_CONNECTED_TO_ESD_P (d) && STRINGP (sound)) | |
409 { | |
2367 | 410 Binbyte *soundext; |
665 | 411 Bytecount soundextlen; |
442 | 412 int succes; |
428 | 413 |
440 | 414 TO_EXTERNAL_FORMAT (LISP_STRING, sound, ALLOCA, (soundext, soundextlen), |
415 Qbinary); | |
442 | 416 |
417 /* #### ESD uses alarm(). But why should we also stop SIGIO? */ | |
418 stop_interrupts (); | |
563 | 419 succes = esd_play_sound_data (soundext, soundextlen, vol); |
442 | 420 start_interrupts (); |
421 QUIT; | |
422 if(succes) | |
423 return Qnil; | |
428 | 424 } |
425 #endif /* HAVE_ESD_SOUND */ | |
426 | |
427 #ifdef HAVE_NATIVE_SOUND | |
428 if ((NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) | |
429 && STRINGP (sound)) | |
430 { | |
2367 | 431 Binbyte *soundext; |
665 | 432 Bytecount soundextlen; |
442 | 433 int succes; |
428 | 434 |
440 | 435 TO_EXTERNAL_FORMAT (LISP_STRING, sound, |
436 ALLOCA, (soundext, soundextlen), | |
437 Qbinary); | |
428 | 438 /* The sound code doesn't like getting SIGIO interrupts. Unix sucks! */ |
439 stop_interrupts (); | |
563 | 440 succes = play_sound_data (soundext, soundextlen, vol); |
428 | 441 start_interrupts (); |
442 QUIT; | |
442 | 443 if (succes) |
444 return Qnil; | |
428 | 445 } |
446 #endif /* HAVE_NATIVE_SOUND */ | |
447 | |
448 DEVMETH (d, ring_bell, (d, vol, pit, dur)); | |
449 return Qnil; | |
450 } | |
451 | |
452 DEFUN ("device-sound-enabled-p", Fdevice_sound_enabled_p, 0, 1, 0, /* | |
453 Return t if DEVICE is able to play sound. Defaults to selected device. | |
454 */ | |
3072 | 455 (USED_IF_HAVE_NATIVE_OR_NAS (device))) |
428 | 456 { |
3308 | 457 #ifdef HAVE_ALSA_SOUND |
458 if (DEVICE_CONNECTED_TO_ALSA_P (decode_device (device))) | |
459 return Qt; | |
460 #endif | |
428 | 461 #ifdef HAVE_NAS_SOUND |
462 if (DEVICE_CONNECTED_TO_NAS_P (decode_device (device))) | |
463 return Qt; | |
464 #endif | |
465 #ifdef HAVE_NATIVE_SOUND | |
466 if (DEVICE_ON_CONSOLE_P (decode_device (device))) | |
467 return Qt; | |
468 #endif | |
469 return Qnil; | |
470 } | |
471 | |
472 DEFUN ("ding", Fding, 0, 3, 0, /* | |
473 Beep, or flash the frame. | |
793 | 474 |
475 \(See `visible-bell'; setting this makes the frame flash instead of | |
476 beeping.) Also, unless NO-TERMINATE is given, terminate any keyboard macro | |
477 currently executing. SOUND specifies the sound to make and DEVICE the | |
478 device to make it on (defaults to the selected device). | |
479 | |
480 SOUND is either a string (raw data to be played directly), a symbol, or | |
481 `nil' (equivalent to the symbol `default'). Sound symbols are looked up in | |
482 `sound-alist', and resolve either to strings of data or to other symbols. | |
483 Sound symbols that map directly to data should be considered named sounds; | |
484 sound symbols that map to other sounds should be considered abstract | |
485 sounds, and are used when a particular behavior or state occurs. | |
486 | |
2757 | 487 Remember that the sound symbol is the *second* argument to `ding', not the |
793 | 488 first. |
489 | |
490 The following abstract sounds are used by XEmacs itself: | |
491 | |
492 alarm when a package wants to remind the user | |
493 auto-save-error when an auto-save does not succeed | |
494 buffer-bound when you attempt to move off the end of a buffer | |
495 command-error any uncaught error (i.e. any error that the user | |
496 sees) except those handled by undefined-click, | |
497 undefined-key, buffer-bound, or read-only | |
498 default used when nothing else is appropriate. | |
499 isearch-failed unable to locate search text during incremental search | |
500 isearch-quit when you delete chars past the beginning of the search | |
501 text in isearch | |
502 no-completion during completing-read | |
503 quit when C-g is typed | |
504 read-only when you try to modify a read-only buffer | |
505 ready when a compile or other time-consuming task is done | |
506 undefined-click when you use an undefined mouse-click combination | |
507 undefined-key when you type a key that is undefined | |
508 warp XEmacs has changed the selected-window or frame | |
509 asynchronously -- e.g. a debugger breakpoint is hit | |
510 in an asynchronous process filter | |
511 y-or-n-p when you type something other than 'y' or 'n' | |
512 yes-or-no-p when you type something other than 'yes' or 'no' | |
513 | |
514 Other lisp packages may use other beep types, but these are the ones that | |
515 the C kernel of Emacs uses. | |
516 | |
428 | 517 */ |
793 | 518 (no_terminate, sound, device)) |
428 | 519 { |
430 | 520 static time_t last_bell_time; |
521 static struct device *last_bell_device; | |
428 | 522 time_t now; |
523 struct device *d = decode_device (device); | |
524 | |
793 | 525 device = wrap_device (d); |
428 | 526 now = time (0); |
527 | |
793 | 528 if (NILP (no_terminate) && !NILP (Vexecuting_macro)) |
428 | 529 /* Stop executing a keyboard macro. */ |
563 | 530 invalid_operation ("Keyboard macro terminated by a command ringing the bell", Qunbound); |
428 | 531 |
532 if (d == last_bell_device && now-last_bell_time < bell_inhibit_time) | |
533 return Qnil; | |
442 | 534 else if (!NILP (Vvisible_bell) && DEVMETH (d, flash, (d))) |
428 | 535 ; |
536 else | |
537 Fplay_sound (sound, Qnil, device); | |
538 | |
539 last_bell_time = now; | |
540 last_bell_device = d; | |
541 return Qnil; | |
542 } | |
543 | |
544 DEFUN ("wait-for-sounds", Fwait_for_sounds, 0, 1, 0, /* | |
545 Wait for all sounds to finish playing on DEVICE. | |
546 */ | |
2294 | 547 (USED_IF_HAVE_NAS (device))) |
428 | 548 { |
549 #ifdef HAVE_NAS_SOUND | |
550 struct device *d = decode_device (device); | |
551 if (DEVICE_CONNECTED_TO_NAS_P (d)) | |
552 { | |
553 /* #### somebody fix this to be device-dependent. */ | |
554 nas_wait_for_sounds (); | |
555 } | |
556 #endif | |
557 return Qnil; | |
558 } | |
559 | |
560 DEFUN ("connected-to-nas-p", Fconnected_to_nas_p, 0, 1, 0, /* | |
561 Return t if connected to NAS server for sounds on DEVICE. | |
562 */ | |
2294 | 563 (USED_IF_HAVE_NAS (device))) |
428 | 564 { |
565 #ifdef HAVE_NAS_SOUND | |
566 return DEVICE_CONNECTED_TO_NAS_P (decode_device (device)) ? Qt : Qnil; | |
567 #else | |
568 return Qnil; | |
569 #endif | |
570 } | |
571 #ifdef HAVE_NAS_SOUND | |
572 | |
573 static void | |
574 init_nas_sound (struct device *d) | |
575 { | |
576 #ifdef HAVE_X_WINDOWS | |
577 if (DEVICE_X_P (d)) | |
578 { | |
563 | 579 Extbyte *err_message = nas_init_play (DEVICE_X_DISPLAY (d)); |
442 | 580 DEVICE_CONNECTED_TO_NAS_P (d) = !err_message; |
428 | 581 /* Print out the message? */ |
582 } | |
583 #endif /* HAVE_X_WINDOWS */ | |
584 } | |
585 | |
586 #endif /* HAVE_NAS_SOUND */ | |
587 | |
588 #ifdef HAVE_NATIVE_SOUND | |
589 | |
590 static void | |
591 init_native_sound (struct device *d) | |
592 { | |
3731 | 593 if (!(DEVICE_X_P(d) || DEVICE_GTK_P(d))) |
428 | 594 DEVICE_ON_CONSOLE_P (d) = 1; |
595 #ifdef HAVE_X_WINDOWS | |
596 else | |
597 { | |
598 /* When running on a machine with native sound support, we cannot use | |
599 digitized sounds as beeps unless emacs is running on the same machine | |
600 that $DISPLAY points to, and $DISPLAY points to frame 0 of that | |
601 machine. | |
602 */ | |
603 | |
604 Display *display = DEVICE_X_DISPLAY (d); | |
563 | 605 Extbyte *dpy = DisplayString (display); |
606 Extbyte *tail = strchr (dpy, ':'); | |
428 | 607 if (! tail || |
608 strncmp (tail, ":0", 2)) | |
609 DEVICE_ON_CONSOLE_P (d) = 0; | |
610 else | |
611 { | |
563 | 612 Extbyte dpyname[255], localname[255]; |
428 | 613 |
614 /* some systems can't handle SIGIO or SIGALARM in gethostbyname. */ | |
615 stop_interrupts (); | |
616 strncpy (dpyname, dpy, tail-dpy); | |
617 dpyname [tail-dpy] = 0; | |
618 if (!*dpyname || | |
619 !strcmp (dpyname, "unix") || | |
620 !strcmp (dpyname, "localhost")) | |
621 DEVICE_ON_CONSOLE_P (d) = 1; | |
622 else if (gethostname (localname, sizeof (localname))) | |
623 DEVICE_ON_CONSOLE_P (d) = 0; /* can't find hostname? */ | |
624 else | |
625 { | |
626 /* We have to call gethostbyname() on the result of gethostname() | |
627 because the two aren't guaranteed to be the same name for the | |
628 same host: on some losing systems, one is a FQDN and the other | |
629 is not. Here in the wide wonderful world of Unix it's rocket | |
630 science to obtain the local hostname in a portable fashion. | |
631 | |
632 And don't forget, gethostbyname() reuses the structure it | |
633 returns, so we have to copy the fucker before calling it | |
634 again. | |
635 | |
636 Thank you master, may I have another. | |
637 */ | |
638 struct hostent *h = gethostbyname (dpyname); | |
639 if (!h) | |
640 DEVICE_ON_CONSOLE_P (d) = 0; | |
641 else | |
642 { | |
3504 | 643 Extbyte *hn = alloca_array (Extbyte, strlen (h->h_name) + 1); |
428 | 644 struct hostent *l; |
645 strcpy (hn, h->h_name); | |
646 l = gethostbyname (localname); | |
647 DEVICE_ON_CONSOLE_P (d) = (l && !(strcmp (l->h_name, hn))); | |
648 } | |
649 } | |
650 start_interrupts (); | |
651 } | |
652 } | |
653 #endif /* HAVE_X_WINDOWS */ | |
654 } | |
655 | |
656 #endif /* HAVE_NATIVE_SOUND */ | |
657 | |
658 void | |
3072 | 659 init_device_sound (struct device * USED_IF_HAVE_NATIVE_OR_NAS (d)) |
428 | 660 { |
661 #ifdef HAVE_NAS_SOUND | |
662 init_nas_sound (d); | |
663 #endif | |
664 | |
665 #ifdef HAVE_NATIVE_SOUND | |
666 init_native_sound (d); | |
667 #endif | |
668 } | |
669 | |
670 void | |
671 syms_of_sound (void) | |
672 { | |
563 | 673 DEFKEYWORD (Q_volume); |
674 DEFKEYWORD (Q_pitch); | |
675 DEFKEYWORD (Q_duration); | |
676 DEFKEYWORD (Q_sound); | |
428 | 677 |
563 | 678 DEFERROR_STANDARD (Qsound_error, Qio_error); |
428 | 679 |
680 DEFSUBR (Fplay_sound_file); | |
681 DEFSUBR (Fplay_sound); | |
682 DEFSUBR (Fding); | |
683 DEFSUBR (Fwait_for_sounds); | |
684 DEFSUBR (Fconnected_to_nas_p); | |
685 DEFSUBR (Fdevice_sound_enabled_p); | |
686 } | |
687 | |
688 | |
689 void | |
690 vars_of_sound (void) | |
691 { | |
3308 | 692 #ifdef HAVE_ALSA_SOUND |
693 Fprovide (intern ("alsa-sound")); | |
694 #endif | |
428 | 695 #ifdef HAVE_NATIVE_SOUND |
696 Fprovide (intern ("native-sound")); | |
697 #endif | |
698 #ifdef HAVE_NAS_SOUND | |
699 Fprovide (intern ("nas-sound")); | |
700 #endif | |
432 | 701 #ifdef HAVE_ESD_SOUND |
702 Fprovide (intern ("esd-sound")); | |
703 #endif | |
428 | 704 |
705 DEFVAR_INT ("bell-volume", &bell_volume /* | |
706 *How loud to be, from 0 to 100. | |
707 */ ); | |
708 bell_volume = 50; | |
709 | |
710 DEFVAR_INT ("bell-inhibit-time", &bell_inhibit_time /* | |
711 *Don't ring the bell on the same device more than once within this many seconds. | |
712 */ ); | |
713 bell_inhibit_time = 0; | |
714 | |
715 DEFVAR_LISP ("sound-alist", &Vsound_alist /* | |
716 An alist associating names with sounds. | |
717 When `beep' or `ding' is called with one of the name symbols, the associated | |
718 sound will be generated instead of the standard beep. | |
719 | |
720 Each element of `sound-alist' is a list describing a sound. | |
721 The first element of the list is the name of the sound being defined. | |
722 Subsequent elements of the list are alternating keyword/value pairs: | |
723 | |
724 Keyword: Value: | |
725 ------- ----- | |
726 sound A string of raw sound data, or the name of another sound to | |
727 play. The symbol `t' here means use the default X beep. | |
728 volume An integer from 0-100, defaulting to `bell-volume' | |
729 pitch If using the default X beep, the pitch (Hz) to generate. | |
730 duration If using the default X beep, the duration (milliseconds). | |
731 | |
732 For compatibility, elements of `sound-alist' may also be: | |
733 | |
734 ( sound-name . <sound> ) | |
735 ( sound-name <volume> <sound> ) | |
736 | |
737 You should probably add things to this list by calling the function | |
738 load-sound-file. | |
739 | |
740 Caveats: | |
741 - XEmacs must be built with sound support for your system. Not all | |
742 systems support sound. | |
743 | |
744 - The pitch, duration, and volume options are available everywhere, but | |
745 many X servers ignore the `pitch' option. | |
746 | |
793 | 747 Sound symbols that map directly to data should be considered named sounds; |
748 sound symbols that map to other sounds should be considered abstract | |
749 sounds, and are used when a particular behavior or state occurs. See | |
750 `ding' for a list of the standard abstract sounds. | |
428 | 751 */ ); |
752 Vsound_alist = Qnil; | |
753 | |
754 DEFVAR_LISP ("synchronous-sounds", &Vsynchronous_sounds /* | |
755 Play sounds synchronously, if non-nil. | |
756 Only applies if NAS is used and supports asynchronous playing | |
757 of sounds. Otherwise, sounds are always played synchronously. | |
758 */ ); | |
759 Vsynchronous_sounds = Qnil; | |
760 | |
761 DEFVAR_LISP ("native-sound-only-on-console", &Vnative_sound_only_on_console /* | |
762 Non-nil value means play sounds only if XEmacs is running | |
763 on the system console. | |
442 | 764 Nil means always play sounds, even if running on a non-console tty |
428 | 765 or a secondary X display. |
766 | |
767 This variable only applies to native sound support. | |
768 */ ); | |
769 Vnative_sound_only_on_console = Qt; | |
770 | |
771 #if defined (HAVE_NATIVE_SOUND) && defined (hp9000s800) | |
772 { | |
773 void vars_of_hpplay (void); | |
774 vars_of_hpplay (); | |
775 } | |
776 #endif | |
777 } |