/* > arsound.h

 * SJ Middleton, 1994

 * This has headers and prototypes relating to the handling of the
 * Acorn Replay sound playback resources.

 */


#ifndef __arsound_h
# define __arsound_h

#ifndef __armovie_h
# include "armovie.h"
#endif

/*
 * The address of a word containing these flags is passed to the play entry point.
 * This word must be in the RMA as it can be updated by the sound routines.
 */

typedef enum
{
    arsound_Pause       = 0x01,     /* whilst this bit is set, no sound is played but all structures are held */
    arsound_Mute        = 0x02,     /* whilst this bit is set everything happens as normal except no sound comes out */
    arsound_Exit        = 0x04      /* whilst this bit is set no data is transferred to DMA buffers, used for background stop */
} arsound_muteflag;

/* returned in out_flags */

typedef enum
{
    arsound_NoTiming        = 0x01, /* don't have to wait for a second to time sound system */
    arsound_QualityCosts    = 0x02, /* higher quality results in increased CPU overhead */
    arsound_SoundSystemOff  = 0x04  /* sound system was disabled so timing didn't occur */
} arsound_outflag;

typedef struct
{
    volatile arsound_muteflag   flags;  /* as above */
    int     chunktime;                  /* should be set to zero for Multi-tasking playback */
    int     frequency_int,              /* 32. */
            frequency_frac;             /* 0.24 */
    char    quality;                    /* TBA */
    char    reversed;                   /* 1 = RL, 0 = LR */
    char    reserved0[2];
    int     reserved1[11];
} arsound_pollstr;

/*
 * This structure represents the double sound buffers.
 */

typedef struct
{
    unsigned int count;         /* number of samples left to play */
    volatile int empty;         /* 0 = playing, 1 = finished/empty, 2 = data not played */
    void        *start;         /* points into buffer */

/* followed by data */

} arsound_buffer;

/*
 * This structure represents the start of the playback code as stored on disc
 * and as loaded into the RMA. Note that the use of any reserved or unnamed
 * entry points is not guaranteed to remain the same between versions of the
 * Sound code.
 */

typedef struct
{
    unsigned int    play_entry,     /* B play code */
                    stop_entry,     /* B stop code */
                    data_entry;     /* B new data code */

    arsound_outflag flags;          /* flags returned to caller */

    arsound_buffer  *sndbufA,
                    *sndbufB;

    int             reserved6[3];

    int             samples_played_int,
                    samples_played_frac;

/* and other private workspace values */

} arsound_hdr;

/* Function prototypes */

/* ============================================================================ */

/* WRAPPER ROUTINES */

/*
 * Call the entry points in arsound_hdr
 */

extern BOOL arsound_play(int sndratio);
extern void arsound_stop(void);
extern void arsound_data(void *data, size_t size);

/* From arsndcode.c */

/* ============================================================================ */

/* SOUNDCODE FILE ROUTINES */

/* ----------------------- armovie_getsoundcode -------------------------------
 *
 * Description: loads up the appropriate piece of sound playback code for a
 *              given sample type.
 * Parameters:  const armovie_soundstr *sound - sound parameters
 * Returns:     success
 * Notes:       This code works out which of the playback code modules is needed
 *              and loads it into the RMA.
 *              If it is already loaded it sets up control values and returns.
 */

extern BOOL armovie_getsoundcode(const armovie_soundstr *sound);


/* ---------------------- armovie_unloadsoundcode ------------------------------
 *
 * Description: frees up the RMA space used by the sound playback code
 * Notes:       best to put this function on an exit handler. It won't object
 *              if it is called more than once. It first frees the sound buffers.
 */

extern void armovie_unloadsoundcode(void);



/* ============================================================================ */

/* INFORMATION ROUTINES */

/* ------------------------- arsound_bufferstatus ------------------------------
 *
 * Description: examine emptiness of sound buffers
 * Parameters:  none
 * Returns:     bit 0 set = A buffer is empty
 *              bit 1 set = B buffer is empty
 */

extern int arsound_bufferstatus(void);

/* ------------------------- arsound_samplesplayed ----------------------------
 *
 * Description: get position in movie
 * Parameters:  none
 * Returns:     number of input samples played since arsound_play was called
 */

extern int arsound_samplesplayed(void);


/* ------------------------- armovie_setmute -----------------------------------
 *
 * Description: write to the mute flags address in the RMA
 * Parameters:  arsound_muteflag flags -- new flags to write
 * Returns:     void
 */

