plugin cleanup in preparation of future changes; fix FILE handle leaks

This commit is contained in:
bnnm 2017-08-13 11:53:44 +02:00
parent 321c617bfa
commit 68d3f43868

View File

@ -23,77 +23,100 @@
#define VERSION "(unknown version)" #define VERSION "(unknown version)"
#endif #endif
/* ************************************* */
/* XMPlay function library */
static XMPFUNC_IN *xmpfin; static XMPFUNC_IN *xmpfin;
static XMPFUNC_MISC *xmpfmisc; static XMPFUNC_MISC *xmpfmisc;
static XMPFUNC_FILE *xmpffile; static XMPFUNC_FILE *xmpffile;
/* XMPlay extension list, only needed to associate extensions in Windows */
/* todo: as of v3.8.2.17, any more than ~1000 will crash XMplay's file list screen (but not using the non-native Winamp plugin...) */
#define EXTENSION_LIST_SIZE 1000 /*VGM_EXTENSION_LIST_CHAR_SIZE * 2*/
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
/* plugin config */
double fade_seconds = 10.0;
double fade_delay_seconds = 10.0;
double loop_count = 2.0;
/* plugin state */
VGMSTREAM * vgmstream = NULL;
int framesDone, framesLength;
int stream_length_samples = 0;
int fade_samples = 0;
static int shownerror = 0; /* init error */
/* ************************************* */ /* ************************************* */
typedef struct _XMPSTREAMFILE { /* a STREAMFILE that operates via XMPlay's XMPFUNC_FILE+XMPFILE */
STREAMFILE sf; typedef struct _XMPLAY_STREAMFILE {
XMPFILE file; STREAMFILE sf; /* callbacks */
off_t offset; XMPFILE infile; /* actual FILE */
char name[PATH_LIMIT]; char name[PATH_LIMIT];
} XMPSTREAMFILE; off_t offset; /* current offset */
int internal_xmpfile; /* infile was not supplied externally and can be closed */
} XMPLAY_STREAMFILE;
static void xmpsf_seek(XMPSTREAMFILE *this, off_t offset) { static STREAMFILE *open_xmplay_streamfile_by_xmpfile(XMPFILE file, const char *path, int internal);
if (xmpffile->Seek(this->file, offset))
static size_t xmpsf_read(XMPLAY_STREAMFILE *this, uint8_t *dest, off_t offset, size_t length) {
size_t read;
if (this->offset != offset) {
if (xmpffile->Seek(this->infile, offset))
this->offset = offset; this->offset = offset;
else else
this->offset = xmpffile->Tell(this->file); this->offset = xmpffile->Tell(this->infile);
} }
static off_t xmpsf_get_size(XMPSTREAMFILE *this) read = xmpffile->Read(this->infile, dest, length);
{
return xmpffile->GetSize(this->file);
}
static off_t xmpsf_get_offset(XMPSTREAMFILE *this)
{
return xmpffile->Tell(this->file);
}
static void xmpsf_get_name(XMPSTREAMFILE *this, char *buffer, size_t length)
{
strncpy(buffer, this->name, length);
buffer[length - 1] = '\0';
}
static size_t xmpsf_read(XMPSTREAMFILE *this, uint8_t *dest, off_t offset, size_t length)
{
size_t read;
if (this->offset != offset)
xmpsf_seek(this, offset);
read = xmpffile->Read(this->file, dest, length);
if (read > 0) if (read > 0)
this->offset += read; this->offset += read;
return read; return read;
} }
static void xmpsf_close(XMPSTREAMFILE *this) static off_t xmpsf_get_size(XMPLAY_STREAMFILE *this) {
{ return xmpffile->GetSize(this->infile);
// The line below is what Causes this Plugin to Crash. Credits to Ian Luck to Finding this issue. }
// This closes the internal XMPFILE, which must be done by XMPlay instead.
// However vgmtream sometimes opens its own files, so it may be leaking handles. static off_t xmpsf_get_offset(XMPLAY_STREAMFILE *this) {
//xmpffile->Close(this->file); return xmpffile->Tell(this->infile);
}
static void xmpsf_get_name(XMPLAY_STREAMFILE *this, char *buffer, size_t length) {
strncpy(buffer, this->name, length);
buffer[length-1] = '\0';
}
static STREAMFILE *xmpsf_open(XMPLAY_STREAMFILE *this, const char *const filename, size_t buffersize) {
XMPFILE newfile;
if (!filename)
return NULL;
newfile = xmpffile->Open(filename);
if (!newfile) return NULL;
return open_xmplay_streamfile_by_xmpfile(newfile, filename, 1); /* internal XMPFILE */
}
static void xmpsf_close(XMPLAY_STREAMFILE *this) {
/* Close XMPFILE, but only if we opened it (ex. for subfiles inside metas).
* Otherwise must be left open as other parts of XMPlay need it and would crash. */
if (this->internal_xmpfile) {
xmpffile->Close(this->infile);
}
free(this); free(this);
} }
static STREAMFILE *xmpsf_create_from_path(const char *path); static STREAMFILE *open_xmplay_streamfile_by_xmpfile(XMPFILE infile, const char *path, int internal) {
static STREAMFILE *xmpsf_open(XMPSTREAMFILE *this, const char *const filename, size_t buffersize) XMPLAY_STREAMFILE *streamfile = calloc(1,sizeof(XMPLAY_STREAMFILE));
{
if (!filename) return NULL;
return xmpsf_create_from_path(filename);
}
static STREAMFILE *xmpsf_create(XMPFILE file, const char *path)
{
XMPSTREAMFILE *streamfile = malloc(sizeof(XMPSTREAMFILE));
if (!streamfile) return NULL; if (!streamfile) return NULL;
memset(streamfile, 0, sizeof(XMPSTREAMFILE));
streamfile->sf.read = (void*)xmpsf_read; streamfile->sf.read = (void*)xmpsf_read;
streamfile->sf.get_size = (void*)xmpsf_get_size; streamfile->sf.get_size = (void*)xmpsf_get_size;
streamfile->sf.get_offset = (void*)xmpsf_get_offset; streamfile->sf.get_offset = (void*)xmpsf_get_offset;
@ -101,69 +124,98 @@ static STREAMFILE *xmpsf_create(XMPFILE file, const char *path)
streamfile->sf.get_realname = (void*)xmpsf_get_name; streamfile->sf.get_realname = (void*)xmpsf_get_name;
streamfile->sf.open = (void*)xmpsf_open; streamfile->sf.open = (void*)xmpsf_open;
streamfile->sf.close = (void*)xmpsf_close; streamfile->sf.close = (void*)xmpsf_close;
streamfile->file = file; streamfile->infile = infile;
streamfile->offset = 0; streamfile->offset = 0;
strncpy(streamfile->name, path, sizeof(streamfile->name)); strncpy(streamfile->name, path, sizeof(streamfile->name));
return &streamfile->sf; streamfile->internal_xmpfile = internal;
return &streamfile->sf; /* pointer to STREAMFILE start = rest of the custom data follows */
} }
STREAMFILE *xmpsf_create_from_path(const char *path) VGMSTREAM *init_vgmstream_xmplay(XMPFILE file, const char *path) {
{ STREAMFILE *streamfile = NULL;
XMPFILE file = xmpffile->Open(path); VGMSTREAM *vgmstream = NULL;
if (!file)
return NULL;
return xmpsf_create(file, path); streamfile = open_xmplay_streamfile_by_xmpfile(file, path, 0); /* external XMPFILE */
} if (!streamfile) return NULL;
// Probably not needed at all. vgmstream = init_vgmstream_from_STREAMFILE(streamfile);
//VGMSTREAM *init_vgmstream_from_path(const char *path) if (!vgmstream) goto fail;
//{
// STREAMFILE *sf;
// VGMSTREAM *vgm;
//
// sf = xmpsf_create_from_path(path);
// if (!sf) return NULL;
//
// vgm = init_vgmstream_from_STREAMFILE(sf);
// if (!vgm) goto err1;
//
// return vgm;
//
//err1:
// xmpsf_close((XMPSTREAMFILE *)sf);
// return NULL;
//}
VGMSTREAM *init_vgmstream_from_xmpfile(XMPFILE file, const char *path) return vgmstream;
{
STREAMFILE *sf;
VGMSTREAM *vgm;
sf = xmpsf_create(file, path); fail:
if (!sf) return NULL; xmpsf_close((XMPLAY_STREAMFILE *)streamfile);
vgm = init_vgmstream_from_STREAMFILE(sf);
if (!vgm) goto err1;
return vgm;
err1:
xmpsf_close((XMPSTREAMFILE *)sf);
return NULL; return NULL;
} }
/* ************************************* */ /* ************************************* */
/* internal state */ #if 0
VGMSTREAM * vgmstream = NULL; /* get the tags as an array of "key\0value\0", NULL-terminated */
int32_t totalFrames, framesDone, framesLength, framesFade; static char *get_tags(VGMSTREAM * infostream) {
char *tags;
size_t tag_number = 20; // ?
#define APP_NAME "vgmstream plugin" //unused? tags = (char*)xmpfmisc->Alloc(tag_number+1);
void __stdcall XMP_About(HWND hwParent) { for (...) {
MessageBox(hwParent, ...
}
tags[tag_number]=0; // terminating NULL
return tags; /* assuming XMPlay free()s this, since it Alloc()s it */
}
#endif
/* Adds ext to XMPlay's extension list. */
static int add_extension(int length, char * dst, const char * ext) {
int ext_len;
int i;
if (length <= 1)
return 0;
ext_len = strlen(ext);
/* check if end reached or not enough room to add */
if (ext_len+2 > length-2) {
dst[0]='\0';
return 0;
}
/* copy new extension + null terminate */
for (i=0; i < ext_len; i++)
dst[i] = ext[i];
dst[i]='/';
dst[i+1]='\0';
return i+1;
}
/* Creates XMPlay's extension list, a single string with 2 nulls.
* Extensions must be in this format: "Description\0extension1/.../extensionN" */
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
int i, written;
written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0');
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) {
written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]);
}
working_extension_list[written-1] = '\0'; /* remove last "/" */
}
/* ************************************* */
/* info for the "about" button in plugin options */
void WINAPI xmplay_About(HWND win) {
MessageBox(win,
"vgmstream plugin " VERSION " " __DATE__ "\n" "vgmstream plugin " VERSION " " __DATE__ "\n"
"by hcs, FastElbja, manakoAT, bxaimc, snakemeat, soneek, kode54, bnnm and many others\n" "by hcs, FastElbja, manakoAT, bxaimc, snakemeat, soneek, kode54, bnnm and many others\n"
"\n" "\n"
@ -174,168 +226,93 @@ void __stdcall XMP_About(HWND hwParent) {
,"about xmp-vgmstream",MB_OK); ,"about xmp-vgmstream",MB_OK);
} }
void __stdcall XMP_Close() { #if 0
close_vgmstream(vgmstream); /* present config options to user (OPTIONAL) */
vgmstream = NULL; void WINAPI xmplay_Config(HWND win) {
/* defined in resource.rc */
DialogBox(input_module.hDllInstance, (const char *)IDD_CONFIG, win, configDlgProc);
}
#endif
/* check if a file is playable by this plugin */
BOOL WINAPI xmplay_CheckFile(const char *filename, XMPFILE file) {
VGMSTREAM* infostream = NULL;
if (file)
infostream = init_vgmstream_xmplay(file, filename);
else
infostream = init_vgmstream(filename); //TODO: unicode problems?
if (!infostream)
return FALSE;
close_vgmstream(infostream);
return TRUE;
} }
BOOL __stdcall XMP_CheckFile(const char *filename, XMPFILE file) { /* update info from a file, returning the number of subsongs */
VGMSTREAM* thisvgmstream; DWORD WINAPI xmplay_GetFileInfo(const char *filename, XMPFILE file, float **length, char **tags) {
int ret; VGMSTREAM* infostream;
if (file) thisvgmstream = init_vgmstream_from_xmpfile(file, filename); if (file)
else thisvgmstream = init_vgmstream(filename); infostream = init_vgmstream_xmplay(file, filename);
else
infostream = init_vgmstream(filename); //TODO: unicode problems?
if (!infostream)
return 0;
if (!thisvgmstream) ret = FALSE; if (length && infostream->sample_rate) {
else { ret = TRUE; close_vgmstream(thisvgmstream); } int stream_length_samples = get_vgmstream_play_samples(loop_count, fade_seconds, fade_delay_seconds, infostream);
return ret;
}
DWORD __stdcall XMP_GetFileInfo(const char *filename, XMPFILE file, float **length, char **tags)
{
VGMSTREAM* thisvgmstream;
if (file) thisvgmstream = init_vgmstream_from_xmpfile(file, filename);
else thisvgmstream = init_vgmstream(filename);
if (!thisvgmstream) return 0;
if (length && thisvgmstream->sample_rate)
{
int totalFrames = get_vgmstream_play_samples(2.0, 10.0, 10.0, thisvgmstream);
float *lens = (float*)xmpfmisc->Alloc(sizeof(float)); float *lens = (float*)xmpfmisc->Alloc(sizeof(float));
lens[0] = (float)totalFrames / (float)thisvgmstream->sample_rate; lens[0] = (float)stream_length_samples / (float)infostream->sample_rate;
*length = lens; *length = lens;
} }
close_vgmstream(thisvgmstream); close_vgmstream(infostream);
return 1; return 1;
} }
DWORD __stdcall XMP_Open(const char *filename, XMPFILE file) { /* open a file for playback, returning: 0=failed, 1=success, 2=success and XMPlay can close the file */
if (file) vgmstream = init_vgmstream_from_xmpfile(file, filename); DWORD WINAPI xmplay_Open(const char *filename, XMPFILE file) {
else vgmstream = init_vgmstream(filename); if (file)
vgmstream = init_vgmstream_xmplay(file, filename);
else
vgmstream = init_vgmstream(filename);
if (!vgmstream)
return 0;
if (!vgmstream) return 0;
totalFrames = get_vgmstream_play_samples(2.0, 10.0, 10.0, vgmstream);
framesDone = 0; framesDone = 0;
framesFade = vgmstream->sample_rate * 10; stream_length_samples = get_vgmstream_play_samples(loop_count, fade_seconds, fade_delay_seconds, vgmstream);
framesLength = totalFrames - framesFade; fade_samples = (int)(fade_seconds * vgmstream->sample_rate);
framesLength = stream_length_samples - fade_samples;
if (totalFrames) if (stream_length_samples) {
{ float length = (float)stream_length_samples / (float)vgmstream->sample_rate;
float length = (float)totalFrames / (float)vgmstream->sample_rate;
xmpfin->SetLength(length, TRUE); xmpfin->SetLength(length, TRUE);
} }
return 1; return 1;
} }
DWORD __stdcall XMP_Process(float* buffer, DWORD bufsize) { /* close the playback file */
INT16 buf[1024]; void WINAPI xmplay_Close() {
UINT32 i, j, todo, done; close_vgmstream(vgmstream);
vgmstream = NULL;
BOOL doLoop = xmpfin->GetLooping();
float *sbuf = buffer;
UINT32 samplesTodo;
bufsize /= vgmstream->channels;
samplesTodo = doLoop ? bufsize : totalFrames - framesDone;
if (samplesTodo > bufsize)
samplesTodo = bufsize;
done = 0;
while (done < samplesTodo) {
todo = 1024 / vgmstream->channels;
if (todo > samplesTodo - done)
todo = samplesTodo - done;
render_vgmstream(buf, todo, vgmstream);
for (i = 0, j = todo * vgmstream->channels; i < j; ++i)
{
*sbuf++ = buf[i] * 1.0f / 32768.0f;
}
done += todo;
}
sbuf = buffer;
if (!doLoop && framesDone + done > framesLength)
{
long fadeStart = (framesLength > framesDone) ? framesLength : framesDone;
long fadeEnd = (framesDone + done) > totalFrames ? totalFrames : (framesDone + done);
long fadePos;
float fadeScale = (float)(totalFrames - fadeStart) / framesFade;
float fadeStep = 1.0f / framesFade;
sbuf += (fadeStart - framesDone) * vgmstream->channels;
j = vgmstream->channels;
for (fadePos = fadeStart; fadePos < fadeEnd; ++fadePos)
{
for (i = 0; i < j; ++i)
{
sbuf[i] = sbuf[i] * fadeScale;
}
sbuf += j;
fadeScale -= fadeStep;
if (fadeScale <= 0.0f) break;
}
done = (int)(fadePos - framesDone);
}
framesDone += done;
return done * vgmstream->channels;
} }
void __stdcall XMP_SetFormat(XMPFORMAT *form) { /* set the sample format */
form->res = 16 / 8; void WINAPI xmplay_SetFormat(XMPFORMAT *form) {
form->res = 16 / 8; /* PCM 16 */
form->chan = vgmstream->channels; form->chan = vgmstream->channels;
form->rate = vgmstream->sample_rate; form->rate = vgmstream->sample_rate;
} }
char * __stdcall XMP_GetTags() /* get tags, return NULL to delay title update (OPTIONAL) */
{ char * WINAPI xmplay_GetTags() {
return NULL; return NULL; //get_tags(vgmstream);
}
double __stdcall XMP_GetGranularity()
{
return 0.001;
}
double __stdcall XMP_SetPosition(DWORD pos) {
double cpos = (double)framesDone / (double)vgmstream->sample_rate;
double time = pos * XMP_GetGranularity();
if (time < cpos)
{
reset_vgmstream(vgmstream);
cpos = 0.0;
}
while (cpos < time)
{
INT16 buffer[1024];
long max_sample_count = 1024 / vgmstream->channels;
long samples_to_skip = (long)((time - cpos) * vgmstream->sample_rate);
if (samples_to_skip > max_sample_count)
samples_to_skip = max_sample_count;
if (!samples_to_skip)
break;
render_vgmstream(buffer, (int)samples_to_skip, vgmstream);
cpos += (double)samples_to_skip / (double)vgmstream->sample_rate;
}
framesDone = (int32_t)(cpos * vgmstream->sample_rate);
return cpos;
} }
/* main panel info text (short file info) */ /* main panel info text (short file info) */
void __stdcall XMP_GetInfoText(char* format, char* length) { void WINAPI xmplay_GetInfoText(char* format, char* length) {
if (!format) if (!format)
return; return;
@ -344,7 +321,7 @@ void __stdcall XMP_GetInfoText(char* format, char* length) {
} }
/* info for the "General" window/tab (buf is ~40K) */ /* info for the "General" window/tab (buf is ~40K) */
void __stdcall XMP_GetGeneralInfo(char* buf) { void WINAPI xmplay_GetGeneralInfo(char* buf) {
int i; int i;
char description[1024]; char description[1024];
@ -378,36 +355,138 @@ void __stdcall XMP_GetGeneralInfo(char* buf) {
sprintf(buf,"vgmstream\t\r%s\r", description); sprintf(buf,"vgmstream\t\r%s\r", description);
} }
/* get the seeking granularity in seconds */
double WINAPI xmplay_GetGranularity() {
return 0.001; /* can seek in milliseconds */
}
static int add_extension(int length, char * dst, const char * src); /* seek to a position (in granularity units), return new position or -1 = failed */
static void build_extension_list(); double WINAPI xmplay_SetPosition(DWORD pos) {
double cpos = (double)framesDone / (double)vgmstream->sample_rate;
double time = pos * xmplay_GetGranularity();
/* XMPlay extension list, only needed to associate extensions in Windows */ #if 0
/* todo: as of v3.8.2.17, any more than ~1000 will crash XMplay's file list screen (but not using the non-native Winamp plugin...) */ /* set a subsong */
#define EXTENSION_LIST_SIZE 1000 /*VGM_EXTENSION_LIST_CHAR_SIZE * 2*/ if (pos & XMPIN_POS_SUBSONG) {
char working_extension_list[EXTENSION_LIST_SIZE] = {0}; int subsong = LOWORD(pos);
/* plugin defs, see xmpin.h */ /* "single subsong mode (don't show info on other subsongs)" */
XMPIN vgmstream_intf = { if (pos & XMPIN_POS_SUBSONG1) {
// ???
}
// todo reopen vgmstream based on current with new subsong index
cpos = 0.0;
}
#endif
if (time < cpos) {
reset_vgmstream(vgmstream);
cpos = 0.0;
}
while (cpos < time) {
INT16 buffer[1024];
long max_sample_count = 1024 / vgmstream->channels;
long samples_to_skip = (long)((time - cpos) * vgmstream->sample_rate);
if (samples_to_skip > max_sample_count)
samples_to_skip = max_sample_count;
if (!samples_to_skip)
break;
render_vgmstream(buffer, (int)samples_to_skip, vgmstream);
cpos += (double)samples_to_skip / (double)vgmstream->sample_rate;
}
framesDone = (int32_t)(cpos * vgmstream->sample_rate);
return cpos;
}
/* decode some sample data */
DWORD WINAPI xmplay_Process(float* buf, DWORD bufsize) {
INT16 sample_buffer[1024];
UINT32 i, j, todo, done;
BOOL doLoop = xmpfin->GetLooping();
float *sbuf = buf;
UINT32 samplesTodo;
bufsize /= vgmstream->channels;
samplesTodo = doLoop ? bufsize : stream_length_samples - framesDone;
if (samplesTodo > bufsize)
samplesTodo = bufsize;
/* decode */
done = 0;
while (done < samplesTodo) {
todo = 1024 / vgmstream->channels;
if (todo > samplesTodo - done)
todo = samplesTodo - done;
render_vgmstream(sample_buffer, todo, vgmstream);
for (i = 0, j = todo * vgmstream->channels; i < j; ++i) {
*sbuf++ = sample_buffer[i] * 1.0f / 32768.0f;
}
done += todo;
}
sbuf = buf;
/* fade */
if (!doLoop && framesDone + done > framesLength) {
long fadeStart = (framesLength > framesDone) ? framesLength : framesDone;
long fadeEnd = (framesDone + done) > stream_length_samples ? stream_length_samples : (framesDone + done);
long fadePos;
float fadeScale = (float)(stream_length_samples - fadeStart) / fade_samples;
float fadeStep = 1.0f / fade_samples;
sbuf += (fadeStart - framesDone) * vgmstream->channels;
j = vgmstream->channels;
for (fadePos = fadeStart; fadePos < fadeEnd; ++fadePos) {
for (i = 0; i < j; ++i) {
sbuf[i] = sbuf[i] * fadeScale;
}
sbuf += j;
fadeScale -= fadeStep;
if (fadeScale <= 0.0f)
break;
}
done = (int)(fadePos - framesDone);
}
framesDone += done;
return done * vgmstream->channels;
}
/* *********************************** */
/* main plugin def, see xmpin.h */
XMPIN vgmstream_xmpin = {
XMPIN_FLAG_CANSTREAM, XMPIN_FLAG_CANSTREAM,
"vgmstream for XMPlay", "vgmstream for XMPlay",
working_extension_list, working_extension_list,
XMP_About, xmplay_About,
NULL,//XMP_Config NULL,//XMP_Config
XMP_CheckFile, xmplay_CheckFile,
XMP_GetFileInfo, xmplay_GetFileInfo,
XMP_Open, xmplay_Open,
XMP_Close, xmplay_Close,
NULL, NULL,
XMP_SetFormat, xmplay_SetFormat,
XMP_GetTags, //(OPTIONAL) --actually mandatory xmplay_GetTags, //(OPTIONAL) --actually mandatory
XMP_GetInfoText, xmplay_GetInfoText,
XMP_GetGeneralInfo, xmplay_GetGeneralInfo,
NULL,//GetMessage - text for the "Message" tab window/tab (OPTIONAL) NULL,//GetMessage - text for the "Message" tab window/tab (OPTIONAL)
XMP_SetPosition, xmplay_SetPosition,
XMP_GetGranularity, xmplay_GetGranularity,
NULL, NULL,
XMP_Process, xmplay_Process,
NULL, NULL,
NULL, NULL,
NULL, NULL,
@ -425,17 +504,16 @@ XMPIN vgmstream_intf = {
NULL, NULL,
}; };
static int shownerror = 0; /* get the plugin's XMPIN interface */
__declspec(dllexport) XMPIN* WINAPI XMPIN_GetInterface(UINT32 face, InterfaceProc faceproc) {
__declspec(dllexport) XMPIN* __stdcall XMPIN_GetInterface(UINT32 face, InterfaceProc faceproc) if (face != XMPIN_FACE) {
{ // unsupported version
if (face != XMPIN_FACE) if (face < XMPIN_FACE && !shownerror) {
{ // unsupported version MessageBox(0,
if (face<XMPIN_FACE && !shownerror) "The xmp-vgmstream plugin requires XMPlay 3.8 or above.\n\n"
{ "Please update at:\n"
//Replaced the message box below with a better one. "http://www.un4seen.com/xmplay.html\n"
//MessageBox(0, "The XMP-vgmstream plugin requires XMPlay 3.8 or above", 0, MB_ICONEXCLAMATION); "http://www.un4seen.com/stuff/xmplay.exe", 0, MB_ICONEXCLAMATION);
MessageBox(0, "The xmp-vgmstream plugin requires XMPlay 3.8 or above. Please update at.\n\n http://www.un4seen.com/xmplay.html \n or at\n http://www.un4seen.com/stuff/xmplay.exe.", 0, MB_ICONEXCLAMATION);
shownerror = 1; shownerror = 1;
} }
return NULL; return NULL;
@ -447,52 +525,17 @@ __declspec(dllexport) XMPIN* __stdcall XMPIN_GetInterface(UINT32 face, Interface
build_extension_list(); build_extension_list();
return &vgmstream_intf; return &vgmstream_xmpin;
} }
#if 0
/** // needed?
* Creates XMPlay's extension list, a single string with 2 nulls. BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD reason, LPVOID reserved) {
* Extensions must be in this format: "Description\0extension1/.../extensionN" switch (reason) {
*/ case DLL_PROCESS_ATTACH:
static void build_extension_list() { DisableThreadLibraryCalls(hDLL);
const char ** ext_list; break;
int ext_list_len;
int i, written;
written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0');
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) {
written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]);
} }
working_extension_list[written-1] = '\0'; /* remove last "/" */ return TRUE;
}
/**
* Adds ext to XMPlay's extension list.
*/
static int add_extension(int length, char * dst, const char * ext) {
int ext_len;
int i;
if (length <= 1)
return 0;
ext_len = strlen(ext);
/* check if end reached or not enough room to add */
if (ext_len+2 > length-2) {
dst[0]='\0';
return 0;
}
/* copy new extension + null terminate */
for (i=0; i < ext_len; i++)
dst[i] = ext[i];
dst[i]='/';
dst[i+1]='\0';
return i+1;
} }
#endif