#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#if defined(__linux__)
# include <linux/soundcard.h>
#elif defined(__FreeBSD__)
# include <machine/soundcard.h>
#endif

#include "ysound.h"
#include "ymixer.h"
#include "options.h"


#define MIN(a,b)        ((a) < (b) ? (a) : (b))
#define MAX(a,b)        ((a) > (b) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define ABSOLUTE(x)     (((x) < 0) ? ((x) * -1) : (x))


static int GET_MIXER_NUM_BY_NAME(int fd, const char *name);

static int YMixerSetBass(int fd, double value1, double value2);
static int YMixerSetCD(int fd, double value1, double value2);
static int YMixerSetGainIn(int fd, double value1, double value2);
static int YMixerSetGainOut(int fd, double value1, double value2);
static int YMixerSetLine(int fd, double value1, double value2);
static int YMixerSetLine1(int fd, double value1, double value2);
static int YMixerSetLine2(int fd, double value1, double value2);
static int YMixerSetLine3(int fd, double value1, double value2);
static int YMixerSetMic(int fd, double value1, double value2);
static int YMixerSetMix(int fd, double value1, double value2);
static int YMixerSetPCM(int fd, double value1, double value2);
static int YMixerSetPCM2(int fd, double value1, double value2);
static int YMixerSetRec(int fd, double value1, double value2);
static int YMixerSetSpeaker(int fd, double value1, double value2);
static int YMixerSetSynth(int fd, double value1, double value2);
static int YMixerSetTreble(int fd, double value1, double value2);
static int YMixerSetVolume(int fd, double value1, double value2);
static int YMixerSetDigital1(int fd, double value1, double value2);
static int YMixerSetDigital2(int fd, double value1, double value2);
static int YMixerSetDigital3(int fd, double value1, double value2);
static int YMixerSetPhoneIn(int fd, double value1, double value2);
static int YMixerSetPhoneOut(int fd, double value1, double value2);
static int YMixerSetVideo(int fd, double value1, double value2);
static int YMixerSetRadio(int fd, double value1, double value2);
static int YMixerSetMonitor(int fd, double value1, double value2);

#if 0
static int YMixerGetBass(int fd, double *value, double *value2);
static int YMixerGetCD(int fd, double *value1, double *value2);
static int YMixerGetGainIn(int fd, double *value1, double *value2);
static int YMixerGetGainOut(int fd, double *value1, double *value2);
static int YMixerGetLine(int fd, double *value, double *value2);
static int YMixerGetLine1(int fd, double *value, double *value2);
static int YMixerGetLine2(int fd, double *value, double *value2);
static int YMixerGetLine3(int fd, double *value, double *value2);
static int YMixerGetMic(int fd, double *value1, double *value2);
static int YMixerGetMix(int fd, double *value, double *value2);
static int YMixerGetPCM(int fd, double *value1, double *value2);
static int YMixerGetPCM2(int fd, double *value1, double *value2);
static int YMixerGetRec(int fd, double *value, double *value2);
static int YMixerGetSpeaker(int fd, double *value, double *value2);
static int YMixerGetSynth(int fd, double *value1, double *value2);
static int YMixerGetTreble(int fd, double *value, double *value2);
static int YMixerGetVolume(int fd, double *value1, double *value2);
static int YMixerGetDigital1(int fd, double *value1, double *value2);
static int YMixerGetDigital2(int fd, double *value1, double *value2);
static int YMixerGetDigital3(int fd, double *value1, double *value2);
static int YMixerGetPhoneIn(int fd, double *value1, double *value2);
static int YMixerGetPhoneOut(int fd, double *value1, double *value2);
static int YMixerGetVideo(int fd, double *value1, double *value2);
static int YMixerGetRadio(int fd, double *value1, double *value2);
static int YMixerGetMonitor(int fd, double *value1, double *value2);
#endif

int YMixerGet(
	Recorder *recorder,
	int mixer_code,
	Coefficient *value
);

int YMixerSet(
	Recorder *recorder,
	int mixer_code,         /* One of YMixerCode*. */
	Coefficient *value      /* Each value from 0.0 to 1.0. */
);


