static char rcsid[] =
  "$Id: linux.c,v 1.2 2002/02/28 11:15:59 root Exp root $";

/*
 * $Log: linux.c,v $
 * Revision 1.2  2002/02/28 11:15:59  root
 * #
 *
 * Revision 1.1  2001/10/12 13:51:13  root
 * #
 *
 * Revision 1.4  2000/10/07 18:30:09  root
 * #
 *
 * Revision 1.3  2000/10/06 19:52:44  root
 * #
 *
 * Revision 1.2  2000/09/24 01:46:07  root
 * #
 *
 * Revision 1.1  2000/09/24 01:12:54  root
 * #
 *
 * Revision 1.5  2000/02/20 03:03:53  root
 * #
 *
 * Revision 1.4  2000/02/20 02:52:13  root
 * #
 *
 * Revision 1.3  2000/02/16 13:53:26  root
 * #
 *
 * Revision 1.2  2000/02/16 13:51:59  root
 * #
 *
 * Revision 1.1  2000/02/16 13:50:11  root
 * Initial revision
 *
 * Revision 1.1  2000/02/14 04:08:33  root
 * #
 *
 * Revision 1.4  1999/10/26 17:46:46  root
 * #
 *
 * Revision 1.3  1999/10/26 17:46:41  root
 * #
 *
 * Revision 1.2  1999/09/21 23:01:38  root
 * #
 *
 * Revision 1.1  1999/09/21 22:56:11  root
 * Initial revision
 *
 */



#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/soundcard.h>

#include "hifi.h"

static int fd;


#ifndef SOUND_MIXER_WRITE_RADIO
#define SOUND_MIXER_WRITE_RADIO MIXER_WRITE(SOUND_MIXER_RADIO)
#endif
#ifndef SOUND_MIXER_READ_RADIO
#define SOUND_MIXER_READ_RADIO MIXER_READ(SOUND_MIXER_RADIO)
#endif
#ifndef SOUND_MIXER_READ_LINE
#define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE)
#endif
#ifndef SOUND_MIXER_WRITE_DIGITAL1
#define SOUND_MIXER_WRITE_DIGITAL1 MIXER_WRITE(SOUND_MIXER_DIGITAL1)
#endif
#ifndef SOUND_MIXER_READ_DIGITAL1
#define SOUND_MIXER_READ_DIGITAL1 MIXER_READ(SOUND_MIXER_DIGITAL1)
#endif


void
mixer_open (void)
{
  fd = open ("/dev/mixer", O_NDELAY | O_RDONLY);
  if (fd < 0)
    {
      perror ("open");
      exit (1);
    }
}

static void
do_mixer_set_systemvol (int l, int r)
{
  l |= (r << 8);
  ioctl (fd, SOUND_MIXER_WRITE_VOLUME, &l);

}

void
do_mixer_get_systemvol (int *l, int *r)
{

  ioctl (fd, SOUND_MIXER_READ_VOLUME, l);
  *r = (*l) >> 8;
  (*l) &= 0xff;

}


void
do_slide_mixer_set_systemvol (int l, int r)
{
int cl,cr;
float sl,sr;
int il,ir,i;

do_mixer_get_systemvol (&cl,&cr);

sl=((float) (l-cl))/25;
sr=((float) (r-cr))/25;

for (i=0;i<25;++i) {
il=sl*(float) i;
ir=sr*(float) i;
il+=cl;
ir+=cr;

do_mixer_set_systemvol (il, ir);
usleep(20000);

}

do_mixer_set_systemvol (l, r);

}

void
mixer_set_pcmvol (int l, int r)
{
  l |= (r << 8);
  ioctl (fd, SOUND_MIXER_WRITE_PCM, &l);

}

void
mixer_get_pcmvol (int *l, int *r)
{

  ioctl (fd, SOUND_MIXER_READ_PCM, l);
  *r = (*l) >> 8;
  (*l) &= 0xff;

}

void mixer_get_systemvol(int *left_byte,int *right_byte,int *bal_byte)
{
float bl,br,l,r;
float b;
do_mixer_get_systemvol(left_byte,right_byte);
l=*left_byte;
r=*right_byte;


if (l==0) l=0.0001;
if (r==0) r=0.0001;

if (l>r) {
b=r/l;
b=1.0-b;
b*=128.0;
*bal_byte=128-b;
*right_byte=*left_byte;
} else {
b=l/r;
b=1.0-b;
b*=128.0;
*bal_byte=128+b;
*left_byte=*right_byte;
}

}



