4063a5f2522df30f364329d62dce1c086983a3f4
[platform/upstream/flac.git] / src / plugin_winamp2 / in_flac.c
1 /* in_flac - Winamp2 FLAC input plugin
2  * Copyright (C) 2000,2001,2002,2003  Josh Coalson
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #include <windows.h>
20 #include <mmreg.h>
21 #include <msacm.h>
22 #include <math.h>
23 #include <stdio.h>
24
25 #include "winamp2/in2.h"
26 #include "FLAC/all.h"
27 #include "plugin_common/all.h"
28 #include "share/grabbag.h"
29 #include "share/replaygain_synthesis.h"
30 #include "config.h"
31 #include "infobox.h"
32 #include "tagz.h"
33
34
35 typedef struct {
36         FLAC__bool abort_flag;
37         int seek_to;
38         int paused;
39         unsigned total_samples;
40         unsigned bits_per_sample;
41         unsigned output_bits_per_sample;
42         unsigned channels;
43         unsigned sample_rate;
44         unsigned length_in_msec;
45         FLAC__bool has_replaygain;
46         double replay_scale;
47         DitherContext dither_context;
48 } file_info_struct;
49
50
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);
58
59 char ini_name[MAX_PATH];
60 flac_config_t flac_cfg;
61 static output_config_t cfg; /* local copy */
62
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 */
66
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_;
74
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 */
77
78 static DWORD WINAPI DecodeThread(void *b); /* the decode thread procedure */
79
80
81 static void show_error(const char *message,...)
82 {
83         char foo[512];
84         va_list args;
85         va_start(args, message);
86         vsprintf(foo, message, args);
87         va_end(args);
88         MessageBox(mod_.hMainWindow, foo, "FLAC Plug-in Error", MB_ICONSTOP);
89 }
90
91 void config(HWND hwndParent)
92 {
93         if (DoConfig(mod_.hDllInstance, hwndParent))
94                 WriteConfig();
95 }
96
97 void about(HWND hwndParent)
98 {
99         MessageBox(hwndParent, "Winamp FLAC Plugin v" VERSION ", by Josh Coalson\nSee http://flac.sourceforge.net/", "About FLAC Plugin", MB_OK);
100 }
101
102 void init()
103 {
104         char *p;
105
106         decoder_ = FLAC__file_decoder_new();
107         strcpy(lastfn_, "");
108         /* read config */
109         GetModuleFileName(NULL, ini_name, sizeof(ini_name));
110         p = strrchr(ini_name, '.');
111         if (!p) p = ini_name + strlen(ini_name);
112         strcpy(p, ".ini");
113
114         ReadConfig();
115 }
116
117 void quit()
118 {
119         WriteConfig();
120         safe_decoder_delete_(decoder_);
121         decoder_ = 0;
122 }
123
124 int isourfile(char *fn) { return 0; }
125
126
127 int play(char *fn)
128 {
129         int maxlatency;
130         int thread_id;
131         HANDLE input_file;
132         DWORD  file_size;       /*@@@ fixme 64-bit */
133
134         if (decoder_ == 0)
135                 return 1;
136
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)
139                 return -1;
140         file_size = GetFileSize(input_file, NULL);
141         CloseHandle(input_file);
142
143         file_info_.abort_flag = false;
144         file_info_.has_replaygain = false;
145         if (!safe_decoder_init_(fn, decoder_))
146                 return 1;
147
148         cfg = flac_cfg.output;
149         strcpy(lastfn_, fn);
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;
154
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);
157
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 */
160                 return 1;
161
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);
165
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);
171
172         file_info_.paused = 0;
173         file_info_.seek_to = -1;
174         decode_pos_ms_ = 0;
175         killDecodeThread = 0;
176         thread_handle = CreateThread(NULL, 0, DecodeThread, NULL, 0, &thread_id);
177         if (!thread_handle)
178                 return 1;
179
180         return 0;
181 }
182
183 void pause()
184 {
185         file_info_.paused = 1;
186         mod_.outMod->Pause(1);
187 }
188
189 void unpause()
190 {
191         file_info_.paused = 0;
192         mod_.outMod->Pause(0);
193 }
194
195 int ispaused()
196 {
197         return file_info_.paused;
198 }
199
200 void stop()
201 {
202         if (thread_handle) {
203                 killDecodeThread = 1;
204                 if(WaitForSingleObject(thread_handle, 2000) == WAIT_TIMEOUT) {
205                         show_error("Error while stopping decoding thread.");
206                         TerminateThread(thread_handle, 0);
207                 }
208                 CloseHandle(thread_handle);
209                 thread_handle = NULL;
210         }
211         safe_decoder_finish_(decoder_);
212
213         mod_.outMod->Close();
214
215         mod_.SAVSADeInit();
216 }
217
218 int getlength()
219 {
220         return (int)file_info_.length_in_msec;
221 }
222
223 int getoutputtime()
224 {
225         return decode_pos_ms_ + (mod_.outMod->GetOutputTime() - mod_.outMod->GetWrittenTime());
226 }
227
228 void setoutputtime(int time_in_ms)
229 {
230         file_info_.seek_to = time_in_ms;
231 }
232
233 void setvolume(int volume) { mod_.outMod->SetVolume(volume); }
234 void setpan(int pan) { mod_.outMod->SetPan(pan); }
235
236 int infoDlg(char *fn, HWND hwnd)
237 {
238         DoInfoBox(mod_.hDllInstance, hwnd, fn);
239         return 0;
240 }
241
242 void getfileinfo(char *filename, char *title, int *length_in_msec)
243 {
244         FLAC__StreamMetadata streaminfo;
245
246         if (!filename || !*filename) {
247                 filename = lastfn_;
248                 if (length_in_msec) {
249                         *length_in_msec = getlength();
250                         length_in_msec = 0; /* force skip in following code */
251                 }
252         }
253
254         if (!FLAC__metadata_get_streaminfo(filename, &streaminfo)) {
255                 if (title)
256                         sprintf(title, "Invalid FLAC: %s", filename);
257                 if (length_in_msec)
258                         *length_in_msec = -1;
259                 return;
260         }
261
262         if (title)
263                 get_description_(filename, title, 400);
264
265         if (length_in_msec)
266                 *length_in_msec = (int)(streaminfo.data.stream_info.total_samples * 10 / (streaminfo.data.stream_info.sample_rate / 100));
267 }
268
269 void eq_set(int on, char data[10], int preamp) {}
270
271 static void do_vis(char *data, int nch, int resolution, int position, unsigned samples)
272 {
273         static char vis_buffer[SAMPLES_PER_WRITE * FLAC_PLUGIN__MAX_SUPPORTED_CHANNELS];
274         char *ptr;
275         int size, count;
276
277         /*
278          * Winamp visuals may have problems accepting sample sizes larger than
279          * 16 bits, so we reduce the sample size here if necessary.
280          */
281
282         switch(resolution) {
283                 case 32:
284                 case 24:
285                         size  = resolution / 8;
286                         count = samples * nch;
287                         data += size - 1;
288
289                         ptr = vis_buffer;
290                         while(count--) {
291                                 *ptr++ = data[0] ^ 0x80;
292                                 data += size;
293                         }
294
295                         data = vis_buffer;
296                         resolution = 8;
297
298                         /* fall through */
299                 case 16:
300                 case 8:
301                 default:
302                         mod_.SAAddPCMData(data, nch, resolution, position);
303                         mod_.VSAAddPCMData(data, nch, resolution, position);
304         }
305 }
306
307 static DWORD WINAPI DecodeThread(void *unused)
308 {
309         int done = 0;
310
311         (void)unused;
312
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;
318
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;
325                                 done = 0;
326                                 mod_.outMod->Flush(decode_pos_ms_);
327                         }
328                 }
329                 if(done) {
330                         if(!mod_.outMod->IsPlaying()) {
331                                 PostMessage(mod_.hMainWindow, WM_WA_MPEG_EOF, 0, 0);
332                                 return 0;
333                         }
334                         Sleep(10);
335                 }
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) {
339                                         done = 1;
340                                         break;
341                                 }
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_)]);
344                                         done = 1;
345                                         break;
346                                 }
347                         }
348
349                         if(wide_samples_in_reservoir_ == 0) {
350                                 done = 1;
351                         }
352                         else {
353                                 const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE);
354                                 int bytes;
355                                 unsigned i;
356
357                                 if(cfg.replaygain.enable && file_info_.has_replaygain) {
358                                         bytes = (int)FLAC__replaygain_synthesis__apply_gain(
359                                                 sample_buffer_,
360                                                 true, /* little_endian_data_out */
361                                                 target_bps == 8, /* unsigned_data_out */
362                                                 reservoir__,
363                                                 n,
364                                                 channels,
365                                                 bits_per_sample,
366                                                 target_bps,
367                                                 file_info_.replay_scale,
368                                                 cfg.replaygain.hard_limit,
369                                                 cfg.resolution.replaygain.dither,
370                                                 &file_info_.dither_context
371                                         );
372                                 }
373                                 else {
374                                         bytes = (int)FLAC__plugin_common__pack_pcm_signed_little_endian(
375                                                 sample_buffer_,
376                                                 reservoir__,
377                                                 n,
378                                                 channels,
379                                                 bits_per_sample,
380                                                 target_bps
381                                         );
382                                 }
383
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;
387
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);
393                         }
394                 }
395                 else Sleep(20);
396         }
397         return 0;
398 }
399
400
401
402 In_Module mod_ =
403 {
404         IN_VER,
405         "FLAC Reference Player v" VERSION,
406         0,      /* hMainWindow */
407         0,  /* hDllInstance */
408         "FLAC\0FLAC Audio File (*.FLAC)\0"
409         ,
410         1,      /* is_seekable */
411         1, /* uses output */
412         config,
413         about,
414         init,
415         quit,
416         getfileinfo,
417         infoDlg,
418         isourfile,
419         play,
420         pause,
421         unpause,
422         ispaused,
423         stop,
424
425         getlength,
426         getoutputtime,
427         setoutputtime,
428
429         setvolume,
430         setpan,
431
432         0,0,0,0,0,0,0,0,0, /* vis stuff */
433
434
435         0,0, /* dsp */
436
437         eq_set,
438
439         NULL,           /* setinfo */
440
441         0 /* out_mod */
442
443 };
444
445 __declspec(dllexport) In_Module *winampGetInModule2()
446 {
447         return &mod_;
448 }
449
450 BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
451 {
452         return TRUE;
453 }
454
455 /***********************************************************************
456  * local routines
457  **********************************************************************/
458 FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder)
459 {
460         FLAC__ASSERT(0 != decoder);
461
462         safe_decoder_finish_(decoder);
463
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_);
473
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)]);
476                 return false;
477         }
478
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)]);
481                 return false;
482         }
483
484         if (file_info_.abort_flag)
485                 return false; /* metadata callback already popped up the error dialog */
486
487         return true;
488 }
489
490 void safe_decoder_finish_(FLAC__FileDecoder *decoder)
491 {
492         if(decoder && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
493                 FLAC__file_decoder_finish(decoder);
494 }
495
496 void safe_decoder_delete_(FLAC__FileDecoder *decoder)
497 {
498         if(decoder) {
499                 safe_decoder_finish_(decoder);
500                 FLAC__file_decoder_delete(decoder);
501         }
502 }
503
504 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
505 {
506         file_info_struct *file_info = (file_info_struct *)client_data;
507         const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize;
508         unsigned channel;
509
510         (void)decoder;
511
512         if(file_info->abort_flag)
513                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
514
515         for(channel = 0; channel < channels; channel++)
516                 memcpy(&reservoir_[channel][wide_samples_in_reservoir_], buffer[channel], sizeof(buffer[0][0]) * wide_samples);
517
518         wide_samples_in_reservoir_ += wide_samples;
519
520         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
521 }
522
523 void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
524 {
525         file_info_struct *file_info = (file_info_struct *)client_data;
526         (void)decoder;
527
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;
534
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;
538                         return;
539                 }
540                 file_info->length_in_msec = file_info->total_samples * 10 / (file_info->sample_rate / 100);
541         }
542         else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
543                 double gain, peak;
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);
547                 }
548         }
549 }
550
551 void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
552 {
553         file_info_struct *file_info = (file_info_struct*)client_data;
554         (void)decoder;
555         if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
556                 file_info->abort_flag = true;
557 }
558
559 /*
560  *  title formatting
561  */
562
563 typedef struct
564 {
565         FLAC_Plugin__CanonicalTag t;
566         const char *filename;
567 } tag_param_t;
568
569
570 static __inline char *GetFileName(const char *fullname)
571 {
572         const char *c = fullname + strlen(fullname) - 1;
573
574         while (c > fullname)
575         {
576                 if (*c=='\\' || *c=='/')
577                 {
578                         c++;
579                         break;
580                 }
581                 c--;
582         }
583
584         return (char*)c;
585 }
586
587 static const T_CHAR *get_tag(const T_CHAR *tag, void *param)
588 {
589         tag_param_t *p = (tag_param_t*)param;
590
591         if (!stricmp(tag, "path") || !stricmp(tag, "filepath") || !stricmp(tag, "url"))
592                 return p->filename;
593         else if (!stricmp(tag, "filename"))
594         {
595                 static char foo[MAX_PATH];
596                 char *c;
597
598                 strcpy(foo, GetFileName(p->filename));
599                 if (c = strrchr(foo, '.')) *c = 0;
600
601                 return foo;
602         }
603         else if (!stricmp(tag, "title"))
604                 return p->t.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"))
612                 return p->t.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"))
624                 return p->t.genre;
625         else if (!stricmp(tag, "comment") || !stricmp(tag, "description"))
626                 return p->t.comment;
627         else return NULL;
628 }
629
630 void get_description_(const char *filename, char *description, unsigned max_size)
631 {
632         tag_param_t param;
633
634         FLAC_plugin__canonical_tag_init(&param.t);
635         FLAC_plugin__canonical_tag_get_combined(filename, &param.t);
636         param.filename = filename;
637
638         tagz_format(flac_cfg.title.tag_format, get_tag, NULL, &param, description, max_size);
639
640         FLAC_plugin__canonical_tag_clear(&param.t);
641 }