35d83c51b6f6fb4caca1a4ae5a031a3fdf96a8ab
[platform/upstream/flac.git] / src / libOggFLAC / file_encoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002,2003,2004  Josh Coalson
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the Xiph.org Foundation nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h> /* for malloc() */
34 #include <string.h> /* for strlen(), strcpy() */
35 #include "FLAC/assert.h"
36 #include "OggFLAC/seekable_stream_encoder.h"
37 #include "protected/file_encoder.h"
38
39 #ifdef max
40 #undef max
41 #endif
42 #define max(x,y) ((x)>(y)?(x):(y))
43
44 /***********************************************************************
45  *
46  * Private class method prototypes
47  *
48  ***********************************************************************/
49
50 /* unpublished debug routines */
51 extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
52 extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
53 extern FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value);
54
55 static void set_defaults_(OggFLAC__FileEncoder *encoder);
56 static OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
57 static FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
58 static FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
59 static FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
60
61 /***********************************************************************
62  *
63  * Private class data
64  *
65  ***********************************************************************/
66
67 typedef struct OggFLAC__FileEncoderPrivate {
68         OggFLAC__FileEncoderProgressCallback progress_callback;
69         void *client_data;
70         char *filename;
71         FLAC__uint64 bytes_written;
72         FLAC__uint64 samples_written;
73         unsigned frames_written;
74         unsigned total_frames_estimate;
75         OggFLAC__SeekableStreamEncoder *seekable_stream_encoder;
76         FILE *file;
77 } OggFLAC__FileEncoderPrivate;
78
79 /***********************************************************************
80  *
81  * Public static class data
82  *
83  ***********************************************************************/
84
85 OggFLAC_API const char * const OggFLAC__FileEncoderStateString[] = {
86         "OggFLAC__FILE_ENCODER_OK",
87         "OggFLAC__FILE_ENCODER_NO_FILENAME",
88         "OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR",
89         "OggFLAC__FILE_ENCODER_FATAL_ERROR_WHILE_WRITING",
90         "OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE",
91         "OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR",
92         "OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED",
93         "OggFLAC__FILE_ENCODER_UNINITIALIZED"
94 };
95
96
97 /***********************************************************************
98  *
99  * Class constructor/destructor
100  *
101  ***********************************************************************/
102
103 OggFLAC_API OggFLAC__FileEncoder *OggFLAC__file_encoder_new()
104 {
105         OggFLAC__FileEncoder *encoder;
106
107         FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
108
109         encoder = (OggFLAC__FileEncoder*)calloc(1, sizeof(OggFLAC__FileEncoder));
110         if(encoder == 0) {
111                 return 0;
112         }
113
114         encoder->protected_ = (OggFLAC__FileEncoderProtected*)calloc(1, sizeof(OggFLAC__FileEncoderProtected));
115         if(encoder->protected_ == 0) {
116                 free(encoder);
117                 return 0;
118         }
119
120         encoder->private_ = (OggFLAC__FileEncoderPrivate*)calloc(1, sizeof(OggFLAC__FileEncoderPrivate));
121         if(encoder->private_ == 0) {
122                 free(encoder->protected_);
123                 free(encoder);
124                 return 0;
125         }
126
127         encoder->private_->seekable_stream_encoder = OggFLAC__seekable_stream_encoder_new();
128         if(0 == encoder->private_->seekable_stream_encoder) {
129                 free(encoder->private_);
130                 free(encoder->protected_);
131                 free(encoder);
132                 return 0;
133         }
134
135         encoder->private_->file = 0;
136
137         set_defaults_(encoder);
138
139         encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED;
140
141         return encoder;
142 }
143
144 OggFLAC_API void OggFLAC__file_encoder_delete(OggFLAC__FileEncoder *encoder)
145 {
146         FLAC__ASSERT(0 != encoder);
147         FLAC__ASSERT(0 != encoder->protected_);
148         FLAC__ASSERT(0 != encoder->private_);
149         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
150
151         (void)OggFLAC__file_encoder_finish(encoder);
152
153         OggFLAC__seekable_stream_encoder_delete(encoder->private_->seekable_stream_encoder);
154
155         free(encoder->private_);
156         free(encoder->protected_);
157         free(encoder);
158 }
159
160 /***********************************************************************
161  *
162  * Public class methods
163  *
164  ***********************************************************************/
165
166 OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_init(OggFLAC__FileEncoder *encoder)
167 {
168         FLAC__ASSERT(0 != encoder);
169
170         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
171                 return encoder->protected_->state = OggFLAC__FILE_ENCODER_ALREADY_INITIALIZED;
172
173         if(0 == encoder->private_->filename)
174                 return encoder->protected_->state = OggFLAC__FILE_ENCODER_NO_FILENAME;
175
176         encoder->private_->file = fopen(encoder->private_->filename, "w+b");
177
178         if(encoder->private_->file == 0)
179                 return encoder->protected_->state = OggFLAC__FILE_ENCODER_ERROR_OPENING_FILE;
180
181         encoder->private_->bytes_written = 0;
182         encoder->private_->samples_written = 0;
183         encoder->private_->frames_written = 0;
184
185         OggFLAC__seekable_stream_encoder_set_read_callback(encoder->private_->seekable_stream_encoder, read_callback_);
186         OggFLAC__seekable_stream_encoder_set_seek_callback(encoder->private_->seekable_stream_encoder, seek_callback_);
187         OggFLAC__seekable_stream_encoder_set_tell_callback(encoder->private_->seekable_stream_encoder, tell_callback_);
188         OggFLAC__seekable_stream_encoder_set_write_callback(encoder->private_->seekable_stream_encoder, write_callback_);
189         OggFLAC__seekable_stream_encoder_set_client_data(encoder->private_->seekable_stream_encoder, encoder);
190
191         if(OggFLAC__seekable_stream_encoder_init(encoder->private_->seekable_stream_encoder) != OggFLAC__SEEKABLE_STREAM_ENCODER_OK)
192                 return encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
193
194         {
195                 unsigned blocksize = OggFLAC__file_encoder_get_blocksize(encoder);
196
197                 FLAC__ASSERT(blocksize != 0);
198                 encoder->private_->total_frames_estimate = (unsigned)((OggFLAC__file_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize);
199         }
200
201         return encoder->protected_->state = OggFLAC__FILE_ENCODER_OK;
202 }
203
204 OggFLAC_API void OggFLAC__file_encoder_finish(OggFLAC__FileEncoder *encoder)
205 {
206         FLAC__ASSERT(0 != encoder);
207
208         if(encoder->protected_->state == OggFLAC__FILE_ENCODER_UNINITIALIZED)
209                 return;
210
211         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
212
213         /* OggFLAC__seekable_stream_encoder_finish() might write data so we must close the file after it. */
214
215         OggFLAC__seekable_stream_encoder_finish(encoder->private_->seekable_stream_encoder);
216
217         if(0 != encoder->private_->file) {
218                 fclose(encoder->private_->file);
219                 encoder->private_->file = 0;
220         }
221
222         if(0 != encoder->private_->filename) {
223                 free(encoder->private_->filename);
224                 encoder->private_->filename = 0;
225         }
226
227         set_defaults_(encoder);
228
229         encoder->protected_->state = OggFLAC__FILE_ENCODER_UNINITIALIZED;
230 }
231
232 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_serial_number(OggFLAC__FileEncoder *encoder, long serial_number)
233 {
234         FLAC__ASSERT(0 != encoder);
235         FLAC__ASSERT(0 != encoder->private_);
236         FLAC__ASSERT(0 != encoder->protected_);
237         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
238         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
239                 return false;
240         return OggFLAC__seekable_stream_encoder_set_serial_number(encoder->private_->seekable_stream_encoder, serial_number);
241 }
242
243 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_verify(OggFLAC__FileEncoder *encoder, FLAC__bool value)
244 {
245         FLAC__ASSERT(0 != encoder);
246         FLAC__ASSERT(0 != encoder->private_);
247         FLAC__ASSERT(0 != encoder->protected_);
248         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
249         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
250                 return false;
251         return OggFLAC__seekable_stream_encoder_set_verify(encoder->private_->seekable_stream_encoder, value);
252 }
253
254 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_streamable_subset(OggFLAC__FileEncoder *encoder, FLAC__bool value)
255 {
256         FLAC__ASSERT(0 != encoder);
257         FLAC__ASSERT(0 != encoder->private_);
258         FLAC__ASSERT(0 != encoder->protected_);
259         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
260         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
261                 return false;
262         return OggFLAC__seekable_stream_encoder_set_streamable_subset(encoder->private_->seekable_stream_encoder, value);
263 }
264
265 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value)
266 {
267         FLAC__ASSERT(0 != encoder);
268         FLAC__ASSERT(0 != encoder->private_);
269         FLAC__ASSERT(0 != encoder->protected_);
270         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
271         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
272                 return false;
273         return OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
274 }
275
276 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_loose_mid_side_stereo(OggFLAC__FileEncoder *encoder, FLAC__bool value)
277 {
278         FLAC__ASSERT(0 != encoder);
279         FLAC__ASSERT(0 != encoder->private_);
280         FLAC__ASSERT(0 != encoder->protected_);
281         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
282         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
283                 return false;
284         return OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder, value);
285 }
286
287 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_channels(OggFLAC__FileEncoder *encoder, unsigned value)
288 {
289         FLAC__ASSERT(0 != encoder);
290         FLAC__ASSERT(0 != encoder->private_);
291         FLAC__ASSERT(0 != encoder->protected_);
292         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
293         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
294                 return false;
295         return OggFLAC__seekable_stream_encoder_set_channels(encoder->private_->seekable_stream_encoder, value);
296 }
297
298 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_bits_per_sample(OggFLAC__FileEncoder *encoder, unsigned value)
299 {
300         FLAC__ASSERT(0 != encoder);
301         FLAC__ASSERT(0 != encoder->private_);
302         FLAC__ASSERT(0 != encoder->protected_);
303         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
304         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
305                 return false;
306         return OggFLAC__seekable_stream_encoder_set_bits_per_sample(encoder->private_->seekable_stream_encoder, value);
307 }
308
309 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_sample_rate(OggFLAC__FileEncoder *encoder, unsigned value)
310 {
311         FLAC__ASSERT(0 != encoder);
312         FLAC__ASSERT(0 != encoder->private_);
313         FLAC__ASSERT(0 != encoder->protected_);
314         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
315         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
316                 return false;
317         return OggFLAC__seekable_stream_encoder_set_sample_rate(encoder->private_->seekable_stream_encoder, value);
318 }
319
320 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_blocksize(OggFLAC__FileEncoder *encoder, unsigned value)
321 {
322         FLAC__ASSERT(0 != encoder);
323         FLAC__ASSERT(0 != encoder->private_);
324         FLAC__ASSERT(0 != encoder->protected_);
325         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
326         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
327                 return false;
328         return OggFLAC__seekable_stream_encoder_set_blocksize(encoder->private_->seekable_stream_encoder, value);
329 }
330
331 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_lpc_order(OggFLAC__FileEncoder *encoder, unsigned value)
332 {
333         FLAC__ASSERT(0 != encoder);
334         FLAC__ASSERT(0 != encoder->private_);
335         FLAC__ASSERT(0 != encoder->protected_);
336         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
337         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
338                 return false;
339         return OggFLAC__seekable_stream_encoder_set_max_lpc_order(encoder->private_->seekable_stream_encoder, value);
340 }
341
342 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_qlp_coeff_precision(OggFLAC__FileEncoder *encoder, unsigned value)
343 {
344         FLAC__ASSERT(0 != encoder);
345         FLAC__ASSERT(0 != encoder->private_);
346         FLAC__ASSERT(0 != encoder->protected_);
347         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
348         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
349                 return false;
350         return OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(encoder->private_->seekable_stream_encoder, value);
351 }
352
353 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_qlp_coeff_prec_search(OggFLAC__FileEncoder *encoder, FLAC__bool value)
354 {
355         FLAC__ASSERT(0 != encoder);
356         FLAC__ASSERT(0 != encoder->private_);
357         FLAC__ASSERT(0 != encoder->protected_);
358         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
359         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
360                 return false;
361         return OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder, value);
362 }
363
364 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_escape_coding(OggFLAC__FileEncoder *encoder, FLAC__bool value)
365 {
366         FLAC__ASSERT(0 != encoder);
367         FLAC__ASSERT(0 != encoder->private_);
368         FLAC__ASSERT(0 != encoder->protected_);
369         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
370         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
371                 return false;
372         return OggFLAC__seekable_stream_encoder_set_do_escape_coding(encoder->private_->seekable_stream_encoder, value);
373 }
374
375 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_do_exhaustive_model_search(OggFLAC__FileEncoder *encoder, FLAC__bool value)
376 {
377         FLAC__ASSERT(0 != encoder);
378         FLAC__ASSERT(0 != encoder->private_);
379         FLAC__ASSERT(0 != encoder->protected_);
380         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
381         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
382                 return false;
383         return OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder, value);
384 }
385
386 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_min_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value)
387 {
388         FLAC__ASSERT(0 != encoder);
389         FLAC__ASSERT(0 != encoder->private_);
390         FLAC__ASSERT(0 != encoder->protected_);
391         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
392         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
393                 return false;
394         return OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
395 }
396
397 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_max_residual_partition_order(OggFLAC__FileEncoder *encoder, unsigned value)
398 {
399         FLAC__ASSERT(0 != encoder);
400         FLAC__ASSERT(0 != encoder->private_);
401         FLAC__ASSERT(0 != encoder->protected_);
402         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
403         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
404                 return false;
405         return OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(encoder->private_->seekable_stream_encoder, value);
406 }
407
408 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_rice_parameter_search_dist(OggFLAC__FileEncoder *encoder, unsigned value)
409 {
410         FLAC__ASSERT(0 != encoder);
411         FLAC__ASSERT(0 != encoder->private_);
412         FLAC__ASSERT(0 != encoder->protected_);
413         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
414         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
415                 return false;
416         return OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder, value);
417 }
418
419 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_total_samples_estimate(OggFLAC__FileEncoder *encoder, FLAC__uint64 value)
420 {
421         FLAC__ASSERT(0 != encoder);
422         FLAC__ASSERT(0 != encoder->private_);
423         FLAC__ASSERT(0 != encoder->protected_);
424         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
425         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
426                 return false;
427         return OggFLAC__seekable_stream_encoder_set_total_samples_estimate(encoder->private_->seekable_stream_encoder, value);
428 }
429
430 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_metadata(OggFLAC__FileEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
431 {
432         FLAC__ASSERT(0 != encoder);
433         FLAC__ASSERT(0 != encoder->private_);
434         FLAC__ASSERT(0 != encoder->protected_);
435         FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder);
436         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
437                 return false;
438         return OggFLAC__seekable_stream_encoder_set_metadata(encoder->private_->seekable_stream_encoder, metadata, num_blocks);
439 }
440
441 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_filename(OggFLAC__FileEncoder *encoder, const char *value)
442 {
443         FLAC__ASSERT(0 != encoder);
444         FLAC__ASSERT(0 != encoder->private_);
445         FLAC__ASSERT(0 != encoder->protected_);
446         FLAC__ASSERT(0 != value);
447         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
448                 return false;
449         if(0 != encoder->private_->filename) {
450                 free(encoder->private_->filename);
451                 encoder->private_->filename = 0;
452         }
453         if(0 == (encoder->private_->filename = (char*)malloc(strlen(value)+1))) {
454                 encoder->protected_->state = OggFLAC__FILE_ENCODER_MEMORY_ALLOCATION_ERROR;
455                 return false;
456         }
457         strcpy(encoder->private_->filename, value);
458         return true;
459 }
460
461 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_progress_callback(OggFLAC__FileEncoder *encoder, OggFLAC__FileEncoderProgressCallback value)
462 {
463         FLAC__ASSERT(0 != encoder);
464         FLAC__ASSERT(0 != encoder->private_);
465         FLAC__ASSERT(0 != encoder->protected_);
466         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
467                 return false;
468         encoder->private_->progress_callback = value;
469         return true;
470 }
471
472 OggFLAC_API FLAC__bool OggFLAC__file_encoder_set_client_data(OggFLAC__FileEncoder *encoder, void *value)
473 {
474         FLAC__ASSERT(0 != encoder);
475         FLAC__ASSERT(0 != encoder->private_);
476         FLAC__ASSERT(0 != encoder->protected_);
477         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
478                 return false;
479         encoder->private_->client_data = value;
480         return true;
481 }
482
483 /*
484  * These three functions are not static, but not publically exposed in
485  * include/OggFLAC/ either.  They are used by the test suite.
486  */
487 OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_constant_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
488 {
489         FLAC__ASSERT(0 != encoder);
490         FLAC__ASSERT(0 != encoder->private_);
491         FLAC__ASSERT(0 != encoder->protected_);
492         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
493                 return false;
494         return OggFLAC__seekable_stream_encoder_disable_constant_subframes(encoder->private_->seekable_stream_encoder, value);
495 }
496
497 OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_fixed_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
498 {
499         FLAC__ASSERT(0 != encoder);
500         FLAC__ASSERT(0 != encoder->private_);
501         FLAC__ASSERT(0 != encoder->protected_);
502         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
503                 return false;
504         return OggFLAC__seekable_stream_encoder_disable_fixed_subframes(encoder->private_->seekable_stream_encoder, value);
505 }
506
507 OggFLAC_API FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__FileEncoder *encoder, FLAC__bool value)
508 {
509         FLAC__ASSERT(0 != encoder);
510         FLAC__ASSERT(0 != encoder->private_);
511         FLAC__ASSERT(0 != encoder->protected_);
512         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_UNINITIALIZED)
513                 return false;
514         return OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(encoder->private_->seekable_stream_encoder, value);
515 }
516
517 OggFLAC_API OggFLAC__FileEncoderState OggFLAC__file_encoder_get_state(const OggFLAC__FileEncoder *encoder)
518 {
519         FLAC__ASSERT(0 != encoder);
520         FLAC__ASSERT(0 != encoder->protected_);
521         return encoder->protected_->state;
522 }
523
524 OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__file_encoder_get_seekable_stream_encoder_state(const OggFLAC__FileEncoder *encoder)
525 {
526         FLAC__ASSERT(0 != encoder);
527         FLAC__ASSERT(0 != encoder->private_);
528         return OggFLAC__seekable_stream_encoder_get_state(encoder->private_->seekable_stream_encoder);
529 }
530
531 OggFLAC_API FLAC__StreamEncoderState OggFLAC__file_encoder_get_FLAC_stream_encoder_state(const OggFLAC__FileEncoder *encoder)
532 {
533         FLAC__ASSERT(0 != encoder);
534         FLAC__ASSERT(0 != encoder->private_);
535         return OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(encoder->private_->seekable_stream_encoder);
536 }
537
538 OggFLAC_API FLAC__StreamDecoderState OggFLAC__file_encoder_get_verify_decoder_state(const OggFLAC__FileEncoder *encoder)
539 {
540         FLAC__ASSERT(0 != encoder);
541         FLAC__ASSERT(0 != encoder->private_);
542         return OggFLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->seekable_stream_encoder);
543 }
544
545 OggFLAC_API const char *OggFLAC__file_encoder_get_resolved_state_string(const OggFLAC__FileEncoder *encoder)
546 {
547         if(encoder->protected_->state != OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR)
548                 return OggFLAC__FileEncoderStateString[encoder->protected_->state];
549         else
550                 return OggFLAC__seekable_stream_encoder_get_resolved_state_string(encoder->private_->seekable_stream_encoder);
551 }
552
553 OggFLAC_API void OggFLAC__file_encoder_get_verify_decoder_error_stats(const OggFLAC__FileEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
554 {
555         FLAC__ASSERT(0 != encoder);
556         FLAC__ASSERT(0 != encoder->private_);
557         OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(encoder->private_->seekable_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
558 }
559
560 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_verify(const OggFLAC__FileEncoder *encoder)
561 {
562         FLAC__ASSERT(0 != encoder);
563         FLAC__ASSERT(0 != encoder->private_);
564         return OggFLAC__seekable_stream_encoder_get_verify(encoder->private_->seekable_stream_encoder);
565 }
566
567 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_streamable_subset(const OggFLAC__FileEncoder *encoder)
568 {
569         FLAC__ASSERT(0 != encoder);
570         FLAC__ASSERT(0 != encoder->private_);
571         return OggFLAC__seekable_stream_encoder_get_streamable_subset(encoder->private_->seekable_stream_encoder);
572 }
573
574 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_mid_side_stereo(const OggFLAC__FileEncoder *encoder)
575 {
576         FLAC__ASSERT(0 != encoder);
577         FLAC__ASSERT(0 != encoder->private_);
578         return OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(encoder->private_->seekable_stream_encoder);
579 }
580
581 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_loose_mid_side_stereo(const OggFLAC__FileEncoder *encoder)
582 {
583         FLAC__ASSERT(0 != encoder);
584         FLAC__ASSERT(0 != encoder->private_);
585         return OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(encoder->private_->seekable_stream_encoder);
586 }
587
588 OggFLAC_API unsigned OggFLAC__file_encoder_get_channels(const OggFLAC__FileEncoder *encoder)
589 {
590         FLAC__ASSERT(0 != encoder);
591         FLAC__ASSERT(0 != encoder->private_);
592         return OggFLAC__seekable_stream_encoder_get_channels(encoder->private_->seekable_stream_encoder);
593 }
594
595 OggFLAC_API unsigned OggFLAC__file_encoder_get_bits_per_sample(const OggFLAC__FileEncoder *encoder)
596 {
597         FLAC__ASSERT(0 != encoder);
598         FLAC__ASSERT(0 != encoder->private_);
599         return OggFLAC__seekable_stream_encoder_get_bits_per_sample(encoder->private_->seekable_stream_encoder);
600 }
601
602 OggFLAC_API unsigned OggFLAC__file_encoder_get_sample_rate(const OggFLAC__FileEncoder *encoder)
603 {
604         FLAC__ASSERT(0 != encoder);
605         FLAC__ASSERT(0 != encoder->private_);
606         return OggFLAC__seekable_stream_encoder_get_sample_rate(encoder->private_->seekable_stream_encoder);
607 }
608
609 OggFLAC_API unsigned OggFLAC__file_encoder_get_blocksize(const OggFLAC__FileEncoder *encoder)
610 {
611         FLAC__ASSERT(0 != encoder);
612         FLAC__ASSERT(0 != encoder->private_);
613         return OggFLAC__seekable_stream_encoder_get_blocksize(encoder->private_->seekable_stream_encoder);
614 }
615
616 OggFLAC_API unsigned OggFLAC__file_encoder_get_max_lpc_order(const OggFLAC__FileEncoder *encoder)
617 {
618         FLAC__ASSERT(0 != encoder);
619         FLAC__ASSERT(0 != encoder->private_);
620         return OggFLAC__seekable_stream_encoder_get_max_lpc_order(encoder->private_->seekable_stream_encoder);
621 }
622
623 OggFLAC_API unsigned OggFLAC__file_encoder_get_qlp_coeff_precision(const OggFLAC__FileEncoder *encoder)
624 {
625         FLAC__ASSERT(0 != encoder);
626         FLAC__ASSERT(0 != encoder->private_);
627         return OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(encoder->private_->seekable_stream_encoder);
628 }
629
630 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__FileEncoder *encoder)
631 {
632         FLAC__ASSERT(0 != encoder);
633         FLAC__ASSERT(0 != encoder->private_);
634         return OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->seekable_stream_encoder);
635 }
636
637 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_escape_coding(const OggFLAC__FileEncoder *encoder)
638 {
639         FLAC__ASSERT(0 != encoder);
640         FLAC__ASSERT(0 != encoder->private_);
641         return OggFLAC__seekable_stream_encoder_get_do_escape_coding(encoder->private_->seekable_stream_encoder);
642 }
643
644 OggFLAC_API FLAC__bool OggFLAC__file_encoder_get_do_exhaustive_model_search(const OggFLAC__FileEncoder *encoder)
645 {
646         FLAC__ASSERT(0 != encoder);
647         FLAC__ASSERT(0 != encoder->private_);
648         return OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(encoder->private_->seekable_stream_encoder);
649 }
650
651 OggFLAC_API unsigned OggFLAC__file_encoder_get_min_residual_partition_order(const OggFLAC__FileEncoder *encoder)
652 {
653         FLAC__ASSERT(0 != encoder);
654         FLAC__ASSERT(0 != encoder->private_);
655         return OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(encoder->private_->seekable_stream_encoder);
656 }
657
658 OggFLAC_API unsigned OggFLAC__file_encoder_get_max_residual_partition_order(const OggFLAC__FileEncoder *encoder)
659 {
660         FLAC__ASSERT(0 != encoder);
661         FLAC__ASSERT(0 != encoder->private_);
662         return OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(encoder->private_->seekable_stream_encoder);
663 }
664
665 OggFLAC_API unsigned OggFLAC__file_encoder_get_rice_parameter_search_dist(const OggFLAC__FileEncoder *encoder)
666 {
667         FLAC__ASSERT(0 != encoder);
668         FLAC__ASSERT(0 != encoder->private_);
669         return OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(encoder->private_->seekable_stream_encoder);
670 }
671
672 OggFLAC_API FLAC__uint64 OggFLAC__file_encoder_get_total_samples_estimate(const OggFLAC__FileEncoder *encoder)
673 {
674         FLAC__ASSERT(0 != encoder);
675         FLAC__ASSERT(0 != encoder->private_);
676         return OggFLAC__seekable_stream_encoder_get_total_samples_estimate(encoder->private_->seekable_stream_encoder);
677 }
678
679 OggFLAC_API FLAC__bool OggFLAC__file_encoder_process(OggFLAC__FileEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
680 {
681         FLAC__ASSERT(0 != encoder);
682         FLAC__ASSERT(0 != encoder->private_);
683         if(!OggFLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples)) {
684                 encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
685                 return false;
686         }
687         else
688                 return true;
689 }
690
691 /* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
692 OggFLAC_API FLAC__bool OggFLAC__file_encoder_process_interleaved(OggFLAC__FileEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
693 {
694         FLAC__ASSERT(0 != encoder);
695         FLAC__ASSERT(0 != encoder->private_);
696         if(!OggFLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples)) {
697                 encoder->protected_->state = OggFLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR;
698                 return false;
699         }
700         else
701                 return true;
702 }
703
704
705 /***********************************************************************
706  *
707  * Private class methods
708  *
709  ***********************************************************************/
710
711 void set_defaults_(OggFLAC__FileEncoder *encoder)
712 {
713         FLAC__ASSERT(0 != encoder);
714         FLAC__ASSERT(0 != encoder->private_);
715
716         encoder->private_->progress_callback = 0;
717         encoder->private_->client_data = 0;
718         encoder->private_->total_frames_estimate = 0;
719         encoder->private_->filename = 0;
720 }
721
722 OggFLAC__SeekableStreamEncoderReadStatus read_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
723 {
724         OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
725
726         (void)encoder;
727
728         FLAC__ASSERT(0 != file_encoder);
729
730         *bytes = (unsigned)fread(buffer, 1, *bytes, file_encoder->private_->file);
731         if (*bytes == 0) {
732                 if (feof(file_encoder->private_->file))
733                         return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
734                 else if (ferror(file_encoder->private_->file))
735                         return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT;
736         }
737         return OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE;
738 }
739
740 FLAC__SeekableStreamEncoderSeekStatus seek_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
741 {
742         OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
743
744         (void)encoder;
745
746         FLAC__ASSERT(0 != file_encoder);
747
748         if(fseek(file_encoder->private_->file, (long)absolute_byte_offset, SEEK_SET) < 0)
749                 return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_ERROR;
750         else
751                 return FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK;
752 }
753
754 FLAC__SeekableStreamEncoderTellStatus tell_callback_(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
755 {
756         OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
757         long offset;
758
759         (void)encoder;
760
761         FLAC__ASSERT(0 != file_encoder);
762
763         offset = ftell(file_encoder->private_->file);
764
765         if(offset < 0) {
766                 return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_ERROR;
767         }
768         else {
769                 *absolute_byte_offset = (FLAC__uint64)offset;
770                 return FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK;
771         }
772 }
773
774 #ifdef FLAC__VALGRIND_TESTING
775 static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
776 {
777         size_t ret = fwrite(ptr, size, nmemb, stream);
778         if(!ferror(stream))
779                 fflush(stream);
780         return ret;
781 }
782 #else
783 #define local__fwrite fwrite
784 #endif
785
786 FLAC__StreamEncoderWriteStatus write_callback_(const OggFLAC__SeekableStreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
787 {
788         OggFLAC__FileEncoder *file_encoder = (OggFLAC__FileEncoder*)client_data;
789
790         (void)encoder;
791
792         FLAC__ASSERT(0 != file_encoder);
793
794         if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, file_encoder->private_->file) == bytes) {
795                 file_encoder->private_->bytes_written += bytes;
796                 file_encoder->private_->samples_written += samples;
797                 /* we keep a high watermark on the number of frames written
798                  * because when the encoder goes back to write metadata,
799                  * 'current_frame' will drop back to 0.
800                  */
801                 file_encoder->private_->frames_written = max(file_encoder->private_->frames_written, current_frame+1);
802                 /*@@@ We would like to add an '&& samples > 0' to the if
803                  * clause here but currently because of the nature of our Ogg
804                  * writing implementation, 'samples' is always 0 (see
805                  * ogg_encoder_aspect.c).  The downside is extra progress
806                  * callbacks.
807                  */
808                 if(0 != file_encoder->private_->progress_callback)
809                         file_encoder->private_->progress_callback(file_encoder, file_encoder->private_->bytes_written, file_encoder->private_->samples_written, file_encoder->private_->frames_written, file_encoder->private_->total_frames_estimate, file_encoder->private_->client_data);
810                 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
811         }
812         else
813                 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
814 }