add OggFLAC__stream_encoder_get_resolved_state_string()
[flac.git] / src / libOggFLAC / stream_encoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002,2003  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 calloc() */
34 #include <string.h> /* for memcpy() */
35 #include <ogg/ogg.h>
36 #include "FLAC/assert.h"
37 #include "OggFLAC/stream_decoder.h"
38 #include "protected/stream_encoder.h"
39
40 /***********************************************************************
41  *
42  * Private class method prototypes
43  *
44  ***********************************************************************/
45
46 /* unpublished debug routines */
47 extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
48 extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
49 extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
50
51 static void set_defaults_(OggFLAC__StreamEncoder *encoder);
52 static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
53 static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
54
55
56 /***********************************************************************
57  *
58  * Private class data
59  *
60  ***********************************************************************/
61
62 typedef struct OggFLAC__StreamEncoderPrivate {
63         OggFLAC__StreamEncoderWriteCallback write_callback;
64         void *client_data;
65         FLAC__StreamEncoder *FLAC_stream_encoder;
66         /* internal vars (all the above are class settings) */
67         FLAC__bool is_first_packet;
68         FLAC__uint64 samples_written;
69         struct {
70                 ogg_stream_state stream_state;
71                 ogg_page page;
72         } ogg;
73 } OggFLAC__StreamEncoderPrivate;
74
75
76 /***********************************************************************
77  *
78  * Public static class data
79  *
80  ***********************************************************************/
81
82 OggFLAC_API const char * const OggFLAC__StreamEncoderStateString[] = {
83         "OggFLAC__STREAM_ENCODER_OK",
84         "OggFLAC__STREAM_ENCODER_OGG_ERROR",
85         "OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR",
86         "OggFLAC__STREAM_ENCODER_INVALID_CALLBACK",
87         "OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
88         "OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
89         "OggFLAC__STREAM_ENCODER_UNINITIALIZED"
90 };
91
92
93 /***********************************************************************
94  *
95  * Class constructor/destructor
96  *
97  */
98 OggFLAC_API OggFLAC__StreamEncoder *OggFLAC__stream_encoder_new()
99 {
100         OggFLAC__StreamEncoder *encoder;
101
102         encoder = (OggFLAC__StreamEncoder*)calloc(1, sizeof(OggFLAC__StreamEncoder));
103         if(encoder == 0) {
104                 return 0;
105         }
106
107         encoder->protected_ = (OggFLAC__StreamEncoderProtected*)calloc(1, sizeof(OggFLAC__StreamEncoderProtected));
108         if(encoder->protected_ == 0) {
109                 free(encoder);
110                 return 0;
111         }
112
113         encoder->private_ = (OggFLAC__StreamEncoderPrivate*)calloc(1, sizeof(OggFLAC__StreamEncoderPrivate));
114         if(encoder->private_ == 0) {
115                 free(encoder->protected_);
116                 free(encoder);
117                 return 0;
118         }
119
120         encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new();
121         if(0 == encoder->private_->FLAC_stream_encoder) {
122                 free(encoder->private_);
123                 free(encoder->protected_);
124                 free(encoder);
125                 return 0;
126         }
127
128         set_defaults_(encoder);
129
130         encoder->protected_->state = OggFLAC__STREAM_ENCODER_UNINITIALIZED;
131
132         return encoder;
133 }
134
135 OggFLAC_API void OggFLAC__stream_encoder_delete(OggFLAC__StreamEncoder *encoder)
136 {
137         FLAC__ASSERT(0 != encoder);
138         FLAC__ASSERT(0 != encoder->protected_);
139         FLAC__ASSERT(0 != encoder->private_);
140         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
141
142         (void)OggFLAC__stream_encoder_finish(encoder);
143
144         FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder);
145
146         free(encoder->private_);
147         free(encoder->protected_);
148         free(encoder);
149 }
150
151
152 /***********************************************************************
153  *
154  * Public class methods
155  *
156  ***********************************************************************/
157
158 OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_init(OggFLAC__StreamEncoder *encoder)
159 {
160         FLAC__ASSERT(0 != encoder);
161
162         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
163                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
164
165         if(0 == encoder->private_->write_callback)
166                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_INVALID_CALLBACK;
167
168         if(ogg_stream_init(&encoder->private_->ogg.stream_state, encoder->protected_->serial_number) != 0)
169                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
170
171         FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_);
172         FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_);
173         FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder);
174
175         if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK)
176                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
177
178         encoder->private_->is_first_packet = true;
179         encoder->private_->samples_written = 0;
180
181         return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OK;
182 }
183
184 OggFLAC_API void OggFLAC__stream_encoder_finish(OggFLAC__StreamEncoder *encoder)
185 {
186         FLAC__ASSERT(0 != encoder);
187         FLAC__ASSERT(0 != encoder->private_);
188         FLAC__ASSERT(0 != encoder->protected_);
189
190         if(encoder->protected_->state == OggFLAC__STREAM_ENCODER_UNINITIALIZED)
191                 return;
192
193         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
194
195         FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder);
196
197         (void)ogg_stream_clear(&encoder->private_->ogg.stream_state);
198
199         set_defaults_(encoder);
200
201         encoder->protected_->state = OggFLAC__STREAM_ENCODER_UNINITIALIZED;
202 }
203
204 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_serial_number(OggFLAC__StreamEncoder *encoder, long value)
205 {
206         FLAC__ASSERT(0 != encoder);
207         FLAC__ASSERT(0 != encoder->private_);
208         FLAC__ASSERT(0 != encoder->protected_);
209         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
210         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
211                 return false;
212         encoder->protected_->serial_number = value;
213         return true;
214 }
215
216 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_verify(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
217 {
218         FLAC__ASSERT(0 != encoder);
219         FLAC__ASSERT(0 != encoder->private_);
220         FLAC__ASSERT(0 != encoder->protected_);
221         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
222         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
223                 return false;
224         return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value);
225 }
226
227 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_streamable_subset(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
228 {
229         FLAC__ASSERT(0 != encoder);
230         FLAC__ASSERT(0 != encoder->private_);
231         FLAC__ASSERT(0 != encoder->protected_);
232         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
233         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
234                 return false;
235         return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value);
236 }
237
238 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
239 {
240         FLAC__ASSERT(0 != encoder);
241         FLAC__ASSERT(0 != encoder->private_);
242         FLAC__ASSERT(0 != encoder->protected_);
243         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
244         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
245                 return false;
246         return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
247 }
248
249 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_loose_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
250 {
251         FLAC__ASSERT(0 != encoder);
252         FLAC__ASSERT(0 != encoder->private_);
253         FLAC__ASSERT(0 != encoder->protected_);
254         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
255         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
256                 return false;
257         return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
258 }
259
260 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_channels(OggFLAC__StreamEncoder *encoder, unsigned value)
261 {
262         FLAC__ASSERT(0 != encoder);
263         FLAC__ASSERT(0 != encoder->private_);
264         FLAC__ASSERT(0 != encoder->protected_);
265         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
266         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
267                 return false;
268         return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value);
269 }
270
271 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_bits_per_sample(OggFLAC__StreamEncoder *encoder, unsigned value)
272 {
273         FLAC__ASSERT(0 != encoder);
274         FLAC__ASSERT(0 != encoder->private_);
275         FLAC__ASSERT(0 != encoder->protected_);
276         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
277         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
278                 return false;
279         return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value);
280 }
281
282 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEncoder *encoder, unsigned value)
283 {
284         FLAC__ASSERT(0 != encoder);
285         FLAC__ASSERT(0 != encoder->private_);
286         FLAC__ASSERT(0 != encoder->protected_);
287         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
288         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
289                 return false;
290         return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value);
291 }
292
293 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEncoder *encoder, unsigned value)
294 {
295         FLAC__ASSERT(0 != encoder);
296         FLAC__ASSERT(0 != encoder->private_);
297         FLAC__ASSERT(0 != encoder->protected_);
298         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
299         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
300                 return false;
301         return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
302 }
303
304 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__StreamEncoder *encoder, unsigned value)
305 {
306         FLAC__ASSERT(0 != encoder);
307         FLAC__ASSERT(0 != encoder->private_);
308         FLAC__ASSERT(0 != encoder->protected_);
309         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
310         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
311                 return false;
312         return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value);
313 }
314
315 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_qlp_coeff_precision(OggFLAC__StreamEncoder *encoder, unsigned value)
316 {
317         FLAC__ASSERT(0 != encoder);
318         FLAC__ASSERT(0 != encoder->private_);
319         FLAC__ASSERT(0 != encoder->protected_);
320         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
321         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
322                 return false;
323         return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value);
324 }
325
326 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
327 {
328         FLAC__ASSERT(0 != encoder);
329         FLAC__ASSERT(0 != encoder->private_);
330         FLAC__ASSERT(0 != encoder->protected_);
331         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
332         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
333                 return false;
334         return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value);
335 }
336
337 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_escape_coding(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
338 {
339         FLAC__ASSERT(0 != encoder);
340         FLAC__ASSERT(0 != encoder->private_);
341         FLAC__ASSERT(0 != encoder->protected_);
342         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
343         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
344                 return false;
345         return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value);
346 }
347
348 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_exhaustive_model_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
349 {
350         FLAC__ASSERT(0 != encoder);
351         FLAC__ASSERT(0 != encoder->private_);
352         FLAC__ASSERT(0 != encoder->protected_);
353         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
354         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
355                 return false;
356         return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value);
357 }
358
359 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_min_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value)
360 {
361         FLAC__ASSERT(0 != encoder);
362         FLAC__ASSERT(0 != encoder->private_);
363         FLAC__ASSERT(0 != encoder->protected_);
364         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
365         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
366                 return false;
367         return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
368 }
369
370 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value)
371 {
372         FLAC__ASSERT(0 != encoder);
373         FLAC__ASSERT(0 != encoder->private_);
374         FLAC__ASSERT(0 != encoder->protected_);
375         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
376         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
377                 return false;
378         return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
379 }
380
381 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(OggFLAC__StreamEncoder *encoder, unsigned value)
382 {
383         FLAC__ASSERT(0 != encoder);
384         FLAC__ASSERT(0 != encoder->private_);
385         FLAC__ASSERT(0 != encoder->protected_);
386         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
387         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
388                 return false;
389         return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value);
390 }
391
392 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLAC__StreamEncoder *encoder, FLAC__uint64 value)
393 {
394         FLAC__ASSERT(0 != encoder);
395         FLAC__ASSERT(0 != encoder->private_);
396         FLAC__ASSERT(0 != encoder->protected_);
397         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
398         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
399                 return false;
400         return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value);
401 }
402
403 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
404 {
405         FLAC__ASSERT(0 != encoder);
406         FLAC__ASSERT(0 != encoder->private_);
407         FLAC__ASSERT(0 != encoder->protected_);
408         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
409         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
410                 return false;
411         return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
412 }
413
414 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_write_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderWriteCallback value)
415 {
416         FLAC__ASSERT(0 != encoder);
417         FLAC__ASSERT(0 != encoder->private_);
418         FLAC__ASSERT(0 != encoder->protected_);
419         FLAC__ASSERT(0 != value);
420         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
421                 return false;
422         encoder->private_->write_callback = value;
423         return true;
424 }
425
426 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_client_data(OggFLAC__StreamEncoder *encoder, void *value)
427 {
428         FLAC__ASSERT(0 != encoder);
429         FLAC__ASSERT(0 != encoder->private_);
430         FLAC__ASSERT(0 != encoder->protected_);
431         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
432                 return false;
433         encoder->private_->client_data = value;
434         return true;
435 }
436
437 /*
438  * These three functions are not static, but not publically exposed in
439  * include/FLAC/ either.  They are used by the test suite.
440  */
441 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
442 {
443         FLAC__ASSERT(0 != encoder);
444         FLAC__ASSERT(0 != encoder->private_);
445         FLAC__ASSERT(0 != encoder->protected_);
446         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
447                 return false;
448         return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value);
449 }
450
451 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
452 {
453         FLAC__ASSERT(0 != encoder);
454         FLAC__ASSERT(0 != encoder->private_);
455         FLAC__ASSERT(0 != encoder->protected_);
456         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
457                 return false;
458         return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value);
459 }
460
461 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool 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__STREAM_ENCODER_UNINITIALIZED)
467                 return false;
468         return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value);
469 }
470
471 OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_get_state(const OggFLAC__StreamEncoder *encoder)
472 {
473         FLAC__ASSERT(0 != encoder);
474         FLAC__ASSERT(0 != encoder->private_);
475         FLAC__ASSERT(0 != encoder->protected_);
476         return encoder->protected_->state;
477 }
478
479 OggFLAC_API FLAC__StreamEncoderState OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(const OggFLAC__StreamEncoder *encoder)
480 {
481         FLAC__ASSERT(0 != encoder);
482         FLAC__ASSERT(0 != encoder->private_);
483         FLAC__ASSERT(0 != encoder->protected_);
484         return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder);
485 }
486
487 OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_encoder_get_verify_decoder_state(const OggFLAC__StreamEncoder *encoder)
488 {
489         FLAC__ASSERT(0 != encoder);
490         FLAC__ASSERT(0 != encoder->private_);
491         FLAC__ASSERT(0 != encoder->protected_);
492         return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder);
493 }
494
495 OggFLAC_API const char *OggFLAC__stream_encoder_get_resolved_state_string(const OggFLAC__StreamEncoder *encoder)
496 {
497         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR)
498                 return OggFLAC__StreamEncoderStateString[encoder->protected_->state];
499         else
500                 return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->FLAC_stream_encoder);
501 }
502
503 OggFLAC_API void OggFLAC__stream_encoder_get_verify_decoder_error_stats(const OggFLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
504 {
505         FLAC__ASSERT(0 != encoder);
506         FLAC__ASSERT(0 != encoder->private_);
507         FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
508 }
509
510 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_verify(const OggFLAC__StreamEncoder *encoder)
511 {
512         FLAC__ASSERT(0 != encoder);
513         FLAC__ASSERT(0 != encoder->private_);
514         FLAC__ASSERT(0 != encoder->protected_);
515         return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder);
516 }
517
518 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_streamable_subset(const OggFLAC__StreamEncoder *encoder)
519 {
520         FLAC__ASSERT(0 != encoder);
521         FLAC__ASSERT(0 != encoder->private_);
522         FLAC__ASSERT(0 != encoder->protected_);
523         return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder);
524 }
525
526 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_mid_side_stereo(const OggFLAC__StreamEncoder *encoder)
527 {
528         FLAC__ASSERT(0 != encoder);
529         FLAC__ASSERT(0 != encoder->private_);
530         FLAC__ASSERT(0 != encoder->protected_);
531         return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
532 }
533
534 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_loose_mid_side_stereo(const OggFLAC__StreamEncoder *encoder)
535 {
536         FLAC__ASSERT(0 != encoder);
537         FLAC__ASSERT(0 != encoder->private_);
538         FLAC__ASSERT(0 != encoder->protected_);
539         return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
540 }
541
542 OggFLAC_API unsigned OggFLAC__stream_encoder_get_channels(const OggFLAC__StreamEncoder *encoder)
543 {
544         FLAC__ASSERT(0 != encoder);
545         FLAC__ASSERT(0 != encoder->private_);
546         FLAC__ASSERT(0 != encoder->protected_);
547         return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder);
548 }
549
550 OggFLAC_API unsigned OggFLAC__stream_encoder_get_bits_per_sample(const OggFLAC__StreamEncoder *encoder)
551 {
552         FLAC__ASSERT(0 != encoder);
553         FLAC__ASSERT(0 != encoder->private_);
554         FLAC__ASSERT(0 != encoder->protected_);
555         return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder);
556 }
557
558 OggFLAC_API unsigned OggFLAC__stream_encoder_get_sample_rate(const OggFLAC__StreamEncoder *encoder)
559 {
560         FLAC__ASSERT(0 != encoder);
561         FLAC__ASSERT(0 != encoder->private_);
562         FLAC__ASSERT(0 != encoder->protected_);
563         return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder);
564 }
565
566 OggFLAC_API unsigned OggFLAC__stream_encoder_get_blocksize(const OggFLAC__StreamEncoder *encoder)
567 {
568         FLAC__ASSERT(0 != encoder);
569         FLAC__ASSERT(0 != encoder->private_);
570         FLAC__ASSERT(0 != encoder->protected_);
571         return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
572 }
573
574 OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_lpc_order(const OggFLAC__StreamEncoder *encoder)
575 {
576         FLAC__ASSERT(0 != encoder);
577         FLAC__ASSERT(0 != encoder->private_);
578         FLAC__ASSERT(0 != encoder->protected_);
579         return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder);
580 }
581
582 OggFLAC_API unsigned OggFLAC__stream_encoder_get_qlp_coeff_precision(const OggFLAC__StreamEncoder *encoder)
583 {
584         FLAC__ASSERT(0 != encoder);
585         FLAC__ASSERT(0 != encoder->private_);
586         FLAC__ASSERT(0 != encoder->protected_);
587         return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder);
588 }
589
590 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__StreamEncoder *encoder)
591 {
592         FLAC__ASSERT(0 != encoder);
593         FLAC__ASSERT(0 != encoder->private_);
594         FLAC__ASSERT(0 != encoder->protected_);
595         return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder);
596 }
597
598 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_escape_coding(const OggFLAC__StreamEncoder *encoder)
599 {
600         FLAC__ASSERT(0 != encoder);
601         FLAC__ASSERT(0 != encoder->private_);
602         FLAC__ASSERT(0 != encoder->protected_);
603         return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder);
604 }
605
606 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_exhaustive_model_search(const OggFLAC__StreamEncoder *encoder)
607 {
608         FLAC__ASSERT(0 != encoder);
609         FLAC__ASSERT(0 != encoder->private_);
610         FLAC__ASSERT(0 != encoder->protected_);
611         return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder);
612 }
613
614 OggFLAC_API unsigned OggFLAC__stream_encoder_get_min_residual_partition_order(const OggFLAC__StreamEncoder *encoder)
615 {
616         FLAC__ASSERT(0 != encoder);
617         FLAC__ASSERT(0 != encoder->private_);
618         FLAC__ASSERT(0 != encoder->protected_);
619         return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder);
620 }
621
622 OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_residual_partition_order(const OggFLAC__StreamEncoder *encoder)
623 {
624         FLAC__ASSERT(0 != encoder);
625         FLAC__ASSERT(0 != encoder->private_);
626         FLAC__ASSERT(0 != encoder->protected_);
627         return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder);
628 }
629
630 OggFLAC_API unsigned OggFLAC__stream_encoder_get_rice_parameter_search_dist(const OggFLAC__StreamEncoder *encoder)
631 {
632         FLAC__ASSERT(0 != encoder);
633         FLAC__ASSERT(0 != encoder->private_);
634         FLAC__ASSERT(0 != encoder->protected_);
635         return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder);
636 }
637
638 OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(const OggFLAC__StreamEncoder *encoder)
639 {
640         FLAC__ASSERT(0 != encoder);
641         FLAC__ASSERT(0 != encoder->private_);
642         FLAC__ASSERT(0 != encoder->protected_);
643         return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
644 }
645
646 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process(OggFLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
647 {
648         FLAC__ASSERT(0 != encoder);
649         FLAC__ASSERT(0 != encoder->private_);
650         FLAC__ASSERT(0 != encoder->protected_);
651         return FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples);
652 }
653
654 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
655 {
656         FLAC__ASSERT(0 != encoder);
657         FLAC__ASSERT(0 != encoder->private_);
658         FLAC__ASSERT(0 != encoder->protected_);
659         return FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples);
660 }
661
662 /***********************************************************************
663  *
664  * Private class methods
665  *
666  ***********************************************************************/
667
668 void set_defaults_(OggFLAC__StreamEncoder *encoder)
669 {
670         FLAC__ASSERT(0 != encoder);
671
672         encoder->private_->write_callback = 0;
673         encoder->private_->client_data = 0;
674         encoder->protected_->serial_number = 0;
675 }
676
677 FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
678 {
679         OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data;
680         ogg_packet packet;
681         const FLAC__uint64 total_samples_estimate = FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
682
683         (void)unused;
684         FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
685
686         encoder->private_->samples_written += samples;
687
688         memset(&packet, 0, sizeof(packet));
689         packet.packet = (unsigned char *)buffer;
690         packet.granulepos = encoder->private_->samples_written;
691         /* WATCHOUT:
692          * This depends on the behavior of FLAC__StreamEncoder that 'samples'
693          * will be 0 for metadata writes.
694          */
695         packet.packetno = (samples == 0? -1 : (int)current_frame);
696         packet.bytes = bytes;
697
698         if(encoder->private_->is_first_packet) {
699                 packet.b_o_s = 1;
700                 encoder->private_->is_first_packet = false;
701         }
702
703         if(total_samples_estimate > 0 && total_samples_estimate == encoder->private_->samples_written)
704                 packet.e_o_s = 1;
705
706         if(ogg_stream_packetin(&encoder->private_->ogg.stream_state, &packet) != 0)
707                 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
708
709         while(ogg_stream_pageout(&encoder->private_->ogg.stream_state, &encoder->private_->ogg.page) != 0) {
710                 if(encoder->private_->write_callback(encoder, encoder->private_->ogg.page.header, encoder->private_->ogg.page.header_len, 0, current_frame, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
711                         return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
712
713                 if(encoder->private_->write_callback(encoder, encoder->private_->ogg.page.body, encoder->private_->ogg.page.body_len, 0, current_frame, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
714                         return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
715         }
716
717         return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
718 }
719
720 void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
721 {
722         /*
723          * We don't try to go back and update metadata blocks by mucking
724          * around inside the Ogg layer.  Maybe someday we will care to
725          * and an OggFLAC__SeekableStreamEncoder and OggFLAC__FileEncoder
726          * will be possible but it may just never be useful.
727          */
728         (void)encoder, (void)metadata, (void)client_data;
729 }