Function: play-sound-internal

play-sound-internal is a function defined in sound.c.

Signature

(play-sound-internal SOUND)

Documentation

Play sound SOUND.

Internal use only, use play-sound instead.

Source Code

// Defined in /usr/src/emacs/src/sound.c
{
  Lisp_Object attrs[SOUND_ATTR_SENTINEL];
  specpdl_ref count = SPECPDL_INDEX ();

#ifdef WINDOWSNT
  unsigned long ui_volume_tmp = UINT_MAX;
  unsigned long ui_volume = UINT_MAX;
#endif /* WINDOWSNT */

  /* Parse the sound specification.  Give up if it is invalid.  */
  if (!parse_sound (sound, attrs))
    error ("Invalid sound specification");

  Lisp_Object file = Qnil;

#ifndef WINDOWSNT
  current_sound_device = xzalloc (sizeof *current_sound_device);
  current_sound = xzalloc (sizeof *current_sound);
  record_unwind_protect_void (sound_cleanup);
  char headerbuf[MAX_SOUND_HEADER_BYTES];
  current_sound->header = headerbuf;

  if (STRINGP (attrs[SOUND_FILE]))
    {
      /* Open the sound file.  */
      current_sound->fd =
	openp (list1 (Vdata_directory), attrs[SOUND_FILE], Qnil, &file, Qnil,
	       false, false, NULL);
      if (current_sound->fd < 0)
	sound_perror ("Could not open sound file");

      /* Read the first bytes from the file.  */
      current_sound->header_size
	= emacs_read (current_sound->fd, current_sound->header,
		      MAX_SOUND_HEADER_BYTES);
      if (current_sound->header_size < 0)
	sound_perror ("Invalid sound file header");
    }
  else
    {
      current_sound->data = attrs[SOUND_DATA];
      current_sound->header_size = min (MAX_SOUND_HEADER_BYTES, SBYTES (current_sound->data));
      memcpy (current_sound->header, SDATA (current_sound->data),
	      current_sound->header_size);
    }

  /* Find out the type of sound.  Give up if we can't tell.  */
  find_sound_type (current_sound);

  /* Set up a device.  */
  current_sound_device->file = attrs[SOUND_DEVICE];

  if (FIXNUMP (attrs[SOUND_VOLUME]))
    current_sound_device->volume = XFIXNAT (attrs[SOUND_VOLUME]);
  else if (FLOATP (attrs[SOUND_VOLUME]))
    current_sound_device->volume = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;

  CALLN (Frun_hook_with_args, Qplay_sound_functions, sound);

#ifdef HAVE_ALSA
  if (!alsa_init (current_sound_device))
#endif
    if (!vox_init (current_sound_device))
      error ("No usable sound device driver found");

  /* Open the device.  */
  current_sound_device->open (current_sound_device);

  /* Play the sound.  */
  current_sound->play (current_sound, current_sound_device);

#else /* WINDOWSNT */

  file = Fexpand_file_name (attrs[SOUND_FILE], Vdata_directory);
  file = ENCODE_FILE (file);
  if (FIXNUMP (attrs[SOUND_VOLUME]))
    {
      ui_volume_tmp = XFIXNAT (attrs[SOUND_VOLUME]);
    }
  else if (FLOATP (attrs[SOUND_VOLUME]))
    {
      ui_volume_tmp = XFLOAT_DATA (attrs[SOUND_VOLUME]) * 100;
    }

  CALLN (Frun_hook_with_args, Qplay_sound_functions, sound);

  /*
    Based on some experiments I have conducted, a value of 100 or less
    for the sound volume is much too low.  You cannot even hear it.
    A value of UINT_MAX indicates that you wish for the sound to played
    at the maximum possible volume.  A value of UINT_MAX/2 plays the
    sound at 50% maximum volume.  Therefore the value passed to do_play_sound
    (and thus to waveOutSetVolume) must be some fraction of UINT_MAX.
    The following code adjusts the user specified volume level appropriately.
  */
  if ((ui_volume_tmp > 0) && (ui_volume_tmp <= 100))
    {
      ui_volume = ui_volume_tmp * (UINT_MAX / 100);
    }
  (void)do_play_sound (SSDATA (file), ui_volume);

#endif /* WINDOWSNT */

  return unbind_to (count, Qnil);
}