import -ko -b 1.1.3 XEmacs XEmacs-21_2 r21-2-35
[chise/xemacs-chise.git.1] / src / sound.c
index 9e000d4..550254e 100644 (file)
@@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA.  */
    Hacked on quite a bit by various others. */
 
 #include <config.h>
+#include <time.h>
 #include "lisp.h"
 
 #include "buffer.h"
@@ -32,30 +33,30 @@ Boston, MA 02111-1307, USA.  */
 #include "console-x.h"
 #endif
 
-#include "commands.h"
 #include "device.h"
 #include "redisplay.h"
 #include "sysdep.h"
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+#include "sysfile.h"
 
 #ifdef HAVE_NATIVE_SOUND
-# include <netdb.h>
+# include "sysproc.h"
+# include "nativesound.h"
+#endif
+
+#ifdef HAVE_ESD_SOUND
+extern int esd_play_sound_file (char *file, int vol);
+extern int esd_play_sound_data (unsigned char *data, size_t length, int vol);
+# define DEVICE_CONNECTED_TO_ESD_P(x) 1 /* FIXME: better check */
 #endif
 
 int bell_volume;
+int 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;
 
-/* These are defined in the appropriate file (sunplay.c, sgiplay.c,
-   or hpplay.c). */
-
-extern void play_sound_file (char *name, int volume);
-extern void play_sound_data (unsigned char *data, int length, int volume);
 
 #ifdef HAVE_NAS_SOUND
 extern int nas_play_sound_file (char *name, int volume);
@@ -69,15 +70,17 @@ Lisp_Object Qnas;
 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).
-The sound file must be in the Sun/NeXT U-LAW format except under Linux
-where WAV files are also supported.
+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)
+#if defined (HAVE_NATIVE_SOUND) || defined (HAVE_NAS_SOUND) \
+       || defined (HAVE_ESD_SOUND)
   struct device *d = decode_device (device);
 #endif
   struct gcpro gcpro1;
@@ -117,19 +120,42 @@ where WAV files are also supported.
     {
       char *fileext;
 
-      GET_C_STRING_FILENAME_DATA_ALLOCA (file, fileext);
+      TO_EXTERNAL_FORMAT (LISP_STRING, file,
+                         C_STRING_ALLOCA, 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))
+    {
+      char *fileext;
+      int result;
+
+      TO_EXTERNAL_FORMAT (LISP_STRING, file,
+                         C_STRING_ALLOCA, 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))
     {
-      CONST char *fileext;
+      const char *fileext;
 
-      GET_C_STRING_FILENAME_DATA_ALLOCA (file, fileext);
+      TO_EXTERNAL_FORMAT (LISP_STRING, file,
+                         C_STRING_ALLOCA, fileext,
+                         Qfile_name);
       /* The sound code doesn't like getting SIGIO interrupts.
         Unix sucks! */
       stop_interrupts ();
@@ -291,29 +317,55 @@ See the variable `sound-alist'.
 #ifdef HAVE_NAS_SOUND
   if (DEVICE_CONNECTED_TO_NAS_P (d) && STRINGP (sound))
     {
-      CONST Extbyte *soundext;
+      const Extbyte *soundext;
       Extcount soundextlen;
 
-      GET_STRING_BINARY_DATA_ALLOCA (sound, soundext, soundextlen);
+      TO_EXTERNAL_FORMAT (LISP_STRING, sound,
+                         ALLOCA, (soundext, soundextlen),
+                         Qbinary);
       if (nas_play_sound_data ((unsigned char*)soundext, soundextlen, vol))
        return Qnil;
     }
 #endif /* HAVE_NAS_SOUND */
 
+#ifdef HAVE_ESD_SOUND
+  if (DEVICE_CONNECTED_TO_ESD_P (d) && STRINGP (sound))
+    {
+      Extbyte *soundext;
+      Extcount 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))
     {
-      CONST Extbyte *soundext;
+      const Extbyte *soundext;
       Extcount soundextlen;
+      int succes;
 
-      GET_STRING_BINARY_DATA_ALLOCA (sound, soundext, soundextlen);
+      TO_EXTERNAL_FORMAT (LISP_STRING, sound,
+                         ALLOCA, (soundext, soundextlen),
+                         Qbinary);
       /* The sound code doesn't like getting SIGIO interrupts. Unix sucks! */
       stop_interrupts ();
-      play_sound_data ((unsigned char*)soundext, soundextlen, vol);
+      succes = play_sound_data ((unsigned char*)soundext, soundextlen, vol);
       start_interrupts ();
       QUIT;
-      return Qnil;
+      if (succes)
+        return Qnil;
     }
 #endif  /* HAVE_NATIVE_SOUND */
 
@@ -326,14 +378,12 @@ Return t if DEVICE is able to play sound.  Defaults to selected device.
 */
        (device))
 {
-  struct device *d = decode_device(device);
-
 #ifdef HAVE_NAS_SOUND
-  if (DEVICE_CONNECTED_TO_NAS_P (d))
+  if (DEVICE_CONNECTED_TO_NAS_P (decode_device (device)))
     return Qt;
 #endif
 #ifdef HAVE_NATIVE_SOUND
-  if (DEVICE_ON_CONSOLE_P (d))
+  if (DEVICE_ON_CONSOLE_P (decode_device (device)))
     return Qt;
 #endif
   return Qnil;
@@ -349,25 +399,28 @@ device).
 */
        (arg, sound, device))
 {
-  struct device *d = decode_device (device);
+  static time_t last_bell_time;
+  static struct device *last_bell_device;
+  time_t now;
+  struct device *d = decode_device (device);     
 
   XSETDEVICE (device, d);
+  now = time (0);
 
-  /* #### This is utterly disgusting, and is probably a remnant from
-     legacy code that used `ding'+`message' to signal error instead
-     calling `error'.  As a result, there is no way to beep from Lisp
-     directly, without also invoking this aspect.  Maybe we should
-     define a `ring-bell' function that simply beeps on the console,
-     which `ding' should invoke?  --hniksic */
   if (NILP (arg) && !NILP (Vexecuting_macro))
     /* Stop executing a keyboard macro. */
     error ("Keyboard macro terminated by a command ringing the bell");
-  else if (visible_bell && DEVMETH (d, flash, (d)))
+  
+  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);
-
-  return Qnil;
+  
+  last_bell_time = now;
+  last_bell_device = d;
+  return Qnil;    
 }
 
 DEFUN ("wait-for-sounds", Fwait_for_sounds, 0, 1, 0, /*
@@ -403,13 +456,11 @@ Return t if connected to NAS server for sounds on DEVICE.
 static void
 init_nas_sound (struct device *d)
 {
-  char *error;
-
 #ifdef HAVE_X_WINDOWS
   if (DEVICE_X_P (d))
     {
-      error = nas_init_play (DEVICE_X_DISPLAY (d));
-      DEVICE_CONNECTED_TO_NAS_P (d) = !error;
+      char *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 */
@@ -456,7 +507,7 @@ init_native_sound (struct device *d)
          else
            {
              /* We have to call gethostbyname() on the result of gethostname()
-                because the two aren't guarenteed to be the same name for the
+                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.
@@ -529,11 +580,19 @@ vars_of_sound (void)
 #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.
@@ -561,8 +620,8 @@ You should probably add things to this list by calling the function
 load-sound-file.
 
 Caveats:
- - You can only play audio data if running on the console screen of a
-   Sun SparcStation, SGI, or HP9000s700.
+ - 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.