finished integerized flavor of library; sections with floating point are either ...
[platform/upstream/flac.git] / src / libOggFLAC / seekable_stream_decoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002,2003,2004  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                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
726         }
727         else if(*bytes > 0) {
728                 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) {
729                         seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
730                         return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
731                 }
732                 if(*bytes == 0) {
733                         if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
734                                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
735                         }
736                         else
737                                 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
738                 }
739                 else {
740                         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
741                 }
742         }
743         else
744                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
745 }
746
747 FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
748 {
749         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
750         (void)decoder;
751
752         if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
753                 FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
754                 FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
755                 FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
756
757                 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
758
759                 seekable_stream_decoder->private_->got_a_frame = true;
760                 seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
761                 if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
762                         unsigned delta = (unsigned)(target_sample - this_frame_sample);
763                         /* kick out of seek mode */
764                         seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
765                         /* shift out the samples before target_sample */
766                         if(delta > 0) {
767                                 unsigned channel;
768                                 const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
769                                 for(channel = 0; channel < frame->header.channels; channel++)
770                                         newbuffer[channel] = buffer[channel] + delta;
771                                 seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
772                                 seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
773                                 /* write the relevant samples */
774                                 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
775                         }
776                         else {
777                                 /* write the relevant samples */
778                                 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
779                         }
780                 }
781                 else {
782                         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
783                 }
784         }
785         else {
786                 if(seekable_stream_decoder->private_->do_md5_checking) {
787                         if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
788                                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
789                 }
790                 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
791         }
792 }
793
794 void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
795 {
796         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
797         (void)decoder;
798
799         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
800                 seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
801                 /* save the MD5 signature for comparison later */
802                 memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
803                 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))
804                         seekable_stream_decoder->private_->do_md5_checking = false;
805         }
806         else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
807                 seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
808         }
809
810         if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
811                 FLAC__bool ignore_block = false;
812                 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
813                         ignore_block = true;
814                 else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
815                         ignore_block = true;
816                 if(!ignore_block)
817                         seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
818         }
819 }
820
821 void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
822 {
823         OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
824         (void)decoder;
825
826         if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
827                 seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
828 }
829
830 FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
831 {
832         FLAC__uint64 left_pos = 0, right_pos = stream_length;
833         FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
834         FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
835         FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
836         FLAC__bool did_a_seek;
837         unsigned iteration = 0;
838
839         /* In the first iterations, we will calculate the target byte position 
840          * by the distance from the target sample to left_sample and
841          * right_sample (let's call it "proportional search").  After that, we
842          * will switch to binary search.
843          */
844         unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
845
846         /* We will switch to a linear search once our current sample is less
847          * that this number of samples ahead of the target sample
848          */
849         static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
850
851         /* If the total number of samples is unknown, use a large value and
852          * increase 'iteration' to force binary search immediately.
853          */
854         if(right_sample == 0) {
855                 right_sample = (FLAC__uint64)(-1);
856                 BINARY_SEARCH_AFTER_ITERATION = 0;
857         }
858
859         decoder->private_->target_sample = target_sample;
860         for( ; ; iteration++) {
861                 if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
862                         if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
863                                 pos = (right_pos + left_pos) / 2;
864                         }
865                         else {
866 #ifndef FLAC__INTEGER_ONLY_LIBRARY
867 #if defined _MSC_VER || defined __MINGW32__
868                                 /* with MSVC you have to spoon feed it the casting */
869                                 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));
870 #else
871                                 pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
872 #endif
873 #else
874                                 /* a little less accurate: */
875                                 if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
876                                         pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
877                                 else /* @@@ WATCHOUT, ~2TB limit */
878                                         pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
879 #endif
880                                 /* @@@ TODO: might want to limit pos to some distance
881                                  * before EOF, to make sure we land before the last frame,
882                                  * thereby getting a this_fram_sample and so having a better
883                                  * estimate.  this would also mostly (or totally if we could
884                                  * be sure to land before the last frame) avoid the
885                                  * end-of-stream case we have to check later.
886                                  */
887                         }
888
889                         /* physical seek */
890                         if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
891                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
892                                 return false;
893                         }
894                         if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
895                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
896                                 return false;
897                         }
898                         did_a_seek = true;
899                 }
900                 else
901                         did_a_seek = false;
902
903                 decoder->private_->got_a_frame = false;
904                 if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
905                         decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
906                         return false;
907                 }
908                 if(!decoder->private_->got_a_frame) {
909                         if(did_a_seek) {
910                                 /* this can happen if we seek to a point after the last frame; we drop
911                                  * to binary search right away in this case to avoid any wasted
912                                  * iterations of proportional search.
913                                  */
914                                 right_pos = pos;
915                                 BINARY_SEARCH_AFTER_ITERATION = 0;
916                         }
917                         else {
918                                 /* this can probably only happen if total_samples is unknown and the
919                                  * target_sample is past the end of the stream
920                                  */
921                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
922                                 return false;
923                         }
924                 }
925                 /* our write callback will change the state when it gets to the target frame */
926                 else if(
927                         decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING &&
928                         decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
929                 ) {
930                         break;
931                 }
932                 else {
933                         this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
934                         FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
935
936                         if (did_a_seek) {
937                                 if (this_frame_sample <= target_sample) {
938                                         /* The 'equal' case should not happen, since
939                                          * OggFLAC__stream_decoder_process_single()
940                                          * should recognize that it has hit the
941                                          * target sample and we would exit through
942                                          * the 'break' above.
943                                          */
944                                         FLAC__ASSERT(this_frame_sample != target_sample);
945
946                                         left_sample = this_frame_sample;
947                                         /* sanity check to avoid infinite loop */
948                                         if (left_pos == pos) {
949                                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
950                                                 return false;
951                                         }
952                                         left_pos = pos;
953                                 }
954                                 else if(this_frame_sample > target_sample) {
955                                         right_sample = this_frame_sample;
956                                         /* sanity check to avoid infinite loop */
957                                         if (right_pos == pos) {
958                                                 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
959                                                 return false;
960                                         }
961                                         right_pos = pos;
962                                 }
963                         }
964                 }
965         }
966
967         return true;
968 }