/*
 *	Returns the mixer device's number matching name or
 *	-1 on failed match.
 */
static int GET_MIXER_NUM_BY_NAME(int fd, const char *name)
{
	int i;
	int mixermask;
	const char *reg_name[] = SOUND_DEVICE_NAMES;

	if((fd < 0) || (name == NULL))
	    return(-1);

	/* Get mixer info mask. */
	if(ioctl(fd, SOUND_MIXER_READ_DEVMASK, &mixermask))
	{
	    /* Could not get mixer info mask. */
	    return(-1);
	}

	for(i = 0; i < SOUND_MIXER_NRDEVICES; i++)
	{
	    if(((1 << i) & mixermask) &&
	       !strcmp(name, reg_name[i])
	    )
		break;
	}

	return((i < SOUND_MIXER_NRDEVICES) ? i : -1);
} 


/* Sets the new mixer value. Requires variables; fd, stereomask, value1,
 * value2, and i.
 */
#define DO_SET_YMIXER	\
{ \
 if(ioctl(fd, SOUND_MIXER_READ_STEREODEVS, &stereomask)) \
  return(-1); \
 \
 /* Is this a stereo channel device? */ \
 if((value1 != value2) && !((1 << i) & stereomask)) \
 { \
  value1 = (value1 + value2) / 2; \
  value2 = value1; \
 } \
 \
 left = (unsigned int)(value1 * 100); \
 right = (unsigned int)(value2 * 100); \
 \
 packed_value = (right << 8) + left; \
 \
 return(ioctl(fd, MIXER_WRITE(i), &packed_value)); \
}


/*
 *	Mixer channel device set functions.
 */
static int YMixerSetBass(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "bass");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetCD(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "cd");
	if(i < 0)
	    return(-1);
	    
	DO_SET_YMIXER
}

static int YMixerSetGainIn(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "igain");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetGainOut(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "ogain");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetLine(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "line");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetLine1(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "line1");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetLine2(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "line2");
	if(i < 0)
	    return(-1);
	    
	DO_SET_YMIXER
}

static int YMixerSetLine3(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;        
	
	i = GET_MIXER_NUM_BY_NAME(fd, "line3");
	if(i < 0)
	    return(-1);
	    
	DO_SET_YMIXER
}

static int YMixerSetMic(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "mic");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetMix(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "mix");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetPCM(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "pcm");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetPCM2(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "pcm2");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetRec(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "rec");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetSpeaker(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "speaker");
	if(i < 0)
	    return(-1);
	    
	DO_SET_YMIXER
}

static int YMixerSetSynth(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "synth");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetTreble(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "treble");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetVolume(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "vol");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetDigital1(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "dig1");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetDigital2(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "dig2");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetDigital3(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "dig3");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetPhoneIn(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "phin");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetPhoneOut(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "phout");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetVideo(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "video");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetRadio(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "radio");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}

static int YMixerSetMonitor(int fd, double value1, double value2)
{
	int i, left, right, stereomask, packed_value;

	i = GET_MIXER_NUM_BY_NAME(fd, "monitor");
	if(i < 0)
	    return(-1);

	DO_SET_YMIXER
}


/* Gets mixer values from mixer channel i. Uses variables; fd, 
 * packed_value, i, value1, and value2.
 */
#define DO_GET_YMIXER	\
{ \
 if(ioctl(fd, MIXER_READ(i), &packed_value)) \
  return(-1); \
 (*value1) = (double)(packed_value & 0x000000ff) / (double)100; \
 (*value2) = (double)((packed_value & 0x0000ff00) >> 8) / (double)100; \
}

/*
 *      Mixer channel device get functions.
 */
static int YMixerGetBass(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "bass");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetCD(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "cd");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetGainIn(int fd, double *value1, double *value2)
{
	int i, packed_value;
	
	
	i = GET_MIXER_NUM_BY_NAME(fd, "igain");
	if(i < 0)
	    return(-1);
	    
	DO_GET_YMIXER

	return(0);
}

