/*********************************************************************
 *	play_select.c - exercises output interface of an OSS sound driver
 *			using select() 
 *	Copyright (C) 2000 Rui Sousa 
 ********************************************************************* 
 *     This program is free software; you can redistribute it and/or 
 *     modify it under the terms of the GNU General Public License as 
 *     published by the Free Software Foundation; either version 2 of 
 *     the License, or (at your option) any later version. 
 * 
 *     This program is distributed in the hope that it will be useful, 
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *     GNU General Public License for more details. 
 * 
 *     You should have received a copy of the GNU General Public 
 *     License along with this program; if not, write to the Free 
 *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
 *     USA. 
 ********************************************************************* 
*/

#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include "common.h"
#include <sys/soundcard.h>
#include <sys/ioctl.h>

/* select() returns when it's possible to write one
   entire fragment. If write() is called with a fragment
   sized buffer it won't fail and the entire buffer is
   written. */
int main()
{
	int audio_fd;
	__u8 devbuf[BUF_SIZE];
	__u8 *buf;
	int dev_ptr;
	struct wave wave[CHANNELS];
	int ret, val;
	audio_buf_info ospace_info;
	int fragsize;
	mode_t mode;
	unsigned int channel;
	fd_set set;

	mode = O_WRONLY | O_NONBLOCK;

	audio_fd = setup("/dev/dsp", mode);

	
        for (channel = 0; channel < CHANNELS; channel++)
        {
                wave[channel].w = 2.0 * M_PI * freq[channel] / SPEED;
                wave[channel].t0 = 0.0;
        }

	FD_ZERO(&set);
	FD_SET(audio_fd, &set);

	if ((ret = ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &ospace_info)) == -1)
		perror("SNDCTL_DSP_GETOSPACE");

	fragsize = ospace_info.fragsize;

	while (1) {

		if (DEBUG)
			print_info(audio_fd, mode);

		fill_devbuf(wave, devbuf);

		dev_ptr = 0;
		buf = devbuf;
		ret = 0;
		while (dev_ptr < BUF_SIZE)
		{
			/* wait till we can write a fragment */
			select(FD_SETSIZE, NULL, &set, NULL, NULL);

			val = (BUF_SIZE - dev_ptr < fragsize) ? BUF_SIZE - dev_ptr : fragsize;
			if ((ret = write(audio_fd, buf + dev_ptr, val)) == -1) {
				perror("audio write");
			}

			if (DEBUG)
				printf("(write)\ncount: %d ret: %d\n\n", val, ret);

			/* to be safe this should be ret, the value actually written,
			   but since we want to test it assume the entire fragment was
			   written */
			dev_ptr += val;
		}
	}

	close(audio_fd);

	return 0;
}
