change default extension for ogg flac from .ogg to .oga (SF#1762492: http://sourcefor...
[flac.git] / src / test_libFLAC++ / decoders.cpp
1 /* test_libFLAC++ - Unit tester for libFLAC++
2  * Copyright (C) 2002,2003,2004,2005,2006,2007  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 #if HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #if defined _MSC_VER || defined __MINGW32__
28 #if _MSC_VER <= 1600 /* @@@ [2G limit] */
29 #define fseeko fseek
30 #define ftello ftell
31 #endif
32 #endif
33 #include "decoders.h"
34 #include "FLAC/assert.h"
35 #include "FLAC/metadata.h" // for ::FLAC__metadata_object_is_equal()
36 #include "FLAC++/decoder.h"
37 #include "share/grabbag.h"
38 extern "C" {
39 #include "test_libs_common/file_utils_flac.h"
40 #include "test_libs_common/metadata_utils.h"
41 }
42
43 #ifdef _MSC_VER
44 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
45 #pragma warning ( disable : 4800 )
46 #endif
47
48 typedef enum {
49         LAYER_STREAM = 0, /* FLAC__stream_decoder_init_stream() without seeking */
50         LAYER_SEEKABLE_STREAM, /* FLAC__stream_decoder_init_stream() with seeking */
51         LAYER_FILE, /* FLAC__stream_decoder_init_FILE() */
52         LAYER_FILENAME /* FLAC__stream_decoder_init_file() */
53 } Layer;
54
55 static const char * const LayerString[] = {
56         "Stream",
57         "Seekable Stream",
58         "FILE*",
59         "Filename"
60 };
61
62 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
63 static ::FLAC__StreamMetadata *expected_metadata_sequence_[9];
64 static unsigned num_expected_;
65 static off_t flacfilesize_;
66
67 static const char *flacfilename(bool is_ogg)
68 {
69         return is_ogg? "metadata.oga" : "metadata.flac";
70 }
71
72 static bool die_(const char *msg)
73 {
74         printf("ERROR: %s\n", msg);
75         return false;
76 }
77
78 static FLAC__bool die_s_(const char *msg, const FLAC::Decoder::Stream *decoder)
79 {
80         FLAC::Decoder::Stream::State state = decoder->get_state();
81
82         if(msg)
83                 printf("FAILED, %s", msg);
84         else
85                 printf("FAILED");
86
87         printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
88
89         return false;
90 }
91
92 static void init_metadata_blocks_()
93 {
94         mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
95 }
96
97 static void free_metadata_blocks_()
98 {
99         mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
100 }
101
102 static bool generate_file_(FLAC__bool is_ogg)
103 {
104         printf("\n\ngenerating %sFLAC file for decoder tests...\n", is_ogg? "Ogg ":"");
105
106         num_expected_ = 0;
107         expected_metadata_sequence_[num_expected_++] = &padding_;
108         expected_metadata_sequence_[num_expected_++] = &seektable_;
109         expected_metadata_sequence_[num_expected_++] = &application1_;
110         expected_metadata_sequence_[num_expected_++] = &application2_;
111         expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
112         expected_metadata_sequence_[num_expected_++] = &cuesheet_;
113         expected_metadata_sequence_[num_expected_++] = &picture_;
114         expected_metadata_sequence_[num_expected_++] = &unknown_;
115         /* WATCHOUT: for Ogg FLAC the encoder should move the VORBIS_COMMENT block to the front, right after STREAMINFO */
116
117         if(!file_utils__generate_flacfile(is_ogg, flacfilename(is_ogg), &flacfilesize_, 512 * 1024, &streaminfo_, expected_metadata_sequence_, num_expected_))
118                 return die_("creating the encoded file");
119
120         return true;
121 }
122
123
124 class DecoderCommon {
125 public:
126         Layer layer_;
127         unsigned current_metadata_number_;
128         bool ignore_errors_;
129         bool error_occurred_;
130
131         DecoderCommon(Layer layer): layer_(layer), current_metadata_number_(0), ignore_errors_(false), error_occurred_(false) { }
132         ::FLAC__StreamDecoderWriteStatus common_write_callback_(const ::FLAC__Frame *frame);
133         void common_metadata_callback_(const ::FLAC__StreamMetadata *metadata);
134         void common_error_callback_(::FLAC__StreamDecoderErrorStatus status);
135 };
136
137 ::FLAC__StreamDecoderWriteStatus DecoderCommon::common_write_callback_(const ::FLAC__Frame *frame)
138 {
139         if(error_occurred_)
140                 return ::FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
141
142         if(
143                 (frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
144                 (frame->header.number_type == ::FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
145         ) {
146                 printf("content... ");
147                 fflush(stdout);
148         }
149
150         return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
151 }
152
153 void DecoderCommon::common_metadata_callback_(const ::FLAC__StreamMetadata *metadata)
154 {
155         if(error_occurred_)
156                 return;
157
158         printf("%d... ", current_metadata_number_);
159         fflush(stdout);
160
161         if(current_metadata_number_ >= num_expected_) {
162                 (void)die_("got more metadata blocks than expected");
163                 error_occurred_ = true;
164         }
165         else {
166                 if(!::FLAC__metadata_object_is_equal(expected_metadata_sequence_[current_metadata_number_], metadata)) {
167                         (void)die_("metadata block mismatch");
168                         error_occurred_ = true;
169                 }
170         }
171         current_metadata_number_++;
172 }
173
174 void DecoderCommon::common_error_callback_(::FLAC__StreamDecoderErrorStatus status)
175 {
176         if(!ignore_errors_) {
177                 printf("ERROR: got error callback: err = %u (%s)\n", (unsigned)status, ::FLAC__StreamDecoderErrorStatusString[status]);
178                 error_occurred_ = true;
179         }
180 }
181
182 class StreamDecoder : public FLAC::Decoder::Stream, public DecoderCommon {
183 public:
184         FILE *file_;
185
186         StreamDecoder(Layer layer): FLAC::Decoder::Stream(), DecoderCommon(layer), file_(0) { }
187         ~StreamDecoder() { }
188
189         // from FLAC::Decoder::Stream
190         ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
191         ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
192         ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
193         ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length);
194         bool eof_callback();
195         ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
196         void metadata_callback(const ::FLAC__StreamMetadata *metadata);
197         void error_callback(::FLAC__StreamDecoderErrorStatus status);
198
199         bool test_respond(bool is_ogg);
200 };
201
202 ::FLAC__StreamDecoderReadStatus StreamDecoder::read_callback(FLAC__byte buffer[], size_t *bytes)
203 {
204         const size_t requested_bytes = *bytes;
205
206         if(error_occurred_)
207                 return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT;
208
209         if(feof(file_)) {
210                 *bytes = 0;
211                 return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
212         }
213         else if(requested_bytes > 0) {
214                 *bytes = ::fread(buffer, 1, requested_bytes, file_);
215                 if(*bytes == 0) {
216                         if(feof(file_))
217                                 return ::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
218                         else
219                                 return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
220                 }
221                 else {
222                         return ::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
223                 }
224         }
225         else
226                 return ::FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
227 }
228
229 ::FLAC__StreamDecoderSeekStatus StreamDecoder::seek_callback(FLAC__uint64 absolute_byte_offset)
230 {
231         if(layer_ == LAYER_STREAM)
232                 return ::FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
233
234         if(error_occurred_)
235                 return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
236
237         if(fseeko(file_, (off_t)absolute_byte_offset, SEEK_SET) < 0) {
238                 error_occurred_ = true;
239                 return ::FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
240         }
241
242         return ::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
243 }
244
245 ::FLAC__StreamDecoderTellStatus StreamDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
246 {
247         if(layer_ == LAYER_STREAM)
248                 return ::FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
249
250         if(error_occurred_)
251                 return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
252
253         off_t offset = ftello(file_);
254         *absolute_byte_offset = (FLAC__uint64)offset;
255
256         if(offset < 0) {
257                 error_occurred_ = true;
258                 return ::FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
259         }
260
261         return ::FLAC__STREAM_DECODER_TELL_STATUS_OK;
262 }
263
264 ::FLAC__StreamDecoderLengthStatus StreamDecoder::length_callback(FLAC__uint64 *stream_length)
265 {
266         if(layer_ == LAYER_STREAM)
267                 return ::FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
268
269         if(error_occurred_)
270                 return ::FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
271
272         *stream_length = (FLAC__uint64)flacfilesize_;
273         return ::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
274 }
275
276 bool StreamDecoder::eof_callback()
277 {
278         if(layer_ == LAYER_STREAM)
279                 return false;
280
281         if(error_occurred_)
282                 return true;
283
284         return (bool)feof(file_);
285 }
286
287 ::FLAC__StreamDecoderWriteStatus StreamDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
288 {
289         (void)buffer;
290
291         return common_write_callback_(frame);
292 }
293
294 void StreamDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
295 {
296         common_metadata_callback_(metadata);
297 }
298
299 void StreamDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
300 {
301         common_error_callback_(status);
302 }
303
304 bool StreamDecoder::test_respond(bool is_ogg)
305 {
306         ::FLAC__StreamDecoderInitStatus init_status;
307
308         if(!set_md5_checking(true)) {
309                 printf("FAILED at set_md5_checking(), returned false\n");
310                 return false;
311         }
312
313         printf("testing init%s()... ", is_ogg? "_ogg":"");
314         init_status = is_ogg? init_ogg() : init();
315         if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
316                 return die_s_(0, this);
317         printf("OK\n");
318
319         current_metadata_number_ = 0;
320
321         if(fseeko(file_, 0, SEEK_SET) < 0) {
322                 printf("FAILED rewinding input, errno = %d\n", errno);
323                 return false;
324         }
325
326         printf("testing process_until_end_of_stream()... ");
327         if(!process_until_end_of_stream()) {
328                 State state = get_state();
329                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
330                 return false;
331         }
332         printf("OK\n");
333
334         printf("testing finish()... ");
335         if(!finish()) {
336                 State state = get_state();
337                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
338                 return false;
339         }
340         printf("OK\n");
341
342         return true;
343 }
344
345 class FileDecoder : public FLAC::Decoder::File, public DecoderCommon {
346 public:
347         FileDecoder(Layer layer): FLAC::Decoder::File(), DecoderCommon(layer) { }
348         ~FileDecoder() { }
349
350         // from FLAC::Decoder::Stream
351         ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
352         void metadata_callback(const ::FLAC__StreamMetadata *metadata);
353         void error_callback(::FLAC__StreamDecoderErrorStatus status);
354
355         bool test_respond(bool is_ogg);
356 };
357
358 ::FLAC__StreamDecoderWriteStatus FileDecoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
359 {
360         (void)buffer;
361         return common_write_callback_(frame);
362 }
363
364 void FileDecoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
365 {
366         common_metadata_callback_(metadata);
367 }
368
369 void FileDecoder::error_callback(::FLAC__StreamDecoderErrorStatus status)
370 {
371         common_error_callback_(status);
372 }
373
374 bool FileDecoder::test_respond(bool is_ogg)
375 {
376         ::FLAC__StreamDecoderInitStatus init_status;
377
378         if(!set_md5_checking(true)) {
379                 printf("FAILED at set_md5_checking(), returned false\n");
380                 return false;
381         }
382
383         switch(layer_) {
384                 case LAYER_FILE:
385                         {
386                                 printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
387                                 FILE *file = ::fopen(flacfilename(is_ogg), "rb");
388                                 if(0 == file) {
389                                         printf("ERROR (%s)\n", strerror(errno));
390                                         return false;
391                                 }
392                                 printf("OK\n");
393
394                                 printf("testing init%s()... ", is_ogg? "_ogg":"");
395                                 init_status = is_ogg? init_ogg(file) : init(file);
396                         }
397                         break;
398                 case LAYER_FILENAME:
399                         printf("testing init%s()... ", is_ogg? "_ogg":"");
400                         init_status = is_ogg? init_ogg(flacfilename(is_ogg)) : init(flacfilename(is_ogg));
401                         break;
402                 default:
403                         die_("internal error 001");
404                         return false;
405         }
406         if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
407                 return die_s_(0, this);
408         printf("OK\n");
409
410         current_metadata_number_ = 0;
411
412         printf("testing process_until_end_of_stream()... ");
413         if(!process_until_end_of_stream()) {
414                 State state = get_state();
415                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
416                 return false;
417         }
418         printf("OK\n");
419
420         printf("testing finish()... ");
421         if(!finish()) {
422                 State state = get_state();
423                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
424                 return false;
425         }
426         printf("OK\n");
427
428         return true;
429 }
430
431
432 static FLAC::Decoder::Stream *new_by_layer(Layer layer)
433 {
434         if(layer < LAYER_FILE)
435                 return new StreamDecoder(layer);
436         else
437                 return new FileDecoder(layer);
438 }
439
440 static bool test_stream_decoder(Layer layer, bool is_ogg)
441 {
442         FLAC::Decoder::Stream *decoder;
443         ::FLAC__StreamDecoderInitStatus init_status;
444         bool expect;
445
446         printf("\n+++ libFLAC++ unit test: FLAC::Decoder::%s (layer: %s, format: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer], is_ogg? "Ogg FLAC" : "FLAC");
447
448         //
449         // test new -> delete
450         //
451         printf("allocating decoder instance... ");
452         decoder = new_by_layer(layer);
453         if(0 == decoder) {
454                 printf("FAILED, new returned NULL\n");
455                 return false;
456         }
457         printf("OK\n");
458
459         printf("testing is_valid()... ");
460         if(!decoder->is_valid()) {
461                 printf("FAILED, returned false\n");
462                 return false;
463         }
464         printf("OK\n");
465
466         printf("freeing decoder instance... ");
467         delete decoder;
468         printf("OK\n");
469
470         //
471         // test new -> init -> delete
472         //
473         printf("allocating decoder instance... ");
474         decoder = new_by_layer(layer);
475         if(0 == decoder) {
476                 printf("FAILED, new returned NULL\n");
477                 return false;
478         }
479         printf("OK\n");
480
481         printf("testing is_valid()... ");
482         if(!decoder->is_valid()) {
483                 printf("FAILED, returned false\n");
484                 return false;
485         }
486         printf("OK\n");
487
488         printf("testing init%s()... ", is_ogg? "_ogg":"");
489         switch(layer) {
490                 case LAYER_STREAM:
491                 case LAYER_SEEKABLE_STREAM:
492                         dynamic_cast<StreamDecoder*>(decoder)->file_ = stdin;
493                         init_status = is_ogg? decoder->init_ogg() : decoder->init();
494                         break;
495                 case LAYER_FILE:
496                         init_status = is_ogg?
497                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(stdin) :
498                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init(stdin);
499                         break;
500                 case LAYER_FILENAME:
501                         init_status = is_ogg?
502                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
503                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
504                         break;
505                 default:
506                         die_("internal error 006");
507                         return false;
508         }
509         if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
510                 return die_s_(0, decoder);
511         printf("OK\n");
512
513         printf("freeing decoder instance... ");
514         delete decoder;
515         printf("OK\n");
516
517         //
518         // test normal usage
519         //
520         num_expected_ = 0;
521         expected_metadata_sequence_[num_expected_++] = &streaminfo_;
522
523         printf("allocating decoder instance... ");
524         decoder = new_by_layer(layer);
525         if(0 == decoder) {
526                 printf("FAILED, new returned NULL\n");
527                 return false;
528         }
529         printf("OK\n");
530
531         printf("testing is_valid()... ");
532         if(!decoder->is_valid()) {
533                 printf("FAILED, returned false\n");
534                 return false;
535         }
536         printf("OK\n");
537
538         if(is_ogg) {
539                 printf("testing set_ogg_serial_number()... ");
540                 if(!decoder->set_ogg_serial_number(file_utils__ogg_serial_number))
541                         return die_s_("returned false", decoder);
542                 printf("OK\n");
543         }
544
545         if(!decoder->set_md5_checking(true)) {
546                 printf("FAILED at set_md5_checking(), returned false\n");
547                 return false;
548         }
549
550         switch(layer) {
551                 case LAYER_STREAM:
552                 case LAYER_SEEKABLE_STREAM:
553                         printf("opening %sFLAC file... ", is_ogg? "Ogg ":"");
554                         dynamic_cast<StreamDecoder*>(decoder)->file_ = ::fopen(flacfilename(is_ogg), "rb");
555                         if(0 == dynamic_cast<StreamDecoder*>(decoder)->file_) {
556                                 printf("ERROR (%s)\n", strerror(errno));
557                                 return false;
558                         }
559                         printf("OK\n");
560
561                         printf("testing init%s()... ", is_ogg? "_ogg":"");
562                         init_status = is_ogg? decoder->init_ogg() : decoder->init();
563                         break;
564                 case LAYER_FILE:
565                         {
566                                 printf("opening FLAC file... ");
567                                 FILE *file = ::fopen(flacfilename(is_ogg), "rb");
568                                 if(0 == file) {
569                                         printf("ERROR (%s)\n", strerror(errno));
570                                         return false;
571                                 }
572                                 printf("OK\n");
573
574                                 printf("testing init%s()... ", is_ogg? "_ogg":"");
575                                 init_status = is_ogg?
576                                         dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(file) :
577                                         dynamic_cast<FLAC::Decoder::File*>(decoder)->init(file);
578                         }
579                         break;
580                 case LAYER_FILENAME:
581                         printf("testing init%s()... ", is_ogg? "_ogg":"");
582                         init_status = is_ogg?
583                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init_ogg(flacfilename(is_ogg)) :
584                                 dynamic_cast<FLAC::Decoder::File*>(decoder)->init(flacfilename(is_ogg));
585                         break;
586                 default:
587                         die_("internal error 009");
588                         return false;
589         }
590         if(init_status != ::FLAC__STREAM_DECODER_INIT_STATUS_OK)
591                 return die_s_(0, decoder);
592         printf("OK\n");
593
594         printf("testing get_state()... ");
595         FLAC::Decoder::Stream::State state = decoder->get_state();
596         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
597
598         dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
599         dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
600         dynamic_cast<DecoderCommon*>(decoder)->error_occurred_ = false;
601
602         printf("testing get_md5_checking()... ");
603         if(!decoder->get_md5_checking()) {
604                 printf("FAILED, returned false, expected true\n");
605                 return false;
606         }
607         printf("OK\n");
608
609         printf("testing process_until_end_of_metadata()... ");
610         if(!decoder->process_until_end_of_metadata())
611                 return die_s_("returned false", decoder);
612         printf("OK\n");
613
614         printf("testing process_single()... ");
615         if(!decoder->process_single())
616                 return die_s_("returned false", decoder);
617         printf("OK\n");
618
619         printf("testing skip_single_frame()... ");
620         if(!decoder->skip_single_frame())
621                 return die_s_("returned false", decoder);
622         printf("OK\n");
623
624         if(layer < LAYER_FILE) {
625                 printf("testing flush()... ");
626                 if(!decoder->flush())
627                         return die_s_("returned false", decoder);
628                 printf("OK\n");
629
630                 dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = true;
631                 printf("testing process_single()... ");
632                 if(!decoder->process_single())
633                         return die_s_("returned false", decoder);
634                 printf("OK\n");
635                 dynamic_cast<DecoderCommon*>(decoder)->ignore_errors_ = false;
636         }
637
638         expect = (layer != LAYER_STREAM);
639         printf("testing seek_absolute()... ");
640         if(decoder->seek_absolute(0) != expect)
641                 return die_s_(expect? "returned false" : "returned true", decoder);
642         printf("OK\n");
643
644         printf("testing process_until_end_of_stream()... ");
645         if(!decoder->process_until_end_of_stream())
646                 return die_s_("returned false", decoder);
647         printf("OK\n");
648
649         expect = (layer != LAYER_STREAM);
650         printf("testing seek_absolute()... ");
651         if(decoder->seek_absolute(0) != expect)
652                 return die_s_(expect? "returned false" : "returned true", decoder);
653         printf("OK\n");
654
655         printf("testing get_channels()... ");
656         {
657                 unsigned channels = decoder->get_channels();
658                 if(channels != streaminfo_.data.stream_info.channels) {
659                         printf("FAILED, returned %u, expected %u\n", channels, streaminfo_.data.stream_info.channels);
660                         return false;
661                 }
662         }
663         printf("OK\n");
664
665         printf("testing get_bits_per_sample()... ");
666         {
667                 unsigned bits_per_sample = decoder->get_bits_per_sample();
668                 if(bits_per_sample != streaminfo_.data.stream_info.bits_per_sample) {
669                         printf("FAILED, returned %u, expected %u\n", bits_per_sample, streaminfo_.data.stream_info.bits_per_sample);
670                         return false;
671                 }
672         }
673         printf("OK\n");
674
675         printf("testing get_sample_rate()... ");
676         {
677                 unsigned sample_rate = decoder->get_sample_rate();
678                 if(sample_rate != streaminfo_.data.stream_info.sample_rate) {
679                         printf("FAILED, returned %u, expected %u\n", sample_rate, streaminfo_.data.stream_info.sample_rate);
680                         return false;
681                 }
682         }
683         printf("OK\n");
684
685         printf("testing get_blocksize()... ");
686         {
687                 unsigned blocksize = decoder->get_blocksize();
688                 /* value could be anything since we're at the last block, so accept any reasonable answer */
689                 printf("returned %u... %s\n", blocksize, blocksize>0? "OK" : "FAILED");
690                 if(blocksize == 0)
691                         return false;
692         }
693
694         printf("testing get_channel_assignment()... ");
695         {
696                 ::FLAC__ChannelAssignment ca = decoder->get_channel_assignment();
697                 printf("returned %u (%s)... OK\n", (unsigned)ca, ::FLAC__ChannelAssignmentString[ca]);
698         }
699
700         if(layer < LAYER_FILE) {
701                 printf("testing reset()... ");
702                 if(!decoder->reset())
703                         return die_s_("returned false", decoder);
704                 printf("OK\n");
705
706                 if(layer == LAYER_STREAM) {
707                         /* after a reset() we have to rewind the input ourselves */
708                         printf("rewinding input... ");
709                         if(fseeko(dynamic_cast<StreamDecoder*>(decoder)->file_, 0, SEEK_SET) < 0) {
710                                 printf("FAILED, errno = %d\n", errno);
711                                 return false;
712                         }
713                         printf("OK\n");
714                 }
715
716                 dynamic_cast<DecoderCommon*>(decoder)->current_metadata_number_ = 0;
717
718                 printf("testing process_until_end_of_stream()... ");
719                 if(!decoder->process_until_end_of_stream())
720                         return die_s_("returned false", decoder);
721                 printf("OK\n");
722         }
723
724         printf("testing finish()... ");
725         if(!decoder->finish()) {
726                 FLAC::Decoder::Stream::State state = decoder->get_state();
727                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)state), state.as_cstring());
728                 return false;
729         }
730         printf("OK\n");
731
732         /*
733          * respond all
734          */
735
736         printf("testing set_metadata_respond_all()... ");
737         if(!decoder->set_metadata_respond_all()) {
738                 printf("FAILED, returned false\n");
739                 return false;
740         }
741         printf("OK\n");
742
743         num_expected_ = 0;
744         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
745                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
746                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
747                 expected_metadata_sequence_[num_expected_++] = &padding_;
748                 expected_metadata_sequence_[num_expected_++] = &seektable_;
749                 expected_metadata_sequence_[num_expected_++] = &application1_;
750                 expected_metadata_sequence_[num_expected_++] = &application2_;
751                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
752                 expected_metadata_sequence_[num_expected_++] = &picture_;
753                 expected_metadata_sequence_[num_expected_++] = &unknown_;
754         }
755         else {
756                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
757                 expected_metadata_sequence_[num_expected_++] = &padding_;
758                 expected_metadata_sequence_[num_expected_++] = &seektable_;
759                 expected_metadata_sequence_[num_expected_++] = &application1_;
760                 expected_metadata_sequence_[num_expected_++] = &application2_;
761                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
762                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
763                 expected_metadata_sequence_[num_expected_++] = &picture_;
764                 expected_metadata_sequence_[num_expected_++] = &unknown_;
765         }
766
767         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
768                 return false;
769
770         /*
771          * ignore all
772          */
773
774         printf("testing set_metadata_ignore_all()... ");
775         if(!decoder->set_metadata_ignore_all()) {
776                 printf("FAILED, returned false\n");
777                 return false;
778         }
779         printf("OK\n");
780
781         num_expected_ = 0;
782
783         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
784                 return false;
785
786         /*
787          * respond all, ignore VORBIS_COMMENT
788          */
789
790         printf("testing set_metadata_respond_all()... ");
791         if(!decoder->set_metadata_respond_all()) {
792                 printf("FAILED, returned false\n");
793                 return false;
794         }
795         printf("OK\n");
796
797         printf("testing set_metadata_ignore(VORBIS_COMMENT)... ");
798         if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
799                 printf("FAILED, returned false\n");
800                 return false;
801         }
802         printf("OK\n");
803
804         num_expected_ = 0;
805         expected_metadata_sequence_[num_expected_++] = &streaminfo_;
806         expected_metadata_sequence_[num_expected_++] = &padding_;
807         expected_metadata_sequence_[num_expected_++] = &seektable_;
808         expected_metadata_sequence_[num_expected_++] = &application1_;
809         expected_metadata_sequence_[num_expected_++] = &application2_;
810         expected_metadata_sequence_[num_expected_++] = &cuesheet_;
811         expected_metadata_sequence_[num_expected_++] = &picture_;
812         expected_metadata_sequence_[num_expected_++] = &unknown_;
813
814         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
815                 return false;
816
817         /*
818          * respond all, ignore APPLICATION
819          */
820
821         printf("testing set_metadata_respond_all()... ");
822         if(!decoder->set_metadata_respond_all()) {
823                 printf("FAILED, returned false\n");
824                 return false;
825         }
826         printf("OK\n");
827
828         printf("testing set_metadata_ignore(APPLICATION)... ");
829         if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
830                 printf("FAILED, returned false\n");
831                 return false;
832         }
833         printf("OK\n");
834
835         num_expected_ = 0;
836         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
837                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
838                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
839                 expected_metadata_sequence_[num_expected_++] = &padding_;
840                 expected_metadata_sequence_[num_expected_++] = &seektable_;
841                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
842                 expected_metadata_sequence_[num_expected_++] = &picture_;
843                 expected_metadata_sequence_[num_expected_++] = &unknown_;
844         }
845         else {
846                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
847                 expected_metadata_sequence_[num_expected_++] = &padding_;
848                 expected_metadata_sequence_[num_expected_++] = &seektable_;
849                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
850                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
851                 expected_metadata_sequence_[num_expected_++] = &picture_;
852                 expected_metadata_sequence_[num_expected_++] = &unknown_;
853         }
854
855         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
856                 return false;
857
858         /*
859          * respond all, ignore APPLICATION id of app#1
860          */
861
862         printf("testing set_metadata_respond_all()... ");
863         if(!decoder->set_metadata_respond_all()) {
864                 printf("FAILED, returned false\n");
865                 return false;
866         }
867         printf("OK\n");
868
869         printf("testing set_metadata_ignore_application(of app block #1)... ");
870         if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
871                 printf("FAILED, returned false\n");
872                 return false;
873         }
874         printf("OK\n");
875
876         num_expected_ = 0;
877         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
878                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
879                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
880                 expected_metadata_sequence_[num_expected_++] = &padding_;
881                 expected_metadata_sequence_[num_expected_++] = &seektable_;
882                 expected_metadata_sequence_[num_expected_++] = &application2_;
883                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
884                 expected_metadata_sequence_[num_expected_++] = &picture_;
885                 expected_metadata_sequence_[num_expected_++] = &unknown_;
886         }
887         else {
888                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
889                 expected_metadata_sequence_[num_expected_++] = &padding_;
890                 expected_metadata_sequence_[num_expected_++] = &seektable_;
891                 expected_metadata_sequence_[num_expected_++] = &application2_;
892                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
893                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
894                 expected_metadata_sequence_[num_expected_++] = &picture_;
895                 expected_metadata_sequence_[num_expected_++] = &unknown_;
896         }
897
898         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
899                 return false;
900
901         /*
902          * respond all, ignore APPLICATION id of app#1 & app#2
903          */
904
905         printf("testing set_metadata_respond_all()... ");
906         if(!decoder->set_metadata_respond_all()) {
907                 printf("FAILED, returned false\n");
908                 return false;
909         }
910         printf("OK\n");
911
912         printf("testing set_metadata_ignore_application(of app block #1)... ");
913         if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
914                 printf("FAILED, returned false\n");
915                 return false;
916         }
917         printf("OK\n");
918
919         printf("testing set_metadata_ignore_application(of app block #2)... ");
920         if(!decoder->set_metadata_ignore_application(application2_.data.application.id)) {
921                 printf("FAILED, returned false\n");
922                 return false;
923         }
924         printf("OK\n");
925
926         num_expected_ = 0;
927         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
928                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
929                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
930                 expected_metadata_sequence_[num_expected_++] = &padding_;
931                 expected_metadata_sequence_[num_expected_++] = &seektable_;
932                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
933                 expected_metadata_sequence_[num_expected_++] = &picture_;
934                 expected_metadata_sequence_[num_expected_++] = &unknown_;
935         }
936         else {
937                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
938                 expected_metadata_sequence_[num_expected_++] = &padding_;
939                 expected_metadata_sequence_[num_expected_++] = &seektable_;
940                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
941                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
942                 expected_metadata_sequence_[num_expected_++] = &picture_;
943                 expected_metadata_sequence_[num_expected_++] = &unknown_;
944         }
945
946         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
947                 return false;
948
949         /*
950          * ignore all, respond VORBIS_COMMENT
951          */
952
953         printf("testing set_metadata_ignore_all()... ");
954         if(!decoder->set_metadata_ignore_all()) {
955                 printf("FAILED, returned false\n");
956                 return false;
957         }
958         printf("OK\n");
959
960         printf("testing set_metadata_respond(VORBIS_COMMENT)... ");
961         if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT)) {
962                 printf("FAILED, returned false\n");
963                 return false;
964         }
965         printf("OK\n");
966
967         num_expected_ = 0;
968         expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
969
970         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
971                 return false;
972
973         /*
974          * ignore all, respond APPLICATION
975          */
976
977         printf("testing set_metadata_ignore_all()... ");
978         if(!decoder->set_metadata_ignore_all()) {
979                 printf("FAILED, returned false\n");
980                 return false;
981         }
982         printf("OK\n");
983
984         printf("testing set_metadata_respond(APPLICATION)... ");
985         if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
986                 printf("FAILED, returned false\n");
987                 return false;
988         }
989         printf("OK\n");
990
991         num_expected_ = 0;
992         expected_metadata_sequence_[num_expected_++] = &application1_;
993         expected_metadata_sequence_[num_expected_++] = &application2_;
994
995         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
996                 return false;
997
998         /*
999          * ignore all, respond APPLICATION id of app#1
1000          */
1001
1002         printf("testing set_metadata_ignore_all()... ");
1003         if(!decoder->set_metadata_ignore_all()) {
1004                 printf("FAILED, returned false\n");
1005                 return false;
1006         }
1007         printf("OK\n");
1008
1009         printf("testing set_metadata_respond_application(of app block #1)... ");
1010         if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1011                 printf("FAILED, returned false\n");
1012                 return false;
1013         }
1014         printf("OK\n");
1015
1016         num_expected_ = 0;
1017         expected_metadata_sequence_[num_expected_++] = &application1_;
1018
1019         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1020                 return false;
1021
1022         /*
1023          * ignore all, respond APPLICATION id of app#1 & app#2
1024          */
1025
1026         printf("testing set_metadata_ignore_all()... ");
1027         if(!decoder->set_metadata_ignore_all()) {
1028                 printf("FAILED, returned false\n");
1029                 return false;
1030         }
1031         printf("OK\n");
1032
1033         printf("testing set_metadata_respond_application(of app block #1)... ");
1034         if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1035                 printf("FAILED, returned false\n");
1036                 return false;
1037         }
1038         printf("OK\n");
1039
1040         printf("testing set_metadata_respond_application(of app block #2)... ");
1041         if(!decoder->set_metadata_respond_application(application2_.data.application.id)) {
1042                 printf("FAILED, returned false\n");
1043                 return false;
1044         }
1045         printf("OK\n");
1046
1047         num_expected_ = 0;
1048         expected_metadata_sequence_[num_expected_++] = &application1_;
1049         expected_metadata_sequence_[num_expected_++] = &application2_;
1050
1051         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1052                 return false;
1053
1054         /*
1055          * respond all, ignore APPLICATION, respond APPLICATION id of app#1
1056          */
1057
1058         printf("testing set_metadata_respond_all()... ");
1059         if(!decoder->set_metadata_respond_all()) {
1060                 printf("FAILED, returned false\n");
1061                 return false;
1062         }
1063         printf("OK\n");
1064
1065         printf("testing set_metadata_ignore(APPLICATION)... ");
1066         if(!decoder->set_metadata_ignore(FLAC__METADATA_TYPE_APPLICATION)) {
1067                 printf("FAILED, returned false\n");
1068                 return false;
1069         }
1070         printf("OK\n");
1071
1072         printf("testing set_metadata_respond_application(of app block #1)... ");
1073         if(!decoder->set_metadata_respond_application(application1_.data.application.id)) {
1074                 printf("FAILED, returned false\n");
1075                 return false;
1076         }
1077         printf("OK\n");
1078
1079         num_expected_ = 0;
1080         if(is_ogg) { /* encoder moves vorbis comment after streaminfo according to ogg mapping */
1081                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
1082                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
1083                 expected_metadata_sequence_[num_expected_++] = &padding_;
1084                 expected_metadata_sequence_[num_expected_++] = &seektable_;
1085                 expected_metadata_sequence_[num_expected_++] = &application1_;
1086                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
1087                 expected_metadata_sequence_[num_expected_++] = &picture_;
1088                 expected_metadata_sequence_[num_expected_++] = &unknown_;
1089         }
1090         else {
1091                 expected_metadata_sequence_[num_expected_++] = &streaminfo_;
1092                 expected_metadata_sequence_[num_expected_++] = &padding_;
1093                 expected_metadata_sequence_[num_expected_++] = &seektable_;
1094                 expected_metadata_sequence_[num_expected_++] = &application1_;
1095                 expected_metadata_sequence_[num_expected_++] = &vorbiscomment_;
1096                 expected_metadata_sequence_[num_expected_++] = &cuesheet_;
1097                 expected_metadata_sequence_[num_expected_++] = &picture_;
1098                 expected_metadata_sequence_[num_expected_++] = &unknown_;
1099         }
1100
1101         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1102                 return false;
1103
1104         /*
1105          * ignore all, respond APPLICATION, ignore APPLICATION id of app#1
1106          */
1107
1108         printf("testing set_metadata_ignore_all()... ");
1109         if(!decoder->set_metadata_ignore_all()) {
1110                 printf("FAILED, returned false\n");
1111                 return false;
1112         }
1113         printf("OK\n");
1114
1115         printf("testing set_metadata_respond(APPLICATION)... ");
1116         if(!decoder->set_metadata_respond(FLAC__METADATA_TYPE_APPLICATION)) {
1117                 printf("FAILED, returned false\n");
1118                 return false;
1119         }
1120         printf("OK\n");
1121
1122         printf("testing set_metadata_ignore_application(of app block #1)... ");
1123         if(!decoder->set_metadata_ignore_application(application1_.data.application.id)) {
1124                 printf("FAILED, returned false\n");
1125                 return false;
1126         }
1127         printf("OK\n");
1128
1129         num_expected_ = 0;
1130         expected_metadata_sequence_[num_expected_++] = &application2_;
1131
1132         if(!(layer < LAYER_FILE? dynamic_cast<StreamDecoder*>(decoder)->test_respond(is_ogg) : dynamic_cast<FileDecoder*>(decoder)->test_respond(is_ogg)))
1133                 return false;
1134
1135         if(layer < LAYER_FILE) /* for LAYER_FILE, FLAC__stream_decoder_finish() closes the file */
1136                 ::fclose(dynamic_cast<StreamDecoder*>(decoder)->file_);
1137
1138         printf("freeing decoder instance... ");
1139         delete decoder;
1140         printf("OK\n");
1141
1142         printf("\nPASSED!\n");
1143
1144         return true;
1145 }
1146
1147 bool test_decoders()
1148 {
1149         FLAC__bool is_ogg = false;
1150
1151         while(1) {
1152                 init_metadata_blocks_();
1153
1154                 if(!generate_file_(is_ogg))
1155                         return false;
1156
1157                 if(!test_stream_decoder(LAYER_STREAM, is_ogg))
1158                         return false;
1159
1160                 if(!test_stream_decoder(LAYER_SEEKABLE_STREAM, is_ogg))
1161                         return false;
1162
1163                 if(!test_stream_decoder(LAYER_FILE, is_ogg))
1164                         return false;
1165
1166                 if(!test_stream_decoder(LAYER_FILENAME, is_ogg))
1167                         return false;
1168
1169                 (void) grabbag__file_remove_file(flacfilename(is_ogg));
1170
1171                 free_metadata_blocks_();
1172
1173                 if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
1174                         break;
1175                 is_ogg = true;
1176         }
1177
1178         return true;
1179 }