Decoder interface additions and changes
in preparation for the upcoming CDP architecture -- support for registering external decoders git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1279 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -36,11 +36,12 @@
|
||||
extern bool fileExists2(uio_DirHandle *dir, const char *fileName);
|
||||
// Can't '#include "libs/file.h"' due to some type conflicts.
|
||||
|
||||
#define MAX_REG_DECODERS 31
|
||||
|
||||
#define THIS_PTR TFB_SoundDecoder*
|
||||
|
||||
static const char* bufa_GetName (void);
|
||||
static bool bufa_InitModule (int flags);
|
||||
static bool bufa_InitModule (int flags, const TFB_DecoderFormats*);
|
||||
static void bufa_TermModule ();
|
||||
static uint32 bufa_GetStructSize (void);
|
||||
static int bufa_GetError (THIS_PTR);
|
||||
@@ -83,7 +84,7 @@ typedef struct tfb_bufsounddecoder
|
||||
#define SD_MIN_SIZE (sizeof (TFB_BufSoundDecoder))
|
||||
|
||||
static const char* nula_GetName (void);
|
||||
static bool nula_InitModule (int flags);
|
||||
static bool nula_InitModule (int flags, const TFB_DecoderFormats*);
|
||||
static void nula_TermModule ();
|
||||
static uint32 nula_GetStructSize (void);
|
||||
static int nula_GetError (THIS_PTR);
|
||||
@@ -124,22 +125,24 @@ typedef struct tfb_nullsounddecoder
|
||||
#undef THIS_PTR
|
||||
|
||||
|
||||
static struct sd_DecoderInfo
|
||||
struct TFB_RegSoundDecoder
|
||||
{
|
||||
bool builtin;
|
||||
bool used; // ever used indicator
|
||||
const char* ext;
|
||||
TFB_SoundDecoderFuncs* funcs;
|
||||
}
|
||||
sd_decoders[] =
|
||||
const TFB_SoundDecoderFuncs* funcs;
|
||||
};
|
||||
static TFB_RegSoundDecoder sd_decoders[MAX_REG_DECODERS + 1] =
|
||||
{
|
||||
{"wav", &wava_DecoderVtbl},
|
||||
{"mod", &moda_DecoderVtbl},
|
||||
{"ogg", &ova_DecoderVtbl},
|
||||
{"duk", &duka_DecoderVtbl},
|
||||
{NULL, NULL} // null term
|
||||
{true, true, "wav", &wava_DecoderVtbl},
|
||||
{true, true, "mod", &moda_DecoderVtbl},
|
||||
{true, true, "ogg", &ova_DecoderVtbl},
|
||||
{true, true, "duk", &duka_DecoderVtbl},
|
||||
{false, false, NULL, NULL}, // null term
|
||||
};
|
||||
|
||||
|
||||
TFB_DecoderFormats decoder_formats;
|
||||
static TFB_DecoderFormats decoder_formats;
|
||||
static int sd_flags = 0;
|
||||
|
||||
/* change endianness of 16bit words
|
||||
* Only works optimal when 'data' is aligned on a 32 bits boundary.
|
||||
@@ -175,7 +178,7 @@ SoundDecoder_GetName (TFB_SoundDecoder *decoder)
|
||||
sint32
|
||||
SoundDecoder_Init (int flags, TFB_DecoderFormats *formats)
|
||||
{
|
||||
struct sd_DecoderInfo* info;
|
||||
TFB_RegSoundDecoder* info;
|
||||
sint32 ret = 0;
|
||||
|
||||
if (!formats)
|
||||
@@ -185,26 +188,133 @@ SoundDecoder_Init (int flags, TFB_DecoderFormats *formats)
|
||||
}
|
||||
decoder_formats = *formats;
|
||||
|
||||
// init built-in decoders
|
||||
for (info = sd_decoders; info->ext; info++)
|
||||
{
|
||||
if (!info->funcs->InitModule (flags))
|
||||
if (!info->funcs->InitModule (flags, &decoder_formats))
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Init(): %s audio decoder init failed\n",
|
||||
fprintf (stderr, "SoundDecoder_Init(): "
|
||||
"%s audio decoder init failed\n",
|
||||
info->funcs->GetName ());
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
sd_flags = flags;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
SoundDecoder_Uninit (void)
|
||||
{
|
||||
struct sd_DecoderInfo* info;
|
||||
TFB_RegSoundDecoder* info;
|
||||
|
||||
for (info = sd_decoders; info->ext; info++)
|
||||
info->funcs->TermModule ();
|
||||
// uninit all decoders
|
||||
// and unregister loaded decoders
|
||||
for (info = sd_decoders; info->used; info++)
|
||||
{
|
||||
if (info->ext) // check if present
|
||||
info->funcs->TermModule ();
|
||||
|
||||
if (!info->builtin)
|
||||
{
|
||||
info->used = false;
|
||||
info->ext = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TFB_RegSoundDecoder*
|
||||
SoundDecoder_Register (const char* fileext, TFB_SoundDecoderFuncs* decvtbl)
|
||||
{
|
||||
TFB_RegSoundDecoder* info;
|
||||
TFB_RegSoundDecoder* newslot = NULL;
|
||||
|
||||
if (!decvtbl)
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Register(): Null decoder table\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!fileext)
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Register(): Bad file type for %s\n",
|
||||
decvtbl->GetName ());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check if extension already registered
|
||||
for (info = sd_decoders; info->used &&
|
||||
(!info->ext || strcmp (info->ext, fileext) != 0);
|
||||
++info)
|
||||
{
|
||||
// and pick up an empty slot (where available)
|
||||
if (!newslot && !info->ext)
|
||||
newslot = info;
|
||||
}
|
||||
|
||||
if (info >= sd_decoders + MAX_REG_DECODERS)
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Register(): Decoders limit reached\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (info->ext)
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Register(): "
|
||||
"'%s' decoder already registered (%s denied)\n",
|
||||
fileext, decvtbl->GetName ());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!decvtbl->InitModule (sd_flags, &decoder_formats))
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Register(): %s decoder init failed\n",
|
||||
decvtbl->GetName ());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!newslot)
|
||||
{
|
||||
newslot = info;
|
||||
newslot->used = true;
|
||||
// make next one a term
|
||||
info[1].builtin = false;
|
||||
info[1].used = false;
|
||||
info[1].ext = NULL;
|
||||
}
|
||||
|
||||
newslot->ext = fileext;
|
||||
newslot->funcs = decvtbl;
|
||||
|
||||
return newslot;
|
||||
}
|
||||
|
||||
void
|
||||
SoundDecoder_Unregister (TFB_RegSoundDecoder* regdec)
|
||||
{
|
||||
if (regdec < sd_decoders || regdec >= sd_decoders + MAX_REG_DECODERS ||
|
||||
!regdec->ext || !regdec->funcs)
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Unregister(): "
|
||||
"Invalid or expired decoder passed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
regdec->funcs->TermModule ();
|
||||
regdec->ext = NULL;
|
||||
regdec->funcs = NULL;
|
||||
}
|
||||
|
||||
const TFB_SoundDecoderFuncs*
|
||||
SoundDecoder_Lookup (const char* fileext)
|
||||
{
|
||||
TFB_RegSoundDecoder* info;
|
||||
|
||||
for (info = sd_decoders; info->used &&
|
||||
(!info->ext || strcmp (info->ext, fileext) != 0);
|
||||
++info)
|
||||
;
|
||||
return info->ext ? info->funcs : NULL;
|
||||
}
|
||||
|
||||
TFB_SoundDecoder*
|
||||
@@ -212,8 +322,8 @@ SoundDecoder_Load (uio_DirHandle *dir, char *filename,
|
||||
uint32 buffer_size, uint32 startTime, sint32 runTime)
|
||||
{
|
||||
const char* pext;
|
||||
struct sd_DecoderInfo* info;
|
||||
TFB_SoundDecoderFuncs* funcs;
|
||||
TFB_RegSoundDecoder* info;
|
||||
const TFB_SoundDecoderFuncs* funcs;
|
||||
TFB_SoundDecoder* decoder;
|
||||
uint32 struct_size;
|
||||
|
||||
@@ -226,8 +336,8 @@ SoundDecoder_Load (uio_DirHandle *dir, char *filename,
|
||||
}
|
||||
++pext;
|
||||
|
||||
for (info = sd_decoders;
|
||||
info->ext && strcmp (info->ext, pext) != 0;
|
||||
for (info = sd_decoders; info->used &&
|
||||
(!info->ext || strcmp (info->ext, pext) != 0);
|
||||
++info)
|
||||
;
|
||||
if (!info->ext)
|
||||
@@ -364,7 +474,8 @@ SoundDecoder_Decode (TFB_SoundDecoder *decoder)
|
||||
if (decoder->error)
|
||||
{
|
||||
fprintf (stderr, "SoundDecoder_Decode(): "
|
||||
"tried to loop %s but couldn't rewind, error code %d\n",
|
||||
"tried to loop %s but couldn't rewind, "
|
||||
"error code %d\n",
|
||||
decoder->filename, decoder->error);
|
||||
}
|
||||
else
|
||||
@@ -571,13 +682,13 @@ bufa_GetName (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
bufa_InitModule (int flags)
|
||||
bufa_InitModule (int flags, const TFB_DecoderFormats* fmts)
|
||||
{
|
||||
// this should never be called
|
||||
fprintf (stderr, "bufa_InitModule(): dead function called\n");
|
||||
return false;
|
||||
|
||||
(void)flags; // laugh at compiler warning
|
||||
(void)flags; (void)fmts; // laugh at compiler warning
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -699,13 +810,13 @@ nula_GetName (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
nula_InitModule (int flags)
|
||||
nula_InitModule (int flags, const TFB_DecoderFormats* fmts)
|
||||
{
|
||||
// this should never be called
|
||||
fprintf (stderr, "nula_InitModule(): dead function called\n");
|
||||
return false;
|
||||
|
||||
(void)flags; // laugh at compiler warning
|
||||
(void)flags; (void)fmts; // laugh at compiler warning
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef struct tfb_sounddecoder TFB_SoundDecoder;
|
||||
typedef struct tfb_sounddecoderfunc
|
||||
{
|
||||
const char* (* GetName) (void);
|
||||
bool (* InitModule) (int flags);
|
||||
bool (* InitModule) (int flags, const TFB_DecoderFormats*);
|
||||
void (* TermModule) ();
|
||||
uint32 (* GetStructSize) (void);
|
||||
int (* GetError) (THIS_PTR);
|
||||
@@ -103,7 +103,13 @@ enum
|
||||
SOUNDDECODER_EOF,
|
||||
};
|
||||
|
||||
extern TFB_DecoderFormats decoder_formats;
|
||||
typedef struct TFB_RegSoundDecoder TFB_RegSoundDecoder;
|
||||
|
||||
TFB_RegSoundDecoder* SoundDecoder_Register (const char* fileext,
|
||||
TFB_SoundDecoderFuncs* decvtbl);
|
||||
void SoundDecoder_Unregister (TFB_RegSoundDecoder* regdec);
|
||||
const TFB_SoundDecoderFuncs* SoundDecoder_Lookup (const char* fileext);
|
||||
|
||||
void SoundDecoder_SwapWords (uint16* data, uint32 size);
|
||||
sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats* formats);
|
||||
void SoundDecoder_Uninit (void);
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define THIS_PTR TFB_SoundDecoder* This
|
||||
|
||||
static const char* duka_GetName (void);
|
||||
static bool duka_InitModule (int flags);
|
||||
static bool duka_InitModule (int flags, const TFB_DecoderFormats*);
|
||||
static void duka_TermModule ();
|
||||
static uint32 duka_GetStructSize (void);
|
||||
static int duka_GetError (THIS_PTR);
|
||||
@@ -103,6 +103,8 @@ typedef struct
|
||||
uint16 indices[2]; // initial indices for channels
|
||||
} DukAud_AudSubframe;
|
||||
|
||||
static const TFB_DecoderFormats* duka_formats = NULL;
|
||||
|
||||
sint32
|
||||
duka_readAudFrameHeader (TFB_DuckSoundDecoder* duka, uint32 iframe,
|
||||
DukAud_AudSubframe* aud)
|
||||
@@ -338,9 +340,9 @@ duka_GetName (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
duka_InitModule (int flags)
|
||||
duka_InitModule (int flags, const TFB_DecoderFormats* fmts)
|
||||
{
|
||||
// no specific module init
|
||||
duka_formats = fmts;
|
||||
return true;
|
||||
|
||||
(void)flags; // laugh at compiler warning
|
||||
@@ -372,7 +374,7 @@ duka_Init (THIS_PTR)
|
||||
{
|
||||
//TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This;
|
||||
This->need_swap =
|
||||
decoder_formats.big_endian != decoder_formats.want_big_endian;
|
||||
duka_formats->big_endian != duka_formats->want_big_endian;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -449,7 +451,7 @@ duka_Open (THIS_PTR, uio_DirHandle *dir, const char *file)
|
||||
}
|
||||
|
||||
This->frequency = 22050;
|
||||
This->format = decoder_formats.stereo16;
|
||||
This->format = duka_formats->stereo16;
|
||||
duka->channels = 2;
|
||||
duka->pcm_frame = aud.numsamples;
|
||||
duka->data = HMalloc (DATA_BUF_SIZE);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define THIS_PTR TFB_SoundDecoder* This
|
||||
|
||||
static const char* moda_GetName (void);
|
||||
static bool moda_InitModule (int flags);
|
||||
static bool moda_InitModule (int flags, const TFB_DecoderFormats*);
|
||||
static void moda_TermModule ();
|
||||
static uint32 moda_GetStructSize (void);
|
||||
static int moda_GetError (THIS_PTR);
|
||||
@@ -72,7 +72,7 @@ typedef struct tfb_modsounddecoder
|
||||
} TFB_ModSoundDecoder;
|
||||
|
||||
MIKMODAPI extern struct MDRIVER drv_openal;
|
||||
|
||||
static const TFB_DecoderFormats* moda_formats = NULL;
|
||||
|
||||
static const char*
|
||||
moda_GetName (void)
|
||||
@@ -81,7 +81,7 @@ moda_GetName (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
moda_InitModule (int flags)
|
||||
moda_InitModule (int flags, const TFB_DecoderFormats* fmts)
|
||||
{
|
||||
MikMod_RegisterDriver (&drv_openal);
|
||||
MikMod_RegisterAllLoaders ();
|
||||
@@ -114,6 +114,8 @@ moda_InitModule (int flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
moda_formats = fmts;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -143,7 +145,7 @@ moda_Init (THIS_PTR)
|
||||
{
|
||||
//TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This;
|
||||
This->need_swap =
|
||||
decoder_formats.big_endian != decoder_formats.want_big_endian;
|
||||
moda_formats->big_endian != moda_formats->want_big_endian;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ moda_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
||||
mod->wrap = 0;
|
||||
mod->loop = 1;
|
||||
|
||||
This->format = decoder_formats.stereo16;
|
||||
This->format = moda_formats->stereo16;
|
||||
This->frequency = md_mixfreq;
|
||||
This->length = 0; // FIXME way to obtain this from mikmod?
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define THIS_PTR TFB_SoundDecoder* This
|
||||
|
||||
static const char* ova_GetName (void);
|
||||
static bool ova_InitModule (int flags);
|
||||
static bool ova_InitModule (int flags, const TFB_DecoderFormats*);
|
||||
static void ova_TermModule ();
|
||||
static uint32 ova_GetStructSize (void);
|
||||
static int ova_GetError (THIS_PTR);
|
||||
@@ -72,6 +72,8 @@ typedef struct tfb_oggsounddecoder
|
||||
|
||||
} TFB_OggSoundDecoder;
|
||||
|
||||
static const TFB_DecoderFormats* ova_formats = NULL;
|
||||
|
||||
static size_t
|
||||
ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
@@ -112,9 +114,9 @@ ova_GetName (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
ova_InitModule (int flags)
|
||||
ova_InitModule (int flags, const TFB_DecoderFormats* fmts)
|
||||
{
|
||||
// no specific module init
|
||||
ova_formats = fmts;
|
||||
return true;
|
||||
|
||||
(void)flags; // laugh at compiler warning
|
||||
@@ -195,9 +197,9 @@ ova_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
||||
This->length = (float) ov_time_total (&ova->vf, -1);
|
||||
|
||||
if (vinfo->channels == 1)
|
||||
This->format = decoder_formats.mono16;
|
||||
This->format = ova_formats->mono16;
|
||||
else
|
||||
This->format = decoder_formats.stereo16;
|
||||
This->format = ova_formats->stereo16;
|
||||
|
||||
ova->last_error = 0;
|
||||
|
||||
@@ -219,7 +221,7 @@ ova_Decode (THIS_PTR, void* buf, sint32 bufsize)
|
||||
long rc;
|
||||
int bitstream;
|
||||
|
||||
rc = ov_read (&ova->vf, buf, bufsize, decoder_formats.want_big_endian,
|
||||
rc = ov_read (&ova->vf, buf, bufsize, ova_formats->want_big_endian,
|
||||
2, 1, &bitstream);
|
||||
|
||||
if (rc < 0)
|
||||
|
||||
@@ -60,7 +60,7 @@ typedef struct
|
||||
#define THIS_PTR TFB_SoundDecoder* This
|
||||
|
||||
static const char* wava_GetName (void);
|
||||
static bool wava_InitModule (int flags);
|
||||
static bool wava_InitModule (int flags, const TFB_DecoderFormats*);
|
||||
static void wava_TermModule ();
|
||||
static uint32 wava_GetStructSize (void);
|
||||
static int wava_GetError (THIS_PTR);
|
||||
@@ -104,6 +104,8 @@ typedef struct tfb_wavesounddecoder
|
||||
|
||||
} TFB_WaveSoundDecoder;
|
||||
|
||||
static const TFB_DecoderFormats* wava_formats = NULL;
|
||||
|
||||
|
||||
static const char*
|
||||
wava_GetName (void)
|
||||
@@ -112,9 +114,9 @@ wava_GetName (void)
|
||||
}
|
||||
|
||||
static bool
|
||||
wava_InitModule (int flags)
|
||||
wava_InitModule (int flags, const TFB_DecoderFormats* fmts)
|
||||
{
|
||||
// no specific module init
|
||||
wava_formats = fmts;
|
||||
return true;
|
||||
|
||||
(void)flags; // laugh at compiler warning
|
||||
@@ -145,7 +147,7 @@ static bool
|
||||
wava_Init (THIS_PTR)
|
||||
{
|
||||
//TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This;
|
||||
This->need_swap = decoder_formats.want_big_endian;
|
||||
This->need_swap = wava_formats->want_big_endian;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -284,10 +286,10 @@ wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
||||
{
|
||||
This->format = (wava->FmtHdr.Channels == 1 ?
|
||||
(wava->FmtHdr.BitsPerSample == 8 ?
|
||||
decoder_formats.mono8 : decoder_formats.mono16)
|
||||
wava_formats->mono8 : wava_formats->mono16)
|
||||
:
|
||||
(wava->FmtHdr.BitsPerSample == 8 ?
|
||||
decoder_formats.stereo8 : decoder_formats.stereo16)
|
||||
wava_formats->stereo8 : wava_formats->stereo16)
|
||||
);
|
||||
This->frequency = wava->FmtHdr.SamplesPerSec;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user