/* armovie.h

 * SJ Middleton, 1994

 * C defines and prototypes for Acorn Replay library

 */

#ifndef __armovie_h
# define __armovie_h

#ifndef __os_h
# include "os.h"
#endif

#ifndef __memalloc_h
# include "memalloc.h"
#endif

#ifndef __replaytype_h
# include "replaytype.h"
#endif

/*
 * Flags showing elements of the armovie header
 */

typedef enum
{
    armovie_ReversedStereo  = 0x00000001,   /* 1 = RL, 0 = LR */

/* read from Info file */
    armovie_Seekable        = 0x00000020    /* 1 = can start from any sample, 0 = must start from chunk */
} armovie_soundflag;

typedef enum
{
    armovie_ColourSpace     = 0x0000000f    /* see replaytype.h for types */
} armovie_hdrflag;

typedef struct
{
    int     offset,                     /* byte offset in file of chunk */
            size;                       /* size of chunk in bytes */
} armovie_catentry;

typedef struct
{
    int     format;                 /* 0 = no sound */
    double  rate;                   /* > 255 then in Hz, < 256 then in s */
    char    channels,               /* 1 or 2 currently */
            precision,              /* bits per sample */
            sndmul;                 /* decompressed bits per sample from file */

    int     max_soundsize;          /* largest sound chunk in file */

    armovie_soundflag   sflags;     /* as above */

    armovie_catentry    *chunks;    /* chunks for this track */

    char    filename[11];   /* decompressor - dirname if format 2, filename if format 1 */
} armovie_soundstr;

typedef struct
{
    char    *name,                  /* space allocated using malloc */
            *date,                  /* " */
            *author;                /* " */

    int     video_format,           /* 0 = no video */
            xsize,                  /* in pixels */
            ysize,                  /* in pixels */
            bpp,                    /* bits per pixel for video */
            frames_per_chunk,
            nchunks,                /* +1 from version in header so real number of chunks */
            nframes,                /* total number of frames */
            catalogue_offset,       /* in bytes from start of file */
            sprite_offset,          /* " */
            sprite_size,            /* in bytes (stored as a complete standard spritefile) */
            key_frame_offset,       /* in bytes from start of file, <= 0 no key frames */
            palette_offset;         /* from start of file */

    double  fps;                    /* frames per second */

    int     even_chunksize,         /* total chunks sizes audio and video */
            odd_chunksize;

    int     fsr;                    /* sample rate divisor (from name) */
    int     start_timecode;         /* in frames */
    int     base_timecode;          /* frames per second of start_timecode */

    armovie_hdrflag     flags;          /* as above */

    int                 nsoundtracks;   /* defines size of structure below */
    armovie_soundstr    *sound;         /* ptr to malloced data structure */

    armovie_catentry    *video_chunks;  /* chunks of video data */

    void    *palette_data;              /* optional palette data, probably never to be used */

    int     catalogue_size;             /* size of cat data in bytes */

    char    *indirected_filename;       /* indirected filename for MPEG etc. from video type line */
} armovie_hdr;

/* -------------------------------------------------------------------------- */

/* Function prototypes */

/* From arlibmain.c */

/* -------------------------- armovie_init -------------------------------------
 *
 * Description: initialise the armovie playback system.
 * Parameters:  void
 * Returns:     void
 * Notes:       This function should be called before any use of
 *              armovie_playsound(). It sets up an unknown message handler to
 *              catch mode changes so that it always knows when the VIDC clock
 *              rate may have changed. Then the next time a sound is played
 *              it will retime VIDC before starting playing.
 *              It also calls atexit(armovie_cleanup).
 */

extern void armovie_init(void);


/* -------------------------------------------------------------------------- */
/* From armovie.c */

/*
 * Abstract handle for a movie that is playing or opened for some other purpose.
 */

typedef struct armovie__str *armovie;

/*
 * Code as passed to the completion function.
 * Check for code <= armovie_Aborted to find out if playing has stopped.
 */

typedef enum
{
    armovie_Completed,          /* finished playing successfully */
    armovie_Error,              /* error occurred so stopped playback */
    armovie_ModeChange,         /* finished because a mode change happened */

    armovie_Aborted = 63,       /* killed off for some reason */
    armovie_LastChunk = 64,     /* just loaded last chunk of current movie */
    armovie_CompletedButMore    /* finished one movie, but more pending */
} armovie_returncode;


/* ----------------------- armovie_eventfn ------------------------------------
 *
 * Description: user function called by playback task when sound finishes or
 *              error occurs.
 * Parameters:  int reference -- as passed in to playsound
 *              armovie_returncode code -- code as above.
 *              void *handle -- context pointer as passed in with function.
 * Notes:       armovie_Aborted is guaranteed to be the highest return code that
 *              has caused all playback to stop. So check for
 *              code <= armovie_Aborted to see if playback has  finished.
 */

typedef void (*armovie_eventfn)(int reference, armovie_returncode code, void *handle);

