view src/sunplay.c @ 5050:6f2158fa75ed

Fix quick-build, use asserts() in place of ABORT() -------------------- ChangeLog entries follow: -------------------- ChangeLog addition: 2010-02-20 Ben Wing <ben@xemacs.org> * configure.ac (XE_COMPLEX_ARG): Correct doc of --quick-build: It also doesn't check for Lisp shadows. src/ChangeLog addition: 2010-02-20 Ben Wing <ben@xemacs.org> * EmacsFrame.c: * EmacsFrame.c (EmacsFrameRecomputeCellSize): * alloca.c (i00afunc): * buffer.c: * buffer.c (MARKED_SLOT): * buffer.c (complex_vars_of_buffer): * cm.c: * cm.c (cmcheckmagic): * console.c: * console.c (MARKED_SLOT): * device-x.c: * device-x.c (x_get_visual_depth): * emacs.c (sort_args): * eval.c (throw_or_bomb_out): * event-stream.c: * event-stream.c (Fadd_timeout): * event-stream.c (Fadd_async_timeout): * event-stream.c (Frecent_keys): * events.c: * events.c (Fdeallocate_event): * events.c (event_pixel_translation): * extents.c: * extents.c (process_extents_for_insertion_mapper): * fns.c (Fbase64_encode_region): * fns.c (Fbase64_encode_string): * fns.c (Fbase64_decode_region): * fns.c (Fbase64_decode_string): * font-lock.c: * font-lock.c (find_context): * frame-x.c: * frame-x.c (x_wm_mark_shell_size_user_specified): * frame-x.c (x_wm_mark_shell_position_user_specified): * frame-x.c (x_wm_set_shell_iconic_p): * frame-x.c (x_wm_set_cell_size): * frame-x.c (x_wm_set_variable_size): * frame-x.c (x_wm_store_class_hints): * frame-x.c (x_wm_maybe_store_wm_command): * frame-x.c (x_initialize_frame_size): * frame.c (delete_frame_internal): * frame.c (change_frame_size_1): * free-hook.c (check_free): * free-hook.c (note_block_input): * free-hook.c (log_gcpro): * gccache-gtk.c (gc_cache_lookup): * gccache-x.c: * gccache-x.c (gc_cache_lookup): * glyphs-gtk.c: * glyphs-gtk.c (init_image_instance_from_gdk_pixmap): * glyphs-x.c: * glyphs-x.c (extract_xpm_color_names): * insdel.c: * insdel.c (move_gap): * keymap.c: * keymap.c (keymap_lookup_directly): * keymap.c (keymap_delete_inverse_internal): * keymap.c (accessible_keymaps_mapper_1): * keymap.c (where_is_recursive_mapper): * lisp.h: * lstream.c (make_lisp_buffer_stream_1): * macros.c: * macros.c (pop_kbd_macro_event): * mc-alloc.c (remove_page_from_used_list): * menubar-x.c: * menubar-x.c (set_frame_menubar): * ralloc.c: * ralloc.c (obtain): * ralloc.c (relinquish): * ralloc.c (relocate_blocs): * ralloc.c (resize_bloc): * ralloc.c (r_alloc_free): * ralloc.c (r_re_alloc): * ralloc.c (r_alloc_thaw): * ralloc.c (init_ralloc): * ralloc.c (Free_Addr_Block): * scrollbar-x.c: * scrollbar-x.c (x_update_scrollbar_instance_status): * sunplay.c (init_device): * unexnt.c: * unexnt.c (read_in_bss): * unexnt.c (map_in_heap): * window.c: * window.c (real_window): * window.c (window_display_lines): * window.c (window_display_buffer): * window.c (set_window_display_buffer): * window.c (unshow_buffer): * window.c (Fget_lru_window): if (...) ABORT(); ---> assert(); More specifically: if (x == y) ABORT (); --> assert (x != y); if (x != y) ABORT (); --> assert (x == y); if (x > y) ABORT (); --> assert (x <= y); etc. if (!x) ABORT (); --> assert (x); if (x) ABORT (); --> assert (!x); DeMorgan's Law's applied and manually simplified: if (x && !y) ABORT (); --> assert (!x || y); if (!x || y >= z) ABORT (); --> assert (x && y < z); Checked to make sure that assert() of an expression with side effects ensures that the side effects get executed even when asserts are disabled, and add a comment about this being a requirement of any "disabled assert" expression. * depend: * make-src-depend: * make-src-depend (PrintDeps): Fix broken code in make-src-depend so it does what it was always supposed to do, which was separate out config.h and lisp.h and all the files they include into separate variables in the depend part of Makefile so that quick-build can turn off the lisp.h/config.h/text.h/etc. dependencies of the source files, to speed up recompilation.
author Ben Wing <ben@xemacs.org>
date Sat, 20 Feb 2010 05:05:54 -0600
parents aa5ed11f473b
children
line wrap: on
line source

