mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
Split Winamp code
This commit is contained in:
parent
5c1bc35b48
commit
4ade8eb470
@ -1,5 +1,7 @@
|
|||||||
file(GLOB WINAMP_SDK_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/sdk/*.h")
|
file(GLOB WINAMP_SDK_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/sdk/*.h")
|
||||||
set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resource.rc)
|
set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resource.rc)
|
||||||
|
file(GLOB WINAMP_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
|
||||||
|
file(GLOB WINAMP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
|
||||||
|
|
||||||
# Setup source groups, mainly for Visual Studio
|
# Setup source groups, mainly for Visual Studio
|
||||||
source_group("Header Files\\sdk" FILES ${WINAMP_SDK_HEADERS})
|
source_group("Header Files\\sdk" FILES ${WINAMP_SDK_HEADERS})
|
||||||
@ -7,8 +9,8 @@ source_group("Resource Files" FILES ${RESOURCES})
|
|||||||
|
|
||||||
add_library(in_vgmstream SHARED
|
add_library(in_vgmstream SHARED
|
||||||
${WINAMP_SDK_HEADERS}
|
${WINAMP_SDK_HEADERS}
|
||||||
resource.h
|
${WINAMP_HEADERS}
|
||||||
in_vgmstream.c
|
${WINAMP_SOURCES}
|
||||||
${RESOURCES})
|
${RESOURCES})
|
||||||
|
|
||||||
# Link to the vgmstream library
|
# Link to the vgmstream library
|
||||||
|
@ -27,12 +27,14 @@ TARGET_EXT_LIBS += $(LIBS_TARGET_EXT_LIBS)
|
|||||||
|
|
||||||
export CFLAGS LDFLAGS
|
export CFLAGS LDFLAGS
|
||||||
|
|
||||||
|
#SRC_SRCS = $(wildcard *.c)
|
||||||
|
SRC_SRCS = in_vgmstream.c in_streamfile.c in_config.c
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
### targets
|
### targets
|
||||||
|
|
||||||
in_vgmstream: libvgmstream.a $(TARGET_EXT_LIBS) resource.o
|
in_vgmstream: libvgmstream.a $(TARGET_EXT_LIBS) resource.o
|
||||||
$(CC) -shared -static-libgcc $(CFLAGS) "-DVERSION=\"`../version.sh`\"" in_vgmstream.c resource.o $(LDFLAGS) -o $(OUTPUT_WINAMP)
|
$(CC) -shared -static-libgcc $(CFLAGS) "-DVERSION=\"`../version.sh`\"" $(SRC_SRCS) resource.o $(LDFLAGS) -o $(OUTPUT_WINAMP)
|
||||||
$(STRIP) $(OUTPUT_WINAMP)
|
$(STRIP) $(OUTPUT_WINAMP)
|
||||||
|
|
||||||
resource.o: resource.rc resource.h
|
resource.o: resource.rc resource.h
|
||||||
|
372
winamp/in_config.c
Normal file
372
winamp/in_config.c
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
/**
|
||||||
|
* config for Winamp
|
||||||
|
*/
|
||||||
|
#include "in_vgmstream.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************* */
|
||||||
|
/* IN_CONFIG */
|
||||||
|
/* ************************************* */
|
||||||
|
|
||||||
|
/* config */
|
||||||
|
#define CONFIG_APP_NAME TEXT("vgmstream plugin")
|
||||||
|
#define CONFIG_INI_NAME TEXT("plugin.ini")
|
||||||
|
|
||||||
|
#define INI_FADE_TIME TEXT("fade_seconds")
|
||||||
|
#define INI_FADE_DELAY TEXT("fade_delay")
|
||||||
|
#define INI_LOOP_COUNT TEXT("loop_count")
|
||||||
|
#define INI_THREAD_PRIORITY TEXT("thread_priority")
|
||||||
|
#define INI_LOOP_FOREVER TEXT("loop_forever")
|
||||||
|
#define INI_IGNORE_LOOP TEXT("ignore_loop")
|
||||||
|
#define INI_DISABLE_SUBSONGS TEXT("disable_subsongs")
|
||||||
|
#define INI_DOWNMIX_CHANNELS TEXT("downmix_channels")
|
||||||
|
#define INI_TAGFILE_DISABLE TEXT("tagfile_disable")
|
||||||
|
#define INI_FORCE_TITLE TEXT("force_title")
|
||||||
|
#define INI_EXTS_UNKNOWN_ON TEXT("exts_unknown_on")
|
||||||
|
#define INI_EXTS_COMMON_ON TEXT("exts_common_on")
|
||||||
|
#define INI_GAIN_TYPE TEXT("gain_type")
|
||||||
|
#define INI_CLIP_TYPE TEXT("clip_type")
|
||||||
|
|
||||||
|
TCHAR *dlg_priority_strings[7] = {
|
||||||
|
TEXT("Idle"),
|
||||||
|
TEXT("Lowest"),
|
||||||
|
TEXT("Below Normal"),
|
||||||
|
TEXT("Normal"),
|
||||||
|
TEXT("Above Normal"),
|
||||||
|
TEXT("Highest (not recommended)"),
|
||||||
|
TEXT("Time Critical (not recommended)")
|
||||||
|
};
|
||||||
|
TCHAR *dlg_replaygain_strings[] = {
|
||||||
|
TEXT("None"),
|
||||||
|
TEXT("Album"),
|
||||||
|
TEXT("Peak")
|
||||||
|
};
|
||||||
|
|
||||||
|
int priority_values[7] = {
|
||||||
|
THREAD_PRIORITY_IDLE,
|
||||||
|
THREAD_PRIORITY_LOWEST,
|
||||||
|
THREAD_PRIORITY_BELOW_NORMAL,
|
||||||
|
THREAD_PRIORITY_NORMAL,
|
||||||
|
THREAD_PRIORITY_ABOVE_NORMAL,
|
||||||
|
THREAD_PRIORITY_HIGHEST,
|
||||||
|
THREAD_PRIORITY_TIME_CRITICAL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// todo finish UNICODE (requires IPC_GETINIDIRECTORYW from later SDKs to read the ini path properly)
|
||||||
|
/* Winamp INI reader */
|
||||||
|
static void ini_get_filename(In_Module* input_module, TCHAR *inifile) {
|
||||||
|
|
||||||
|
if (IsWindow(input_module->hMainWindow) && SendMessage(input_module->hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) {
|
||||||
|
/* newer Winamp with per-user settings */
|
||||||
|
TCHAR *ini_dir = (TCHAR *)SendMessage(input_module->hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);
|
||||||
|
cfg_strncpy(inifile, ini_dir, PATH_LIMIT);
|
||||||
|
|
||||||
|
cfg_strncat(inifile, TEXT("\\Plugins\\"), PATH_LIMIT);
|
||||||
|
|
||||||
|
/* can't be certain that \Plugins already exists in the user dir */
|
||||||
|
CreateDirectory(inifile,NULL);
|
||||||
|
|
||||||
|
cfg_strncat(inifile, CONFIG_INI_NAME, PATH_LIMIT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* older winamp with single settings */
|
||||||
|
TCHAR *lastSlash;
|
||||||
|
|
||||||
|
GetModuleFileName(NULL, inifile, PATH_LIMIT);
|
||||||
|
lastSlash = cfg_strrchr(inifile, TEXT('\\'));
|
||||||
|
|
||||||
|
*(lastSlash + 1) = 0;
|
||||||
|
|
||||||
|
/* XMPlay doesn't have a "plugins" subfolder */
|
||||||
|
if (settings.is_xmplay)
|
||||||
|
cfg_strncat(inifile, CONFIG_INI_NAME,PATH_LIMIT);
|
||||||
|
else
|
||||||
|
cfg_strncat(inifile, TEXT("Plugins\\") CONFIG_INI_NAME,PATH_LIMIT);
|
||||||
|
/* Maybe should query IPC_GETINIDIRECTORY and use that, not sure what ancient Winamps need.
|
||||||
|
* There must be some proper way to handle dirs since other Winamp plugins save config in
|
||||||
|
* XMPlay correctly (this feels like archaeology, try later) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ini_get_d(const char *inifile, const char *entry, double defval, double *p_val) {
|
||||||
|
TCHAR buf[256];
|
||||||
|
TCHAR defbuf[256];
|
||||||
|
int consumed, res;
|
||||||
|
|
||||||
|
cfg_sprintf(defbuf, TEXT("%.2lf"), defval);
|
||||||
|
GetPrivateProfileString(CONFIG_APP_NAME, entry, defbuf, buf, 256, inifile);
|
||||||
|
res = cfg_sscanf(buf, TEXT("%lf%n"), p_val, &consumed);
|
||||||
|
if (res < 1 || consumed != cfg_strlen(buf) || *p_val < 0) {
|
||||||
|
*p_val = defval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void ini_get_i(const char *inifile, const char *entry, int defval, int *p_val, int min, int max) {
|
||||||
|
*p_val = GetPrivateProfileInt(CONFIG_APP_NAME, entry, defval, inifile);
|
||||||
|
if (*p_val < min || *p_val > max) {
|
||||||
|
*p_val = defval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void ini_get_b(const char *inifile, const char *entry, int defval, int *p_val) {
|
||||||
|
ini_get_i(inifile, entry, defval, p_val, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ini_set_d(const char *inifile, const char *entry, double val) {
|
||||||
|
TCHAR buf[256];
|
||||||
|
cfg_sprintf(buf, TEXT("%.2lf"), val);
|
||||||
|
WritePrivateProfileString(CONFIG_APP_NAME, entry, buf, inifile);
|
||||||
|
}
|
||||||
|
static void ini_set_i(const char *inifile, const char *entry, int val) {
|
||||||
|
TCHAR buf[32];
|
||||||
|
cfg_sprintf(buf, TEXT("%d"), val);
|
||||||
|
WritePrivateProfileString(CONFIG_APP_NAME, entry, buf, inifile);
|
||||||
|
}
|
||||||
|
static void ini_set_b(const char *inifile, const char *entry, int val) {
|
||||||
|
ini_set_i(inifile, entry, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ void load_defaults(winamp_settings_t* defaults) {
|
||||||
|
defaults->thread_priority = 3;
|
||||||
|
defaults->fade_time = 10.0;
|
||||||
|
defaults->fade_delay = 0.0;
|
||||||
|
defaults->loop_count = 2.0;
|
||||||
|
defaults->loop_forever = 0;
|
||||||
|
defaults->ignore_loop = 0;
|
||||||
|
defaults->disable_subsongs = 0;
|
||||||
|
defaults->downmix_channels = 0;
|
||||||
|
defaults->tagfile_disable = 0;
|
||||||
|
defaults->force_title = 0;
|
||||||
|
defaults->exts_unknown_on = 0;
|
||||||
|
defaults->exts_common_on = 0;
|
||||||
|
defaults->gain_type = 1;
|
||||||
|
defaults->clip_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ void load_config(In_Module* input_module, winamp_settings_t* settings, winamp_settings_t* defaults) {
|
||||||
|
TCHAR inifile[PATH_LIMIT];
|
||||||
|
|
||||||
|
ini_get_filename(input_module, inifile);
|
||||||
|
|
||||||
|
ini_get_i(inifile, INI_THREAD_PRIORITY, defaults->thread_priority, &settings->thread_priority, 0, 6);
|
||||||
|
|
||||||
|
ini_get_d(inifile, INI_FADE_TIME, defaults->fade_time, &settings->fade_time);
|
||||||
|
ini_get_d(inifile, INI_FADE_DELAY, defaults->fade_delay, &settings->fade_delay);
|
||||||
|
ini_get_d(inifile, INI_LOOP_COUNT, defaults->loop_count, &settings->loop_count);
|
||||||
|
|
||||||
|
ini_get_b(inifile, INI_LOOP_FOREVER, defaults->loop_forever, &settings->loop_forever);
|
||||||
|
ini_get_b(inifile, INI_IGNORE_LOOP, defaults->ignore_loop, &settings->ignore_loop);
|
||||||
|
|
||||||
|
ini_get_b(inifile, INI_DISABLE_SUBSONGS, defaults->disable_subsongs, &settings->disable_subsongs);
|
||||||
|
ini_get_i(inifile, INI_DOWNMIX_CHANNELS, defaults->downmix_channels, &settings->downmix_channels, 0, 64);
|
||||||
|
ini_get_b(inifile, INI_TAGFILE_DISABLE, defaults->tagfile_disable, &settings->tagfile_disable);
|
||||||
|
ini_get_b(inifile, INI_FORCE_TITLE, defaults->force_title, &settings->force_title);
|
||||||
|
ini_get_b(inifile, INI_EXTS_UNKNOWN_ON, defaults->exts_unknown_on, &settings->exts_unknown_on);
|
||||||
|
ini_get_b(inifile, INI_EXTS_COMMON_ON, defaults->exts_common_on, &settings->exts_common_on);
|
||||||
|
|
||||||
|
ini_get_i(inifile, INI_GAIN_TYPE, defaults->gain_type, (int*)&settings->gain_type, 0, 3);
|
||||||
|
ini_get_i(inifile, INI_CLIP_TYPE, defaults->clip_type, (int*)&settings->clip_type, 0, 3);
|
||||||
|
|
||||||
|
if (settings->loop_forever && settings->ignore_loop)
|
||||||
|
settings->ignore_loop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_config(In_Module* input_module, winamp_settings_t* settings) {
|
||||||
|
TCHAR inifile[PATH_LIMIT];
|
||||||
|
|
||||||
|
ini_get_filename(input_module, inifile);
|
||||||
|
|
||||||
|
ini_set_i(inifile, INI_THREAD_PRIORITY, settings->thread_priority);
|
||||||
|
|
||||||
|
ini_set_d(inifile, INI_FADE_TIME, settings->fade_time);
|
||||||
|
ini_set_d(inifile, INI_FADE_DELAY, settings->fade_delay);
|
||||||
|
ini_set_d(inifile, INI_LOOP_COUNT, settings->loop_count);
|
||||||
|
|
||||||
|
ini_set_b(inifile, INI_LOOP_FOREVER, settings->loop_forever);
|
||||||
|
ini_set_b(inifile, INI_IGNORE_LOOP, settings->ignore_loop);
|
||||||
|
|
||||||
|
ini_set_b(inifile, INI_DISABLE_SUBSONGS, settings->disable_subsongs);
|
||||||
|
ini_set_i(inifile, INI_DOWNMIX_CHANNELS, settings->downmix_channels);
|
||||||
|
ini_set_b(inifile, INI_TAGFILE_DISABLE, settings->tagfile_disable);
|
||||||
|
ini_set_b(inifile, INI_FORCE_TITLE, settings->force_title);
|
||||||
|
ini_set_b(inifile, INI_EXTS_UNKNOWN_ON, settings->exts_unknown_on);
|
||||||
|
ini_set_b(inifile, INI_EXTS_COMMON_ON, settings->exts_common_on);
|
||||||
|
|
||||||
|
ini_set_i(inifile, INI_GAIN_TYPE, settings->gain_type);
|
||||||
|
ini_set_i(inifile, INI_CLIP_TYPE, settings->clip_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void dlg_input_set_d(HWND hDlg, int idc, double val) {
|
||||||
|
TCHAR buf[256];
|
||||||
|
cfg_sprintf(buf, TEXT("%.2lf"), val);
|
||||||
|
SetDlgItemText(hDlg, idc, buf);
|
||||||
|
}
|
||||||
|
static void dlg_input_set_i(HWND hDlg, int idc, int val) {
|
||||||
|
TCHAR buf[32];
|
||||||
|
cfg_sprintf(buf, TEXT("%d"), val);
|
||||||
|
SetDlgItemText(hDlg, idc, buf);
|
||||||
|
}
|
||||||
|
static void dlg_check_set(HWND hDlg, int idc, int val) {
|
||||||
|
CheckDlgButton(hDlg, idc, val ? BST_CHECKED : BST_UNCHECKED);
|
||||||
|
}
|
||||||
|
static void cfg_combo_set(HWND hDlg, int idc, int val, TCHAR **list, int list_size) {
|
||||||
|
int i;
|
||||||
|
HANDLE hCombo = GetDlgItem(hDlg, idc);
|
||||||
|
for (i = 0; i < list_size; i++) {
|
||||||
|
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)list[i]);
|
||||||
|
}
|
||||||
|
SendMessage(hCombo, CB_SETCURSEL, val, 0);
|
||||||
|
}
|
||||||
|
static void cfg_slider_set(HWND hDlg, int idc1, int idc2, int val, int min, int max, TCHAR **list) {
|
||||||
|
HANDLE hSlider = GetDlgItem(hDlg, idc1);
|
||||||
|
SendMessage(hSlider, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(min, max));
|
||||||
|
SendMessage(hSlider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)val+1);
|
||||||
|
SetDlgItemText(hDlg, idc2, list[val]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dlg_input_get_d(HWND hDlg, int idc, double *p_val, LPCTSTR error, int *p_err) {
|
||||||
|
TCHAR buf[256];
|
||||||
|
int res, consumed;
|
||||||
|
double defval = *p_val;
|
||||||
|
|
||||||
|
GetDlgItemText(hDlg, idc, buf, 256);
|
||||||
|
res = cfg_sscanf(buf, TEXT("%lf%n"), p_val, &consumed);
|
||||||
|
if (res < 1 || consumed != cfg_strlen(buf) || *p_val < 0) {
|
||||||
|
MessageBox(hDlg, error, NULL, MB_OK|MB_ICONERROR);
|
||||||
|
*p_val = defval;
|
||||||
|
*p_err = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void dlg_input_get_i(HWND hDlg, int idc, int *p_val, LPCTSTR error, int *p_err) {
|
||||||
|
TCHAR buf[32];
|
||||||
|
int res, consumed;
|
||||||
|
int defval = *p_val;
|
||||||
|
|
||||||
|
GetDlgItemText(hDlg, idc, buf, 32);
|
||||||
|
res = cfg_sscanf(buf, TEXT("%d%n"), p_val, &consumed);
|
||||||
|
if (res < 1 || consumed != cfg_strlen(buf) || *p_val < 0) {
|
||||||
|
MessageBox(hDlg, error, NULL, MB_OK|MB_ICONERROR);
|
||||||
|
*p_val = defval;
|
||||||
|
*p_err = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void dlg_check_get(HWND hDlg, int idc, int *p_val) {
|
||||||
|
*p_val = (IsDlgButtonChecked(hDlg, idc) == BST_CHECKED);
|
||||||
|
}
|
||||||
|
static void dlg_combo_get(HWND hDlg, int idc, int *p_val) {
|
||||||
|
*p_val = SendMessage(GetDlgItem(hDlg, idc), CB_GETCURSEL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dlg_load_form(HWND hDlg, winamp_settings_t* settings) {
|
||||||
|
int err = 0;
|
||||||
|
dlg_input_get_d(hDlg, IDC_FADE_TIME, &settings->fade_time, TEXT("Fade Length must be a positive number"), &err);
|
||||||
|
dlg_input_get_d(hDlg, IDC_FADE_DELAY, &settings->fade_delay, TEXT("Fade Delay must be a positive number"), &err);
|
||||||
|
dlg_input_get_d(hDlg, IDC_LOOP_COUNT, &settings->loop_count, TEXT("Loop Count must be a positive number"), &err);
|
||||||
|
|
||||||
|
dlg_check_get(hDlg, IDC_LOOP_FOREVER, &settings->loop_forever);
|
||||||
|
dlg_check_get(hDlg, IDC_IGNORE_LOOP, &settings->ignore_loop);
|
||||||
|
|
||||||
|
dlg_check_get(hDlg, IDC_DISABLE_SUBSONGS, &settings->disable_subsongs);
|
||||||
|
dlg_input_get_i(hDlg, IDC_DOWNMIX_CHANNELS, &settings->downmix_channels, TEXT("Downmix must be a positive integer number"), &err);
|
||||||
|
dlg_check_get(hDlg, IDC_TAGFILE_DISABLE, &settings->tagfile_disable);
|
||||||
|
dlg_check_get(hDlg, IDC_FORCE_TITLE, &settings->force_title);
|
||||||
|
dlg_check_get(hDlg, IDC_EXTS_UNKNOWN_ON, &settings->exts_unknown_on);
|
||||||
|
dlg_check_get(hDlg, IDC_EXTS_COMMON_ON, &settings->exts_common_on);
|
||||||
|
|
||||||
|
dlg_combo_get(hDlg, IDC_GAIN_TYPE, (int*)&settings->gain_type);
|
||||||
|
dlg_combo_get(hDlg, IDC_CLIP_TYPE, (int*)&settings->clip_type);
|
||||||
|
|
||||||
|
return err ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dlg_save_form(HWND hDlg, winamp_settings_t* settings, int reset) {
|
||||||
|
cfg_slider_set(hDlg, IDC_THREAD_PRIORITY_SLIDER, IDC_THREAD_PRIORITY_TEXT, settings->thread_priority, 1, 7, dlg_priority_strings);
|
||||||
|
|
||||||
|
dlg_input_set_d(hDlg, IDC_FADE_TIME, settings->fade_time);
|
||||||
|
dlg_input_set_d(hDlg, IDC_FADE_DELAY, settings->fade_delay);
|
||||||
|
dlg_input_set_d(hDlg, IDC_LOOP_COUNT, settings->loop_count);
|
||||||
|
|
||||||
|
dlg_check_set(hDlg, IDC_LOOP_FOREVER, settings->loop_forever);
|
||||||
|
dlg_check_set(hDlg, IDC_IGNORE_LOOP, settings->ignore_loop);
|
||||||
|
dlg_check_set(hDlg, IDC_LOOP_NORMALLY, (!settings->loop_forever && !settings->ignore_loop));
|
||||||
|
|
||||||
|
dlg_check_set(hDlg, IDC_DISABLE_SUBSONGS, settings->disable_subsongs);
|
||||||
|
dlg_input_set_i(hDlg, IDC_DOWNMIX_CHANNELS, settings->downmix_channels);
|
||||||
|
dlg_check_set(hDlg, IDC_TAGFILE_DISABLE, settings->tagfile_disable);
|
||||||
|
dlg_check_set(hDlg, IDC_FORCE_TITLE, settings->force_title);
|
||||||
|
dlg_check_set(hDlg, IDC_EXTS_UNKNOWN_ON, settings->exts_unknown_on);
|
||||||
|
dlg_check_set(hDlg, IDC_EXTS_COMMON_ON, settings->exts_common_on);
|
||||||
|
|
||||||
|
cfg_combo_set(hDlg, IDC_GAIN_TYPE, settings->gain_type, dlg_replaygain_strings, (reset ? 0 : 3));
|
||||||
|
cfg_combo_set(hDlg, IDC_CLIP_TYPE, settings->clip_type, dlg_replaygain_strings, (reset ? 0 : 3));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* config dialog handler */
|
||||||
|
INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
static int priority;
|
||||||
|
/* globals to get them a bit controlled */
|
||||||
|
winamp_settings_t* settings_ext = &settings;
|
||||||
|
In_Module* input_module_ext = &input_module;
|
||||||
|
|
||||||
|
switch (uMsg) {
|
||||||
|
case WM_CLOSE: /* hide dialog */
|
||||||
|
EndDialog(hDlg,TRUE);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case WM_INITDIALOG: /* open dialog: load form with current settings */
|
||||||
|
priority = settings_ext->thread_priority;
|
||||||
|
dlg_save_form(hDlg, settings_ext, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_COMMAND: /* button presses */
|
||||||
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
||||||
|
case IDOK: { /* read and verify new values, save and close */
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
settings_ext->thread_priority = priority;
|
||||||
|
ok = dlg_load_form(hDlg, settings_ext);
|
||||||
|
if (!ok) break; /* this leaves values changed though */
|
||||||
|
|
||||||
|
save_config(input_module_ext, settings_ext);
|
||||||
|
|
||||||
|
EndDialog(hDlg,TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDCANCEL: /* cancel dialog */
|
||||||
|
EndDialog(hDlg,TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_DEFAULT_BUTTON: { /* reset values */
|
||||||
|
priority = defaults.thread_priority;
|
||||||
|
dlg_save_form(hDlg, &defaults, 1);
|
||||||
|
|
||||||
|
/* we don't save settings here as user can still cancel the dialog */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case WM_HSCROLL: /* priority scroll */
|
||||||
|
if ((struct HWND__*)lParam == GetDlgItem(hDlg, IDC_THREAD_PRIORITY_SLIDER)) {
|
||||||
|
if (LOWORD(wParam) == TB_THUMBPOSITION || LOWORD(wParam) == TB_THUMBTRACK) {
|
||||||
|
priority = HIWORD(wParam)-1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
priority = SendMessage(GetDlgItem(hDlg,IDC_THREAD_PRIORITY_SLIDER),TBM_GETPOS,0,0)-1;
|
||||||
|
}
|
||||||
|
SetDlgItemText(hDlg, IDC_THREAD_PRIORITY_TEXT, dlg_priority_strings[priority]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
155
winamp/in_streamfile.c
Normal file
155
winamp/in_streamfile.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/**
|
||||||
|
* streamfile for Winamp
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include "in_vgmstream.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************* */
|
||||||
|
/* IN_UNICODE */
|
||||||
|
/* ************************************* */
|
||||||
|
|
||||||
|
/* opens a utf16 (unicode) path */
|
||||||
|
static FILE* wa_fopen(const in_char *wpath) {
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
return _wfopen(wpath,L"rb");
|
||||||
|
#else
|
||||||
|
return fopen(wpath,"rb");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dupes a utf16 (unicode) file */
|
||||||
|
static FILE* wa_fdopen(int fd) {
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
return _wfdopen(fd,L"rb");
|
||||||
|
#else
|
||||||
|
return fdopen(fd,"rb");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************* */
|
||||||
|
/* IN_STREAMFILE */
|
||||||
|
/* ************************************* */
|
||||||
|
|
||||||
|
/* a STREAMFILE that operates via STDIOSTREAMFILE but handles Winamp's unicode (in_char) paths */
|
||||||
|
typedef struct {
|
||||||
|
STREAMFILE sf;
|
||||||
|
STREAMFILE *stdiosf;
|
||||||
|
FILE *infile_ref; /* pointer to the infile in stdiosf (partially handled by stdiosf) */
|
||||||
|
} WINAMP_STREAMFILE;
|
||||||
|
|
||||||
|
static STREAMFILE *open_winamp_streamfile_by_file(FILE *infile, const char * path);
|
||||||
|
//static STREAMFILE *open_winamp_streamfile_by_ipath(const in_char *wpath);
|
||||||
|
|
||||||
|
static size_t wasf_read(WINAMP_STREAMFILE* sf, uint8_t* dest, off_t offset, size_t length) {
|
||||||
|
return sf->stdiosf->read(sf->stdiosf, dest, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t wasf_get_size(WINAMP_STREAMFILE* sf) {
|
||||||
|
return sf->stdiosf->get_size(sf->stdiosf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t wasf_get_offset(WINAMP_STREAMFILE* sf) {
|
||||||
|
return sf->stdiosf->get_offset(sf->stdiosf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wasf_get_name(WINAMP_STREAMFILE* sf, char* buffer, size_t length) {
|
||||||
|
sf->stdiosf->get_name(sf->stdiosf, buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static STREAMFILE *wasf_open(WINAMP_STREAMFILE* sf, const char* const filename, size_t buffersize) {
|
||||||
|
in_char wpath[PATH_LIMIT];
|
||||||
|
char name[PATH_LIMIT];
|
||||||
|
|
||||||
|
if (!filename)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#if !defined (__ANDROID__) && !defined (_MSC_VER)
|
||||||
|
/* When enabling this for MSVC it'll seemingly work, but there are issues possibly related to underlying
|
||||||
|
* IO buffers when using dup(), noticeable by re-opening the same streamfile with small buffer sizes
|
||||||
|
* (reads garbage). This reportedly causes issues in Android too */
|
||||||
|
|
||||||
|
sf->stdiosf->get_name(sf->stdiosf, name, PATH_LIMIT);
|
||||||
|
/* if same name, duplicate the file descriptor we already have open */ //unsure if all this is needed
|
||||||
|
if (sf->infile_ref && !strcmp(name,filename)) {
|
||||||
|
int new_fd;
|
||||||
|
FILE *new_file;
|
||||||
|
|
||||||
|
if (((new_fd = dup(fileno(sf->infile_ref))) >= 0) && (new_file = wa_fdopen(new_fd))) {
|
||||||
|
STREAMFILE *new_sf = open_winamp_streamfile_by_file(new_file, filename);
|
||||||
|
if (new_sf)
|
||||||
|
return new_sf;
|
||||||
|
fclose(new_file);
|
||||||
|
}
|
||||||
|
if (new_fd >= 0 && !new_file)
|
||||||
|
close(new_fd); /* fdopen may fail when opening too many files */
|
||||||
|
|
||||||
|
/* on failure just close and try the default path (which will probably fail a second time) */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* STREAMFILEs carry char/UTF8 names, convert to wchar for Winamp */
|
||||||
|
wa_char_to_ichar(wpath, PATH_LIMIT, filename);
|
||||||
|
return open_winamp_streamfile_by_ipath(wpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wasf_close(WINAMP_STREAMFILE* sf) {
|
||||||
|
/* closes infile_ref + frees in the internal STDIOSTREAMFILE (fclose for wchar is not needed) */
|
||||||
|
sf->stdiosf->close(sf->stdiosf);
|
||||||
|
free(sf); /* and the current struct */
|
||||||
|
}
|
||||||
|
|
||||||
|
static STREAMFILE *open_winamp_streamfile_by_file(FILE* file, const char* path) {
|
||||||
|
WINAMP_STREAMFILE* this_sf = NULL;
|
||||||
|
STREAMFILE* stdiosf = NULL;
|
||||||
|
|
||||||
|
this_sf = calloc(1,sizeof(WINAMP_STREAMFILE));
|
||||||
|
if (!this_sf) goto fail;
|
||||||
|
|
||||||
|
stdiosf = open_stdio_streamfile_by_file(file, path);
|
||||||
|
if (!stdiosf) goto fail;
|
||||||
|
|
||||||
|
this_sf->sf.read = (void*)wasf_read;
|
||||||
|
this_sf->sf.get_size = (void*)wasf_get_size;
|
||||||
|
this_sf->sf.get_offset = (void*)wasf_get_offset;
|
||||||
|
this_sf->sf.get_name = (void*)wasf_get_name;
|
||||||
|
this_sf->sf.open = (void*)wasf_open;
|
||||||
|
this_sf->sf.close = (void*)wasf_close;
|
||||||
|
|
||||||
|
this_sf->stdiosf = stdiosf;
|
||||||
|
this_sf->infile_ref = file;
|
||||||
|
|
||||||
|
return &this_sf->sf; /* pointer to STREAMFILE start = rest of the custom data follows */
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_streamfile(stdiosf);
|
||||||
|
free(this_sf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STREAMFILE* open_winamp_streamfile_by_ipath(const in_char* wpath) {
|
||||||
|
FILE* infile = NULL;
|
||||||
|
STREAMFILE* sf;
|
||||||
|
char path[PATH_LIMIT];
|
||||||
|
|
||||||
|
|
||||||
|
/* convert to UTF-8 if needed for internal use */
|
||||||
|
wa_ichar_to_char(path,PATH_LIMIT, wpath);
|
||||||
|
|
||||||
|
/* open a FILE from a Winamp (possibly UTF-16) path */
|
||||||
|
infile = wa_fopen(wpath);
|
||||||
|
if (!infile) {
|
||||||
|
/* allow non-existing files in some cases */
|
||||||
|
if (!vgmstream_is_virtual_filename(path))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf = open_winamp_streamfile_by_file(infile,path);
|
||||||
|
if (!sf) {
|
||||||
|
if (infile) fclose(infile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sf;
|
||||||
|
}
|
@ -1,33 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* vgmstream for Winamp
|
* vgmstream for Winamp
|
||||||
*/
|
*/
|
||||||
|
#include "in_vgmstream.h"
|
||||||
/* Normally Winamp opens unicode files by their DOS 8.3 name. #define this to use wchar_t filenames,
|
|
||||||
* which must be opened with _wfopen in a WINAMP_STREAMFILE (needed for dual files like .pos).
|
|
||||||
* Only for Winamp paths, other parts would need #define UNICODE for Windows. */
|
|
||||||
#ifdef VGM_WINAMP_UNICODE
|
|
||||||
#define UNICODE_INPUT_PLUGIN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define _CRT_SECURE_NO_DEPRECATE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <windowsx.h>
|
|
||||||
#include <commctrl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <io.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "../src/vgmstream.h"
|
|
||||||
#include "../src/plugins.h"
|
|
||||||
#include "sdk/in2.h"
|
|
||||||
#include "sdk/wa_ipc.h"
|
|
||||||
#include "sdk/ipc_pe.h"
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@ -39,7 +13,9 @@
|
|||||||
#define PLUGIN_DESCRIPTION "vgmstream plugin " VERSION " " __DATE__
|
#define PLUGIN_DESCRIPTION "vgmstream plugin " VERSION " " __DATE__
|
||||||
|
|
||||||
|
|
||||||
/* ************************************* */
|
/* ***************************************** */
|
||||||
|
/* IN_STATE */
|
||||||
|
/* ***************************************** */
|
||||||
|
|
||||||
#define EXT_BUFFER_SIZE 200
|
#define EXT_BUFFER_SIZE 200
|
||||||
|
|
||||||
@ -52,34 +28,6 @@ DWORD WINAPI __stdcall decode(void *arg);
|
|||||||
/* fixed list to simplify but could also malloc/free on init/close */
|
/* fixed list to simplify but could also malloc/free on init/close */
|
||||||
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
REPLAYGAIN_NONE,
|
|
||||||
REPLAYGAIN_ALBUM,
|
|
||||||
REPLAYGAIN_TRACK
|
|
||||||
} replay_gain_type_t;
|
|
||||||
|
|
||||||
/* loaded settings */
|
|
||||||
typedef struct {
|
|
||||||
int thread_priority;
|
|
||||||
|
|
||||||
double fade_time;
|
|
||||||
double fade_delay;
|
|
||||||
double loop_count;
|
|
||||||
int ignore_loop;
|
|
||||||
int loop_forever;
|
|
||||||
|
|
||||||
int disable_subsongs;
|
|
||||||
int downmix_channels;
|
|
||||||
int tagfile_disable;
|
|
||||||
int force_title;
|
|
||||||
int exts_unknown_on;
|
|
||||||
int exts_common_on;
|
|
||||||
|
|
||||||
replay_gain_type_t gain_type;
|
|
||||||
replay_gain_type_t clip_type;
|
|
||||||
|
|
||||||
int is_xmplay;
|
|
||||||
} winamp_settings_t;
|
|
||||||
|
|
||||||
/* current play state */
|
/* current play state */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -110,223 +58,9 @@ winamp_state_t state;
|
|||||||
short sample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS]; //todo maybe should be dynamic
|
short sample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS]; //todo maybe should be dynamic
|
||||||
|
|
||||||
|
|
||||||
/* ************************************* */
|
/* ***************************************** */
|
||||||
/* IN_UNICODE */
|
/* IN_VGMSTREAM UTILS */
|
||||||
/* ************************************* */
|
/* ***************************************** */
|
||||||
//todo safe ops
|
|
||||||
//todo there must be a better way to handle unicode...
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
#define wa_strcmp wcscmp
|
|
||||||
#define wa_strcpy wcscpy
|
|
||||||
#define wa_strncpy wcsncpy
|
|
||||||
#define wa_strcat wcscat
|
|
||||||
#define wa_strlen wcslen
|
|
||||||
#define wa_strchr wcschr
|
|
||||||
#define wa_sscanf swscanf
|
|
||||||
#define wa_snprintf _snwprintf
|
|
||||||
#define wa_strrchr wcsrchr
|
|
||||||
#define wa_fileinfo fileinfoW
|
|
||||||
#define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAMEW
|
|
||||||
#define wa_L(x) L ##x
|
|
||||||
#else
|
|
||||||
#define wa_strcmp strcmp
|
|
||||||
#define wa_strcpy strcpy
|
|
||||||
#define wa_strncpy strncpy
|
|
||||||
#define wa_strcat strcat
|
|
||||||
#define wa_strlen strlen
|
|
||||||
#define wa_strchr strchr
|
|
||||||
#define wa_sscanf sscanf
|
|
||||||
#define wa_snprintf snprintf
|
|
||||||
#define wa_strrchr strrchr
|
|
||||||
#define wa_fileinfo fileinfo
|
|
||||||
#define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAME
|
|
||||||
#define wa_L(x) x
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* converts from utf16 to utf8 (if unicode is on) */
|
|
||||||
static void wa_ichar_to_char(char *dst, size_t dstsize, const in_char *wsrc) {
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
/* converto to UTF8 codepage, default separate bytes, source wstr, wstr length */
|
|
||||||
//int size_needed = WideCharToMultiByte(CP_UTF8,0, src,-1, NULL,0, NULL, NULL);
|
|
||||||
WideCharToMultiByte(CP_UTF8,0, wsrc,-1, dst,dstsize, NULL, NULL);
|
|
||||||
#else
|
|
||||||
strncpy(dst, wsrc, dstsize);
|
|
||||||
dst[dstsize - 1] = '\0';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* converts from utf8 to utf16 (if unicode is on) */
|
|
||||||
static void wa_char_to_ichar(in_char *wdst, size_t wdstsize, const char *src) {
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
//int size_needed = MultiByteToWideChar(CP_UTF8,0, src,-1, NULL,0);
|
|
||||||
MultiByteToWideChar(CP_UTF8,0, src,-1, wdst,wdstsize);
|
|
||||||
#else
|
|
||||||
strncpy(wdst, src, wdstsize);
|
|
||||||
wdst[wdstsize - 1] = '\0';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copies from utf16 to utf16 (if unicode is active) */
|
|
||||||
static void wa_wchar_to_ichar(in_char *wdst, size_t wdstsize, const wchar_t *src) {
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
wcscpy(wdst,src);
|
|
||||||
#else
|
|
||||||
strcpy(wdst,src); //todo ???
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copies from utf16 to utf16 */
|
|
||||||
static void wa_char_to_wchar(wchar_t *wdst, size_t wdstsize, const char *src) {
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
MultiByteToWideChar(CP_UTF8,0, src,-1, wdst,wdstsize);
|
|
||||||
#else
|
|
||||||
strcpy(wdst,src); //todo ???
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* opens a utf16 (unicode) path */
|
|
||||||
static FILE* wa_fopen(const in_char *wpath) {
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
return _wfopen(wpath,L"rb");
|
|
||||||
#else
|
|
||||||
return fopen(wpath,"rb");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dupes a utf16 (unicode) file */
|
|
||||||
static FILE* wa_fdopen(int fd) {
|
|
||||||
#ifdef UNICODE_INPUT_PLUGIN
|
|
||||||
return _wfdopen(fd,L"rb");
|
|
||||||
#else
|
|
||||||
return fdopen(fd,"rb");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************* */
|
|
||||||
/* IN_STREAMFILE */
|
|
||||||
/* ************************************* */
|
|
||||||
|
|
||||||
/* a STREAMFILE that operates via STDIOSTREAMFILE but handles Winamp's unicode (in_char) paths */
|
|
||||||
typedef struct {
|
|
||||||
STREAMFILE sf;
|
|
||||||
STREAMFILE *stdiosf;
|
|
||||||
FILE *infile_ref; /* pointer to the infile in stdiosf (partially handled by stdiosf) */
|
|
||||||
} WINAMP_STREAMFILE;
|
|
||||||
|
|
||||||
static STREAMFILE *open_winamp_streamfile_by_file(FILE *infile, const char * path);
|
|
||||||
static STREAMFILE *open_winamp_streamfile_by_ipath(const in_char *wpath);
|
|
||||||
|
|
||||||
static size_t wasf_read(WINAMP_STREAMFILE* sf, uint8_t* dest, off_t offset, size_t length) {
|
|
||||||
return sf->stdiosf->read(sf->stdiosf, dest, offset, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static off_t wasf_get_size(WINAMP_STREAMFILE* sf) {
|
|
||||||
return sf->stdiosf->get_size(sf->stdiosf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static off_t wasf_get_offset(WINAMP_STREAMFILE* sf) {
|
|
||||||
return sf->stdiosf->get_offset(sf->stdiosf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wasf_get_name(WINAMP_STREAMFILE* sf, char* buffer, size_t length) {
|
|
||||||
sf->stdiosf->get_name(sf->stdiosf, buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static STREAMFILE *wasf_open(WINAMP_STREAMFILE* sf, const char* const filename, size_t buffersize) {
|
|
||||||
in_char wpath[PATH_LIMIT];
|
|
||||||
char name[PATH_LIMIT];
|
|
||||||
|
|
||||||
if (!filename)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#if !defined (__ANDROID__) && !defined (_MSC_VER)
|
|
||||||
/* When enabling this for MSVC it'll seemingly work, but there are issues possibly related to underlying
|
|
||||||
* IO buffers when using dup(), noticeable by re-opening the same streamfile with small buffer sizes
|
|
||||||
* (reads garbage). This reportedly causes issues in Android too */
|
|
||||||
|
|
||||||
sf->stdiosf->get_name(sf->stdiosf, name, PATH_LIMIT);
|
|
||||||
/* if same name, duplicate the file descriptor we already have open */ //unsure if all this is needed
|
|
||||||
if (sf->infile_ref && !strcmp(name,filename)) {
|
|
||||||
int new_fd;
|
|
||||||
FILE *new_file;
|
|
||||||
|
|
||||||
if (((new_fd = dup(fileno(sf->infile_ref))) >= 0) && (new_file = wa_fdopen(new_fd))) {
|
|
||||||
STREAMFILE *new_sf = open_winamp_streamfile_by_file(new_file, filename);
|
|
||||||
if (new_sf)
|
|
||||||
return new_sf;
|
|
||||||
fclose(new_file);
|
|
||||||
}
|
|
||||||
if (new_fd >= 0 && !new_file)
|
|
||||||
close(new_fd); /* fdopen may fail when opening too many files */
|
|
||||||
|
|
||||||
/* on failure just close and try the default path (which will probably fail a second time) */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* STREAMFILEs carry char/UTF8 names, convert to wchar for Winamp */
|
|
||||||
wa_char_to_ichar(wpath, PATH_LIMIT, filename);
|
|
||||||
return open_winamp_streamfile_by_ipath(wpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wasf_close(WINAMP_STREAMFILE* sf) {
|
|
||||||
/* closes infile_ref + frees in the internal STDIOSTREAMFILE (fclose for wchar is not needed) */
|
|
||||||
sf->stdiosf->close(sf->stdiosf);
|
|
||||||
free(sf); /* and the current struct */
|
|
||||||
}
|
|
||||||
|
|
||||||
static STREAMFILE *open_winamp_streamfile_by_file(FILE* file, const char* path) {
|
|
||||||
WINAMP_STREAMFILE* this_sf = NULL;
|
|
||||||
STREAMFILE* stdiosf = NULL;
|
|
||||||
|
|
||||||
this_sf = calloc(1,sizeof(WINAMP_STREAMFILE));
|
|
||||||
if (!this_sf) goto fail;
|
|
||||||
|
|
||||||
stdiosf = open_stdio_streamfile_by_file(file, path);
|
|
||||||
if (!stdiosf) goto fail;
|
|
||||||
|
|
||||||
this_sf->sf.read = (void*)wasf_read;
|
|
||||||
this_sf->sf.get_size = (void*)wasf_get_size;
|
|
||||||
this_sf->sf.get_offset = (void*)wasf_get_offset;
|
|
||||||
this_sf->sf.get_name = (void*)wasf_get_name;
|
|
||||||
this_sf->sf.open = (void*)wasf_open;
|
|
||||||
this_sf->sf.close = (void*)wasf_close;
|
|
||||||
|
|
||||||
this_sf->stdiosf = stdiosf;
|
|
||||||
this_sf->infile_ref = file;
|
|
||||||
|
|
||||||
return &this_sf->sf; /* pointer to STREAMFILE start = rest of the custom data follows */
|
|
||||||
|
|
||||||
fail:
|
|
||||||
close_streamfile(stdiosf);
|
|
||||||
free(this_sf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static STREAMFILE* open_winamp_streamfile_by_ipath(const in_char* wpath) {
|
|
||||||
FILE* infile = NULL;
|
|
||||||
STREAMFILE* sf;
|
|
||||||
char path[PATH_LIMIT];
|
|
||||||
|
|
||||||
|
|
||||||
/* convert to UTF-8 if needed for internal use */
|
|
||||||
wa_ichar_to_char(path,PATH_LIMIT, wpath);
|
|
||||||
|
|
||||||
/* open a FILE from a Winamp (possibly UTF-16) path */
|
|
||||||
infile = wa_fopen(wpath);
|
|
||||||
if (!infile) {
|
|
||||||
/* allow non-existing files in some cases */
|
|
||||||
if (!vgmstream_is_virtual_filename(path))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf = open_winamp_streamfile_by_file(infile,path);
|
|
||||||
if (!sf) {
|
|
||||||
if (infile) fclose(infile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* opens vgmstream for winamp */
|
/* opens vgmstream for winamp */
|
||||||
static VGMSTREAM* init_vgmstream_winamp(const in_char* fn, int stream_index) {
|
static VGMSTREAM* init_vgmstream_winamp(const in_char* fn, int stream_index) {
|
||||||
@ -345,411 +79,15 @@ static VGMSTREAM* init_vgmstream_winamp(const in_char* fn, int stream_index) {
|
|||||||
return vgmstream;
|
return vgmstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************************************* */
|
|
||||||
/* IN_CONFIG */
|
|
||||||
/* ************************************* */
|
|
||||||
//todo snprintf
|
|
||||||
/* Windows unicode, separate from Winamp's unicode flag */
|
|
||||||
#ifdef UNICODE
|
|
||||||
#define cfg_strncpy wcsncpy
|
|
||||||
#define cfg_strncat wcsncat
|
|
||||||
#define cfg_sprintf _swprintf
|
|
||||||
#define cfg_sscanf swscanf
|
|
||||||
#define cfg_strlen wcslen
|
|
||||||
#define cfg_strrchr wcsrchr
|
|
||||||
#else
|
|
||||||
#define cfg_strncpy strncpy
|
|
||||||
#define cfg_strncat strncat
|
|
||||||
#define cfg_sprintf sprintf
|
|
||||||
#define cfg_sscanf sscanf
|
|
||||||
#define cfg_strlen strlen
|
|
||||||
#define cfg_strrchr strrchr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* converts from utf8 to utf16 (if unicode is active) */
|
|
||||||
static void cfg_char_to_wchar(TCHAR *wdst, size_t wdstsize, const char *src) {
|
|
||||||
#ifdef UNICODE
|
|
||||||
//int size_needed = MultiByteToWideChar(CP_UTF8,0, src,-1, NULL,0);
|
|
||||||
MultiByteToWideChar(CP_UTF8,0, src,-1, wdst,wdstsize);
|
|
||||||
#else
|
|
||||||
strcpy(wdst,src);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* config */
|
|
||||||
#define CONFIG_APP_NAME TEXT("vgmstream plugin")
|
|
||||||
#define CONFIG_INI_NAME TEXT("plugin.ini")
|
|
||||||
|
|
||||||
#define INI_FADE_TIME TEXT("fade_seconds")
|
|
||||||
#define INI_FADE_DELAY TEXT("fade_delay")
|
|
||||||
#define INI_LOOP_COUNT TEXT("loop_count")
|
|
||||||
#define INI_THREAD_PRIORITY TEXT("thread_priority")
|
|
||||||
#define INI_LOOP_FOREVER TEXT("loop_forever")
|
|
||||||
#define INI_IGNORE_LOOP TEXT("ignore_loop")
|
|
||||||
#define INI_DISABLE_SUBSONGS TEXT("disable_subsongs")
|
|
||||||
#define INI_DOWNMIX_CHANNELS TEXT("downmix_channels")
|
|
||||||
#define INI_TAGFILE_DISABLE TEXT("tagfile_disable")
|
|
||||||
#define INI_FORCE_TITLE TEXT("force_title")
|
|
||||||
#define INI_EXTS_UNKNOWN_ON TEXT("exts_unknown_on")
|
|
||||||
#define INI_EXTS_COMMON_ON TEXT("exts_common_on")
|
|
||||||
#define INI_GAIN_TYPE TEXT("gain_type")
|
|
||||||
#define INI_CLIP_TYPE TEXT("clip_type")
|
|
||||||
|
|
||||||
TCHAR *dlg_priority_strings[] = {
|
|
||||||
TEXT("Idle"),
|
|
||||||
TEXT("Lowest"),
|
|
||||||
TEXT("Below Normal"),
|
|
||||||
TEXT("Normal"),
|
|
||||||
TEXT("Above Normal"),
|
|
||||||
TEXT("Highest (not recommended)"),
|
|
||||||
TEXT("Time Critical (not recommended)")
|
|
||||||
};
|
|
||||||
TCHAR *dlg_replaygain_strings[] = {
|
|
||||||
TEXT("None"),
|
|
||||||
TEXT("Album"),
|
|
||||||
TEXT("Peak")
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
// todo finish UNICODE (requires IPC_GETINIDIRECTORYW from later SDKs to read the ini path properly)
|
|
||||||
/* Winamp INI reader */
|
|
||||||
static void ini_get_filename(TCHAR *inifile) {
|
|
||||||
|
|
||||||
if (IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) {
|
|
||||||
/* newer Winamp with per-user settings */
|
|
||||||
TCHAR *ini_dir = (TCHAR *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY);
|
|
||||||
cfg_strncpy(inifile, ini_dir, PATH_LIMIT);
|
|
||||||
|
|
||||||
cfg_strncat(inifile, TEXT("\\Plugins\\"), PATH_LIMIT);
|
|
||||||
|
|
||||||
/* can't be certain that \Plugins already exists in the user dir */
|
|
||||||
CreateDirectory(inifile,NULL);
|
|
||||||
|
|
||||||
cfg_strncat(inifile, CONFIG_INI_NAME, PATH_LIMIT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* older winamp with single settings */
|
|
||||||
TCHAR *lastSlash;
|
|
||||||
|
|
||||||
GetModuleFileName(NULL, inifile, PATH_LIMIT);
|
|
||||||
lastSlash = cfg_strrchr(inifile, TEXT('\\'));
|
|
||||||
|
|
||||||
*(lastSlash + 1) = 0;
|
|
||||||
|
|
||||||
/* XMPlay doesn't have a "plugins" subfolder */
|
|
||||||
if (settings.is_xmplay)
|
|
||||||
cfg_strncat(inifile, CONFIG_INI_NAME,PATH_LIMIT);
|
|
||||||
else
|
|
||||||
cfg_strncat(inifile, TEXT("Plugins\\") CONFIG_INI_NAME,PATH_LIMIT);
|
|
||||||
/* Maybe should query IPC_GETINIDIRECTORY and use that, not sure what ancient Winamps need.
|
|
||||||
* There must be some proper way to handle dirs since other Winamp plugins save config in
|
|
||||||
* XMPlay correctly (this feels like archaeology, try later) */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void ini_get_d(const char *inifile, const char *entry, double defval, double *p_val) {
|
|
||||||
TCHAR buf[256];
|
|
||||||
TCHAR defbuf[256];
|
|
||||||
int consumed, res;
|
|
||||||
|
|
||||||
cfg_sprintf(defbuf, TEXT("%.2lf"), defval);
|
|
||||||
GetPrivateProfileString(CONFIG_APP_NAME, entry, defbuf, buf, 256, inifile);
|
|
||||||
res = cfg_sscanf(buf, TEXT("%lf%n"), p_val, &consumed);
|
|
||||||
if (res < 1 || consumed != cfg_strlen(buf) || *p_val < 0) {
|
|
||||||
*p_val = defval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ini_get_i(const char *inifile, const char *entry, int defval, int *p_val, int min, int max) {
|
|
||||||
*p_val = GetPrivateProfileInt(CONFIG_APP_NAME, entry, defval, inifile);
|
|
||||||
if (*p_val < min || *p_val > max) {
|
|
||||||
*p_val = defval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void ini_get_b(const char *inifile, const char *entry, int defval, int *p_val) {
|
|
||||||
ini_get_i(inifile, entry, defval, p_val, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ini_set_d(const char *inifile, const char *entry, double val) {
|
|
||||||
TCHAR buf[256];
|
|
||||||
cfg_sprintf(buf, TEXT("%.2lf"), val);
|
|
||||||
WritePrivateProfileString(CONFIG_APP_NAME, entry, buf, inifile);
|
|
||||||
}
|
|
||||||
static void ini_set_i(const char *inifile, const char *entry, int val) {
|
|
||||||
TCHAR buf[32];
|
|
||||||
cfg_sprintf(buf, TEXT("%d"), val);
|
|
||||||
WritePrivateProfileString(CONFIG_APP_NAME, entry, buf, inifile);
|
|
||||||
}
|
|
||||||
static void ini_set_b(const char *inifile, const char *entry, int val) {
|
|
||||||
ini_set_i(inifile, entry, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_defaults(winamp_settings_t* defaults) {
|
|
||||||
defaults->thread_priority = 3;
|
|
||||||
defaults->fade_time = 10.0;
|
|
||||||
defaults->fade_delay = 0.0;
|
|
||||||
defaults->loop_count = 2.0;
|
|
||||||
defaults->loop_forever = 0;
|
|
||||||
defaults->ignore_loop = 0;
|
|
||||||
defaults->disable_subsongs = 0;
|
|
||||||
defaults->downmix_channels = 0;
|
|
||||||
defaults->tagfile_disable = 0;
|
|
||||||
defaults->force_title = 0;
|
|
||||||
defaults->exts_unknown_on = 0;
|
|
||||||
defaults->exts_common_on = 0;
|
|
||||||
defaults->gain_type = 1;
|
|
||||||
defaults->clip_type = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_config(winamp_settings_t* settings, winamp_settings_t* defaults) {
|
|
||||||
TCHAR inifile[PATH_LIMIT];
|
|
||||||
|
|
||||||
ini_get_filename(inifile);
|
|
||||||
|
|
||||||
ini_get_i(inifile, INI_THREAD_PRIORITY, defaults->thread_priority, &settings->thread_priority, 0, 6);
|
|
||||||
|
|
||||||
ini_get_d(inifile, INI_FADE_TIME, defaults->fade_time, &settings->fade_time);
|
|
||||||
ini_get_d(inifile, INI_FADE_DELAY, defaults->fade_delay, &settings->fade_delay);
|
|
||||||
ini_get_d(inifile, INI_LOOP_COUNT, defaults->loop_count, &settings->loop_count);
|
|
||||||
|
|
||||||
ini_get_b(inifile, INI_LOOP_FOREVER, defaults->loop_forever, &settings->loop_forever);
|
|
||||||
ini_get_b(inifile, INI_IGNORE_LOOP, defaults->ignore_loop, &settings->ignore_loop);
|
|
||||||
|
|
||||||
ini_get_b(inifile, INI_DISABLE_SUBSONGS, defaults->disable_subsongs, &settings->disable_subsongs);
|
|
||||||
ini_get_i(inifile, INI_DOWNMIX_CHANNELS, defaults->downmix_channels, &settings->downmix_channels, 0, 64);
|
|
||||||
ini_get_b(inifile, INI_TAGFILE_DISABLE, defaults->tagfile_disable, &settings->tagfile_disable);
|
|
||||||
ini_get_b(inifile, INI_FORCE_TITLE, defaults->force_title, &settings->force_title);
|
|
||||||
ini_get_b(inifile, INI_EXTS_UNKNOWN_ON, defaults->exts_unknown_on, &settings->exts_unknown_on);
|
|
||||||
ini_get_b(inifile, INI_EXTS_COMMON_ON, defaults->exts_common_on, &settings->exts_common_on);
|
|
||||||
|
|
||||||
ini_get_i(inifile, INI_GAIN_TYPE, defaults->gain_type, (int*)&settings->gain_type, 0, 3);
|
|
||||||
ini_get_i(inifile, INI_CLIP_TYPE, defaults->clip_type, (int*)&settings->clip_type, 0, 3);
|
|
||||||
|
|
||||||
if (settings->loop_forever && settings->ignore_loop)
|
|
||||||
settings->ignore_loop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void save_config(winamp_settings_t* settings) {
|
|
||||||
TCHAR inifile[PATH_LIMIT];
|
|
||||||
|
|
||||||
ini_get_filename(inifile);
|
|
||||||
|
|
||||||
ini_set_i(inifile, INI_THREAD_PRIORITY, settings->thread_priority);
|
|
||||||
|
|
||||||
ini_set_d(inifile, INI_FADE_TIME, settings->fade_time);
|
|
||||||
ini_set_d(inifile, INI_FADE_DELAY, settings->fade_delay);
|
|
||||||
ini_set_d(inifile, INI_LOOP_COUNT, settings->loop_count);
|
|
||||||
|
|
||||||
ini_set_b(inifile, INI_LOOP_FOREVER, settings->loop_forever);
|
|
||||||
ini_set_b(inifile, INI_IGNORE_LOOP, settings->ignore_loop);
|
|
||||||
|
|
||||||
ini_set_b(inifile, INI_DISABLE_SUBSONGS, settings->disable_subsongs);
|
|
||||||
ini_set_i(inifile, INI_DOWNMIX_CHANNELS, settings->downmix_channels);
|
|
||||||
ini_set_b(inifile, INI_TAGFILE_DISABLE, settings->tagfile_disable);
|
|
||||||
ini_set_b(inifile, INI_FORCE_TITLE, settings->force_title);
|
|
||||||
ini_set_b(inifile, INI_EXTS_UNKNOWN_ON, settings->exts_unknown_on);
|
|
||||||
ini_set_b(inifile, INI_EXTS_COMMON_ON, settings->exts_common_on);
|
|
||||||
|
|
||||||
ini_set_i(inifile, INI_GAIN_TYPE, settings->gain_type);
|
|
||||||
ini_set_i(inifile, INI_CLIP_TYPE, settings->clip_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void dlg_input_set_d(HWND hDlg, int idc, double val) {
|
|
||||||
TCHAR buf[256];
|
|
||||||
cfg_sprintf(buf, TEXT("%.2lf"), val);
|
|
||||||
SetDlgItemText(hDlg, idc, buf);
|
|
||||||
}
|
|
||||||
static void dlg_input_set_i(HWND hDlg, int idc, int val) {
|
|
||||||
TCHAR buf[32];
|
|
||||||
cfg_sprintf(buf, TEXT("%d"), val);
|
|
||||||
SetDlgItemText(hDlg, idc, buf);
|
|
||||||
}
|
|
||||||
static void dlg_check_set(HWND hDlg, int idc, int val) {
|
|
||||||
CheckDlgButton(hDlg, idc, val ? BST_CHECKED : BST_UNCHECKED);
|
|
||||||
}
|
|
||||||
static void cfg_combo_set(HWND hDlg, int idc, int val, TCHAR **list, int list_size) {
|
|
||||||
int i;
|
|
||||||
HANDLE hCombo = GetDlgItem(hDlg, idc);
|
|
||||||
for (i = 0; i < list_size; i++) {
|
|
||||||
SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)list[i]);
|
|
||||||
}
|
|
||||||
SendMessage(hCombo, CB_SETCURSEL, val, 0);
|
|
||||||
}
|
|
||||||
static void cfg_slider_set(HWND hDlg, int idc1, int idc2, int val, int min, int max, TCHAR **list) {
|
|
||||||
HANDLE hSlider = GetDlgItem(hDlg, idc1);
|
|
||||||
SendMessage(hSlider, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(min, max));
|
|
||||||
SendMessage(hSlider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)val+1);
|
|
||||||
SetDlgItemText(hDlg, idc2, list[val]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dlg_input_get_d(HWND hDlg, int idc, double *p_val, LPCTSTR error, int *p_err) {
|
|
||||||
TCHAR buf[256];
|
|
||||||
int res, consumed;
|
|
||||||
double defval = *p_val;
|
|
||||||
|
|
||||||
GetDlgItemText(hDlg, idc, buf, 256);
|
|
||||||
res = cfg_sscanf(buf, TEXT("%lf%n"), p_val, &consumed);
|
|
||||||
if (res < 1 || consumed != cfg_strlen(buf) || *p_val < 0) {
|
|
||||||
MessageBox(hDlg, error, NULL, MB_OK|MB_ICONERROR);
|
|
||||||
*p_val = defval;
|
|
||||||
*p_err = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void dlg_input_get_i(HWND hDlg, int idc, int *p_val, LPCTSTR error, int *p_err) {
|
|
||||||
TCHAR buf[32];
|
|
||||||
int res, consumed;
|
|
||||||
int defval = *p_val;
|
|
||||||
|
|
||||||
GetDlgItemText(hDlg, idc, buf, 32);
|
|
||||||
res = cfg_sscanf(buf, TEXT("%d%n"), p_val, &consumed);
|
|
||||||
if (res < 1 || consumed != cfg_strlen(buf) || *p_val < 0) {
|
|
||||||
MessageBox(hDlg, error, NULL, MB_OK|MB_ICONERROR);
|
|
||||||
*p_val = defval;
|
|
||||||
*p_err = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void dlg_check_get(HWND hDlg, int idc, int *p_val) {
|
|
||||||
*p_val = (IsDlgButtonChecked(hDlg, idc) == BST_CHECKED);
|
|
||||||
}
|
|
||||||
static void dlg_combo_get(HWND hDlg, int idc, int *p_val) {
|
|
||||||
*p_val = SendMessage(GetDlgItem(hDlg, idc), CB_GETCURSEL, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dlg_load_form(HWND hDlg, winamp_settings_t* settings) {
|
|
||||||
int err = 0;
|
|
||||||
dlg_input_get_d(hDlg, IDC_FADE_TIME, &settings->fade_time, TEXT("Fade Length must be a positive number"), &err);
|
|
||||||
dlg_input_get_d(hDlg, IDC_FADE_DELAY, &settings->fade_delay, TEXT("Fade Delay must be a positive number"), &err);
|
|
||||||
dlg_input_get_d(hDlg, IDC_LOOP_COUNT, &settings->loop_count, TEXT("Loop Count must be a positive number"), &err);
|
|
||||||
|
|
||||||
dlg_check_get(hDlg, IDC_LOOP_FOREVER, &settings->loop_forever);
|
|
||||||
dlg_check_get(hDlg, IDC_IGNORE_LOOP, &settings->ignore_loop);
|
|
||||||
|
|
||||||
dlg_check_get(hDlg, IDC_DISABLE_SUBSONGS, &settings->disable_subsongs);
|
|
||||||
dlg_input_get_i(hDlg, IDC_DOWNMIX_CHANNELS, &settings->downmix_channels, TEXT("Downmix must be a positive integer number"), &err);
|
|
||||||
dlg_check_get(hDlg, IDC_TAGFILE_DISABLE, &settings->tagfile_disable);
|
|
||||||
dlg_check_get(hDlg, IDC_FORCE_TITLE, &settings->force_title);
|
|
||||||
dlg_check_get(hDlg, IDC_EXTS_UNKNOWN_ON, &settings->exts_unknown_on);
|
|
||||||
dlg_check_get(hDlg, IDC_EXTS_COMMON_ON, &settings->exts_common_on);
|
|
||||||
|
|
||||||
dlg_combo_get(hDlg, IDC_GAIN_TYPE, (int*)&settings->gain_type);
|
|
||||||
dlg_combo_get(hDlg, IDC_CLIP_TYPE, (int*)&settings->clip_type);
|
|
||||||
|
|
||||||
return err ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dlg_save_form(HWND hDlg, winamp_settings_t* settings, int reset) {
|
|
||||||
cfg_slider_set(hDlg, IDC_THREAD_PRIORITY_SLIDER, IDC_THREAD_PRIORITY_TEXT, settings->thread_priority, 1, 7, dlg_priority_strings);
|
|
||||||
|
|
||||||
dlg_input_set_d(hDlg, IDC_FADE_TIME, settings->fade_time);
|
|
||||||
dlg_input_set_d(hDlg, IDC_FADE_DELAY, settings->fade_delay);
|
|
||||||
dlg_input_set_d(hDlg, IDC_LOOP_COUNT, settings->loop_count);
|
|
||||||
|
|
||||||
dlg_check_set(hDlg, IDC_LOOP_FOREVER, settings->loop_forever);
|
|
||||||
dlg_check_set(hDlg, IDC_IGNORE_LOOP, settings->ignore_loop);
|
|
||||||
dlg_check_set(hDlg, IDC_LOOP_NORMALLY, (!settings->loop_forever && !settings->ignore_loop));
|
|
||||||
|
|
||||||
dlg_check_set(hDlg, IDC_DISABLE_SUBSONGS, settings->disable_subsongs);
|
|
||||||
dlg_input_set_i(hDlg, IDC_DOWNMIX_CHANNELS, settings->downmix_channels);
|
|
||||||
dlg_check_set(hDlg, IDC_TAGFILE_DISABLE, settings->tagfile_disable);
|
|
||||||
dlg_check_set(hDlg, IDC_FORCE_TITLE, settings->force_title);
|
|
||||||
dlg_check_set(hDlg, IDC_EXTS_UNKNOWN_ON, settings->exts_unknown_on);
|
|
||||||
dlg_check_set(hDlg, IDC_EXTS_COMMON_ON, settings->exts_common_on);
|
|
||||||
|
|
||||||
cfg_combo_set(hDlg, IDC_GAIN_TYPE, settings->gain_type, dlg_replaygain_strings, (reset ? 0 : 3));
|
|
||||||
cfg_combo_set(hDlg, IDC_CLIP_TYPE, settings->clip_type, dlg_replaygain_strings, (reset ? 0 : 3));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* config dialog handler */
|
|
||||||
INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
||||||
static int priority;
|
|
||||||
|
|
||||||
switch (uMsg) {
|
|
||||||
case WM_CLOSE: /* hide dialog */
|
|
||||||
EndDialog(hDlg,TRUE);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case WM_INITDIALOG: /* open dialog: load form with current settings */
|
|
||||||
priority = settings.thread_priority;
|
|
||||||
dlg_save_form(hDlg, &settings, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_COMMAND: /* button presses */
|
|
||||||
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
||||||
case IDOK: { /* read and verify new values, save and close */
|
|
||||||
int ok;
|
|
||||||
|
|
||||||
settings.thread_priority = priority;
|
|
||||||
ok = dlg_load_form(hDlg, &settings);
|
|
||||||
if (!ok) break; /* this leaves values changed though */
|
|
||||||
|
|
||||||
save_config(&settings);
|
|
||||||
|
|
||||||
EndDialog(hDlg,TRUE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case IDCANCEL: /* cancel dialog */
|
|
||||||
EndDialog(hDlg,TRUE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_DEFAULT_BUTTON: { /* reset values */
|
|
||||||
priority = defaults.thread_priority;
|
|
||||||
dlg_save_form(hDlg, &defaults, 1);
|
|
||||||
|
|
||||||
/* we don't save settings here as user can still cancel the dialog */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
case WM_HSCROLL: /* priority scroll */
|
|
||||||
if ((struct HWND__*)lParam == GetDlgItem(hDlg, IDC_THREAD_PRIORITY_SLIDER)) {
|
|
||||||
if (LOWORD(wParam) == TB_THUMBPOSITION || LOWORD(wParam) == TB_THUMBTRACK) {
|
|
||||||
priority = HIWORD(wParam)-1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
priority = SendMessage(GetDlgItem(hDlg,IDC_THREAD_PRIORITY_SLIDER),TBM_GETPOS,0,0)-1;
|
|
||||||
}
|
|
||||||
SetDlgItemText(hDlg, IDC_THREAD_PRIORITY_TEXT, dlg_priority_strings[priority]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ***************************************** */
|
|
||||||
/* IN_VGMSTREAM UTILS */
|
|
||||||
/* ***************************************** */
|
|
||||||
|
|
||||||
/* makes a modified filename, suitable to pass parameters around */
|
/* makes a modified filename, suitable to pass parameters around */
|
||||||
static void make_fn_subsong(in_char * dst, int dst_size, const in_char * filename, int stream_index) {
|
static void make_fn_subsong(in_char* dst, int dst_size, const in_char* filename, int stream_index) {
|
||||||
/* Follows "(file)(config)(ext)". Winamp needs to "see" (ext) to validate, and file goes first so relative
|
/* Follows "(file)(config)(ext)". Winamp needs to "see" (ext) to validate, and file goes first so relative
|
||||||
* files work in M3Us (path is added). Protocols a la "vgmstream://(config)(file)" work but don't get full paths. */
|
* files work in M3Us (path is added). Protocols a la "vgmstream://(config)(file)" work but don't get full paths. */
|
||||||
wa_snprintf(dst,dst_size, wa_L("%s|$s=%i|.vgmstream"), filename, stream_index);
|
wa_snprintf(dst,dst_size, wa_L("%s|$s=%i|.vgmstream"), filename, stream_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unpacks the subsongs by adding entries to the playlist */
|
/* unpacks the subsongs by adding entries to the playlist */
|
||||||
static int split_subsongs(const in_char * filename, int stream_index, VGMSTREAM *vgmstream) {
|
static int split_subsongs(const in_char* filename, int stream_index, VGMSTREAM *vgmstream) {
|
||||||
int i, playlist_index;
|
int i, playlist_index;
|
||||||
HWND hPlaylistWindow;
|
HWND hPlaylistWindow;
|
||||||
|
|
||||||
@ -796,8 +134,8 @@ static int split_subsongs(const in_char * filename, int stream_index, VGMSTREAM
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parses a modified filename ('fakename') extracting tags parameters (NULL tag for first = filename) */
|
/* parses a modified filename ('fakename') extracting tags parameters (NULL tag for first = filename) */
|
||||||
static int parse_fn_string(const in_char * fn, const in_char * tag, in_char * dst, int dst_size) {
|
static int parse_fn_string(const in_char* fn, const in_char* tag, in_char* dst, int dst_size) {
|
||||||
const in_char *end = wa_strchr(fn,'|');
|
const in_char* end = wa_strchr(fn,'|');
|
||||||
|
|
||||||
if (tag==NULL) {
|
if (tag==NULL) {
|
||||||
wa_strcpy(dst,fn);
|
wa_strcpy(dst,fn);
|
||||||
@ -809,8 +147,8 @@ static int parse_fn_string(const in_char * fn, const in_char * tag, in_char * ds
|
|||||||
dst[0] = '\0';
|
dst[0] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int parse_fn_int(const in_char * fn, const in_char * tag, int * num) {
|
static int parse_fn_int(const in_char* fn, const in_char* tag, int* num) {
|
||||||
const in_char * start = wa_strchr(fn,'|');
|
const in_char* start = wa_strchr(fn,'|');
|
||||||
|
|
||||||
if (start > 0) {
|
if (start > 0) {
|
||||||
wa_sscanf(start+1, wa_L("$s=%i "), num);
|
wa_sscanf(start+1, wa_L("$s=%i "), num);
|
||||||
@ -834,7 +172,7 @@ static int is_xmplay() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Adds ext to Winamp's extension list */
|
/* Adds ext to Winamp's extension list */
|
||||||
static void add_extension(char *dst, int dst_len, const char *ext) {
|
static void add_extension(char* dst, int dst_len, const char* ext) {
|
||||||
char buf[EXT_BUFFER_SIZE];
|
char buf[EXT_BUFFER_SIZE];
|
||||||
char ext_upp[EXT_BUFFER_SIZE];
|
char ext_upp[EXT_BUFFER_SIZE];
|
||||||
int ext_len, written;
|
int ext_len, written;
|
||||||
@ -876,17 +214,17 @@ static void add_extension(char *dst, int dst_len, const char *ext) {
|
|||||||
* Each extension must be in this format: "extension\0Description\0"
|
* Each extension must be in this format: "extension\0Description\0"
|
||||||
* The list is used to accept extensions by default when IsOurFile returns 0, and to register file types.
|
* The list is used to accept extensions by default when IsOurFile returns 0, and to register file types.
|
||||||
* It could be ignored/empty and just detect in IsOurFile instead. */
|
* It could be ignored/empty and just detect in IsOurFile instead. */
|
||||||
static void build_extension_list(char *winamp_list, int winamp_list_size) {
|
static void build_extension_list(char* winamp_list, int winamp_list_size) {
|
||||||
const char ** ext_list;
|
const char** ext_list;
|
||||||
size_t ext_list_len;
|
size_t ext_list_len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
winamp_list[0]='\0';
|
winamp_list[0] = '\0';
|
||||||
winamp_list[1]='\0';
|
winamp_list[1] = '\0';
|
||||||
|
|
||||||
ext_list = vgmstream_get_formats(&ext_list_len);
|
ext_list = vgmstream_get_formats(&ext_list_len);
|
||||||
|
|
||||||
for (i=0; i < ext_list_len; i++) {
|
for (i = 0; i < ext_list_len; i++) {
|
||||||
add_extension(winamp_list, winamp_list_size, ext_list[i]);
|
add_extension(winamp_list, winamp_list_size, ext_list[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -930,9 +268,9 @@ static void apply_config(VGMSTREAM* vgmstream, winamp_settings_t* settings) {
|
|||||||
vgmstream_apply_config(vgmstream, &vcfg);
|
vgmstream_apply_config(vgmstream, &vcfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int winampGetExtendedFileInfo_common(in_char* filename, char *metadata, char* ret, int retlen);
|
static int winampGetExtendedFileInfo_common(in_char* filename, char* metadata, char* ret, int retlen);
|
||||||
|
|
||||||
static double get_album_gain_volume(const in_char *fn) {
|
static double get_album_gain_volume(const in_char* fn) {
|
||||||
char replaygain[64];
|
char replaygain[64];
|
||||||
double gain = 0.0;
|
double gain = 0.0;
|
||||||
int had_replaygain = 0;
|
int had_replaygain = 0;
|
||||||
@ -941,7 +279,7 @@ static double get_album_gain_volume(const in_char *fn) {
|
|||||||
|
|
||||||
replaygain[0] = '\0'; /* reset each time to make sure we read actual tags */
|
replaygain[0] = '\0'; /* reset each time to make sure we read actual tags */
|
||||||
if (settings.gain_type == REPLAYGAIN_ALBUM
|
if (settings.gain_type == REPLAYGAIN_ALBUM
|
||||||
&& winampGetExtendedFileInfo_common((in_char *)fn, "replaygain_album_gain", replaygain, sizeof(replaygain))
|
&& winampGetExtendedFileInfo_common((in_char*)fn, "replaygain_album_gain", replaygain, sizeof(replaygain))
|
||||||
&& replaygain[0] != '\0') {
|
&& replaygain[0] != '\0') {
|
||||||
gain = atof(replaygain);
|
gain = atof(replaygain);
|
||||||
had_replaygain = 1;
|
had_replaygain = 1;
|
||||||
@ -949,7 +287,7 @@ static double get_album_gain_volume(const in_char *fn) {
|
|||||||
|
|
||||||
replaygain[0] = '\0';
|
replaygain[0] = '\0';
|
||||||
if (!had_replaygain
|
if (!had_replaygain
|
||||||
&& winampGetExtendedFileInfo_common((in_char *)fn, "replaygain_track_gain", replaygain, sizeof(replaygain))
|
&& winampGetExtendedFileInfo_common((in_char*)fn, "replaygain_track_gain", replaygain, sizeof(replaygain))
|
||||||
&& replaygain[0] != '\0') {
|
&& replaygain[0] != '\0') {
|
||||||
gain = atof(replaygain);
|
gain = atof(replaygain);
|
||||||
had_replaygain = 1;
|
had_replaygain = 1;
|
||||||
@ -961,12 +299,12 @@ static double get_album_gain_volume(const in_char *fn) {
|
|||||||
|
|
||||||
replaygain[0] = '\0';
|
replaygain[0] = '\0';
|
||||||
if (settings.clip_type == REPLAYGAIN_ALBUM
|
if (settings.clip_type == REPLAYGAIN_ALBUM
|
||||||
&& winampGetExtendedFileInfo_common((in_char *)fn, "replaygain_album_peak", replaygain, sizeof(replaygain))
|
&& winampGetExtendedFileInfo_common((in_char*)fn, "replaygain_album_peak", replaygain, sizeof(replaygain))
|
||||||
&& replaygain[0] != '\0') {
|
&& replaygain[0] != '\0') {
|
||||||
peak = atof(replaygain);
|
peak = atof(replaygain);
|
||||||
}
|
}
|
||||||
else if (settings.clip_type != REPLAYGAIN_NONE
|
else if (settings.clip_type != REPLAYGAIN_NONE
|
||||||
&& winampGetExtendedFileInfo_common((in_char *)fn, "replaygain_track_peak", replaygain, sizeof(replaygain))
|
&& winampGetExtendedFileInfo_common((in_char*)fn, "replaygain_track_peak", replaygain, sizeof(replaygain))
|
||||||
&& replaygain[0] != '\0') {
|
&& replaygain[0] != '\0') {
|
||||||
peak = atof(replaygain);
|
peak = atof(replaygain);
|
||||||
}
|
}
|
||||||
@ -983,7 +321,7 @@ static double get_album_gain_volume(const in_char *fn) {
|
|||||||
|
|
||||||
/* about dialog */
|
/* about dialog */
|
||||||
void winamp_About(HWND hwndParent) {
|
void winamp_About(HWND hwndParent) {
|
||||||
const char *ABOUT_TEXT =
|
const char* ABOUT_TEXT =
|
||||||
PLUGIN_DESCRIPTION "\n"
|
PLUGIN_DESCRIPTION "\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"
|
||||||
@ -1008,7 +346,7 @@ void winamp_Init() {
|
|||||||
|
|
||||||
/* get ini config */
|
/* get ini config */
|
||||||
load_defaults(&defaults);
|
load_defaults(&defaults);
|
||||||
load_config(&settings, &defaults);
|
load_config(&input_module, &settings, &defaults);
|
||||||
|
|
||||||
/* XMPlay with in_vgmstream doesn't support most IPC_x messages so no playlist manipulation */
|
/* XMPlay with in_vgmstream doesn't support most IPC_x messages so no playlist manipulation */
|
||||||
if (settings.is_xmplay) {
|
if (settings.is_xmplay) {
|
||||||
|
186
winamp/in_vgmstream.h
Normal file
186
winamp/in_vgmstream.h
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#ifndef _IN_VGMSTREAM_
|
||||||
|
#define _IN_VGMSTREAM_
|
||||||
|
|
||||||
|
|
||||||
|
/* Normally Winamp opens unicode files by their DOS 8.3 name. #define this to use wchar_t filenames,
|
||||||
|
* which must be opened with _wfopen in a WINAMP_STREAMFILE (needed for dual files like .pos).
|
||||||
|
* Only for Winamp paths, other parts would need #define UNICODE for Windows. */
|
||||||
|
#ifdef VGM_WINAMP_UNICODE
|
||||||
|
#define UNICODE_INPUT_PLUGIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _CRT_SECURE_NO_DEPRECATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "../src/vgmstream.h"
|
||||||
|
#include "../src/plugins.h"
|
||||||
|
#include "sdk/in2.h"
|
||||||
|
#include "sdk/wa_ipc.h"
|
||||||
|
#include "sdk/ipc_pe.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************* */
|
||||||
|
/* IN_CONFIG */
|
||||||
|
/* ************************************* */
|
||||||
|
|
||||||
|
extern In_Module input_module;
|
||||||
|
extern int priority_values[7];
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
REPLAYGAIN_NONE,
|
||||||
|
REPLAYGAIN_ALBUM,
|
||||||
|
REPLAYGAIN_TRACK
|
||||||
|
} replay_gain_type_t;
|
||||||
|
|
||||||
|
/* loaded settings */
|
||||||
|
typedef struct {
|
||||||
|
int thread_priority;
|
||||||
|
|
||||||
|
double fade_time;
|
||||||
|
double fade_delay;
|
||||||
|
double loop_count;
|
||||||
|
int ignore_loop;
|
||||||
|
int loop_forever;
|
||||||
|
|
||||||
|
int disable_subsongs;
|
||||||
|
int downmix_channels;
|
||||||
|
int tagfile_disable;
|
||||||
|
int force_title;
|
||||||
|
int exts_unknown_on;
|
||||||
|
int exts_common_on;
|
||||||
|
|
||||||
|
replay_gain_type_t gain_type;
|
||||||
|
replay_gain_type_t clip_type;
|
||||||
|
|
||||||
|
int is_xmplay;
|
||||||
|
} winamp_settings_t;
|
||||||
|
|
||||||
|
extern winamp_settings_t defaults;
|
||||||
|
extern winamp_settings_t settings;
|
||||||
|
|
||||||
|
/* in_config.c */
|
||||||
|
void load_defaults(winamp_settings_t* defaults);
|
||||||
|
void load_config(In_Module* input_module, winamp_settings_t* settings, winamp_settings_t* defaults);
|
||||||
|
INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************* */
|
||||||
|
/* IN_UNICODE */
|
||||||
|
/* ************************************* */
|
||||||
|
//todo safe ops
|
||||||
|
//todo there must be a better way to handle unicode...
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
#define wa_strcmp wcscmp
|
||||||
|
#define wa_strcpy wcscpy
|
||||||
|
#define wa_strncpy wcsncpy
|
||||||
|
#define wa_strcat wcscat
|
||||||
|
#define wa_strlen wcslen
|
||||||
|
#define wa_strchr wcschr
|
||||||
|
#define wa_sscanf swscanf
|
||||||
|
#define wa_snprintf _snwprintf
|
||||||
|
#define wa_strrchr wcsrchr
|
||||||
|
#define wa_fileinfo fileinfoW
|
||||||
|
#define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAMEW
|
||||||
|
#define wa_L(x) L ##x
|
||||||
|
#else
|
||||||
|
#define wa_strcmp strcmp
|
||||||
|
#define wa_strcpy strcpy
|
||||||
|
#define wa_strncpy strncpy
|
||||||
|
#define wa_strcat strcat
|
||||||
|
#define wa_strlen strlen
|
||||||
|
#define wa_strchr strchr
|
||||||
|
#define wa_sscanf sscanf
|
||||||
|
#define wa_snprintf snprintf
|
||||||
|
#define wa_strrchr strrchr
|
||||||
|
#define wa_fileinfo fileinfo
|
||||||
|
#define wa_IPC_PE_INSERTFILENAME IPC_PE_INSERTFILENAME
|
||||||
|
#define wa_L(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* converts from utf16 to utf8 (if unicode is on) */
|
||||||
|
static inline void wa_ichar_to_char(char *dst, size_t dstsize, const in_char *wsrc) {
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
/* converto to UTF8 codepage, default separate bytes, source wstr, wstr length */
|
||||||
|
//int size_needed = WideCharToMultiByte(CP_UTF8,0, src,-1, NULL,0, NULL, NULL);
|
||||||
|
WideCharToMultiByte(CP_UTF8,0, wsrc,-1, dst,dstsize, NULL, NULL);
|
||||||
|
#else
|
||||||
|
strncpy(dst, wsrc, dstsize);
|
||||||
|
dst[dstsize - 1] = '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* converts from utf8 to utf16 (if unicode is on) */
|
||||||
|
static inline void wa_char_to_ichar(in_char *wdst, size_t wdstsize, const char *src) {
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
//int size_needed = MultiByteToWideChar(CP_UTF8,0, src,-1, NULL,0);
|
||||||
|
MultiByteToWideChar(CP_UTF8,0, src,-1, wdst,wdstsize);
|
||||||
|
#else
|
||||||
|
strncpy(wdst, src, wdstsize);
|
||||||
|
wdst[wdstsize - 1] = '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copies from utf16 to utf16 (if unicode is active) */
|
||||||
|
static inline void wa_wchar_to_ichar(in_char *wdst, size_t wdstsize, const wchar_t *src) {
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
wcscpy(wdst,src);
|
||||||
|
#else
|
||||||
|
strcpy(wdst,src); //todo ???
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copies from utf16 to utf16 */
|
||||||
|
static inline void wa_char_to_wchar(wchar_t *wdst, size_t wdstsize, const char *src) {
|
||||||
|
#ifdef UNICODE_INPUT_PLUGIN
|
||||||
|
MultiByteToWideChar(CP_UTF8,0, src,-1, wdst,wdstsize);
|
||||||
|
#else
|
||||||
|
strcpy(wdst,src); //todo ???
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//todo snprintf
|
||||||
|
/* Windows unicode, separate from Winamp's unicode flag */
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define cfg_strncpy wcsncpy
|
||||||
|
#define cfg_strncat wcsncat
|
||||||
|
#define cfg_sprintf _swprintf
|
||||||
|
#define cfg_sscanf swscanf
|
||||||
|
#define cfg_strlen wcslen
|
||||||
|
#define cfg_strrchr wcsrchr
|
||||||
|
#else
|
||||||
|
#define cfg_strncpy strncpy
|
||||||
|
#define cfg_strncat strncat
|
||||||
|
#define cfg_sprintf sprintf
|
||||||
|
#define cfg_sscanf sscanf
|
||||||
|
#define cfg_strlen strlen
|
||||||
|
#define cfg_strrchr strrchr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* converts from utf8 to utf16 (if unicode is active) */
|
||||||
|
static inline void cfg_char_to_wchar(TCHAR *wdst, size_t wdstsize, const char *src) {
|
||||||
|
#ifdef UNICODE
|
||||||
|
//int size_needed = MultiByteToWideChar(CP_UTF8,0, src,-1, NULL,0);
|
||||||
|
MultiByteToWideChar(CP_UTF8,0, src,-1, wdst,wdstsize);
|
||||||
|
#else
|
||||||
|
strcpy(wdst,src);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ************************************* */
|
||||||
|
/* IN_STREAMFILE */
|
||||||
|
/* ************************************* */
|
||||||
|
|
||||||
|
/* in_streamfile.c */
|
||||||
|
STREAMFILE* open_winamp_streamfile_by_ipath(const in_char* wpath);
|
||||||
|
|
||||||
|
#endif /*_IN_VGMSTREAM_*/
|
@ -1,206 +1,218 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9.00"
|
Version="9.00"
|
||||||
Name="in_vgmstream"
|
Name="in_vgmstream"
|
||||||
ProjectGUID="{42D86561-8CE4-40F5-86CE-58C986B77502}"
|
ProjectGUID="{42D86561-8CE4-40F5-86CE-58C986B77502}"
|
||||||
RootNamespace="in_vgmstream"
|
RootNamespace="in_vgmstream"
|
||||||
Keyword="Win32Proj"
|
Keyword="Win32Proj"
|
||||||
TargetFrameworkVersion="131072"
|
TargetFrameworkVersion="131072"
|
||||||
>
|
>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
<Platform
|
<Platform
|
||||||
Name="Win32"
|
Name="Win32"
|
||||||
/>
|
/>
|
||||||
</Platforms>
|
</Platforms>
|
||||||
<ToolFiles>
|
<ToolFiles>
|
||||||
</ToolFiles>
|
</ToolFiles>
|
||||||
<Configurations>
|
<Configurations>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
OutputDirectory="Debug"
|
OutputDirectory="Debug"
|
||||||
IntermediateDirectory="Debug"
|
IntermediateDirectory="Debug"
|
||||||
ConfigurationType="2"
|
ConfigurationType="2"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreBuildEventTool"
|
Name="VCPreBuildEventTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="../ext_includes"
|
AdditionalIncludeDirectories="../ext_includes"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;"
|
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
Detect64BitPortabilityProblems="true"
|
Detect64BitPortabilityProblems="true"
|
||||||
DebugInformationFormat="4"
|
DebugInformationFormat="4"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManagedResourceCompilerTool"
|
Name="VCManagedResourceCompilerTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCResourceCompilerTool"
|
Name="VCResourceCompilerTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreLinkEventTool"
|
Name="VCPreLinkEventTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="../ext_libs/libvorbis.lib ../ext_libs/libmpg123-0.lib ../ext_libs/libg719_decode.lib"
|
AdditionalDependencies="../ext_libs/libvorbis.lib ../ext_libs/libmpg123-0.lib ../ext_libs/libg719_decode.lib"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
RandomizedBaseAddress="1"
|
RandomizedBaseAddress="1"
|
||||||
DataExecutionPrevention="0"
|
DataExecutionPrevention="0"
|
||||||
TargetMachine="1"
|
TargetMachine="1"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCALinkTool"
|
Name="VCALinkTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManifestTool"
|
Name="VCManifestTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXDCMakeTool"
|
Name="VCXDCMakeTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCBscMakeTool"
|
Name="VCBscMakeTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCFxCopTool"
|
Name="VCFxCopTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCAppVerifierTool"
|
Name="VCAppVerifierTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|Win32"
|
Name="Release|Win32"
|
||||||
OutputDirectory="Release"
|
OutputDirectory="Release"
|
||||||
IntermediateDirectory="Release"
|
IntermediateDirectory="Release"
|
||||||
ConfigurationType="2"
|
ConfigurationType="2"
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreBuildEventTool"
|
Name="VCPreBuildEventTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
AdditionalIncludeDirectories="../ext_includes"
|
AdditionalIncludeDirectories="../ext_includes"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_G7221"
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_G7221"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
Detect64BitPortabilityProblems="true"
|
Detect64BitPortabilityProblems="true"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="3"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManagedResourceCompilerTool"
|
Name="VCManagedResourceCompilerTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCResourceCompilerTool"
|
Name="VCResourceCompilerTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreLinkEventTool"
|
Name="VCPreLinkEventTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalDependencies="../ext_libs/libvorbis.lib ../ext_libs/libmpg123-0.lib ../ext_libs/libg719_decode.lib"
|
AdditionalDependencies="../ext_libs/libvorbis.lib ../ext_libs/libmpg123-0.lib ../ext_libs/libg719_decode.lib"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
ModuleDefinitionFile=""
|
ModuleDefinitionFile=""
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
RandomizedBaseAddress="1"
|
RandomizedBaseAddress="1"
|
||||||
DataExecutionPrevention="0"
|
DataExecutionPrevention="0"
|
||||||
TargetMachine="1"
|
TargetMachine="1"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCALinkTool"
|
Name="VCALinkTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManifestTool"
|
Name="VCManifestTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXDCMakeTool"
|
Name="VCXDCMakeTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCBscMakeTool"
|
Name="VCBscMakeTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCFxCopTool"
|
Name="VCFxCopTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCAppVerifierTool"
|
Name="VCAppVerifierTool"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
</Configurations>
|
</Configurations>
|
||||||
<References>
|
<References>
|
||||||
</References>
|
</References>
|
||||||
<Files>
|
<Files>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\resource.h"
|
RelativePath=".\in_vgmstream.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
<File
|
||||||
<Filter
|
RelativePath=".\resource.h"
|
||||||
Name="Resource Files"
|
>
|
||||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
</File>
|
||||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
</Filter>
|
||||||
>
|
<Filter
|
||||||
<File
|
Name="Resource Files"
|
||||||
RelativePath=".\resource.rc"
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||||
>
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
</File>
|
>
|
||||||
</Filter>
|
<File
|
||||||
<Filter
|
RelativePath=".\resource.rc"
|
||||||
Name="Source Files"
|
>
|
||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
</File>
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
</Filter>
|
||||||
>
|
<Filter
|
||||||
<File
|
Name="Source Files"
|
||||||
RelativePath=".\in_vgmstream.c"
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
>
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
</File>
|
>
|
||||||
</Filter>
|
<File
|
||||||
</Files>
|
RelativePath=".\in_config.c"
|
||||||
<Globals>
|
>
|
||||||
</Globals>
|
</File>
|
||||||
</VisualStudioProject>
|
<File
|
||||||
|
RelativePath=".\in_streamfile.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\in_vgmstream.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
||||||
|
@ -126,12 +126,15 @@
|
|||||||
</PreBuildEvent>
|
</PreBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="in_vgmstream.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="resource.rc" />
|
<ResourceCompile Include="resource.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="in_config.c" />
|
||||||
|
<ClCompile Include="in_streamfile.c" />
|
||||||
<ClCompile Include="in_vgmstream.c" />
|
<ClCompile Include="in_vgmstream.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,32 +1,41 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Header Files">
|
<Filter Include="Header Files">
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Resource Files">
|
<Filter Include="Resource Files">
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Source Files">
|
<Filter Include="Source Files">
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="resource.h">
|
<ClInclude Include="in_vgmstream.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
<ClInclude Include="resource.h">
|
||||||
<ItemGroup>
|
<Filter>Header Files</Filter>
|
||||||
<ResourceCompile Include="resource.rc">
|
</ClInclude>
|
||||||
<Filter>Resource Files</Filter>
|
</ItemGroup>
|
||||||
</ResourceCompile>
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<ResourceCompile Include="resource.rc">
|
||||||
<ItemGroup>
|
<Filter>Resource Files</Filter>
|
||||||
<ClCompile Include="in_vgmstream.c">
|
</ResourceCompile>
|
||||||
<Filter>Source Files</Filter>
|
</ItemGroup>
|
||||||
</ClCompile>
|
<ItemGroup>
|
||||||
</ItemGroup>
|
<ClCompile Include="in_config.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="in_streamfile.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="in_vgmstream.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user