1
1
/* in_flac - Winamp2 FLAC input plugin
2
* Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
2
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
23
#include <windows.h>
24
#include <limits.h> /* for INT_MAX */
22
27
#include "winamp2/in2.h"
28
#include "configure.h"
24
29
#include "infobox.h"
27
#define PLUGIN_VERSION "1.1.2"
32
#define PLUGIN_VERSION "1.1.4"
29
34
static In_Module mod_; /* the input module (declared near the bottom of this file) */
30
35
static char lastfn_[MAX_PATH]; /* currently playing file (used for getting info on the current file) */
31
36
flac_config_t flac_cfg;
33
static file_info_struct file_info_;
38
static stream_data_struct stream_data_;
35
static FLAC__FileDecoder *decoder_;
40
static FLAC__StreamDecoder *decoder_;
36
41
static char sample_buffer_[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS * (24/8) * 2];
37
42
/* (24/8) for max bytes per sample, and 2 for DSPs */
76
81
if (decoder_ == 0) return 1;
77
82
if (!(filesize = FileSize(fn))) return -1;
79
if (!FLAC_plugin__decoder_init(decoder_, fn, filesize, &file_info_, &flac_cfg.output))
84
if (!FLAC_plugin__decoder_init(decoder_, fn, filesize, &stream_data_, &flac_cfg.output))
81
86
strcpy(lastfn_, fn);
83
maxlatency = mod_.outMod->Open(file_info_.sample_rate, file_info_.channels, file_info_.output_bits_per_sample, -1, -1);
88
maxlatency = mod_.outMod->Open(stream_data_.sample_rate, stream_data_.channels, stream_data_.output_bits_per_sample, -1, -1);
84
89
if (maxlatency < 0)
86
91
FLAC_plugin__decoder_finish(decoder_);
90
95
mod_.outMod->SetVolume(-666);
91
96
mod_.outMod->SetPan(0);
92
97
/* initialize vis stuff */
93
mod_.SAVSAInit(maxlatency, file_info_.sample_rate);
94
mod_.VSASetInfo(file_info_.sample_rate, file_info_.channels);
98
mod_.SAVSAInit(maxlatency, stream_data_.sample_rate);
99
mod_.VSASetInfo(stream_data_.sample_rate, stream_data_.channels);
96
mod_.SetInfo(file_info_.average_bps, file_info_.sample_rate/1000, file_info_.channels, 1);
101
mod_.SetInfo(stream_data_.average_bps, stream_data_.sample_rate/1000, stream_data_.channels, 1);
97
102
/* start playing thread */
99
104
thread_handle = CreateThread(NULL, 0, DecodeThread, NULL, 0, &thread_id);
210
215
static DWORD WINAPI DecodeThread(void *unused)
212
const unsigned channels = file_info_.channels;
213
const unsigned bits_per_sample = file_info_.bits_per_sample;
214
const unsigned target_bps = file_info_.output_bits_per_sample;
215
const unsigned sample_rate = file_info_.sample_rate;
217
const unsigned channels = stream_data_.channels;
218
const unsigned bits_per_sample = stream_data_.bits_per_sample;
219
const unsigned target_bps = stream_data_.output_bits_per_sample;
220
const unsigned sample_rate = stream_data_.sample_rate;
216
221
const unsigned fact = channels * (target_bps/8);
218
while (file_info_.is_playing)
223
while (stream_data_.is_playing)
220
225
/* seek needed */
221
if (file_info_.seek_to != -1)
226
if (stream_data_.seek_to != -1)
223
const int pos = FLAC_plugin__seek(decoder_, &file_info_);
228
const int pos = FLAC_plugin__seek(decoder_, &stream_data_);
224
229
if (pos != -1) mod_.outMod->Flush(pos);
226
231
/* stream ended */
227
else if (file_info_.eof)
232
else if (stream_data_.eof)
229
234
if (!mod_.outMod->IsPlaying())
239
244
/* decode samples */
240
int bytes = FLAC_plugin__decode(decoder_, &file_info_, sample_buffer_);
245
int bytes = FLAC_plugin__decode(decoder_, &stream_data_, sample_buffer_);
241
246
const int n = bytes / fact;
242
247
/* visualization */
243
248
do_vis(sample_buffer_, channels, target_bps, mod_.outMod->GetWrittenTime(), n);
245
250
if (mod_.dsp_isactive())
246
251
bytes = mod_.dsp_dosamples((short*)sample_buffer_, n, target_bps, channels, sample_rate) * fact;
248
while (mod_.outMod->CanWrite()<bytes && file_info_.is_playing && file_info_.seek_to==-1)
253
while (mod_.outMod->CanWrite()<bytes && stream_data_.is_playing && stream_data_.seek_to==-1)
250
if (file_info_.is_playing && file_info_.seek_to==-1)
255
if (stream_data_.is_playing && stream_data_.seek_to==-1)
251
256
mod_.outMod->Write(sample_buffer_, bytes);
252
257
/* show bitrate */
253
258
if (flac_cfg.display.show_bps)
255
const int rate = FLAC_plugin__get_rate(mod_.outMod->GetWrittenTime(), mod_.outMod->GetOutputTime(), &file_info_);
256
if (rate) mod_.SetInfo(rate/1000, file_info_.sample_rate/1000, file_info_.channels, 1);
260
const int rate = FLAC_plugin__get_rate(mod_.outMod->GetWrittenTime(), mod_.outMod->GetOutputTime(), &stream_data_);
261
if (rate) mod_.SetInfo(rate/1000, stream_data_.sample_rate/1000, stream_data_.channels, 1);
327
332
FLAC__StreamMetadata streaminfo;
329
if (!filename || !*filename)
334
if (!filename || !*filename) {
331
335
filename = lastfn_;
334
*length_in_msec = (int)file_info_.length_in_msec;
335
length_in_msec = 0; /* force skip in following code */
336
if (length_in_msec) {
337
*length_in_msec = stream_data_.length_in_msec;
338
length_in_msec = 0; /* force skip in following code */
339
if (!FLAC__metadata_get_streaminfo(filename, &streaminfo))
342
if (!FLAC__metadata_get_streaminfo(filename, &streaminfo)) {
341
343
if (length_in_msec)
342
344
*length_in_msec = -1;
348
349
static WCHAR buffer[400];
349
350
format_title(filename, buffer, 400);
350
351
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, buffer, -1, title, 400, NULL, NULL);
354
if (length_in_msec) {
354
355
/* with VC++ you have to spoon feed it the casting from uint64->int64->double */
355
*length_in_msec = (int)((double)(FLAC__int64)streaminfo.data.stream_info.total_samples / (double)streaminfo.data.stream_info.sample_rate * 1000.0 + 0.5);
356
FLAC__uint64 l = (FLAC__uint64)((double)(FLAC__int64)streaminfo.data.stream_info.total_samples / (double)streaminfo.data.stream_info.sample_rate * 1000.0 + 0.5);
359
*length_in_msec = (int)l;