#include <linux/soundcard.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "module.h"

////////////////////////////////////////////////////////////
// The dsp_fd variable stores the file descriptor for the
// sound device. I need this variable global so all sound
// related procedures can access the device. I declare it
// static to remove temptation from coders.
////////////////////////////////////////////////////////////
static int dsp_fd;

/**********************************************************************
The SoundInit function initialises the /dev/dsp device. The first
four operations should be obvious. If they arent then the VoxWare
documention on nic.funet.fi:/pub/Linux/ALPHA/sound should help.
The fifth operation allows for better debugging, read on.
**********************************************************************/

void SoundInit(void)
{
	dsp_fd = open("/dev/dsp", O_WRONLY, 0);
	if (dsp_fd == -1)
	{
		printf("fatal: cannot open dsp device\n");
		exit(1);
	}
	if (ioctl(dsp_fd, SNDCTL_DSP_STEREO, &samplestereo) == -1)
	{
		printf("fatal: cannot set mono/stereo output\n");
		exit(1);
	}
	if (ioctl(dsp_fd, SNDCTL_DSP_SAMPLESIZE, &samplesize) == -1)
	{
		printf("fatal: cannot set 8/16 bit sampling\n");
		exit(1);
	}
	if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &samplerate) == -1)
	{
		printf("fatal: cannot set sampling rate\n");
		exit(1);
	}
	////////////////////////////////////////////////////////////
	// The following fragmentation code causes Voxware to use
	// smaller dma blocks. This allows slightly more accurate
	// timing over the output which makes my debugging easier.
	// It unfortunately means large cpu usage peaks will cause
	// the playback to pause. You could increase the number of 
	// fragments (high word) or increase the size of fragments
	// (low word). I dont recommend turning fragmentation off.
	////////////////////////////////////////////////////////////
	int frag = 0x00100008;
	if (ioctl(dsp_fd, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)
	{
		printf("fatal: cannot set fragment\n");
		exit(1);
	}
}

/**********************************************************************
The SoundDest routine releases the /dev/dsp device.
**********************************************************************/

void SoundDest(void)
{
	if (close(dsp_fd) == -1)
	{
		printf("fatal: cannot close dsp device\n");
		exit(1);
	}
}

/**********************************************************************
The SoundSend routine sends one chunk of data to the /dev/dsp device.
**********************************************************************/

void SoundSend(char * buffer, int length)
{
	if (write(dsp_fd, buffer, length) != length)
	{
		printf("fatal: cannot write dsp device\n");
		exit(1);
	}
}
