add ..._get_total_samples_estimate(), add progress callback to file encoder
[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__SeekableStreamEncoderSeekStatus seek_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
35 static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
36
37 /***********************************************************************
38  *
39  * Private class data
40  *
41  ***********************************************************************/
42
43 typedef struct FLAC__FileEncoderPrivate {
44         FLAC__FileEncoderProgressCallback progress_callback;
45         void *client_data;
46         char *filename;
47         unsigned total_frames_estimate;
48         FLAC__SeekableStreamEncoder *seekable_stream_encoder;
49         FILE *file;
50 } FLAC__FileEncoderPrivate;
51
52 /***********************************************************************
53  *
54  * Public static class data
55  *
56  ***********************************************************************/
57
58 const char * const FLAC__FileEncoderStateString[] = {
59         "FLAC__FILE_ENCODER_OK",
60         "FLAC__FILE_ENCODER_NO_FILENAME",
61         "FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR",
62         "FLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING",
63         "FLAC__FILE_ENCODER_ERROR_OPENING_FILE",
64         "FLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR",
65         "FLAC__FILE_ENCODER_ALREADY_INITIALIZED",
66         "FLAC__FILE_ENCODER_UNINITIALIZED"
67 };
68
69
70 /***********************************************************************
71  *
72  * Class constructor/destructor
73  *
74  ***********************************************************************/
75
76 FLAC__FileEncoder *FLAC__file_encoder_new()
77 {
78         FLAC__FileEncoder *encoder;
79
80         FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
81
82         encoder = (FLAC__FileEncoder*)malloc(sizeof(FLAC__FileEncoder));
83         if(encoder == 0) {
84                 return 0;
85         }
86         encoder->protected_ = (FLAC__FileEncoderProtected*)malloc(sizeof(FLAC__FileEncoderProtected));
87         if(encoder->protected_ == 0) {
88                 free(encoder);
89                 return 0;
90         }
91         encoder->private_ = (FLAC__FileEncoderPrivate*)malloc(sizeof(FLAC__FileEncoderPrivate));
92         if(encoder->private_ == 0) {
93                 free(encoder->protected_);
94                 free(encoder);
95                 return 0;
96         }
97
98         encoder->private_->seekable_stream_encoder = FLAC__seekable_stream_encoder_new();
99
100         if(0 == encoder->private_->seekable_stream_encoder) {
101                 free(encoder->private_);
102                 free(encoder->protected_);
103                 free(encoder);
104                 return 0;
105         }
106
107         encoder->private_->file = 0;
108
109         set_defaults_(encoder);
110
111         encoder->protected_->state = FLAC__FILE_ENCODER_UNINITIALIZED;
112
113         return encoder;
114 }
115
116 void FLAC__file_encoder_delete(FLAC__FileEncoder *encoder)
117 {
118         FLAC__ASSERT(0 != encoder);
119         FLAC__ASSERT(0 != encoder->protected_);
120         FLAC__ASSERT(0 != encoder->private_);
121         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
122
123         (void)FLAC__file_encoder_finish(encoder);
124
125         FLAC__seekable_stream_encoder_delete(encoder->private_->seekable_stream_encoder);
126
127         free(encoder->private_);
128         free(encoder->protected_);
129         free(encoder);
130 }
131
132 /***********************************************************************
133  *
134  * Public class methods
135  *
136  ***********************************************************************/
137
138 FLAC__FileEncoderState FLAC__file_encoder_init(FLAC__FileEncoder *encoder)
139 {
140         FLAC__ASSERT(0 != encoder);
141
142         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
143                 return encoder->protected_->state = FLAC__FILE_ENCODER_ALREADY_INITIALIZED;
144
145         if(0 == encoder->private_->filename)
146                 return encoder->protected_->state = FLAC__FILE_ENCODER_NO_FILENAME;
147
148         encoder->private_->file = fopen(encoder->private_->filename, "w+b");
149
150         if(encoder->private_->file == 0)
151                 return encoder->protected_->state = FLAC__FILE_ENCODER_ERROR_OPENING_FILE;
152
153         FLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_);
154         FLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_);
155         FLAC__seekable_stream_encoder_set_client_data(encoder->private_->seekable_stream_encoder, encoder);
156
157         if(FLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != FLAC__SEEKABLE_STREAM_ENCODER_OK)
158                 return encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
159
160         {
161                 unsigned blocksize = FLAC__file_encoder_get_blocksize(encoder);
162
163                 FLAC__ASSERT(blocksize != 0);
164                 encoder->private_->total_frames_estimate = (FLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize;
165         }
166
167         return encoder->protected_->state = FLAC__FILE_ENCODER_OK;
168 }
169
170 void FLAC__file_encoder_finish(FLAC__FileEncoder *encoder)
171 {
172         FLAC__ASSERT(0 != encoder);
173
174         if(encoder->protected_->state == FLAC__FILE_ENCODER_UNINITIALIZED)
175                 return;
176
177         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
178
179         /* FLAC__seekable_stream_encoder_finish() might write data so we must close the file after it. */
180
181         FLAC__seekable_stream_encoder_finish(encoder->private_->seekable_stream_encoder);
182
183         if(0 != encoder->private_->file) {
184                 fclose(encoder->private_->file);
185                 encoder->private_->file = 0;
186         }
187
188         if(0 != encoder->private_->filename) {
189                 free(encoder->private_->filename);
190                 encoder->private_->filename = 0;
191         }
192
193         set_defaults_(encoder);
194
195         encoder->protected_->state = FLAC__FILE_ENCODER_UNINITIALIZED;
196 }
197
198 FLAC__bool FLAC__file_encoder_set_streamable_subset(FLAC__FileEncoder *encoder, FLAC__bool value)
199 {
200         FLAC__ASSERT(0 != encoder);
201         FLAC__ASSERT(0 != encoder->private_);
202         FLAC__ASSERT(0 != encoder->protected_);
203         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
204         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
205                 return false;
206         return FLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->seekable_stream_encoder, value);
207 }
208
209 FLAC__bool FLAC__file_encoder_set_do_mid_side_stereo(FLAC__FileEncoder *encoder, FLAC__bool value)
210 {
211         FLAC__ASSERT(0 != encoder);
212         FLAC__ASSERT(0 != encoder->private_);
213         FLAC__ASSERT(0 != encoder->protected_);
214         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
215         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
216                 return false;
217         return FLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
218 }
219
220 FLAC__bool FLAC__file_encoder_set_loose_mid_side_stereo(FLAC__FileEncoder *encoder, FLAC__bool value)
221 {
222         FLAC__ASSERT(0 != encoder);
223         FLAC__ASSERT(0 != encoder->private_);
224         FLAC__ASSERT(0 != encoder->protected_);
225         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
226         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
227                 return false;
228         return FLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
229 }
230
231 FLAC__bool FLAC__file_encoder_set_channels(FLAC__FileEncoder *encoder, unsigned value)
232 {
233         FLAC__ASSERT(0 != encoder);
234         FLAC__ASSERT(0 != encoder->private_);
235         FLAC__ASSERT(0 != encoder->protected_);
236         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
237         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
238                 return false;
239         return FLAC__seekable_stream_encoder_set_channels(encoder->private_->seekable_stream_encoder, value);
240 }
241
242 FLAC__bool FLAC__file_encoder_set_bits_per_sample(FLAC__FileEncoder *encoder, unsigned value)
243 {
244         FLAC__ASSERT(0 != encoder);
245         FLAC__ASSERT(0 != encoder->private_);
246         FLAC__ASSERT(0 != encoder->protected_);
247         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
248         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
249                 return false;
250         return FLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->seekable_stream_encoder, value);
251 }
252
253 FLAC__bool FLAC__file_encoder_set_sample_rate(FLAC__FileEncoder *encoder, unsigned value)
254 {
255         FLAC__ASSERT(0 != encoder);
256         FLAC__ASSERT(0 != encoder->private_);
257         FLAC__ASSERT(0 != encoder->protected_);
258         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
259         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
260                 return false;
261         return FLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->seekable_stream_encoder, value);
262 }
263
264 FLAC__bool FLAC__file_encoder_set_blocksize(FLAC__FileEncoder *encoder, unsigned value)
265 {
266         FLAC__ASSERT(0 != encoder);
267         FLAC__ASSERT(0 != encoder->private_);
268         FLAC__ASSERT(0 != encoder->protected_);
269         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
270         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
271                 return false;
272         return FLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
273 }
274
275 FLAC__bool FLAC__file_encoder_set_max_lpc_order(FLAC__FileEncoder *encoder, unsigned value)
276 {
277         FLAC__ASSERT(0 != encoder);
278         FLAC__ASSERT(0 != encoder->private_);
279         FLAC__ASSERT(0 != encoder->protected_);
280         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
281         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
282                 return false;
283         return FLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->seekable_stream_encoder, value);
284 }
285
286 FLAC__bool FLAC__file_encoder_set_qlp_coeff_precision(FLAC__FileEncoder *encoder, unsigned value)
287 {
288         FLAC__ASSERT(0 != encoder);
289         FLAC__ASSERT(0 != encoder->private_);
290         FLAC__ASSERT(0 != encoder->protected_);
291         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
292         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
293                 return false;
294         return FLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->seekable_stream_encoder, value);
295 }
296
297 FLAC__bool FLAC__file_encoder_set_do_qlp_coeff_prec_search(FLAC__FileEncoder *encoder, FLAC__bool value)
298 {
299         FLAC__ASSERT(0 != encoder);
300         FLAC__ASSERT(0 != encoder->private_);
301         FLAC__ASSERT(0 != encoder->protected_);
302         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
303         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
304                 return false;
305         return FLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder, value);
306 }
307
308 FLAC__bool FLAC__file_encoder_set_do_escape_coding(FLAC__FileEncoder *encoder, FLAC__bool value)
309 {
310         FLAC__ASSERT(0 != encoder);
311         FLAC__ASSERT(0 != encoder->private_);
312         FLAC__ASSERT(0 != encoder->protected_);
313         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
314         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
315                 return false;
316         return FLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->seekable_stream_encoder, value);
317 }
318
319 FLAC__bool FLAC__file_encoder_set_do_exhaustive_model_search(FLAC__FileEncoder *encoder, FLAC__bool value)
320 {
321         FLAC__ASSERT(0 != encoder);
322         FLAC__ASSERT(0 != encoder->private_);
323         FLAC__ASSERT(0 != encoder->protected_);
324         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
325         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
326                 return false;
327         return FLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder, value);
328 }
329
330 FLAC__bool FLAC__file_encoder_set_min_residual_partition_order(FLAC__FileEncoder *encoder, unsigned value)
331 {
332         FLAC__ASSERT(0 != encoder);
333         FLAC__ASSERT(0 != encoder->private_);
334         FLAC__ASSERT(0 != encoder->protected_);
335         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
336         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
337                 return false;
338         return FLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
339 }
340
341 FLAC__bool FLAC__file_encoder_set_max_residual_partition_order(FLAC__FileEncoder *encoder, unsigned value)
342 {
343         FLAC__ASSERT(0 != encoder);
344         FLAC__ASSERT(0 != encoder->private_);
345         FLAC__ASSERT(0 != encoder->protected_);
346         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
347         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
348                 return false;
349         return FLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
350 }
351
352 FLAC__bool FLAC__file_encoder_set_rice_parameter_search_dist(FLAC__FileEncoder *encoder, unsigned value)
353 {
354         FLAC__ASSERT(0 != encoder);
355         FLAC__ASSERT(0 != encoder->private_);
356         FLAC__ASSERT(0 != encoder->protected_);
357         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
358         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
359                 return false;
360         return FLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder, value);
361 }
362
363 FLAC__bool FLAC__file_encoder_set_total_samples_estimate(FLAC__FileEncoder *encoder, FLAC__uint64 value)
364 {
365         FLAC__ASSERT(0 != encoder);
366         FLAC__ASSERT(0 != encoder->private_);
367         FLAC__ASSERT(0 != encoder->protected_);
368         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
369         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
370                 return false;
371         return FLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->seekable_stream_encoder, value);
372 }
373
374 FLAC__bool FLAC__file_encoder_set_metadata(FLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
375 {
376         FLAC__ASSERT(0 != encoder);
377         FLAC__ASSERT(0 != encoder->private_);
378         FLAC__ASSERT(0 != encoder->protected_);
379         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
380         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
381                 return false;
382         return FLAC__seekable_stream_encoder_set_metadata(encoder->private_->seekable_stream_encoder, metadata, num_blocks);
383 }
384
385 FLAC__bool FLAC__file_encoder_set_filename(FLAC__FileEncoder *encoder, const char *value)
386 {
387         FLAC__ASSERT(0 != encoder);
388         FLAC__ASSERT(0 != encoder->private_);
389         FLAC__ASSERT(0 != encoder->protected_);
390         FLAC__ASSERT(0 != value);
391         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
392                 return false;
393         if(0 != encoder->private_->filename) {
394                 free(encoder->private_->filename);
395                 encoder->private_->filename = 0;
396         }
397         if(0 == (encoder->private_->filename = (char*)malloc(strlen(value)+1))) {
398                 encoder->protected_->state = FLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR;
399                 return false;
400         }
401         strcpy(encoder->private_->filename, value);
402         return true;
403 }
404
405 FLAC__bool FLAC__file_encoder_set_progress_callback(FLAC__FileEncoder *encoder, FLAC__FileEncoderProgressCallback value)
406 {
407         FLAC__ASSERT(0 != encoder);
408         FLAC__ASSERT(0 != encoder->private_);
409         FLAC__ASSERT(0 != encoder->protected_);
410         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
411                 return false;
412         encoder->private_->progress_callback = value;
413         return true;
414 }
415
416 FLAC__bool FLAC__file_encoder_set_client_data(FLAC__FileEncoder *encoder, void *value)
417 {
418         FLAC__ASSERT(0 != encoder);
419         FLAC__ASSERT(0 != encoder->private_);
420         FLAC__ASSERT(0 != encoder->protected_);
421         if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED)
422                 return false;
423         encoder->private_->client_data = value;
424         return true;
425 }
426
427 FLAC__FileEncoderState FLAC__file_encoder_get_state(const FLAC__FileEncoder *encoder)
428 {
429         FLAC__ASSERT(0 != encoder);
430         FLAC__ASSERT(0 != encoder->protected_);
431         return encoder->protected_->state;
432 }
433
434 FLAC__SeekableStreamEncoderState FLAC__file_encoder_get_seekable_stream_encoder_state(const FLAC__FileEncoder *encoder)
435 {
436         FLAC__ASSERT(0 != encoder);
437         FLAC__ASSERT(0 != encoder->private_);
438         return FLAC__seekable_stream_encoder_get_state(encoder->private_->seekable_stream_encoder);
439 }
440
441 FLAC__StreamEncoderState FLAC__file_encoder_get_stream_encoder_state(const FLAC__FileEncoder *encoder)
442 {
443         FLAC__ASSERT(0 != encoder);
444         FLAC__ASSERT(0 != encoder->private_);
445         return FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder->private_->seekable_stream_encoder);
446 }
447
448 FLAC__bool FLAC__file_encoder_get_streamable_subset(const FLAC__FileEncoder *encoder)
449 {
450         FLAC__ASSERT(0 != encoder);
451         FLAC__ASSERT(0 != encoder->private_);
452         return FLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->seekable_stream_encoder);
453 }
454
455 FLAC__bool FLAC__file_encoder_get_do_mid_side_stereo(const FLAC__FileEncoder *encoder)
456 {
457         FLAC__ASSERT(0 != encoder);
458         FLAC__ASSERT(0 != encoder->private_);
459         return FLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->seekable_stream_encoder);
460 }
461
462 FLAC__bool FLAC__file_encoder_get_loose_mid_side_stereo(const FLAC__FileEncoder *encoder)
463 {
464         FLAC__ASSERT(0 != encoder);
465         FLAC__ASSERT(0 != encoder->private_);
466         return FLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder);
467 }
468
469 unsigned FLAC__file_encoder_get_channels(const FLAC__FileEncoder *encoder)
470 {
471         FLAC__ASSERT(0 != encoder);
472         FLAC__ASSERT(0 != encoder->private_);
473         return FLAC__seekable_stream_encoder_get_channels(encoder->private_->seekable_stream_encoder);
474 }
475
476 unsigned FLAC__file_encoder_get_bits_per_sample(const FLAC__FileEncoder *encoder)
477 {
478         FLAC__ASSERT(0 != encoder);
479         FLAC__ASSERT(0 != encoder->private_);
480         return FLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->seekable_stream_encoder);
481 }
482
483 unsigned FLAC__file_encoder_get_sample_rate(const FLAC__FileEncoder *encoder)
484 {
485         FLAC__ASSERT(0 != encoder);
486         FLAC__ASSERT(0 != encoder->private_);
487         return FLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->seekable_stream_encoder);
488 }
489
490 unsigned FLAC__file_encoder_get_blocksize(const FLAC__FileEncoder *encoder)
491 {
492         FLAC__ASSERT(0 != encoder);
493         FLAC__ASSERT(0 != encoder->private_);
494         return FLAC__seekable_stream_encoder_get_blocksize(encoder->private_->seekable_stream_encoder);
495 }
496
497 unsigned FLAC__file_encoder_get_max_lpc_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_lpc_order(encoder->private_->seekable_stream_encoder);
502 }
503
504 unsigned FLAC__file_encoder_get_qlp_coeff_precision(const FLAC__FileEncoder *encoder)
505 {
506         FLAC__ASSERT(0 != encoder);
507         FLAC__ASSERT(0 != encoder->private_);
508         return FLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->seekable_stream_encoder);
509 }
510
511 FLAC__bool FLAC__file_encoder_get_do_qlp_coeff_prec_search(const FLAC__FileEncoder *encoder)
512 {
513         FLAC__ASSERT(0 != encoder);
514         FLAC__ASSERT(0 != encoder->private_);
515         return FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder);
516 }
517
518 FLAC__bool FLAC__file_encoder_get_do_escape_coding(const FLAC__FileEncoder *encoder)
519 {
520         FLAC__ASSERT(0 != encoder);
521         FLAC__ASSERT(0 != encoder->private_);
522         return FLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->seekable_stream_encoder);
523 }
524
525 FLAC__bool FLAC__file_encoder_get_do_exhaustive_model_search(const FLAC__FileEncoder *encoder)
526 {
527         FLAC__ASSERT(0 != encoder);
528         FLAC__ASSERT(0 != encoder->private_);
529         return FLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder);
530 }
531
532 unsigned FLAC__file_encoder_get_min_residual_partition_order(const FLAC__FileEncoder *encoder)
533 {
534         FLAC__ASSERT(0 != encoder);
535         FLAC__ASSERT(0 != encoder->private_);
536         return FLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->seekable_stream_encoder);
537 }
538
539 unsigned FLAC__file_encoder_get_max_residual_partition_order(const FLAC__FileEncoder *encoder)
540 {
541         FLAC__ASSERT(0 != encoder);
542         FLAC__ASSERT(0 != encoder->private_);
543         return FLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->seekable_stream_encoder);
544 }
545
546 unsigned FLAC__file_encoder_get_rice_parameter_search_dist(const FLAC__FileEncoder *encoder)
547 {
548         FLAC__ASSERT(0 != encoder);
549         FLAC__ASSERT(0 != encoder->private_);
550         return FLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder);
551 }
552
553 FLAC__uint64 FLAC__file_encoder_get_total_samples_estimate(const FLAC__FileEncoder *encoder)
554 {
555         FLAC__ASSERT(0 != encoder);
556         FLAC__ASSERT(0 != encoder->private_);
557         return FLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder);
558 }
559
560 FLAC__bool FLAC__file_encoder_process(FLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
561 {
562         FLAC__ASSERT(0 != encoder);
563         FLAC__ASSERT(0 != encoder->private_);
564         return FLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples);
565 }
566
567 /* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
568 FLAC__bool FLAC__file_encoder_process_interleaved(FLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
569 {
570         FLAC__ASSERT(0 != encoder);
571         FLAC__ASSERT(0 != encoder->private_);
572         return FLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples);
573 }
574
575
576 /***********************************************************************
577  *
578  * Private class methods
579  *
580  ***********************************************************************/
581
582 void set_defaults_(FLAC__FileEncoder *encoder)
583 {
584         FLAC__ASSERT(0 != encoder);
585         FLAC__ASSERT(0 != encoder->private_);
586
587         encoder->private_->progress_callback = 0;
588         encoder->private_->client_data = 0;
589         encoder->private_->total_frames_estimate = 0;
590         encoder->private_->filename = 0;
591 }
592
593 FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const FLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
594 {
595         FLAC__FileEncoder *file_encoder = (FLAC__FileEncoder*)client_data;
596
597         (void)encoder;
598
599         FLAC__ASSERT(0 != file_encoder);
600
601         if(fseek(file_encoder->private_->file, absolute_byte_offset, SEEK_SET) < 0)
602                 return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR;
603         else
604                 return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
605 }
606
607 FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
608 {
609         FLAC__FileEncoder *file_encoder = (FLAC__FileEncoder*)client_data;
610
611         (void)encoder, (void)samples, (void)current_frame;
612
613         FLAC__ASSERT(0 != file_encoder);
614
615         if(fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) {
616                 if(0 != file_encoder->private_->progress_callback)
617                         file_encoder->private_->progress_callback(file_encoder, current_frame, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data);
618                 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
619         }
620         else
621                 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
622 }