extern void arsound_setmute(arsound_muteflag flags);


/* ------------------------- armovie_readmute ----------------------------------
 *
 * Description: read the mute flags from the RMA
 * Parameters:  void
 * Returns:     arsound_muteflag flags -- flag state
 */

extern arsound_muteflag arsound_readmute(void);



/* ============================================================================ */

/* TIMING ROUTINES */


/* ------------------------- armovie_starttiming ------------------------------
 *
 * Description: Initiate timing of sound card
 * Parameters:  none
 * Returns:     TRUE if timing started successfully.
 */

extern BOOL armovie_starttiming(void);

/* ------------------------- armovie_finishtiming -----------------------------
 *
 * Description: Force timing to finish
 * Parameters:  none
 * Notes:       Calls the alarm function setup by starttiming() directly.
 */

extern void armovie_finishtiming(void);

/* ------------------------- armovie_checktiming ------------------------------
 *
 * Description: Calls start timing if necessary.
 * Parameters:  none
 * Returns:     success
 */

extern BOOL armovie_checktiming(void);

/* ------------------------- armovie_invalidateclickrate----------------------
 *
 * Description: flags current timing info as invalid
 * Parameters:  none
 * Returns:     TRUE if invalidation means that sound should be stopped
 * Info:        call when mode has changed.
 */

extern BOOL armovie_invalidateclockrate(void);


/* ============================================================================ */

/* DEVICE ROUTINES */

/*
 * Note that device claiming only works with the internal sound system since
 * otherwise the device claim number is not name.
 * The value of ARMovie$SoundDir is compared with <ARMovie$Dir>.MovingLine
 * to see if the internal sound system is being used.
 */

/* ------------------------- armovie_releasefn --------------------------------
 *
 * Description: function called when sound system is claimed
 * Parameters:  const char *info -- info passed in msg data block
 *              void *handle -- handle registered with setreleasefn
 * Returns:     FALSE to return a DeviceInUse message to claiming task,
 *              else our task should shut down all its playback facilities and
 *              return TRUE.
 */

typedef BOOL (*armovie_releasefn)(const char *info, void *handle);

/* ------------------------- armovie_setreleasefn -----------------------------
 *
 * Description: Set function to be called when another application claims
 *              sound device.
 * Parameters:  armovie_releasefn fn -- function ptr
 *              void *handle -- context to call function with
 * Returns:     void
 * Notes:       function registered will be called if a Message_DeviceClaim for
 *              the sound system is received.
 */

extern void armovie_setreleasefn(armovie_releasefn fn, void *handle);

/* ------------------------- armovie_claimsounddevice -------------------------
 *
 * Description: ensures sound device is claimed
 * Parameters:  none
 * Returns:     success of claim
 * Notes:       use this to claim device before entering a non-multitasking mode
 *              for example.
 */

extern BOOL armovie_claimsounddevice(void);

/* ------------------------- armovie_releasesounddevice -------------------------
 *
 * Description: ensures sound device has been released
 * Parameters:  none
 * Returns:     void
 * Notes:
 */

extern void armovie_releasesounddevice(void);


/* ============================================================================ */

/* MEMORY ROUTINES */


/* --------------------- armovie_claimsoundbuffers -----------------------------
 *
 * Description: claims buffer space for sound playback
 * Parameters:  int nsamples -- the maximum number of samples in a sound chunk.
 * Returns:     TRUE if successful.
 * Notes:       will claim 2 buffers of (nsamples*output size + 16) bytes.
 */

extern BOOL armovie_claimsoundbuffers(const armovie_soundstr *sound, int nsamples);


/* --------------------- armovie_releasesoundbuffers ---------------------------
 *
 * Description: release RMA buffers claimed by armovie_claimsoundbuffers
 * Parameters:  none
 * Returns:     none
 * Notes:       This function won't object if it is called more than once.
 */

extern void armovie_releasesoundbuffers(void);


/* ------------------------- armovie_registersoundmemfns ----------------------
 *
 * Description: register memory allocators for sound buffers
 * Parameters:  see memalloc.h
 * Returns:     void
 * Notes:       These functions are used for controlling the memory registered
 *              with the sound code as buffers. The sound code itself is
 *              always loaded into the RMA. You should only use c_alloc,
 *              m_alloc or d_alloc with this function as the memory cannot
 *              be allowed to move.
 */

extern void armovie_registersoundmemfns(mem_allocfn alloc_fn, mem_freefn free_fn);

#endif

/* eof arsound.h */
