switch malloc+memset(0) to calloc()
[flac.git] / src / libOggFLAC / file_decoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h> /* for malloc() */
22 #include <string.h> /* for strcmp() */
23 #include <sys/stat.h> /* for stat() */
24 #if defined _MSC_VER || defined __MINGW32__
25 #include <io.h> /* for _setmode() */
26 #include <fcntl.h> /* for _O_BINARY */
27 #elif defined __CYGWIN__
28 #include <io.h> /* for setmode(), O_BINARY */
29 #include <fcntl.h> /* for _O_BINARY */
30 #endif
31 #include "FLAC/assert.h"
32 #include "protected/file_decoder.h"
33 #include "protected/seekable_stream_decoder.h"
34 #include "private/md5.h"
35
36 /***********************************************************************
37  *
38  * Private class method prototypes
39  *
40  ***********************************************************************/
41
42 static void set_defaults_(FLAC__FileDecoder *decoder);
43 static FILE *get_binary_stdin_();
44 static FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
45 static FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
46 static FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
47 static FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
48 static FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
49 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
50 static void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
51 static void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
52
53 /***********************************************************************
54  *
55  * Private class data
56  *
57  ***********************************************************************/
58
59 typedef struct FLAC__FileDecoderPrivate {
60         FLAC__FileDecoderWriteCallback write_callback;
61         FLAC__FileDecoderMetadataCallback metadata_callback;
62         FLAC__FileDecoderErrorCallback error_callback;
63         void *client_data;
64         FILE *file;
65         char *filename; /* == NULL if stdin */
66         FLAC__SeekableStreamDecoder *seekable_stream_decoder;
67 } FLAC__FileDecoderPrivate;
68
69 /***********************************************************************
70  *
71  * Public static class data
72  *
73  ***********************************************************************/
74
75 const OggFLAC_API char * const FLAC__FileDecoderStateString[] = {
76         "FLAC__FILE_DECODER_OK",
77         "FLAC__FILE_DECODER_END_OF_FILE",
78         "FLAC__FILE_DECODER_ERROR_OPENING_FILE",
79         "FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR",
80         "FLAC__FILE_DECODER_SEEK_ERROR",
81         "FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_DECODER_ERROR",
82         "FLAC__FILE_DECODER_ALREADY_INITIALIZED",
83         "FLAC__FILE_DECODER_INVALID_CALLBACK",
84         "FLAC__FILE_DECODER_UNINITIALIZED"
85 };
86
87 /***********************************************************************
88  *
89  * Class constructor/destructor
90  *
91  ***********************************************************************/
92
93 OggFLAC_API FLAC__FileDecoder *FLAC__file_decoder_new()
94 {
95         FLAC__FileDecoder *decoder;
96
97         FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
98
99         decoder = (FLAC__FileDecoder*)calloc(1, sizeof(FLAC__FileDecoder));
100         if(decoder == 0) {
101                 return 0;
102         }
103
104         decoder->protected_ = (FLAC__FileDecoderProtected*)calloc(1, sizeof(FLAC__FileDecoderProtected));
105         if(decoder->protected_ == 0) {
106                 free(decoder);
107                 return 0;
108         }
109
110         decoder->private_ = (FLAC__FileDecoderPrivate*)calloc(1, sizeof(FLAC__FileDecoderPrivate));
111         if(decoder->private_ == 0) {
112                 free(decoder->protected_);
113                 free(decoder);
114                 return 0;
115         }
116
117         decoder->private_->seekable_stream_decoder = FLAC__seekable_stream_decoder_new();
118         if(0 == decoder->private_->seekable_stream_decoder) {
119                 free(decoder->private_);
120                 free(decoder->protected_);
121                 free(decoder);
122                 return 0;
123         }
124
125         decoder->private_->file = 0;
126
127         set_defaults_(decoder);
128
129         decoder->protected_->state = FLAC__FILE_DECODER_UNINITIALIZED;
130
131         return decoder;
132 }
133
134 OggFLAC_API void FLAC__file_decoder_delete(FLAC__FileDecoder *decoder)
135 {
136         FLAC__ASSERT(0 != decoder);
137         FLAC__ASSERT(0 != decoder->protected_);
138         FLAC__ASSERT(0 != decoder->private_);
139         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
140
141         (void)FLAC__file_decoder_finish(decoder);
142
143         FLAC__seekable_stream_decoder_delete(decoder->private_->seekable_stream_decoder);
144
145         free(decoder->private_);
146         free(decoder->protected_);
147         free(decoder);
148 }
149
150 /***********************************************************************
151  *
152  * Public class methods
153  *
154  ***********************************************************************/
155
156 OggFLAC_API FLAC__FileDecoderState FLAC__file_decoder_init(FLAC__FileDecoder *decoder)
157 {
158         FLAC__ASSERT(0 != decoder);
159
160         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
161                 return decoder->protected_->state = FLAC__FILE_DECODER_ALREADY_INITIALIZED;
162
163         if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
164                 return decoder->protected_->state = FLAC__FILE_DECODER_INVALID_CALLBACK;
165
166         if(0 == decoder->private_->filename)
167                 decoder->private_->file = get_binary_stdin_();
168         else
169                 decoder->private_->file = fopen(decoder->private_->filename, "rb");
170
171         if(decoder->private_->file == 0)
172                 return decoder->protected_->state = FLAC__FILE_DECODER_ERROR_OPENING_FILE;
173
174         FLAC__seekable_stream_decoder_set_read_callback(decoder->private_->seekable_stream_decoder, read_callback_);
175         FLAC__seekable_stream_decoder_set_seek_callback(decoder->private_->seekable_stream_decoder, seek_callback_);
176         FLAC__seekable_stream_decoder_set_tell_callback(decoder->private_->seekable_stream_decoder, tell_callback_);
177         FLAC__seekable_stream_decoder_set_length_callback(decoder->private_->seekable_stream_decoder, length_callback_);
178         FLAC__seekable_stream_decoder_set_eof_callback(decoder->private_->seekable_stream_decoder, eof_callback_);
179         FLAC__seekable_stream_decoder_set_write_callback(decoder->private_->seekable_stream_decoder, write_callback_);
180         FLAC__seekable_stream_decoder_set_metadata_callback(decoder->private_->seekable_stream_decoder, metadata_callback_);
181         FLAC__seekable_stream_decoder_set_error_callback(decoder->private_->seekable_stream_decoder, error_callback_);
182         FLAC__seekable_stream_decoder_set_client_data(decoder->private_->seekable_stream_decoder, decoder);
183
184         if(FLAC__seekable_stream_decoder_init(decoder->private_->seekable_stream_decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK)
185                 return decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
186
187         return decoder->protected_->state = FLAC__FILE_DECODER_OK;
188 }
189
190 OggFLAC_API FLAC__bool FLAC__file_decoder_finish(FLAC__FileDecoder *decoder)
191 {
192         FLAC__ASSERT(0 != decoder);
193
194         if(decoder->protected_->state == FLAC__FILE_DECODER_UNINITIALIZED)
195                 return true;
196
197         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
198
199         if(0 != decoder->private_->file && decoder->private_->file != stdin) {
200                 fclose(decoder->private_->file);
201                 decoder->private_->file = 0;
202         }
203
204         if(0 != decoder->private_->filename) {
205                 free(decoder->private_->filename);
206                 decoder->private_->filename = 0;
207         }
208
209         set_defaults_(decoder);
210
211         decoder->protected_->state = FLAC__FILE_DECODER_UNINITIALIZED;
212
213         return FLAC__seekable_stream_decoder_finish(decoder->private_->seekable_stream_decoder);
214 }
215
216 OggFLAC_API FLAC__bool FLAC__file_decoder_set_md5_checking(FLAC__FileDecoder *decoder, FLAC__bool value)
217 {
218         FLAC__ASSERT(0 != decoder);
219         FLAC__ASSERT(0 != decoder->private_);
220         FLAC__ASSERT(0 != decoder->protected_);
221         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
222         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
223                 return false;
224         return FLAC__seekable_stream_decoder_set_md5_checking(decoder->private_->seekable_stream_decoder, value);
225 }
226
227 OggFLAC_API FLAC__bool FLAC__file_decoder_set_filename(FLAC__FileDecoder *decoder, const char *value)
228 {
229         FLAC__ASSERT(0 != decoder);
230         FLAC__ASSERT(0 != decoder->private_);
231         FLAC__ASSERT(0 != decoder->protected_);
232         FLAC__ASSERT(0 != value);
233         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
234                 return false;
235         if(0 != decoder->private_->filename) {
236                 free(decoder->private_->filename);
237                 decoder->private_->filename = 0;
238         }
239         if(0 != strcmp(value, "-")) {
240                 if(0 == (decoder->private_->filename = (char*)malloc(strlen(value)+1))) {
241                         decoder->protected_->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
242                         return false;
243                 }
244                 strcpy(decoder->private_->filename, value);
245         }
246         return true;
247 }
248
249 OggFLAC_API FLAC__bool FLAC__file_decoder_set_write_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderWriteCallback value)
250 {
251         FLAC__ASSERT(0 != decoder);
252         FLAC__ASSERT(0 != decoder->private_);
253         FLAC__ASSERT(0 != decoder->protected_);
254         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
255                 return false;
256         decoder->private_->write_callback = value;
257         return true;
258 }
259
260 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderMetadataCallback value)
261 {
262         FLAC__ASSERT(0 != decoder);
263         FLAC__ASSERT(0 != decoder->private_);
264         FLAC__ASSERT(0 != decoder->protected_);
265         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
266                 return false;
267         decoder->private_->metadata_callback = value;
268         return true;
269 }
270
271 OggFLAC_API FLAC__bool FLAC__file_decoder_set_error_callback(FLAC__FileDecoder *decoder, FLAC__FileDecoderErrorCallback value)
272 {
273         FLAC__ASSERT(0 != decoder);
274         FLAC__ASSERT(0 != decoder->private_);
275         FLAC__ASSERT(0 != decoder->protected_);
276         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
277                 return false;
278         decoder->private_->error_callback = value;
279         return true;
280 }
281
282 OggFLAC_API FLAC__bool FLAC__file_decoder_set_client_data(FLAC__FileDecoder *decoder, void *value)
283 {
284         FLAC__ASSERT(0 != decoder);
285         FLAC__ASSERT(0 != decoder->private_);
286         FLAC__ASSERT(0 != decoder->protected_);
287         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
288                 return false;
289         decoder->private_->client_data = value;
290         return true;
291 }
292
293 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond(FLAC__FileDecoder *decoder, FLAC__MetadataType type)
294 {
295         FLAC__ASSERT(0 != decoder);
296         FLAC__ASSERT(0 != decoder->private_);
297         FLAC__ASSERT(0 != decoder->protected_);
298         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
299         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
300                 return false;
301         return FLAC__seekable_stream_decoder_set_metadata_respond(decoder->private_->seekable_stream_decoder, type);
302 }
303
304 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond_application(FLAC__FileDecoder *decoder, const FLAC__byte id[4])
305 {
306         FLAC__ASSERT(0 != decoder);
307         FLAC__ASSERT(0 != decoder->private_);
308         FLAC__ASSERT(0 != decoder->protected_);
309         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
310         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
311                 return false;
312         return FLAC__seekable_stream_decoder_set_metadata_respond_application(decoder->private_->seekable_stream_decoder, id);
313 }
314
315 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_respond_all(FLAC__FileDecoder *decoder)
316 {
317         FLAC__ASSERT(0 != decoder);
318         FLAC__ASSERT(0 != decoder->private_);
319         FLAC__ASSERT(0 != decoder->protected_);
320         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
321         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
322                 return false;
323         return FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder->private_->seekable_stream_decoder);
324 }
325
326 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore(FLAC__FileDecoder *decoder, FLAC__MetadataType type)
327 {
328         FLAC__ASSERT(0 != decoder);
329         FLAC__ASSERT(0 != decoder->private_);
330         FLAC__ASSERT(0 != decoder->protected_);
331         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
332         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
333                 return false;
334         return FLAC__seekable_stream_decoder_set_metadata_ignore(decoder->private_->seekable_stream_decoder, type);
335 }
336
337 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore_application(FLAC__FileDecoder *decoder, const FLAC__byte id[4])
338 {
339         FLAC__ASSERT(0 != decoder);
340         FLAC__ASSERT(0 != decoder->private_);
341         FLAC__ASSERT(0 != decoder->protected_);
342         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
343         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
344                 return false;
345         return FLAC__seekable_stream_decoder_set_metadata_ignore_application(decoder->private_->seekable_stream_decoder, id);
346 }
347
348 OggFLAC_API FLAC__bool FLAC__file_decoder_set_metadata_ignore_all(FLAC__FileDecoder *decoder)
349 {
350         FLAC__ASSERT(0 != decoder);
351         FLAC__ASSERT(0 != decoder->private_);
352         FLAC__ASSERT(0 != decoder->protected_);
353         FLAC__ASSERT(0 != decoder->private_->seekable_stream_decoder);
354         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
355                 return false;
356         return FLAC__seekable_stream_decoder_set_metadata_ignore_all(decoder->private_->seekable_stream_decoder);
357 }
358
359
360 OggFLAC_API FLAC__FileDecoderState FLAC__file_decoder_get_state(const FLAC__FileDecoder *decoder)
361 {
362         FLAC__ASSERT(0 != decoder);
363         FLAC__ASSERT(0 != decoder->protected_);
364         return decoder->protected_->state;
365 }
366
367 OggFLAC_API FLAC__SeekableStreamDecoderState FLAC__file_decoder_get_seekable_stream_decoder_state(const FLAC__FileDecoder *decoder)
368 {
369         FLAC__ASSERT(0 != decoder);
370         FLAC__ASSERT(0 != decoder->private_);
371         return FLAC__seekable_stream_decoder_get_state(decoder->private_->seekable_stream_decoder);
372 }
373
374 OggFLAC_API FLAC__StreamDecoderState FLAC__file_decoder_get_stream_decoder_state(const FLAC__FileDecoder *decoder)
375 {
376         FLAC__ASSERT(0 != decoder);
377         FLAC__ASSERT(0 != decoder->private_);
378         return FLAC__seekable_stream_decoder_get_stream_decoder_state(decoder->private_->seekable_stream_decoder);
379 }
380
381 OggFLAC_API FLAC__bool FLAC__file_decoder_get_md5_checking(const FLAC__FileDecoder *decoder)
382 {
383         FLAC__ASSERT(0 != decoder);
384         FLAC__ASSERT(0 != decoder->private_);
385         return FLAC__seekable_stream_decoder_get_md5_checking(decoder->private_->seekable_stream_decoder);
386 }
387
388 OggFLAC_API unsigned FLAC__file_decoder_get_channels(const FLAC__FileDecoder *decoder)
389 {
390         FLAC__ASSERT(0 != decoder);
391         FLAC__ASSERT(0 != decoder->private_);
392         return FLAC__seekable_stream_decoder_get_channels(decoder->private_->seekable_stream_decoder);
393 }
394
395 OggFLAC_API FLAC__ChannelAssignment FLAC__file_decoder_get_channel_assignment(const FLAC__FileDecoder *decoder)
396 {
397         FLAC__ASSERT(0 != decoder);
398         FLAC__ASSERT(0 != decoder->private_);
399         return FLAC__seekable_stream_decoder_get_channel_assignment(decoder->private_->seekable_stream_decoder);
400 }
401
402 OggFLAC_API unsigned FLAC__file_decoder_get_bits_per_sample(const FLAC__FileDecoder *decoder)
403 {
404         FLAC__ASSERT(0 != decoder);
405         FLAC__ASSERT(0 != decoder->private_);
406         return FLAC__seekable_stream_decoder_get_bits_per_sample(decoder->private_->seekable_stream_decoder);
407 }
408
409 OggFLAC_API unsigned FLAC__file_decoder_get_sample_rate(const FLAC__FileDecoder *decoder)
410 {
411         FLAC__ASSERT(0 != decoder);
412         FLAC__ASSERT(0 != decoder->private_);
413         return FLAC__seekable_stream_decoder_get_sample_rate(decoder->private_->seekable_stream_decoder);
414 }
415
416 OggFLAC_API unsigned FLAC__file_decoder_get_blocksize(const FLAC__FileDecoder *decoder)
417 {
418         FLAC__ASSERT(0 != decoder);
419         FLAC__ASSERT(0 != decoder->private_);
420         return FLAC__seekable_stream_decoder_get_blocksize(decoder->private_->seekable_stream_decoder);
421 }
422
423 OggFLAC_API FLAC__bool FLAC__file_decoder_process_single(FLAC__FileDecoder *decoder)
424 {
425         FLAC__bool ret;
426         FLAC__ASSERT(0 != decoder);
427
428         if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
429                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
430
431         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
432                 return true;
433
434         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
435
436         ret = FLAC__seekable_stream_decoder_process_single(decoder->private_->seekable_stream_decoder);
437         if(!ret)
438                 decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
439
440         return ret;
441 }
442
443 OggFLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_metadata(FLAC__FileDecoder *decoder)
444 {
445         FLAC__bool ret;
446         FLAC__ASSERT(0 != decoder);
447
448         if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
449                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
450
451         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
452                 return true;
453
454         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
455
456         ret = FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder->private_->seekable_stream_decoder);
457         if(!ret)
458                 decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
459
460         return ret;
461 }
462
463 OggFLAC_API FLAC__bool FLAC__file_decoder_process_until_end_of_file(FLAC__FileDecoder *decoder)
464 {
465         FLAC__bool ret;
466         FLAC__ASSERT(0 != decoder);
467
468         if(decoder->private_->seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
469                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
470
471         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
472                 return true;
473
474         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
475
476         ret = FLAC__seekable_stream_decoder_process_until_end_of_stream(decoder->private_->seekable_stream_decoder);
477         if(!ret)
478                 decoder->protected_->state = FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR;
479
480         return ret;
481 }
482
483 OggFLAC_API FLAC__bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, FLAC__uint64 sample)
484 {
485         FLAC__ASSERT(0 != decoder);
486         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK || decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE);
487
488         if(decoder->private_->filename == 0) { /* means the file is stdin... */
489                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
490                 return false;
491         }
492
493         if(!FLAC__seekable_stream_decoder_seek_absolute(decoder->private_->seekable_stream_decoder, sample)) {
494                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
495                 return false;
496         }
497         else {
498                 decoder->protected_->state = FLAC__FILE_DECODER_OK;
499                 return true;
500         }
501 }
502
503
504 /***********************************************************************
505  *
506  * Private class methods
507  *
508  ***********************************************************************/
509
510 void set_defaults_(FLAC__FileDecoder *decoder)
511 {
512         FLAC__ASSERT(0 != decoder);
513         FLAC__ASSERT(0 != decoder->private_);
514
515         decoder->private_->filename = 0;
516         decoder->private_->write_callback = 0;
517         decoder->private_->metadata_callback = 0;
518         decoder->private_->error_callback = 0;
519         decoder->private_->client_data = 0;
520 }
521
522 /*
523  * This will forcibly set stdin to binary mode (for OSes that require it)
524  */
525 FILE *get_binary_stdin_()
526 {
527         /* if something breaks here it is probably due to the presence or
528          * absence of an underscore before the identifiers 'setmode',
529          * 'fileno', and/or 'O_BINARY'; check your system header files.
530          */
531 #if defined _MSC_VER || defined __MINGW32__
532         _setmode(_fileno(stdin), _O_BINARY);
533 #elif defined __CYGWIN__
534         /* almost certainly not needed for any modern Cygwin, but let's be safe... */
535         setmode(_fileno(stdin), _O_BINARY);
536 #endif
537
538         return stdin;
539 }
540
541 FLAC__SeekableStreamDecoderReadStatus read_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
542 {
543         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
544         (void)decoder;
545
546         if(*bytes > 0) {
547                 size_t bytes_read = fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file);
548                 if(bytes_read == 0 && !feof(file_decoder->private_->file)) {
549                         return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
550                 }
551                 else {
552                         *bytes = (unsigned)bytes_read;
553                         return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
554                 }
555         }
556         else
557                 return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; /* abort to avoid a deadlock */
558 }
559
560 FLAC__SeekableStreamDecoderSeekStatus seek_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
561 {
562         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
563         (void)decoder;
564
565         if(fseek(file_decoder->private_->file, (long)absolute_byte_offset, SEEK_SET) < 0)
566                 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
567         else
568                 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
569 }
570
571 FLAC__SeekableStreamDecoderTellStatus tell_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
572 {
573         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
574         long pos;
575         (void)decoder;
576
577         if((pos = ftell(file_decoder->private_->file)) < 0)
578                 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
579         else {
580                 *absolute_byte_offset = (FLAC__uint64)pos;
581                 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
582         }
583 }
584
585 FLAC__SeekableStreamDecoderLengthStatus length_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
586 {
587         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
588         struct stat filestats;
589         (void)decoder;
590
591         if(0 == file_decoder->private_->filename || stat(file_decoder->private_->filename, &filestats) != 0)
592                 return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
593         else {
594                 *stream_length = (FLAC__uint64)filestats.st_size;
595                 return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
596         }
597 }
598
599 FLAC__bool eof_callback_(const FLAC__SeekableStreamDecoder *decoder, void *client_data)
600 {
601         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
602         (void)decoder;
603
604         return feof(file_decoder->private_->file);
605 }
606
607 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
608 {
609         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
610         (void)decoder;
611
612         return file_decoder->private_->write_callback(file_decoder, frame, buffer, file_decoder->private_->client_data);
613 }
614
615 void metadata_callback_(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
616 {
617         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
618         (void)decoder;
619
620         file_decoder->private_->metadata_callback(file_decoder, metadata, file_decoder->private_->client_data);
621 }
622
623 void error_callback_(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
624 {
625         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
626         (void)decoder;
627
628         file_decoder->private_->error_callback(file_decoder, status, file_decoder->private_->client_data);
629 }