/* 
    kwintv, Video4Linux compatible KDE application

    Copyright (C) 1998 Moritz Wenk (wenk@mathematik.uni-kl.de)
*/
#ifdef HAVE_CONFIG_H
#include <config.h>  // config.h by configure
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/soundcard.h>
#include <sys/ioctl.h>

#include "dsp.h"

static char DSPerror[256];
#define DSP_PERROR(action,file) \
  {sprintf(DSPerror,"%s: %s: %s\n",action,file,strerror(errno));fprintf(stderr,DSPerror);}

#define TRAP(txt) fprintf(stderr,"%s:%d:%s\n",__FILE__,__LINE__,txt);exit(1);

dsp::dsp( const char * dev )
{
  if (-1 == (fd = ::open(dev, O_RDONLY))) {
    DSP_PERROR("open",dev);
  }
}

dsp::~dsp()
{
  ::close(fd);
  if (buffer) close();
}

int dsp::open (int bits, int channels, int rate)
{
  int afmt,trigger;

  ioctl(fd, SNDCTL_DSP_RESET, 0);
    
    int frag;
    frag=(8<<16)|(10);//8 buffers, 1024 bytes each
    ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);
  /* format */
  switch (bits) {
  case 16:
    afmt = AFMT_S16_LE;
    ioctl(fd, SNDCTL_DSP_SETFMT, &afmt);
    if (afmt == AFMT_S16_LE)
      break;
    /* fall back*/
    fprintf(stderr,"no 16 bit sound, trying 8 bit...\n");
    bits = 8;
  case 8:
    afmt = AFMT_U8;
    ioctl(fd, SNDCTL_DSP_SETFMT, &afmt);
    if (afmt != AFMT_U8) {
      fprintf(stderr,"Oops: no 8 bit sound ?\n");
      goto err;
    }
    break;
  default:
    fprintf(stderr,"%d bit sound not supported\n",
	    bits);
    goto err;
  }
    
  /* channels */
  ioctl(fd, SNDCTL_DSP_CHANNELS, &channels);
  /* sample rate */
  ioctl(fd, SNDCTL_DSP_SPEED,    &rate);

  if (-1 == ioctl(fd, SNDCTL_DSP_GETBLKSIZE,  &blocksize))
    goto err;
    printf("%d\n",blocksize);
  blocksize*=4;
  buffer = (char *)malloc(blocksize);

  /* trigger record */
  trigger = ~PCM_ENABLE_INPUT;
  ioctl(fd,SNDCTL_DSP_SETTRIGGER,&trigger);
  trigger = PCM_ENABLE_INPUT;
  ioctl(fd,SNDCTL_DSP_SETTRIGGER,&trigger);

  return fd;
    
 err:
  return 0;
}



int dsp::close()
{
  free(buffer);
  buffer=0;
  return 0;
}

char * dsp::readBuf()
{
  if (blocksize != read(fd,buffer,blocksize)) {
    perror("read /dev/dsp");
    return buffer;
//    exit(1);
  }
  return buffer;
}


int dsp::getSize()
{
	struct audio_buf_info z;
        ioctl(fd, SNDCTL_DSP_GETISPACE, &z);
        return z.bytes;
}
