/[emacs]/emacs/src/sound.c
ViewVC logotype

Diff of /emacs/src/sound.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.25 by monnier, Tue Apr 30 01:01:49 2002 UTC revision 1.25.2.1 by miles, Fri Apr 4 06:21:03 2003 UTC
# Line 21  Boston, MA 02111-1307, USA.  */ Line 21  Boston, MA 02111-1307, USA.  */
21  /* Written by Gerd Moellmann <gerd@gnu.org>.  Tested with Luigi's  /* Written by Gerd Moellmann <gerd@gnu.org>.  Tested with Luigi's
22     driver on FreeBSD 2.2.7 with a SoundBlaster 16.  */     driver on FreeBSD 2.2.7 with a SoundBlaster 16.  */
23    
24    /*
25      Modified by Ben Key <Bkey1@tampabay.rr.com> to add a partial
26      implementation of the play-sound specification for Windows.
27    
28      Notes:
29      In the Windows implementation of play-sound-internal only the
30      :file and :volume keywords are supported.  The :device keyword,
31      if present, is ignored.  The :data keyword, if present, will
32      cause an error to be generated.
33    
34      The Windows implementation of play-sound is implemented via the
35      Win32 API functions mciSendString, waveOutGetVolume, and
36      waveOutSetVolume which are exported by Winmm.dll.
37    */
38    
39  #include <config.h>  #include <config.h>
40    
41  #if defined HAVE_SOUND  #if defined HAVE_SOUND
42    
43    /* BEGIN: Common Includes */
44  #include <fcntl.h>  #include <fcntl.h>
45  #include <unistd.h>  #include <unistd.h>
46  #include <sys/types.h>  #include <sys/types.h>
# Line 34  Boston, MA 02111-1307, USA.  */ Line 50  Boston, MA 02111-1307, USA.  */
50  #include "atimer.h"  #include "atimer.h"
51  #include <signal.h>  #include <signal.h>
52  #include "syssignal.h"  #include "syssignal.h"
53    /* END: Common Includes */
54    
55    
56    /* BEGIN: Non Windows Includes */
57    #ifndef WINDOWSNT
58    
59  #ifndef MSDOS  #ifndef MSDOS
60  #include <sys/ioctl.h>  #include <sys/ioctl.h>
# Line 51  Boston, MA 02111-1307, USA.  */ Line 72  Boston, MA 02111-1307, USA.  */
72  #ifdef HAVE_SOUNDCARD_H  #ifdef HAVE_SOUNDCARD_H
73  #include <soundcard.h>  #include <soundcard.h>
74  #endif  #endif
75    /* END: Non Windows Includes */
76    
77    #else /* WINDOWSNT */
78    
79    /* BEGIN: Windows Specific Includes */
80    #include <stdio.h>
81    #include <stdlib.h>
82    #include <string.h>
83    #include <limits.h>
84    #include <windows.h>
85    #include <mmsystem.h>
86    /* END: Windows Specific Includes */
87    
88    #endif /* WINDOWSNT */
89    
90    /* BEGIN: Common Definitions */
91    #define abs(X)    ((X) < 0 ? -(X) : (X))
92    
93    /* Symbols.  */
94    
95    extern Lisp_Object QCfile, QCdata;
96    Lisp_Object QCvolume, QCdevice;
97    Lisp_Object Qsound;
98    Lisp_Object Qplay_sound_functions;
99    
100    /* Indices of attributes in a sound attributes vector.  */
101    
102    enum sound_attr
103    {
104      SOUND_FILE,
105      SOUND_DATA,
106      SOUND_DEVICE,
107      SOUND_VOLUME,
108      SOUND_ATTR_SENTINEL
109    };
110    
111    static void sound_perror P_ ((char *));
112    static void sound_warning P_ ((char *));
113    static int parse_sound P_ ((Lisp_Object, Lisp_Object *));
114    
115    /* END: Common Definitions */
116    
117    /* BEGIN: Non Windows Definitions */
118    #ifndef WINDOWSNT
119    
120  #ifndef DEFAULT_SOUND_DEVICE  #ifndef DEFAULT_SOUND_DEVICE
121  #define DEFAULT_SOUND_DEVICE "/dev/dsp"  #define DEFAULT_SOUND_DEVICE "/dev/dsp"
122  #endif  #endif
123    
 #define abs(X)    ((X) < 0 ? -(X) : (X))  
