/*
 * Note: There are proper Allegro addons for OggVorbis now, such as alogg by
 * Vincent Penquerc'h (currently at http://lyrian.obnix.com/alogg/).
 * I leave this up to show who did it first ;-) --pw, 2002-08-20.
 */


/* vorbillegro.c
 *
 * Demonstration of using Ogg Vorbis in an Allegro program, or more
 * specifically, using vorbisfile with AUDIOSTREAM routines.  This is
 * a demo rather than a proper library as I have no need for Vorbis
 * streaming in a game at the moment, and because vorbisfile is so
 * simple to program anyway.  But if this is useful to you, I'd like
 * to hear about it.
 *
 * This file is based off vorbisfile_example.c in the Ogg Vorbis
 * source distribution, and so falls under the licence.  The original
 * copyleft message takes up the next comment block.  The LGPL itself
 * can be read somewhere on http://www.gnu.org/.
 *
 * Peter Wang <tjaden@users.sourceforge.net>, 17 November 2000.
 */


/*
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
 * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH    *
 * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.        *
 *                                                                  *
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
 * by Monty <monty@xiph.org> and the XIPHOPHORUS Company            *
 * http://www.xiph.org/                                             *
 */


#include <stdio.h>
#include <stdarg.h>
#include <allegro.h>
#include <vorbis/vorbisfile.h>


/* Loose variables.  */

static FILE *fp;
static OggVorbis_File vf;
static int current_section;
static AUDIOSTREAM *as;
static int buffer_size;
static int loaded;


/* Audiostream output format.  */
static const int samples = 64;
static const int bits = 16;
static const int stereo = TRUE;
static const int freq = 44100;
static const int volume = 255;
static const int panning = 128;

#ifdef ALLEGRO_BIG_ENDIAN
    static const int big_endian = 1;
#else
    static const int big_endian = 0;
#endif 


/* Ready a Vorbis file to be played.  Return TRUE on success.  */
int load_vorbis_stream (const char *filename)
{
    if (!(fp = fopen (filename, "rb")))
	return FALSE;

    if (ov_open (fp, &vf, NULL, 0) < 0) {
	fclose (fp);
	return FALSE;
    }

    /* XXX need to find stereocity and frequency of vorbis file */
    
    as = play_audio_stream (samples, bits, stereo, freq, volume, panning);
    if (!as) {
	ov_clear (&vf);
	return FALSE;
    }

    buffer_size = samples * ((bits == 16) ? 2 : 1) * (stereo ? 2 : 1);
    current_section = 0;
    loaded = 1;

    return TRUE;    
}


/* Free the file from memory.  */
void unload_vorbis_stream (void)
{
    if (loaded) {
	stop_audio_stream (as);
	ov_clear (&vf);
	loaded = 0;
    }
}


/* Decode and buffer a part of the stream.  Return -1 if the music
 * stopped, zero if the playback buffer is full, or 1 if data was
 * successfully decoded and buffered.  */
int poll_vorbis_stream (void)
{
    void *buffer;
    long size, x;

    size = buffer_size;

    while (size > 0) {
	buffer = get_audio_stream_buffer (as);
	if (!buffer)
	    return 0;

    	x = ov_read (&vf, buffer, size, big_endian, ((bits == 16) ? 2 : 1),
		     0, &current_section);
	free_audio_stream_buffer (as);

	if (x == 0)
	    return -1;
	else if (x < 0)
	    return 0;

	size -= x;
    }
    
    return 1;
}


/* Testing program.  */

int bg, fg;


int start_allegro ()
{
    allegro_init ();
    install_timer ();
    install_keyboard ();
    
    reserve_voices (1, 0);
    if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0) {
	allegro_message ("Error installing digital sound.\n");
	return 1;
    }
    
    set_gfx_mode (GFX_SAFE, 320, 200, 0, 0);

    bg = makecol (255, 255, 255);
    fg = makecol (0, 0, 0);
    clear_to_color (screen, bg);
    text_mode (bg);

    return 0;
}


void sayf (const char *fmt, ...)
{
    static int y = 0;
    char buf[512];
    va_list ap;

    va_start (ap, fmt);
    uvsprintf (buf, fmt, ap);
    va_end (ap);

    if (y > SCREEN_H - text_height (font))
	clear_to_color (screen, bg), y = 0;

    textout (screen, font, buf, 0, y, fg);
    y += text_height (font) + 1;
}


int main (int argc, char *argv[])
{
    int i;
    
    if (argc < 2) {
	allegro_message ("Pass a few Vorbis filenames on the command line.\n");
	return 1;
    }

    if (start_allegro ())
	return 1;

    sayf ("Welcome to Really Advanced Player 6091!");
    sayf ("Press a key to skip to the next song.");

    for (i = 1; i < argc; i++) {
	if (!load_vorbis_stream (argv[i])) {
	    sayf ("Error opening file `%s'.", argv[i]);
	    continue;
	}

	sayf ("Playing file `%s'.", get_filename (argv[i]));

	while (!keypressed ()) {
	    if (poll_vorbis_stream () < 0)
		break;
	    yield_timeslice ();
	}
	clear_keybuf ();

	unload_vorbis_stream ();
    }

    sayf ("Done.  Press any key to quit.");
    readkey ();

    return 0;
}

END_OF_MAIN ();


/* vorbillegro.c ends here.  */

