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