124    
125  /* Structure forward declarations.  */  /* Structure forward declarations.  */
126    
# Line 163  struct sound_device Line 227  struct sound_device
227                                struct sound *s));                                struct sound *s));
228    
229    /* Write NYBTES bytes from BUFFER to device SD.  */    /* Write NYBTES bytes from BUFFER to device SD.  */
230    void (* write) P_ ((struct sound_device *sd, char *buffer, int nbytes));    void (* write) P_ ((struct sound_device *sd, const char *buffer,
231                          int nbytes));
232    
233    /* A place for devices to store additional data.  */    /* A place for devices to store additional data.  */
234    void *data;    void *data;
# Line 202  struct sound Line 267  struct sound
267    void (* play) P_ ((struct sound *s, struct sound_device *sd));    void (* play) P_ ((struct sound *s, struct sound_device *sd));
268  };  };
269    
 /* Indices of attributes in a sound attributes vector.  */  
   
 enum sound_attr  
 {  
   SOUND_FILE,  
   SOUND_DATA,  
   SOUND_DEVICE,  
   SOUND_VOLUME,  
   SOUND_ATTR_SENTINEL  
 };  
   
 /* Symbols.  */  
   
 extern Lisp_Object QCfile, QCdata;  
 Lisp_Object QCvolume, QCdevice;  
 Lisp_Object Qsound;  
 Lisp_Object Qplay_sound_functions;  
   
270  /* These are set during `play-sound-internal' so that sound_cleanup has  /* These are set during `play-sound-internal' so that sound_cleanup has
271     access to them.  */     access to them.  */
272    
# Line 233  static void vox_configure P_ ((struct so Line 280  static void vox_configure P_ ((struct so
280  static void vox_close P_ ((struct sound_device *sd));  static void vox_close P_ ((struct sound_device *sd));
281  static void vox_choose_format P_ ((struct sound_device *, struct sound *));  static void vox_choose_format P_ ((struct sound_device *, struct sound *));
282  static void vox_init P_ ((struct sound_device *));  static void vox_init P_ ((struct sound_device *));
283  static void vox_write P_ ((struct sound_device *, char *, int));  static void vox_write P_ ((struct sound_device *, const char *, int));
 static void sound_perror P_ ((char *));  
 static void sound_warning P_ ((char *));  
 static int parse_sound P_ ((Lisp_Object, Lisp_Object *));  
