/* 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_sol2.c --- adin microphone library for Sun SPARC Solaris 2.x */

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

/* Tested on Solaris-2.6 */
/* may not work in Solaris x86 because assuming BIG ENDIAN here */

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

/* #define J_DEF_VOLUME 14 */		/* 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 <sys/stropts.h>

/* sound header */
#include <sys/audioio.h>
static int afd;			/* audio file descriptor */
static struct audio_info ainfo;	/* audio format info */

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

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

  /* open the device */
  if ((afd = open(devname, O_RDONLY)) == -1) {
    perror("adin_mic_standby: open audio device");
    return(FALSE);
  }

#if 0
  {
    /* output hardware info (debug) */
    struct audio_device adev;
    if (ioctl(afd, AUDIO_GETDEV, &adev)== -1) {
      perror("adin_mic_standby: AUDIO_GETDEV");
      return(FALSE);
    }
    j_printf("Hardware name: %s\n",adev.name);
    j_printf("Hardware version: %s\n", adev.version);
    j_printf("Properties: %s\n", adev.config);
  }
#endif

  /* get current setting */
  if (ioctl(afd, AUDIO_GETINFO, &ainfo) == -1) {
    perror("adin_mic_standby: AUDIO_GETINFO");
    return(FALSE);
  }
  /* pause for changing setting */
  ainfo.record.pause = 1;
  if (ioctl(afd, AUDIO_SETINFO, &ainfo) == -1) {
    perror("adin_mic_standby: AUDIO_SETINFO");
    return(FALSE);
  }
  /* flush current input buffer (in old format) */
  if((ioctl(afd , I_FLUSH , FLUSHR)) == -1) {
    perror("adin_mic_standby: I_FLUSH");
    return(FALSE);
  }
  /* set record setting */
  ainfo.record.sample_rate = sfreq;
  ainfo.record.channels = 1;
  ainfo.record.precision = 16;
  ainfo.record.encoding = AUDIO_ENCODING_LINEAR;
  /* ainfo.record.gain = J_DEF_VOLUME * (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN) / 100 + AUDIO_MIN_GAIN; */
  ainfo.record.port = AUDIO_MICROPHONE;
  /* recording should be paused when initialized */
  ainfo.record.pause = 1;

  /* set audio setting, remain pause */
  if (ioctl(afd, AUDIO_SETINFO, &ainfo) == -1) {
    perror("adin_mic_standby: AUDIO_SETINFO");
    return(FALSE);
  }

  return(TRUE);

}

/* start recording */
boolean
adin_mic_start()
{
  if (ioctl(afd, AUDIO_GETINFO, &ainfo) == -1) {
    perror("adin_mic_start: AUDIO_GETINFO");
    return(FALSE);
  }
  ainfo.record.pause = 0;
  if (ioctl(afd, AUDIO_SETINFO, &ainfo) == -1) {
    perror("adin_mic_start: AUDIO_SETINFO");
    return(FALSE);
  }

  return(TRUE);
}

/* stop recording */
boolean
adin_mic_stop()
{
  if (ioctl(afd, AUDIO_GETINFO, &ainfo) == -1) {
    perror("adin_mic_stop: AUDIO_GETINFO");
    return(FALSE);
  }
  ainfo.record.pause = 1;
  if (ioctl(afd, AUDIO_SETINFO, &ainfo) == -1) {
    perror("adin_mic_stop: AUDIO_SETINFO");
    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 cnt;
  cnt = read(afd, buf, sampnum * sizeof(SP16)) / sizeof(SP16);
  if (cnt < 0) {
    perror("adin_mic_read: failed to read sample\n");
    return(-2);
  }
  return(cnt);
}
