 /*********************************************************************
 *	play_sleep.c - exercises output interface of an OSS sound driver
 *			continuosly writing to /dev/dsp
 *	Copyright (C) 1999-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 "time.h"
#include <sys/soundcard.h>
#include <sys/ioctl.h>

/* write countinously to /dev/dsp.
   write may return before writing the entire buffer
   so loop until it's done. We sleep between writes */
int main()
{
	int audio_fd;
	__u8 devbuf[BUF_SIZE];
	__u8 *buf;
	struct wave wave[CHANNELS];
	mode_t mode;
	struct timespec t;
	unsigned int channel;
	int ret, val;
	audio_buf_info ospace_info;
        int fragsize;
	int bytespersec;

	mode = O_WRONLY | O_NONBLOCK;

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

	switch (FORMAT) {

	case AFMT_S8:
	case AFMT_U8:
		bytespersec = SPEED * CHANNELS * 1;
		break;
	case AFMT_S16_LE:
	case AFMT_S16_BE:
	case AFMT_U16_LE:
	case AFMT_U16_BE:
		bytespersec = SPEED * CHANNELS * 2;
		break;
	}

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

	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);

		ret = 0;
		buf = devbuf;
		do {
			if (ret != -1) {
				val -= ret;
				buf += ret;
			}


			val = fragsize;
			if ((ret = write(audio_fd, buf, val)) == -1) {
				perror("audio write");
			}

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

			if (ret == -1) {
				t.tv_nsec = (double) fragsize / bytespersec * 1e9;
				t.tv_sec = (int) ((double)fragsize / bytespersec);

				t.tv_nsec -= t.tv_sec * 1000000000;

				if (nanosleep(&t, NULL) < 0)
					perror("not sleeping");
			}
		}
		while (ret < val);
	}

	close(audio_fd);

	return 0;
}