284  static void find_sound_type P_ ((struct sound *));  static void find_sound_type P_ ((struct sound *));
285  static u_int32_t le2hl P_ ((u_int32_t));  static u_int32_t le2hl P_ ((u_int32_t));
286  static u_int16_t le2hs P_ ((u_int16_t));  static u_int16_t le2hs P_ ((u_int16_t));
# Line 250  static void au_play P_ ((struct sound *, Line 294  static void au_play P_ ((struct sound *,
294  static u_int16_t be2hs P_ ((u_int16_t));  static u_int16_t be2hs P_ ((u_int16_t));
295  #endif  #endif
296    
297    /* END: Non Windows Definitions */
298    #else /* WINDOWSNT */
299    
300    /* BEGIN: Windows Specific Definitions */
301    static int do_play_sound P_ ((const char *, unsigned long));
302    /*
303      END: Windows Specific Definitions */
304    #endif /* WINDOWSNT */
305    
306    
307  /***********************************************************************  /***********************************************************************
308                                 General                                 General
309   ***********************************************************************/   ***********************************************************************/
310    
311    /* BEGIN: Common functions */
312    
313  /* Like perror, but signals an error.  */  /* Like perror, but signals an error.  */
314    
315  static void  static void
# Line 326  parse_sound (sound, attrs) Line 380  parse_sound (sound, attrs)
380    attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);    attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice);
381    attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);    attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume);
382    
383    #ifndef WINDOWSNT
384    /* File name or data must be specified.  */    /* File name or data must be specified.  */
385    if (!STRINGP (attrs[SOUND_FILE])    if (!STRINGP (attrs[SOUND_FILE])
386        && !STRINGP (attrs[SOUND_DATA]))        && !STRINGP (attrs[SOUND_DATA]))
387      return 0;      return 0;
388    #else /* WINDOWSNT */
389      /*
390        Data is not supported in Windows.  Therefore a
391        File name MUST be supplied.
392      */
393      if (!STRINGP (attrs[SOUND_FILE]))
394        {
395          return 0;
396        }
397    #endif /* WINDOWSNT */
398    
399    /* Volume must be in the range 0..100 or unspecified.  */    /* Volume must be in the range 0..100 or unspecified.  */
400    if (!NILP (attrs[SOUND_VOLUME]))    if (!NILP (attrs[SOUND_VOLUME]))
# Line 350  parse_sound (sound, attrs) Line 415  parse_sound (sound, attrs)
415          return 0;          return 0;
416      }      }
417    
418    #ifndef WINDOWSNT
419    /* Device must be a string or unspecified.  */    /* Device must be a string or unspecified.  */
420    if (!NILP (attrs[SOUND_DEVICE])    if (!NILP (attrs[SOUND_DEVICE])
421        && !STRINGP (attrs[SOUND_DEVICE]))        && !STRINGP (attrs[SOUND_DEVICE]))
422      return 0;      return 0;
423    #endif  /* WINDOWSNT */
424      /*
425        Since device is ignored in Windows, it does not matter
426        what it is.
427       */
428    return 1;    return 1;
429  }  }
430    
431    /* END: Common functions */
432    
433    /* BEGIN: Non Windows functions */
434    #ifndef WINDOWSNT
435    
436  /* Find out the type of the sound file whose file descriptor is FD.  /* Find out the type of the sound file whose file descriptor is FD.
437     S is the sound file structure to fill in.  */     S is the sound file structure to fill in.  */
# Line 388  sound_cleanup (arg) Line 462  sound_cleanup (arg)
462    return Qnil;    return Qnil;
463  }  }
464    
   
 DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,  
        doc: /* Play sound SOUND.  
   
 Internal use only, use `play-sound' instead.  */)  
      (sound)  
      Lisp_Object sound;  
 {  
   Lisp_Object attrs[SOUND_ATTR_SENTINEL];  
   Lisp_Object file;  
   struct gcpro gcpro1, gcpro2;  
   struct sound_device sd;  
   struct sound s;  
   Lisp_Object args[2];  
   int count = specpdl_ptr - specpdl;  
   
   file = Qnil;  
   GCPRO2 (sound, file);  
   bzero (&sd, sizeof sd);  
   bzero (&s, sizeof s);  
   current_sound_device = &sd;  
   current_sound = &s;  
   record_unwind_protect (sound_cleanup, Qnil);  
   s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);  
   
   /* Parse the sound specification.  Give up if it is invalid.  */  
   if (!parse_sound (sound, attrs))  
     error ("Invalid sound specification");  
   
   if (STRINGP (attrs[SOUND_FILE]))  
     {  
       /* Open the sound file.  */  
       s.fd = openp (Fcons (Vdata_directory, Qnil),  
                     attrs[SOUND_FILE], Qnil, &file, Qnil);  
       if (s.fd < 0)  
         sound_perror ("Could not open sound file");  
   
       /* Read the first bytes from the file.  */  
       s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES);  
       if (s.header_size < 0)  
         sound_perror ("Invalid sound file header");  
     }  
   else  
     {  
       s.data = attrs[SOUND_DATA];  
       s.header_size = min (MAX_SOUND_HEADER_BYTES, STRING_BYTES (XSTRING (s.data)));  
       bcopy (XSTRING (s.data)->data, s.header, s.header_size);  
     }  
   
   /* Find out the type of sound.  Give up if we can't tell.  */  
   find_sound_type (&s);  
   
   /* Set up a device.  */  
   if (STRINGP (attrs[SOUND_DEVICE]))  
     {  
       int len = XSTRING (attrs[SOUND_DEVICE])->size;  
       sd.file = (char *) alloca (len + 1);  
       strcpy (sd.file, XSTRING (attrs[SOUND_DEVICE])->data);  
     }  
   
   if (INTEGERP (attrs[SOUND_VOLUME]))  
     sd.volume = XFASTINT (attrs[SOUND_VOLUME]);  
   else if (FLOATP (attrs[SOUND_VOLUME]))  
     sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;  
   
   args[0] = Qplay_sound_functions;  
   args[1] = sound;  
   Frun_hook_with_args (2, args);  
   
   /* There is only one type of device we currently support, the VOX  
      sound driver.  Set up the device interface functions for that  
      device.  */  
   vox_init (&sd);  
   
   /* Open the device.  */  
   sd.open (&sd);  
   
   /* Play the sound.  */  
   s.play (&s, &sd);  
   
   /* Close the input file, if any.  */  
   if (!STRINGP (s.data))  
     {  
       emacs_close (s.fd);  
       s.fd = -1;  
     }  
   
   /* Close the device.  */  
   sd.close (&sd);  
   
   /* Clean up.  */  
   current_sound_device = NULL;  
   current_sound = NULL;  
   UNGCPRO;  
   unbind_to (count, Qnil);  
   return Qnil;  
 }  
   
   
