fix tiny bug with filename setting
[flac.git] / src / libFLAC / file_decoder.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2000,2001  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 #include "FLAC/assert.h"
25 #include "protected/file_decoder.h"
26 #include "protected/stream_decoder.h"
27 #include "private/md5.h"
28
29 /***********************************************************************
30  *
31  * Private class method prototypes
32  *
33  ***********************************************************************/
34
35 static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
36 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
37 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
38 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
39 static FLAC__bool seek_to_absolute_sample_(FLAC__FileDecoder *decoder, long filesize, FLAC__uint64 target_sample);
40
41 /***********************************************************************
42  *
43  * Private class data
44  *
45  ***********************************************************************/
46
47 typedef struct FLAC__FileDecoderPrivate {
48         FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
49         void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
50         void (*error_callback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
51         void *client_data;
52         FILE *file;
53         char *filename; /* == NULL if stdin */
54         FLAC__StreamDecoder *stream_decoder;
55         struct MD5Context md5context;
56         FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
57         FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
58         /* the rest of these are only used for seeking: */
59         FLAC__StreamMetaData_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
60         const FLAC__StreamMetaData_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
61         FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
62         FLAC__uint64 target_sample;
63 } FLAC__FileDecoderPrivate;
64
65 /***********************************************************************
66  *
67  * Public static class data
68  *
69  ***********************************************************************/
70
71 const char *FLAC__FileDecoderStateString[] = {
72         "FLAC__FILE_DECODER_OK",
73         "FLAC__FILE_DECODER_SEEKING",
74         "FLAC__FILE_DECODER_END_OF_FILE",
75         "FLAC__FILE_DECODER_ERROR_OPENING_FILE",
76         "FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR",
77         "FLAC__FILE_DECODER_SEEK_ERROR",
78         "FLAC__FILE_DECODER_STREAM_ERROR",
79         "FLAC__FILE_DECODER_STREAM_DECODER_ERROR",
80         "FLAC__FILE_DECODER_ALREADY_INITIALIZED",
81         "FLAC__FILE_DECODER_INVALID_CALLBACK",
82         "FLAC__FILE_DECODER_UNINITIALIZED"
83 };
84
85 /***********************************************************************
86  *
87  * Class constructor/destructor
88  *
89  ***********************************************************************/
90
91 FLAC__FileDecoder *FLAC__file_decoder_new()
92 {
93         FLAC__FileDecoder *decoder;
94
95         FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
96
97         decoder = (FLAC__FileDecoder*)malloc(sizeof(FLAC__FileDecoder));
98         if(decoder == 0) {
99                 return 0;
100         }
101         decoder->protected_ = (FLAC__FileDecoderProtected*)malloc(sizeof(FLAC__FileDecoderProtected));
102         if(decoder->protected_ == 0) {
103                 free(decoder);
104                 return 0;
105         }
106         decoder->private_ = (FLAC__FileDecoderPrivate*)malloc(sizeof(FLAC__FileDecoderPrivate));
107         if(decoder->private_ == 0) {
108                 free(decoder->protected_);
109                 free(decoder);
110                 return 0;
111         }
112
113         decoder->protected_->state = FLAC__FILE_DECODER_UNINITIALIZED;
114
115         decoder->private_->filename = 0;
116         decoder->private_->write_callback = 0;
117         decoder->private_->metadata_callback = 0;
118         decoder->private_->error_callback = 0;
119         decoder->private_->client_data = 0;
120
121         return decoder;
122 }
123
124 void FLAC__file_decoder_delete(FLAC__FileDecoder *decoder)
125 {
126         FLAC__ASSERT(decoder != 0);
127         FLAC__ASSERT(decoder->protected_ != 0);
128         FLAC__ASSERT(decoder->private_ != 0);
129
130         free(decoder->private_);
131         free(decoder->protected_);
132         free(decoder);
133 }
134
135 /***********************************************************************
136  *
137  * Public class methods
138  *
139  ***********************************************************************/
140
141 FLAC__FileDecoderState FLAC__file_decoder_init(FLAC__FileDecoder *decoder)
142 {
143         FLAC__ASSERT(decoder != 0);
144
145         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
146                 return decoder->protected_->state = FLAC__FILE_DECODER_ALREADY_INITIALIZED;
147
148         decoder->protected_->state = FLAC__FILE_DECODER_OK;
149
150         if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
151                 return decoder->protected_->state = FLAC__FILE_DECODER_INVALID_CALLBACK;
152
153         decoder->private_->file = 0;
154         decoder->private_->stream_decoder = 0;
155         decoder->private_->seek_table = 0;
156
157         if(0 == decoder->private_->filename)
158                 decoder->private_->file = stdin;
159         else
160                 decoder->private_->file = fopen(decoder->private_->filename, "rb");
161
162         if(decoder->private_->file == 0)
163                 return decoder->protected_->state = FLAC__FILE_DECODER_ERROR_OPENING_FILE;
164
165         /* We initialize the MD5Context even though we may never use it.  This is
166          * because md5_checking may be turned on to start and then turned off if a
167          * seek occurs.  So we always init the context here and finalize it in
168          * FLAC__file_decoder_finish() to make sure things are always cleaned up
169          * properly.
170          */
171         MD5Init(&decoder->private_->md5context);
172
173         decoder->private_->stream_decoder = FLAC__stream_decoder_new();
174
175         FLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
176         FLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
177         FLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
178         FLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
179         FLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
180
181         if(FLAC__stream_decoder_init(decoder->private_->stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
182                 return decoder->protected_->state = FLAC__FILE_DECODER_STREAM_DECODER_ERROR;
183
184         return decoder->protected_->state;
185 }
186
187 FLAC__bool FLAC__file_decoder_finish(FLAC__FileDecoder *decoder)
188 {
189         FLAC__bool md5_failed = false;
190
191         FLAC__ASSERT(decoder != 0);
192         if(decoder->protected_->state == FLAC__FILE_DECODER_UNINITIALIZED)
193                 return true;
194         if(decoder->private_->file != 0 && decoder->private_->file != stdin)
195                 fclose(decoder->private_->file);
196         if(0 != decoder->private_->filename)
197                 free(decoder->private_->filename);
198         /* see the comment in FLAC__file_decoder_init() as to why we always
199          * call MD5Final()
200          */
201         MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
202         if(decoder->private_->stream_decoder != 0) {
203                 FLAC__stream_decoder_finish(decoder->private_->stream_decoder);
204                 FLAC__stream_decoder_delete(decoder->private_->stream_decoder);
205         }
206         if(decoder->protected_->md5_checking) {
207                 if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
208                         md5_failed = true;
209         }
210         decoder->protected_->state = FLAC__FILE_DECODER_UNINITIALIZED;
211         return !md5_failed;
212 }
213
214 FLAC__bool FLAC__file_decoder_set_md5_checking(const FLAC__FileDecoder *decoder, FLAC__bool value)
215 {
216         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
217                 return false;
218         decoder->protected_->md5_checking = value;
219         return true;
220 }
221
222 FLAC__bool FLAC__file_decoder_set_filename(const FLAC__FileDecoder *decoder, const char *value)
223 {
224         FLAC__ASSERT(value != 0);
225         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
226                 return false;
227         if(0 != decoder->private_->filename)
228                 free(decoder->private_->filename);
229         if(0 == strcmp(value, "-")) {
230                 decoder->private_->filename = 0;
231         }
232         else  {
233                 if(0 == (decoder->private_->filename = (char*)malloc(strlen(value)+1))) {
234                         decoder->protected_->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
235                         return false;
236                 }
237                 strcpy(decoder->private_->filename, value);
238         }
239         return true;
240 }
241
242 FLAC__bool FLAC__file_decoder_set_write_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderWriteStatus (*value)(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data))
243 {
244         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
245                 return false;
246         decoder->private_->write_callback = value;
247         return true;
248 }
249
250 FLAC__bool FLAC__file_decoder_set_metadata_callback(const FLAC__FileDecoder *decoder, void (*value)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data))
251 {
252         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
253                 return false;
254         decoder->private_->metadata_callback = value;
255         return true;
256 }
257
258 FLAC__bool FLAC__file_decoder_set_error_callback(const FLAC__FileDecoder *decoder, void (*value)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data))
259 {
260         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
261                 return false;
262         decoder->private_->error_callback = value;
263         return true;
264 }
265
266 FLAC__bool FLAC__file_decoder_set_client_data(const FLAC__FileDecoder *decoder, void *value)
267 {
268         if(decoder->protected_->state != FLAC__FILE_DECODER_UNINITIALIZED)
269                 return false;
270         decoder->private_->client_data = value;
271         return true;
272 }
273
274 FLAC__FileDecoderState FLAC__file_decoder_get_state(const FLAC__FileDecoder *decoder)
275 {
276         return decoder->protected_->state;
277 }
278
279 FLAC__bool FLAC__file_decoder_get_md5_checking(const FLAC__FileDecoder *decoder)
280 {
281         return decoder->protected_->md5_checking;
282 }
283
284 FLAC__bool FLAC__file_decoder_process_whole_file(FLAC__FileDecoder *decoder)
285 {
286         FLAC__bool ret;
287         FLAC__ASSERT(decoder != 0);
288
289         if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
290                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
291
292         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
293                 return true;
294
295         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
296
297         ret = FLAC__stream_decoder_process_whole_stream(decoder->private_->stream_decoder);
298         if(!ret)
299                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
300
301         return ret;
302 }
303
304 FLAC__bool FLAC__file_decoder_process_metadata(FLAC__FileDecoder *decoder)
305 {
306         FLAC__bool ret;
307         FLAC__ASSERT(decoder != 0);
308
309         if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
310                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
311
312         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
313                 return true;
314
315         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
316
317         ret = FLAC__stream_decoder_process_metadata(decoder->private_->stream_decoder);
318         if(!ret)
319                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
320
321         return ret;
322 }
323
324 FLAC__bool FLAC__file_decoder_process_one_frame(FLAC__FileDecoder *decoder)
325 {
326         FLAC__bool ret;
327         FLAC__ASSERT(decoder != 0);
328
329         if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
330                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
331
332         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
333                 return true;
334
335         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
336
337         ret = FLAC__stream_decoder_process_one_frame(decoder->private_->stream_decoder);
338         if(!ret)
339                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
340
341         return ret;
342 }
343
344 FLAC__bool FLAC__file_decoder_process_remaining_frames(FLAC__FileDecoder *decoder)
345 {
346         FLAC__bool ret;
347         FLAC__ASSERT(decoder != 0);
348
349         if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
350                 decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
351
352         if(decoder->protected_->state == FLAC__FILE_DECODER_END_OF_FILE)
353                 return true;
354
355         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
356
357         ret = FLAC__stream_decoder_process_remaining_frames(decoder->private_->stream_decoder);
358         if(!ret)
359                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
360
361         return ret;
362 }
363
364 /***********************************************************************
365  *
366  * Private class methods
367  *
368  ***********************************************************************/
369
370 FLAC__bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, FLAC__uint64 sample)
371 {
372         long filesize;
373         struct stat filestats;
374
375         FLAC__ASSERT(decoder != 0);
376         FLAC__ASSERT(decoder->protected_->state == FLAC__FILE_DECODER_OK);
377
378         if(decoder->private_->filename == 0) { /* means the file is stdin... */
379                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
380                 return false;
381         }
382
383         decoder->protected_->state = FLAC__FILE_DECODER_SEEKING;
384
385         /* turn off md5 checking if a seek is attempted */
386         decoder->protected_->md5_checking = false;
387
388         if(!FLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
389                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
390                 return false;
391         }
392         /* get the file length */
393         if(stat(decoder->private_->filename, &filestats) != 0) {
394                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
395                 return false;
396         }
397         filesize = filestats.st_size;
398         /* rewind */
399         if(0 != fseek(decoder->private_->file, 0, SEEK_SET)) {
400                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
401                 return false;
402         }
403         if(!FLAC__stream_decoder_process_metadata(decoder->private_->stream_decoder)) {
404                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
405                 return false;
406         }
407         if(sample > decoder->private_->stream_info.total_samples) {
408                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
409                 return false;
410         }
411
412         return seek_to_absolute_sample_(decoder, filesize, sample);
413 }
414
415 FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
416 {
417         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
418         (void)decoder;
419         if(feof(file_decoder->private_->file)) {
420                 file_decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
421                 return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
422         }
423         else if(*bytes > 0) {
424                 size_t bytes_read = fread(buffer, sizeof(FLAC__byte), *bytes, file_decoder->private_->file);
425                 if(bytes_read == 0) {
426                         if(feof(file_decoder->private_->file)) {
427                                 file_decoder->protected_->state = FLAC__FILE_DECODER_END_OF_FILE;
428                                 return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
429                         }
430                         else
431                                 return FLAC__STREAM_DECODER_READ_ABORT;
432                 }
433                 else {
434                         *bytes = (unsigned)bytes_read;
435                         return FLAC__STREAM_DECODER_READ_CONTINUE;
436                 }
437         }
438         else
439                 return FLAC__STREAM_DECODER_READ_ABORT; /* abort to avoid a deadlock */
440 }
441
442 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
443 {
444         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
445         (void)decoder;
446
447         if(file_decoder->protected_->state == FLAC__FILE_DECODER_SEEKING) {
448                 FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
449                 FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
450                 FLAC__uint64 target_sample = file_decoder->private_->target_sample;
451
452                 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
453
454                 file_decoder->private_->last_frame = *frame; /* save the frame */
455                 if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
456                         unsigned delta = (unsigned)(target_sample - this_frame_sample);
457                         /* kick out of seek mode */
458                         file_decoder->protected_->state = FLAC__FILE_DECODER_OK;
459                         /* shift out the samples before target_sample */
460                         if(delta > 0) {
461                                 unsigned channel;
462                                 const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
463                                 for(channel = 0; channel < frame->header.channels; channel++)
464                                         newbuffer[channel] = buffer[channel] + delta;
465                                 file_decoder->private_->last_frame.header.blocksize -= delta;
466                                 file_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
467                                 /* write the relevant samples */
468                                 return file_decoder->private_->write_callback(file_decoder, &file_decoder->private_->last_frame, newbuffer, file_decoder->private_->client_data);
469                         }
470                         else {
471                                 /* write the relevant samples */
472                                 return file_decoder->private_->write_callback(file_decoder, frame, buffer, file_decoder->private_->client_data);
473                         }
474                 }
475                 else {
476                         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
477                 }
478         }
479         else {
480                 if(file_decoder->protected_->md5_checking) {
481                         if(!FLAC__MD5Accumulate(&file_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
482                                 return FLAC__STREAM_DECODER_WRITE_ABORT;
483                 }
484                 return file_decoder->private_->write_callback(file_decoder, frame, buffer, file_decoder->private_->client_data);
485         }
486 }
487
488 void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
489 {
490         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
491         (void)decoder;
492
493         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
494                 file_decoder->private_->stream_info = metadata->data.stream_info;
495                 /* save the MD5 signature for comparison later */
496                 memcpy(file_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
497                 if(0 == memcmp(file_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
498                         file_decoder->protected_->md5_checking = false;
499         }
500         else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
501                 file_decoder->private_->seek_table = &metadata->data.seek_table;
502         }
503
504         if(file_decoder->protected_->state != FLAC__FILE_DECODER_SEEKING)
505                 file_decoder->private_->metadata_callback(file_decoder, metadata, file_decoder->private_->client_data);
506 }
507
508 void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
509 {
510         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
511         (void)decoder;
512
513         if(file_decoder->protected_->state != FLAC__FILE_DECODER_SEEKING)
514                 file_decoder->private_->error_callback(file_decoder, status, file_decoder->private_->client_data);
515 }
516
517 FLAC__bool seek_to_absolute_sample_(FLAC__FileDecoder *decoder, long filesize, FLAC__uint64 target_sample)
518 {
519         /* @@@ we should really change long to off_t and start using lseek(); with fseek() we have the 2GB file limit. */
520         long first_frame_offset, lower_bound, upper_bound, pos = -1, last_pos = -1;
521         int i, lower_seek_point = -1, upper_seek_point = -1;
522         unsigned approx_bytes_per_frame;
523         FLAC__uint64 last_frame_sample = 0xffffffffffffffff;
524         FLAC__bool needs_seek;
525         const FLAC__bool is_variable_blocksize_stream = (decoder->private_->stream_info.min_blocksize != decoder->private_->stream_info.max_blocksize);
526
527         /* we are just guessing here, but we want to guess high, not low */
528         if(decoder->private_->stream_info.max_framesize > 0) {
529                 approx_bytes_per_frame = decoder->private_->stream_info.max_framesize;
530         }
531         else if(!is_variable_blocksize_stream) {
532                 /* note there are no () around 'decoder->private_->stream_info.bits_per_sample/8' to keep precision up since it's an integer calulation */
533                 approx_bytes_per_frame = decoder->private_->stream_info.min_blocksize * decoder->private_->stream_info.channels * decoder->private_->stream_info.bits_per_sample/8 + 64;
534         }
535         else
536                 approx_bytes_per_frame = 1152 * decoder->private_->stream_info.channels * decoder->private_->stream_info.bits_per_sample/8 + 64;
537
538         /*
539          * The file pointer is currently at the first frame plus any read
540          * ahead data, so first we get the file pointer, then subtract
541          * uncomsumed bytes to get the position of the first frame in the
542          * file.
543          */
544         if(-1 == (first_frame_offset = ftell(decoder->private_->file))) {
545                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
546                 return false;
547         }
548         first_frame_offset -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder);
549         FLAC__ASSERT(first_frame_offset >= 0);
550
551         /*
552          * First, we set an upper and lower bound on where in the
553          * file we will search.  For now we assume the worst case
554          * scenario, which is our best guess at the beginning of
555          * the first and last frames.
556          */
557         lower_bound = first_frame_offset;
558
559         /* calc the upper_bound, beyond which we never want to seek */
560         if(decoder->private_->stream_info.max_framesize > 0)
561                 upper_bound = filesize - (decoder->private_->stream_info.max_framesize + 128 + 2); /* 128 for a possible ID3V1 tag, 2 for indexing differences */
562         else
563                 upper_bound = filesize - ((decoder->private_->stream_info.channels * decoder->private_->stream_info.bits_per_sample * FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2);
564
565         /*
566          * Now we refine the bounds if we have a seektable with
567          * suitable points.  Note that according to the spec they
568          * must be ordered by ascending sample number.
569          */
570         if(0 != decoder->private_->seek_table) {
571                 /* find the closest seek point <= target_sample, if it exists */
572                 for(i = (int)decoder->private_->seek_table->num_points - 1; i >= 0; i--) {
573                         if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number <= target_sample)
574                                 break;
575                 }
576                 if(i >= 0) { /* i.e. we found a suitable seek point... */
577                         lower_bound = first_frame_offset + (long)decoder->private_->seek_table->points[i].stream_offset;
578                         lower_seek_point = i;
579                 }
580
581                 /* find the closest seek point > target_sample, if it exists */
582                 for(i = 0; i < (int)decoder->private_->seek_table->num_points; i++) {
583                         if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number > target_sample)
584                                 break;
585                 }
586                 if(i < (int)decoder->private_->seek_table->num_points) { /* i.e. we found a suitable seek point... */
587                         upper_bound = first_frame_offset + (long)decoder->private_->seek_table->points[i].stream_offset;
588                         upper_seek_point = i;
589                 }
590         }
591
592         /*
593          * Now guess at where within those bounds our target
594          * sample will be.
595          */
596         if(lower_seek_point >= 0) {
597                 /* first see if our sample is within a few frames of the lower seekpoint */
598                 if(decoder->private_->seek_table->points[lower_seek_point].sample_number <= target_sample && target_sample < decoder->private_->seek_table->points[lower_seek_point].sample_number + (decoder->private_->seek_table->points[lower_seek_point].frame_samples * 4)) {
599                         pos = lower_bound;
600                 }
601                 else if(upper_seek_point >= 0) {
602                         const FLAC__uint64 target_offset = target_sample - decoder->private_->seek_table->points[lower_seek_point].sample_number;
603                         const FLAC__uint64 range_samples = decoder->private_->seek_table->points[upper_seek_point].sample_number - decoder->private_->seek_table->points[lower_seek_point].sample_number;
604                         const long range_bytes = upper_bound - lower_bound;
605 #ifdef _MSC_VER
606                         /* with VC++ you have to spoon feed it the casting */
607                         pos = lower_bound + (long)((double)(FLAC__int64)target_offset / (double)(FLAC__int64)range_samples * (double)(range_bytes-1)) - approx_bytes_per_frame;
608 #else
609                         pos = lower_bound + (long)((double)target_offset / (double)range_samples * (double)(range_bytes-1)) - approx_bytes_per_frame;
610 #endif
611                 }
612         }
613         if(pos < 0) {
614                 /* We need to use the metadata and the filelength to estimate the position of the frame with the correct sample */
615 #ifdef _MSC_VER
616                 /* with VC++ you have to spoon feed it the casting */
617                 pos = first_frame_offset + (long)((double)(FLAC__int64)target_sample / (double)(FLAC__int64)decoder->private_->stream_info.total_samples * (double)(filesize-first_frame_offset-1)) - approx_bytes_per_frame;
618 #else
619                 pos = first_frame_offset + (long)((double)target_sample / (double)decoder->private_->stream_info.total_samples * (double)(filesize-first_frame_offset-1)) - approx_bytes_per_frame;
620 #endif
621         }
622
623         /* clip the position to the bounds, lower bound takes precedence */
624         if(pos >= upper_bound)
625                 pos = upper_bound-1;
626         if(pos < lower_bound)
627                 pos = lower_bound;
628         needs_seek = true;
629
630         decoder->private_->target_sample = target_sample;
631         while(1) {
632                 if(needs_seek) {
633                         if(-1 == fseek(decoder->private_->file, pos, SEEK_SET)) {
634                                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
635                                 return false;
636                         }
637                         if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
638                                 decoder->protected_->state = FLAC__FILE_DECODER_STREAM_ERROR;
639                                 return false;
640                         }
641                 }
642                 if(!FLAC__stream_decoder_process_one_frame(decoder->private_->stream_decoder)) {
643                         decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
644                         return false;
645                 }
646                 /* our write callback will change the state when it gets to the target frame */
647                 if(decoder->protected_->state != FLAC__FILE_DECODER_SEEKING) {
648                         break;
649                 }
650                 else { /* we need to narrow the search */
651                         FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
652                         FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
653                         if(this_frame_sample == last_frame_sample) {
654                                 /* our last move backwards wasn't big enough */
655                                 pos -= (last_pos - pos);
656                                 needs_seek = true;
657                         }
658                         else {
659                                 if(target_sample < this_frame_sample) {
660                                         last_pos = pos;
661                                         approx_bytes_per_frame = decoder->private_->last_frame.header.blocksize * decoder->private_->last_frame.header.channels * decoder->private_->last_frame.header.bits_per_sample/8 + 64;
662                                         pos -= approx_bytes_per_frame;
663                                         needs_seek = true;
664                                 }
665                                 else { /* target_sample >= this_frame_sample + this frame's blocksize */
666                                         last_pos = pos;
667                                         if(-1 == (pos = ftell(decoder->private_->file))) {
668                                                 decoder->protected_->state = FLAC__FILE_DECODER_SEEK_ERROR;
669                                                 return false;
670                                         }
671                                         pos -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder);
672                                         needs_seek = false;
673                                 }
674                         }
675                         if(pos < lower_bound)
676                                 pos = lower_bound;
677                         last_frame_sample = this_frame_sample;
678                 }
679         }
680
681         return true;
682 }