Ejemplo n.º 1
0
/* XEmacs requires code both for playback of pre-loaded data and for playback
   from a soundfile; we use one function for both cases.

   Returns 1 on succes. 0 otherwise.
*/
static int linux_play_data_or_file(int fd,unsigned char *data,
				    int length,int volume)
{
  size_t         (*parsesndfile)(void **dayta,size_t *sz,void **outbuf);
  size_t         (*sndcnv)(void **dayta,size_t *sz,void **);
  fmtType        ffmt;
  int            fmt,speed,tracks;
  unsigned char *pptr,*optr,*cptr,*sptr;
  int            wrtn, crtn;
  size_t         prtn, rrtn;
  unsigned char  sndbuf[SNDBUFSZ];

  /* We need to read at least the header information before we can start
     doing anything */
  if (!data || length < HEADERSZ) {
    if (fd < 0) return 0;
    else {
      length = read(fd,sndbuf,SNDBUFSZ);
      if (length < HEADERSZ)
	return 0;
      data   = sndbuf;
      length = SNDBUFSZ; }
  }

  ffmt = analyze_format(data,&fmt,&speed,&tracks,&parsesndfile);

  if (ffmt != fmtRaw && ffmt != fmtSunAudio && ffmt != fmtWave) {
    warn("Unsupported file format (neither RAW, nor Sun/DECAudio, nor WAVE)");
      return 0; }

  /* The VoxWare-SDK discourages opening /dev/audio; opening /dev/dsp and
     properly initializing it via ioctl() is preferred */
  if ((audio_fd=open(audio_dev, O_WRONLY | O_NONBLOCK, 0)) < 0) {
    /* JV. Much too verbose. In addition this can crash. See NOTE: in
       Fplay_sound 
       perror(audio_dev); */
    if (mix_fd > 0 && mix_fd != audio_fd) { close(mix_fd); mix_fd = -1; }
    return 0; }

  /* The VoxWare-SDK discourages direct manipulation of the mixer device as
     this could lead to problems, when multiple sound cards are installed */
  mix_fd = audio_fd;

  sighup_handler = signal(SIGHUP, sighandler);
  sigint_handler = signal(SIGINT, sighandler);

  if (!audio_init(mix_fd,audio_fd,fmt,speed,tracks,&volume,&sndcnv))
    goto END_OF_PLAY;
  audio_vol = volume;

  reset_parsestate();

  /* Mainloop: read a block of data, parse its contents, perform all
               the necessary conversions and output it to the sound
               device; repeat until all data has been processed */
  rrtn = length;
  do {
    for (pptr = data; (prtn = parsesndfile((void **)&pptr, &rrtn,
					   (void **)&optr)) > 0; )
      for (cptr = optr; (crtn = sndcnv((void **)&cptr, &prtn,
				       (void **)&sptr)) > 0; ) {
	for (;;) {
	  if ((wrtn = write(audio_fd,sptr,crtn)) < 0) {
	    perror("write"); goto END_OF_PLAY; }
	  else if (wrtn) break;
	  else if (ioctl(audio_fd,SNDCTL_DSP_SYNC,NULL) < 0) {
	    perror("SNDCTL_DSP_SYNC"); goto END_OF_PLAY; } }
	if (wrtn != crtn) {
	  char buf[255];
	  sprintf(buf,"play: crtn = %d, wrtn = %d",crtn,wrtn);
	  warn(buf);
	  goto END_OF_PLAY; } }
    if (fd >= 0) {
      if ((rrtn = read(fd,sndbuf,SNDBUFSZ)) < 0) {
	perror("read"); goto END_OF_PLAY; } }
    else
      break;
  } while (rrtn > 0);

  if (ffmt == fmtWave)
    parse_wave_complete();


END_OF_PLAY:
  /* Now cleanup all used resources */

  ioctl(audio_fd,SNDCTL_DSP_SYNC,NULL);
  ioctl(audio_fd,SNDCTL_DSP_RESET,NULL);

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

  if (mix_fd > 0) {
    if (audio_vol >= 0) {
      ioctl(mix_fd,SOUND_MIXER_WRITE_PCM,&audio_vol);
      audio_vol = -1; }
    if (mix_fd != audio_fd)
      close(mix_fd);
    mix_fd = -1; }

  close(audio_fd);
  audio_fd = -1;

  return 1;
}
Ejemplo n.º 2
0
int
esd_play_sound_data (Binbyte *data, size_t length, int UNUSED (vol))
{                              /* #### FIXME: vol is ignored */
  size_t         (*parsesndfile)(void **dayta,size_t *sz,void **outbuf);
  size_t         (*sndcnv)(void **dayta,size_t *sz,void **);
  fmtType        ffmt;
  int            fmt,speed,tracks;
  unsigned char *pptr,*optr,*cptr,*sptr;
  Bytecount      wrtn, crtn;
  size_t         prtn;
  int flags, sock;

  /* analyze_format needs at least this many bytes to work with */
  if (length < HEADERSZ)
    return 0;

  ffmt = analyze_format(data,&fmt,&speed,&tracks,&parsesndfile);

  if (ffmt != fmtRaw && ffmt != fmtSunAudio && ffmt != fmtWave) {
    sound_warn("Unsupported file format (neither RAW, nor Sun/DECAudio, nor WAVE)");
      return 0;
  }

  /* convert header information into ESD flags */
  flags = ESD_STREAM|ESD_PLAY;
  sndcnv = sndcnvnop;
  switch (fmt)
    {
    case AFMT_MU_LAW:
      sndcnv = sndcnvULaw_2linear;
      flags |= ESD_BITS8;
      break;
    case AFMT_S8:
      sndcnv = sndcnv2unsigned;        /* ESD needs unsigned bytes */
    case AFMT_U8:
      flags |= ESD_BITS8;
      break;
    case AFMT_S16_BE:
      sndcnv = sndcnv16swap;   /* ESD wants little endian */
    case AFMT_S16_LE:
      flags |= ESD_BITS16;
      break;
    default:
      {
	Extbyte warn_buf[255];
	sprintf (warn_buf, "byte format %d unimplemented", fmt);
	sound_warn (warn_buf);
	return 0;
      }
    }
  switch (tracks)
    {
    case 1: flags |= ESD_MONO; break;
    case 2: flags |= ESD_STEREO; break;
    default:
      {
	Extbyte warn_buf[255];
	sprintf (warn_buf, "%d channels - only 1 or 2 supported", tracks);
	sound_warn (warn_buf);
	return 0;
      }
    }

  sock = esd_play_stream(flags, speed, NULL, "xemacs");
  if (sock < 0)
    return 0;

  reset_parsestate();

  for (pptr = data; (prtn = parsesndfile((void **)&pptr,&length,
                                        (void **)&optr)) > 0; )
    for (cptr = optr; (crtn = sndcnv((void **)&cptr,&prtn,
                                    (void **)&sptr)) > 0; )
      {
	if ((wrtn = write(sock,sptr,crtn)) < 0)
	  {
	    sound_perror ("write error");
	    goto END_OF_PLAY;
	  }
	if (wrtn != crtn)
	  {
	    Extbyte warn_buf[255];
	    sprintf (warn_buf, "only wrote %ld of %ld bytes", wrtn, crtn);
	    sound_warn (warn_buf);
	    goto END_OF_PLAY;
	  }
      }

  if (ffmt == fmtWave)
    parse_wave_complete();

END_OF_PLAY:
  /* Now cleanup all used resources */

  close(sock);
  return 1;
}