From 85ec5e5bab82c1f076d318aecf1c04923667142c Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 2 Nov 2019 16:05:01 +0100 Subject: [PATCH] Clean some winamp code --- winamp/in_vgmstream.c | 941 ++++++++++++++++++++---------------------- winamp/resource.h | 8 +- winamp/resource.rc | 110 ++--- 3 files changed, 504 insertions(+), 555 deletions(-) diff --git a/winamp/in_vgmstream.c b/winamp/in_vgmstream.c index 360d959c..2f183bb2 100644 --- a/winamp/in_vgmstream.c +++ b/winamp/in_vgmstream.c @@ -41,41 +41,44 @@ /* ************************************* */ +#define EXT_BUFFER_SIZE 200 + /* plugin module (declared at the bottom of this file) */ In_Module input_module; DWORD WINAPI __stdcall decode(void *arg); /* Winamp Play extension list, to accept and associate extensions in Windows */ #define EXTENSION_LIST_SIZE (0x2000 * 6) -#define EXT_BUFFER_SIZE 200 /* fixed list to simplify but could also malloc/free on init/close */ char working_extension_list[EXTENSION_LIST_SIZE] = {0}; -typedef enum -{ +typedef enum { REPLAYGAIN_NONE, REPLAYGAIN_ALBUM, REPLAYGAIN_TRACK -} ReplayGainType; +} replay_gain_type_t; -/* defaults */ +/* loaded settings */ typedef struct { - double fade_seconds; - double fade_delay_seconds; + int thread_priority; + + double fade_time; + double fade_delay; double loop_count; int ignore_loop; int loop_forever; - int thread_priority; + int disable_subsongs; int downmix_channels; int tagfile_disable; int exts_unknown_on; int exts_common_on; - ReplayGainType gain_type; - ReplayGainType clip_type; -} winamp_settings; -/* current song settings */ + replay_gain_type_t gain_type; + replay_gain_type_t clip_type; +} winamp_settings_t; + +/* current song config */ typedef struct { int song_play_forever; double song_loop_count; @@ -86,33 +89,36 @@ typedef struct { int song_ignore_fade; } winamp_song_config; -winamp_settings settings; -winamp_song_config config; +/* current play state */ +typedef struct { + int paused; + int decode_abort; + int seek_needed_samples; + int decode_pos_ms; + int decode_pos_samples; + int stream_length_samples; + int fade_samples; + int output_channels; + double volume; +} winamp_state_t; /* Winamp needs at least 576 16-bit samples, stereo, doubled in case DSP effects are active */ #define SAMPLE_BUFFER_SIZE 576 -short sample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS]; //todo maybe should be dynamic - -/* plugin state */ -VGMSTREAM * vgmstream = NULL; -HANDLE decode_thread_handle = INVALID_HANDLE_VALUE; - -int paused = 0; -int decode_abort = 0; -int seek_needed_samples = -1; -int decode_pos_ms = 0; -int decode_pos_samples = 0; -int stream_length_samples = 0; -int fade_samples = 0; -int output_channels = 0; - -double volume = 1.0; - const char* tagfile_name = "!tags.m3u"; +/* plugin state */ +HANDLE decode_thread_handle = INVALID_HANDLE_VALUE; + +VGMSTREAM * vgmstream = NULL; in_char lastfn[PATH_LIMIT] = {0}; /* name of the currently playing file */ +winamp_settings_t defaults; +winamp_settings_t settings; +winamp_song_config config; +winamp_state_t state; +short sample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS]; //todo maybe should be dynamic + /* ************************************* */ /* IN_UNICODE */ @@ -345,7 +351,7 @@ static VGMSTREAM* init_vgmstream_winamp(const in_char *fn, int stream_index) { /* ************************************* */ /* IN_CONFIG */ /* ************************************* */ - +//todo snprintf /* Windows unicode, separate from Winamp's unicode flag */ #ifdef UNICODE #define cfg_strncpy wcsncpy @@ -377,35 +383,21 @@ static void cfg_char_to_wchar(TCHAR *wdst, size_t wdstsize, const char *src) { #define CONFIG_APP_NAME TEXT("vgmstream plugin") #define CONFIG_INI_NAME TEXT("plugin.ini") -#define DEFAULT_FADE_SECONDS TEXT("10.00") -#define DEFAULT_FADE_DELAY_SECONDS TEXT("0.00") -#define DEFAULT_LOOP_COUNT TEXT("2.00") -#define DEFAULT_THREAD_PRIORITY 3 -#define DEFAULT_LOOP_FOREVER 0 -#define DEFAULT_IGNORE_LOOP 0 -#define DEFAULT_DISABLE_SUBSONGS 0 -#define DEFAULT_DOWNMIX_CHANNELS 0 -#define DEFAULT_TAGFILE_DISABLE 0 -#define DEFAULT_EXTS_UNKNOWN_ON 0 -#define DEFAULT_EXTS_COMMON_ON 0 -#define DEFAULT_GAIN_TYPE 1 -#define DEFAULT_CLIP_TYPE 2 +#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_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") -#define INI_ENTRY_FADE_SECONDS TEXT("fade_seconds") -#define INI_ENTRY_FADE_DELAY_SECONDS TEXT("fade_delay") -#define INI_ENTRY_LOOP_COUNT TEXT("loop_count") -#define INI_ENTRY_THREAD_PRIORITY TEXT("thread_priority") -#define INI_ENTRY_LOOP_FOREVER TEXT("loop_forever") -#define INI_ENTRY_IGNORE_LOOP TEXT("ignore_loop") -#define INI_ENTRY_DISABLE_SUBSONGS TEXT("disable_subsongs") -#define INI_ENTRY_DOWNMIX_CHANNELS TEXT("downmix_channels") -#define INI_ENTRY_TAGFILE_DISABLE TEXT("tagfile_disable") -#define INI_ENTRY_EXTS_UNKNOWN_ON TEXT("exts_unknown_on") -#define INI_ENTRY_EXTS_COMMON_ON TEXT("exts_common_on") -#define INI_ENTRY_GAIN_TYPE TEXT("gain_type") -#define INI_ENTRY_CLIP_TYPE TEXT("clip_type") - -TCHAR *priority_strings[] = { +TCHAR *dlg_priority_strings[] = { TEXT("Idle"), TEXT("Lowest"), TEXT("Below Normal"), @@ -414,6 +406,12 @@ TCHAR *priority_strings[] = { 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, @@ -423,22 +421,14 @@ int priority_values[] = { THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL }; -TCHAR *replaygain_strings[] = { - TEXT("None"), - TEXT("Album"), - TEXT("Peak") -}; // todo finish UNICODE (requires IPC_GETINIDIRECTORYW from later SDKs to read the ini path properly) - /* Winamp INI reader */ -static void GetINIFileName(TCHAR *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 */ +static void ini_get_filename(TCHAR *iniFile) { - if(IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) { - TCHAR * iniDir = (TCHAR *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY); + if (IsWindow(input_module.hMainWindow) && SendMessage(input_module.hMainWindow, WM_WA_IPC,0,IPC_GETVERSION) >= 0x5000) { + /* newer Winamp with per-user settings */ + TCHAR *iniDir = (TCHAR *)SendMessage(input_module.hMainWindow, WM_WA_IPC, 0, IPC_GETINIDIRECTORY); cfg_strncpy(iniFile, iniDir, PATH_LIMIT); cfg_strncat(iniFile, TEXT("\\Plugins\\"), PATH_LIMIT); @@ -449,7 +439,8 @@ static void GetINIFileName(TCHAR *iniFile) { cfg_strncat(iniFile, CONFIG_INI_NAME, PATH_LIMIT); } else { - TCHAR * lastSlash; + /* older winamp with single settings */ + TCHAR *lastSlash; GetModuleFileName(NULL, iniFile, PATH_LIMIT); lastSlash = cfg_strrchr(iniFile, TEXT('\\')); @@ -460,294 +451,254 @@ static void GetINIFileName(TCHAR *iniFile) { } -static void load_config() { - TCHAR iniFile[PATH_LIMIT]; +static void ini_get_d(const char *iniFile, const char *entry, double defval, double *p_val) { TCHAR buf[256]; - size_t buf_size = 256; + TCHAR defbuf[256]; int consumed, res; - GetINIFileName(iniFile); - - settings.thread_priority = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_THREAD_PRIORITY,DEFAULT_THREAD_PRIORITY,iniFile); - if (settings.thread_priority < 0 || settings.thread_priority > 6) { - cfg_sprintf(buf, TEXT("%d"),DEFAULT_THREAD_PRIORITY); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_THREAD_PRIORITY,buf,iniFile); - settings.thread_priority = DEFAULT_THREAD_PRIORITY; + 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; } - - GetPrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_FADE_SECONDS,DEFAULT_FADE_SECONDS,buf,buf_size,iniFile); - res = cfg_sscanf(buf, TEXT("%lf%n"),&settings.fade_seconds,&consumed); - if (res < 1 || consumed != cfg_strlen(buf) || settings.fade_seconds < 0) { - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_FADE_SECONDS,DEFAULT_FADE_SECONDS,iniFile); - cfg_sscanf(DEFAULT_FADE_SECONDS, TEXT("%lf"),&settings.fade_seconds); +} +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); +} - GetPrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_FADE_DELAY_SECONDS,DEFAULT_FADE_DELAY_SECONDS,buf,buf_size,iniFile); - res = cfg_sscanf(buf, TEXT("%lf%n"),&settings.fade_delay_seconds,&consumed); - if (res < 1 || consumed != cfg_strlen(buf)) { - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_FADE_DELAY_SECONDS,DEFAULT_FADE_DELAY_SECONDS,iniFile); - cfg_sscanf(DEFAULT_FADE_DELAY_SECONDS, TEXT("%lf"),&settings.fade_delay_seconds); +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->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_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_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]); +} - GetPrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_LOOP_COUNT,DEFAULT_LOOP_COUNT,buf,buf_size,iniFile); - res = cfg_sscanf(buf, TEXT("%lf%n"),&settings.loop_count,&consumed); - if (res < 1 || consumed != cfg_strlen(buf) || settings.loop_count < 0) { - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_LOOP_COUNT,DEFAULT_LOOP_COUNT,iniFile); - cfg_sscanf(DEFAULT_LOOP_COUNT, TEXT("%lf"),&settings.loop_count); +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; - settings.loop_forever = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_LOOP_FOREVER,DEFAULT_LOOP_FOREVER,iniFile); - settings.ignore_loop = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_IGNORE_LOOP,DEFAULT_IGNORE_LOOP,iniFile); - if (settings.loop_forever && settings.ignore_loop) { - cfg_sprintf(buf, TEXT("%d"),DEFAULT_LOOP_FOREVER); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_LOOP_FOREVER,buf,iniFile); - settings.loop_forever = DEFAULT_LOOP_FOREVER; - - cfg_sprintf(buf, TEXT("%d"),DEFAULT_IGNORE_LOOP); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_IGNORE_LOOP,buf,iniFile); - settings.ignore_loop = DEFAULT_IGNORE_LOOP; + 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); +} - settings.disable_subsongs = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_DISABLE_SUBSONGS,DEFAULT_DISABLE_SUBSONGS,iniFile); - //if (settings.disable_subsongs < 0) { //unneeded? - // sprintf(buf, TEXT("%d"),DEFAULT_DISABLE_SUBSONGS); - // WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_DISABLE_SUBSONGS,buf,iniFile); - // settings.disable_subsongs = DEFAULT_DISABLE_SUBSONGS; - //} +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); - settings.downmix_channels = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_DOWNMIX_CHANNELS,DEFAULT_DOWNMIX_CHANNELS,iniFile); - if (settings.downmix_channels < 0) { - cfg_sprintf(buf, TEXT("%d"),DEFAULT_DOWNMIX_CHANNELS); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_DOWNMIX_CHANNELS,buf,iniFile); - settings.downmix_channels = DEFAULT_DOWNMIX_CHANNELS; - } + dlg_check_get(hDlg, IDC_LOOP_FOREVER, &settings->loop_forever); + dlg_check_get(hDlg, IDC_IGNORE_LOOP, &settings->ignore_loop); - settings.tagfile_disable = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_TAGFILE_DISABLE,DEFAULT_TAGFILE_DISABLE,iniFile); - settings.exts_unknown_on = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_EXTS_UNKNOWN_ON,DEFAULT_EXTS_UNKNOWN_ON,iniFile); - settings.exts_common_on = GetPrivateProfileInt(CONFIG_APP_NAME,INI_ENTRY_EXTS_COMMON_ON,DEFAULT_EXTS_COMMON_ON,iniFile); + 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_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_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)); - settings.gain_type = GetPrivateProfileInt(CONFIG_APP_NAME, INI_ENTRY_GAIN_TYPE, DEFAULT_GAIN_TYPE, iniFile); - settings.clip_type = GetPrivateProfileInt(CONFIG_APP_NAME, INI_ENTRY_CLIP_TYPE, DEFAULT_CLIP_TYPE, iniFile); } /* config dialog handler */ INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - TCHAR buf[256]; - TCHAR iniFile[PATH_LIMIT]; - static int mypri; - HANDLE hSlider; - HANDLE hReplayGain; - HANDLE hClipProtect; - size_t buf_size = 256; - int i; + static int priority; switch (uMsg) { case WM_CLOSE: /* hide dialog */ EndDialog(hDlg,TRUE); return TRUE; - case WM_INITDIALOG: /* open dialog */ - GetINIFileName(iniFile); //todo unneeded? - - hSlider = GetDlgItem(hDlg,IDC_THREAD_PRIORITY_SLIDER); - SendMessage(hSlider, TBM_SETRANGE, - (WPARAM) TRUE, /* redraw flag */ - (LPARAM) MAKELONG(1, 7)); /* min. & max. positions */ - SendMessage(hSlider, TBM_SETPOS, - (WPARAM) TRUE, /* redraw flag */ - (LPARAM) settings.thread_priority+1); - mypri = settings.thread_priority; - SetDlgItemText(hDlg,IDC_THREAD_PRIORITY_TEXT,priority_strings[settings.thread_priority]); - - hReplayGain = GetDlgItem(hDlg, IDC_REPLAYGAIN); - hClipProtect = GetDlgItem(hDlg, IDC_CLIPPROTECT); - for (i = 0; i < 3; i++) { - SendMessage(hReplayGain, CB_ADDSTRING, 0, (LPARAM)replaygain_strings[i]); - SendMessage(hClipProtect, CB_ADDSTRING, 0, (LPARAM)replaygain_strings[i]); - } - SendMessage(hReplayGain, CB_SETCURSEL, settings.gain_type, 0); - SendMessage(hClipProtect, CB_SETCURSEL, settings.clip_type, 0); - - cfg_sprintf(buf, TEXT("%.2lf"),settings.fade_seconds); - SetDlgItemText(hDlg,IDC_FADE_SECONDS,buf); - - cfg_sprintf(buf, TEXT("%.2lf"),settings.fade_delay_seconds); - SetDlgItemText(hDlg,IDC_FADE_DELAY_SECONDS,buf); - - cfg_sprintf(buf, TEXT("%.2lf"),settings.loop_count); - SetDlgItemText(hDlg,IDC_LOOP_COUNT,buf); - - if (settings.loop_forever) - CheckDlgButton(hDlg,IDC_LOOP_FOREVER,BST_CHECKED); - else if (settings.ignore_loop) - CheckDlgButton(hDlg,IDC_IGNORE_LOOP,BST_CHECKED); - else - CheckDlgButton(hDlg,IDC_LOOP_NORMALLY,BST_CHECKED); - - if (settings.disable_subsongs) - CheckDlgButton(hDlg,IDC_DISABLE_SUBSONGS,BST_CHECKED); - - cfg_sprintf(buf, TEXT("%d"),settings.downmix_channels); - SetDlgItemText(hDlg,IDC_DOWNMIX_CHANNELS,buf); - - if (settings.tagfile_disable) - CheckDlgButton(hDlg,IDC_TAGFILE_DISABLE,BST_CHECKED); - if (settings.exts_unknown_on) - CheckDlgButton(hDlg,IDC_EXTS_UNKNOWN_ON,BST_CHECKED); - if (settings.exts_common_on) - CheckDlgButton(hDlg,IDC_EXTS_COMMON_ON,BST_CHECKED); - + 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 */ - { - double temp_fade_seconds; - double temp_fade_delay_seconds; - double temp_loop_count; - int temp_downmix_channels; - int consumed, res; + case IDOK: { /* read and verify new values, save and close */ + int ok; - GetDlgItemText(hDlg,IDC_FADE_SECONDS,buf,buf_size); - res = cfg_sscanf(buf, TEXT("%lf%n"),&temp_fade_seconds,&consumed); - if (res < 1 || consumed != cfg_strlen(buf) || temp_fade_seconds < 0) { - MessageBox(hDlg, - TEXT("Invalid value for Fade Length\n") - TEXT("Must be a number greater than or equal to zero"), - TEXT("Error"),MB_OK|MB_ICONERROR); - break; - } + settings.thread_priority = priority; + ok = dlg_load_form(hDlg, &settings); + if (!ok) break; /* this leaves values changed though */ - GetDlgItemText(hDlg,IDC_FADE_DELAY_SECONDS,buf,buf_size); - res = cfg_sscanf(buf, TEXT("%lf%n"),&temp_fade_delay_seconds,&consumed); - if (res < 1 || consumed != cfg_strlen(buf)) { - MessageBox(hDlg, - TEXT("Invalid value for Fade Delay\n") - TEXT("Must be a number"), - TEXT("Error"),MB_OK|MB_ICONERROR); - break; - } - - GetDlgItemText(hDlg,IDC_LOOP_COUNT,buf,buf_size); - res = cfg_sscanf(buf, TEXT("%lf%n"),&temp_loop_count,&consumed); - if (res < 1 || consumed != cfg_strlen(buf) || temp_loop_count < 0) { - MessageBox(hDlg, - TEXT("Invalid value for Loop Count\n") - TEXT("Must be a number greater than or equal to zero"), - TEXT("Error"),MB_OK|MB_ICONERROR); - break; - } - - GetDlgItemText(hDlg,IDC_DOWNMIX_CHANNELS,buf,buf_size); - res = cfg_sscanf(buf, TEXT("%d%n"),&temp_downmix_channels,&consumed); - if (res < 1 || consumed != cfg_strlen(buf) || temp_downmix_channels < 0) { - MessageBox(hDlg, - TEXT("Invalid value for Downmix Channels\n") - TEXT("Must be a number greater than or equal to zero"), - TEXT("Error"),MB_OK|MB_ICONERROR); - break; - } - - - GetINIFileName(iniFile); - - settings.thread_priority = mypri; - cfg_sprintf(buf, TEXT("%d"),settings.thread_priority); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_THREAD_PRIORITY,buf,iniFile); - - settings.fade_seconds = temp_fade_seconds; - cfg_sprintf(buf, TEXT("%.2lf"),settings.fade_seconds); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_FADE_SECONDS,buf,iniFile); - - settings.fade_delay_seconds = temp_fade_delay_seconds; - cfg_sprintf(buf, TEXT("%.2lf"),settings.fade_delay_seconds); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_FADE_DELAY_SECONDS,buf,iniFile); - - settings.loop_count = temp_loop_count; - cfg_sprintf(buf, TEXT("%.2lf"),settings.loop_count); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_LOOP_COUNT,buf,iniFile); - - settings.loop_forever = (IsDlgButtonChecked(hDlg,IDC_LOOP_FOREVER) == BST_CHECKED); - cfg_sprintf(buf, TEXT("%d"),settings.loop_forever); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_LOOP_FOREVER,buf,iniFile); - - settings.ignore_loop = (IsDlgButtonChecked(hDlg,IDC_IGNORE_LOOP) == BST_CHECKED); - cfg_sprintf(buf, TEXT("%d"),settings.ignore_loop); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_IGNORE_LOOP,buf,iniFile); - - settings.disable_subsongs = (IsDlgButtonChecked(hDlg,IDC_DISABLE_SUBSONGS) == BST_CHECKED); - cfg_sprintf(buf, TEXT("%d"),settings.disable_subsongs); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_DISABLE_SUBSONGS,buf,iniFile); - - settings.loop_count = temp_loop_count; - cfg_sprintf(buf, TEXT("%.2lf"),settings.loop_count); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_LOOP_COUNT,buf,iniFile); - - settings.downmix_channels = temp_downmix_channels; - cfg_sprintf(buf, TEXT("%d"),settings.downmix_channels); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_DOWNMIX_CHANNELS,buf,iniFile); - - settings.tagfile_disable = (IsDlgButtonChecked(hDlg,IDC_TAGFILE_DISABLE) == BST_CHECKED); - cfg_sprintf(buf, TEXT("%d"),settings.tagfile_disable); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_TAGFILE_DISABLE,buf,iniFile); - - settings.exts_unknown_on = (IsDlgButtonChecked(hDlg,IDC_EXTS_UNKNOWN_ON) == BST_CHECKED); - cfg_sprintf(buf, TEXT("%d"),settings.exts_unknown_on); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_EXTS_UNKNOWN_ON,buf,iniFile); - - settings.exts_common_on = (IsDlgButtonChecked(hDlg,IDC_EXTS_COMMON_ON) == BST_CHECKED); - cfg_sprintf(buf, TEXT("%d"),settings.exts_common_on); - WritePrivateProfileString(CONFIG_APP_NAME,INI_ENTRY_EXTS_COMMON_ON,buf,iniFile); - - hReplayGain = GetDlgItem(hDlg, IDC_REPLAYGAIN); - settings.gain_type = SendMessage(hReplayGain, CB_GETCURSEL, 0, 0); - cfg_sprintf(buf, TEXT("%d"), settings.gain_type); - WritePrivateProfileString(CONFIG_APP_NAME, INI_ENTRY_GAIN_TYPE, buf, iniFile); - - hClipProtect = GetDlgItem(hDlg, IDC_CLIPPROTECT); - settings.clip_type = SendMessage(hClipProtect, CB_GETCURSEL, 0, 0); - cfg_sprintf(buf, TEXT("%d"), settings.clip_type); - WritePrivateProfileString(CONFIG_APP_NAME, INI_ENTRY_CLIP_TYPE, buf, iniFile); - } + save_config(&settings); EndDialog(hDlg,TRUE); break; + } - case IDCANCEL: + case IDCANCEL: /* cancel dialog */ EndDialog(hDlg,TRUE); break; - case IDC_DEFAULT_BUTTON: - hSlider = GetDlgItem(hDlg,IDC_THREAD_PRIORITY_SLIDER); - SendMessage(hSlider, TBM_SETRANGE, - (WPARAM) TRUE, /* redraw flag */ - (LPARAM) MAKELONG(1, 7)); /* min. & max. positions */ - SendMessage(hSlider, TBM_SETPOS, - (WPARAM) TRUE, /* redraw flag */ - (LPARAM) DEFAULT_THREAD_PRIORITY+1); - mypri = DEFAULT_THREAD_PRIORITY; - SetDlgItemText(hDlg,IDC_THREAD_PRIORITY_TEXT,priority_strings[mypri]); + case IDC_DEFAULT_BUTTON: { /* reset values */ + priority = defaults.thread_priority; + dlg_save_form(hDlg, &defaults, 1); - hReplayGain = GetDlgItem(hDlg, IDC_REPLAYGAIN); - SendMessage(hReplayGain, CB_SETCURSEL, DEFAULT_GAIN_TYPE, 0); - hClipProtect = GetDlgItem(hDlg, IDC_CLIPPROTECT); - SendMessage(hClipProtect, CB_SETCURSEL, DEFAULT_CLIP_TYPE, 0); - - SetDlgItemText(hDlg,IDC_FADE_SECONDS,DEFAULT_FADE_SECONDS); - SetDlgItemText(hDlg,IDC_FADE_DELAY_SECONDS,DEFAULT_FADE_DELAY_SECONDS); - SetDlgItemText(hDlg,IDC_LOOP_COUNT,DEFAULT_LOOP_COUNT); - - CheckDlgButton(hDlg,IDC_LOOP_FOREVER,BST_UNCHECKED); - CheckDlgButton(hDlg,IDC_IGNORE_LOOP,BST_UNCHECKED); - CheckDlgButton(hDlg,IDC_LOOP_NORMALLY,BST_CHECKED); - - CheckDlgButton(hDlg,IDC_DISABLE_SUBSONGS,BST_UNCHECKED); - SetDlgItemText(hDlg,IDC_DOWNMIX_CHANNELS,DEFAULT_DOWNMIX_CHANNELS); - CheckDlgButton(hDlg,IDC_TAGFILE_DISABLE,BST_UNCHECKED); - CheckDlgButton(hDlg,IDC_EXTS_UNKNOWN_ON,BST_UNCHECKED); - CheckDlgButton(hDlg,IDC_EXTS_COMMON_ON,BST_UNCHECKED); + /* we don't save settings here as user can still cancel the dialog */ break; + } default: return FALSE; @@ -755,14 +706,14 @@ INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara 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) { - mypri = HIWORD(wParam)-1; + if ((struct HWND__*)lParam == GetDlgItem(hDlg, IDC_THREAD_PRIORITY_SLIDER)) { + if (LOWORD(wParam) == TB_THUMBPOSITION || LOWORD(wParam) == TB_THUMBTRACK) { + priority = HIWORD(wParam)-1; } else { - mypri = SendMessage(GetDlgItem(hDlg,IDC_THREAD_PRIORITY_SLIDER),TBM_GETPOS,0,0)-1; + priority = SendMessage(GetDlgItem(hDlg,IDC_THREAD_PRIORITY_SLIDER),TBM_GETPOS,0,0)-1; } - SetDlgItemText(hDlg,IDC_THREAD_PRIORITY_TEXT,priority_strings[mypri]); + SetDlgItemText(hDlg, IDC_THREAD_PRIORITY_TEXT, dlg_priority_strings[priority]); } break; @@ -871,22 +822,22 @@ static int is_xmplay() { } /* Adds ext to Winamp's extension list */ -static void add_extension(int length, char * dst, const char * ext) { +static void add_extension(char *dst, int dst_len, const char *ext) { char buf[EXT_BUFFER_SIZE]; char ext_upp[EXT_BUFFER_SIZE]; int ext_len, written; int i,j; - if (length <= 1) + if (dst_len <= 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++) + for (i = 0; i < dst_len - 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) { + if (i == dst_len - 2 || i + EXT_BUFFER_SIZE+2 > dst_len - 2 || ext_len * 3 + 20+2 > EXT_BUFFER_SIZE) { dst[i] = '\0'; dst[i+1] = '\0'; return; @@ -913,18 +864,18 @@ static void add_extension(int length, char * dst, const char * ext) { * 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. * It could be ignored/empty and just detect in IsOurFile instead. */ -static void build_extension_list() { +static void build_extension_list(char *winamp_list, int winamp_list_size) { const char ** ext_list; size_t ext_list_len; int i; - working_extension_list[0]='\0'; - working_extension_list[1]='\0'; + winamp_list[0]='\0'; + winamp_list[1]='\0'; ext_list = vgmstream_get_formats(&ext_list_len); for (i=0; i < ext_list_len; i++) { - add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]); + add_extension(winamp_list, winamp_list_size, ext_list[i]); } } @@ -973,8 +924,8 @@ static void get_title(in_char * dst, int dst_size, const in_char * fn, VGMSTREAM static void set_config_defaults(winamp_song_config *current) { current->song_play_forever = settings.loop_forever; current->song_loop_count = settings.loop_count; - current->song_fade_time = settings.fade_seconds; - current->song_fade_delay = settings.fade_delay_seconds; + current->song_fade_time = settings.fade_time; + current->song_fade_delay = settings.fade_delay; current->song_ignore_loop = settings.ignore_loop; current->song_really_force_loop = 0; current->song_ignore_fade = 0; @@ -1026,8 +977,7 @@ static void apply_config(VGMSTREAM * vgmstream, winamp_song_config *current) { static int winampGetExtendedFileInfo_common(in_char* filename, char *metadata, char* ret, int retlen); -static double getAlbumGainVolume(const in_char *fn) -{ +static double get_album_gain_volume(const in_char *fn) { char replaygain_gain[64], replaygain_peak[64]; double gain = 0.0; int had_replaygain = 0; @@ -1083,8 +1033,8 @@ void winamp_About(HWND hwndParent) { void winamp_Init() { /* get ini config */ - load_config(); - + load_defaults(&defaults); + load_config(&settings, &defaults); /* XMPlay with in_vgmstream doesn't support most IPC_x messages so no playlist manipulation */ if (is_xmplay()) { @@ -1092,7 +1042,7 @@ void winamp_Init() { } /* dynamically make a list of supported extensions */ - build_extension_list(); + build_extension_list(working_extension_list, EXTENSION_LIST_SIZE); } /* called at program quit */ @@ -1120,8 +1070,9 @@ int winamp_Play(const in_char *fn) { in_char filename[PATH_LIMIT]; int stream_index = 0; + /* shouldn't happen */ if (vgmstream) - return 1; // TODO: this should either pop up an error box or close the file + return 1; /* check for info encoded in the filename */ parse_fn_string(fn, NULL, filename,PATH_LIMIT); @@ -1145,14 +1096,24 @@ int winamp_Play(const in_char *fn) { /* enable after all config but before outbuf (though ATM outbuf is not dynamic so no need to read input_channels) */ vgmstream_mixing_autodownmix(vgmstream, settings.downmix_channels); - vgmstream_mixing_enable(vgmstream, SAMPLE_BUFFER_SIZE, NULL /*&input_channels*/, &output_channels); + vgmstream_mixing_enable(vgmstream, SAMPLE_BUFFER_SIZE, NULL /*&input_channels*/, &state.output_channels); + + /* reset internals */ + state.paused = 0; + state.decode_abort = 0; + state.seek_needed_samples = -1; + state.decode_pos_ms = 0; + state.decode_pos_samples = 0; + state.stream_length_samples = get_vgmstream_play_samples(config.song_loop_count,config.song_fade_time,config.song_fade_delay,vgmstream); + state.fade_samples = (int)(config.song_fade_time * vgmstream->sample_rate); + state.volume = get_album_gain_volume(fn); /* save original name */ wa_strncpy(lastfn,fn,PATH_LIMIT); /* open the output plugin */ - max_latency = input_module.outMod->Open(vgmstream->sample_rate,output_channels, 16, 0, 0); + max_latency = input_module.outMod->Open(vgmstream->sample_rate, state.output_channels, 16, 0, 0); if (max_latency < 0) { close_vgmstream(vgmstream); vgmstream = NULL; @@ -1160,21 +1121,11 @@ int winamp_Play(const in_char *fn) { } /* set info display */ - input_module.SetInfo(get_vgmstream_average_bitrate(vgmstream)/1000, vgmstream->sample_rate/1000, output_channels, 1); + input_module.SetInfo(get_vgmstream_average_bitrate(vgmstream)/1000, vgmstream->sample_rate/1000, state.output_channels, 1); /* setup visualization */ input_module.SAVSAInit(max_latency,vgmstream->sample_rate); - input_module.VSASetInfo(vgmstream->sample_rate,output_channels); - - /* reset internals */ - decode_abort = 0; - seek_needed_samples = -1; - decode_pos_ms = 0; - decode_pos_samples = 0; - paused = 0; - stream_length_samples = get_vgmstream_play_samples(config.song_loop_count,config.song_fade_time,config.song_fade_delay,vgmstream); - fade_samples = (int)(config.song_fade_time * vgmstream->sample_rate); - volume = getAlbumGainVolume(fn); + input_module.VSASetInfo(vgmstream->sample_rate, state.output_channels); /* start */ decode_thread_handle = CreateThread( @@ -1185,36 +1136,37 @@ int winamp_Play(const in_char *fn) { 0, /* run thread immediately */ NULL); /* don't keep track of the thread id */ - SetThreadPriority(decode_thread_handle,priority_values[settings.thread_priority]); //todo don't use priority values directly? + SetThreadPriority(decode_thread_handle, priority_values[settings.thread_priority]); return 0; /* success */ } /* pause stream */ void winamp_Pause() { - paused = 1; + state.paused = 1; input_module.outMod->Pause(1); } /* unpause stream */ void winamp_UnPause() { - paused = 0; + state.paused = 0; input_module.outMod->Pause(0); } /* return 1 if paused, 0 if not */ int winamp_IsPaused() { - return paused; + return state.paused; } /* stop (unload) stream */ void winamp_Stop() { if (decode_thread_handle != INVALID_HANDLE_VALUE) { - decode_abort = 1; + state.decode_abort = 1; /* arbitrary wait length */ if (WaitForSingleObject(decode_thread_handle,1000) == WAIT_TIMEOUT) { - TerminateThread(decode_thread_handle,0); // TODO: error? + MessageBox(input_module.hMainWindow, TEXT("Error stopping decode thread\n"), ("Error"),MB_OK|MB_ICONERROR); + TerminateThread(decode_thread_handle, 0); } CloseHandle(decode_thread_handle); decode_thread_handle = INVALID_HANDLE_VALUE; @@ -1230,12 +1182,12 @@ void winamp_Stop() { /* get length in ms */ int winamp_GetLength() { - return stream_length_samples * 1000LL / vgmstream->sample_rate; + return state.stream_length_samples * 1000LL / vgmstream->sample_rate; } /* current output time in ms */ int winamp_GetOutputTime() { - return decode_pos_ms + (input_module.outMod->GetOutputTime()-input_module.outMod->GetWrittenTime()); + return state.decode_pos_ms + (input_module.outMod->GetOutputTime() - input_module.outMod->GetWrittenTime()); } /* seeks to point in stream (in ms) */ @@ -1243,7 +1195,7 @@ void winamp_SetOutputTime(int time_in_ms) { if (!vgmstream) return; - seek_needed_samples = (long long)time_in_ms * vgmstream->sample_rate / 1000LL; + state.seek_needed_samples = (long long)time_in_ms * vgmstream->sample_rate / 1000LL; } /* pass these commands through */ @@ -1293,7 +1245,7 @@ int winamp_InfoBox(const in_char *fn, HWND hwnd) { close_vgmstream(infostream); infostream = NULL; - tmpVolume = getAlbumGainVolume(fn); + tmpVolume = get_album_gain_volume(fn); } @@ -1372,50 +1324,50 @@ void winamp_EQSet(int on, char data[10], int preamp) { /* the decode thread */ DWORD WINAPI __stdcall decode(void *arg) { const int max_buffer_samples = SAMPLE_BUFFER_SIZE; - const int max_samples = stream_length_samples; + const int max_samples = state.stream_length_samples; - while (!decode_abort) { + while (!state.decode_abort) { int samples_to_do; int output_bytes; - if (decode_pos_samples + max_buffer_samples > stream_length_samples + if (state.decode_pos_samples + max_buffer_samples > state.stream_length_samples && (!settings.loop_forever || !vgmstream->loop_flag)) - samples_to_do = stream_length_samples - decode_pos_samples; + samples_to_do = state.stream_length_samples - state.decode_pos_samples; else samples_to_do = max_buffer_samples; /* seek setup (max samples to skip if still seeking, mark done) */ - if (seek_needed_samples != -1) { + if (state.seek_needed_samples >= 0) { /* reset if we need to seek backwards */ - if (seek_needed_samples < decode_pos_samples) { + if (state.seek_needed_samples < state.decode_pos_samples) { reset_vgmstream(vgmstream); apply_config(vgmstream, &config); /* config is undone by reset */ - decode_pos_samples = 0; - decode_pos_ms = 0; + state.decode_pos_samples = 0; + state.decode_pos_ms = 0; } /* adjust seeking past file, can happen using the right (->) key * (should be done here and not in SetOutputTime due to threads/race conditions) */ - if (seek_needed_samples > max_samples && !settings.loop_forever) { - seek_needed_samples = max_samples; + if (state.seek_needed_samples > max_samples && !settings.loop_forever) { + state.seek_needed_samples = max_samples; } /* adjust max samples to seek */ - if (decode_pos_samples < seek_needed_samples) { - samples_to_do = seek_needed_samples - decode_pos_samples; + if (state.decode_pos_samples < state.seek_needed_samples) { + samples_to_do = state.seek_needed_samples - state.decode_pos_samples; if (samples_to_do > max_buffer_samples) samples_to_do = max_buffer_samples; } else { - seek_needed_samples = -1; + state.seek_needed_samples = -1; } /* flush Winamp buffers */ - input_module.outMod->Flush((int)decode_pos_ms); + input_module.outMod->Flush((int)state.decode_pos_ms); } - output_bytes = (samples_to_do * output_channels * sizeof(short)); + output_bytes = (samples_to_do * state.output_channels * sizeof(short)); if (input_module.dsp_isactive()) output_bytes = output_bytes * 2; /* Winamp's DSP may need double samples */ @@ -1427,36 +1379,36 @@ DWORD WINAPI __stdcall decode(void *arg) { } Sleep(10); } - else if (seek_needed_samples != -1) { /* seek */ + else if (state.seek_needed_samples != -1) { /* seek */ render_vgmstream(sample_buffer,samples_to_do,vgmstream); /* discard decoded samples and keep seeking */ - decode_pos_samples += samples_to_do; - decode_pos_ms = decode_pos_samples * 1000LL / vgmstream->sample_rate; + state.decode_pos_samples += samples_to_do; + state.decode_pos_ms = state.decode_pos_samples * 1000LL / vgmstream->sample_rate; } else if (input_module.outMod->CanWrite() >= output_bytes) { /* decode */ render_vgmstream(sample_buffer,samples_to_do,vgmstream); /* apply ReplayGain, if needed */ - if (volume != 1.0) { + if (state.volume != 1.0) { int j, k; for (j = 0; j < samples_to_do; j++) { for (k = 0; k < vgmstream->channels; k++) { sample_buffer[j*vgmstream->channels + k] = - (short)(sample_buffer[j*vgmstream->channels + k] * volume); + (short)(sample_buffer[j*vgmstream->channels + k] * state.volume); } } } /* fade near the end */ - if (vgmstream->loop_flag && fade_samples > 0 && !settings.loop_forever) { - int fade_channels = output_channels; - int samples_into_fade = decode_pos_samples - (stream_length_samples - fade_samples); + if (vgmstream->loop_flag && state.fade_samples > 0 && !settings.loop_forever) { + int fade_channels = state.output_channels; + int samples_into_fade = state.decode_pos_samples - (state.stream_length_samples - state.fade_samples); if (samples_into_fade + samples_to_do > 0) { int j, k; for (j = 0; j < samples_to_do; j++, samples_into_fade++) { if (samples_into_fade > 0) { - const double fadedness = (double)(fade_samples-samples_into_fade)/fade_samples; + const double fadedness = (double)(state.fade_samples - samples_into_fade) / state.fade_samples; for (k = 0; k < fade_channels; k++) { sample_buffer[j*fade_channels+k] = (short)(sample_buffer[j*fade_channels+k]*fadedness); @@ -1467,18 +1419,18 @@ DWORD WINAPI __stdcall decode(void *arg) { } /* output samples */ - input_module.SAAddPCMData((char*)sample_buffer,output_channels,16,decode_pos_ms); - input_module.VSAAddPCMData((char*)sample_buffer,output_channels,16,decode_pos_ms); + input_module.SAAddPCMData((char*)sample_buffer,state.output_channels,16,state.decode_pos_ms); + input_module.VSAAddPCMData((char*)sample_buffer,state.output_channels,16,state.decode_pos_ms); if (input_module.dsp_isactive()) { /* find out DSP's needs */ - int dsp_output_samples = input_module.dsp_dosamples(sample_buffer,samples_to_do,16,output_channels,vgmstream->sample_rate); - output_bytes = dsp_output_samples * output_channels * sizeof(short); + int dsp_output_samples = input_module.dsp_dosamples(sample_buffer,samples_to_do,16,state.output_channels,vgmstream->sample_rate); + output_bytes = dsp_output_samples * state.output_channels * sizeof(short); } input_module.outMod->Write((char*)sample_buffer, output_bytes); - decode_pos_samples += samples_to_do; - decode_pos_ms = decode_pos_samples*1000LL/vgmstream->sample_rate; + state.decode_pos_samples += samples_to_do; + state.decode_pos_ms = state.decode_pos_samples * 1000LL / vgmstream->sample_rate; } else { /* can't write right now */ Sleep(20); @@ -1490,7 +1442,7 @@ DWORD WINAPI __stdcall decode(void *arg) { /* configuration dialog */ void winamp_Config(HWND hwndParent) { - /* defined in resource.rc */ + /* open dialog defined in resource.rc */ DialogBox(input_module.hDllInstance, (const TCHAR *)IDD_CONFIG, hwndParent, configDlgProc); } @@ -1728,19 +1680,28 @@ __declspec(dllexport) int winampUseUnifiedFileInfoDlg(const wchar_t * fn) { return 0; } -winamp_song_config ext_config; +__declspec(dllexport) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) { + /* may uninstall without restart as we aren't subclassing */ + return IN_PLUGIN_UNINSTALL_NOW; +} -short ext_sample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS]; //todo maybe should be dynamic +/* ************************************* */ +/* EXTENDED DECODE */ +/* ************************************* */ -int ext_seek_needed_samples = -1; -int ext_decode_pos_samples = 0; -int ext_stream_length_samples = -1; -int ext_fade_samples = 0; -int ext_output_channels = 0; +//TODO: call common functions to avoid so much repeated code +/* the following functions are used for ReplayGain and transcoding, in places like the media + * library or CD burner, if implemented. In usual Winamp fashion they are messy, barely + * documented, slightly different repeats of the above. */ -static void *winampGetExtendedRead_open_common(in_char *fn, int *size, int *bps, int *nch, int *srate) -{ - VGMSTREAM *ext_vgmstream = NULL; +winamp_song_config xconfig; +winamp_state_t xstate; +short xsample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS]; + + +/* open the file and prepares to decode */ +static void *winampGetExtendedRead_open_common(in_char *fn, int *size, int *bps, int *nch, int *srate) { + VGMSTREAM *xvgmstream = NULL; in_char filename[PATH_LIMIT]; int stream_index = 0; @@ -1749,42 +1710,42 @@ static void *winampGetExtendedRead_open_common(in_char *fn, int *size, int *bps, parse_fn_int(fn, wa_L("$s"), &stream_index); /* open the stream */ - ext_vgmstream = init_vgmstream_winamp(filename, stream_index); - if (!ext_vgmstream) { + xvgmstream = init_vgmstream_winamp(filename, stream_index); + if (!xvgmstream) { return NULL; } /* config */ - set_config_defaults(&ext_config); - apply_config(ext_vgmstream, &ext_config); + set_config_defaults(&xconfig); + apply_config(xvgmstream, &xconfig); /* enable after all config but before outbuf (though ATM outbuf is not dynamic so no need to read input_channels) */ - vgmstream_mixing_autodownmix(ext_vgmstream, settings.downmix_channels); - vgmstream_mixing_enable(ext_vgmstream, SAMPLE_BUFFER_SIZE, NULL /*&input_channels*/, &ext_output_channels); + vgmstream_mixing_autodownmix(xvgmstream, settings.downmix_channels); + vgmstream_mixing_enable(xvgmstream, SAMPLE_BUFFER_SIZE, NULL /*&input_channels*/, &xstate.output_channels); /* reset internals */ - ext_seek_needed_samples = -1; - ext_decode_pos_samples = 0; - ext_stream_length_samples = get_vgmstream_play_samples(ext_config.song_loop_count, ext_config.song_fade_time, ext_config.song_fade_delay, ext_vgmstream); - ext_fade_samples = (int)(ext_config.song_fade_time * ext_vgmstream->sample_rate); + xstate.paused = 0; /* unused */ + xstate.decode_abort = 0; /* unused */ + xstate.seek_needed_samples = -1; + xstate.decode_pos_ms = 0; /* unused */ + xstate.decode_pos_samples = 0; + xstate.stream_length_samples = get_vgmstream_play_samples(xconfig.song_loop_count, xconfig.song_fade_time, xconfig.song_fade_delay, xvgmstream); + xstate.fade_samples = (int)(xconfig.song_fade_time * xvgmstream->sample_rate); + xstate.volume = 1.0; /* unused */ - if (size) { - *size = ext_stream_length_samples * ext_output_channels * 2; - } - if (bps) { + if (size) /* bytes to decode (-1 if unknown) */ + *size = xstate.stream_length_samples * xstate.output_channels * sizeof(short); + if (bps) *bps = 16; - } - if (nch) { - *nch = ext_output_channels; - } - if (srate) { - *srate = ext_vgmstream->sample_rate; - } - return ext_vgmstream; + if (nch) + *nch = xstate.output_channels; + if (srate) + *srate = xvgmstream->sample_rate; + + return xvgmstream; /* handle passed to other extended functions */ } -__declspec(dllexport) void *winampGetExtendedRead_open(const char *fn, int *size, int *bps, int *nch, int *srate) -{ +__declspec(dllexport) void *winampGetExtendedRead_open(const char *fn, int *size, int *bps, int *nch, int *srate) { in_char filename_wchar[PATH_LIMIT]; wa_char_to_ichar(filename_wchar, PATH_LIMIT, fn); @@ -1792,8 +1753,7 @@ __declspec(dllexport) void *winampGetExtendedRead_open(const char *fn, int *size return winampGetExtendedRead_open_common(filename_wchar, size, bps, nch, srate); } -__declspec(dllexport) void *winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) -{ +__declspec(dllexport) void *winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) { in_char filename_ichar[PATH_LIMIT]; wa_wchar_to_ichar(filename_ichar, PATH_LIMIT, fn); @@ -1801,77 +1761,78 @@ __declspec(dllexport) void *winampGetExtendedRead_openW(const wchar_t *fn, int * return winampGetExtendedRead_open_common(filename_ichar, size, bps, nch, srate); } -__declspec(dllexport) size_t winampGetExtendedRead_getData(void *handle, char *dest, size_t len, int *killswitch) -{ +/* decode len to dest buffer, called multiple times until file done or decoding is aborted */ +__declspec(dllexport) size_t winampGetExtendedRead_getData(void *handle, char *dest, size_t len, int *killswitch) { const int max_buffer_samples = SAMPLE_BUFFER_SIZE; - const int max_samples = ext_stream_length_samples; + const int max_samples = xstate.stream_length_samples; unsigned copied = 0; int done = 0; + VGMSTREAM *xvgmstream = handle; - VGMSTREAM *ext_vgmstream = handle; - if (!ext_vgmstream) { + if (!xvgmstream) { return 0; } - while (copied + max_buffer_samples * ext_vgmstream->channels * 2 < len && !done) { + while (copied + (max_buffer_samples * xvgmstream->channels * sizeof(short)) < len && !done) { int samples_to_do; - if (ext_decode_pos_samples + max_buffer_samples > ext_stream_length_samples - && (!settings.loop_forever || !ext_vgmstream->loop_flag)) - samples_to_do = ext_stream_length_samples - ext_decode_pos_samples; + + if (xstate.decode_pos_samples + max_buffer_samples > xstate.stream_length_samples + && (!settings.loop_forever || !xvgmstream->loop_flag)) + samples_to_do = xstate.stream_length_samples - xstate.decode_pos_samples; else samples_to_do = max_buffer_samples; /* seek setup (max samples to skip if still seeking, mark done) */ - if (ext_seek_needed_samples != -1) { + if (xstate.seek_needed_samples != -1) { /* reset if we need to seek backwards */ - if (ext_seek_needed_samples < ext_decode_pos_samples) { - reset_vgmstream(ext_vgmstream); - apply_config(ext_vgmstream, &ext_config); /* config is undone by reset */ + if (xstate.seek_needed_samples < xstate.decode_pos_samples) { + reset_vgmstream(xvgmstream); + apply_config(xvgmstream, &xconfig); /* config is undone by reset */ - ext_decode_pos_samples = 0; + xstate.decode_pos_samples = 0; } /* adjust seeking past file, can happen using the right (->) key * (should be done here and not in SetOutputTime due to threads/race conditions) */ - if (ext_seek_needed_samples > max_samples && !settings.loop_forever) { - ext_seek_needed_samples = max_samples; + if (xstate.seek_needed_samples > max_samples && !settings.loop_forever) { + xstate.seek_needed_samples = max_samples; } /* adjust max samples to seek */ - if (ext_decode_pos_samples < ext_seek_needed_samples) { - samples_to_do = ext_seek_needed_samples - ext_decode_pos_samples; + if (xstate.decode_pos_samples < xstate.seek_needed_samples) { + samples_to_do = xstate.seek_needed_samples - xstate.decode_pos_samples; if (samples_to_do > max_buffer_samples) samples_to_do = max_buffer_samples; } else { - ext_seek_needed_samples = -1; + xstate.seek_needed_samples = -1; } } if (!samples_to_do) { /* track finished */ break; } - else if (ext_seek_needed_samples != -1) { /* seek */ - render_vgmstream(ext_sample_buffer, samples_to_do, ext_vgmstream); + else if (xstate.seek_needed_samples != -1) { /* seek */ + render_vgmstream(xsample_buffer, samples_to_do, xvgmstream); /* discard decoded samples and keep seeking */ - ext_decode_pos_samples += samples_to_do; + xstate.decode_pos_samples += samples_to_do; } else { /* decode */ - render_vgmstream(ext_sample_buffer, samples_to_do, ext_vgmstream); + render_vgmstream(xsample_buffer, samples_to_do, xvgmstream); /* fade near the end */ - if (ext_vgmstream->loop_flag && ext_fade_samples > 0 && !settings.loop_forever) { - int fade_channels = ext_output_channels; - int samples_into_fade = ext_decode_pos_samples - (ext_stream_length_samples - ext_fade_samples); - if (samples_into_fade + ext_decode_pos_samples > 0) { + if (xvgmstream->loop_flag && xstate.fade_samples > 0 && !settings.loop_forever) { + int fade_channels = xstate.output_channels; + int samples_into_fade = xstate.decode_pos_samples - (xstate.stream_length_samples - xstate.fade_samples); + if (samples_into_fade + xstate.decode_pos_samples > 0) { int j, k; for (j = 0; j < samples_to_do; j++, samples_into_fade++) { if (samples_into_fade > 0) { - const double fadedness = (double)(ext_fade_samples-samples_into_fade)/ext_fade_samples; + const double fadedness = (double)(xstate.fade_samples - samples_into_fade) / xstate.fade_samples; for (k = 0; k < fade_channels; k++) { - ext_sample_buffer[j*fade_channels+k] = - (short)(ext_sample_buffer[j*fade_channels+k]*fadedness); + xsample_buffer[j*fade_channels+k] = + (short)(xsample_buffer[j*fade_channels+k]*fadedness); } } } @@ -1879,54 +1840,42 @@ __declspec(dllexport) size_t winampGetExtendedRead_getData(void *handle, char *d } /* output samples */ - memcpy(&dest[copied], ext_sample_buffer, samples_to_do * ext_output_channels * 2); - copied += samples_to_do * ext_output_channels * 2; + memcpy(&dest[copied], xsample_buffer, samples_to_do * xstate.output_channels * sizeof(short)); + copied += samples_to_do * xstate.output_channels * sizeof(short); - ext_decode_pos_samples += samples_to_do; + xstate.decode_pos_samples += samples_to_do; } + /* check decoding cancelled */ if (killswitch && *killswitch) { break; } } - return copied; + + return copied; /* return 0 to signal file done */ } -__declspec(dllexport) int winampGetExtendedRead_setTime(void *handle, int time_in_ms) -{ - VGMSTREAM *ext_vgmstream = handle; - if (ext_vgmstream) { - ext_seek_needed_samples = (long long)time_in_ms * ext_vgmstream->sample_rate / 1000LL; +/* seek in the file (possibly unused) */ +__declspec(dllexport) int winampGetExtendedRead_setTime(void *handle, int time_in_ms) { + VGMSTREAM *xvgmstream = handle; + if (xvgmstream) { + xstate.seek_needed_samples = (long long)time_in_ms * xvgmstream->sample_rate / 1000LL; return 1; } return 0; } -__declspec(dllexport) void winampGetExtendedRead_close(void *handle) -{ - VGMSTREAM *ext_vgmstream = handle; - if (ext_vgmstream) { - close_vgmstream(ext_vgmstream); +/* file done */ +__declspec(dllexport) void winampGetExtendedRead_close(void *handle) { + VGMSTREAM *xvgmstream = handle; + if (xvgmstream) { + close_vgmstream(xvgmstream); } } -__declspec(dllexport) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) { - /* may uninstall without restart as we aren't subclassing */ - return IN_PLUGIN_UNINSTALL_NOW; +/* other winamp sekrit exports: */ +#if 0 +__declspec(dllexport) void winampAddUnifiedFileInfoPane(?) { + ? } - -/* winamp sekrit exports: */ -/* -EXPORTS - winampGetInModule2 @1 - winampGetExtendedFileInfo @2 - winampGetExtendedFileInfoW @3 - winampAddUnifiedFileInfoPane @4 - winampUseUnifiedFileInfoDlg @5 - winampGetExtendedRead_close @6 - winampGetExtendedRead_getData @7 - winampGetExtendedRead_open @8 - winampGetExtendedRead_openW @9 - winampGetExtendedRead_setTime @10 - winampUninstallPlugin @11 -*/ +#endif diff --git a/winamp/resource.h b/winamp/resource.h index 38d17852..193ed6b2 100644 --- a/winamp/resource.h +++ b/winamp/resource.h @@ -1,7 +1,7 @@ #define IDD_CONFIG 101 #define IDC_LOOP_COUNT 1000 -#define IDC_FADE_SECONDS 1001 -#define IDC_FADE_DELAY_SECONDS 1002 +#define IDC_FADE_TIME 1001 +#define IDC_FADE_DELAY 1002 #define IDC_LOOP_NORMALLY 1003 #define IDC_LOOP_FOREVER 1004 #define IDC_IGNORE_LOOP 1005 @@ -11,7 +11,7 @@ #define IDC_DISABLE_SUBSONGS 1009 #define IDC_DOWNMIX_CHANNELS 1011 #define IDC_TAGFILE_DISABLE 1012 -#define IDC_REPLAYGAIN 1013 -#define IDC_CLIPPROTECT 1014 +#define IDC_GAIN_TYPE 1013 +#define IDC_CLIP_TYPE 1014 #define IDC_EXTS_UNKNOWN_ON 1015 #define IDC_EXTS_COMMON_ON 1016 diff --git a/winamp/resource.rc b/winamp/resource.rc index fd09736f..60a1a0a7 100644 --- a/winamp/resource.rc +++ b/winamp/resource.rc @@ -1,55 +1,55 @@ -#include "resource.h" -//#include "afxres.h" -#include -#define IDC_STATIC -1 - -//elements: text, id, x, y, width, height [, style [, extended-style]] -IDD_CONFIG DIALOGEX 0, 0, 187, 196 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "in_vgmstream configuration" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - // right column - DEFPUSHBUTTON "OK",IDOK,129,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 - PUSHBUTTON "Default",IDC_DEFAULT_BUTTON,129,41,50,14 - - LTEXT "Thread Priority",IDC_STATIC,110,60,46,8 - CONTROL "Slider1",IDC_THREAD_PRIORITY_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,96,76,77,10 - CTEXT "DATARIFIC",IDC_THREAD_PRIORITY_TEXT,96,92,77,18 - - LTEXT "ReplayGain",IDC_STATIC,100,108,38,8 - COMBOBOX IDC_REPLAYGAIN,95,118,80,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Clip Protect",IDC_STATIC,100,135,37,8 - COMBOBOX IDC_CLIPPROTECT,95,145,80,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - // left column - LTEXT "Loop Count",IDC_STATIC,7,10,44,12 - EDITTEXT IDC_LOOP_COUNT,52,7,39,14,ES_AUTOHSCROLL - - LTEXT "Fade Length",IDC_STATIC,7,25,41,8 - EDITTEXT IDC_FADE_SECONDS,52,23,39,14,ES_AUTOHSCROLL - LTEXT "seconds",IDC_STATIC,93,25,29,11 - - LTEXT "Fade Delay",IDC_STATIC,7,40,41,8 - EDITTEXT IDC_FADE_DELAY_SECONDS,52,38,39,14,ES_AUTOHSCROLL - LTEXT "seconds",IDC_STATIC,93,40,29,11 - - CONTROL "Loop normally",IDC_LOOP_NORMALLY,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,57,77,10 - CONTROL "Loop forever",IDC_LOOP_FOREVER,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,70,77,10 - CONTROL "Ignore looping",IDC_IGNORE_LOOP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,83,77,10 - - CONTROL "Disable subsongs",IDC_DISABLE_SUBSONGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,99,87,10 - - LTEXT "Downmix",IDC_STATIC,7,115,48,12 - EDITTEXT IDC_DOWNMIX_CHANNELS,52,112,37,14,ES_AUTOHSCROLL - - CONTROL "Disable tagfile",IDC_TAGFILE_DISABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,131,87,10 - - //CONTROL "Override title",IDC_OVERRIDE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,147,97,10 - - CONTROL "Enable unknown exts",IDC_EXTS_UNKNOWN_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,163,87,10 - - CONTROL "Enable common exts",IDC_EXTS_COMMON_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,179,87,10 - -END +#include "resource.h" +//#include "afxres.h" +#include +#define IDC_STATIC -1 + +//elements: text, id, x, y, width, height [, style [, extended-style]] +IDD_CONFIG DIALOGEX 0, 0, 187, 196 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "in_vgmstream configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + // right column + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + PUSHBUTTON "Default",IDC_DEFAULT_BUTTON,129,41,50,14 + + LTEXT "Thread Priority",IDC_STATIC,110,60,46,8 + CONTROL "Slider1",IDC_THREAD_PRIORITY_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,96,76,77,10 + CTEXT "DATARIFIC",IDC_THREAD_PRIORITY_TEXT,96,92,77,18 + + LTEXT "ReplayGain",IDC_STATIC,100,118,38,8 + COMBOBOX IDC_GAIN_TYPE,95,128,80,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Clip Protect",IDC_STATIC,100,145,37,8 + COMBOBOX IDC_CLIP_TYPE,95,155,80,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + // left column + LTEXT "Loop Count",IDC_STATIC,7,10,44,12 + EDITTEXT IDC_LOOP_COUNT,52,7,39,14,ES_AUTOHSCROLL + + LTEXT "Fade Length",IDC_STATIC,7,25,41,8 + EDITTEXT IDC_FADE_TIME,52,23,39,14,ES_AUTOHSCROLL + LTEXT "seconds",IDC_STATIC,93,25,29,11 + + LTEXT "Fade Delay",IDC_STATIC,7,40,41,8 + EDITTEXT IDC_FADE_DELAY,52,38,39,14,ES_AUTOHSCROLL + LTEXT "seconds",IDC_STATIC,93,40,29,11 + + CONTROL "Loop normally",IDC_LOOP_NORMALLY,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,57,77,10 + CONTROL "Loop forever",IDC_LOOP_FOREVER,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,70,77,10 + CONTROL "Ignore looping",IDC_IGNORE_LOOP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,83,77,10 + + CONTROL "Disable subsongs",IDC_DISABLE_SUBSONGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,99,87,10 + + LTEXT "Downmix",IDC_STATIC,7,115,48,12 + EDITTEXT IDC_DOWNMIX_CHANNELS,52,112,37,14,ES_AUTOHSCROLL + + CONTROL "Disable tagfile",IDC_TAGFILE_DISABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,131,87,10 + + //CONTROL "Override title",IDC_OVERRIDE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,147,97,10 + + CONTROL "Enable unknown exts",IDC_EXTS_UNKNOWN_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,163,87,10 + + CONTROL "Enable common exts",IDC_EXTS_COMMON_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,179,87,10 + +END