/* ----------------------- armovie_eventhandler -------------------------------
 *
 * Description: register the above event function with the ARLib system
 * Paameters:   armovie_eventfn fn -- function to call with event codes as above
 *              void *handle -- context pointer to call function with.
 * Returns:     NULL
 * Notes:       You can call this function as many times as you want, only the
 *              most recent function and pointer will be used.
 */

extern void armovie_eventhandler(armovie_eventfn fn, void *handle);


/*
 * flags passed in to armovie_playsound
 */

typedef enum
{
    arplay_Loop             = 0x00000001,
    arplay_LoopIndefinite   = 0x00000002,   /* 1 = loop for ever, 0 = use loop count */
    arplay_PlayChunk        = 0x00000004,   /* use play_from and play_to */
    arplay_LoopFromStart    = 0x00000008,   /* 1 = loop back to 0 even if we started halfway through */
    arplay_QueueSound       = 0x00000040,   /* 1 = play when current sound finishes */
    arplay_ExternalData     = 0x00000080,   /* 1 = don't open file or allocate temp buffer */
    arplay_StartMute        = 0x00000100,   /* 1 = start playing with mute enabled */
    arplay_StartPause       = 0x00000200    /* 1 = start playing with pause enabled */
} armovie_playflag;

/* ------------------------ armovie_playsound ---------------------------------
 *
 * Description: initiate multi-tasking sound-only playback of an Replay movie.
 *
 * Parameters:  const char *filename -- filename of movie file
 *              int play_from -- offset in cs into movie to start playing. (-1 = start)
 *              int play_to -- offset in cs into movie to stop playing. (-1 = end)
 *              int loop_for -- number of times to loop through the above chunk.
 *              armovie_playflag playflags -- flags as above.
 *              int soundtrack -- soundtrack number (from 1).
 *              int reference -- handle to identify movie with
 *
 * Returns:     a handle for the movie playing or NULL is failure.
 *
 * Notes:       This function sets up everything needed for playback, including
 *              loading the sound code, claiming memory in the RMA, claiming and
 *              setting up the sound system, and starting up a repeating alarm
 *              function to keep the playback code fed with chunks of data.

 *              The movie file will be kept open until the completion function
 *              is called, although this function will return immediately.

 *              Even if a late start time is given, the last chunk of the movie
 *              will always be played and the completion function will never be
 *              called until after this function has returned.

 *              Note the play_to time is inclusive, so to play the first 2
 *              seconds of a movie play from 0 to 199.
 */

extern armovie armovie_playsound(const char *filename, int play_from, int play_to, int loop_for,
            armovie_playflag playflags, int soundtrack, int reference);


/* ----------------------- armovie_stopsound ---------------------------------
 *
 * Description: stop a sound started with armovie_playsound().
 * Parameters:  None
 * Returns:     void
 * Notes:       stops playback, frees buffers etc. Does everything as if you'd
 *              waited for the sound to finish on its own except call the
 *              completion function.
 */

extern void armovie_stopsound(void);


/* ------------------------ armovie_getpos ------------------------------------
 * Description: how far through playback is a movie
 * Parameters:  int *t -- offset in centi-seconds from start of current movie.
 *              int *nloops -- if non-NULL this will hold the number of times
 *                              through that the the movie has been played.
 * Returns:     reference code of current movie (as originally passed in).
 *              -1 if no movie playing.
 */

extern int armovie_getpos(int *t, int *nloops);


/* ------------------- armovie_registermemfns --------------------------------
 *
 * Description: register memory functions to use when allocating memory for
 *              temporary space
 * Parameters:  mem_allocfn alloc_fn -- used to get space
 *              mem_freefn free_fn -- used to free space
 * Returns:     void
 * Notes:       Initially c_alloc and c_free are used to get space.
 *              This function is provided so that f_alloc and f_free can be used
 *              instead if the application already uses the flex module. Flex
 *              means less memory tied up permanently and less chance of heap
 *              fragmentation but higher overheads.

 *              In short: if you already use flex then call
 *                  armovie_registermemfns(f_alloc, f_free);
 *              just after armovie_init().
 *              Otherwise do nothing.
 */

extern void armovie_registermemfns(mem_allocfn alloc_fn, mem_freefn free_fn);

/* ------------------- armovie_registercataloguememfns --------------------------
 *
 * Description: register memory functions to use when allocating memory for
 *              chunk catalogues
 * Parameters:  mem_allocfn alloc_fn -- used to get space
 *              mem_freefn free_fn -- used to free space
 * Returns:     void
 * Notes:       Initially c_alloc and c_free are used to get space.
 */

extern void armovie_registercataloguememfns(mem_allocfn allocfn, mem_freefn freefn);

/* -------------------------------------------------------------------------- */

/* The following functions are for internal use and shouldn't need to be called by a client */


/* ------------------------- armovie_modechange -------------------------------
 * Description: Tell system that mode has change.
 * Parameters:  none
 * Returns:     void
 * Notes:       call this function when the mode has changed. It will stop any
 *              current movie and flag that sound system may need retiming.
 */

