Mercurial > hg > xemacs-beta
view src/sound.c @ 2367:ecf1ebac70d8
[xemacs-hg @ 2004-11-04 23:05:23 by ben]
commit mega-patch
configure.in: Turn off -Winline and -Wchar-subscripts.
Use the right set of cflags when compiling modules.
Rewrite ldap configuration to separate the inclusion of lber
(needed in recent Cygwin) from the basic checks for the
needed libraries.
add a function for MAKE_JUNK_C; initially code was added to
generate xemacs.def using this, but it will need to be rewritten.
add an rm -f for junk.c to avoid weird Cygwin bug with cp -f onto
an existing file.
Sort list of auto-detected functions and eliminate unused checks for
stpcpy, setlocale and getwd.
Add autodetection of Cygwin scanf problems
BETA: Rewrite section on configure to indicate what flags are important
and what not.
digest-doc.c, make-dump-id.c, profile.c, sorted-doc.c: Add proper decls for main().
make-msgfile.c: Document that this is old junk.
Move proposal to text.c.
make-msgfile.lex: Move proposal to text.c.
make-mswin-unicode.pl: Convert error-generating code so that the entire message will
be seen as a single unrecognized token.
mule/mule-ccl.el: Update docs.
lispref/mule.texi: Update CCL docs.
ldap/eldap.c: Mule-ize.
Use EXTERNAL_LIST_LOOP_2 instead of deleted EXTERNAL_LIST_LOOP.
* XEmacs 21.5.18 "chestnut" is released.
---------------------------------------------------------------
MULE-RELATED WORK:
---------------------------------------------------------------
---------------------------
byte-char conversion
---------------------------
buffer.c, buffer.h, insdel.c, text.c: Port FSF algorithm for byte-char conversion, replacing broken
previous version. Track the char position of the gap. Add
functions to do char-byte conversion downwards as well as upwards.
Move comments about algorithm workings to internals manual.
---------------------------
work on types
---------------------------
alloc.c, console-x-impl.h, dump-data.c, dump-data.h, dumper.c, dialog-msw.c, dired-msw.c, doc.c, editfns.c, esd.c, event-gtk.h, event-msw.c, events.c, file-coding.c, file-coding.h, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-shared.c, glyphs-x.c, glyphs.c, glyphs.h, gui.c, hpplay.c, imgproc.c, intl-win32.c, lrecord.h, lstream.c, keymap.c, lisp.h, libsst.c, linuxplay.c, miscplay.c, miscplay.h, mule-coding.c, nas.c, nt.c, ntheap.c, ntplay.c, objects-msw.c, objects-tty.c, objects-x.c, print.c, process-nt.c, process.c, redisplay.h, select-common.h, select-gtk.c, select-x.c, sgiplay.c, sound.c, sound.h, sunplay.c, sysfile.h, sysdep.c, syswindows.h, text.c, unexnt.c, win32.c, xgccache.c: Further work on types. This creates a full set of types for all
the basic semantics of `char' that I have so far identified, so that
its semantics can always be identified for the purposes of proper
Mule-safe code, and the raw use of `char' always avoided.
(1) More type renaming, for consistency of naming.
Char_ASCII -> Ascbyte
UChar_ASCII -> UAscbyte
Char_Binary -> CBinbyte
UChar_Binary -> Binbyte
SChar_Binary -> SBinbyte
(2) Introduce Rawbyte, CRawbyte, Boolbyte, Chbyte, UChbyte, and
Bitbyte and use them.
(3) New types Itext, Wexttext and Textcount for separating out
the concepts of bytes and textual units (different under UTF-16
and UTF-32, which are potential internal encodings).
(4) qxestr*_c -> qxestr*_ascii.
lisp.h: New; goes with other qxe() functions. #### Maybe goes in a
different section.
lisp.h: Group generic int-type defs together with EMACS_INT defs.
lisp.h: * lisp.h (WEXTTEXT_IS_WIDE)
New defns.
lisp.h: New type to replace places where int occurs as a boolean.
It's signed because occasionally people may want to use -1 as
an error value, and because unsigned ints are viral -- see comments
in the internals manual against using them.
dynarr.c: int -> Bytecount.
---------------------------
Mule-izing
---------------------------
device-x.c: Partially Mule-ize.
dumper.c, dumper.h: Mule-ize. Use Rawbyte. Use stderr_out not printf. Use wext_*().
sysdep.c, syswindows.h, text.c: New Wexttext API for manipulation of external text that may be
Unicode (e.g. startup code under Windows).
emacs.c: Mule-ize. Properly deal with argv in external encoding.
Use wext_*() and Wexttext. Use Rawbyte.
#if 0 some old junk on SCO that is unlikely to be correct.
Rewrite allocation code in run-temacs.
emacs.c, symsinit.h, win32.c: Rename win32 init function and call it even earlier, to
initialize mswindows_9x_p even earlier, for use in startup code
(XEUNICODE_P).
process.c: Use _wenviron not environ under Windows, to get Unicode environment
variables.
event-Xt.c: Mule-ize drag-n-drop related stuff.
dragdrop.c, dragdrop.h, frame-x.c: Mule-ize.
text.h: Add some more stand-in defines for particular kinds of conversion;
use in Mule-ization work in frame-x.c etc.
---------------------------
Freshening
---------------------------
intl-auto-encap-win32.c, intl-auto-encap-win32.h: Regenerate.
---------------------------
Unicode-work
---------------------------
intl-win32.c, syswindows.h: Factor out common options to MultiByteToWideChar and
WideCharToMultiByte. Add convert_unicode_to_multibyte_malloc()
and convert_unicode_to_multibyte_dynarr() and use. Add stuff for
alloca() conversion of multibyte/unicode.
alloc.c: Use dfc_external_data_len() in case of unicode coding system.
alloc.c, mule-charset.c: Don't zero out and reinit charset Unicode tables. This fucks up
dump-time loading. Anyway, either we load them at dump time or
run time, never both.
unicode.c: Dump the blank tables as well.
---------------------------------------------------------------
DOCUMENTATION, MOSTLY MULE-RELATED:
---------------------------------------------------------------
EmacsFrame.c, emodules.c, event-Xt.c, fileio.c, input-method-xlib.c, mule-wnnfns.c, redisplay-gtk.c, redisplay-tty.c, redisplay-x.c, regex.c, sysdep.c: Add comment about Mule work needed.
text.h: Add more documentation describing why DFC routines were not written
to return their value. Add some other DFC documentation.
console-msw.c, console-msw.h: Add pointer to docs in win32.c.
emacs.c: Add comments on sources of doc info.
text.c, charset.h, unicode.c, intl-win32.c, intl-encap-win32.c, text.h, file-coding.c, mule-coding.c: Collect background comments and related to text matters and
internationalization, and proposals for work to be done, in text.c
or Internals manual, stuff related to specific textual API's in
text.h, and stuff related to internal implementation of Unicode
conversion in unicode.c. Put lots of pointers to the comments to
make them easier to find.
s/mingw32.h, s/win32-common.h, s/win32-native.h, s/windowsnt.h, win32.c: Add bunches of new documentation on the different kinds of
builds and environments under Windows and how they work.
Collect this info in win32.c. Add pointers to these docs in
the relevant s/* files.
emacs.c: Document places with long comments.
Remove comment about exiting, move to internals manual, put
in pointer.
event-stream.c: Move docs about event queues and focus to internals manual, put
in pointer.
events.h: Move docs about event stream callbacks to internals manual, put
in pointer.
profile.c, redisplay.c, signal.c: Move documentation to the Internals manual.
process-nt.c: Add pointer to comment in win32-native.el.
lisp.h: Add comments about some comment conventions.
lisp.h: Add comment about the second argument.
device-msw.c, redisplay-msw.c: @@#### comments are out-of-date.
---------------------------------------------------------------
PDUMP WORK (MOTIVATED BY UNICODE CHANGES)
---------------------------------------------------------------
alloc.c, buffer.c, bytecode.c, console-impl.h, console.c, device.c, dumper.c, lrecord.h, elhash.c, emodules.h, events.c, extents.c, frame.c, glyphs.c, glyphs.h, mule-charset.c, mule-coding.c, objects.c, profile.c, rangetab.c, redisplay.c, specifier.c, specifier.h, window.c, lstream.c, file-coding.h, file-coding.c: PDUMP:
Properly implement dump_add_root_block(), which never worked before,
and is necessary for dumping Unicode tables.
Pdump name changes for accuracy:
XD_STRUCT_PTR -> XD_BLOCK_PTR.
XD_STRUCT_ARRAY -> XD_BLOCK_ARRAY.
XD_C_STRING -> XD_ASCII_STRING.
*_structure_* -> *_block_*.
lrecord.h: some comments added about
dump_add_root_block() vs dump_add_root_block_ptr().
extents.c: remove incorrect comment about pdump problems with gap array.
---------------------------------------------------------------
ALLOCATION
---------------------------------------------------------------
abbrev.c, alloc.c, bytecode.c, casefiddle.c, device-msw.c, device-x.c, dired-msw.c, doc.c, doprnt.c, dragdrop.c, editfns.c, emodules.c, file-coding.c, fileio.c, filelock.c, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-x.c, gui-msw.c, gui-x.c, imgproc.c, intl-win32.c, lread.c, menubar-gtk.c, menubar.c, nt.c, objects-msw.c, objects-x.c, print.c, process-nt.c, process-unix.c, process.c, realpath.c, redisplay.c, search.c, select-common.c, symbols.c, sysdep.c, syswindows.h, text.c, text.h, ui-byhand.c: New macros {alloca,xnew}_{itext,{i,ext,raw,bin,asc}bytes} for
more convenient allocation of these commonly requested items.
Modify functions to use alloca_ibytes, alloca_array, alloca_extbytes,
xnew_ibytes, etc. also XREALLOC_ARRAY, xnew.
alloc.c: Rewrite the allocation functions to factor out repeated code.
Add assertions for freeing dumped data.
lisp.h: Moved down and consolidated with other allocation stuff.
lisp.h, dynarr.c: New functions for allocation that's very efficient when mostly in
LIFO order.
lisp.h, text.c, text.h: Factor out some stuff for general use by alloca()-conversion funs.
text.h, lisp.h: Fill out convenience routines for allocating various kinds of
bytes and put them in lisp.h. Use them in place of xmalloc(),
ALLOCA().
text.h: Fill out the convenience functions so the _MALLOC() kinds match
the alloca() kinds.
---------------------------------------------------------------
ERROR-CHECKING
---------------------------------------------------------------
text.h: Create ASSERT_ASCTEXT_ASCII() and ASSERT_ASCTEXT_ASCII_LEN()
from similar Eistring checkers and change the Eistring checkers to
use them instead.
---------------------------------------------------------------
MACROS IN LISP.H
---------------------------------------------------------------
lisp.h: Redo GCPRO declarations. Create a "base" set of functions that can
be used to generate any kind of gcpro sets -- regular, ngcpro,
nngcpro, private ones used in GC_EXTERNAL_LIST_LOOP_2.
buffer.c, callint.c, chartab.c, console-msw.c, device-x.c, dialog-msw.c, dired.c, extents.c, ui-gtk.c, rangetab.c, nt.c, mule-coding.c, minibuf.c, menubar-msw.c, menubar.c, menubar-gtk.c, lread.c, lisp.h, gutter.c, glyphs.c, glyphs-widget.c, fns.c, fileio.c, file-coding.c, specifier.c: Eliminate EXTERNAL_LIST_LOOP, which does not check for circularities.
Use EXTERNAL_LIST_LOOP_2 instead or EXTERNAL_LIST_LOOP_3
or EXTERNAL_PROPERTY_LIST_LOOP_3 or GC_EXTERNAL_LIST_LOOP_2
(new macro). Removed/redid comments on EXTERNAL_LIST_LOOP.
---------------------------------------------------------------
SPACING FIXES
---------------------------------------------------------------
callint.c, hftctl.c, number-gmp.c, process-unix.c: Spacing fixes.
---------------------------------------------------------------
FIX FOR GEOMETRY PROBLEM IN FIRST FRAME
---------------------------------------------------------------
unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by
release 1.5.12 of Cygwin].
toolbar.c: bug fix for problem of initial frame being 77 chars wide on Windows.
will be overridden by my other ws.
---------------------------------------------------------------
FIX FOR LEAKING PROCESS HANDLES:
---------------------------------------------------------------
process-nt.c: Fixes for leaking handles. Inspired by work done by Adrian Aichner
<adrian@xemacs.org>.
---------------------------------------------------------------
FIX FOR CYGWIN BUG (Unicode-related):
---------------------------------------------------------------
unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by
release 1.5.12 of Cygwin].
---------------------------------------------------------------
WARNING FIXES:
---------------------------------------------------------------
console-stream.c: `reinit' is unused.
compiler.h, event-msw.c, frame-msw.c, intl-encap-win32.c, text.h: Add stuff to deal with ANSI-aliasing warnings I got.
regex.c: Gather includes together to avoid warning.
---------------------------------------------------------------
CHANGES TO INITIALIZATION ROUTINES:
---------------------------------------------------------------
buffer.c, emacs.c, console.c, debug.c, device-x.c, device.c, dragdrop.c, emodules.c, eval.c, event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, event-tty.c, events.c, extents.c, faces.c, file-coding.c, fileio.c, font-lock.c, frame-msw.c, glyphs-widget.c, glyphs.c, gui-x.c, insdel.c, lread.c, lstream.c, menubar-gtk.c, menubar-x.c, minibuf.c, mule-wnnfns.c, objects-msw.c, objects.c, print.c, scrollbar-x.c, search.c, select-x.c, text.c, undo.c, unicode.c, window.c, symsinit.h: Call reinit_*() functions directly from emacs.c, for clarity.
Factor out some redundant init code. Move disallowed stuff
that had crept into vars_of_glyphs() into complex_vars_of_glyphs().
Call init_eval_semi_early() from eval.c not in the middle of
vars_of_() in emacs.c since there should be no order dependency
in the latter calls.
---------------------------------------------------------------
ARMAGEDDON:
---------------------------------------------------------------
alloc.c, emacs.c, lisp.h, print.c: Rename inhibit_non_essential_printing_operations to
inhibit_non_essential_conversion_operations.
text.c: Assert on !inhibit_non_essential_conversion_operations.
console-msw.c, print.c: Don't do conversion in SetConsoleTitle or FindWindow to avoid
problems during armageddon. Put #errors for NON_ASCII_INTERNAL_FORMAT
in places where problems would arise.
---------------------------------------------------------------
CHANGES TO THE BUILD PROCEDURE:
---------------------------------------------------------------
config.h.in, s/cxux.h, s/usg5-4-2.h, m/powerpc.h: Add comment about correct ordering of this file.
Rearrange everything to follow this -- put all #undefs together
and before the s&m files. Add undefs for HAVE_ALLOCA, C_ALLOCA,
BROKEN_ALLOCA_IN_FUNCTION_CALLS, STACK_DIRECTION. Remove unused
HAVE_STPCPY, HAVE_GETWD, HAVE_SETLOCALE.
m/gec63.h: Deleted; totally broken, not used at all, not in FSF.
m/7300.h, m/acorn.h, m/alliant-2800.h, m/alliant.h, m/altos.h, m/amdahl.h, m/apollo.h, m/att3b.h, m/aviion.h, m/celerity.h, m/clipper.h, m/cnvrgnt.h, m/convex.h, m/cydra5.h, m/delta.h, m/delta88k.h, m/dpx2.h, m/elxsi.h, m/ews4800r.h, m/gould.h, m/hp300bsd.h, m/hp800.h, m/hp9000s300.h, m/i860.h, m/ibmps2-aix.h, m/ibmrs6000.h, m/ibmrt-aix.h, m/ibmrt.h, m/intel386.h, m/iris4d.h, m/iris5d.h, m/iris6d.h, m/irist.h, m/isi-ov.h, m/luna88k.h, m/m68k.h, m/masscomp.h, m/mg1.h, m/mips-nec.h, m/mips-siemens.h, m/mips.h, m/news.h, m/nh3000.h, m/nh4000.h, m/ns32000.h, m/orion105.h, m/pfa50.h, m/plexus.h, m/pmax.h, m/powerpc.h, m/pyrmips.h, m/sequent-ptx.h, m/sequent.h, m/sgi-challenge.h, m/symmetry.h, m/tad68k.h, m/tahoe.h, m/targon31.h, m/tekxd88.h, m/template.h, m/tower32.h, m/tower32v3.h, m/ustation.h, m/vax.h, m/wicat.h, m/xps100.h: Delete C_ALLOCA, HAVE_ALLOCA, STACK_DIRECTION,
BROKEN_ALLOCA_IN_FUNCTION_CALLS. All of this is auto-detected.
When in doubt, I followed recent FSF sources, which also have
these things deleted.
author | ben |
---|---|
date | Thu, 04 Nov 2004 23:08:28 +0000 |
parents | d5131a81147e |
children | 902d5bd9b75c |
line wrap: on
line source
/* Sound functions. Copyright (C) 1992, 1993, 1994 Lucid Inc. Copyright (C) 1994, 1995 Free Software Foundation, Inc. Copyright (C) 2002 Ben Wing. This file is part of XEmacs. XEmacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. XEmacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with XEmacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Synched up with: Not in FSF. */ /* This file Mule-ized by Ben Wing, 5-15-01. */ /* Originally written by Jamie Zawinski. Hacked on quite a bit by various others. */ #include <config.h> #include <time.h> #include "lisp.h" #include "buffer.h" #ifdef HAVE_X_WINDOWS #include "console-x-impl.h" #endif #include "device-impl.h" #include "redisplay.h" #include "sound.h" #include "sysdep.h" #include "sysfile.h" #ifdef HAVE_NATIVE_SOUND # include "sysproc.h" #endif #ifdef WIN32_NATIVE #include "syswindows.h" #endif #ifdef HAVE_ESD_SOUND extern int esd_play_sound_file (Extbyte *file, int vol); extern int esd_play_sound_data (Binbyte *data, size_t length, int vol); # define DEVICE_CONNECTED_TO_ESD_P(x) 1 /* #### better check */ #endif Fixnum bell_volume; Fixnum bell_inhibit_time; Lisp_Object Vsound_alist; Lisp_Object Vsynchronous_sounds; Lisp_Object Vnative_sound_only_on_console; Lisp_Object Q_volume, Q_pitch, Q_duration, Q_sound; Lisp_Object Qsound_error; #ifdef HAVE_NAS_SOUND extern int nas_play_sound_file (Extbyte *name, int volume); extern int nas_play_sound_data (Binbyte *data, int length, int volume); extern int nas_wait_for_sounds (void); extern Extbyte *nas_init_play (Display *); #endif DOESNT_RETURN report_sound_error (const Ascbyte *string, Lisp_Object data) { report_error_with_errno (Qsound_error, string, data); } DEFUN ("play-sound-file", Fplay_sound_file, 1, 3, "fSound file name: ", /* Play the named sound file on DEVICE's speaker at the specified volume \(0-100, default specified by the `bell-volume' variable). On Unix machines the sound file must be in the Sun/NeXT U-LAW format except under Linux where WAV files are also supported. On Microsoft Windows the sound file must be in WAV format. DEVICE defaults to the selected device. */ (file, volume, device)) { /* This function can call lisp */ int vol; #if defined (HAVE_NATIVE_SOUND) || defined (HAVE_NAS_SOUND) \ || defined (HAVE_ESD_SOUND) struct device *d = decode_device (device); #endif struct gcpro gcpro1; CHECK_STRING (file); if (NILP (volume)) vol = bell_volume; else { CHECK_INT (volume); vol = XINT (volume); } GCPRO1 (file); while (1) { file = Fexpand_file_name (file, Qnil); if (!NILP(Ffile_readable_p (file))) break; else { /* #### This is crockish. It might be a better idea to try to open the file, and use report_file_error() if it fails. --hniksic */ if (NILP (Ffile_exists_p (file))) file = signal_continuable_error (Qfile_error, "File does not exist", file); else file = signal_continuable_error (Qfile_error, "File is unreadable", file); } } UNGCPRO; #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (d)) { Extbyte *fileext; LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); /* #### NAS code should allow specification of a device. */ if (nas_play_sound_file (fileext, vol)) return Qnil; } #endif /* HAVE_NAS_SOUND */ #ifdef HAVE_ESD_SOUND if (DEVICE_CONNECTED_TO_ESD_P (d)) { Extbyte *fileext; int result; LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); /* #### ESD uses alarm(). But why should we also stop SIGIO? */ stop_interrupts (); result = esd_play_sound_file (fileext, vol); start_interrupts (); if (result) return Qnil; } #endif /* HAVE_ESD_SOUND */ #ifdef HAVE_NATIVE_SOUND if (NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) { Extbyte *fileext; #ifdef WIN32_NATIVE /* #### more garbage. we should be passing the internal file name to play_sound_file. */ LISP_STRING_TO_EXTERNAL (file, fileext, Qmswindows_tstr); #else LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name); #endif /* The sound code doesn't like getting SIGIO interrupts. Unix sucks! */ stop_interrupts (); play_sound_file (fileext, vol); start_interrupts (); QUIT; } #endif /* HAVE_NATIVE_SOUND */ return Qnil; } static void parse_sound_alist_elt (Lisp_Object elt, Lisp_Object *volume, Lisp_Object *pitch, Lisp_Object *duration, Lisp_Object *sound) { *volume = Qnil; *pitch = Qnil; *duration = Qnil; *sound = Qnil; if (! CONSP (elt)) return; /* The things we do for backward compatibility... I wish I had just forced this to be a plist to begin with. */ if (SYMBOLP (elt) || STRINGP (elt)) /* ( name . <sound> ) */ { *sound = elt; } else if (!CONSP (elt)) { return; } else if (NILP (XCDR (elt)) && /* ( name <sound> ) */ (SYMBOLP (XCAR (elt)) || STRINGP (XCAR (elt)))) { *sound = XCAR (elt); } else if (INT_OR_FLOATP (XCAR (elt)) && /* ( name <vol> . <sound> ) */ (SYMBOLP (XCDR (elt)) || STRINGP (XCDR (elt)))) { *volume = XCAR (elt); *sound = XCDR (elt); } else if (INT_OR_FLOATP (XCAR (elt)) && /* ( name <vol> <sound> ) */ CONSP (XCDR (elt)) && NILP (XCDR (XCDR (elt))) && (SYMBOLP (XCAR (XCDR (elt))) || STRINGP (XCAR (XCDR (elt))))) { *volume = XCAR (elt); *sound = XCAR (XCDR (elt)); } else if ((SYMBOLP (XCAR (elt)) || /* ( name <sound> . <vol> ) */ STRINGP (XCAR (elt))) && INT_OR_FLOATP (XCDR (elt))) { *sound = XCAR (elt); *volume = XCDR (elt); } #if 0 /* this one is ambiguous with the plist form */ else if ((SYMBOLP (XCAR (elt)) || /* ( name <sound> <vol> ) */ STRINGP (XCAR (elt))) && CONSP (XCDR (elt)) && NILP (XCDR (XCDR (elt))) && INT_OR_FLOATP (XCAR (XCDR (elt)))) { *sound = XCAR (elt); *volume = XCAR (XCDR (elt)); } #endif /* 0 */ else /* ( name [ keyword <value> ]* ) */ { while (CONSP (elt)) { Lisp_Object key, val; key = XCAR (elt); val = XCDR (elt); if (!CONSP (val)) return; elt = XCDR (val); val = XCAR (val); if (EQ (key, Q_volume)) { if (INT_OR_FLOATP (val)) *volume = val; } else if (EQ (key, Q_pitch)) { if (INT_OR_FLOATP (val)) *pitch = val; if (NILP (*sound)) *sound = Qt; } else if (EQ (key, Q_duration)) { if (INT_OR_FLOATP (val)) *duration = val; if (NILP (*sound)) *sound = Qt; } else if (EQ (key, Q_sound)) { if (SYMBOLP (val) || STRINGP (val)) *sound = val; } } } } DEFUN ("play-sound", Fplay_sound, 1, 3, 0, /* Play a sound of the provided type. SOUND can a symbol, specifying a sound to be looked up in `sound-alist' \(generally, either the symbol directly maps to a sound or is an "abstract" symbol that maps to another symbol and is used to specify the sound that is played when a particular behavior occurs. `ding' lists the built-in abstract sounds and their intended purpose. SOUND can also be a string, which directly encodes the sound data to be played. If SOUND is nil, the abstract sound `default' will be used. VOLUME controls the volume (max is around 150? not sure). DEVICE is the device to play the sound on (defaults to the selected device). If the sound cannot be played in any other way, the standard "bell" will sound. */ (sound, volume, device)) { int looking_for_default = 0; /* variable `sound' is anything that can be a cdr in sound-alist */ Lisp_Object new_volume, pitch, duration, data; int loop_count = 0; int vol, pit, dur; struct device *d = decode_device (device); /* NOTE! You'd better not signal an error in here. */ try_it_again: while (1) { if (SYMBOLP (sound)) sound = Fcdr (Fassq (sound, Vsound_alist)); parse_sound_alist_elt (sound, &new_volume, &pitch, &duration, &data); sound = data; if (NILP (volume)) volume = new_volume; if (EQ (sound, Qt) || EQ (sound, Qnil) || STRINGP (sound)) break; if (loop_count++ > 500) /* much bogosity has occurred */ break; } if (NILP (sound) && !looking_for_default) { looking_for_default = 1; loop_count = 0; sound = Qdefault; goto try_it_again; } vol = (INT_OR_FLOATP (volume) ? (int) XFLOATINT (volume) : bell_volume); pit = (INT_OR_FLOATP (pitch) ? (int) XFLOATINT (pitch) : -1); dur = (INT_OR_FLOATP (duration) ? (int) XFLOATINT (duration) : -1); /* If the sound is a string, and we're connected to Nas, do that. Else if the sound is a string, and we're on console, play it natively. Else just beep. */ #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound)) { Binbyte *soundext; Bytecount soundextlen; TO_EXTERNAL_FORMAT (LISP_STRING, sound, ALLOCA, (soundext, soundextlen), Qbinary); if (nas_play_sound_data (soundext, soundextlen, vol)) return Qnil; } #endif /* HAVE_NAS_SOUND */ #ifdef HAVE_ESD_SOUND if (DEVICE_CONNECTED_TO_ESD_P (d) && STRINGP (sound)) { Binbyte *soundext; Bytecount soundextlen; int succes; TO_EXTERNAL_FORMAT (LISP_STRING, sound, ALLOCA, (soundext, soundextlen), Qbinary); /* #### ESD uses alarm(). But why should we also stop SIGIO? */ stop_interrupts (); succes = esd_play_sound_data (soundext, soundextlen, vol); start_interrupts (); QUIT; if(succes) return Qnil; } #endif /* HAVE_ESD_SOUND */ #ifdef HAVE_NATIVE_SOUND if ((NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d)) && STRINGP (sound)) { Binbyte *soundext; Bytecount soundextlen; int succes; TO_EXTERNAL_FORMAT (LISP_STRING, sound, ALLOCA, (soundext, soundextlen), Qbinary); /* The sound code doesn't like getting SIGIO interrupts. Unix sucks! */ stop_interrupts (); succes = play_sound_data (soundext, soundextlen, vol); start_interrupts (); QUIT; if (succes) return Qnil; } #endif /* HAVE_NATIVE_SOUND */ DEVMETH (d, ring_bell, (d, vol, pit, dur)); return Qnil; } DEFUN ("device-sound-enabled-p", Fdevice_sound_enabled_p, 0, 1, 0, /* Return t if DEVICE is able to play sound. Defaults to selected device. */ (device)) { #ifdef HAVE_NAS_SOUND if (DEVICE_CONNECTED_TO_NAS_P (decode_device (device))) return Qt; #endif #ifdef HAVE_NATIVE_SOUND if (DEVICE_ON_CONSOLE_P (decode_device (device))) return Qt; #endif return Qnil; } DEFUN ("ding", Fding, 0, 3, 0, /* Beep, or flash the frame. \(See `visible-bell'; setting this makes the frame flash instead of beeping.) Also, unless NO-TERMINATE is given, terminate any keyboard macro currently executing. SOUND specifies the sound to make and DEVICE the device to make it on (defaults to the selected device). SOUND is either a string (raw data to be played directly), a symbol, or `nil' (equivalent to the symbol `default'). Sound symbols are looked up in `sound-alist', and resolve either to strings of data or to other symbols. Sound symbols that map directly to data should be considered named sounds; sound symbols that map to other sounds should be considered abstract sounds, and are used when a particular behavior or state occurs. Rremember that the sound symbol is the *second* argument to `ding', not the first. The following abstract sounds are used by XEmacs itself: alarm when a package wants to remind the user auto-save-error when an auto-save does not succeed buffer-bound when you attempt to move off the end of a buffer command-error any uncaught error (i.e. any error that the user sees) except those handled by undefined-click, undefined-key, buffer-bound, or read-only default used when nothing else is appropriate. isearch-failed unable to locate search text during incremental search isearch-quit when you delete chars past the beginning of the search text in isearch no-completion during completing-read quit when C-g is typed read-only when you try to modify a read-only buffer ready when a compile or other time-consuming task is done undefined-click when you use an undefined mouse-click combination undefined-key when you type a key that is undefined warp XEmacs has changed the selected-window or frame asynchronously -- e.g. a debugger breakpoint is hit in an asynchronous process filter y-or-n-p when you type something other than 'y' or 'n' yes-or-no-p when you type something other than 'yes' or 'no' Other lisp packages may use other beep types, but these are the ones that the C kernel of Emacs uses. */ (no_terminate, sound, device)) { static time_t last_bell_time; static struct device *last_bell_device; time_t now; struct device *d = decode_device (device); device = wrap_device (d); now = time (0); if (NILP (no_terminate) && !NILP (Vexecuting_macro)) /* Stop executing a keyboard macro. */ invalid_operation ("Keyboard macro terminated by a command ringing the bell", Qunbound); if (d == last_bell_device && now-last_bell_time < bell_inhibit_time) return Qnil; else if (!NILP (Vvisible_bell) && DEVMETH (d, flash, (d))) ; else Fplay_sound (sound, Qnil, device); last_bell_time = now; last_bell_device = d; return Qnil; } #ifdef HAVE_NAS_SOUND #define USED_IF_HAVE_NAS(decl) decl #else #define USED_IF_HAVE_NAS(decl) UNUSED (decl) #endif DEFUN ("wait-for-sounds", Fwait_for_sounds, 0, 1, 0, /* Wait for all sounds to finish playing on DEVICE. */ (USED_IF_HAVE_NAS (device))) { #ifdef HAVE_NAS_SOUND struct device *d = decode_device (device); if (DEVICE_CONNECTED_TO_NAS_P (d)) { /* #### somebody fix this to be device-dependent. */ nas_wait_for_sounds (); } #endif return Qnil; } DEFUN ("connected-to-nas-p", Fconnected_to_nas_p, 0, 1, 0, /* Return t if connected to NAS server for sounds on DEVICE. */ (USED_IF_HAVE_NAS (device))) { #ifdef HAVE_NAS_SOUND return DEVICE_CONNECTED_TO_NAS_P (decode_device (device)) ? Qt : Qnil; #else return Qnil; #endif } #ifdef HAVE_NAS_SOUND static void init_nas_sound (struct device *d) { #ifdef HAVE_X_WINDOWS if (DEVICE_X_P (d)) { Extbyte *err_message = nas_init_play (DEVICE_X_DISPLAY (d)); DEVICE_CONNECTED_TO_NAS_P (d) = !err_message; /* Print out the message? */ } #endif /* HAVE_X_WINDOWS */ } #endif /* HAVE_NAS_SOUND */ #ifdef HAVE_NATIVE_SOUND static void init_native_sound (struct device *d) { if (DEVICE_TTY_P (d) || DEVICE_STREAM_P (d) || DEVICE_MSWINDOWS_P(d)) DEVICE_ON_CONSOLE_P (d) = 1; #ifdef HAVE_X_WINDOWS else { /* When running on a machine with native sound support, we cannot use digitized sounds as beeps unless emacs is running on the same machine that $DISPLAY points to, and $DISPLAY points to frame 0 of that machine. */ Display *display = DEVICE_X_DISPLAY (d); Extbyte *dpy = DisplayString (display); Extbyte *tail = strchr (dpy, ':'); if (! tail || strncmp (tail, ":0", 2)) DEVICE_ON_CONSOLE_P (d) = 0; else { Extbyte dpyname[255], localname[255]; /* some systems can't handle SIGIO or SIGALARM in gethostbyname. */ stop_interrupts (); strncpy (dpyname, dpy, tail-dpy); dpyname [tail-dpy] = 0; if (!*dpyname || !strcmp (dpyname, "unix") || !strcmp (dpyname, "localhost")) DEVICE_ON_CONSOLE_P (d) = 1; else if (gethostname (localname, sizeof (localname))) DEVICE_ON_CONSOLE_P (d) = 0; /* can't find hostname? */ else { /* We have to call gethostbyname() on the result of gethostname() because the two aren't guaranteed to be the same name for the same host: on some losing systems, one is a FQDN and the other is not. Here in the wide wonderful world of Unix it's rocket science to obtain the local hostname in a portable fashion. And don't forget, gethostbyname() reuses the structure it returns, so we have to copy the fucker before calling it again. Thank you master, may I have another. */ struct hostent *h = gethostbyname (dpyname); if (!h) DEVICE_ON_CONSOLE_P (d) = 0; else { Extbyte hn [255]; struct hostent *l; strcpy (hn, h->h_name); l = gethostbyname (localname); DEVICE_ON_CONSOLE_P (d) = (l && !(strcmp (l->h_name, hn))); } } start_interrupts (); } } #endif /* HAVE_X_WINDOWS */ } #endif /* HAVE_NATIVE_SOUND */ void init_device_sound (struct device *d) { #ifdef HAVE_NAS_SOUND init_nas_sound (d); #endif #ifdef HAVE_NATIVE_SOUND init_native_sound (d); #endif } void syms_of_sound (void) { DEFKEYWORD (Q_volume); DEFKEYWORD (Q_pitch); DEFKEYWORD (Q_duration); DEFKEYWORD (Q_sound); DEFERROR_STANDARD (Qsound_error, Qio_error); DEFSUBR (Fplay_sound_file); DEFSUBR (Fplay_sound); DEFSUBR (Fding); DEFSUBR (Fwait_for_sounds); DEFSUBR (Fconnected_to_nas_p); DEFSUBR (Fdevice_sound_enabled_p); } void vars_of_sound (void) { #ifdef HAVE_NATIVE_SOUND Fprovide (intern ("native-sound")); #endif #ifdef HAVE_NAS_SOUND Fprovide (intern ("nas-sound")); #endif #ifdef HAVE_ESD_SOUND Fprovide (intern ("esd-sound")); #endif DEFVAR_INT ("bell-volume", &bell_volume /* *How loud to be, from 0 to 100. */ ); bell_volume = 50; DEFVAR_INT ("bell-inhibit-time", &bell_inhibit_time /* *Don't ring the bell on the same device more than once within this many seconds. */ ); bell_inhibit_time = 0; DEFVAR_LISP ("sound-alist", &Vsound_alist /* An alist associating names with sounds. When `beep' or `ding' is called with one of the name symbols, the associated sound will be generated instead of the standard beep. Each element of `sound-alist' is a list describing a sound. The first element of the list is the name of the sound being defined. Subsequent elements of the list are alternating keyword/value pairs: Keyword: Value: ------- ----- sound A string of raw sound data, or the name of another sound to play. The symbol `t' here means use the default X beep. volume An integer from 0-100, defaulting to `bell-volume' pitch If using the default X beep, the pitch (Hz) to generate. duration If using the default X beep, the duration (milliseconds). For compatibility, elements of `sound-alist' may also be: ( sound-name . <sound> ) ( sound-name <volume> <sound> ) You should probably add things to this list by calling the function load-sound-file. Caveats: - XEmacs must be built with sound support for your system. Not all systems support sound. - The pitch, duration, and volume options are available everywhere, but many X servers ignore the `pitch' option. Sound symbols that map directly to data should be considered named sounds; sound symbols that map to other sounds should be considered abstract sounds, and are used when a particular behavior or state occurs. See `ding' for a list of the standard abstract sounds. */ ); Vsound_alist = Qnil; DEFVAR_LISP ("synchronous-sounds", &Vsynchronous_sounds /* Play sounds synchronously, if non-nil. Only applies if NAS is used and supports asynchronous playing of sounds. Otherwise, sounds are always played synchronously. */ ); Vsynchronous_sounds = Qnil; DEFVAR_LISP ("native-sound-only-on-console", &Vnative_sound_only_on_console /* Non-nil value means play sounds only if XEmacs is running on the system console. Nil means always play sounds, even if running on a non-console tty or a secondary X display. This variable only applies to native sound support. */ ); Vnative_sound_only_on_console = Qt; #if defined (HAVE_NATIVE_SOUND) && defined (hp9000s800) { void vars_of_hpplay (void); vars_of_hpplay (); } #endif }