465  /***********************************************************************  /***********************************************************************
466                          Byte-order Conversion                          Byte-order Conversion
467   ***********************************************************************/   ***********************************************************************/
# Line 554  be2hs (value) Line 529  be2hs (value)
529    
530  #endif /* 0 */  #endif /* 0 */
531    
   
532  /***********************************************************************  /***********************************************************************
533                            RIFF-WAVE (*.wav)                            RIFF-WAVE (*.wav)
534   ***********************************************************************/   ***********************************************************************/
# Line 624  wav_play (s, sd) Line 598  wav_play (s, sd)
598       files I found so far.  If someone feels inclined to implement the       files I found so far.  If someone feels inclined to implement the
599       whole RIFF-WAVE spec, please do.  */       whole RIFF-WAVE spec, please do.  */
600    if (STRINGP (s->data))    if (STRINGP (s->data))
601      sd->write (sd, XSTRING (s->data)->data + sizeof *header,      sd->write (sd, SDATA (s->data) + sizeof *header,
602                 STRING_BYTES (XSTRING (s->data)) - sizeof *header);                 SBYTES (s->data) - sizeof *header);
603    else    else
604      {      {
605        char *buffer;        char *buffer;
# Line 644  wav_play (s, sd) Line 618  wav_play (s, sd)
618  }  }
619    
620    
   
621  /***********************************************************************  /***********************************************************************
622                             Sun Audio (*.au)                             Sun Audio (*.au)
623   ***********************************************************************/   ***********************************************************************/
# Line 712  au_play (s, sd) Line 685  au_play (s, sd)
685    sd->configure (sd);    sd->configure (sd);
686    
687    if (STRINGP (s->data))    if (STRINGP (s->data))
688      sd->write (sd, XSTRING (s->data)->data + header->data_offset,      sd->write (sd, SDATA (s->data) + header->data_offset,
689                 STRING_BYTES (XSTRING (s->data)) - header->data_offset);                 SBYTES (s->data) - header->data_offset);
690    else    else
691      {      {
692        int blksize = 2048;        int blksize = 2048;
# Line 734  au_play (s, sd) Line 707  au_play (s, sd)
707  }  }
708    
709    
   
710  /***********************************************************************  /***********************************************************************
711                         Voxware Driver Interface                         Voxware Driver Interface
712   ***********************************************************************/   ***********************************************************************/
# Line 908  vox_init (sd) Line 880  vox_init (sd)
880    sd->write = vox_write;    sd->write = vox_write;
881  }  }
882    
   
