/*************************************************************************/
/*                  VChat interactive IP-level chat system               */
/*-----------------------------------------------------------------------*/
/*  (c) '93/'94 by Andreas S. Wetzel (mickey@deadline.bln.sub.org)       */
/*                 All rights reserverd.                                 */ 
/*-----------------------------------------------------------------------*/
/* See the file COPYRIGHT in the top level directory of VChat for        */
/* copyright notices and further disclaimers.                            */ 
/*************************************************************************/

#include "../config.h"
#include "../global.h"
#include <stdio.h>
#include <syslog.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include "audio.h"
#include "proto.h"

void audio_out(void)
{
#ifdef AUDIO
	int audio;
	int fd;
	int tmp;
	int c;
	int abufsize;
	char *audiobuf;
	extern int samplesize;
	extern long dsp_speed;
	extern int dsp_stereo;
	extern char audio_dev[];
	extern char *audio_file;

	if((fd = open(audio_file, O_RDONLY, 0)) == -1)
	{
		log(LOG_ERR, "unable to open '%s'.", audio_file);
		return; 
	}

	if(get_param(fd) == -1)
	{
		return;
	}

	if((audio = open(audio_dev, O_WRONLY | O_NONBLOCK, 0)) == -1)
	{
		log(LOG_ERR, "unable to open audio device %s.", audio_dev);
		close(fd);
		return;
	}

	tmp = samplesize;
	ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize);

	if(tmp != samplesize)
	{
		log(LOG_ERR, "Unable to set samplesize.");
		close(fd);
		close(audio);
		return;
	}

	if(ioctl(audio, SNDCTL_DSP_STEREO, &dsp_stereo) == -1)
	{
		log(LOG_ERR, "Unable to set mono/stereo.");
		close(fd);
		close(audio);
		return;
	}

	if(ioctl(audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1)
	{
		log(LOG_ERR, "Unable to set dsp speed.");
		close(fd);
		close(audio);
		return;
	}

	ioctl(audio, SNDCTL_DSP_GETBLKSIZE, &abufsize);

	if(abufsize < 1024 || abufsize > (131072))
	{
		log(LOG_ERR, "Invalid audio buffer size %d", abufsize);
		close(fd);
		close(audio);
		return;
	}

	if((audiobuf = (char *)malloc(abufsize)) == NULL)
	{
		log(LOG_ERR, "Unable to allocate audio-buffer (0x%x bytes).", abufsize);
		close(fd);
		close(audio);
		return;
	}

	while((c = read(fd, audiobuf, abufsize)) >0)
	{
		if(write(audio, audiobuf, c) < c)
		{
			log(LOG_WARNING, "audio playback overrun.");
		}
	}

	close(fd);
	close(audio);
	free(audiobuf);

#endif
}

int get_param(int d)
{
#ifdef AUDIO
	extern int samplesize;
	extern long dsp_speed;
	extern int dsp_stereo;
	extern char *audio_file;
	extern char audio_dev[];

	struct deadsnd_id dsid;

	if(read(d, (char *)&dsid, sizeof(struct deadsnd_id)) != sizeof(struct deadsnd_id))
	{
		log(LOG_ERR, "unexpected end of audio file.");
		close(d);
		return(-1);
	}
	else
	{
		if(dsid.id == DEADSNDID)
		{
			/* Deadsnd file */

			dsp_speed = (dsp_speed == -1) ? dsid.freq : dsp_speed;
			dsp_stereo = (dsp_stereo == -1) ? dsid.mode : dsp_stereo;
			samplesize = (samplesize == -1) ? dsid.bps : samplesize;
		}
		else
		{
			/* Normal sample file */

			dsp_speed = (dsp_speed == -1) ? DEF_DSP_SPEED : dsp_speed;
			dsp_stereo = (dsp_stereo == -1) ? DEF_DSP_MODE : dsp_stereo;
			samplesize = (samplesize == -1) ? DEF_SAMPLESIZE : samplesize;
		}

		switch(samplesize)
		{
			case 8:		if(strlen(audio_dev) == 0)
					{
						sprintf(audio_dev, "%s\0", DEF_8_DEVICE);
					}
					break;
			case 12:	if(strlen(audio_dev) == 0)
					{
						sprintf(audio_dev, "%s\0", DEF_12_DEVICE);
					}
					break;
			case 16:	if(strlen(audio_dev) == 0)
					{
						sprintf(audio_dev, "%s\0", DEF_16_DEVICE);
					}
					break;
		}



	}
#endif
}
