/* Copyright (c) 1991-2002 Doshita Lab. Speech Group, Kyoto University */
/* Copyright (c) 2000-2002 Speech and Acoustics Processing Lab., NAIST */
/*   All rights reserved   */

/* adin_mic_sun4.c --- adin microphone library for Sun SunOS 4.x */

/* $Id: adin_mic_sun4.c,v 1.2 2002/09/11 22:01:50 ri Exp $ */

/* Tested on SunOS4.1.3 */
/* assume all Sun machines are BIG ENDIAN */

/* volume will be set to J_DEF_VOLUME at startup */


#define J_DEF_VOLUME 20		/* 0-99 */

#include <sent/stddefs.h>
#include <sent/adin.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stropts.h>
#include <poll.h>

static int volume = J_DEF_VOLUME;		/* 0-100 */

/* sound header */
#include <multimedia/libaudio.h>/* see man audio_device(3) */
#include <multimedia/audio_device.h>
static int afd;			/* audio file descriptor */
static struct pollfd pfd;	/* fd for polling */
static audio_info_t ainfo;	/* audio info */

/* check audio port resource and initialize */
/* will be called once at startup time */
boolean
adin_mic_standby(int sfreq, void *dummy)
{
  char *defaultdev = "/dev/audio"; /* default device file */
  char *devname;
  Audio_hdr Dev_hdr, old_hdr;
  double vol;

  /* get device name if specified in $AUDIODEV */
  if ((devname = getenv("AUDIODEV")) == NULL) {
    devname = defaultdev;
  }

  /* open the device */
  if ((afd = open(devname, O_RDONLY)) == -1) {
    if (errno == EBUSY) {
      j_printerr("audio device %s is busy\n", devname);
      return(FALSE);
    } else {
      j_printerr("unable to open %s\n",devname);
      return(FALSE);
    }
  }

  /* set recording port to microphone */
  AUDIO_INITINFO(&ainfo);
  ainfo.record.port = AUDIO_MICROPHONE;
  if (ioctl(afd, AUDIO_SETINFO, &ainfo) == -1) {
    perror("Audio_set_info");
    return(FALSE);
  }

  /* set recording parameters */
  if (audio_get_record_config(afd, &Dev_hdr) != AUDIO_SUCCESS) {
    j_printerr("get_config error\n"); return(FALSE);
  }
  Dev_hdr.sample_rate = sfreq;
  Dev_hdr.samples_per_unit = 1; /* ? I don't know this param. ? */
  Dev_hdr.bytes_per_unit = 2;
  Dev_hdr.channels = 1;
  Dev_hdr.encoding = AUDIO_ENCODING_LINEAR;
  if (audio_set_record_config(afd, &Dev_hdr) != AUDIO_SUCCESS) {
    j_printerr("set_config error\n"); return(FALSE);
  }

  /* set volume */
  vol = (float)volume / (float)100;
  if (audio_set_record_gain(afd, &vol) != AUDIO_SUCCESS) {
    j_printerr("cannot set record volume\n");
    return(FALSE);
  }

  /* flush buffer */
  if((ioctl(afd , I_FLUSH , FLUSHRW)) == -1) {
    j_printerr("cannot flush input buffer\n");
    return(FALSE);
  }
  
  /* setup polling */
  pfd.fd = afd;
  pfd.events = POLLIN;

  /* pause transfer */
  if (audio_pause_record(afd) == AUDIO_ERR_NOEFFECT) {
    j_printerr("cannot pause audio\n");
    return(FALSE);
  }

  return(TRUE);
}

/* start recording */
boolean
adin_mic_start()
{
  /* resume input */
  if (audio_resume_record(afd) == AUDIO_ERR_NOEFFECT) {
    j_printerr("cannot resume audio\n");
    return(FALSE);
  }
  return(TRUE);
}

/* stop recording */
boolean
adin_mic_stop()
{
  /* pause input */
  if (audio_pause_record(afd) == AUDIO_ERR_NOEFFECT) {
    j_printerr("cannot pause audio\n");
    return(FALSE);
  }
  return(TRUE);
}

/* read samples from audio device */
/* try to read `sampnum' samples and returns actual sample num recorded */
int
adin_mic_read(SP16 *buf, int sampnum)
{
  int bytes;
  int len;

  /* SunOS4.x needs special dealing when no samples are found */
  len = sampnum * sizeof(SP16);
  bytes = 0;
  while(bytes < len) {
    bytes = read(afd, buf, len);
    if (bytes < 0) {
      if (errno != EAGAIN) {	/* error */
	perror("adin_mic_read: failed to read sample");
	return(-2);
      } else {			/* retry */
	poll(&pfd, 1L, -1);
      }
    }
  }
  if (bytes < 0) {
    perror("adin_mic_read: failed to read sample");
    return(-2);
  }
  return(bytes / sizeof(SP16)); /* success */
}
