From d2f55cd24a3ef9021376ce9ecf44e05e3c89d79a Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Wed, 8 Jan 2003 07:59:48 +0000 Subject: [PATCH] new configuration dialog and replay gain code; thanks to X-Fixer --- src/plugin_winamp2/config.c | 144 +++++++++++++++++++ src/plugin_winamp2/config.h | 49 +++++++ src/plugin_winamp2/in_flac.c | 249 ++++++++++++++++++++------------- src/plugin_winamp2/in_flac.dsp | 18 ++- src/plugin_winamp2/resource.h | 26 ++++ src/plugin_winamp2/resource.rc | 124 ++++++++++++++++ 6 files changed, 506 insertions(+), 104 deletions(-) create mode 100644 src/plugin_winamp2/config.c create mode 100644 src/plugin_winamp2/config.h create mode 100644 src/plugin_winamp2/resource.h create mode 100644 src/plugin_winamp2/resource.rc diff --git a/src/plugin_winamp2/config.c b/src/plugin_winamp2/config.c new file mode 100644 index 00000000..a794a317 --- /dev/null +++ b/src/plugin_winamp2/config.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include "winamp2/in2.h" +#include "winamp2/frontend.h" +#include "config.h" +#include "resource.h" + + +static char buffer[256]; + +// +// read/write +// + +#define RI(x, def) (x = GetPrivateProfileInt("FLAC", #x, def, ini_name)) +#define WI(x) WritePrivateProfileString("FLAC", #x, itoa(x, buffer, 10), ini_name) + + +void ReadConfig() +{ + RI(flac_cfg.output.replaygain.enable, 1); + RI(flac_cfg.output.replaygain.album_mode, 0); + RI(flac_cfg.output.replaygain.hard_limit, 0); + RI(flac_cfg.output.replaygain.preamp, 0); + RI(flac_cfg.output.resolution.normal.dither_24_to_16, 0); + RI(flac_cfg.output.resolution.replaygain.dither, 0); + RI(flac_cfg.output.resolution.replaygain.noise_shaping, 1); + RI(flac_cfg.output.resolution.replaygain.bps_out, 16); +} + +void WriteConfig() +{ + WI(flac_cfg.output.replaygain.enable); + WI(flac_cfg.output.replaygain.album_mode); + WI(flac_cfg.output.replaygain.hard_limit); + WI(flac_cfg.output.replaygain.preamp); + WI(flac_cfg.output.resolution.normal.dither_24_to_16); + WI(flac_cfg.output.resolution.replaygain.dither); + WI(flac_cfg.output.resolution.replaygain.noise_shaping); + WI(flac_cfg.output.resolution.replaygain.bps_out); +} + +// +// dialog +// + +#define Check(x,y) CheckDlgButton(hwnd, x, y ? BST_CHECKED : BST_UNCHECKED) +#define GetCheck(x) (IsDlgButtonChecked(hwnd, x)==BST_CHECKED) +#define GetSel(x) SendDlgItemMessage(hwnd, x, CB_GETCURSEL, 0, 0) +#define GetPos(x) SendDlgItemMessage(hwnd, x, TBM_GETPOS, 0, 0) + +#define PREAMP_RANGE 24 + + +static void UpdatePreamp(HWND hwnd, HWND hamp) +{ + int pos = SendMessage(hamp, TBM_GETPOS, 0, 0) - PREAMP_RANGE; + sprintf(buffer, "%d dB", pos); + SetDlgItemText(hwnd, IDC_PA, buffer); +} + +static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + // init + case WM_INITDIALOG: + Check(IDC_ENABLE, flac_cfg.output.replaygain.enable); + Check(IDC_ALBUM, flac_cfg.output.replaygain.album_mode); + Check(IDC_LIMITER, flac_cfg.output.replaygain.hard_limit); + Check(IDC_DITHER, flac_cfg.output.resolution.normal.dither_24_to_16); + Check(IDC_DITHERRG, flac_cfg.output.resolution.replaygain.dither); + { + HWND hamp = GetDlgItem(hwnd, IDC_PREAMP); + SendMessage(hamp, TBM_SETRANGE, 1, MAKELONG(0, PREAMP_RANGE*2)); + SendMessage(hamp, TBM_SETPOS, 1, flac_cfg.output.replaygain.preamp+PREAMP_RANGE); + UpdatePreamp(hwnd, hamp); + } + { + HWND hlist = GetDlgItem(hwnd, IDC_TO); + SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"16 bps"); + SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"24 bps"); + SendMessage(hlist, CB_SETCURSEL, flac_cfg.output.resolution.replaygain.bps_out/8 - 2, 0); + + hlist = GetDlgItem(hwnd, IDC_SHAPE); + SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"None"); + SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"Low"); + SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"Medium"); + SendMessage(hlist, CB_ADDSTRING, 0, (LPARAM)"High"); + SendMessage(hlist, CB_SETCURSEL, flac_cfg.output.resolution.replaygain.noise_shaping, 0); + } + return TRUE; + // commands + case WM_COMMAND: + switch (LOWORD(wParam)) + { + // ok/cancel + case IDOK: + if (thread_handle != INVALID_HANDLE_VALUE) + SendMessage(mod_.hMainWindow, WM_COMMAND, WINAMP_BUTTON4, 0); + + flac_cfg.output.replaygain.enable = GetCheck(IDC_ENABLE); + flac_cfg.output.replaygain.album_mode = GetCheck(IDC_ALBUM); + flac_cfg.output.replaygain.hard_limit = GetCheck(IDC_LIMITER); + flac_cfg.output.replaygain.preamp = GetPos(IDC_PREAMP) - PREAMP_RANGE; + flac_cfg.output.resolution.normal.dither_24_to_16 = GetCheck(IDC_DITHER); + flac_cfg.output.resolution.replaygain.dither = GetCheck(IDC_DITHERRG); + flac_cfg.output.resolution.replaygain.noise_shaping = GetSel(IDC_SHAPE); + flac_cfg.output.resolution.replaygain.bps_out = (GetSel(IDC_TO)+2)*8; + /* fall through */ + case IDCANCEL: + EndDialog(hwnd, LOWORD(wParam)); + return TRUE; + case IDC_RESET: + Check(IDC_ENABLE, 1); + Check(IDC_ALBUM, 0); + Check(IDC_LIMITER, 0); + Check(IDC_DITHER, 0); + Check(IDC_DITHERRG, 0); + + SendDlgItemMessage(hwnd, IDC_PREAMP, TBM_SETPOS, 1, PREAMP_RANGE); + UpdatePreamp(hwnd, GetDlgItem(hwnd, IDC_PREAMP)); + + SendDlgItemMessage(hwnd, IDC_TO, CB_SETCURSEL, 0, 0); + SendDlgItemMessage(hwnd, IDC_SHAPE, CB_SETCURSEL, 1, 0); + break; + } + break; + // scroller + case WM_HSCROLL: + if (GetDlgCtrlID((HWND)lParam)==IDC_PREAMP) + UpdatePreamp(hwnd, (HWND)lParam); + return 0; + } + + return 0; +} + + +int DoConfig(HWND parent) +{ + return DialogBox(mod_.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG), parent, DialogProc) == IDOK; +} diff --git a/src/plugin_winamp2/config.h b/src/plugin_winamp2/config.h new file mode 100644 index 00000000..c805efe7 --- /dev/null +++ b/src/plugin_winamp2/config.h @@ -0,0 +1,49 @@ + +// +// common stuff +// + +typedef struct { + //! + /* + struct { + gboolean tag_override; + gchar *tag_format; + gboolean convert_char_set; + gchar *file_char_set; + gchar *user_char_set; + } title; + */ + + struct { + struct { + BOOL enable; + BOOL album_mode; + INT preamp; + BOOL hard_limit; + } replaygain; + struct { + struct { + BOOL dither_24_to_16; + } normal; + struct { + BOOL dither; + INT noise_shaping; /* value must be one of NoiseShaping enum, c.f. plugin_common/replaygain_synthesis.h */ + INT bps_out; + } replaygain; + } resolution; + } output; +} flac_config_t; + +extern flac_config_t flac_cfg; +extern char ini_name[MAX_PATH]; +extern HANDLE thread_handle; +extern In_Module mod_; + +// +// prototypes +// + +void ReadConfig(); +void WriteConfig(); +int DoConfig(HWND parent); diff --git a/src/plugin_winamp2/in_flac.c b/src/plugin_winamp2/in_flac.c index c8a8493e..adf6a3d8 100644 --- a/src/plugin_winamp2/in_flac.c +++ b/src/plugin_winamp2/in_flac.c @@ -22,13 +22,13 @@ #include #include -#include "in2.h" +#include "winamp2/in2.h" #include "FLAC/all.h" #include "plugin_common/all.h" +#include "share/grabbag.h" +#include "config.h" -#define FLAC__DO_DITHER - BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) { return TRUE; @@ -41,11 +41,16 @@ typedef struct { FLAC__bool abort_flag; unsigned total_samples; unsigned bits_per_sample; + unsigned output_bits_per_sample; unsigned channels; unsigned sample_rate; unsigned length_in_msec; + DitherContext dither_context; + FLAC__bool has_replaygain; + double replay_scale; } file_info_struct; + static FLAC__bool safe_decoder_init_(const char *infilename, FLAC__FileDecoder *decoder); static void safe_decoder_finish_(FLAC__FileDecoder *decoder); static void safe_decoder_delete_(FLAC__FileDecoder *decoder); @@ -54,65 +59,34 @@ static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__Str static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); static void get_description_(const char *filename, char *description, unsigned max_size); -In_Module mod_; /* the output module (declared near the bottom of this file) */ -char lastfn_[MAX_PATH]; /* currently playing file (used for getting info on the current file) */ -int decode_pos_ms_; /* current decoding position, in milliseconds */ -int paused_; /* are we paused? */ -int seek_needed_; /* if != -1, it is the point that the decode thread should seek to, in ms. */ +In_Module mod_; /* the input module (declared near the bottom of this file) */ +char ini_name[MAX_PATH]; +flac_config_t flac_cfg; + +static char lastfn_[MAX_PATH]; /* currently playing file (used for getting info on the current file) */ +static int decode_pos_ms_; /* current decoding position, in milliseconds */ +static int paused_; /* are we paused? */ +static int seek_needed_; /* if != -1, it is the point that the decode thread should seek to, in ms. */ #define SAMPLES_PER_WRITE 576 -FLAC__int32 reservoir_[FLAC__MAX_BLOCK_SIZE * 2/*for overflow*/ * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; -char sample_buffer_[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS * (24/8) * 2]; /* (24/8) for max bytes per sample, and 2 for who knows what */ -unsigned wide_samples_in_reservoir_; +static FLAC__int32 reservoir_[FLAC__MAX_BLOCK_SIZE * 2/*for overflow*/ * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; +static char sample_buffer_[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS * (24/8) * 2]; /* (24/8) for max bytes per sample, and 2 for who knows what */ +static unsigned wide_samples_in_reservoir_; static file_info_struct file_info_; static FLAC__FileDecoder *decoder_; -int killDecodeThread = 0; /* the kill switch for the decode thread */ -HANDLE thread_handle = INVALID_HANDLE_VALUE; /* the handle to the decode thread */ +static volatile int killDecodeThread = 0; /* the kill switch for the decode thread */ +HANDLE thread_handle = INVALID_HANDLE_VALUE; /* the handle to the decode thread */ -DWORD WINAPI __stdcall DecodeThread(void *b); /* the decode thread procedure */ +static DWORD WINAPI DecodeThread(void *b); /* the decode thread procedure */ -static void do_vis(char *data, int nch, int resolution, int position, unsigned samples) -{ - static char vis_buffer[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; - char *ptr; - int size, count; - - /* - * Winamp visuals may have problems accepting sample sizes larger than - * 16 bits, so we reduce the sample size here if necessary. - */ - - switch(resolution) { - case 32: - case 24: - size = resolution / 8; - count = samples * nch; - - ptr = vis_buffer; - while(count--) { - data += size; - *ptr++ = data[-1] ^ 0x80; - } - - data = vis_buffer; - resolution = 8; - - /* fall through */ - case 16: - case 8: - default: - mod_.SAAddPCMData(data, nch, resolution, position); - mod_.VSAAddPCMData(data, nch, resolution, position); - } -} - void config(HWND hwndParent) { - MessageBox(hwndParent, "No configuration.", "Configuration", MB_OK); - /* if we had a configuration we'd want to write it here :) */ + if (DoConfig(hwndParent)) + WriteConfig(); } + void about(HWND hwndParent) { MessageBox(hwndParent, "Winamp FLAC Plugin v" VERSION ", by Josh Coalson\nSee http://flac.sourceforge.net/", "About FLAC Plugin", MB_OK); @@ -120,12 +94,22 @@ void about(HWND hwndParent) void init() { + char *p; + decoder_ = FLAC__file_decoder_new(); strcpy(lastfn_, ""); + // read config + GetModuleFileName(NULL, ini_name, sizeof(ini_name)); + p = strrchr(ini_name, '.'); + if (!p) p = ini_name + strlen(ini_name); + strcpy(p, ".ini"); + + ReadConfig(); } void quit() { + WriteConfig(); safe_decoder_delete_(decoder_); decoder_ = 0; } @@ -137,52 +121,48 @@ int play(char *fn) { int maxlatency; int thread_id; - HANDLE input_file = INVALID_HANDLE_VALUE; - unsigned output_bits_per_sample; + HANDLE input_file; - if(0 == decoder_) { + if(0 == decoder_) return 1; - } input_file = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if(input_file == INVALID_HANDLE_VALUE) { + if(input_file == INVALID_HANDLE_VALUE) return -1; - } CloseHandle(input_file); - if(!safe_decoder_init_(fn, decoder_)) { + file_info_.abort_flag = false; + file_info_.has_replaygain = false; + if(!safe_decoder_init_(fn, decoder_)) return 1; - } - -#ifdef FLAC__DO_DITHER - output_bits_per_sample = min(file_info_.bits_per_sample, 16); -#else - output_bits_per_sample = file_info_.bits_per_sample; -#endif strcpy(lastfn_, fn); - paused_ = 0; - decode_pos_ms_ = 0; - seek_needed_ = -1; wide_samples_in_reservoir_ = 0; + file_info_.output_bits_per_sample = file_info_.has_replaygain && flac_cfg.output.replaygain.enable ? + flac_cfg.output.resolution.replaygain.dither ? flac_cfg.output.resolution.replaygain.bps_out : file_info_.bits_per_sample : + flac_cfg.output.resolution.normal.dither_24_to_16 ? min(file_info_.bits_per_sample, 16) : file_info_.bits_per_sample; - maxlatency = mod_.outMod->Open(file_info_.sample_rate, file_info_.channels, output_bits_per_sample, -1, -1); - if(maxlatency < 0) { /* error opening device */ + if (file_info_.has_replaygain && flac_cfg.output.replaygain.enable && flac_cfg.output.resolution.replaygain.dither) + FLAC__plugin_common__init_dither_context(&file_info_.dither_context, file_info_.bits_per_sample, flac_cfg.output.resolution.replaygain.noise_shaping); + + maxlatency = mod_.outMod->Open(file_info_.sample_rate, file_info_.channels, file_info_.output_bits_per_sample, -1, -1); + if(maxlatency < 0) /* error opening device */ return 1; - } /* dividing by 1000 for the first parameter of setinfo makes it */ /* display 'H'... for hundred.. i.e. 14H Kbps. */ mod_.SetInfo((file_info_.sample_rate*file_info_.bits_per_sample*file_info_.channels)/1000, file_info_.sample_rate/1000, file_info_.channels, 1); - /* initialize vis stuff */ mod_.SAVSAInit(maxlatency, file_info_.sample_rate); mod_.VSASetInfo(file_info_.sample_rate, file_info_.channels); + /* set the output plug-ins default volume */ + mod_.outMod->SetVolume(-666); - mod_.outMod->SetVolume(-666); /* set the output plug-ins default volume */ - + paused_ = 0; + decode_pos_ms_ = 0; + seek_needed_ = -1; killDecodeThread = 0; - thread_handle = (HANDLE) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DecodeThread, (void *) &killDecodeThread, 0, &thread_id); + thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) DecodeThread, NULL, 0, &thread_id); return 0; } @@ -208,7 +188,7 @@ void stop() { if(thread_handle != INVALID_HANDLE_VALUE) { killDecodeThread = 1; - if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_TIMEOUT) { + if(WaitForSingleObject(thread_handle, 2000) == WAIT_TIMEOUT) { MessageBox(mod_.hMainWindow, "error asking thread to die!\n", "error killing decode thread", 0); TerminateThread(thread_handle, 0); } @@ -243,6 +223,14 @@ void setpan(int pan) { mod_.outMod->SetPan(pan); } int infoDlg(char *fn, HWND hwnd) { /* @@@TODO: implement info dialog. */ + if (!stricmp(fn, lastfn_)) { + char buffer[512]; + sprintf(buffer, "%s\nLength: %d:%02d, ReplayGain: %spresent\n%dHz, %d channel(s), %dbps (%dbps on output)", + lastfn_, file_info_.length_in_msec/60000, (file_info_.length_in_msec/1000)%60, file_info_.has_replaygain ? "" : "not ", + file_info_.sample_rate, file_info_.channels, file_info_.bits_per_sample, file_info_.output_bits_per_sample); + MessageBox(hwnd, buffer, "FLAC Info", 0); + } + return 0; } @@ -250,7 +238,7 @@ void getfileinfo(char *filename, char *title, int *length_in_msec) { FLAC__StreamMetadata streaminfo; - if(0 == filename || filename[0] == '\0') { + if (!filename || !*filename) { filename = lastfn_; if(length_in_msec) { *length_in_msec = getlength(); @@ -276,23 +264,56 @@ void getfileinfo(char *filename, char *title, int *length_in_msec) *length_in_msec = (int)(streaminfo.data.stream_info.total_samples * 10 / (streaminfo.data.stream_info.sample_rate / 100)); } -void eq_set(int on, char data[10], int preamp) +void eq_set(int on, char data[10], int preamp) {} + +static void do_vis(char *data, int nch, int resolution, int position, unsigned samples) { + static char vis_buffer[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS]; + char *ptr; + int size, count; + + /* + * Winamp visuals may have problems accepting sample sizes larger than + * 16 bits, so we reduce the sample size here if necessary. + */ + + switch(resolution) { + case 32: + case 24: + size = resolution / 8; + count = samples * nch; + data += size - 1; + + ptr = vis_buffer; + while(count--) { + *ptr++ = data[0] ^ 0x80; + data += size; + } + + data = vis_buffer; + resolution = 8; + + /* fall through */ + case 16: + case 8: + default: + mod_.SAAddPCMData(data, nch, resolution, position); + mod_.VSAAddPCMData(data, nch, resolution, position); + } } -DWORD WINAPI __stdcall DecodeThread(void *b) +static DWORD WINAPI DecodeThread(void *unused) { int done = 0; - while(! *((int *)b) ) { + (void)unused; + + while(!killDecodeThread) { const unsigned channels = file_info_.channels; const unsigned bits_per_sample = file_info_.bits_per_sample; -#ifdef FLAC__DO_DITHER - const unsigned target_bps = min(bits_per_sample, 16); -#else - const unsigned target_bps = bits_per_sample; -#endif + const unsigned target_bps = file_info_.output_bits_per_sample; const unsigned sample_rate = file_info_.sample_rate; + if(seek_needed_ != -1) { const double distance = (double)seek_needed_ / (double)getlength(); const unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples); @@ -329,14 +350,40 @@ DWORD WINAPI __stdcall DecodeThread(void *b) else { const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE); const unsigned delta = n * channels; - int bytes = (int)FLAC__plugin_common__pack_pcm_signed_little_endian(sample_buffer_, reservoir_, n, channels, bits_per_sample, target_bps); + int bytes; unsigned i; + if(flac_cfg.output.replaygain.enable && file_info_.has_replaygain) { + bytes = (int)FLAC__plugin_common__apply_gain( + sample_buffer_, + reservoir_, + n, + channels, + bits_per_sample, + target_bps, + (float)file_info_.replay_scale, + flac_cfg.output.replaygain.hard_limit, + flac_cfg.output.resolution.replaygain.dither, + (NoiseShaping)flac_cfg.output.resolution.replaygain.noise_shaping, + &file_info_.dither_context + ); + } + else { + bytes = (int)FLAC__plugin_common__pack_pcm_signed_little_endian( + sample_buffer_, + reservoir_, + n, + channels, + bits_per_sample, + target_bps + ); + } + for(i = delta; i < wide_samples_in_reservoir_ * channels; i++) reservoir_[i-delta] = reservoir_[i]; wide_samples_in_reservoir_ -= n; - do_vis((char *)sample_buffer_, channels, target_bps, decode_pos_ms_, n); + do_vis(sample_buffer_, channels, target_bps, decode_pos_ms_, n); decode_pos_ms_ += (n*1000 + sample_rate/2)/sample_rate; if(mod_.dsp_isactive()) bytes = mod_.dsp_dosamples((short *)sample_buffer_, n, target_bps, channels, sample_rate) * (channels*target_bps/8); @@ -413,8 +460,11 @@ FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder) FLAC__file_decoder_set_md5_checking(decoder, false); FLAC__file_decoder_set_filename(decoder, filename); - FLAC__file_decoder_set_write_callback(decoder, write_callback_); + FLAC__file_decoder_set_metadata_ignore_all(decoder); + FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO); + FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_); + FLAC__file_decoder_set_write_callback(decoder, write_callback_); FLAC__file_decoder_set_error_callback(decoder, error_callback_); FLAC__file_decoder_set_client_data(decoder, &file_info_); if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) { @@ -422,16 +472,13 @@ FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder) return false; } - file_info_.abort_flag = false; if(!FLAC__file_decoder_process_until_end_of_metadata(decoder)) { MessageBox(mod_.hMainWindow, FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)], "ERROR processing metadata", 0); return false; } - if(file_info_.abort_flag) { - /* metadata callback already popped up the error dialog */ - return false; - } + if(file_info_.abort_flag) + return false; /* metadata callback already popped up the error dialog */ return true; } @@ -474,6 +521,7 @@ void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMeta { file_info_struct *file_info = (file_info_struct *)client_data; (void)decoder; + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { FLAC__ASSERT(metadata->data.stream_info.total_samples < 0x100000000); /* this plugin can only handle < 4 gigasamples */ file_info->total_samples = (unsigned)(metadata->data.stream_info.total_samples&0xffffffff); @@ -481,21 +529,20 @@ void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMeta file_info->channels = metadata->data.stream_info.channels; file_info->sample_rate = metadata->data.stream_info.sample_rate; -#ifdef FLAC__DO_DITHER if(file_info->bits_per_sample != 8 && file_info->bits_per_sample != 16 && file_info->bits_per_sample != 24) { MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16/24-bit samples\n", "ERROR: plugin can only handle 8/16/24-bit samples", 0); file_info->abort_flag = true; return; } -#else - if(file_info->bits_per_sample != 8 && file_info->bits_per_sample != 16 && file_info->bits_per_sample != 24) { - MessageBox(mod_.hMainWindow, "ERROR: plugin can only handle 8/16/24-bit samples\n", "ERROR: plugin can only handle 8/16/24-bit samples", 0); - file_info->abort_flag = true; - return; - } -#endif file_info->length_in_msec = file_info->total_samples * 10 / (file_info->sample_rate / 100); } + else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + double gain, peak; + if(grabbag__replaygain_load_from_vorbiscomment(metadata, flac_cfg.output.replaygain.album_mode, &gain, &peak)) { + file_info_.has_replaygain = true; + file_info_.replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)flac_cfg.output.replaygain.preamp, /*prevent_clipping=*/!flac_cfg.output.replaygain.hard_limit); + } + } } void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) diff --git a/src/plugin_winamp2/in_flac.dsp b/src/plugin_winamp2/in_flac.dsp index c1285e39..c77c34bf 100644 --- a/src/plugin_winamp2/in_flac.dsp +++ b/src/plugin_winamp2/in_flac.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "in_flac_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I ".." /I "..\..\include" /D "NDEBUG" /D VERSION=\"1.0.5-beta1\" /D "in_flac_EXPORTS" /D "FLAC__NO_DLL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /Ox /Og /Oi /Os /Op /Ob1 /I "include" /I ".." /I "..\..\include" /D "NDEBUG" /D VERSION=\"1.0.5-beta1\" /D "in_flac_EXPORTS" /D "FLAC__NO_DLL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 ..\..\obj\release\lib\plugin_common_static.lib ..\..\obj\release\lib\grabbag_static.lib ..\..\obj\release\lib\libFLAC_static.lib kernel32.lib user32.lib /nologo /dll /machine:I386 /nodefaultlib:"libc.lib" /out:"../../obj/release/bin/in_flac.dll" /libpath:"../../obj/release/lib" +# ADD LINK32 plugin_common_static.lib grabbag_static.lib libFLAC_static.lib gain_analysis_static.lib kernel32.lib user32.lib /nologo /dll /machine:I386 /nodefaultlib:"libc.lib" /out:"../../obj/release/bin/in_flac.dll" /libpath:"../../obj/release/lib" /opt:nowin98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "in_flac - Win32 Debug" @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "in_flac_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "..\..\include" /D "_DEBUG" /D "REAL_STDIO" /D VERSION=\"1.0.5-beta1\" /D "in_flac_EXPORTS" /D "FLAC__NO_DLL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "include" /I ".." /I "..\..\include" /D "_DEBUG" /D "REAL_STDIO" /D VERSION=\"1.0.5-beta1\" /D "in_flac_EXPORTS" /D "FLAC__NO_DLL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" @@ -106,8 +106,20 @@ SOURCE="out.h" # End Group # Begin Source File +SOURCE=.\config.c +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + SOURCE=.\in_flac.c # End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File # End Group # End Target # End Project diff --git a/src/plugin_winamp2/resource.h b/src/plugin_winamp2/resource.h new file mode 100644 index 00000000..fc6a6c93 --- /dev/null +++ b/src/plugin_winamp2/resource.h @@ -0,0 +1,26 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDC_RESET 3 +#define IDD_CONFIG 101 +#define IDC_ENABLE 1000 +#define IDC_ALBUM 1001 +#define IDC_LIMITER 1002 +#define IDC_PREAMP 1003 +#define IDC_PA 1004 +#define IDC_DITHER 1005 +#define IDC_DITHERRG 1006 +#define IDC_TO 1008 +#define IDC_SHAPE 1009 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1009 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/plugin_winamp2/resource.rc b/src/plugin_winamp2/resource.rc new file mode 100644 index 00000000..48c9cdae --- /dev/null +++ b/src/plugin_winamp2/resource.rc @@ -0,0 +1,124 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Russian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +#ifdef _WIN32 +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOG DISCARDABLE 0, 0, 227, 193 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "FLAC Configuration" +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX " ReplayGain ",IDC_STATIC,4,2,220,57 + CONTROL "&Enable ReplayGain",IDC_ENABLE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,15,77,10 + CONTROL "&Album mode",IDC_ALBUM,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,27,55,10 + CONTROL "6dB &hard limiter",IDC_LIMITER,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,125,27,64,10 + LTEXT "&Preamp",IDC_STATIC,10,44,25,8 + CONTROL "Slider1",IDC_PREAMP,"msctls_trackbar32",TBS_NOTICKS | + WS_TABSTOP,38,43,154,12 + RTEXT "",IDC_PA,196,44,21,8 + GROUPBOX " Resolution ",IDC_STATIC,3,62,220,96 + GROUPBOX " Without ReplayGain ",IDC_STATIC,9,71,209,30 + CONTROL "&Dither 24bps to 16bps",IDC_DITHER,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,84,85,10 + GROUPBOX " With ReplayGain ",IDC_STATIC,9,104,209,48 + CONTROL "E&nable dithering",IDC_DITHERRG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,18,116,67,10 + LTEXT "Dither &to",IDC_STATIC,18,135,28,8 + COMBOBOX IDC_TO,52,132,39,43,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Noise &shaping",IDC_STATIC,115,135,46,8 + COMBOBOX IDC_SHAPE,166,132,46,48,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,65,176,50,14 + PUSHBUTTON "Cancel",IDCANCEL,119,176,50,14 + PUSHBUTTON "Reset",IDC_RESET,173,176,50,14 + LTEXT "Note: pressing OK will stop FLAC playback",IDC_STATIC,4, + 162,135,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 220 + TOPMARGIN, 7 + BOTTOMMARGIN, 186 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Russian resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED +