switch malloc+memset(0) to calloc()
[flac.git] / src / libOggFLAC / stream_decoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <stdlib.h> /* for calloc() */
21 #include <string.h> /* for memset() */
22 #include "ogg/ogg.h"
23 #include "FLAC/assert.h"
24 #include "protected/stream_decoder.h"
25
26 #ifdef min
27 #undef min
28 #endif
29 #define min(x,y) ((x)<(y)?(x):(y))
30
31 /***********************************************************************
32  *
33  * Private class method prototypes
34  *
35  ***********************************************************************/
36
37 static void set_defaults_(OggFLAC__StreamDecoder *decoder);
38 static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
39 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
40 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
41 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
42
43
44 /***********************************************************************
45  *
46  * Private class data
47  *
48  ***********************************************************************/
49
50 typedef struct OggFLAC__StreamDecoderPrivate {
51         OggFLAC__StreamDecoderReadCallback read_callback;
52         OggFLAC__StreamDecoderWriteCallback write_callback;
53         OggFLAC__StreamDecoderMetadataCallback metadata_callback;
54         OggFLAC__StreamDecoderErrorCallback error_callback;
55         void *client_data;
56         FLAC__StreamDecoder *FLAC_stream_decoder;
57         struct {
58                 ogg_stream_state stream_state;
59                 ogg_sync_state sync_state;
60                 FLAC__bool need_serial_number;
61         } ogg;
62 } OggFLAC__StreamDecoderPrivate;
63
64 /***********************************************************************
65  *
66  * Public static class data
67  *
68  ***********************************************************************/
69
70 const OggFLAC_API char * const OggFLAC__StreamDecoderStateString[] = {
71         "OggFLAC__STREAM_DECODER_OK",
72         "OggFLAC__STREAM_DECODER_OGG_ERROR",
73         "OggFLAC__STREAM_DECODER_READ_ERROR",
74         "OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR",
75         "OggFLAC__STREAM_DECODER_INVALID_CALLBACK",
76         "OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
77         "OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED",
78         "OggFLAC__STREAM_DECODER_UNINITIALIZED"
79 };
80
81
82 /***********************************************************************
83  *
84  * Class constructor/destructor
85  *
86  ***********************************************************************/
87 OggFLAC_API OggFLAC__StreamDecoder *OggFLAC__stream_decoder_new()
88 {
89         OggFLAC__StreamDecoder *decoder;
90
91         decoder = (OggFLAC__StreamDecoder*)calloc(1, sizeof(OggFLAC__StreamDecoder));
92         if(decoder == 0) {
93                 return 0;
94         }
95
96         decoder->protected_ = (OggFLAC__StreamDecoderProtected*)calloc(1, sizeof(OggFLAC__StreamDecoderProtected));
97         if(decoder->protected_ == 0) {
98                 free(decoder);
99                 return 0;
100         }
101
102         decoder->private_ = (OggFLAC__StreamDecoderPrivate*)calloc(1, sizeof(OggFLAC__StreamDecoderPrivate));
103         if(decoder->private_ == 0) {
104                 free(decoder->protected_);
105                 free(decoder);
106                 return 0;
107         }
108
109         decoder->private_->FLAC_stream_decoder = FLAC__stream_decoder_new();
110         if(0 == decoder->private_->FLAC_stream_decoder) {
111                 free(decoder->private_);
112                 free(decoder->protected_);
113                 free(decoder);
114                 return 0;
115         }
116
117         set_defaults_(decoder);
118
119         decoder->protected_->state = OggFLAC__STREAM_DECODER_UNINITIALIZED;
120
121         return decoder;
122 }
123
124 OggFLAC_API void OggFLAC__stream_decoder_delete(OggFLAC__StreamDecoder *decoder)
125 {
126         FLAC__ASSERT(0 != decoder);
127         FLAC__ASSERT(0 != decoder->protected_);
128         FLAC__ASSERT(0 != decoder->private_);
129         FLAC__ASSERT(0 != decoder->private_->FLAC_stream_decoder);
130
131         OggFLAC__stream_decoder_finish(decoder);
132
133         FLAC__stream_decoder_delete(decoder->private_->FLAC_stream_decoder);
134
135         free(decoder->private_);
136         free(decoder->protected_);
137         free(decoder);
138 }
139
140 /***********************************************************************
141  *
142  * Public class methods
143  *
144  ***********************************************************************/
145
146 OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_init(OggFLAC__StreamDecoder *decoder)
147 {
148         FLAC__ASSERT(0 != decoder);
149
150         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
151                 return decoder->protected_->state = OggFLAC__STREAM_DECODER_ALREADY_INITIALIZED;
152
153         if(0 == decoder->private_->read_callback || 0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
154                 return decoder->protected_->state = OggFLAC__STREAM_DECODER_INVALID_CALLBACK;
155
156         decoder->private_->ogg.need_serial_number = decoder->protected_->use_first_serial_number;
157         /* we will determine the serial number later if necessary */
158         if(ogg_stream_init(&decoder->private_->ogg.stream_state, decoder->protected_->serial_number) != 0)
159                 return decoder->protected_->state = OggFLAC__STREAM_DECODER_OGG_ERROR;
160
161         if(ogg_sync_init(&decoder->private_->ogg.sync_state) != 0)
162                 return decoder->protected_->state = OggFLAC__STREAM_DECODER_OGG_ERROR;
163
164         FLAC__stream_decoder_set_read_callback(decoder->private_->FLAC_stream_decoder, read_callback_);
165         FLAC__stream_decoder_set_write_callback(decoder->private_->FLAC_stream_decoder, write_callback_);
166         FLAC__stream_decoder_set_metadata_callback(decoder->private_->FLAC_stream_decoder, metadata_callback_);
167         FLAC__stream_decoder_set_error_callback(decoder->private_->FLAC_stream_decoder, error_callback_);
168         FLAC__stream_decoder_set_client_data(decoder->private_->FLAC_stream_decoder, decoder);
169
170         if(FLAC__stream_decoder_init(decoder->private_->FLAC_stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
171                 return decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
172
173         return decoder->protected_->state = OggFLAC__STREAM_DECODER_OK;
174 }
175
176 OggFLAC_API void OggFLAC__stream_decoder_finish(OggFLAC__StreamDecoder *decoder)
177 {
178         FLAC__ASSERT(0 != decoder);
179         FLAC__ASSERT(0 != decoder->private_);
180         FLAC__ASSERT(0 != decoder->protected_);
181
182         if(decoder->protected_->state == OggFLAC__STREAM_DECODER_UNINITIALIZED)
183                 return;
184
185         FLAC__ASSERT(0 != decoder->private_->FLAC_stream_decoder);
186
187         FLAC__stream_decoder_finish(decoder->private_->FLAC_stream_decoder);
188
189         (void)ogg_sync_clear(&decoder->private_->ogg.sync_state);
190         (void)ogg_stream_clear(&decoder->private_->ogg.stream_state);
191
192         set_defaults_(decoder);
193
194         decoder->protected_->state = OggFLAC__STREAM_DECODER_UNINITIALIZED;
195 }
196
197 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_read_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderReadCallback value)
198 {
199         FLAC__ASSERT(0 != decoder);
200         FLAC__ASSERT(0 != decoder->private_);
201         FLAC__ASSERT(0 != decoder->protected_);
202         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
203                 return false;
204         decoder->private_->read_callback = value;
205         return true;
206 }
207
208 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_write_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderWriteCallback value)
209 {
210         FLAC__ASSERT(0 != decoder);
211         FLAC__ASSERT(0 != decoder->private_);
212         FLAC__ASSERT(0 != decoder->protected_);
213         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
214                 return false;
215         decoder->private_->write_callback = value;
216         return true;
217 }
218
219 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderMetadataCallback value)
220 {
221         FLAC__ASSERT(0 != decoder);
222         FLAC__ASSERT(0 != decoder->private_);
223         FLAC__ASSERT(0 != decoder->protected_);
224         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
225                 return false;
226         decoder->private_->metadata_callback = value;
227         return true;
228 }
229
230 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_error_callback(OggFLAC__StreamDecoder *decoder, OggFLAC__StreamDecoderErrorCallback value)
231 {
232         FLAC__ASSERT(0 != decoder);
233         FLAC__ASSERT(0 != decoder->private_);
234         FLAC__ASSERT(0 != decoder->protected_);
235         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
236                 return false;
237         decoder->private_->error_callback = value;
238         return true;
239 }
240
241 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_client_data(OggFLAC__StreamDecoder *decoder, void *value)
242 {
243         FLAC__ASSERT(0 != decoder);
244         FLAC__ASSERT(0 != decoder->private_);
245         FLAC__ASSERT(0 != decoder->protected_);
246         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
247                 return false;
248         decoder->private_->client_data = value;
249         return true;
250 }
251
252 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_serial_number(OggFLAC__StreamDecoder *decoder, long value)
253 {
254         FLAC__ASSERT(0 != decoder);
255         FLAC__ASSERT(0 != decoder->private_);
256         FLAC__ASSERT(0 != decoder->protected_);
257         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
258                 return false;
259         decoder->protected_->use_first_serial_number = false;
260         decoder->protected_->serial_number = value;
261         return true;
262 }
263
264 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond(OggFLAC__StreamDecoder *decoder, FLAC__MetadataType type)
265 {
266         FLAC__ASSERT(0 != decoder);
267         FLAC__ASSERT(0 != decoder->private_);
268         FLAC__ASSERT(0 != decoder->protected_);
269         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
270                 return false;
271         return FLAC__stream_decoder_set_metadata_respond(decoder->private_->FLAC_stream_decoder, type);
272 }
273
274 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_application(OggFLAC__StreamDecoder *decoder, const FLAC__byte id[4])
275 {
276         FLAC__ASSERT(0 != decoder);
277         FLAC__ASSERT(0 != decoder->private_);
278         FLAC__ASSERT(0 != decoder->protected_);
279         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
280                 return false;
281         return FLAC__stream_decoder_set_metadata_respond_application(decoder->private_->FLAC_stream_decoder, id);
282 }
283
284 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_respond_all(OggFLAC__StreamDecoder *decoder)
285 {
286         FLAC__ASSERT(0 != decoder);
287         FLAC__ASSERT(0 != decoder->private_);
288         FLAC__ASSERT(0 != decoder->protected_);
289         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
290                 return false;
291         return FLAC__stream_decoder_set_metadata_respond_all(decoder->private_->FLAC_stream_decoder);
292 }
293
294 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore(OggFLAC__StreamDecoder *decoder, FLAC__MetadataType type)
295 {
296         FLAC__ASSERT(0 != decoder);
297         FLAC__ASSERT(0 != decoder->private_);
298         FLAC__ASSERT(0 != decoder->protected_);
299         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
300                 return false;
301         return FLAC__stream_decoder_set_metadata_ignore(decoder->private_->FLAC_stream_decoder, type);
302 }
303
304 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_application(OggFLAC__StreamDecoder *decoder, const FLAC__byte id[4])
305 {
306         FLAC__ASSERT(0 != decoder);
307         FLAC__ASSERT(0 != decoder->private_);
308         FLAC__ASSERT(0 != decoder->protected_);
309         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
310                 return false;
311         return FLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->FLAC_stream_decoder, id);
312 }
313
314 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_set_metadata_ignore_all(OggFLAC__StreamDecoder *decoder)
315 {
316         FLAC__ASSERT(0 != decoder);
317         FLAC__ASSERT(0 != decoder->private_);
318         FLAC__ASSERT(0 != decoder->protected_);
319         if(decoder->protected_->state != OggFLAC__STREAM_DECODER_UNINITIALIZED)
320                 return false;
321         return FLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->FLAC_stream_decoder);
322 }
323
324 OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__stream_decoder_get_state(const OggFLAC__StreamDecoder *decoder)
325 {
326         FLAC__ASSERT(0 != decoder);
327         FLAC__ASSERT(0 != decoder->protected_);
328         return decoder->protected_->state;
329 }
330
331 OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__StreamDecoder *decoder)
332 {
333         FLAC__ASSERT(0 != decoder);
334         FLAC__ASSERT(0 != decoder->private_);
335         return FLAC__stream_decoder_get_state(decoder->private_->FLAC_stream_decoder);
336 }
337
338 OggFLAC_API unsigned OggFLAC__stream_decoder_get_channels(const OggFLAC__StreamDecoder *decoder)
339 {
340         FLAC__ASSERT(0 != decoder);
341         FLAC__ASSERT(0 != decoder->private_);
342         return FLAC__stream_decoder_get_channels(decoder->private_->FLAC_stream_decoder);
343 }
344
345 OggFLAC_API FLAC__ChannelAssignment OggFLAC__stream_decoder_get_channel_assignment(const OggFLAC__StreamDecoder *decoder)
346 {
347         FLAC__ASSERT(0 != decoder);
348         FLAC__ASSERT(0 != decoder->private_);
349         return FLAC__stream_decoder_get_channel_assignment(decoder->private_->FLAC_stream_decoder);
350 }
351
352 OggFLAC_API unsigned OggFLAC__stream_decoder_get_bits_per_sample(const OggFLAC__StreamDecoder *decoder)
353 {
354         FLAC__ASSERT(0 != decoder);
355         FLAC__ASSERT(0 != decoder->private_);
356         return FLAC__stream_decoder_get_bits_per_sample(decoder->private_->FLAC_stream_decoder);
357 }
358
359 OggFLAC_API unsigned OggFLAC__stream_decoder_get_sample_rate(const OggFLAC__StreamDecoder *decoder)
360 {
361         FLAC__ASSERT(0 != decoder);
362         FLAC__ASSERT(0 != decoder->private_);
363         return FLAC__stream_decoder_get_sample_rate(decoder->private_->FLAC_stream_decoder);
364 }
365
366 OggFLAC_API unsigned OggFLAC__stream_decoder_get_blocksize(const OggFLAC__StreamDecoder *decoder)
367 {
368         FLAC__ASSERT(0 != decoder);
369         FLAC__ASSERT(0 != decoder->private_);
370         return FLAC__stream_decoder_get_blocksize(decoder->private_->FLAC_stream_decoder);
371 }
372
373 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_flush(OggFLAC__StreamDecoder *decoder)
374 {
375         FLAC__ASSERT(0 != decoder);
376         FLAC__ASSERT(0 != decoder->private_);
377         FLAC__ASSERT(0 != decoder->protected_);
378
379         (void)ogg_sync_clear(&decoder->private_->ogg.sync_state);
380
381         if(!FLAC__stream_decoder_flush(decoder->private_->FLAC_stream_decoder)) {
382                 decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
383                 return false;
384         }
385
386         decoder->protected_->state = OggFLAC__STREAM_DECODER_OK;
387
388         return true;
389 }
390
391 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_reset(OggFLAC__StreamDecoder *decoder)
392 {
393         FLAC__ASSERT(0 != decoder);
394         FLAC__ASSERT(0 != decoder->private_);
395         FLAC__ASSERT(0 != decoder->protected_);
396
397         if(!OggFLAC__stream_decoder_flush(decoder)) {
398                 decoder->protected_->state = OggFLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
399                 return false;
400         }
401
402         if(!FLAC__stream_decoder_reset(decoder->private_->FLAC_stream_decoder)) {
403                 decoder->protected_->state = OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR;
404                 return false;
405         }
406
407         decoder->protected_->state = OggFLAC__STREAM_DECODER_OK;
408
409         return true;
410 }
411
412 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_single(OggFLAC__StreamDecoder *decoder)
413 {
414         FLAC__ASSERT(0 != decoder);
415         FLAC__ASSERT(0 != decoder->private_);
416         return FLAC__stream_decoder_process_single(decoder->private_->FLAC_stream_decoder);
417 }
418
419 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_metadata(OggFLAC__StreamDecoder *decoder)
420 {
421         FLAC__ASSERT(0 != decoder);
422         FLAC__ASSERT(0 != decoder->private_);
423         return FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->FLAC_stream_decoder);
424 }
425
426 OggFLAC_API FLAC__bool OggFLAC__stream_decoder_process_until_end_of_stream(OggFLAC__StreamDecoder *decoder)
427 {
428         FLAC__ASSERT(0 != decoder);
429         FLAC__ASSERT(0 != decoder->private_);
430         return FLAC__stream_decoder_process_until_end_of_stream(decoder->private_->FLAC_stream_decoder);
431 }
432
433
434 /***********************************************************************
435  *
436  * Private class methods
437  *
438  ***********************************************************************/
439
440 void set_defaults_(OggFLAC__StreamDecoder *decoder)
441 {
442         decoder->private_->read_callback = 0;
443         decoder->private_->write_callback = 0;
444         decoder->private_->metadata_callback = 0;
445         decoder->private_->error_callback = 0;
446         decoder->private_->client_data = 0;
447         decoder->protected_->use_first_serial_number = true;
448 }
449
450 FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *unused, FLAC__byte buffer[], unsigned *bytes, void *client_data)
451 {
452         static const unsigned OGG_BYTES_CHUNK = 8192;
453         OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
454         unsigned ogg_bytes_to_read, ogg_bytes_read;
455         ogg_page page;
456         char *oggbuf;
457
458         (void)unused;
459
460         /*
461          * We have to be careful not to read in more than the
462          * FLAC__StreamDecoder says it has room for.  We know
463          * that the size of the decoded data must be no more
464          * than the encoded data we will read.
465          */
466         ogg_bytes_to_read = min(*bytes, OGG_BYTES_CHUNK);
467         oggbuf = ogg_sync_buffer(&decoder->private_->ogg.sync_state, ogg_bytes_to_read);
468
469         if(decoder->private_->read_callback(decoder, oggbuf, &ogg_bytes_to_read, decoder->private_->client_data) != FLAC__STREAM_DECODER_READ_STATUS_CONTINUE) {
470                 decoder->protected_->state = OggFLAC__STREAM_DECODER_READ_ERROR;
471                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
472         }
473         ogg_bytes_read = ogg_bytes_to_read;
474
475         if(ogg_sync_wrote(&decoder->private_->ogg.sync_state, ogg_bytes_read) < 0) {
476                 decoder->protected_->state = OggFLAC__STREAM_DECODER_READ_ERROR;
477                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
478         }
479
480         *bytes = 0;
481         while(ogg_sync_pageout(&decoder->private_->ogg.sync_state, &page) == 1) {
482                 /* grab the serial number if necessary */
483                 if(decoder->private_->ogg.need_serial_number) {
484                         decoder->private_->ogg.stream_state.serialno = decoder->protected_->serial_number = ogg_page_serialno(&page);
485                         decoder->private_->ogg.need_serial_number = false;
486                 }
487                 if(ogg_stream_pagein(&decoder->private_->ogg.stream_state, &page) == 0) {
488                         ogg_packet packet;
489
490                         while(ogg_stream_packetout(&decoder->private_->ogg.stream_state, &packet) == 1) {
491                                 memcpy(buffer, packet.packet, packet.bytes);
492                                 *bytes += packet.bytes;
493                                 buffer += packet.bytes;
494                         }
495                 } else {
496                         decoder->protected_->state = OggFLAC__STREAM_DECODER_READ_ERROR;
497                         return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
498                 }
499         }
500
501         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
502 }
503
504 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *unused, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
505 {
506         OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
507         (void)unused;
508         return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
509 }
510
511 void metadata_callback_(const FLAC__StreamDecoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
512 {
513         OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
514         (void)unused;
515         decoder->private_->metadata_callback(decoder, metadata, decoder->private_->client_data);
516 }
517
518 void error_callback_(const FLAC__StreamDecoder *unused, FLAC__StreamDecoderErrorStatus status, void *client_data)
519 {
520         OggFLAC__StreamDecoder *decoder = (OggFLAC__StreamDecoder*)client_data;
521         (void)unused;
522         decoder->private_->error_callback(decoder, status, decoder->private_->client_data);
523 }