~ubuntu-branches/ubuntu/raring/flac/raring

« back to all changes in this revision

Viewing changes to src/libOggFLAC/seekable_stream_decoder.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2007-05-29 22:56:36 UTC
  • mto: (8.1.1 lenny)
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20070529225636-p8lkii0r0kp50pns
Tags: upstream-1.1.4
ImportĀ upstreamĀ versionĀ 1.1.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* libOggFLAC - Free Lossless Audio Codec + Ogg library
2
 
 * Copyright (C) 2002,2003,2004,2005  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
 
}