Update Winamp plugin with the "latest" (2008) SDK defs [unicode preps]

This commit is contained in:
bnnm 2017-04-28 16:15:32 +02:00
parent fa829d49f7
commit 3fc6db0414
4 changed files with 1388 additions and 423 deletions

View File

@ -1,103 +1,137 @@
#ifndef NULLSOFT_WINAMP_IN2H
#define NULLSOFT_WINAMP_IN2H
#include "out.h"
// note: exported symbol is now winampGetInModule2.
#define IN_VER 0x100
#define IN_UNICODE 0x0F000000
#ifdef UNICODE_INPUT_PLUGIN
#define in_char wchar_t
#define IN_VER (IN_UNICODE | 0x100)
#else
#define in_char char
#define IN_VER 0x100
#endif
#define IN_MODULE_FLAG_USES_OUTPUT_PLUGIN 1
// By default, Winamp assumes that your input plugin wants to use Winamp's EQ, and doesn't do replay gain
// if you handle any of these yourself (EQ, Replay Gain adjustments), then set these flags accordingly
#define IN_MODULE_FLAG_EQ 2 // set this if you do your own EQ
#define IN_MODULE_FLAG_REPLAYGAIN 8 // set this if you adjusted volume for replay gain
// for tracks with no replay gain metadata, you should clear this flag
// UNLESS you handle "non_replaygain" gain adjustment yourself
#define IN_MODULE_FLAG_REPLAYGAIN_PREAMP 16 // use this if you queried for the replay gain preamp parameter and used it
// this parameter is new to 5.54
typedef struct
{
int version; // module type (IN_VER)
char *description; // description of module, with version string
int version; // module type (IN_VER)
char *description; // description of module, with version string
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
// May be altered from Config, so the user can select what they want
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
// May be altered from Config, so the user can select what they want
int is_seekable; // is this stream seekable?
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
int is_seekable; // is this stream seekable?
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
// note that this has turned into a "flags" field
// see IN_MODULE_FLAG_*
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Init)(); // called at program init
void (*Quit)(); // called at program quit
void (*Init)(); // called at program init
void (*Quit)(); // called at program quit
void (*GetFileInfo)(char *file, char *title, int *length_in_ms); // if file == NULL, current playing is used
int (*InfoBox)(char *file, HWND hwndParent);
#define GETFILEINFO_TITLE_LENGTH 2048
void (*GetFileInfo)(const in_char *file, in_char *title, int *length_in_ms); // if file == NULL, current playing is used
int (*IsOurFile)(char *fn); // called before extension checks, to allow detection of mms://, etc
// playback stuff
int (*Play)(char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
void (*Pause)(); // pause stream
void (*UnPause)(); // unpause stream
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
void (*Stop)(); // stop (unload) stream
#define INFOBOX_EDITED 0
#define INFOBOX_UNCHANGED 1
int (*InfoBox)(const in_char *file, HWND hwndParent);
// time stuff
int (*GetLength)(); // get length in ms
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush()..
int (*IsOurFile)(const in_char *fn); // called before extension checks, to allow detection of mms://, etc
// playback stuff
int (*Play)(const in_char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
void (*Pause)(); // pause stream
void (*UnPause)(); // unpause stream
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
void (*Stop)(); // stop (unload) stream
// volume stuff
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
// time stuff
int (*GetLength)(); // get length in ms
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal your thread to seek, which seeks and calls outMod->Flush()..
// in-window builtin vis stuff
// volume stuff
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
// call after opening audio device with max latency in ms and samplerate
void (*SAVSADeInit)(); // call in Stop()
// in-window builtin vis stuff
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
// call after opening audio device with max latency in ms and samplerate
void (*SAVSADeInit)(); // call in Stop()
// simple vis supplying mode
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
// sets the spec data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// simple vis supplying mode
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
// sets the spec data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
// use when calling SAAdd()
void (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
// use when calling SAAdd()
int (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
// vis stuff (plug-in)
// simple vis supplying mode
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// vis stuff (plug-in)
// simple vis supplying mode
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
void (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
int (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
// call this in Play() to tell the vis plug-ins the current output params.
void (*VSASetInfo)(int nch, int srate);
// call this in Play() to tell the vis plug-ins the current output params.
void (*VSASetInfo)(int srate, int nch); // <-- Correct (benski, dec 2005).. old declaration had the params backwards
// dsp plug-in processing:
// (filled in by winamp, called by input plug)
// dsp plug-in processing:
// (filled in by winamp, calld by input plug)
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
// could be greater than went in.. Use it to estimate if you'll have enough room in the
// output buffer
int (*dsp_isactive)();
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
// could be greater than went in.. Use it to estimate if you'll have enough room in the
// output buffer
int (*dsp_isactive)();
// returns number of samples to output. This can be as much as twice numsamples.
// be sure to allocate enough buffer for samples, then.
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
// returns number of samples to output. This can be as much as twice numsamples.
// be sure to allocate enough buffer for samples, then.
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
// eq stuff
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
// eq stuff
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
// info setting (filled in by winamp)
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
// info setting (filled in by winamp)
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
Out_Module *outMod; // filled in by winamp, optionally used :)
Out_Module *outMod; // filled in by winamp, optionally used :)
} In_Module;
// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param)
// which determine if we can uninstall the plugin immediately or on winamp restart
//
// uninstall support was added from 5.0+ and uninstall now support from 5.5+
// it is down to you to ensure that if uninstall now is returned that it will not cause a crash
// (ie don't use if you've been subclassing the main window)
#define IN_PLUGIN_UNINSTALL_NOW 0x1
#define IN_PLUGIN_UNINSTALL_REBOOT 0x0
#endif

View File

@ -5,6 +5,10 @@
** Copyright (c) 1998, Justin Frankel/Nullsoft Inc.
*/
/* Winamp uses wchar_t when this is on, so extra steps are needed */
//#define UNICODE_INPUT_PLUGIN
#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
#endif
@ -22,6 +26,7 @@
#include "wa_ipc.h"
#include "resource.h"
#ifndef VERSION
#include "../version.h"
#endif
@ -33,14 +38,16 @@
#define PLUGIN_DESCRIPTION "vgmstream plugin " VERSION " " __DATE__
#define INI_NAME "plugin.ini"
/* post when playback stops */
#define WM_WA_MPEG_EOF WM_USER+2
In_Module input_module; /* the input module, declared at the bottom of this file */
DWORD WINAPI __stdcall decode(void *arg);
char lastfn[MAX_PATH+1] = {0}; /* name of the currently playing file */
short sample_buffer[576*2*2]; /* 576 16-bit samples, stereo, possibly doubled in size for DSP */
#define WINAMP_MAX_PATH 32768 /* originally 260+1 */
char lastfn[WINAMP_MAX_PATH] = {0}; /* name of the currently playing file */
#define DEFAULT_FADE_SECONDS "10.00"
#define DEFAULT_FADE_DELAY_SECONDS "0.00"
@ -56,6 +63,16 @@ short sample_buffer[576*2*2]; /* 576 16-bit samples, stereo, possibly doubled in
#define LOOP_FOREVER_INI_ENTRY "loop_forever"
#define IGNORE_LOOP_INI_ENTRY "ignore_loop"
char *priority_strings[] = {"Idle","Lowest","Below Normal","Normal","Above Normal","Highest (not recommended)","Time Critical (not recommended)"};
int priority_values[] = {THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_TIME_CRITICAL};
/* Winamp Play extension list, needed to accept/play and associate extensions in Windows */
#define EXTENSION_LIST_SIZE VGM_EXTENSION_LIST_CHAR_SIZE * 6
#define EXT_BUFFER_SIZE 200
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
/* plugin config */
double fade_seconds;
double fade_delay_seconds;
double loop_count;
@ -63,11 +80,11 @@ int thread_priority;
int loop_forever;
int ignore_loop;
char *priority_strings[] = {"Idle","Lowest","Below Normal","Normal","Above Normal","Highest (not recommended)","Time Critical (not recommended)"};
int priority_values[] = {THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_TIME_CRITICAL};
/* plugin state */
VGMSTREAM * vgmstream = NULL;
HANDLE decode_thread_handle = INVALID_HANDLE_VALUE;
short sample_buffer[576*2*2]; /* 576 16-bit samples, stereo, possibly doubled in size for DSP */
int paused = 0;
int decode_abort = 0;
int seek_needed_samples = -1;
@ -76,15 +93,93 @@ int decode_pos_samples = 0;
int stream_length_samples = 0;
int fade_samples = 0;
/* Winamp Play extension list, needed to accept/play and associate extensions in Windows */
#define EXTENSION_LIST_SIZE VGM_EXTENSION_LIST_CHAR_SIZE * 6
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
#define EXT_BUFFER_SIZE 200
/* ***************************************** */
static void add_extension(int length, char * dst, const char * src);
static void build_extension_list();
/* Winamp INI reader */
static void GetINIFileName(char * iniFile) {
/* if we're running on a newer winamp version that better supports
* saving of settings to a per-user directory, use that directory - if not
* then just revert to the old behaviour */
if(IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) {
char * iniDir = (char *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);
strncpy(iniFile, iniDir, WINAMP_MAX_PATH);
strncat(iniFile, "\\Plugins\\", WINAMP_MAX_PATH);
/* can't be certain that \Plugins already exists in the user dir */
CreateDirectory(iniFile,NULL);
strncat(iniFile, INI_NAME, WINAMP_MAX_PATH);
}
else {
char * lastSlash;
GetModuleFileName(NULL, iniFile, WINAMP_MAX_PATH);
lastSlash = strrchr(iniFile, '\\');
*(lastSlash + 1) = 0;
strncat(iniFile, "Plugins\\" INI_NAME,WINAMP_MAX_PATH);
}
}
/* Adds ext to Winamp's extension list */
static void add_extension(int length, char * dst, const char * ext) {
char buf[EXT_BUFFER_SIZE];
char ext_upp[EXT_BUFFER_SIZE];
int ext_len, written;
int i,j;
if (length <= 1)
return;
ext_len = strlen(ext);
/* find end of dst (double \0), saved in i */
for (i=0; i<length-2 && (dst[i] || dst[i+1]); i++)
;
/* check if end reached or not enough room to add */
if (i == length-2 || i + EXT_BUFFER_SIZE+2 > length-2 || ext_len * 3 + 20+2 > EXT_BUFFER_SIZE) {
dst[i]='\0';
dst[i+1]='\0';
return;
}
if (i > 0)
i++;
/* uppercase ext */
for (j=0; j < ext_len; j++)
ext_upp[j] = toupper(ext[j]);
ext_upp[j] = '\0';
/* copy new extension + double null terminate */
written = sprintf(buf, "%s%c%s Audio File (*.%s)%c", ext,'\0',ext_upp,ext_upp,'\0'); /*ex: "vgmstream\0vgmstream Audio File (*.VGMSTREAM)\0" */
for (j=0; j < written; i++,j++)
dst[i] = buf[j];
dst[i]='\0';
dst[i+1]='\0';
}
/* Creates Winamp's extension list, a single string that ends with \0\0.
* Each extension must be in this format: "extension\0Description\0" */
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
int i;
working_extension_list[0]='\0';
working_extension_list[1]='\0';
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) {
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);
}
}
/* ***************************************** */
/* about dialog */
void about(HWND hwndParent) {
MessageBox(hwndParent,
PLUGIN_DESCRIPTION "\n"
@ -92,36 +187,10 @@ void about(HWND hwndParent) {
"http://sourceforge.net/projects/vgmstream"
,"about in_vgmstream",MB_OK);
}
void quit() {}
void GetINIFileName(char * iniFile) {
/* if we're running on a newer winamp version that better supports
* saving of settings to a per-user directory, use that directory - if not
* then just revert to the old behaviour */
if(IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) {
char * iniDir = (char *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);
strncpy(iniFile, iniDir, MAX_PATH);
strncat(iniFile, "\\Plugins\\", MAX_PATH);
/* can't be certain that \Plugins already exists in the user dir */
CreateDirectory(iniFile,NULL);
strncat(iniFile, INI_NAME, MAX_PATH);
}
else {
char * lastSlash;
GetModuleFileName(NULL, iniFile, MAX_PATH);
lastSlash = strrchr(iniFile, '\\');
*(lastSlash + 1) = 0;
strncat(iniFile, "Plugins\\" INI_NAME,MAX_PATH);
}
}
/* called at program init */
void init() {
char iniFile[MAX_PATH+1];
char iniFile[WINAMP_MAX_PATH];
char buf[256];
int consumed;
@ -167,18 +236,23 @@ void init() {
build_extension_list();
}
/* we don't recognize protocols */
int isourfile(char *fn) { return 0; }
/* called at program quit */
void quit() {
}
/* called before extension checks, to allow detection of mms://, etc */
int isourfile(const in_char *fn) {
return 0; /* we don't recognize protocols */
}
/* request to start playing a file */
int play(char *fn)
{
int play(const in_char *fn) {
int max_latency;
/* don't lose a pointer! */
if (vgmstream) {
/* TODO: this should either pop up an error box or close the file */
return 1;
return 1; /* error */
}
/* open the stream, set up */
vgmstream = init_vgmstream(fn);
@ -191,11 +265,11 @@ int play(char *fn)
if (vgmstream->channels <= 0) {
close_vgmstream(vgmstream);
vgmstream=NULL;
return 1;
return 1; /* error */
}
/* Remember that name, friends! */
strncpy(lastfn,fn,MAX_PATH);
strncpy(lastfn,fn,WINAMP_MAX_PATH);
/* open the output plugin */
max_latency = input_module.outMod->Open(vgmstream->sample_rate,vgmstream->channels,
@ -204,7 +278,7 @@ int play(char *fn)
if (max_latency < 0) {
close_vgmstream(vgmstream);
vgmstream=NULL;
return 1;
return 1; /* error */
}
/* Set info display */
@ -234,15 +308,27 @@ int play(char *fn)
SetThreadPriority(decode_thread_handle,priority_values[thread_priority]);
return 0;
return 0; /* success */
}
/* pausing... */
void pause() { paused=1; input_module.outMod->Pause(1); }
void unpause() {paused=0; input_module.outMod->Pause(0); }
int ispaused() { return paused; }
/* pause stream */
void pause() {
paused=1;
input_module.outMod->Pause(1);
}
/* stop playback */
/* unpause stream */
void unpause() {
paused=0;
input_module.outMod->Pause(0);
}
/* ispaused? return 1 if paused, 0 if not */
int ispaused() {
return paused;
}
/* stop (unload) stream */
void stop() {
if (decode_thread_handle != INVALID_HANDLE_VALUE) {
decode_abort=1;
@ -265,28 +351,32 @@ void stop() {
input_module.SAVSADeInit();
}
/* get current stream length */
/* get length in ms */
int getlength() {
return stream_length_samples*1000LL/vgmstream->sample_rate;
}
/* get current output time */
/* current output time in ms */
int getoutputtime() {
return decode_pos_ms+(input_module.outMod->GetOutputTime()-input_module.outMod->GetWrittenTime());
}
/* seek */
/* seeks to point in stream (in ms) */
void setoutputtime(int t) {
if (vgmstream)
seek_needed_samples = (long long)t * vgmstream->sample_rate / 1000LL;
}
/* pass these commands through */
void setvolume(int volume) { input_module.outMod->SetVolume(volume); }
void setpan(int pan) { input_module.outMod->SetPan(pan); }
void setvolume(int volume) {
input_module.outMod->SetVolume(volume);
}
void setpan(int pan) {
input_module.outMod->SetPan(pan);
}
/* display information */
int infoDlg(char *fn, HWND hwnd) {
int infoDlg(const in_char *fn, HWND hwnd) {
VGMSTREAM * infostream = NULL;
char description[1024];
description[0]='\0';
@ -297,7 +387,7 @@ int infoDlg(char *fn, HWND hwnd) {
if (!vgmstream) return 0;
describe_vgmstream(vgmstream,description,sizeof(description));
} else {
infostream = init_vgmstream(fn);
infostream = init_vgmstream((char*)fn);
if (!infostream) return 0;
describe_vgmstream(infostream,description,sizeof(description));
close_vgmstream(infostream);
@ -309,7 +399,7 @@ int infoDlg(char *fn, HWND hwnd) {
}
/* retrieve information on this or possibly another file */
void getfileinfo(char *filename, char *title, int *length_in_ms) {
void getfileinfo(const in_char *filename, in_char *title, int *length_in_ms) {
if (!filename || !*filename) /* currently playing file*/
{
if (!vgmstream) return;
@ -318,7 +408,7 @@ void getfileinfo(char *filename, char *title, int *length_in_ms) {
{
char *p=lastfn+strlen(lastfn);
while (*p != '\\' && p >= lastfn) p--;
strcpy(title,++p);
strcpy((char*)title,++p);
}
}
else /* some other file */
@ -337,15 +427,17 @@ void getfileinfo(char *filename, char *title, int *length_in_ms) {
}
if (title)
{
char *p=filename+strlen(filename);
const char *p = filename + strlen(filename);
while (*p != '\\' && p >= filename) p--;
strcpy(title,++p);
strcpy((char*)title,++p);
}
}
}
/* nothin' */
void eq_set(int on, char data[10], int preamp) {}
/* eq stuff */
void eq_set(int on, char data[10], int preamp) {
/* nothin' */
}
/* the decode thread */
DWORD WINAPI __stdcall decode(void *arg) {
@ -439,7 +531,7 @@ DWORD WINAPI __stdcall decode(void *arg) {
INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
char buf[256];
char iniFile[MAX_PATH+1];
char iniFile[WINAMP_MAX_PATH];
static int mypri;
HANDLE hSlider;
@ -587,12 +679,16 @@ INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
return TRUE;
}
/* configuration dialog */
void config(HWND hwndParent) {
/* defined in resource.rc */
DialogBox(input_module.hDllInstance, (const char *)IDD_CONFIG, hwndParent, configDlgProc);
}
In_Module input_module =
{
/* *********************************** */
/* main plugin def */
In_Module input_module = {
IN_VER,
PLUGIN_DESCRIPTION,
0, /* hMainWindow */
@ -624,68 +720,6 @@ In_Module input_module =
0 // out_mod
};
__declspec( dllexport ) In_Module * winampGetInModule2()
{
__declspec( dllexport ) In_Module * winampGetInModule2() {
return &input_module;
}
/**
* Creates Winamp's extension list, a single string that ends with \0\0.
* Each extension must be in this format: "extension\0Description\0"
*/
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
int i;
working_extension_list[0]='\0';
working_extension_list[1]='\0';
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) {
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);
}
}
/**
* Adds ext to Winamp's extension list.
*/
static void add_extension(int length, char * dst, const char * ext) {
char buf[EXT_BUFFER_SIZE];
char ext_upp[EXT_BUFFER_SIZE];
int ext_len, written;
int i,j;
if (length <= 1)
return;
ext_len = strlen(ext);
/* find end of dst (double \0), saved in i */
for (i=0; i<length-2 && (dst[i] || dst[i+1]); i++)
;
/* check if end reached or not enough room to add */
if (i == length-2 || i + EXT_BUFFER_SIZE+2 > length-2 || ext_len * 3 + 20+2 > EXT_BUFFER_SIZE) {
dst[i]='\0';
dst[i+1]='\0';
return;
}
if (i > 0)
i++;
/* uppercase ext */
for (j=0; j < ext_len; j++)
ext_upp[j] = toupper(ext[j]);
ext_upp[j] = '\0';
/* copy new extension + double null terminate */
written = sprintf(buf, "%s%c%s Audio File (*.%s)%c", ext,'\0',ext_upp,ext_upp,'\0'); /*ex: "vgmstream\0vgmstream Audio File (*.VGMSTREAM)\0" */
for (j=0; j < written; i++,j++)
dst[i] = buf[j];
dst[i]='\0';
dst[i+1]='\0';
}

View File

@ -1,52 +1,73 @@
#ifndef NULLSOFT_OUTH
#define NULLSOFT_OUTH
#include <windows.h>
#include <stddef.h>
// ids:
// waveout: 32
// gapless: 64
// xfade: 63
// disk: 33
// dsound: 38
// NULL: 65
// mm2: 69
#if (_MSC_VER <= 1200)
typedef int intptr_t;
#endif
#define OUT_VER 0x10
typedef struct
{
int version; // module version (OUT_VER)
char *description; // description of module, with version string
int id; // module id. each input module gets its own. non-nullsoft modules should
// be >= 65536.
int version; // module version (OUT_VER)
char *description; // description of module, with version string
intptr_t id; // module id. each input module gets its own. non-nullsoft modules should
// be >= 65536.
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Init)(); // called when loaded
void (*Quit)(); // called when unloaded
void (*Init)(); // called when loaded
void (*Quit)(); // called when unloaded
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
// returns >=0 on success, <0 on failure
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
// ... so don't expect the max latency returned to be what you asked for.
// returns max latency in ms (0 for diskwriters, etc)
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
// prebufferms must be <= bufferlenms
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
// returns >=0 on success, <0 on failure
void (*Close)(); // close the ol' output device.
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
// ... so don't expect the max latency returned to be what you asked for.
// returns max latency in ms (0 for diskwriters, etc)
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
// prebufferms must be <= bufferlenms
// pass bufferlenms==-666 to tell the output plugin that it's clock is going to be used to sync video
// out_ds turns off silence-eating when -666 is passed
int (*Write)(char *buf, int len);
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
// 1 returns not able to write (yet). Non-blocking, always.
void (*Close)(); // close the ol' output device.
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
// Never will decrease unless you call Write (or Close, heh)
int (*Write)(char *buf, int len);
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
// 1 returns not able to write (yet). Non-blocking, always.
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
// Never will decrease unless you call Write (or Close, heh)
int (*Pause)(int pause); // returns previous pause state
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
void (*SetVolume)(int volume); // volume is 0-255
void (*SetPan)(int pan); // pan is -128 to 128
int (*Pause)(int pause); // returns previous pause state
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
// (used for seeking)
void (*SetVolume)(int volume); // volume is 0-255
void (*SetPan)(int pan); // pan is -128 to 128
int (*GetOutputTime)(); // returns played time in MS
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
// (used for seeking)
int (*GetOutputTime)(); // returns played time in MS
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
} Out_Module;
#endif

File diff suppressed because it is too large Load Diff