mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 00:20:47 +01:00
Use internal plugin settings in Winamp
This commit is contained in:
parent
b6e06f1bca
commit
de651f7176
@ -81,18 +81,6 @@ typedef struct {
|
|||||||
int is_xmplay;
|
int is_xmplay;
|
||||||
} winamp_settings_t;
|
} winamp_settings_t;
|
||||||
|
|
||||||
/* current song config */
|
|
||||||
typedef struct {
|
|
||||||
int song_play_forever;
|
|
||||||
double song_loop_count;
|
|
||||||
double song_fade_time;
|
|
||||||
double song_fade_delay;
|
|
||||||
int song_ignore_fade;
|
|
||||||
int song_ignore_loop;
|
|
||||||
int song_force_loop;
|
|
||||||
int song_really_force_loop;
|
|
||||||
} winamp_song_config;
|
|
||||||
|
|
||||||
/* current play state */
|
/* current play state */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int paused;
|
int paused;
|
||||||
@ -101,7 +89,6 @@ typedef struct {
|
|||||||
int decode_pos_ms;
|
int decode_pos_ms;
|
||||||
int decode_pos_samples;
|
int decode_pos_samples;
|
||||||
int stream_length_samples;
|
int stream_length_samples;
|
||||||
int fade_samples;
|
|
||||||
int output_channels;
|
int output_channels;
|
||||||
double volume;
|
double volume;
|
||||||
} winamp_state_t;
|
} winamp_state_t;
|
||||||
@ -114,12 +101,11 @@ const char* tagfile_name = "!tags.m3u";
|
|||||||
/* plugin state */
|
/* plugin state */
|
||||||
HANDLE decode_thread_handle = INVALID_HANDLE_VALUE;
|
HANDLE decode_thread_handle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
in_char lastfn[PATH_LIMIT] = {0}; /* name of the currently playing file */
|
in_char lastfn[PATH_LIMIT] = {0}; /* name of the currently playing file */
|
||||||
|
|
||||||
winamp_settings_t defaults;
|
winamp_settings_t defaults;
|
||||||
winamp_settings_t settings;
|
winamp_settings_t settings;
|
||||||
winamp_song_config config;
|
|
||||||
winamp_state_t state;
|
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
|
||||||
|
|
||||||
@ -228,23 +214,23 @@ typedef struct {
|
|||||||
static STREAMFILE *open_winamp_streamfile_by_file(FILE *infile, const char * path);
|
static STREAMFILE *open_winamp_streamfile_by_file(FILE *infile, const char * path);
|
||||||
static STREAMFILE *open_winamp_streamfile_by_ipath(const in_char *wpath);
|
static STREAMFILE *open_winamp_streamfile_by_ipath(const in_char *wpath);
|
||||||
|
|
||||||
static size_t wasf_read(WINAMP_STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length) {
|
static size_t wasf_read(WINAMP_STREAMFILE* sf, uint8_t* dest, off_t offset, size_t length) {
|
||||||
return streamfile->stdiosf->read(streamfile->stdiosf,dest,offset,length);
|
return sf->stdiosf->read(sf->stdiosf, dest, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static off_t wasf_get_size(WINAMP_STREAMFILE *streamfile) {
|
static off_t wasf_get_size(WINAMP_STREAMFILE* sf) {
|
||||||
return streamfile->stdiosf->get_size(streamfile->stdiosf);
|
return sf->stdiosf->get_size(sf->stdiosf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static off_t wasf_get_offset(WINAMP_STREAMFILE *streamfile) {
|
static off_t wasf_get_offset(WINAMP_STREAMFILE* sf) {
|
||||||
return streamfile->stdiosf->get_offset(streamfile->stdiosf);
|
return sf->stdiosf->get_offset(sf->stdiosf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wasf_get_name(WINAMP_STREAMFILE *streamfile, char *buffer, size_t length) {
|
static void wasf_get_name(WINAMP_STREAMFILE* sf, char* buffer, size_t length) {
|
||||||
streamfile->stdiosf->get_name(streamfile->stdiosf, buffer, length);
|
sf->stdiosf->get_name(sf->stdiosf, buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static STREAMFILE *wasf_open(WINAMP_STREAMFILE *streamFile, const char *const filename, size_t buffersize) {
|
static STREAMFILE *wasf_open(WINAMP_STREAMFILE* sf, const char* const filename, size_t buffersize) {
|
||||||
in_char wpath[PATH_LIMIT];
|
in_char wpath[PATH_LIMIT];
|
||||||
char name[PATH_LIMIT];
|
char name[PATH_LIMIT];
|
||||||
|
|
||||||
@ -256,13 +242,13 @@ static STREAMFILE *wasf_open(WINAMP_STREAMFILE *streamFile, const char *const fi
|
|||||||
* IO buffers when using dup(), noticeable by re-opening the same streamfile with small buffer sizes
|
* 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 */
|
* (reads garbage). This reportedly causes issues in Android too */
|
||||||
|
|
||||||
streamFile->stdiosf->get_name(streamFile->stdiosf, name, PATH_LIMIT);
|
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 same name, duplicate the file descriptor we already have open */ //unsure if all this is needed
|
||||||
if (streamFile->infile_ref && !strcmp(name,filename)) {
|
if (sf->infile_ref && !strcmp(name,filename)) {
|
||||||
int new_fd;
|
int new_fd;
|
||||||
FILE *new_file;
|
FILE *new_file;
|
||||||
|
|
||||||
if (((new_fd = dup(fileno(streamFile->infile_ref))) >= 0) && (new_file = wa_fdopen(new_fd))) {
|
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);
|
STREAMFILE *new_sf = open_winamp_streamfile_by_file(new_file, filename);
|
||||||
if (new_sf)
|
if (new_sf)
|
||||||
return new_sf;
|
return new_sf;
|
||||||
@ -276,24 +262,24 @@ static STREAMFILE *wasf_open(WINAMP_STREAMFILE *streamFile, const char *const fi
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* STREAMFILEs carry char/UTF8 names, convert to wchar for Winamp */
|
/* STREAMFILEs carry char/UTF8 names, convert to wchar for Winamp */
|
||||||
wa_char_to_ichar(wpath,PATH_LIMIT, filename);
|
wa_char_to_ichar(wpath, PATH_LIMIT, filename);
|
||||||
return open_winamp_streamfile_by_ipath(wpath);
|
return open_winamp_streamfile_by_ipath(wpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wasf_close(WINAMP_STREAMFILE *streamfile) {
|
static void wasf_close(WINAMP_STREAMFILE* sf) {
|
||||||
/* closes infile_ref + frees in the internal STDIOSTREAMFILE (fclose for wchar is not needed) */
|
/* closes infile_ref + frees in the internal STDIOSTREAMFILE (fclose for wchar is not needed) */
|
||||||
streamfile->stdiosf->close(streamfile->stdiosf);
|
sf->stdiosf->close(sf->stdiosf);
|
||||||
free(streamfile); /* and the current struct */
|
free(sf); /* and the current struct */
|
||||||
}
|
}
|
||||||
|
|
||||||
static STREAMFILE *open_winamp_streamfile_by_file(FILE *infile, const char * path) {
|
static STREAMFILE *open_winamp_streamfile_by_file(FILE* file, const char* path) {
|
||||||
WINAMP_STREAMFILE *this_sf = NULL;
|
WINAMP_STREAMFILE* this_sf = NULL;
|
||||||
STREAMFILE *stdiosf = NULL;
|
STREAMFILE* stdiosf = NULL;
|
||||||
|
|
||||||
this_sf = calloc(1,sizeof(WINAMP_STREAMFILE));
|
this_sf = calloc(1,sizeof(WINAMP_STREAMFILE));
|
||||||
if (!this_sf) goto fail;
|
if (!this_sf) goto fail;
|
||||||
|
|
||||||
stdiosf = open_stdio_streamfile_by_file(infile, path);
|
stdiosf = open_stdio_streamfile_by_file(file, path);
|
||||||
if (!stdiosf) goto fail;
|
if (!stdiosf) goto fail;
|
||||||
|
|
||||||
this_sf->sf.read = (void*)wasf_read;
|
this_sf->sf.read = (void*)wasf_read;
|
||||||
@ -304,7 +290,7 @@ static STREAMFILE *open_winamp_streamfile_by_file(FILE *infile, const char * pat
|
|||||||
this_sf->sf.close = (void*)wasf_close;
|
this_sf->sf.close = (void*)wasf_close;
|
||||||
|
|
||||||
this_sf->stdiosf = stdiosf;
|
this_sf->stdiosf = stdiosf;
|
||||||
this_sf->infile_ref = infile;
|
this_sf->infile_ref = file;
|
||||||
|
|
||||||
return &this_sf->sf; /* pointer to STREAMFILE start = rest of the custom data follows */
|
return &this_sf->sf; /* pointer to STREAMFILE start = rest of the custom data follows */
|
||||||
|
|
||||||
@ -315,9 +301,9 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static STREAMFILE *open_winamp_streamfile_by_ipath(const in_char *wpath) {
|
static STREAMFILE* open_winamp_streamfile_by_ipath(const in_char* wpath) {
|
||||||
FILE *infile = NULL;
|
FILE* infile = NULL;
|
||||||
STREAMFILE *streamFile;
|
STREAMFILE* sf;
|
||||||
char path[PATH_LIMIT];
|
char path[PATH_LIMIT];
|
||||||
|
|
||||||
|
|
||||||
@ -332,26 +318,26 @@ static STREAMFILE *open_winamp_streamfile_by_ipath(const in_char *wpath) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
streamFile = open_winamp_streamfile_by_file(infile,path);
|
sf = open_winamp_streamfile_by_file(infile,path);
|
||||||
if (!streamFile) {
|
if (!sf) {
|
||||||
if (infile) fclose(infile);
|
if (infile) fclose(infile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return streamFile;
|
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) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
|
|
||||||
//return init_vgmstream(fn);
|
//return init_vgmstream(fn);
|
||||||
|
|
||||||
/* manually init streamfile to pass the stream index */
|
/* manually init streamfile to pass the stream index */
|
||||||
STREAMFILE *streamFile = open_winamp_streamfile_by_ipath(fn); //open_stdio_streamfile(fn);
|
STREAMFILE* sf = open_winamp_streamfile_by_ipath(fn); //open_stdio_streamfile(fn);
|
||||||
if (streamFile) {
|
if (sf) {
|
||||||
streamFile->stream_index = stream_index;
|
sf->stream_index = stream_index;
|
||||||
vgmstream = init_vgmstream_from_STREAMFILE(streamFile);
|
vgmstream = init_vgmstream_from_STREAMFILE(sf);
|
||||||
close_streamfile(streamFile);
|
close_streamfile(sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
@ -506,7 +492,7 @@ static void ini_set_b(const char *inifile, const char *entry, int val) {
|
|||||||
ini_set_i(inifile, entry, val);
|
ini_set_i(inifile, entry, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_defaults(winamp_settings_t *defaults) {
|
static void load_defaults(winamp_settings_t* defaults) {
|
||||||
defaults->thread_priority = 3;
|
defaults->thread_priority = 3;
|
||||||
defaults->fade_time = 10.0;
|
defaults->fade_time = 10.0;
|
||||||
defaults->fade_delay = 0.0;
|
defaults->fade_delay = 0.0;
|
||||||
@ -523,7 +509,7 @@ static void load_defaults(winamp_settings_t *defaults) {
|
|||||||
defaults->clip_type = 2;
|
defaults->clip_type = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_config(winamp_settings_t *settings, winamp_settings_t *defaults) {
|
static void load_config(winamp_settings_t* settings, winamp_settings_t* defaults) {
|
||||||
TCHAR inifile[PATH_LIMIT];
|
TCHAR inifile[PATH_LIMIT];
|
||||||
|
|
||||||
ini_get_filename(inifile);
|
ini_get_filename(inifile);
|
||||||
@ -551,7 +537,7 @@ static void load_config(winamp_settings_t *settings, winamp_settings_t *defaults
|
|||||||
settings->ignore_loop = 0;
|
settings->ignore_loop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_config(winamp_settings_t *settings) {
|
static void save_config(winamp_settings_t* settings) {
|
||||||
TCHAR inifile[PATH_LIMIT];
|
TCHAR inifile[PATH_LIMIT];
|
||||||
|
|
||||||
ini_get_filename(inifile);
|
ini_get_filename(inifile);
|
||||||
@ -638,7 +624,7 @@ static void dlg_combo_get(HWND hDlg, int idc, int *p_val) {
|
|||||||
*p_val = SendMessage(GetDlgItem(hDlg, idc), CB_GETCURSEL, 0, 0);
|
*p_val = SendMessage(GetDlgItem(hDlg, idc), CB_GETCURSEL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dlg_load_form(HWND hDlg, winamp_settings_t *settings) {
|
static int dlg_load_form(HWND hDlg, winamp_settings_t* settings) {
|
||||||
int err = 0;
|
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_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_FADE_DELAY, &settings->fade_delay, TEXT("Fade Delay must be a positive number"), &err);
|
||||||
@ -660,7 +646,7 @@ static int dlg_load_form(HWND hDlg, winamp_settings_t *settings) {
|
|||||||
return err ? 0 : 1;
|
return err ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dlg_save_form(HWND hDlg, winamp_settings_t *settings, int reset) {
|
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);
|
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_TIME, settings->fade_time);
|
||||||
@ -904,8 +890,8 @@ static void build_extension_list(char *winamp_list, int winamp_list_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* unicode utils */
|
/* unicode utils */
|
||||||
static void get_title(in_char * dst, int dst_size, const in_char * fn, VGMSTREAM * infostream) {
|
static void get_title(in_char* dst, int dst_size, const in_char* fn, VGMSTREAM* infostream) {
|
||||||
in_char *basename;
|
in_char* basename;
|
||||||
in_char buffer[PATH_LIMIT];
|
in_char buffer[PATH_LIMIT];
|
||||||
in_char filename[PATH_LIMIT];
|
in_char filename[PATH_LIMIT];
|
||||||
//int stream_index = 0;
|
//int stream_index = 0;
|
||||||
@ -945,80 +931,17 @@ static void get_title(in_char * dst, int dst_size, const in_char * fn, VGMSTREAM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_config_defaults(winamp_song_config *current) {
|
static void apply_config(VGMSTREAM* vgmstream, winamp_settings_t* settings) {
|
||||||
current->song_play_forever = settings.loop_forever;
|
vgmstream_cfg_t vcfg = {0};
|
||||||
current->song_loop_count = settings.loop_count;
|
|
||||||
current->song_fade_time = settings.fade_time;
|
|
||||||
current->song_fade_delay = settings.fade_delay;
|
|
||||||
current->song_ignore_fade = 0;
|
|
||||||
current->song_force_loop = 0;
|
|
||||||
current->song_really_force_loop = 0;
|
|
||||||
current->song_ignore_loop = settings.ignore_loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void apply_config(VGMSTREAM* vgmstream, winamp_song_config* cfg) {
|
vcfg.allow_play_forever = 1;
|
||||||
|
vcfg.play_forever = settings->loop_forever;
|
||||||
|
vcfg.loop_times = settings->loop_count;
|
||||||
|
vcfg.fade_period = settings->fade_time;
|
||||||
|
vcfg.fade_delay = settings->fade_delay;
|
||||||
|
vcfg.ignore_loop = settings->ignore_loop;
|
||||||
|
|
||||||
/* honor suggested config (order matters, and config mixes with/overwrites player defaults) */
|
vgmstream_apply_config(vgmstream, &vcfg);
|
||||||
if (vgmstream->config.play_forever) {
|
|
||||||
cfg->song_play_forever = 1;
|
|
||||||
cfg->song_ignore_loop = 0;
|
|
||||||
}
|
|
||||||
if (vgmstream->config.loop_count_set) {
|
|
||||||
cfg->song_loop_count = vgmstream->config.loop_count;
|
|
||||||
cfg->song_play_forever = 0;
|
|
||||||
cfg->song_ignore_loop = 0;
|
|
||||||
}
|
|
||||||
if (vgmstream->config.fade_delay_set) {
|
|
||||||
cfg->song_fade_delay = vgmstream->config.fade_delay;
|
|
||||||
}
|
|
||||||
if (vgmstream->config.fade_time_set) {
|
|
||||||
cfg->song_fade_time = vgmstream->config.fade_time;
|
|
||||||
}
|
|
||||||
if (vgmstream->config.ignore_fade) {
|
|
||||||
cfg->song_ignore_fade = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vgmstream->config.force_loop) {
|
|
||||||
cfg->song_ignore_loop = 0;
|
|
||||||
cfg->song_force_loop = 1;
|
|
||||||
cfg->song_really_force_loop = 0;
|
|
||||||
}
|
|
||||||
if (vgmstream->config.really_force_loop) {
|
|
||||||
cfg->song_ignore_loop = 0;
|
|
||||||
cfg->song_force_loop = 0;
|
|
||||||
cfg->song_really_force_loop = 1;
|
|
||||||
}
|
|
||||||
if (vgmstream->config.ignore_loop) {
|
|
||||||
cfg->song_ignore_loop = 1;
|
|
||||||
cfg->song_force_loop = 0;
|
|
||||||
cfg->song_really_force_loop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* apply config */
|
|
||||||
if (cfg->song_force_loop && !vgmstream->loop_flag) {
|
|
||||||
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
|
|
||||||
}
|
|
||||||
if (cfg->song_really_force_loop) {
|
|
||||||
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
|
|
||||||
}
|
|
||||||
if (cfg->song_ignore_loop) {
|
|
||||||
vgmstream_force_loop(vgmstream, 0, 0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove non-compatible options */
|
|
||||||
if (!vgmstream->loop_flag) {
|
|
||||||
cfg->song_play_forever = 0;
|
|
||||||
}
|
|
||||||
if (cfg->song_play_forever) {
|
|
||||||
cfg->song_ignore_fade = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* loop N times, but also play stream end instead of fading out */
|
|
||||||
if (cfg->song_loop_count > 0 && cfg->song_ignore_fade) {
|
|
||||||
vgmstream_set_loop_target(vgmstream, (int)cfg->song_loop_count);
|
|
||||||
cfg->song_fade_time = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -1161,8 +1084,7 @@ int winamp_Play(const in_char *fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* config */
|
/* config */
|
||||||
set_config_defaults(&config);
|
apply_config(vgmstream, &settings);
|
||||||
apply_config(vgmstream, &config);
|
|
||||||
|
|
||||||
/* enable after all config but before outbuf (though ATM outbuf is not dynamic so no need to read input_channels) */
|
/* 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_autodownmix(vgmstream, settings.downmix_channels);
|
||||||
@ -1174,8 +1096,7 @@ int winamp_Play(const in_char *fn) {
|
|||||||
state.seek_needed_samples = -1;
|
state.seek_needed_samples = -1;
|
||||||
state.decode_pos_ms = 0;
|
state.decode_pos_ms = 0;
|
||||||
state.decode_pos_samples = 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.stream_length_samples = vgmstream_get_samples(vgmstream);
|
||||||
state.fade_samples = (int)(config.song_fade_time * vgmstream->sample_rate);
|
|
||||||
state.volume = get_album_gain_volume(fn);
|
state.volume = get_album_gain_volume(fn);
|
||||||
|
|
||||||
|
|
||||||
@ -1191,7 +1112,7 @@ int winamp_Play(const in_char *fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set info display */
|
/* set info display */
|
||||||
input_module.SetInfo(get_vgmstream_average_bitrate(vgmstream)/1000, vgmstream->sample_rate/1000, state.output_channels, 1);
|
input_module.SetInfo(get_vgmstream_average_bitrate(vgmstream) / 1000, vgmstream->sample_rate / 1000, state.output_channels, 1);
|
||||||
|
|
||||||
/* setup visualization */
|
/* setup visualization */
|
||||||
input_module.SAVSAInit(max_latency,vgmstream->sample_rate);
|
input_module.SAVSAInit(max_latency,vgmstream->sample_rate);
|
||||||
@ -1293,8 +1214,7 @@ int winamp_InfoBox(const in_char *fn, HWND hwnd) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* some other file in playlist given by filename */
|
/* some other file in playlist given by filename */
|
||||||
VGMSTREAM * infostream = NULL;
|
VGMSTREAM* infostream = NULL;
|
||||||
winamp_song_config infoconfig = {0};
|
|
||||||
in_char filename[PATH_LIMIT];
|
in_char filename[PATH_LIMIT];
|
||||||
int stream_index = 0;
|
int stream_index = 0;
|
||||||
|
|
||||||
@ -1305,8 +1225,7 @@ int winamp_InfoBox(const in_char *fn, HWND hwnd) {
|
|||||||
infostream = init_vgmstream_winamp(filename, stream_index);
|
infostream = init_vgmstream_winamp(filename, stream_index);
|
||||||
if (!infostream) return 0;
|
if (!infostream) return 0;
|
||||||
|
|
||||||
set_config_defaults(&infoconfig);
|
apply_config(infostream, &settings);
|
||||||
apply_config(infostream, &infoconfig);
|
|
||||||
|
|
||||||
vgmstream_mixing_autodownmix(infostream, settings.downmix_channels);
|
vgmstream_mixing_autodownmix(infostream, settings.downmix_channels);
|
||||||
vgmstream_mixing_enable(infostream, 0, NULL, NULL);
|
vgmstream_mixing_enable(infostream, 0, NULL, NULL);
|
||||||
@ -1351,8 +1270,7 @@ void winamp_GetFileInfo(const in_char *fn, in_char *title, int *length_in_ms) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* some other file in playlist given by filename */
|
/* some other file in playlist given by filename */
|
||||||
VGMSTREAM * infostream = NULL;
|
VGMSTREAM* infostream = NULL;
|
||||||
winamp_song_config infoconfig = {0};
|
|
||||||
in_char filename[PATH_LIMIT];
|
in_char filename[PATH_LIMIT];
|
||||||
int stream_index = 0;
|
int stream_index = 0;
|
||||||
|
|
||||||
@ -1363,8 +1281,7 @@ void winamp_GetFileInfo(const in_char *fn, in_char *title, int *length_in_ms) {
|
|||||||
infostream = init_vgmstream_winamp(filename, stream_index);
|
infostream = init_vgmstream_winamp(filename, stream_index);
|
||||||
if (!infostream) return;
|
if (!infostream) return;
|
||||||
|
|
||||||
set_config_defaults(&infoconfig);
|
apply_config(infostream, &settings);
|
||||||
apply_config(infostream, &infoconfig);
|
|
||||||
|
|
||||||
vgmstream_mixing_autodownmix(infostream, settings.downmix_channels);
|
vgmstream_mixing_autodownmix(infostream, settings.downmix_channels);
|
||||||
vgmstream_mixing_enable(infostream, 0, NULL, NULL);
|
vgmstream_mixing_enable(infostream, 0, NULL, NULL);
|
||||||
@ -1376,8 +1293,7 @@ void winamp_GetFileInfo(const in_char *fn, in_char *title, int *length_in_ms) {
|
|||||||
if (length_in_ms) {
|
if (length_in_ms) {
|
||||||
*length_in_ms = -1000;
|
*length_in_ms = -1000;
|
||||||
if (infostream) {
|
if (infostream) {
|
||||||
const int num_samples = get_vgmstream_play_samples(
|
const int num_samples = vgmstream_get_samples(infostream);
|
||||||
infoconfig.song_loop_count,infoconfig.song_fade_time,infoconfig.song_fade_delay,infostream);
|
|
||||||
*length_in_ms = num_samples * 1000LL /infostream->sample_rate;
|
*length_in_ms = num_samples * 1000LL /infostream->sample_rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1395,13 +1311,13 @@ void winamp_EQSet(int on, char data[10], int preamp) {
|
|||||||
DWORD WINAPI __stdcall decode(void *arg) {
|
DWORD WINAPI __stdcall decode(void *arg) {
|
||||||
const int max_buffer_samples = SAMPLE_BUFFER_SIZE;
|
const int max_buffer_samples = SAMPLE_BUFFER_SIZE;
|
||||||
const int max_samples = state.stream_length_samples;
|
const int max_samples = state.stream_length_samples;
|
||||||
|
int play_forever = vgmstream_get_play_forever(vgmstream);
|
||||||
|
|
||||||
while (!state.decode_abort) {
|
while (!state.decode_abort) {
|
||||||
int samples_to_do;
|
int samples_to_do;
|
||||||
int output_bytes;
|
int output_bytes;
|
||||||
|
|
||||||
if (state.decode_pos_samples + max_buffer_samples > state.stream_length_samples
|
if (state.decode_pos_samples + max_buffer_samples > state.stream_length_samples && !play_forever)
|
||||||
&& (!config.song_play_forever || !vgmstream->loop_flag))
|
|
||||||
samples_to_do = state.stream_length_samples - state.decode_pos_samples;
|
samples_to_do = state.stream_length_samples - state.decode_pos_samples;
|
||||||
else
|
else
|
||||||
samples_to_do = max_buffer_samples;
|
samples_to_do = max_buffer_samples;
|
||||||
@ -1411,7 +1327,6 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
|||||||
/* reset if we need to seek backwards */
|
/* reset if we need to seek backwards */
|
||||||
if (state.seek_needed_samples < state.decode_pos_samples) {
|
if (state.seek_needed_samples < state.decode_pos_samples) {
|
||||||
reset_vgmstream(vgmstream);
|
reset_vgmstream(vgmstream);
|
||||||
apply_config(vgmstream, &config); /* config is undone by reset */
|
|
||||||
|
|
||||||
state.decode_pos_samples = 0;
|
state.decode_pos_samples = 0;
|
||||||
state.decode_pos_ms = 0;
|
state.decode_pos_ms = 0;
|
||||||
@ -1419,7 +1334,7 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
|||||||
|
|
||||||
/* adjust seeking past file, can happen using the right (->) key
|
/* adjust seeking past file, can happen using the right (->) key
|
||||||
* (should be done here and not in SetOutputTime due to threads/race conditions) */
|
* (should be done here and not in SetOutputTime due to threads/race conditions) */
|
||||||
if (state.seek_needed_samples > max_samples && !config.song_play_forever) {
|
if (state.seek_needed_samples > max_samples && !play_forever) {
|
||||||
state.seek_needed_samples = max_samples;
|
state.seek_needed_samples = max_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1457,9 +1372,10 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
|||||||
state.decode_pos_ms = state.decode_pos_samples * 1000LL / vgmstream->sample_rate;
|
state.decode_pos_ms = state.decode_pos_samples * 1000LL / vgmstream->sample_rate;
|
||||||
}
|
}
|
||||||
else if (input_module.outMod->CanWrite() >= output_bytes) { /* decode */
|
else if (input_module.outMod->CanWrite() >= output_bytes) { /* decode */
|
||||||
render_vgmstream(sample_buffer,samples_to_do,vgmstream);
|
|
||||||
|
|
||||||
/* apply ReplayGain, if needed */
|
render_vgmstream(sample_buffer, samples_to_do, vgmstream);
|
||||||
|
|
||||||
|
/* apply ReplayGain, if needed */
|
||||||
if (state.volume != 1.0) {
|
if (state.volume != 1.0) {
|
||||||
int j, k;
|
int j, k;
|
||||||
for (j = 0; j < samples_to_do; j++) {
|
for (j = 0; j < samples_to_do; j++) {
|
||||||
@ -1470,24 +1386,6 @@ DWORD WINAPI __stdcall decode(void *arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fade near the end */
|
|
||||||
if (vgmstream->loop_flag && state.fade_samples > 0 && !config.song_play_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)(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* output samples */
|
/* output samples */
|
||||||
input_module.SAAddPCMData((char*)sample_buffer,state.output_channels,16,state.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);
|
input_module.VSAAddPCMData((char*)sample_buffer,state.output_channels,16,state.decode_pos_ms);
|
||||||
@ -1622,7 +1520,7 @@ static void load_tagfile_info(in_char* filename) {
|
|||||||
/* load all tags from tagfile */
|
/* load all tags from tagfile */
|
||||||
tagFile = open_winamp_streamfile_by_ipath(tagfile_path_i);
|
tagFile = open_winamp_streamfile_by_ipath(tagfile_path_i);
|
||||||
if (tagFile != NULL) {
|
if (tagFile != NULL) {
|
||||||
VGMSTREAM_TAGS *tags;
|
VGMSTREAM_TAGS* tags;
|
||||||
const char *tag_key, *tag_val;
|
const char *tag_key, *tag_val;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -1776,7 +1674,6 @@ __declspec(dllexport) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg
|
|||||||
* library or CD burner, if implemented. In usual Winamp fashion they are messy, barely
|
* library or CD burner, if implemented. In usual Winamp fashion they are messy, barely
|
||||||
* documented, slightly different repeats of the above. */
|
* documented, slightly different repeats of the above. */
|
||||||
|
|
||||||
winamp_song_config xconfig;
|
|
||||||
winamp_state_t xstate;
|
winamp_state_t xstate;
|
||||||
short xsample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS];
|
short xsample_buffer[SAMPLE_BUFFER_SIZE*2 * VGMSTREAM_MAX_CHANNELS];
|
||||||
|
|
||||||
@ -1798,8 +1695,7 @@ static void *winampGetExtendedRead_open_common(in_char *fn, int *size, int *bps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* config */
|
/* config */
|
||||||
set_config_defaults(&xconfig);
|
apply_config(xvgmstream, &settings);
|
||||||
apply_config(xvgmstream, &xconfig);
|
|
||||||
|
|
||||||
/* enable after all config but before outbuf (though ATM outbuf is not dynamic so no need to read input_channels) */
|
/* enable after all config but before outbuf (though ATM outbuf is not dynamic so no need to read input_channels) */
|
||||||
vgmstream_mixing_autodownmix(xvgmstream, settings.downmix_channels);
|
vgmstream_mixing_autodownmix(xvgmstream, settings.downmix_channels);
|
||||||
@ -1811,8 +1707,7 @@ static void *winampGetExtendedRead_open_common(in_char *fn, int *size, int *bps,
|
|||||||
xstate.seek_needed_samples = -1;
|
xstate.seek_needed_samples = -1;
|
||||||
xstate.decode_pos_ms = 0; /* unused */
|
xstate.decode_pos_ms = 0; /* unused */
|
||||||
xstate.decode_pos_samples = 0;
|
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.stream_length_samples = vgmstream_get_samples(xvgmstream);
|
||||||
xstate.fade_samples = (int)(xconfig.song_fade_time * xvgmstream->sample_rate);
|
|
||||||
xstate.volume = 1.0; /* unused */
|
xstate.volume = 1.0; /* unused */
|
||||||
|
|
||||||
if (size) /* bytes to decode (-1 if unknown) */
|
if (size) /* bytes to decode (-1 if unknown) */
|
||||||
@ -1849,17 +1744,17 @@ __declspec(dllexport) size_t winampGetExtendedRead_getData(void *handle, char *d
|
|||||||
const int max_samples = xstate.stream_length_samples;
|
const int max_samples = xstate.stream_length_samples;
|
||||||
unsigned copied = 0;
|
unsigned copied = 0;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
VGMSTREAM *xvgmstream = handle;
|
VGMSTREAM* xvgmstream = handle;
|
||||||
|
int play_forever;
|
||||||
if (!xvgmstream) {
|
if (!xvgmstream)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
play_forever = vgmstream_get_play_forever(xvgmstream);
|
||||||
|
|
||||||
while (copied + (max_buffer_samples * xvgmstream->channels * sizeof(short)) < len && !done) {
|
while (copied + (max_buffer_samples * xvgmstream->channels * sizeof(short)) < len && !done) {
|
||||||
int samples_to_do;
|
int samples_to_do;
|
||||||
|
|
||||||
if (xstate.decode_pos_samples + max_buffer_samples > xstate.stream_length_samples
|
if (xstate.decode_pos_samples + max_buffer_samples > xstate.stream_length_samples && !play_forever)
|
||||||
&& (!config.song_play_forever || !xvgmstream->loop_flag))
|
|
||||||
samples_to_do = xstate.stream_length_samples - xstate.decode_pos_samples;
|
samples_to_do = xstate.stream_length_samples - xstate.decode_pos_samples;
|
||||||
else
|
else
|
||||||
samples_to_do = max_buffer_samples;
|
samples_to_do = max_buffer_samples;
|
||||||
@ -1869,14 +1764,13 @@ __declspec(dllexport) size_t winampGetExtendedRead_getData(void *handle, char *d
|
|||||||
/* reset if we need to seek backwards */
|
/* reset if we need to seek backwards */
|
||||||
if (xstate.seek_needed_samples < xstate.decode_pos_samples) {
|
if (xstate.seek_needed_samples < xstate.decode_pos_samples) {
|
||||||
reset_vgmstream(xvgmstream);
|
reset_vgmstream(xvgmstream);
|
||||||
apply_config(xvgmstream, &xconfig); /* config is undone by reset */
|
|
||||||
|
|
||||||
xstate.decode_pos_samples = 0;
|
xstate.decode_pos_samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adjust seeking past file, can happen using the right (->) key
|
/* adjust seeking past file, can happen using the right (->) key
|
||||||
* (should be done here and not in SetOutputTime due to threads/race conditions) */
|
* (should be done here and not in SetOutputTime due to threads/race conditions) */
|
||||||
if (xstate.seek_needed_samples > max_samples && !config.song_play_forever) {
|
if (xstate.seek_needed_samples > max_samples && !play_forever) {
|
||||||
xstate.seek_needed_samples = max_samples;
|
xstate.seek_needed_samples = max_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1903,24 +1797,6 @@ __declspec(dllexport) size_t winampGetExtendedRead_getData(void *handle, char *d
|
|||||||
else { /* decode */
|
else { /* decode */
|
||||||
render_vgmstream(xsample_buffer, samples_to_do, xvgmstream);
|
render_vgmstream(xsample_buffer, samples_to_do, xvgmstream);
|
||||||
|
|
||||||
/* fade near the end */
|
|
||||||
if (xvgmstream->loop_flag && xstate.fade_samples > 0 && !config.song_play_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)(xstate.fade_samples - samples_into_fade) / xstate.fade_samples;
|
|
||||||
for (k = 0; k < fade_channels; k++) {
|
|
||||||
xsample_buffer[j*fade_channels+k] =
|
|
||||||
(short)(xsample_buffer[j*fade_channels+k]*fadedness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* output samples */
|
/* output samples */
|
||||||
memcpy(&dest[copied], xsample_buffer, samples_to_do * xstate.output_channels * sizeof(short));
|
memcpy(&dest[copied], xsample_buffer, samples_to_do * xstate.output_channels * sizeof(short));
|
||||||
copied += samples_to_do * xstate.output_channels * sizeof(short);
|
copied += samples_to_do * xstate.output_channels * sizeof(short);
|
||||||
|
Loading…
Reference in New Issue
Block a user