/* play.c - play a sound file on the speaker
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
 ** Modified 24-May-91 by Jamie Zawinski (for Lucid Emacs).
 ** Modified 17-Dec-92 by Jamie Zawinski (largely rewritten for SunOS 4.1.3).
 **
 ** Permission to use, copy, modify, and distribute this software and its
 ** documentation for any purpose and without fee is hereby granted, provided
 ** that the above copyright notice appear in all copies and that both that
 ** copyright notice and this permission notice appear in supporting
 ** documentation.  This software is provided "as is" without express or
 ** implied warranty.
 */

/* Synched up with: Not in FSF. */

/* This file Mule-ized by Ben Wing, 5-15-01. */

#include <config.h>
#include "lisp.h"
#include "sound.h"

#include "sysdep.h"
#include "sysfile.h"
#include "syssignal.h"

#include <multimedia/libaudio.h>
#include <multimedia/audio_device.h>

static SIGTYPE (*sighup_handler) (int sig);
static SIGTYPE (*sigint_handler) (int sig);
static SIGTYPE sighandler (int sig);

static int audio_fd;

#define audio_open()	open ("/dev/audio", (O_WRONLY | O_NONBLOCK), 0)

static int initialized_device_p;
static int reset_volume_p, reset_device_p;
static double old_volume;
static Audio_hdr dev_hdr;

static int
init_device (int volume, Binbyte *data, int fd,
	     unsigned int *header_length)
{
  Audio_hdr file_hdr;

  reset_volume_p = 0;
  reset_device_p = 0;

  assert (!(data && fd)); /* one or the other */

  if (AUDIO_SUCCESS != audio_get_play_config (audio_fd, &dev_hdr))
    {
      sound_perror ("Not a valid audio device");
      return 1;
    }

  if (AUDIO_SUCCESS != (data
			? audio_decode_filehdr (data, &file_hdr, header_length)
			: audio_read_filehdr (fd, &file_hdr, 0, 0)))
    {
      if (data)
	sound_perror ("invalid audio data");
      else
	sound_perror ("invalid audio file");
      return 1;
    }

  audio_flush_play (audio_fd);

  if (!initialized_device_p || (0 != audio_cmp_hdr (&dev_hdr, &file_hdr)))
    {
      Audio_hdr new_hdr;
      new_hdr = file_hdr;
      reset_device_p = 1;
      initialized_device_p = 1;
      if (AUDIO_SUCCESS != audio_set_play_config (audio_fd, &new_hdr))
	{
	  Extbyte buf1 [100], buf2 [100], buf3 [250];
	  audio_enc_to_str (&file_hdr, buf1);
	  audio_enc_to_str (&new_hdr, buf2);
	  sprintf (buf3, "wanted %s, got %s", buf1, buf2);
	  sound_warn (buf3);
	  return 1;
	}
    }

  if (volume < 0 || volume > 100)
    {
      Extbyte buf [255];
      sprintf (buf, "volume must be between 0 and 100 (not %d)", volume);
      sound_warn (buf);
      return 1;
    }
  {
    /* set the volume; scale it to 0.0 - 1.0 */
    double V = (volume / 100.0);
    audio_get_play_gain (audio_fd, &old_volume);
    reset_volume_p = 1;
    audio_set_play_gain (audio_fd, &V);
  }

  return 0;
}


static void
reset_device (int wait_p)
{
  if (wait_p)
    audio_drain (audio_fd, 1);
  else
    audio_flush_play (audio_fd);
  if (reset_device_p)
    audio_set_play_config (audio_fd, &dev_hdr);
  if (reset_volume_p)
    audio_set_play_gain (audio_fd, &old_volume);
}