static int YMixerGetGainOut(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "ogain");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetLine(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "line");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetLine1(int fd, double *value1, double *value2)
{
	int i, packed_value;
	
	
	i = GET_MIXER_NUM_BY_NAME(fd, "line1");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetLine2(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "line2");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetLine3(int fd, double *value1, double *value2)
{
	int i, packed_value;
	
	
	i = GET_MIXER_NUM_BY_NAME(fd, "line3");
	if(i < 0)
	    return(-1);
	    
	DO_GET_YMIXER

	return(0);
}

static int YMixerGetMic(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "mic");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetMix(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "mix");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}       

static int YMixerGetPCM(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "pcm");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetPCM2(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "pcm2");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetRec(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "rec");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetSpeaker(int fd, double *value1, double *value2)
{
	int i, packed_value;
	
	
	i = GET_MIXER_NUM_BY_NAME(fd, "speaker");
	if(i < 0)
	    return(-1);
	    
	DO_GET_YMIXER
	
	return(0);
}

static int YMixerGetSynth(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "synth");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}

static int YMixerGetTreble(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "treble");
	if(i < 0)
	    return(-1);
	    
	DO_GET_YMIXER
	
	return(0);
}

static int YMixerGetVolume(int fd, double *value1, double *value2)
{
	int i, packed_value;


	i = GET_MIXER_NUM_BY_NAME(fd, "vol");
	if(i < 0)
	    return(-1);

	DO_GET_YMIXER

	return(0);
}


/* ******************************************************************* */

/*
 *      Gets mixer channel device values for the specified channel
 *	device mixer_code.   Returns -1 on error, -2 on unsupported
 *	mixer_code, or 0 on success.
 *
 *      The given value must point to an array of YMixerValues many 
 *      values which will be defined correctly on success.
 */
