new seekable stream encoder and file encoder layers, not fully implemented yet
[platform/upstream/flac.git] / src / libFLAC / seekable_stream_encoder.c
1 /* libFLAC - Free Lossless Audio Codec 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 <stdio.h>
21 #include <stdlib.h> /* for malloc() */
22 #include <string.h> /* for memcpy() */
23 #include "FLAC/assert.h"
24 #include "protected/seekable_stream_encoder.h"
25 #include "protected/stream_encoder.h"
26
27 /***********************************************************************
28  *
29  * Private class method prototypes
30  *
31  ***********************************************************************/
32
33 static void set_defaults_(FLAC__SeekableStreamEncoder *encoder);
34 static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
35 static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
36
37 /***********************************************************************
38  *
39  * Private class data
40  *
41  ***********************************************************************/
42
43 typedef struct FLAC__SeekableStreamEncoderPrivate {
44         FILE *file;
45         char *filename;
46         FLAC__StreamEncoder *stream_encoder;
47 } FLAC__SeekableStreamEncoderPrivate;
48
49 /***********************************************************************
50  *
51  * Public static class data
52  *
53  ***********************************************************************/
54
55 const char * const FLAC__SeekableStreamEncoderStateString[] = {
56         "FLAC__SEEKABLE_STREAM_ENCODER_OK",
57         "FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR",
58         "FLAC__SEEKABLE_STREAM_ENCODER_ERROR_OPENING_FILE",
59         "FLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
60         "FLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED",
61         "FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED"
62 };
63
64
65 /***********************************************************************
66  *
67  * Class constructor/destructor
68  *
69  ***********************************************************************/
70 FLAC__SeekableStreamEncoder *FLAC__seekable_stream_encoder_new()
71 {
72         FLAC__SeekableStreamEncoder *encoder;
73
74         FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
75
76         encoder = (FLAC__SeekableStreamEncoder*)malloc(sizeof(FLAC__SeekableStreamEncoder));
77         if(encoder == 0) {
78                 return 0;
79         }
80         encoder->protected_ = (FLAC__SeekableStreamEncoderProtected*)malloc(sizeof(FLAC__SeekableStreamEncoderProtected));
81         if(encoder->protected_ == 0) {
82                 free(encoder);
83                 return 0;
84         }
85         encoder->private_ = (FLAC__SeekableStreamEncoderPrivate*)malloc(sizeof(FLAC__SeekableStreamEncoderPrivate));
86         if(encoder->private_ == 0) {
87                 free(encoder->protected_);
88                 free(encoder);
89                 return 0;
90         }
91
92         encoder->private_->stream_encoder = FLAC__stream_encoder_new();
93
94         if(0 == encoder->private_->stream_encoder) {
95                 free(encoder->private_);
96                 free(encoder->protected_);
97                 free(encoder);
98                 return 0;
99         }
100
101         set_defaults_(encoder);
102
103         encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
104
105         return encoder;
106 }
107
108 void FLAC__seekable_stream_encoder_delete(FLAC__SeekableStreamEncoder *encoder)
109 {
110         FLAC__ASSERT(0 != encoder);
111         FLAC__ASSERT(0 != encoder->protected_);
112         FLAC__ASSERT(0 != encoder->private_);
113         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
114
115         (void)FLAC__seekable_stream_encoder_finish(encoder);
116
117         FLAC__stream_encoder_delete(encoder->private_->stream_encoder);
118
119         free(encoder->private_);
120         free(encoder->protected_);
121         free(encoder);
122 }
123
124 /***********************************************************************
125  *
126  * Public class methods
127  *
128  ***********************************************************************/
129
130 FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_init(FLAC__SeekableStreamEncoder *encoder)
131 {
132         FLAC__ASSERT(0 != encoder);
133
134         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
135                 return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED;
136
137         if(0 == encoder->private_->filename)
138                 return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_NO_FILENAME;
139
140         encoder->private_->file = fopen(encoder->private_->filename, "wb");
141
142         if(encoder->private_->file == 0)
143                 return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_ERROR_OPENING_FILE;
144
145         FLAC__stream_encoder_set_write_callback(encoder->private_->stream_encoder, write_callback_);
146         FLAC__stream_encoder_set_metadata_callback(encoder->private_->stream_encoder, metadata_callback_);
147         FLAC__stream_encoder_set_client_data(encoder->private_->stream_encoder, encoder);
148
149         if(FLAC__stream_encoder_init(encoder->private_->stream_encoder) != FLAC__STREAM_ENCODER_OK)
150                 return encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR;
151
152         return decoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_OK;
153 }
154
155 void FLAC__seekable_stream_encoder_finish(FLAC__SeekableStreamEncoder *encoder)
156 {
157         FLAC__ASSERT(0 != encoder);
158
159         if(encoder->protected_->state == FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
160                 return;
161
162         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
163
164         if(0 != encoder->private_->file) {
165                 fclose(encoder->private_->file);
166                 encoder->private_->file = 0;
167         }
168
169         if(0 != encoder->private_->filename) {
170                 free(encoder->private_->filename);
171                 encoder->private_->filename = 0;
172         }
173
174         set_defaults_(encoder);
175
176         encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
177
178         return FLAC__stream_encoder_finish(encoder->private_->stream_encoder);
179 }
180
181 FLAC__bool FLAC__seekable_stream_encoder_set_streamable_subset(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
182 {
183         FLAC__ASSERT(0 != encoder);
184         FLAC__ASSERT(0 != encoder->private_);
185         FLAC__ASSERT(0 != encoder->protected_);
186         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
187         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
188                 return false;
189         return FLAC__stream_encoder_set_streamable_subset(encoder->private_->stream_encoder, value);
190 }
191
192 FLAC__bool FLAC__seekable_stream_encoder_set_do_mid_side_stereo(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
193 {
194         FLAC__ASSERT(0 != encoder);
195         FLAC__ASSERT(0 != encoder->private_);
196         FLAC__ASSERT(0 != encoder->protected_);
197         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
198         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
199                 return false;
200         return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->stream_encoder, value);
201 }
202
203 FLAC__bool FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
204 {
205         FLAC__ASSERT(0 != encoder);
206         FLAC__ASSERT(0 != encoder->private_);
207         FLAC__ASSERT(0 != encoder->protected_);
208         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
209         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
210                 return false;
211         return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->stream_encoder, value);
212 }
213
214 FLAC__bool FLAC__seekable_stream_encoder_set_channels(FLAC__SeekableStreamEncoder *encoder, unsigned value)
215 {
216         FLAC__ASSERT(0 != encoder);
217         FLAC__ASSERT(0 != encoder->private_);
218         FLAC__ASSERT(0 != encoder->protected_);
219         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
220         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
221                 return false;
222         return FLAC__stream_encoder_set_channels(encoder->private_->stream_encoder, value);
223 }
224
225 FLAC__bool FLAC__seekable_stream_encoder_set_bits_per_sample(FLAC__SeekableStreamEncoder *encoder, unsigned value)
226 {
227         FLAC__ASSERT(0 != encoder);
228         FLAC__ASSERT(0 != encoder->private_);
229         FLAC__ASSERT(0 != encoder->protected_);
230         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
231         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
232                 return false;
233         return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->stream_encoder, value);
234 }
235
236 FLAC__bool FLAC__seekable_stream_encoder_set_sample_rate(FLAC__SeekableStreamEncoder *encoder, unsigned value)
237 {
238         FLAC__ASSERT(0 != encoder);
239         FLAC__ASSERT(0 != encoder->private_);
240         FLAC__ASSERT(0 != encoder->protected_);
241         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
242         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
243                 return false;
244         return FLAC__stream_encoder_set_sample_rate(encoder->private_->stream_encoder, value);
245 }
246
247 FLAC__bool FLAC__seekable_stream_encoder_set_blocksize(FLAC__SeekableStreamEncoder *encoder, unsigned value)
248 {
249         FLAC__ASSERT(0 != encoder);
250         FLAC__ASSERT(0 != encoder->private_);
251         FLAC__ASSERT(0 != encoder->protected_);
252         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
253         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
254                 return false;
255         return FLAC__stream_encoder_set_blocksize(encoder->private_->stream_encoder, value);
256 }
257
258 FLAC__bool FLAC__seekable_stream_encoder_set_max_lpc_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
259 {
260         FLAC__ASSERT(0 != encoder);
261         FLAC__ASSERT(0 != encoder->private_);
262         FLAC__ASSERT(0 != encoder->protected_);
263         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
264         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
265                 return false;
266         return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->stream_encoder, value);
267 }
268
269 FLAC__bool FLAC__seekable_stream_encoder_set_qlp_coeff_precision(FLAC__SeekableStreamEncoder *encoder, unsigned value)
270 {
271         FLAC__ASSERT(0 != encoder);
272         FLAC__ASSERT(0 != encoder->private_);
273         FLAC__ASSERT(0 != encoder->protected_);
274         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
275         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
276                 return false;
277         return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->stream_encoder, value);
278 }
279
280 FLAC__bool FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
281 {
282         FLAC__ASSERT(0 != encoder);
283         FLAC__ASSERT(0 != encoder->private_);
284         FLAC__ASSERT(0 != encoder->protected_);
285         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
286         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
287                 return false;
288         return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->stream_encoder, value);
289 }
290
291 FLAC__bool FLAC__seekable_stream_encoder_set_do_escape_coding(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
292 {
293         FLAC__ASSERT(0 != encoder);
294         FLAC__ASSERT(0 != encoder->private_);
295         FLAC__ASSERT(0 != encoder->protected_);
296         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
297         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
298                 return false;
299         return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->stream_encoder, value);
300 }
301
302 FLAC__bool FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
303 {
304         FLAC__ASSERT(0 != encoder);
305         FLAC__ASSERT(0 != encoder->private_);
306         FLAC__ASSERT(0 != encoder->protected_);
307         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
308         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
309                 return false;
310         return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->stream_encoder, value);
311 }
312
313 FLAC__bool FLAC__seekable_stream_encoder_set_min_residual_partition_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
314 {
315         FLAC__ASSERT(0 != encoder);
316         FLAC__ASSERT(0 != encoder->private_);
317         FLAC__ASSERT(0 != encoder->protected_);
318         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
319         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
320                 return false;
321         return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->stream_encoder, value);
322 }
323
324 FLAC__bool FLAC__seekable_stream_encoder_set_max_residual_partition_order(FLAC__SeekableStreamEncoder *encoder, unsigned value)
325 {
326         FLAC__ASSERT(0 != encoder);
327         FLAC__ASSERT(0 != encoder->private_);
328         FLAC__ASSERT(0 != encoder->protected_);
329         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
330         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
331                 return false;
332         return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->stream_encoder, value);
333 }
334
335 FLAC__bool FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(FLAC__SeekableStreamEncoder *encoder, unsigned value)
336 {
337         FLAC__ASSERT(0 != encoder);
338         FLAC__ASSERT(0 != encoder->private_);
339         FLAC__ASSERT(0 != encoder->protected_);
340         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
341         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
342                 return false;
343         return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->stream_encoder, value);
344 }
345
346 FLAC__bool FLAC__seekable_stream_encoder_set_total_samples_estimate(FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value)
347 {
348         FLAC__ASSERT(0 != encoder);
349         FLAC__ASSERT(0 != encoder->private_);
350         FLAC__ASSERT(0 != encoder->protected_);
351         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
352         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
353                 return false;
354         return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->stream_encoder, value);
355 }
356
357 FLAC__bool FLAC__seekable_stream_encoder_set_metadata(FLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
358 {
359         FLAC__ASSERT(0 != encoder);
360         FLAC__ASSERT(0 != encoder->private_);
361         FLAC__ASSERT(0 != encoder->protected_);
362         FLAC__ASSERT(0 != encoder->private_->stream_encoder);
363         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
364                 return false;
365         return FLAC__stream_encoder_set_metadata(encoder->private_->stream_encoder, value);
366 }
367
368 FLAC__bool FLAC__seekable_stream_encoder_set_seek_callback(FLAC__SeekableStreamEncoder *encoder, FLAC__SeekableStreamEncoderSeekStatus (*value)(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data))
369 {
370         FLAC__ASSERT(0 != encoder);
371         FLAC__ASSERT(0 != encoder->private_);
372         FLAC__ASSERT(0 != encoder->protected_);
373         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
374                 return false;
375         encoder->private_->seek_callback = value;
376         return true;
377 }
378
379 FLAC__bool FLAC__stream_encoder_set_write_callback(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderWriteStatus (*value)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data))
380 {
381         FLAC__ASSERT(0 != encoder);
382         FLAC__ASSERT(0 != encoder->private_);
383         FLAC__ASSERT(0 != encoder->protected_);
384         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
385                 return false;
386         encoder->private_->write_callback = value;
387         return true;
388 }
389
390 FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, void *value)
391 {
392         FLAC__ASSERT(0 != encoder);
393         FLAC__ASSERT(0 != encoder->private_);
394         FLAC__ASSERT(0 != encoder->protected_);
395         if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
396                 return false;
397         encoder->private_->client_data = value;
398         return true;
399 }
400
401 FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_state(const FLAC__SeekableStreamEncoder *encoder)
402 {
403         FLAC__ASSERT(0 != encoder);
404         FLAC__ASSERT(0 != encoder->protected_);
405         return encoder->protected_->state;
406 }
407
408 FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_stream_encoder_state(const FLAC__SeekableStreamEncoder *encoder)
409 {
410         FLAC__ASSERT(0 != encoder);
411         FLAC__ASSERT(0 != encoder->private_);
412         return FLAC__stream_encoder_get_state(encoder->private_->stream_encoder);
413 }
414
415 FLAC__bool FLAC__seekable_stream_encoder_get_streamable_subset(const FLAC__SeekableStreamEncoder *encoder)
416 {
417         FLAC__ASSERT(0 != encoder);
418         FLAC__ASSERT(0 != encoder->private_);
419         return FLAC__stream_encoder_get_streamable_subset(encoder->private_->stream_encoder);
420 }
421
422 FLAC__bool FLAC__seekable_stream_encoder_get_do_mid_side_stereo(const FLAC__SeekableStreamEncoder *encoder)
423 {
424         FLAC__ASSERT(0 != encoder);
425         FLAC__ASSERT(0 != encoder->private_);
426         return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->stream_encoder);
427 }
428
429 FLAC__bool FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const FLAC__SeekableStreamEncoder *encoder)
430 {
431         FLAC__ASSERT(0 != encoder);
432         FLAC__ASSERT(0 != encoder->private_);
433         return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->stream_encoder);
434 }
435
436 unsigned FLAC__seekable_stream_encoder_get_channels(const FLAC__SeekableStreamEncoder *encoder)
437 {
438         FLAC__ASSERT(0 != encoder);
439         FLAC__ASSERT(0 != encoder->private_);
440         return FLAC__stream_encoder_get_channels(encoder->private_->stream_encoder);
441 }
442
443 unsigned FLAC__seekable_stream_encoder_get_bits_per_sample(const FLAC__SeekableStreamEncoder *encoder)
444 {
445         FLAC__ASSERT(0 != encoder);
446         FLAC__ASSERT(0 != encoder->private_);
447         return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->stream_encoder);
448 }
449
450 unsigned FLAC__seekable_stream_encoder_get_sample_rate(const FLAC__SeekableStreamEncoder *encoder)
451 {
452         FLAC__ASSERT(0 != encoder);
453         FLAC__ASSERT(0 != encoder->private_);
454         return FLAC__stream_encoder_get_sample_rate(encoder->private_->stream_encoder);
455 }
456
457 unsigned FLAC__seekable_stream_encoder_get_blocksize(const FLAC__SeekableStreamEncoder *encoder)
458 {
459         FLAC__ASSERT(0 != encoder);
460         FLAC__ASSERT(0 != encoder->private_);
461         return FLAC__stream_encoder_get_blocksize(encoder->private_->stream_encoder);
462 }
463
464 unsigned FLAC__seekable_stream_encoder_get_max_lpc_order(const FLAC__SeekableStreamEncoder *encoder)
465 {
466         FLAC__ASSERT(0 != encoder);
467         FLAC__ASSERT(0 != encoder->private_);
468         return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->stream_encoder);
469 }
470
471 unsigned FLAC__seekable_stream_encoder_get_qlp_coeff_precision(const FLAC__SeekableStreamEncoder *encoder)
472 {
473         FLAC__ASSERT(0 != encoder);
474         FLAC__ASSERT(0 != encoder->private_);
475         return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->stream_encoder);
476 }
477
478 FLAC__bool FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__SeekableStreamEncoder *encoder)
479 {
480         FLAC__ASSERT(0 != encoder);
481         FLAC__ASSERT(0 != encoder->private_);
482         return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->stream_encoder);
483 }
484
485 FLAC__bool FLAC__seekable_stream_encoder_get_do_escape_coding(const FLAC__SeekableStreamEncoder *encoder)
486 {
487         FLAC__ASSERT(0 != encoder);
488         FLAC__ASSERT(0 != encoder->private_);
489         return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->stream_encoder);
490 }
491
492 FLAC__bool FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const FLAC__SeekableStreamEncoder *encoder)
493 {
494         FLAC__ASSERT(0 != encoder);
495         FLAC__ASSERT(0 != encoder->private_);
496         return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->stream_encoder);
497 }
498
499 unsigned FLAC__seekable_stream_encoder_get_min_residual_partition_order(const FLAC__SeekableStreamEncoder *encoder)
500 {
501         FLAC__ASSERT(0 != encoder);
502         FLAC__ASSERT(0 != encoder->private_);
503         return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->stream_encoder);
504 }
505
506 unsigned FLAC__seekable_stream_encoder_get_max_residual_partition_order(const FLAC__SeekableStreamEncoder *encoder)
507 {
508         FLAC__ASSERT(0 != encoder);
509         FLAC__ASSERT(0 != encoder->private_);
510         return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->stream_encoder);
511 }
512
513 unsigned FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const FLAC__SeekableStreamEncoder *encoder)
514 {
515         FLAC__ASSERT(0 != encoder);
516         FLAC__ASSERT(0 != encoder->private_);
517         return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->stream_encoder);
518 }
519
520 FLAC__bool FLAC__seekable_stream_encoder_process(FLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
521 {
522         FLAC__ASSERT(0 != encoder);
523         FLAC__ASSERT(0 != encoder->private_);
524         return FLAC__stream_encoder_process(encoder->private_->stream_encoder, buffer, samples);
525 }
526
527 /* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
528 FLAC__bool FLAC__seekable_stream_encoder_process_interleaved(FLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
529 {
530         FLAC__ASSERT(0 != encoder);
531         FLAC__ASSERT(0 != encoder->private_);
532         return FLAC__stream_encoder_process_interleaved(encoder->private_->stream_encoder, buffer, samples);
533 }
534
535 /***********************************************************************
536  *
537  * Private class methods
538  *
539  ***********************************************************************/
540
541 void set_defaults_(FLAC__SeekableStreamEncoder *encoder)
542 {
543         FLAC__ASSERT(0 != encoder);
544         FLAC__ASSERT(0 != encoder->private_);
545         FLAC__ASSERT(0 != encoder->protected_);
546
547         encoder->protected_->filename = 0;
548 }
549
550 FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
551 {
552         FLAC__SeekableStreamEncoder *seekable_stream_encoder = (FLAC__SeekableStreamEncoder*)client_data;
553
554         /* mark the current seek point if hit (if stream_offset == 0 that means we're still writing metadata and haven't hit the first frame yet) */
555         if(seekable_stream_encoder->private_->stream_offset > 0 && seekable_stream_encoder->private_->seek_table.num_points > 0) {
556                 FLAC__uint64 current_sample = (FLAC__uint64)current_frame * (FLAC__uint64)FLAC__stream_encoder_get_blocksize(encoder), test_sample;
557                 unsigned i;
558                 for(i = seekable_stream_encoder->private_->first_seek_point_to_check; i < seekable_stream_encoder->private_->seek_table.num_points; i++) {
559                         test_sample = seekable_stream_encoder->private_->seek_table.points[i].sample_number;
560                         if(test_sample > current_sample) {
561                                 break;
562                         }
563                         else if(test_sample == current_sample) {
564                                 seekable_stream_encoder->private_->seek_table.points[i].stream_offset = seekable_stream_encoder->private_->bytes_written - seekable_stream_encoder->private_->stream_offset;
565                                 seekable_stream_encoder->private_->seek_table.points[i].frame_samples = FLAC__stream_encoder_get_blocksize(encoder);
566                                 seekable_stream_encoder->private_->first_seek_point_to_check++;
567                                 break;
568                         }
569                         else {
570                                 seekable_stream_encoder->private_->first_seek_point_to_check++;
571                         }
572                 }
573         }
574
575         seekable_stream_encoder->private_->bytes_written += bytes;
576         seekable_stream_encoder->private_->samples_written += samples;
577         seekable_stream_encoder->private_->current_frame = current_frame;
578
579         if(samples && seekable_stream_encoder->private_->verbose && seekable_stream_encoder->private_->total_samples_to_encode > 0 && !(current_frame & mask))
580                 print_stats(seekable_stream_encoder->private_);
581
582         if(seekable_stream_encoder->private_->verify) {
583                 seekable_stream_encoder->private_->verify_fifo.encoded_signal = buffer;
584                 seekable_stream_encoder->private_->verify_fifo.encoded_bytes = bytes;
585                 if(seekable_stream_encoder->private_->verify_fifo.into_frames) {
586                         if(!FLAC__stream_decoder_process_one_frame(seekable_stream_encoder->private_->verify_fifo.decoder)) {
587                                 seekable_stream_encoder->private_->verify_fifo.result = FLAC__VERIFY_FAILED_IN_FRAME;
588                                 return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
589                         }
590                 }
591                 else {
592                         if(!FLAC__stream_decoder_process_metadata(seekable_stream_encoder->private_->verify_fifo.decoder)) {
593                                 seekable_stream_encoder->private_->verify_fifo.result = FLAC__VERIFY_FAILED_IN_METADATA;
594                                 return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
595                         }
596                 }
597         }
598
599 #ifdef FLAC__HAS_OGG
600         if(seekable_stream_encoder->private_->use_ogg) {
601                 ogg_packet op;
602
603                 memset(&op, 0, sizeof(op));
604                 op.packet = (unsigned char *)buffer;
605                 op.granulepos = seekable_stream_encoder->private_->samples_written - 1;
606                 /*@@@ WATCHOUT:
607                  * this depends on the behavior of libFLAC that we will get one
608                  * write_callback first with all the metadata (and 'samples'
609                  * will be 0), then one write_callback for each frame.
610                  */
611                 op.packetno = (samples == 0? -1 : (int)seekable_stream_encoder->private_->current_frame);
612                 op.bytes = bytes;
613
614                 if (seekable_stream_encoder->private_->bytes_written == bytes)
615                         op.b_o_s = 1;
616
617                 if (seekable_stream_encoder->private_->total_samples_to_encode == seekable_stream_encoder->private_->samples_written)
618                         op.e_o_s = 1;
619
620                 ogg_stream_packetin(&seekable_stream_encoder->private_->ogg.os, &op);
621
622                 while(ogg_stream_pageout(&seekable_stream_encoder->private_->ogg.os, &seekable_stream_encoder->private_->ogg.og) != 0) {
623                         int written;
624                         written = fwrite(seekable_stream_encoder->private_->ogg.og.header, 1, seekable_stream_encoder->private_->ogg.og.header_len, seekable_stream_encoder->private_->fout);
625                         if (written != seekable_stream_encoder->private_->ogg.og.header_len)
626                                 return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
627
628                         written = fwrite(seekable_stream_encoder->private_->ogg.og.body, 1, seekable_stream_encoder->private_->ogg.og.body_len, seekable_stream_encoder->private_->fout);
629                         if (written != seekable_stream_encoder->private_->ogg.og.body_len)
630                                 return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
631                 }
632
633                 return FLAC__STREAM_ENCODER_WRITE_OK;
634         }
635         else
636 #endif
637         {
638                 if(fwrite(buffer, sizeof(FLAC__byte), bytes, seekable_stream_encoder->private_->fout) == bytes)
639                         return FLAC__STREAM_ENCODER_WRITE_OK;
640                 else
641                         return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
642         }
643 }
644
645 void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
646 {
647         seekable_stream_encoder->private_ *seekable_stream_encoder->private_ = (seekable_stream_encoder->private_ *)client_data;
648         FLAC__byte b;
649         FILE *f = seekable_stream_encoder->private_->fout;
650         const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
651         const unsigned min_framesize = metadata->data.stream_info.min_framesize;
652         const unsigned max_framesize = metadata->data.stream_info.max_framesize;
653
654         FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
655
656         /*
657          * If we are writing to an ogg stream, there is no need to go back
658          * and update the STREAMINFO or SEEKTABLE blocks; the values we would
659          * update are not necessary with Ogg as the transport.  We can't do
660          * it reliably anyway without knowing the Ogg structure.
661          */
662 #ifdef FLAC__HAS_OGG
663         if(seekable_stream_encoder->private_->use_ogg)
664                 return;
665 #endif
666
667         /*
668          * we get called by the encoder when the encoding process has
669          * finished so that we can update the STREAMINFO and SEEKTABLE
670          * blocks.
671          */
672
673         (void)encoder; /* silence compiler warning about unused parameter */
674
675         if(f != stdout) {
676                 fclose(seekable_stream_encoder->private_->fout);
677                 if(0 == (f = fopen(seekable_stream_encoder->private_->outfilename, "r+b")))
678                         return;
679         }
680
681         /* all this is based on intimate knowledge of the stream header
682          * layout, but a change to the header format that would break this
683          * would also break all streams encoded in the previous format.
684          */
685
686         if(-1 == fseek(f, 26, SEEK_SET)) goto end_;
687         fwrite(metadata->data.stream_info.md5sum, 1, 16, f);
688
689         /* if we get this far we know we can seek so no need to check the
690          * return value from fseek()
691          */
692         fseek(f, 21, SEEK_SET);
693         if(fread(&b, 1, 1, f) != 1) goto framesize_;
694         fseek(f, 21, SEEK_SET);
695         b = (b & 0xf0) | (FLAC__byte)((samples >> 32) & 0x0F);
696         if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
697         b = (FLAC__byte)((samples >> 24) & 0xFF);
698         if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
699         b = (FLAC__byte)((samples >> 16) & 0xFF);
700         if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
701         b = (FLAC__byte)((samples >> 8) & 0xFF);
702         if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
703         b = (FLAC__byte)(samples & 0xFF);
704         if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
705
706 framesize_:
707         fseek(f, 12, SEEK_SET);
708         b = (FLAC__byte)((min_framesize >> 16) & 0xFF);
709         if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
710         b = (FLAC__byte)((min_framesize >> 8) & 0xFF);
711         if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
712         b = (FLAC__byte)(min_framesize & 0xFF);
713         if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
714         b = (FLAC__byte)((max_framesize >> 16) & 0xFF);
715         if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
716         b = (FLAC__byte)((max_framesize >> 8) & 0xFF);
717         if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
718         b = (FLAC__byte)(max_framesize & 0xFF);
719         if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
720
721 seektable_:
722         if(seekable_stream_encoder->private_->seek_table.num_points > 0) {
723                 long pos;
724                 unsigned i;
725
726                 /* convert any unused seek points to placeholders */
727                 for(i = 0; i < seekable_stream_encoder->private_->seek_table.num_points; i++) {
728                         if(seekable_stream_encoder->private_->seek_table.points[i].sample_number == FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER)
729                                 break;
730                         else if(seekable_stream_encoder->private_->seek_table.points[i].frame_samples == 0)
731                                 seekable_stream_encoder->private_->seek_table.points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
732                 }
733
734                 /* the offset of the seek table data 'pos' should be after then stream sync and STREAMINFO block and SEEKTABLE header */
735                 pos = (FLAC__STREAM_SYNC_LEN + FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
736                 pos += metadata->length;
737                 pos += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
738                 fseek(f, pos, SEEK_SET);
739                 for(i = 0; i < seekable_stream_encoder->private_->seek_table.num_points; i++) {
740                         if(!write_big_endian_uint64(f, seekable_stream_encoder->private_->seek_table.points[i].sample_number)) goto end_;
741                         if(!write_big_endian_uint64(f, seekable_stream_encoder->private_->seek_table.points[i].stream_offset)) goto end_;
742                         if(!write_big_endian_uint16(f, (FLAC__uint16)seekable_stream_encoder->private_->seek_table.points[i].frame_samples)) goto end_;
743                 }
744         }
745
746 end_:
747         fclose(f);
748         return;
749 }