883  /* Write NBYTES bytes from BUFFER to device SD.  */  /* Write NBYTES bytes from BUFFER to device SD.  */
884    
885  static void  static void
886  vox_write (sd, buffer, nbytes)  vox_write (sd, buffer, nbytes)
887       struct sound_device *sd;       struct sound_device *sd;
888       char *buffer;       const char *buffer;
889       int nbytes;       int nbytes;
890  {  {
891    int nwritten = emacs_write (sd->fd, buffer, nbytes);    int nwritten = emacs_write (sd->fd, buffer, nbytes);
# Line 922  vox_write (sd, buffer, nbytes) Line 893  vox_write (sd, buffer, nbytes)
893      sound_perror ("Error writing to sound device");      sound_perror ("Error writing to sound device");
894  }  }
895    
896    /* END: Non Windows functions */
897    #else /* WINDOWSNT */
898    
899    /* BEGIN: Windows specific functions */
900    
901    static int
902    do_play_sound (psz_file, ui_volume)
903         const char *psz_file;
904         unsigned long ui_volume;
905    {
906      int i_result = 0;
907      MCIERROR mci_error = 0;
908      char sz_cmd_buf[520] = {0};
909      char sz_ret_buf[520] = {0};
910      MMRESULT mm_result = MMSYSERR_NOERROR;
911      unsigned long ui_volume_org = 0;
912      BOOL b_reset_volume = FALSE;
913    
914      memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
915      memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
916      sprintf (sz_cmd_buf,
917               "open \"%s\" alias GNUEmacs_PlaySound_Device wait",
918               psz_file);
919      mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
920      if (mci_error != 0)
921        {
922          sound_warning ("The open mciSendString command failed to open\n"
923                         "the specified sound file");
924          i_result = (int) mci_error;
925          return i_result;
926        }
927      if ((ui_volume > 0) && (ui_volume != UINT_MAX))
928        {
929          mm_result = waveOutGetVolume ((HWAVEOUT) WAVE_MAPPER, &ui_volume_org);
930          if (mm_result == MMSYSERR_NOERROR)
931            {
932              b_reset_volume = TRUE;
933              mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume);
934              if ( mm_result != MMSYSERR_NOERROR)
935                {
936                  sound_warning ("waveOutSetVolume failed to set the volume level\n"
937                                 "of the WAVE_MAPPER device.\n"
938                                 "As a result, the user selected volume level will\n"
939                                 "not be used.");
940                }
941            }
942          else
943            {
944              sound_warning ("waveOutGetVolume failed to obtain the original\n"
945                             "volume level of the WAVE_MAPPER device.\n"
946                             "As a result, the user selected volume level will\n"
947                             "not be used.");
948            }
949        }
950      memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
951      memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
952      strcpy (sz_cmd_buf, "play GNUEmacs_PlaySound_Device wait");
953      mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
954      if (mci_error != 0)
955        {
956          sound_warning ("The play mciSendString command failed to play the\n"
957                         "opened sound file.");
958          i_result = (int) mci_error;
959        }
960      memset (sz_cmd_buf, 0, sizeof(sz_cmd_buf));
961      memset (sz_ret_buf, 0, sizeof(sz_ret_buf));
962      strcpy (sz_cmd_buf, "close GNUEmacs_PlaySound_Device wait");
963      mci_error = mciSendString (sz_cmd_buf, sz_ret_buf, 520, NULL);
964      if (b_reset_volume == TRUE)
965        {
966          mm_result=waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume_org);
967          if (mm_result != MMSYSERR_NOERROR)
968            {
969              sound_warning ("waveOutSetVolume failed to reset the original volume\n"
970                             "level of the WAVE_MAPPER device.");
971            }
972        }
973      return i_result;
974    }
975    
976    /* END: Windows specific functions */
977    
978    #endif /* WINDOWSNT */
979    
980    DEFUN ("play-sound-internal", Fplay_sound_internal, Splay_sound_internal, 1, 1, 0,
981           doc: /* Play sound SOUND.
982    
983    Internal use only, use `play-sound' instead.\n  */)
984         (sound)
985         Lisp_Object sound;
986    {
987      Lisp_Object attrs[SOUND_ATTR_SENTINEL];
988      int count = SPECPDL_INDEX ();
989    
990    #ifndef WINDOWSNT
991      Lisp_Object file;
992      struct gcpro gcpro1, gcpro2;
993      struct sound_device sd;
994      struct sound s;
995      Lisp_Object args[2];
996    #else /* WINDOWSNT */
997      int len = 0;
998      Lisp_Object lo_file = {0};
999      char * psz_file = NULL;
1000      unsigned long ui_volume_tmp = UINT_MAX;
1001      unsigned long ui_volume = UINT_MAX;
1002      int i_result = 0;
1003    #endif /* WINDOWSNT */
1004    
1005      /* Parse the sound specification.  Give up if it is invalid.  */
1006      if (!parse_sound (sound, attrs))
1007        error ("Invalid sound specification");
1008    
1009    #ifndef WINDOWSNT
1010      file = Qnil;
1011      GCPRO2 (sound, file);
1012      bzero (&sd, sizeof sd);
1013      bzero (&s, sizeof s);
1014      current_sound_device = &sd;
1015      current_sound = &s;
1016      record_unwind_protect (sound_cleanup, Qnil);
1017      s.header = (char *) alloca (MAX_SOUND_HEADER_BYTES);
1018    
1019      if (STRINGP (attrs[SOUND_FILE]))
1020        {
1021          /* Open the sound file.  */
1022          s.fd = openp (Fcons (Vdata_directory, Qnil),
1023                        attrs[SOUND_FILE], Qnil, &file, Qnil);
1024          if (s.fd < 0)
1025            sound_perror ("Could not open sound file");
1026    
1027          /* Read the first bytes from the file.  */
1028          s.header_size = emacs_read (s.fd, s.header, MAX_SOUND_HEADER_BYTES);
1029          if (s.header_size < 0)
1030            sound_perror ("Invalid sound file header");
1031        }
1032      else
1033        {
1034          s.data = attrs[SOUND_DATA];
1035          s.header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (s.data));
1036          bcopy (SDATA (s.data), s.header, s.header_size);
1037        }
1038    
1039      /* Find out the type of sound.  Give up if we can't tell.  */
1040      find_sound_type (&s);
1041    
1042      /* Set up a device.  */
1043      if (STRINGP (attrs[SOUND_DEVICE]))
1044        {
1045          int len = SCHARS (attrs[SOUND_DEVICE]);
1046          sd.file = (char *) alloca (len + 1);
1047          strcpy (sd.file, SDATA (attrs[SOUND_DEVICE]));
1048        }
1049    
1050      if (INTEGERP (attrs[SOUND_VOLUME]))
1051        sd.volume = XFASTINT (attrs[SOUND_VOLUME]);
1052      else if (FLOATP (attrs[SOUND_VOLUME]))
1053        sd.volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
1054    
1055      args[0] = Qplay_sound_functions;
1056      args[1] = sound;
1057      Frun_hook_with_args (2, args);
1058    
1059      /* There is only one type of device we currently support, the VOX
1060         sound driver.  Set up the device interface functions for that
1061         device.  */
1062      vox_init (&sd);
1063    
1064      /* Open the device.  */
1065      sd.open (&sd);
1066    
1067      /* Play the sound.  */
1068      s.play (&s, &sd);
1069    
1070      /* Close the input file, if any.  */
1071      if (!STRINGP (s.data))
1072        {
1073          emacs_close (s.fd);
1074          s.fd = -1;
1075        }
1076    
1077      /* Close the device.  */
1078      sd.close (&sd);
1079    
1080      /* Clean up.  */
1081      current_sound_device = NULL;
1082      current_sound = NULL;
1083      UNGCPRO;
1084    
1085    #else /* WINDOWSNT */
1086    
1087      lo_file = Fexpand_file_name (attrs[SOUND_FILE], Qnil);
1088      len = XSTRING (lo_file)->size;
1089      psz_file = (char *) alloca (len + 1);
1090      strcpy (psz_file, XSTRING (lo_file)->data);
1091      if (INTEGERP (attrs[SOUND_VOLUME]))
1092        {
1093          ui_volume_tmp = XFASTINT (attrs[SOUND_VOLUME]);
1094        }
1095      else if (FLOATP (attrs[SOUND_VOLUME]))
1096        {
1097          ui_volume_tmp = (unsigned long) XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
1098        }
1099      /*
1100        Based on some experiments I have conducted, a value of 100 or less
1101        for the sound volume is much too low.  You cannot even hear it.
1102        A value of UINT_MAX indicates that you wish for the sound to played
1103        at the maximum possible volume.  A value of UINT_MAX/2 plays the
1104        sound at 50% maximum volume.  Therefore the value passed to do_play_sound
1105        (and thus to waveOutSetVolume) must be some fraction of UINT_MAX.
1106        The following code adjusts the user specified volume level appropriately.
1107      */
1108      if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100))
1109        {
1110          ui_volume = ui_volume_tmp * (UINT_MAX / 100);
1111        }
1112      i_result = do_play_sound (psz_file, ui_volume);
1113    
1114    #endif /* WINDOWSNT */
1115    
1116      unbind_to (count, Qnil);
1117      return Qnil;
1118    }
1119    
1120  /***********************************************************************  /***********************************************************************
1121                              Initialization                              Initialization

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.25.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26