/* > demo.c

 * SJ Middleton, 1993

 * This file gives a demonstration of how to use the armovie_playfile() function.
 * It allows you to load up sound data into memory and supply the data on demand
 * so instant access is possible.

 */

#include "dbox.h"
#include "flex.h"
#include "xferrecv.h"
#include "werr.h"
#include "wimpt.h"

#include <stddef.h>

#include "armovie.h"
#include "utils.h"

#define DEMO_IDENT  "demo"

/* template fields */

#define FILENAME_FIELD  4
#define BUTTON1_FIELD   0
#define BUTTON2_FIELD   1
#define BUTTON3_FIELD   2

static dbox         demo_d = NULL;
static armovie_hdr  *demo_hdr = NULL;

static void         *sound_chunks[3] = { 0, 0, 0 };

/*
 * - Set the dialogue box field to the given filename,
 * - stores a pointer to the header structure in the static demo_hdr
 *   (this header is needed to pass to the playfile() function).
 * - load the first three chunks into flex blocks stored in sound_chunks[] above.
 */

static BOOL load_file(dbox d, const char *filename)
{

/* clear anything else loaded */
    if (demo_hdr)
    {
        dbox_setfield(d, FILENAME_FIELD, "");
        armovie_freehdr(demo_hdr);
    }

    if (armovie_identify(filename, &demo_hdr))
    {
        armovie_soundstr    *sp = demo_hdr->sound;
        filehandle          f;

/* check there is sound in this movie */
        if (sp == NULL || sp->format == 0)
        {
            werr(0, "Movie '%s' has no soundtracks", filename);
            return FALSE;
        }

/* load upto three chunks from the movie */
        if (wimpt_complain(file_open(fopt_Read, filename, &f)) == NULL)
        {
            armovie_catentry *chunks = sp->chunks;

            int i, nchunks = demo_hdr->nchunks > 3 ? 3 : demo_hdr->nchunks;

            for (i = 0; i < nchunks; i++)
            {
                if (f_alloc(&sound_chunks[i], chunks[i].size))
                    wimpt_complain(file_readfrom(f, sound_chunks[i], chunks[i].size, chunks[i].offset));
            }

/* clear unused chunks */
            for (; i < 3; i++)
                f_free(&sound_chunks[i]);

            file_close(f);
        }

        dbox_setfield(d, FILENAME_FIELD, (char *)filename);
    }
    return TRUE;
}

/*
 * This function will be called ARLib to find the sound data.
 * It takes the header information and the start and end time that
 * were passed in to armovie_playfile() and works out what chunks are needed
 * then asks for pointers to them and their sizes.
 * Which is what this function gives.
 */

static os_error *loadchunk_fn(int chunk, char **pptr, int *pnbytes, int reference, void *handle)
{
    *pptr = sound_chunks[chunk];
    *pnbytes = flex_size(&sound_chunks[chunk]);

    return NULL;
    reference = reference;
    handle = handle;
}

/*
 * This is called from the button press routine.
 * It causes the given chunk to play 3 times.

 * Note you could give whatever start and end times you want
 * ARLib would work out which chunks it referred to and ask
 * for them in the loadchunk function.
 */

static void play_chunk(int chunk)
{
    if (sound_chunks[chunk])
    {
        int chunk_size = (int)(demo_hdr->frames_per_chunk*100.0/demo_hdr->fps);
        armovie_playfile("", demo_hdr,
            chunk*chunk_size,                       /* from in cs */
            (chunk + 1)*chunk_size - 1,             /* to in cs */
            3,                                      /* loops */
            arplay_Loop | arplay_PlayChunk | arplay_ExternalData,   /* flags */
            1,                                      /* soundtrack */
            0,                                      /* reference */
            loadchunk_fn, NULL);

        armovie_eventhandler(0, NULL);
    }
}

/*
 * Handle button press and close events.
 */

static void demo_events(dbox d, void *handle)
{
    dbox_field action = dbox_get(d);
    switch (action)
    {
        case dbox_CLOSE:
        {
            int i;

            armovie_stopsound();                /* really should check it is us playing first */

            for (i= 0; i < 3; i++)              /* free up all used memory on window close */
                f_free(&sound_chunks[i]);

            armovie_freehdr(demo_hdr);
            demo_hdr = NULL;

            dbox_dispose(&demo_d);
            demo_d = NULL;

            break;
        }

        case BUTTON1_FIELD:
            play_chunk(0);
            break;

        case BUTTON2_FIELD:
            play_chunk(1);
            break;

        case BUTTON3_FIELD:
            play_chunk(2);
            break;
    }
    handle = handle;
}

/*
 * Load file when dropped in window
 */

static BOOL demo_rawevents(dbox d, void *e, void *handle)
{
    char *filename;
    if (xferrecv_checkinsert(&filename) == filetype_ARMovie)
    {
        load_file(d, filename);
        xferrecv_insertfileok();
        return TRUE;
    }

    return FALSE;
    handle = handle;
}


void demo_open(void)
{
    if (demo_d == NULL)
    {
        if ((demo_d = dbox_new(DEMO_IDENT)) != NULL)
        {
            dbox_showstatic(demo_d);
            dbox_eventhandler(demo_d, demo_events, NULL);
            dbox_raw_eventhandler(demo_d, demo_rawevents, NULL);
        }
    }
}

/* eof demo.c */