void
play_sound_file (Extbyte *sound_file, int volume)
{
  int rrtn, wrtn;
  Binbyte buf [255];
  int file_fd;

  audio_fd = audio_open ();

  if (audio_fd < 0)
    {
      sound_perror ("open /dev/audio");
      return;
    }

  /* where to find the proto for signal()... */
  sighup_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGHUP, sighandler);
  sigint_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGINT, sighandler);

  file_fd = open (sound_file, O_RDONLY, 0);
  if (file_fd < 0)
    {
      sound_perror (sound_file);
      goto END_OF_PLAY;
    }

  if (init_device (volume, (Binbyte *) 0, file_fd, (unsigned int *) 0))
    goto END_OF_PLAY;

  while (1)
    {
      rrtn = read (file_fd, (CBinbyte *) buf, sizeof (buf));
      if (rrtn < 0)
	{
	  sound_perror ("read");
	  goto END_OF_PLAY;
	}
      if (rrtn == 0)
	break;

      while (1)
	{
	  wrtn = write (audio_fd, (CBinbyte *) buf, rrtn);
	  if (wrtn < 0)
	    {
	      sound_perror ("write");
	      goto END_OF_PLAY;
	    }
	  if (wrtn != 0)
	    break;

	  if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1))
	    goto END_OF_PLAY;
	}
      if (wrtn != rrtn)
	{
	  Extbyte warn_buf [255];
	  sprintf (warn_buf, "play: rrtn = %d, wrtn = %d", rrtn, wrtn);
	  sound_warn (warn_buf);
	  goto END_OF_PLAY;
	}
    }

 END_OF_PLAY:

  if (file_fd > 0)
    close (file_fd);

  if (audio_fd > 0)
    {
      reset_device (1);
      close (audio_fd);
    }

  EMACS_SIGNAL (SIGHUP, sighup_handler);
  EMACS_SIGNAL (SIGINT, sigint_handler);
}


int
play_sound_data (Binbyte *data, int length, int volume)
{
  int wrtn, start = 0;
  unsigned int ilen;
  int result = 0;

  audio_fd = -1;

  if (length == 0) return 0;

  /* this is just to get a better error message */
  if (strncmp (".snd\0", (CBinbyte *) data, 4))
    {
      sound_warn ("Not valid audio data (bad magic number)");
      goto END_OF_PLAY;
    }
  if (length <= sizeof (Audio_hdr))
    {
      sound_warn ("Not valid audio data (too short)");
      goto END_OF_PLAY;
    }

  audio_fd = audio_open ();
  if (audio_fd < 0)
      return 0;

  /* where to find the proto for signal()... */
  sighup_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGHUP, sighandler);
  sigint_handler = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGINT, sighandler);

  if (init_device (volume, data, 0, &ilen))
    goto END_OF_PLAY;

  data   += (ilen<<2);
  length -= (ilen<<2);
  if (length <= 1)
    goto END_OF_PLAY;

  while (1)
    {
      wrtn = write (audio_fd, (CBinbyte *) (data+start), length-start);
      if (wrtn < 0)
	{
	  sound_perror ("write");
	  goto END_OF_PLAY;
	}
      if (wrtn != 0)
	{
	  start += wrtn;
	  break;
	}
      if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1))
	goto END_OF_PLAY;
    }
  if (wrtn != length)
    {
      Extbyte buf [255];
      sprintf (buf, "play: rrtn = %d, wrtn = %d", length, wrtn);
      sound_warn (buf);
      goto END_OF_PLAY;
    }

 result = 1;
  
 END_OF_PLAY:

  if (audio_fd > 0)
    {
      reset_device (1);
      close (audio_fd);
    }

  EMACS_SIGNAL (SIGHUP, sighup_handler);
  EMACS_SIGNAL (SIGINT, sigint_handler);

  return result;
}

/* #### sigcontext doesn't exist in Solaris.  This should be updated
   to be correct for Solaris. */
static SIGTYPE
sighandler (int sig)
{
  if (audio_fd > 0)
    {
      reset_device (0);
      close (audio_fd);
    }
  if (sig == SIGHUP && sighup_handler)
    sighup_handler (sig);
  else if (sig == SIGINT && sigint_handler)
    sigint_handler (sig);
  else
    exit (1);
}