/* First stab at an ogg player
 * Dan Pemstein
 * Thu Sep  5 02:13:54 CDT 2002
 *
 * Smushed these two example files together:
 * http://www.xiph.org/ogg/vorbis/doc/vorbisfile/example.html
 * http://docs.meg.nu/local-docs/libao/ao_example.c
 *
 * gcc -lao -lvorbis -lvorbisfile -lm -lncurses -o tryao tryao.c
 *
 *
 */

#include <math.h>
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <ao/ao.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>

#define BUF_SIZE 4096
#define SEEK_SIZE 1

int main(int argc, char **argv)
{
	/* ao vars */
	ao_device *device;				/* the sound card */
	ao_sample_format format;	/* Struct holding bits, rate, channels */
	int default_driver;				/* OSS, ALSA, etc */

	/* vorbis vars */
	OggVorbis_File vf;
	vorbis_info *vi;
	long ret;
	int current_section;
	FILE *f;

	/* curses stuff */
	WINDOW *win;
	int ch;
	
	/* shared vars */
	char pcmout[BUF_SIZE];				/*  play buffer */
	int i;
	double time;
	int hr, min, sec;
	int thr, tmin, tsec;


	/* Open our vorbis file */
	if ((f = fopen(argv[1], "r")) == NULL) {
		printf("Error opening %s\n", argv[1]);
		return 1;
	}

	/* vorbis initialization */
	if (ov_open(f, &vf, NULL, 0) < 0) {
		printf("Input isn't ogg\n");
		return 1;
	}

	/* Get channel and bitrate info and set the format for ao */
	vi = ov_info(&vf, -1);
	format.bits = 16;		/* hard-code this (are all vorbi 16bit?) */
	format.channels = vi->channels;
	format.rate = vi->rate;
	format.byte_format = AO_FMT_LITTLE; /* what endian, could be a pain*/
	
	/* AO initialization:  We will let the library choose the driver */
	ao_initialize();
	default_driver = ao_default_driver_id();

	device = ao_open_live(default_driver, &format, NULL);
	if (device == NULL) {
		printf("Couldn't find default driver\n");
		return 1;
	}

	/* do some curse stuff */
	if ((win = initscr()) == NULL) {
		perror("Error initing curses\n");
		return 1;
	}

	noecho(); /* turn of key echo */
	nodelay(win, TRUE); /* non-blocking reads */
	keypad(win, TRUE); /* enable the keypad */

	time = ov_time_total(&vf, -1);
	thr = floor(time / 3600);
	tmin = floor(time / 60) - (60 * thr);
	tsec = floor(time) - (60 * tmin);
	/* main loop */
	while (1) {
		ch = getch();
		if (ch == KEY_LEFT)
			i = ov_raw_seek(&vf, ov_raw_tell(&vf) - (4 * BUF_SIZE));
		else if (ch == KEY_RIGHT)
			i = ov_raw_seek(&vf, ov_raw_tell(&vf) + SEEK_SIZE);
		else if (ch == 'x')
			break;

		time = ov_time_tell(&vf);
		hr = floor(time / 3600);
		min = floor(time / 60) - (60 * hr);
		sec = floor(time) - (60 * min);
	
		deleteln();
		mvaddstr(5, 10, "Fast forward: ->, Rewind: <-, Stop: x");
		mvprintw(10, 10, "%d:%d:%d / %d:%d:%d",
				hr, min, sec, thr, tmin, tsec);
		mvprintw(11, 10, "%d", ov_bitrate_instant(&vf));
		refresh();
		ret = ov_read(&vf, pcmout, BUF_SIZE, 0, 2, 1,
				&current_section);
		if (ret == 0)
			break;
		ao_play(device, pcmout, ret);
	}
	/* clean up ao */
	ao_close(device);
	ao_shutdown();

	/* clean up vorbis */
	ov_clear(&vf);

	/* clean up curses */
	delwin(win);
	endwin();
	refresh();
	
	return 0;
}
