Mercurial > hg > xemacs-beta
annotate src/sound.c @ 5090:0ca81354c4c7
Further frame-geometry cleanups
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-03 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Intro to Window and Frame Geometry):
* internals/internals.texi (The Paned Area):
* internals/internals.texi (The Displayable Area):
Update to make note of e.g. the fact that the bottom gutter is
actually above the minibuffer.
src/ChangeLog addition:
2010-03-03 Ben Wing <ben@xemacs.org>
* emacs.c:
* emacs.c (assert_equal_failed):
* lisp.h:
* lisp.h (assert_equal):
New fun assert_equal, asserting that two values == each other, and
printing out both values upon failure.
* frame-gtk.c (gtk_initialize_frame_size):
* frame-impl.h:
* frame-impl.h (FRAME_TOP_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_BOTTOM_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_LEFT_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_PANED_TOP_EDGE):
* frame-impl.h (FRAME_NONPANED_SIZE):
* frame-x.c (x_initialize_frame_size):
* frame.c:
* gutter.c (get_gutter_coords):
* gutter.c (calculate_gutter_size):
* gutter.h:
* gutter.h (WINDOW_REAL_TOP_GUTTER_BOUNDS):
* gutter.h (FRAME_TOP_GUTTER_BOUNDS):
* input-method-xlib.c:
* input-method-xlib.c (XIM_SetGeometry):
* redisplay-output.c (clear_left_border):
* redisplay-output.c (clear_right_border):
* redisplay-output.c (redisplay_output_pixmap):
* redisplay-output.c (redisplay_clear_region):
* redisplay-output.c (redisplay_clear_top_of_window):
* redisplay-output.c (redisplay_clear_to_window_end):
* redisplay-xlike-inc.c (XLIKE_clear_frame):
* redisplay.c:
* redisplay.c (UPDATE_CACHE_RETURN):
* redisplay.c (pixel_to_glyph_translation):
* toolbar.c (update_frame_toolbars_geometry):
* window.c (Fwindow_pixel_edges):
Get rid of some redundant macros. Consistently use the
FRAME_TOP_*_START, FRAME_RIGHT_*_END, etc. format. Rename
FRAME_*_BORDER_* to FRAME_*_INTERNAL_BORDER_*. Comment out
FRAME_BOTTOM_* for gutters and the paned area due to the
uncertainty over where the paned area actually begins. (Eventually
we should probably move the gutters outside the minibuffer so that
the paned area is contiguous.) Use FRAME_PANED_* more often in the
code to make things clearer.
Update the diagram to show that the bottom gutter is inside the
minibuffer (!) and that there are "junk boxes" when you have left
and/or right gutters (dead boxes that are mistakenly left uncleared,
unlike the corresponding scrollbar dead boxes). Update the text
appropriately to cover the bottom gutter position, etc.
Rewrite gutter-geometry code to use the FRAME_*_GUTTER_* in place of
equivalent expressions referencing other frame elements, to make the
code more portable in case we move around the gutter location.
Cleanup FRAME_*_GUTTER_BOUNDS() in gutter.h.
Add some #### GEOM! comments where I think code is incorrect --
typically, it wasn't fixed up properly when the gutter was added.
Some cosmetic changes.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 03 Mar 2010 05:07:47 -0600 |
parents | 4aebb0131297 |
children | 308d34e9f07d |
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 |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4343
diff
changeset
|
101 report_sound_error (const Ascbyte *reason, Lisp_Object data) |
563 | 102 { |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4343
diff
changeset
|
103 report_error_with_errno (Qsound_error, reason, data); |
563 | 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 | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
161 LISP_PATHNAME_CONVERT_OUT (file, fileext); |
3308 | 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 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
173 LISP_PATHNAME_CONVERT_OUT (file, fileext); |
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 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
186 LISP_PATHNAME_CONVERT_OUT (file, fileext); |
442 | 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 | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
385 LISP_STRING_TO_SIZED_EXTERNAL (sound, soundext, soundextlen, Qbinary); |
3308 | 386 if (alsa_play_sound_data (soundext, soundextlen, vol)) |
387 return Qnil; | |
388 } | |
389 #endif /* HAVE_ALSA_SOUND */ | |
390 | |
428 | 391 #ifdef HAVE_NAS_SOUND |
392 if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound)) | |
393 { | |
2367 | 394 Binbyte *soundext; |
665 | 395 Bytecount soundextlen; |
428 | 396 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
397 LISP_STRING_TO_SIZED_EXTERNAL (sound, soundext, soundextlen, Qbinary); |
563 | 398 if (nas_play_sound_data (soundext, soundextlen, vol)) |
428 | 399 return Qnil; |
400 } | |
401 #endif /* HAVE_NAS_SOUND */ | |
402 | |
403 #ifdef HAVE_ESD_SOUND | |
404 if (DEVICE_CONNECTED_TO_ESD_P (d) && STRINGP (sound)) | |
405 { | |
2367 | 406 Binbyte *soundext; |
665 | 407 Bytecount soundextlen; |
442 | 408 int succes; |
428 | 409 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
410 LISP_STRING_TO_SIZED_EXTERNAL (sound, soundext, soundextlen, Qbinary); |
442 | 411 |
412 /* #### ESD uses alarm(). But why should we also stop SIGIO? */ | |
413 stop_interrupts (); | |
563 | 414 succes = esd_play_sound_data (soundext, soundextlen, vol); |
442 | 415 start_interrupts (); |
416 QUIT; | |
417 if(succes) | |
418 return Qnil; | |
428 | 419 } |
420 #endif /* HAVE_ESD_SOUND */ | |
421 | |
422 #ifdef HAVE_NATIVE_SOUND | |
423 if ((NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) | |
424 && STRINGP (sound)) | |
425 { | |
2367 | 426 Binbyte *soundext; |
665 | 427 Bytecount soundextlen; |
442 | 428 int succes; |
428 | 429 |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
430 LISP_STRING_TO_SIZED_EXTERNAL (sound, soundext, soundextlen, Qbinary); |
428 | 431 /* The sound code doesn't like getting SIGIO interrupts. Unix sucks! */ |
432 stop_interrupts (); | |
563 | 433 succes = play_sound_data (soundext, soundextlen, vol); |
428 | 434 start_interrupts (); |
435 QUIT; | |
442 | 436 if (succes) |
437 return Qnil; | |
428 | 438 } |
439 #endif /* HAVE_NATIVE_SOUND */ | |
440 | |
441 DEVMETH (d, ring_bell, (d, vol, pit, dur)); | |
442 return Qnil; | |
443 } | |
444 | |
445 DEFUN ("device-sound-enabled-p", Fdevice_sound_enabled_p, 0, 1, 0, /* | |
446 Return t if DEVICE is able to play sound. Defaults to selected device. | |
447 */ | |
3072 | 448 (USED_IF_HAVE_NATIVE_OR_NAS (device))) |
428 | 449 { |
3308 | 450 #ifdef HAVE_ALSA_SOUND |
451 if (DEVICE_CONNECTED_TO_ALSA_P (decode_device (device))) | |
452 return Qt; | |
453 #endif | |
428 | 454 #ifdef HAVE_NAS_SOUND |
455 if (DEVICE_CONNECTED_TO_NAS_P (decode_device (device))) | |
456 return Qt; | |
457 #endif | |
458 #ifdef HAVE_NATIVE_SOUND | |
459 if (DEVICE_ON_CONSOLE_P (decode_device (device))) | |
460 return Qt; | |
461 #endif | |
462 return Qnil; | |
463 } | |
464 | |
465 DEFUN ("ding", Fding, 0, 3, 0, /* | |
466 Beep, or flash the frame. | |
793 | 467 |
468 \(See `visible-bell'; setting this makes the frame flash instead of | |
469 beeping.) Also, unless NO-TERMINATE is given, terminate any keyboard macro | |
470 currently executing. SOUND specifies the sound to make and DEVICE the | |
471 device to make it on (defaults to the selected device). | |
472 | |
473 SOUND is either a string (raw data to be played directly), a symbol, or | |
474 `nil' (equivalent to the symbol `default'). Sound symbols are looked up in | |
475 `sound-alist', and resolve either to strings of data or to other symbols. | |
476 Sound symbols that map directly to data should be considered named sounds; | |
477 sound symbols that map to other sounds should be considered abstract | |
478 sounds, and are used when a particular behavior or state occurs. | |
479 | |
2757 | 480 Remember that the sound symbol is the *second* argument to `ding', not the |
793 | 481 first. |
482 | |
483 The following abstract sounds are used by XEmacs itself: | |
484 | |
485 alarm when a package wants to remind the user | |
486 auto-save-error when an auto-save does not succeed | |
487 buffer-bound when you attempt to move off the end of a buffer | |
488 command-error any uncaught error (i.e. any error that the user | |
489 sees) except those handled by undefined-click, | |
490 undefined-key, buffer-bound, or read-only | |
491 default used when nothing else is appropriate. | |
492 isearch-failed unable to locate search text during incremental search | |
493 isearch-quit when you delete chars past the beginning of the search | |
494 text in isearch | |
495 no-completion during completing-read | |
496 quit when C-g is typed | |
497 read-only when you try to modify a read-only buffer | |
498 ready when a compile or other time-consuming task is done | |
499 undefined-click when you use an undefined mouse-click combination | |
500 undefined-key when you type a key that is undefined | |
501 warp XEmacs has changed the selected-window or frame | |
502 asynchronously -- e.g. a debugger breakpoint is hit | |
503 in an asynchronous process filter | |
504 y-or-n-p when you type something other than 'y' or 'n' | |
505 yes-or-no-p when you type something other than 'yes' or 'no' | |
506 | |
507 Other lisp packages may use other beep types, but these are the ones that | |
508 the C kernel of Emacs uses. | |
509 | |
428 | 510 */ |
793 | 511 (no_terminate, sound, device)) |
428 | 512 { |
430 | 513 static time_t last_bell_time; |
514 static struct device *last_bell_device; | |
428 | 515 time_t now; |
516 struct device *d = decode_device (device); | |
517 | |
793 | 518 device = wrap_device (d); |
428 | 519 now = time (0); |
520 | |
793 | 521 if (NILP (no_terminate) && !NILP (Vexecuting_macro)) |
428 | 522 /* Stop executing a keyboard macro. */ |
563 | 523 invalid_operation ("Keyboard macro terminated by a command ringing the bell", Qunbound); |
428 | 524 |
525 if (d == last_bell_device && now-last_bell_time < bell_inhibit_time) | |
526 return Qnil; | |
442 | 527 else if (!NILP (Vvisible_bell) && DEVMETH (d, flash, (d))) |
428 | 528 ; |
529 else | |
530 Fplay_sound (sound, Qnil, device); | |
531 | |
532 last_bell_time = now; | |
533 last_bell_device = d; | |
534 return Qnil; | |
535 } | |
536 | |
537 DEFUN ("wait-for-sounds", Fwait_for_sounds, 0, 1, 0, /* | |
538 Wait for all sounds to finish playing on DEVICE. | |
539 */ | |
2294 | 540 (USED_IF_HAVE_NAS (device))) |
428 | 541 { |
542 #ifdef HAVE_NAS_SOUND | |
543 struct device *d = decode_device (device); | |
544 if (DEVICE_CONNECTED_TO_NAS_P (d)) | |
545 { | |
546 /* #### somebody fix this to be device-dependent. */ | |
547 nas_wait_for_sounds (); | |
548 } | |
549 #endif | |
550 return Qnil; | |
551 } | |
552 | |
553 DEFUN ("connected-to-nas-p", Fconnected_to_nas_p, 0, 1, 0, /* | |
554 Return t if connected to NAS server for sounds on DEVICE. | |
555 */ | |
2294 | 556 (USED_IF_HAVE_NAS (device))) |
428 | 557 { |
558 #ifdef HAVE_NAS_SOUND | |
559 return DEVICE_CONNECTED_TO_NAS_P (decode_device (device)) ? Qt : Qnil; | |
560 #else | |
561 return Qnil; | |
562 #endif | |
563 } | |
564 #ifdef HAVE_NAS_SOUND | |
565 | |
566 static void | |
567 init_nas_sound (struct device *d) | |
568 { | |
569 #ifdef HAVE_X_WINDOWS | |
570 if (DEVICE_X_P (d)) | |
571 { | |
563 | 572 Extbyte *err_message = nas_init_play (DEVICE_X_DISPLAY (d)); |
442 | 573 DEVICE_CONNECTED_TO_NAS_P (d) = !err_message; |
428 | 574 /* Print out the message? */ |
575 } | |
576 #endif /* HAVE_X_WINDOWS */ | |
577 } | |
578 | |
579 #endif /* HAVE_NAS_SOUND */ | |
580 | |
581 #ifdef HAVE_NATIVE_SOUND | |
582 | |
583 static void | |
584 init_native_sound (struct device *d) | |
585 { | |
3731 | 586 if (!(DEVICE_X_P(d) || DEVICE_GTK_P(d))) |
428 | 587 DEVICE_ON_CONSOLE_P (d) = 1; |
588 #ifdef HAVE_X_WINDOWS | |
589 else | |
590 { | |
591 /* When running on a machine with native sound support, we cannot use | |
592 digitized sounds as beeps unless emacs is running on the same machine | |
593 that $DISPLAY points to, and $DISPLAY points to frame 0 of that | |
594 machine. | |
595 */ | |
596 | |
597 Display *display = DEVICE_X_DISPLAY (d); | |
563 | 598 Extbyte *dpy = DisplayString (display); |
599 Extbyte *tail = strchr (dpy, ':'); | |
428 | 600 if (! tail || |
601 strncmp (tail, ":0", 2)) | |
602 DEVICE_ON_CONSOLE_P (d) = 0; | |
603 else | |
604 { | |
563 | 605 Extbyte dpyname[255], localname[255]; |
428 | 606 |
607 /* some systems can't handle SIGIO or SIGALARM in gethostbyname. */ | |
608 stop_interrupts (); | |
609 strncpy (dpyname, dpy, tail-dpy); | |
610 dpyname [tail-dpy] = 0; | |
611 if (!*dpyname || | |
612 !strcmp (dpyname, "unix") || | |
613 !strcmp (dpyname, "localhost")) | |
614 DEVICE_ON_CONSOLE_P (d) = 1; | |
615 else if (gethostname (localname, sizeof (localname))) | |
616 DEVICE_ON_CONSOLE_P (d) = 0; /* can't find hostname? */ | |
617 else | |
618 { | |
619 /* We have to call gethostbyname() on the result of gethostname() | |
620 because the two aren't guaranteed to be the same name for the | |
621 same host: on some losing systems, one is a FQDN and the other | |
622 is not. Here in the wide wonderful world of Unix it's rocket | |
623 science to obtain the local hostname in a portable fashion. | |
624 | |
625 And don't forget, gethostbyname() reuses the structure it | |
626 returns, so we have to copy the fucker before calling it | |
627 again. | |
628 | |
629 Thank you master, may I have another. | |
630 */ | |
631 struct hostent *h = gethostbyname (dpyname); | |
632 if (!h) | |
633 DEVICE_ON_CONSOLE_P (d) = 0; | |
634 else | |
635 { | |
3504 | 636 Extbyte *hn = alloca_array (Extbyte, strlen (h->h_name) + 1); |
428 | 637 struct hostent *l; |
638 strcpy (hn, h->h_name); | |
639 l = gethostbyname (localname); | |
640 DEVICE_ON_CONSOLE_P (d) = (l && !(strcmp (l->h_name, hn))); | |
641 } | |
642 } | |
643 start_interrupts (); | |
644 } | |
645 } | |
646 #endif /* HAVE_X_WINDOWS */ | |
647 } | |
648 | |
649 #endif /* HAVE_NATIVE_SOUND */ | |
650 | |
651 void | |
3072 | 652 init_device_sound (struct device * USED_IF_HAVE_NATIVE_OR_NAS (d)) |
428 | 653 { |
654 #ifdef HAVE_NAS_SOUND | |
655 init_nas_sound (d); | |
656 #endif | |
657 | |
658 #ifdef HAVE_NATIVE_SOUND | |
659 init_native_sound (d); | |
660 #endif | |
661 } | |
662 | |
663 void | |
664 syms_of_sound (void) | |
665 { | |
563 | 666 DEFKEYWORD (Q_volume); |
667 DEFKEYWORD (Q_pitch); | |
668 DEFKEYWORD (Q_duration); | |
669 DEFKEYWORD (Q_sound); | |
428 | 670 |
563 | 671 DEFERROR_STANDARD (Qsound_error, Qio_error); |
428 | 672 |
673 DEFSUBR (Fplay_sound_file); | |
674 DEFSUBR (Fplay_sound); | |
675 DEFSUBR (Fding); | |
676 DEFSUBR (Fwait_for_sounds); | |
677 DEFSUBR (Fconnected_to_nas_p); | |
678 DEFSUBR (Fdevice_sound_enabled_p); | |
679 } | |
680 | |
681 | |
682 void | |
683 vars_of_sound (void) | |
684 { | |
3308 | 685 #ifdef HAVE_ALSA_SOUND |
686 Fprovide (intern ("alsa-sound")); | |
687 #endif | |
428 | 688 #ifdef HAVE_NATIVE_SOUND |
689 Fprovide (intern ("native-sound")); | |
690 #endif | |
691 #ifdef HAVE_NAS_SOUND | |
692 Fprovide (intern ("nas-sound")); | |
693 #endif | |
432 | 694 #ifdef HAVE_ESD_SOUND |
695 Fprovide (intern ("esd-sound")); | |
696 #endif | |
428 | 697 |
698 DEFVAR_INT ("bell-volume", &bell_volume /* | |
699 *How loud to be, from 0 to 100. | |
700 */ ); | |
701 bell_volume = 50; | |
702 | |
703 DEFVAR_INT ("bell-inhibit-time", &bell_inhibit_time /* | |
704 *Don't ring the bell on the same device more than once within this many seconds. | |
705 */ ); | |
706 bell_inhibit_time = 0; | |
707 | |
708 DEFVAR_LISP ("sound-alist", &Vsound_alist /* | |
709 An alist associating names with sounds. | |
710 When `beep' or `ding' is called with one of the name symbols, the associated | |
711 sound will be generated instead of the standard beep. | |
712 | |
713 Each element of `sound-alist' is a list describing a sound. | |
714 The first element of the list is the name of the sound being defined. | |
715 Subsequent elements of the list are alternating keyword/value pairs: | |
716 | |
717 Keyword: Value: | |
718 ------- ----- | |
719 sound A string of raw sound data, or the name of another sound to | |
720 play. The symbol `t' here means use the default X beep. | |
721 volume An integer from 0-100, defaulting to `bell-volume' | |
722 pitch If using the default X beep, the pitch (Hz) to generate. | |
723 duration If using the default X beep, the duration (milliseconds). | |
724 | |
725 For compatibility, elements of `sound-alist' may also be: | |
726 | |
727 ( sound-name . <sound> ) | |
728 ( sound-name <volume> <sound> ) | |
729 | |
730 You should probably add things to this list by calling the function | |
731 load-sound-file. | |
732 | |
733 Caveats: | |
734 - XEmacs must be built with sound support for your system. Not all | |
735 systems support sound. | |
736 | |
737 - The pitch, duration, and volume options are available everywhere, but | |
738 many X servers ignore the `pitch' option. | |
739 | |
793 | 740 Sound symbols that map directly to data should be considered named sounds; |
741 sound symbols that map to other sounds should be considered abstract | |
742 sounds, and are used when a particular behavior or state occurs. See | |
743 `ding' for a list of the standard abstract sounds. | |
428 | 744 */ ); |
745 Vsound_alist = Qnil; | |
746 | |
747 DEFVAR_LISP ("synchronous-sounds", &Vsynchronous_sounds /* | |
748 Play sounds synchronously, if non-nil. | |
749 Only applies if NAS is used and supports asynchronous playing | |
750 of sounds. Otherwise, sounds are always played synchronously. | |
751 */ ); | |
752 Vsynchronous_sounds = Qnil; | |
753 | |
754 DEFVAR_LISP ("native-sound-only-on-console", &Vnative_sound_only_on_console /* | |
755 Non-nil value means play sounds only if XEmacs is running | |
756 on the system console. | |
442 | 757 Nil means always play sounds, even if running on a non-console tty |
428 | 758 or a secondary X display. |
759 | |
760 This variable only applies to native sound support. | |
761 */ ); | |
762 Vnative_sound_only_on_console = Qt; | |
763 | |
764 #if defined (HAVE_NATIVE_SOUND) && defined (hp9000s800) | |
765 { | |
766 void vars_of_hpplay (void); | |
767 vars_of_hpplay (); | |
768 } | |
769 #endif | |
770 } |