void mixer_set_systemvol(int left_byte,int right_byte,int bal_byte)
{
float bl,br,l,r;
float b;

b=bal_byte-128;
b=b/128.0;

l=left_byte;
r=right_byte;

if (b>=0) {
bl=1.0-b;
br=1.0;
} else {
bl=1.0;
br=1.0+b;
}

l=left_byte;
l*=bl;
r=right_byte;
r*=br;

do_mixer_set_systemvol((int) l,(int) r);

}
void slide_mixer_set_systemvol(int left_byte,int right_byte,int bal_byte)
{
float bl,br,l,r;
float b;

b=bal_byte-128;
b=b/128.0;

l=left_byte;
r=right_byte;

if (b>=0) {
bl=1.0-b;
br=1.0;
} else {
bl=1.0;
br=1.0+b;
}

l=left_byte;
l*=bl;
r=right_byte;
r*=br;

do_slide_mixer_set_systemvol((int) l,(int) r);

}
void
mixer_set_tunervol (int l, int r)
{
  int i=0;

  ioctl(fd,SOUND_MIXER_READ_DEVMASK,&i);

  l |= (r << 8);
  if (i & SOUND_MASK_RADIO) {
  	ioctl (fd, SOUND_MIXER_WRITE_RADIO, &l);
  } else {
  	ioctl (fd, SOUND_MIXER_WRITE_LINE, &l);
  }
}

void
mixer_get_tunervol (int *l, int *r)
{
  int i=0;
  ioctl(fd,SOUND_MIXER_READ_DEVMASK,&i);

  if (i & SOUND_MASK_RADIO) {
	ioctl (fd, SOUND_MIXER_READ_RADIO, l);
  } else  {
        ioctl (fd, SOUND_MIXER_READ_LINE, l);
  }

  *r = (*l) >> 8;
  (*l) &= 0xff;

}
void
mixer_set_cdvol (int l, int r)
{
  l |= (r << 8);
  ioctl (fd, SOUND_MIXER_WRITE_CD, &l);

}

void
mixer_get_cdvol (int *l, int *r)
{

  ioctl (fd, SOUND_MIXER_READ_CD, l);
  *r = (*l) >> 8;
  (*l) &= 0xff;
}
void
mixer_set_spdif (int l)
{
  if (l) l=100;

  l |= (l << 8);
  ioctl (fd, SOUND_MIXER_WRITE_DIGITAL1, &l);

}

void
mixer_get_spdif (int *l)
{

  ioctl (fd, SOUND_MIXER_READ_DIGITAL1, l);
  *l|=*l >> 8;
  (*l) &= 0xff;
  if (*l>50) *l=1; else *l=0;

}

void 
mixer_set_source(int sources)
{
int i=0,j;

  ioctl(fd,SOUND_MIXER_READ_DEVMASK,&j);

if (sources & HIFI_WAVE_Source_CD)  i|= (1 << SOUND_MIXER_CD);
if (sources & HIFI_WAVE_Source_Tuner) {
if (j & SOUND_MASK_RADIO) {
 i|= (1 << SOUND_MIXER_RADIO);
} else {
i|= (1 << SOUND_MIXER_LINE);
}
}
if (sources & HIFI_WAVE_Source_SPDIF)  i|= (1 << SOUND_MIXER_DIGITAL1);

ioctl(fd,SOUND_MIXER_WRITE_RECSRC,&i);

}

void 
mixer_get_source(int *sources)
{
int i=0,j;
ioctl(fd,SOUND_MIXER_READ_RECSRC,&i);

*sources=0;

  ioctl(fd,SOUND_MIXER_READ_DEVMASK,&j);

if (i & (1 << SOUND_MIXER_CD)) *sources|=HIFI_WAVE_Source_CD;
if (j & SOUND_MASK_RADIO) {
if (i & (1 << SOUND_MIXER_RADIO)) *sources|=HIFI_WAVE_Source_Tuner;
} else {
if (i & (1 << SOUND_MIXER_LINE)) *sources|=HIFI_WAVE_Source_Tuner;
}
if (i & (1 << SOUND_MIXER_DIGITAL1)) *sources|=HIFI_WAVE_Source_SPDIF;

}