extern void armovie_modechange(void);


/* -------------------------- armovie_abort -----------------------------------
 * Description: stop playback and send abort to client
 * Parameters:  see arsound.h
 * Returns:     TRUE always
 * Notes:       This function is for registering as an upcall with arsndcode
 *              to be used when somebody else takes the sound system device away
 *              from us.
 */

extern BOOL armovie_abort(const char *info, void *handle);


/* ------------------------- armovie_cleanup ----------------------------------
 * Description: cleanup system prior to exit
 * Parameters:  none
 * Returns:     void
 * Notes:       call this function before quitting application. It could be
 *              passed as a parameter to atexit().
 */

extern void armovie_cleanup(void);


typedef os_error *(*armovie_loadchunk_fn)(int chunk, char **pptr, int *pnbytes, int reference, void *handle);

/* ------------------------- armovie_playfile ---------------------------------
 *
 * Description: initiate multi-tasking sound-only playback of a general file
 *
 * Parameters:  const char *filename -- filename of movie file
 *              int play_from -- offset in cs into movie to start playing. (-1 = start)
 *              int play_to -- offset in cs into movie to stop playing. (-1 = end)
 *              int loop_for -- number of times to loop through the above chunk.
 *              armovie_playflag playflags -- flags as above.
 *              int soundtrack -- soundtrack number (from 1).
 *              int reference -- handle to identify movie with
 *              armovie_loadchunk_fn fn -- function to call to get sound data
 *              void *handle -- handle to call above function with
 *
 * Returns:     a handle for the movie playing or NULL is failure.
 * Notes:       this is mainly for use by Empire. It is like playsound except
 *              that 'hdr' should contain all the appropriate information about
 *              the sound. and data is gotten by calling the loadchunk function
 *              rather than directly from the file.
 */

extern armovie armovie_playfile(const char *filename, armovie_hdr *hdr, int play_from, int play_to, int loop_for, armovie_playflag playflags, int soundtrack, int reference, armovie_loadchunk_fn fn, void *handle);


/* From arhdr.c and arhdr1.c */

/* ------------------------ armovie_identify -----------------------------------
 *
 * Description: pull out the important information about a replay file
 * Parameters:  const char *filename -- filename of movie file
 *              armovie_hdr **hdrp -- a pointer to the movie info will be stored here if not NULL.
 * Returns:     TRUE if file was a movie.
 * Notes:       the header info is put into areas allocated with malloc().
 *              To free the space use armovie_freehdr().
 *              gives errors with werr() if there are any problems.
 */

extern BOOL armovie_identify(const char *filename, armovie_hdr **hdrp);

/* ------------------------ armovie_freehdr ------------------------------------
 *
 * Description: Free the memory returned by armovie_identify()
 * Parameters:  armovie_hdr *hdr -- pointer to info as written back by armovie_identify()
 * Returns:     void
 */

extern void armovie_freehdr(armovie_hdr *hdr);

/* ------------------------ armovie_validate_soundtrack ------------------------
 *
 * Description: check that a movie is actually playable with the current library
 * Parameters:  const armovie_hdr *hdr -- hdr info as written by armovie_identify.
 *              int track -- soundtrack number to play.
 * Returns:     TRUE if armovie_playsound() could play this soundtrack.
 * Notes:       gives errors with werr() describing why it wouldn't play.
 */

extern BOOL armovie_validate_soundtrack(const armovie_hdr *hdr, int track);


/* ------------------------ armovie_readhdr -----------------------------------
 *
 * Description: Read the important bits of a movie file header
 * Parameters:  const char *filename -- movie file name
 * Returns:     ptr to a malloced movie hdr descriptor. free up with armovie_freehdr().
 * Notes:       This function doesn't return errors if the file runs out before
 *              it has read all the information, so it can be used for scanning
 *              header files before they are joined with video/audio data.
 */

extern armovie_hdr *armovie_readhdr(const char *filename);
extern armovie_hdr *armovie_readhdrto(const char *filename, int line);

extern armovie_hdr *armovie_scanhdr(unsigned f);
extern armovie_hdr *armovie_scanhdrto(unsigned f, int line);

/* --------------------- armovie_disposecataloguememory ------------------------
 *
 * Description: Dispose of video and sound catalogue arrays
 * Parameters:  armovie_hdr *hdr -- as returned by armovie_identify.
 * Notes:       frees hdr->sound[].chunks and hdr->video_chunks and sets the
 *              relevant ptrs to NULL.
 */

extern void armovie_disposecataloguememory(armovie_hdr *hdr);

extern BOOL armovie_alloccatalogue(armovie_catentry **anchor, int nentries);
extern void armovie_freecatalogue(armovie_catentry **anchor);
extern BOOL armovie__readcatalogue(unsigned int f, armovie_hdr *hdr);

#endif

/* eof armovie.h */