int YMixerGet(
	Recorder *recorder,
	int mixer_code,		/* One of YMixerCode*. */
	Coefficient *value
)
{
	int i, fd;
/*	int status = -2; */
	int mixer_index = mixer_code - YMixerCodeBaseOffset;


	if((recorder == NULL) || (value == NULL))
	    return(-1);

	/* Reset return values. */
	for(i = 0; i < YMixerValues; i++)
	    value[i] = 0.0;

	/* Get mixer file descriptor. */
	fd = recorder->audio.mixer_fd;
	if(fd < 0)
	    return(-1);

	/* Handle by mixer code. */
#if 0
/* Don't query from device. */
	switch(mixer_code)
	{
	  case YMixerCodeBass:
	    status = YMixerGetBass(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeCD:
	    status = YMixerGetCD(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeGainIn:
	    status = YMixerGetGainIn(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeGainOut:
	    status = YMixerGetGainOut(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeLine:
	    status = YMixerGetLine(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeLine1:
	    status = YMixerGetLine1(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeLine2:
	    status = YMixerGetLine2(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeLine3:
	    status = YMixerGetLine3(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeMic:
	    status = YMixerGetMic(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeMix:
	    status = YMixerGetMix(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodePCM:
	    status = YMixerGetPCM(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodePCM2:
	    status = YMixerGetPCM2(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeRec:
	    status = YMixerGetRec(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeSpeaker:
	    status = YMixerGetSpeaker(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeSynth:
	    status = YMixerGetSynth(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeTreble:
	    status = YMixerGetTreble(fd, &value[0], &value[1]);
	    break;

	  case YMixerCodeVolume:
	    status = YMixerGetVolume(fd, &value[0], &value[1]);
	    break;
	}
/* For now just get from mixer index. */
#endif

	if((mixer_index >= 0) && (mixer_index < YTotalMixers))
	{
	    Coefficient *opt_mixer_value = option.mixer_value[mixer_index];
 
	    for(i = 0; i < YMixerValues; i++)
		value[i] = opt_mixer_value[i];
	}

	return(0);
}


/*
 *	Sets actual mixer channel device values for the specified channel
 *	device mixer_code. Returns -1 on error, -2 on unsupported
 *	mixer_code, or 0 on success.
 *
 *	The given value must point to an array of YMixerValues many
 *	values.
 *
 *	The recorder's audio structure will be updated with the newly set
 *	mixer value on success.
 */
int YMixerSet(
	Recorder *recorder,
	int mixer_code,         /* One of YMixerCode*. */
	Coefficient *value      /* Each value from 0.0 to 1.0. */
)
{
	int i, fd, status = -2;
	int mixer_index = mixer_code - YMixerCodeBaseOffset;


	if((recorder == NULL) || (value == NULL))
	    return(-1);

	fd = recorder->audio.mixer_fd;
	if(fd < 0)
	    return(-1);


	/* Clip. */
	for(i = 0; i < YMixerValues; i++)
	{
	    if(value[i] < 0.0)
		value[i] = 0.0;
	    if(value[i] > 1.0)
		value[i] = 1.0;
	}

	/* Update last mixer value on recorder's audio structure. */
	if((mixer_index >= 0) && (mixer_index < YTotalMixers))
	{
	    Coefficient *opt_mixer_value = option.mixer_value[mixer_index];

	    for(i = 0; i < YMixerValues; i++)
		opt_mixer_value[i] = value[i];
	}

	/* Handle actual setting by mixer code. */
	switch(mixer_code)
	{
	  case YMixerCodeVolume:
	    status = YMixerSetVolume(fd, value[0], value[1]);
	    break;

	  case YMixerCodeBass:
	    status = YMixerSetBass(fd, value[0], value[1]);
	    break;

	  case YMixerCodeTreble:
	    status = YMixerSetTreble(fd, value[0], value[1]);
	    break;

	  case YMixerCodeCD:
	    status = YMixerSetCD(fd, value[0], value[1]);
	    break;

	  case YMixerCodeGainIn:
	    status = YMixerSetGainIn(fd, value[0], value[1]);
	    break;

	  case YMixerCodeGainOut:
	    status = YMixerSetGainOut(fd, value[0], value[1]);
	    break;

	  case YMixerCodeLine:
	    status = YMixerSetLine(fd, value[0], value[1]);
	    break;

	  case YMixerCodeLine1:
	    status = YMixerSetLine1(fd, value[0], value[1]);
	    break;

	  case YMixerCodeLine2:
	    status = YMixerSetLine2(fd, value[0], value[1]);
	    break;

	  case YMixerCodeLine3:
	    status = YMixerSetLine3(fd, value[0], value[1]);
	    break;

	  case YMixerCodeMic:
	    status = YMixerSetMic(fd, value[0], value[1]);
	    break;

	  case YMixerCodeMix:
	    status = YMixerSetMix(fd, value[0], value[1]);
	    break;

	  case YMixerCodePCM:
	    status = YMixerSetPCM(fd, value[0], value[1]);
	    break;

	  case YMixerCodePCM2:
	    status = YMixerSetPCM2(fd, value[0], value[1]);
	    break;

	  case YMixerCodeRec:
	    status = YMixerSetRec(fd, value[0], value[1]);
	    break;

	  case YMixerCodeSpeaker:
	    status = YMixerSetSpeaker(fd, value[0], value[1]);
	    break;

	  case YMixerCodeSynth:
	    status = YMixerSetSynth(fd, value[0], value[1]);
	    break;

	  case YMixerCodeDigital1:
	    status = YMixerSetDigital1(fd, value[0], value[1]);
	    break;

	  case YMixerCodeDigital2:
	    status = YMixerSetDigital2(fd, value[0], value[1]);
	    break;

	  case YMixerCodeDigital3:
	    status = YMixerSetDigital3(fd, value[0], value[1]);
	    break;

	  case YMixerCodePhoneIn:
	    status = YMixerSetPhoneIn(fd, value[0], value[1]);
	    break;

	  case YMixerCodePhoneOut:
	    status = YMixerSetPhoneOut(fd, value[0], value[1]);
	    break;

	  case YMixerCodeVideo:
	    status = YMixerSetVideo(fd, value[0], value[1]);
	    break;

	  case YMixerCodeRadio:
	    status = YMixerSetRadio(fd, value[0], value[1]);
	    break;

	  case YMixerCodeMonitor:
	    status = YMixerSetMonitor(fd, value[0], value[1]);
	    break;
	}

	return(status);
}
