1 /* in_flac - Winamp2 FLAC input plugin
2 * Copyright (C) 2000,2001,2002,2003 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,
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.
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.
25 #include "winamp2/in2.h"
27 #include "plugin_common/all.h"
28 #include "share/grabbag.h"
29 #include "share/replaygain_synthesis.h"
36 FLAC__bool abort_flag;
39 unsigned total_samples;
40 unsigned bits_per_sample;
41 unsigned output_bits_per_sample;
44 unsigned length_in_msec;
45 FLAC__bool has_replaygain;
47 DitherContext dither_context;
51 static FLAC__bool safe_decoder_init_(const char *infilename, FLAC__FileDecoder *decoder);
52 static void safe_decoder_finish_(FLAC__FileDecoder *decoder);
53 static void safe_decoder_delete_(FLAC__FileDecoder *decoder);
54 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
55 static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
56 static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
57 static void get_description_(const char *filename, char *description, unsigned max_size);
59 char ini_name[MAX_PATH];
60 flac_config_t flac_cfg;
61 static output_config_t cfg; /* local copy */
63 static In_Module mod_; /* the input module (declared near the bottom of this file) */
64 static char lastfn_[MAX_PATH]; /* currently playing file (used for getting info on the current file) */
65 static int decode_pos_ms_; /* current decoding position, in milliseconds */
67 #define SAMPLES_PER_WRITE 576
68 static FLAC__int32 reservoir_[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS][FLAC__MAX_BLOCK_SIZE * 2/*for overflow*/];
69 static FLAC__int32 *reservoir__[FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS] = { reservoir_[0], reservoir_[1] }; /*@@@ kind of a hard-coded hack */
70 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 */
71 static unsigned wide_samples_in_reservoir_;
72 static file_info_struct file_info_;
73 static FLAC__FileDecoder *decoder_;
75 static volatile int killDecodeThread = 0; /* the kill switch for the decode thread */
76 static HANDLE thread_handle = NULL; /* the handle to the decode thread */
78 static DWORD WINAPI DecodeThread(void *b); /* the decode thread procedure */
81 static void show_error(const char *message,...)
85 va_start(args, message);
86 vsprintf(foo, message, args);
88 MessageBox(mod_.hMainWindow, foo, "FLAC Plug-in Error", MB_ICONSTOP);
91 void config(HWND hwndParent)
93 if (DoConfig(mod_.hDllInstance, hwndParent))
97 void about(HWND hwndParent)
99 MessageBox(hwndParent, "Winamp FLAC Plugin v" VERSION ", by Josh Coalson\nSee http://flac.sourceforge.net/", "About FLAC Plugin", MB_OK);
106 decoder_ = FLAC__file_decoder_new();
109 GetModuleFileName(NULL, ini_name, sizeof(ini_name));
110 p = strrchr(ini_name, '.');
111 if (!p) p = ini_name + strlen(ini_name);
120 safe_decoder_delete_(decoder_);
124 int isourfile(char *fn) { return 0; }
132 DWORD file_size; /*@@@ fixme 64-bit */
137 input_file = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
138 if(input_file == INVALID_HANDLE_VALUE)
140 file_size = GetFileSize(input_file, NULL);
141 CloseHandle(input_file);
143 file_info_.abort_flag = false;
144 file_info_.has_replaygain = false;
145 if (!safe_decoder_init_(fn, decoder_))
148 cfg = flac_cfg.output;
150 wide_samples_in_reservoir_ = 0;
151 file_info_.output_bits_per_sample = file_info_.has_replaygain && cfg.replaygain.enable ?
152 cfg.resolution.replaygain.bps_out :
153 cfg.resolution.normal.dither_24_to_16 ? min(file_info_.bits_per_sample, 16) : file_info_.bits_per_sample;
155 if (file_info_.has_replaygain && cfg.replaygain.enable && cfg.resolution.replaygain.dither)
156 FLAC__replaygain_synthesis__init_dither_context(&file_info_.dither_context, file_info_.bits_per_sample, cfg.resolution.replaygain.noise_shaping);
158 maxlatency = mod_.outMod->Open(file_info_.sample_rate, file_info_.channels, file_info_.output_bits_per_sample, -1, -1);
159 if (maxlatency < 0) /* error opening device */
162 /* dividing by 1000 for the first parameter of setinfo makes it */
163 /* display 'H'... for hundred.. i.e. 14H Kbps. */
164 mod_.SetInfo((int)(file_size/(125.*file_info_.total_samples/file_info_.sample_rate)), file_info_.sample_rate/1000, file_info_.channels, 1);
166 /* initialize vis stuff */
167 mod_.SAVSAInit(maxlatency, file_info_.sample_rate);
168 mod_.VSASetInfo(file_info_.sample_rate, file_info_.channels);
169 /* set the output plug-ins default volume */
170 mod_.outMod->SetVolume(-666);
172 file_info_.paused = 0;
173 file_info_.seek_to = -1;
175 killDecodeThread = 0;
176 thread_handle = CreateThread(NULL, 0, DecodeThread, NULL, 0, &thread_id);
185 file_info_.paused = 1;
186 mod_.outMod->Pause(1);
191 file_info_.paused = 0;
192 mod_.outMod->Pause(0);
197 return file_info_.paused;
203 killDecodeThread = 1;
204 if(WaitForSingleObject(thread_handle, 2000) == WAIT_TIMEOUT) {
205 show_error("Error while stopping decoding thread.");
206 TerminateThread(thread_handle, 0);
208 CloseHandle(thread_handle);
209 thread_handle = NULL;
211 safe_decoder_finish_(decoder_);
213 mod_.outMod->Close();
220 return (int)file_info_.length_in_msec;
225 return decode_pos_ms_ + (mod_.outMod->GetOutputTime() - mod_.outMod->GetWrittenTime());
228 void setoutputtime(int time_in_ms)
230 file_info_.seek_to = time_in_ms;
233 void setvolume(int volume) { mod_.outMod->SetVolume(volume); }
234 void setpan(int pan) { mod_.outMod->SetPan(pan); }
236 int infoDlg(char *fn, HWND hwnd)
238 DoInfoBox(mod_.hDllInstance, hwnd, fn);
242 void getfileinfo(char *filename, char *title, int *length_in_msec)
244 FLAC__StreamMetadata streaminfo;
246 if (!filename || !*filename) {
248 if (length_in_msec) {
249 *length_in_msec = getlength();
250 length_in_msec = 0; /* force skip in following code */
254 if (!FLAC__metadata_get_streaminfo(filename, &streaminfo)) {
256 sprintf(title, "Invalid FLAC: %s", filename);
258 *length_in_msec = -1;
263 get_description_(filename, title, 400);
266 *length_in_msec = (int)(streaminfo.data.stream_info.total_samples * 10 / (streaminfo.data.stream_info.sample_rate / 100));
269 void eq_set(int on, char data[10], int preamp) {}
271 static void do_vis(char *data, int nch, int resolution, int position, unsigned samples)
273 static char vis_buffer[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS];
278 * Winamp visuals may have problems accepting sample sizes larger than
279 * 16 bits, so we reduce the sample size here if necessary.
285 size = resolution / 8;
286 count = samples * nch;
291 *ptr++ = data[0] ^ 0x80;
302 mod_.SAAddPCMData(data, nch, resolution, position);
303 mod_.VSAAddPCMData(data, nch, resolution, position);
307 static DWORD WINAPI DecodeThread(void *unused)
313 while(!killDecodeThread) {
314 const unsigned channels = file_info_.channels;
315 const unsigned bits_per_sample = file_info_.bits_per_sample;
316 const unsigned target_bps = file_info_.output_bits_per_sample;
317 const unsigned sample_rate = file_info_.sample_rate;
319 if(file_info_.seek_to != -1) {
320 const double distance = (double)file_info_.seek_to / (double)getlength();
321 const unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples);
322 if(FLAC__file_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) {
323 decode_pos_ms_ = (int)(distance * (double)getlength());
324 file_info_.seek_to = -1;
326 mod_.outMod->Flush(decode_pos_ms_);
330 if(!mod_.outMod->IsPlaying()) {
331 PostMessage(mod_.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
336 else if(mod_.outMod->CanWrite() >= ((int)(SAMPLES_PER_WRITE*channels*((target_bps+7)/8)) << (mod_.dsp_isactive()?1:0))) {
337 while(wide_samples_in_reservoir_ < SAMPLES_PER_WRITE) {
338 if(FLAC__file_decoder_get_state(decoder_) == FLAC__FILE_DECODER_END_OF_FILE) {
342 else if(!FLAC__file_decoder_process_single(decoder_)) {
343 show_error("Error while processing frame (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder_)]);
349 if(wide_samples_in_reservoir_ == 0) {
353 const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE);
357 if(cfg.replaygain.enable && file_info_.has_replaygain) {
358 bytes = (int)FLAC__replaygain_synthesis__apply_gain(
360 true, /* little_endian_data_out */
361 target_bps == 8, /* unsigned_data_out */
367 file_info_.replay_scale,
368 cfg.replaygain.hard_limit,
369 cfg.resolution.replaygain.dither,
370 &file_info_.dither_context
374 bytes = (int)FLAC__plugin_common__pack_pcm_signed_little_endian(
384 for (i = 0; i < channels; i++)
385 memmove(&reservoir_[i][0], &reservoir_[i][n], sizeof(reservoir_[0][0]) * (wide_samples_in_reservoir_ - n));
386 wide_samples_in_reservoir_ -= n;
388 do_vis(sample_buffer_, channels, target_bps, decode_pos_ms_, n);
389 decode_pos_ms_ += (n*1000 + sample_rate/2)/sample_rate;
390 if(mod_.dsp_isactive())
391 bytes = mod_.dsp_dosamples((short *)sample_buffer_, n, target_bps, channels, sample_rate) * (channels*target_bps/8);
392 mod_.outMod->Write(sample_buffer_, bytes);
405 "FLAC Reference Player v" VERSION,
407 0, /* hDllInstance */
408 "FLAC\0FLAC Audio File (*.FLAC)\0"
432 0,0,0,0,0,0,0,0,0, /* vis stuff */
445 __declspec(dllexport) In_Module *winampGetInModule2()
450 BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
455 /***********************************************************************
457 **********************************************************************/
458 FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder)
460 FLAC__ASSERT(0 != decoder);
462 safe_decoder_finish_(decoder);
464 FLAC__file_decoder_set_md5_checking(decoder, false);
465 FLAC__file_decoder_set_filename(decoder, filename);
466 FLAC__file_decoder_set_metadata_ignore_all(decoder);
467 FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
468 FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
469 FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
470 FLAC__file_decoder_set_write_callback(decoder, write_callback_);
471 FLAC__file_decoder_set_error_callback(decoder, error_callback_);
472 FLAC__file_decoder_set_client_data(decoder, &file_info_);
474 if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
475 show_error("Error while initializing decoder (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
479 if(!FLAC__file_decoder_process_until_end_of_metadata(decoder)) {
480 show_error("Error while processing metadata (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
484 if (file_info_.abort_flag)
485 return false; /* metadata callback already popped up the error dialog */
490 void safe_decoder_finish_(FLAC__FileDecoder *decoder)
492 if(decoder && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
493 FLAC__file_decoder_finish(decoder);
496 void safe_decoder_delete_(FLAC__FileDecoder *decoder)
499 safe_decoder_finish_(decoder);
500 FLAC__file_decoder_delete(decoder);
504 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
506 file_info_struct *file_info = (file_info_struct *)client_data;
507 const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize;
512 if(file_info->abort_flag)
513 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
515 for(channel = 0; channel < channels; channel++)
516 memcpy(&reservoir_[channel][wide_samples_in_reservoir_], buffer[channel], sizeof(buffer[0][0]) * wide_samples);
518 wide_samples_in_reservoir_ += wide_samples;
520 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
523 void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
525 file_info_struct *file_info = (file_info_struct *)client_data;
528 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
529 FLAC__ASSERT(metadata->data.stream_info.total_samples < 0x100000000); /* this plugin can only handle < 4 gigasamples */
530 file_info->total_samples = (unsigned)(metadata->data.stream_info.total_samples&0xfffffffful);
531 file_info->bits_per_sample = metadata->data.stream_info.bits_per_sample;
532 file_info->channels = metadata->data.stream_info.channels;
533 file_info->sample_rate = metadata->data.stream_info.sample_rate;
535 if(file_info->bits_per_sample!=8 && file_info->bits_per_sample!=16 && file_info->bits_per_sample!=24) {
536 show_error("This plugin can only handle 8/16/24-bit samples.");
537 file_info->abort_flag = true;
540 file_info->length_in_msec = file_info->total_samples * 10 / (file_info->sample_rate / 100);
542 else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
544 if(grabbag__replaygain_load_from_vorbiscomment(metadata, cfg.replaygain.album_mode, &gain, &peak)) {
545 file_info_.has_replaygain = true;
546 file_info_.replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)cfg.replaygain.preamp, !cfg.replaygain.hard_limit);
551 void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
553 file_info_struct *file_info = (file_info_struct*)client_data;
555 if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
556 file_info->abort_flag = true;
565 FLAC_Plugin__CanonicalTag t;
566 const char *filename;
570 static __inline char *GetFileName(const char *fullname)
572 const char *c = fullname + strlen(fullname) - 1;
576 if (*c=='\\' || *c=='/')
587 static const T_CHAR *get_tag(const T_CHAR *tag, void *param)
589 tag_param_t *p = (tag_param_t*)param;
591 if (!stricmp(tag, "path") || !stricmp(tag, "filepath") || !stricmp(tag, "url"))
593 else if (!stricmp(tag, "filename"))
595 static char foo[MAX_PATH];
598 strcpy(foo, GetFileName(p->filename));
599 if (c = strrchr(foo, '.')) *c = 0;
603 else if (!stricmp(tag, "title"))
605 else if (!stricmp(tag, "artist"))
606 return p->t.performer ? p->t.performer : p->t.composer;
607 else if (!stricmp(tag, "composer"))
608 return p->t.composer;
609 else if (!stricmp(tag, "performer"))
610 return p->t.performer;
611 else if (!stricmp(tag, "album"))
613 else if (!stricmp(tag, "year") || !stricmp(tag, "date"))
614 return p->t.year_recorded ? p->t.year_recorded : p->t.year_performed;
615 else if (!stricmp(tag, "year_recorded"))
616 return p->t.year_recorded;
617 else if (!stricmp(tag, "year_performed"))
618 return p->t.year_performed;
619 else if (!stricmp(tag, "track_number"))
620 return p->t.track_number;
621 else if (!stricmp(tag, "tracks_in_album"))
622 return p->t.tracks_in_album;
623 else if (!stricmp(tag, "genre"))
625 else if (!stricmp(tag, "comment") || !stricmp(tag, "description"))
630 void get_description_(const char *filename, char *description, unsigned max_size)
634 FLAC_plugin__canonical_tag_init(¶m.t);
635 FLAC_plugin__canonical_tag_get_combined(filename, ¶m.t);
636 param.filename = filename;
638 tagz_format(flac_cfg.title.tag_format, get_tag, NULL, ¶m, description, max_size);
640 FLAC_plugin__canonical_tag_clear(¶m.t);