add 2206 to copyright notice
[platform/upstream/flac.git] / src / libOggFLAC / seekable_stream_decoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the Xiph.org Foundation nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h> /* for calloc() */
34 #include <string.h> /* for memcpy()/memcmp() */
35 #include "FLAC/assert.h"
36 #include "protected/seekable_stream_decoder.h"
37 #include "protected/stream_decoder.h"
38 #include "../libFLAC/include/private/float.h" /* @@@ ugly hack, but how else to do?  we need to reuse the float formats but don't want to expose it */
39 #include "../libFLAC/include/private/md5.h" /* @@@ ugly hack, but how else to do?  we need to reuse the md5 code but don't want to expose it */
40
41 /***********************************************************************
42  *
43  * Private class method prototypes
44  *
45  ***********************************************************************/
46
47 static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder);
48 static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
49 static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
50 static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
51 static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
52 static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
53
54 /***********************************************************************
55  *
56  * Private class data
57  *
58  ***********************************************************************/
59
60 typedef struct OggFLAC__SeekableStreamDecoderPrivate {
61         OggFLAC__SeekableStreamDecoderReadCallback read_callback;
62         OggFLAC__SeekableStreamDecoderSeekCallback seek_callback;
63         OggFLAC__SeekableStreamDecoderTellCallback tell_callback;
64         OggFLAC__SeekableStreamDecoderLengthCallback length_callback;
65         OggFLAC__SeekableStreamDecoderEofCallback eof_callback;
66         OggFLAC__SeekableStreamDecoderWriteCallback write_callback;
67         OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
68         OggFLAC__SeekableStreamDecoderErrorCallback error_callback;
69         void *client_data;
70         OggFLAC__StreamDecoder *stream_decoder;
71         FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */
72         struct FLAC__MD5Context md5context;
73         FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
74         FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
75         /* the rest of these are only used for seeking: */
76         FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
77         const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
78         /* Since we always want to see the STREAMINFO and SEEK_TABLE blocks at this level, we need some extra flags to keep track of whether they should be passed on up through the metadata_callback */
79         FLAC__bool ignore_stream_info_block;
80         FLAC__bool ignore_seek_table_block;
81         FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
82         FLAC__uint64 target_sample;
83         FLAC__bool got_a_frame; /* hack needed in seek routine to check when process_single() actually writes a frame */
84 } OggFLAC__SeekableStreamDecoderPrivate;
85
86 /***********************************************************************
87  *
88  * Public static class data
89  *
90  ***********************************************************************/
91
92 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[] = {
93         "OggFLAC__SEEKABLE_STREAM_DECODER_OK",
94         "OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING",
95         "OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
96         "OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
97         "OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
98         "OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
99         "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
100         "OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
101         "OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
102         "OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
103 };
104
105 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[] = {
106         "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
107         "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
108 };
109
110 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[] = {
111         "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
112         "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
113 };
114
115 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[] = {
116         "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
117         "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
118 };
119
120 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[] = {
121         "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
122         "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
123 };
124
125
126 /***********************************************************************
127  *
128  * Class constructor/destructor
129  *
130  ***********************************************************************/
131
132 OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new()
133 {
134         OggFLAC__SeekableStreamDecoder *decoder;
135
136         FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
137
138         decoder = (OggFLAC__SeekableStreamDecoder*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoder));
139         if(decoder == 0) {
140                 return 0;
141         }
142
143         decoder->protected_ = (OggFLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderProtected));
144         if(decoder->protected_ == 0) {
145                 free(decoder);
146                 return 0;
147         }
148
149         decoder->private_ = (OggFLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderPrivate));
150         if(decoder->private_ == 0) {
151                 free(decoder->protected_);
152                 free(decoder);
153                 return 0;
154         }
155
156         decoder->private_->stream_decoder = OggFLAC__stream_decoder_new();
157         if(0 == decoder->private_->stream_decoder) {
158                 free(decoder->private_);
159                 free(decoder->protected_);
160                 free(decoder);
161                 return 0;
162         }
163
164         set_defaults_(decoder);
165
166         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
167
168         return decoder;
169 }
170
171 OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStreamDecoder *decoder)
172 {
173         FLAC__ASSERT(0 != decoder);
174         FLAC__ASSERT(0 != decoder->protected_);
175         FLAC__ASSERT(0 != decoder->private_);
176         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
177
178         (void)OggFLAC__seekable_stream_decoder_finish(decoder);
179
180         OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder);
181
182         free(decoder->private_);
183         free(decoder->protected_);
184         free(decoder);
185 }
186
187 /***********************************************************************
188  *
189  * Public class methods
190  *
191  ***********************************************************************/
192
193 OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_init(OggFLAC__SeekableStreamDecoder *decoder)
194 {
195         FLAC__ASSERT(0 != decoder);
196
197         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
198                 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
199
200         if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
201                 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
202
203         if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
204                 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
205
206         decoder->private_->seek_table = 0;
207
208         decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
209
210         /* We initialize the FLAC__MD5Context even though we may never use it.  This
211          * is because md5 checking may be turned on to start and then turned off if
212          * a seek occurs.  So we always init the context here and finalize it in
213          * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
214          * cleaned up properly.
215          */
216         FLAC__MD5Init(&decoder->private_->md5context);
217
218         OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
219         OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
220         OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
221         OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
222         OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
223
224         /* We always want to see these blocks.  Whether or not we pass them up
225          * through the metadata callback will be determined by flags set in our
226          * implementation of ..._set_metadata_respond/ignore...()
227          */
228         OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
229         OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
230
231         if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK)
232                 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
233
234         return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
235 }
236
237 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder)
238 {
239         FLAC__bool md5_failed = false;
240
241         FLAC__ASSERT(0 != decoder);
242         FLAC__ASSERT(0 != decoder->private_);
243         FLAC__ASSERT(0 != decoder->protected_);
244
245         if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
246                 return true;
247
248         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
249
250         /* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we
251          * always call FLAC__MD5Final()
252          */
253         FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
254
255         OggFLAC__stream_decoder_finish(decoder->private_->stream_decoder);
256
257         if(decoder->private_->do_md5_checking) {
258                 if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
259                         md5_failed = true;
260         }
261
262         set_defaults_(decoder);
263
264         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
265
266         return !md5_failed;
267 }
268
269 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
270 {
271         FLAC__ASSERT(0 != decoder);
272         FLAC__ASSERT(0 != decoder->protected_);
273         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
274                 return false;
275         decoder->protected_->md5_checking = value;
276         return true;
277 }
278
279 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value)
280 {
281         FLAC__ASSERT(0 != decoder);
282         FLAC__ASSERT(0 != decoder->private_);
283         FLAC__ASSERT(0 != decoder->protected_);
284         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
285                 return false;
286         decoder->private_->read_callback = value;
287         return true;
288 }
289
290 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_seek_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderSeekCallback value)
291 {
292         FLAC__ASSERT(0 != decoder);
293         FLAC__ASSERT(0 != decoder->private_);
294         FLAC__ASSERT(0 != decoder->protected_);
295         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
296                 return false;
297         decoder->private_->seek_callback = value;
298         return true;
299 }
300
301 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_tell_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderTellCallback value)
302 {
303         FLAC__ASSERT(0 != decoder);
304         FLAC__ASSERT(0 != decoder->private_);
305         FLAC__ASSERT(0 != decoder->protected_);
306         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
307                 return false;
308         decoder->private_->tell_callback = value;
309         return true;
310 }
311
312 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_length_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderLengthCallback value)
313 {
314         FLAC__ASSERT(0 != decoder);
315         FLAC__ASSERT(0 != decoder->private_);
316         FLAC__ASSERT(0 != decoder->protected_);
317         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
318                 return false;
319         decoder->private_->length_callback = value;
320         return true;
321 }
322
323 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_eof_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderEofCallback value)
324 {
325         FLAC__ASSERT(0 != decoder);
326         FLAC__ASSERT(0 != decoder->private_);
327         FLAC__ASSERT(0 != decoder->protected_);
328         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
329                 return false;
330         decoder->private_->eof_callback = value;
331         return true;
332 }
333
334 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_write_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderWriteCallback value)
335 {
336         FLAC__ASSERT(0 != decoder);
337         FLAC__ASSERT(0 != decoder->private_);
338         FLAC__ASSERT(0 != decoder->protected_);
339         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
340                 return false;
341         decoder->private_->write_callback = value;
342         return true;
343 }
344
345 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderMetadataCallback value)
346 {
347         FLAC__ASSERT(0 != decoder);
348         FLAC__ASSERT(0 != decoder->private_);
349         FLAC__ASSERT(0 != decoder->protected_);
350         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
351                 return false;
352         decoder->private_->metadata_callback = value;
353         return true;
354 }
355
356 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_error_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderErrorCallback value)
357 {
358         FLAC__ASSERT(0 != decoder);
359         FLAC__ASSERT(0 != decoder->private_);
360         FLAC__ASSERT(0 != decoder->protected_);
361         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
362                 return false;
363         decoder->private_->error_callback = value;
364         return true;
365 }
366
367 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_client_data(OggFLAC__SeekableStreamDecoder *decoder, void *value)
368 {
369         FLAC__ASSERT(0 != decoder);
370         FLAC__ASSERT(0 != decoder->private_);
371         FLAC__ASSERT(0 != decoder->protected_);
372         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
373                 return false;
374         decoder->private_->client_data = value;
375         return true;
376 }
377
378 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLAC__SeekableStreamDecoder *decoder, long value)
379 {
380         FLAC__ASSERT(0 != decoder);
381         FLAC__ASSERT(0 != decoder->private_);
382         FLAC__ASSERT(0 != decoder->protected_);
383         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
384                 return false;
385         OggFLAC__stream_decoder_set_serial_number(decoder->private_->stream_decoder, value);
386         return true;
387 }
388
389 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
390 {
391         FLAC__ASSERT(0 != decoder);
392         FLAC__ASSERT(0 != decoder->private_);
393         FLAC__ASSERT(0 != decoder->protected_);
394         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
395         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
396                 return false;
397         if(type == FLAC__METADATA_TYPE_STREAMINFO)
398                 decoder->private_->ignore_stream_info_block = false;
399         else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
400                 decoder->private_->ignore_seek_table_block = false;
401         return OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
402 }
403
404 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
405 {
406         FLAC__ASSERT(0 != decoder);
407         FLAC__ASSERT(0 != decoder->private_);
408         FLAC__ASSERT(0 != decoder->protected_);
409         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
410         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
411                 return false;
412         return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
413 }
414
415 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder)
416 {
417         FLAC__ASSERT(0 != decoder);
418         FLAC__ASSERT(0 != decoder->private_);
419         FLAC__ASSERT(0 != decoder->protected_);
420         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
421         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
422                 return false;
423         decoder->private_->ignore_stream_info_block = false;
424         decoder->private_->ignore_seek_table_block = false;
425         return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
426 }
427
428 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
429 {
430         FLAC__ASSERT(0 != decoder);
431         FLAC__ASSERT(0 != decoder->private_);
432         FLAC__ASSERT(0 != decoder->protected_);
433         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
434         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
435                 return false;
436         if(type == FLAC__METADATA_TYPE_STREAMINFO) {
437                 decoder->private_->ignore_stream_info_block = true;
438                 return true;
439         }
440         else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
441                 decoder->private_->ignore_seek_table_block = true;
442                 return true;
443         }
444         else
445                 return OggFLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type);
446 }
447
448 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
449 {
450         FLAC__ASSERT(0 != decoder);
451         FLAC__ASSERT(0 != decoder->private_);
452         FLAC__ASSERT(0 != decoder->protected_);
453         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
454         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
455                 return false;
456         return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id);
457 }
458
459 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder)
460 {
461         FLAC__ASSERT(0 != decoder);
462         FLAC__ASSERT(0 != decoder->private_);
463         FLAC__ASSERT(0 != decoder->protected_);
464         FLAC__ASSERT(0 != decoder->private_->stream_decoder);
465         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
466                 return false;
467         decoder->private_->ignore_stream_info_block = true;
468         decoder->private_->ignore_seek_table_block = true;
469         return
470                 OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) &&
471                 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) &&
472                 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
473 }
474
475 OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder)
476 {
477         FLAC__ASSERT(0 != decoder);
478         FLAC__ASSERT(0 != decoder->protected_);
479         return decoder->protected_->state;
480 }
481
482 OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
483 {
484         FLAC__ASSERT(0 != decoder);
485         FLAC__ASSERT(0 != decoder->private_);
486         return OggFLAC__stream_decoder_get_state(decoder->private_->stream_decoder);
487 }
488
489 OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
490 {
491         FLAC__ASSERT(0 != decoder);
492         FLAC__ASSERT(0 != decoder->private_);
493         return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->stream_decoder);
494 }
495
496 OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder)
497 {
498         if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR)
499                 return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state];
500         else
501                 return OggFLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder);
502 }
503
504 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder)
505 {
506         FLAC__ASSERT(0 != decoder);
507         FLAC__ASSERT(0 != decoder->protected_);
508         return decoder->protected_->md5_checking;
509 }
510
511 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder)
512 {
513         FLAC__ASSERT(0 != decoder);
514         FLAC__ASSERT(0 != decoder->private_);
515         return OggFLAC__stream_decoder_get_channels(decoder->private_->stream_decoder);
516 }
517
518 OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder)
519 {
520         FLAC__ASSERT(0 != decoder);
521         FLAC__ASSERT(0 != decoder->private_);
522         return OggFLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder);
523 }
524
525 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder)
526 {
527         FLAC__ASSERT(0 != decoder);
528         FLAC__ASSERT(0 != decoder->private_);
529         return OggFLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder);
530 }
531
532 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder)
533 {
534         FLAC__ASSERT(0 != decoder);
535         FLAC__ASSERT(0 != decoder->private_);
536         return OggFLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder);
537 }
538
539 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder)
540 {
541         FLAC__ASSERT(0 != decoder);
542         FLAC__ASSERT(0 != decoder->private_);
543         return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder);
544 }
545
546 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder)
547 {
548         FLAC__ASSERT(0 != decoder);
549         FLAC__ASSERT(0 != decoder->private_);
550         FLAC__ASSERT(0 != decoder->protected_);
551
552         decoder->private_->do_md5_checking = false;
553
554         if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
555                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
556                 return false;
557         }
558
559         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
560
561         return true;
562 }
563
564 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableStreamDecoder *decoder)
565 {
566         FLAC__ASSERT(0 != decoder);
567         FLAC__ASSERT(0 != decoder->private_);
568         FLAC__ASSERT(0 != decoder->protected_);
569
570         if(!OggFLAC__seekable_stream_decoder_flush(decoder)) {
571                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
572                 return false;
573         }
574
575         if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
576                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
577                 return false;
578         }
579
580         decoder->private_->seek_table = 0;
581
582         decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
583
584         /* We initialize the FLAC__MD5Context even though we may never use it.  This
585          * is because md5 checking may be turned on to start and then turned off if
586          * a seek occurs.  So we always init the context here and finalize it in
587          * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
588          * cleaned up properly.
589          */
590         FLAC__MD5Init(&decoder->private_->md5context);
591
592         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
593
594         return true;
595 }
596
597 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__SeekableStreamDecoder *decoder)
598 {
599         FLAC__bool ret;
600         FLAC__ASSERT(0 != decoder);
601
602         if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
603                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
604
605         if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
606                 return true;
607
608         FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
609
610         ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder);
611         if(!ret)
612                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
613
614         return ret;
615 }
616
617 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(OggFLAC__SeekableStreamDecoder *decoder)
618 {
619         FLAC__bool ret;
620         FLAC__ASSERT(0 != decoder);
621
622         if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
623                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
624
625         if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
626                 return true;
627
628         FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
629
630         ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder);
631         if(!ret)
632                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
633
634         return ret;
635 }
636
637 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_stream(OggFLAC__SeekableStreamDecoder *decoder)
638 {
639         FLAC__bool ret;
640         FLAC__ASSERT(0 != decoder);
641
642         if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
643                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
644
645         if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
646                 return true;
647
648         FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
649
650         ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder);
651         if(!ret)
652                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
653
654         return ret;
655 }
656
657 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
658 {
659         FLAC__uint64 length;
660
661         FLAC__ASSERT(0 != decoder);
662         FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);
663
664         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING;
665
666         /* turn off md5 checking if a seek is attempted */
667         decoder->private_->do_md5_checking = false;
668
669         if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
670                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
671                 return false;
672         }
673         /* get the file length */
674         if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {
675                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
676                 return false;
677         }
678         /* rewind */
679         if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
680                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
681                 return false;
682         }
683         if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {
684                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
685                 return false;
686         }
687         if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) {
688                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
689                 return false;
690         }
691
692         return seek_to_absolute_sample_(decoder, length, sample);
693 }
694
695 /***********************************************************************
696  *
697  * Private class methods
698  *
699  ***********************************************************************/
700
701 void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder)
702 {
703         decoder->private_->read_callback = 0;
704         decoder->private_->seek_callback = 0;
705         decoder->private_->tell_callback = 0;
706         decoder->private_->length_callback = 0;
707         decoder->private_->eof_callback = 0;
708         decoder->private_->write_callback = 0;
709         decoder->private_->metadata_callback = 0;
710         decoder->private_->error_callback = 0;
711         decoder->private_->client_data = 0;
712         /* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
713         decoder->private_->ignore_stream_info_block = false;
714         decoder->private_->ignore_seek_table_block = true;
715
716         decoder->protected_->md5_checking = false;
717 }
718
719 FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
720 {
721         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
722         (void)decoder;
723         if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
724                 *bytes = 0;
725 #if 0
726                 /*@@@@@@ we used to do this: */
727                 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
728                 /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
729 #endif
730                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
731         }
732         else if(*bytes > 0) {
733                 if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {
734                         seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
735                         return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
736                 }
737                 if(*bytes == 0) {
738                         if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
739 #if 0
740                                 /*@@@@@@ we used to do this: */
741                                 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
742                                 /* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
743 #endif
744                                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
745                         }
746                         else
747                                 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
748                 }
749                 else {
750                         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
751                 }
752         }
753         else
754                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
755 }
756
757 FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
758 {
759         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
760         (void)decoder;
761
762         if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
763                 FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
764                 FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
765                 FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
766
767                 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
768
769                 seekable_stream_decoder->private_->got_a_frame = true;
770                 seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
771                 if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
772                         unsigned delta = (unsigned)(target_sample - this_frame_sample);
773                         /* kick out of seek mode */
774                         seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
775                         /* shift out the samples before target_sample */
776                         if(delta > 0) {
777                                 unsigned channel;
778                                 const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
779                                 for(channel = 0; channel < frame->header.channels; channel++)
780                                         newbuffer[channel] = buffer[channel] + delta;
781                                 seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
782                                 seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
783                                 /* write the relevant samples */
784                                 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
785                         }
786                         else {
787                                 /* write the relevant samples */
788                                 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
789                         }
790                 }
791                 else {
792                         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
793                 }
794         }
795         else {
796                 if(seekable_stream_decoder->private_->do_md5_checking) {
797                         if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
798                                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
799                 }
800                 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
801         }
802 }
803
804 void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
805 {
806         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
807         (void)decoder;
808
809         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
810                 seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
811                 /* save the MD5 signature for comparison later */
812                 memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
813                 if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
814                         seekable_stream_decoder->private_->do_md5_checking = false;
815         }
816         else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
817                 seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
818         }
819
820         if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
821                 FLAC__bool ignore_block = false;
822                 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
823                         ignore_block = true;
824                 else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
825                         ignore_block = true;
826                 if(!ignore_block)
827                         seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
828         }
829 }
830
831 void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
832 {
833         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
834         (void)decoder;
835
836         if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
837                 seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
838 }
839
840 FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
841 {
842         FLAC__uint64 left_pos = 0, right_pos = stream_length;
843         FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
844         FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
845         FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
846         FLAC__bool did_a_seek;
847         unsigned iteration = 0;
848
849         /* In the first iterations, we will calculate the target byte position 
850          * by the distance from the target sample to left_sample and
851          * right_sample (let's call it "proportional search").  After that, we
852          * will switch to binary search.
853          */
854         unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
855
856         /* We will switch to a linear search once our current sample is less
857          * that this number of samples ahead of the target sample
858          */
859         static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
860
861         /* If the total number of samples is unknown, use a large value and
862          * increase 'iteration' to force binary search immediately.
863          */
864         if(right_sample == 0) {
865                 right_sample = (FLAC__uint64)(-1);
866                 BINARY_SEARCH_AFTER_ITERATION = 0;
867         }
868
869         decoder->private_->target_sample = target_sample;
870         for( ; ; iteration++) {
871                 if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
872                         if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
873                                 pos = (right_pos + left_pos) / 2;
874                         }
875                         else {
876 #ifndef FLAC__INTEGER_ONLY_LIBRARY
877 #if defined _MSC_VER || defined __MINGW32__
878                                 /* with MSVC you have to spoon feed it the casting */
879                                 pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos));
880 #else
881                                 pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
882 #endif
883 #else
884                                 /* a little less accurate: */
885                                 if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
886                                         pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
887                                 else /* @@@ WATCHOUT, ~2TB limit */
888                                         pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
889 #endif
890                                 /* @@@ TODO: might want to limit pos to some distance
891                                  * before EOF, to make sure we land before the last frame,
892                                  * thereby getting a this_fram_sample and so having a better
893                                  * estimate.  this would also mostly (or totally if we could
894                                  * be sure to land before the last frame) avoid the
895                                  * end-of-stream case we have to check later.
896                                  */
897                         }
898
899                         /* physical seek */
900                         if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
901                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
902                                 return false;
903                         }
904                         if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
905                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
906                                 return false;
907                         }
908                         did_a_seek = true;
909                 }
910                 else
911                         did_a_seek = false;
912
913                 decoder->private_->got_a_frame = false;
914                 if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
915                         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
916                         return false;
917                 }
918                 if(!decoder->private_->got_a_frame) {
919                         if(did_a_seek) {
920                                 /* this can happen if we seek to a point after the last frame; we drop
921                                  * to binary search right away in this case to avoid any wasted
922                                  * iterations of proportional search.
923                                  */
924                                 right_pos = pos;
925                                 BINARY_SEARCH_AFTER_ITERATION = 0;
926                         }
927                         else {
928                                 /* this can probably only happen if total_samples is unknown and the
929                                  * target_sample is past the end of the stream
930                                  */
931                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
932                                 return false;
933                         }
934                 }
935                 /* our write callback will change the state when it gets to the target frame */
936                 else if(
937                         decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING &&
938                         decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
939                 ) {
940                         break;
941                 }
942                 else {
943                         this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
944                         FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
945
946                         if (did_a_seek) {
947                                 if (this_frame_sample <= target_sample) {
948                                         /* The 'equal' case should not happen, since
949                                          * OggFLAC__stream_decoder_process_single()
950                                          * should recognize that it has hit the
951                                          * target sample and we would exit through
952                                          * the 'break' above.
953                                          */
954                                         FLAC__ASSERT(this_frame_sample != target_sample);
955
956                                         left_sample = this_frame_sample;
957                                         /* sanity check to avoid infinite loop */
958                                         if (left_pos == pos) {
959                                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
960                                                 return false;
961                                         }
962                                         left_pos = pos;
963                                 }
964                                 else if(this_frame_sample > target_sample) {
965                                         right_sample = this_frame_sample;
966                                         /* sanity check to avoid infinite loop */
967                                         if (right_pos == pos) {
968                                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
969                                                 return false;
970                                         }
971                                         right_pos = pos;
972                                 }
973                         }
974                 }
975         }
976
977         return true;
978 }