flac/
flac.rs

1#![allow(dead_code)]
2#![allow(unused_imports)]
3#![allow(clippy::map_entry)]
4#![allow(clippy::type_complexity)]
5#![allow(clippy::too_many_arguments)]
6#![allow(clippy::enum_variant_names)]
7
8const SHOW_CALLBACKS: bool = false;
9
10use std::{
11    any::Any,
12    borrow::Cow,
13    ffi::{CStr, c_void},
14    fmt::{self, Debug, Display, Formatter},
15    io::{self, Read, Write, Seek, SeekFrom},
16    ops::{Deref, DerefMut},
17    collections::BTreeMap,
18    ptr,
19    slice,
20};
21
22/// ## The compression level of the FLAC file
23/// A higher number means less file size. Default compression level is 5
24#[derive(Debug, Clone, Copy, PartialEq)]
25pub enum FlacCompression {
26    /// Almost no compression
27    Level0 = 0,
28    Level1 = 1,
29    Level2 = 2,
30    Level3 = 3,
31    Level4 = 4,
32    Level5 = 5,
33    Level6 = 6,
34    Level7 = 7,
35
36    /// Maximum compression
37    Level8 = 8
38}
39
40/// ## Parameters for the encoder to encode the audio.
41#[derive(Debug, Clone, Copy, PartialEq)]
42pub struct FlacEncoderParams {
43    /// * If set to true, the FLAC encoder will send the encoded data to a decoder to verify if the encoding is successful, and the encoding process will be slower.
44    pub verify_decoded: bool,
45
46    /// * The compression level of the FLAC file, a higher number means less file size.
47    pub compression: FlacCompression,
48
49    /// * Num channels of the audio file, max channels is 8.
50    pub channels: u16,
51
52    /// * The sample rate of the audio file. Every FLAC frame contains this value.
53    pub sample_rate: u32,
54
55    /// * How many bits in an `i32` are valid for a sample, for example, if this value is 16, your `i32` sample should be between -32768 to +32767.
56    ///   Because the FLAC encoder **only eats `[i32]`** , and you can't just pass `[i16]` to it.
57    ///   It seems like 8, 12, 16, 20, 24, 32 are valid values for this field.
58    pub bits_per_sample: u32,
59
60    /// * How many samples you will put into the encoder, set to zero if you don't know.
61    pub total_samples_estimate: u64,
62}
63
64impl FlacEncoderParams {
65    pub fn new() -> Self {
66        Self {
67            verify_decoded: false,
68            compression: FlacCompression::Level5,
69            channels: 2,
70            sample_rate: 44100,
71            bits_per_sample: 16,
72            total_samples_estimate: 0,
73        }
74    }
75}
76
77impl Default for FlacEncoderParams {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83#[cfg(feature = "id3")]
84use id3::{self, TagLike};
85
86use libflac_sys::*;
87
88/// ## A trait for me to coveniently write `FlacDecoderError`, `FlacDecoderInitError`, `FlacEncoderError`, `FlacEncoderInitError`
89/// Not for you to use.
90pub trait FlacError: Any {
91    /// * This method allows the trait to be able to downcast to a specific error struct.
92    fn as_any(&self) -> &dyn Any;
93
94    /// * Get the error or status code from the error struct. The code depends on which type of the error struct.
95    fn get_code(&self) -> u32;
96
97    /// * Get the message that describes the error code, mostly useful if you don't know what exact the error type is.
98    fn get_message(&self) -> &'static str;
99
100    /// * On which function call to get the error. Also useful for addressing errors.
101    fn get_function(&self) -> &'static str;
102
103    /// * This function is implemented by the specific error struct, each struct has a different way to describe the code.
104    fn get_message_from_code(&self) -> &'static str;
105
106    /// * The common formatter for the error.
107    fn format(&self, f: &mut Formatter) -> fmt::Result {
108        let code = self.get_code();
109        let message = self.get_message();
110        let function = self.get_function();
111        write!(f, "Code: {code}, function: {function}, message: {message}")?;
112        Ok(())
113    }
114}
115
116macro_rules! impl_FlacError {
117    ($error:ty) => {
118        impl FlacError for $error {
119            fn as_any(&self) -> &dyn Any {self}
120            fn get_code(&self) -> u32 {self.code}
121            fn get_message(&self) -> &'static str {self.message}
122            fn get_function(&self) -> &'static str {self.function}
123            fn get_message_from_code(&self) -> &'static str {
124                Self::get_message_from_code(self.get_code())
125            }
126        }
127
128        impl std::error::Error for $error {}
129
130        impl Display for $error {
131            fn fmt(&self, f: &mut Formatter) -> fmt::Result {
132                <$error as FlacError>::format(self, f)
133            }
134        }
135    }
136}
137
138/// ## Error info for the encoder, most of the encoder functions return this.
139#[derive(Debug, Clone, Copy)]
140pub struct FlacEncoderError {
141    /// * This code is actually `FlacEncoderErrorCode`
142    pub code: u32,
143
144    /// * The description of the status, as a constant string from `libflac-sys`
145    pub message: &'static str,
146
147    /// * Which function generates this error
148    pub function: &'static str,
149}
150
151impl FlacEncoderError {
152    pub fn new(code: u32, function: &'static str) -> Self {
153        Self {
154            code,
155            message: Self::get_message_from_code(code),
156            function,
157        }
158    }
159
160    pub fn get_message_from_code(code: u32) -> &'static str {
161        unsafe {
162            CStr::from_ptr(*FLAC__StreamEncoderStateString.as_ptr().add(code as usize)).to_str().unwrap()
163        }
164    }
165}
166
167impl_FlacError!(FlacEncoderError);
168
169/// ## The error code for `FlacEncoderError`
170#[derive(Debug, Clone, Copy)]
171pub enum FlacEncoderErrorCode {
172    /// * The encoder is in the normal OK state and samples can be processed.
173    StreamEncoderOk = FLAC__STREAM_ENCODER_OK as isize,
174
175    /// * The encoder is in the uninitialized state; one of the FLAC__stream_encoder_init_*() functions must be called before samples can be processed.
176    StreamEncoderUninitialized = FLAC__STREAM_ENCODER_UNINITIALIZED as isize,
177
178    /// * An error occurred in the underlying Ogg layer.
179    StreamEncoderOggError = FLAC__STREAM_ENCODER_OGG_ERROR as isize,
180
181    /// * An error occurred in the underlying verify stream decoder; check FLAC__stream_encoder_get_verify_decoder_state().
182    StreamEncoderVerifyDecoderError = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR as isize,
183
184    /// * The verify decoder detected a mismatch between the original audio signal and the decoded audio signal.
185    StreamEncoderVerifyMismatchInAudioData = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA as isize,
186
187    /// * One of the closures returned a fatal error.
188    StreamEncoderClientError = FLAC__STREAM_ENCODER_CLIENT_ERROR as isize,
189
190    /// * An I/O error occurred while opening/reading/writing a file.
191    StreamEncoderIOError = FLAC__STREAM_ENCODER_IO_ERROR as isize,
192
193    /// * An error occurred while writing the stream; usually, the `on_write()` returned an error.
194    StreamEncoderFramingError = FLAC__STREAM_ENCODER_FRAMING_ERROR as isize,
195
196    /// * Memory allocation failed
197    StreamEncoderMemoryAllocationError = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR as isize,
198}
199
200impl Display for FlacEncoderErrorCode {
201    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
202        match self {
203            Self::StreamEncoderOk => write!(f, "The encoder is in the normal OK state and samples can be processed."),
204            Self::StreamEncoderUninitialized => write!(f, "The encoder is in the uninitialized state; one of the FLAC__stream_encoder_init_*() functions must be called before samples can be processed."),
205            Self::StreamEncoderOggError => write!(f, "An error occurred in the underlying Ogg layer."),
206            Self::StreamEncoderVerifyDecoderError => write!(f, "An error occurred in the underlying verify stream decoder; check FLAC__stream_encoder_get_verify_decoder_state()."),
207            Self::StreamEncoderVerifyMismatchInAudioData => write!(f, "The verify decoder detected a mismatch between the original audio signal and the decoded audio signal."),
208            Self::StreamEncoderClientError => write!(f, "One of the closures returned a fatal error."),
209            Self::StreamEncoderIOError => write!(f, "An I/O error occurred while opening/reading/writing a file."),
210            Self::StreamEncoderFramingError => write!(f, "An error occurred while writing the stream; usually, the `on_write()` returned an error."),
211            Self::StreamEncoderMemoryAllocationError => write!(f, "Memory allocation failed."),
212        }
213    }
214}
215
216impl From<u32> for FlacEncoderErrorCode {
217    fn from(code: u32) -> Self {
218        use FlacEncoderErrorCode::*;
219        match code {
220            FLAC__STREAM_ENCODER_OK => StreamEncoderOk,
221            FLAC__STREAM_ENCODER_UNINITIALIZED => StreamEncoderUninitialized,
222            FLAC__STREAM_ENCODER_OGG_ERROR => StreamEncoderOggError,
223            FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR => StreamEncoderVerifyDecoderError,
224            FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA => StreamEncoderVerifyMismatchInAudioData,
225            FLAC__STREAM_ENCODER_CLIENT_ERROR => StreamEncoderClientError,
226            FLAC__STREAM_ENCODER_IO_ERROR => StreamEncoderIOError,
227            FLAC__STREAM_ENCODER_FRAMING_ERROR  => StreamEncoderFramingError,
228            FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR => StreamEncoderMemoryAllocationError,
229            o => panic!("Not an encoder error code: {o}."),
230        }
231    }
232}
233
234impl std::error::Error for FlacEncoderErrorCode {}
235
236/// ## Error info for `initialize()`
237#[derive(Debug, Clone, Copy)]
238pub struct FlacEncoderInitError {
239    /// * This code is actually `FlacEncoderInitErrorCode`
240    pub code: u32,
241
242    /// * The description of the status, as a constant string from `libflac-sys`
243    pub message: &'static str,
244
245    /// * Which function generates this error
246    pub function: &'static str,
247}
248
249impl FlacEncoderInitError {
250    pub fn new(code: u32, function: &'static str) -> Self {
251        Self {
252            code,
253            message: Self::get_message_from_code(code),
254            function,
255        }
256    }
257
258    pub fn get_message_from_code(code: u32) -> &'static str {
259        unsafe {
260            CStr::from_ptr(*FLAC__StreamEncoderInitStatusString.as_ptr().add(code as usize)).to_str().unwrap()
261        }
262    }
263}
264
265impl_FlacError!(FlacEncoderInitError);
266
267/// ## The error code for `FlacEncoderInitError`
268#[derive(Debug, Clone, Copy)]
269pub enum FlacEncoderInitErrorCode {
270    /// * Initialization was successful
271    StreamEncoderInitStatusOk = FLAC__STREAM_ENCODER_INIT_STATUS_OK as isize,
272
273    /// * General failure to set up encoder; call FLAC__stream_encoder_get_state() for cause.
274    StreamEncoderInitStatusEncoderError = FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR as isize,
275
276    /// * The library was not compiled with support for the given container format.
277    StreamEncoderInitStatusUnsupportedContainer = FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER as isize,
278
279    /// * A required callback was not supplied.
280    StreamEncoderInitStatusInvalidCallbacks = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS as isize,
281
282    /// * The encoder has an invalid setting for number of channels.
283    StreamEncoderInitStatusInvalidNumberOfChannels = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS as isize,
284
285    /// * The encoder has an invalid setting for bits-per-sample. FLAC supports 4-32 bps.
286    StreamEncoderInitStatusInvalidBitsPerSample = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE as isize,
287
288    /// * The encoder has an invalid setting for the input sample rate.
289    StreamEncoderInitStatusInvalidSampleRate = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE as isize,
290
291    /// * The encoder has an invalid setting for the block size.
292    StreamEncoderInitStatusInvalidBlockSize = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE as isize,
293
294    /// * The encoder has an invalid setting for the maximum LPC order.
295    StreamEncoderInitStatusInvalidMaxLpcOrder = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER as isize,
296
297    /// * The encoder has an invalid setting for the precision of the quantized linear predictor coefficients.
298    StreamEncoderInitStatusInvalidQlpCoeffPrecision = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION as isize,
299
300    /// * The specified block size is less than the maximum LPC order.
301    StreamEncoderInitStatusBlockSizeTooSmallForLpcOrder = FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER as isize,
302
303    /// * The encoder is bound to the Subset but other settings violate it.
304    StreamEncoderInitStatusNotStreamable = FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE as isize,
305
306    /// * The metadata input to the encoder is invalid, in one of the following ways:
307    ///   * FLAC__stream_encoder_set_metadata() was called with a null pointer but a block count > 0
308    ///   * One of the metadata blocks contains an undefined type
309    ///   * It contains an illegal CUESHEET as checked by FLAC__format_cuesheet_is_legal()
310    ///   * It contains an illegal SEEKTABLE as checked by FLAC__format_seektable_is_legal()
311    ///   * It contains more than one SEEKTABLE block or more than one VORBIS_COMMENT block
312    ///   * FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED
313    ///   * FLAC__stream_encoder_init_*() was called when the encoder was already initialized, usually because FLAC__stream_encoder_finish() was not called.
314    StreamEncoderInitStatusInvalidMetadata = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA as isize,
315
316    /// * FLAC__stream_encoder_init_*() was called when the encoder was already initialized, usually because FLAC__stream_encoder_finish() was not called.
317    StreamEncoderInitStatusAlreadyInitialized = FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED as isize,
318}
319
320impl Display for FlacEncoderInitErrorCode {
321    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
322        match self {
323            Self::StreamEncoderInitStatusOk => write!(f, "Initialization was successful."),
324            Self::StreamEncoderInitStatusEncoderError => write!(f, "General failure to set up encoder; call FLAC__stream_encoder_get_state() for cause."),
325            Self::StreamEncoderInitStatusUnsupportedContainer => write!(f, "The library was not compiled with support for the given container format."),
326            Self::StreamEncoderInitStatusInvalidCallbacks => write!(f, "A required callback was not supplied."),
327            Self::StreamEncoderInitStatusInvalidNumberOfChannels => write!(f, "The encoder has an invalid setting for number of channels."),
328            Self::StreamEncoderInitStatusInvalidBitsPerSample => write!(f, "The encoder has an invalid setting for bits-per-sample. FLAC supports 4-32 bps."),
329            Self::StreamEncoderInitStatusInvalidSampleRate => write!(f, "The encoder has an invalid setting for the input sample rate."),
330            Self::StreamEncoderInitStatusInvalidBlockSize => write!(f, "The encoder has an invalid setting for the block size."),
331            Self::StreamEncoderInitStatusInvalidMaxLpcOrder => write!(f, "The encoder has an invalid setting for the maximum LPC order."),
332            Self::StreamEncoderInitStatusInvalidQlpCoeffPrecision => write!(f, "The encoder has an invalid setting for the precision of the quantized linear predictor coefficients."),
333            Self::StreamEncoderInitStatusBlockSizeTooSmallForLpcOrder => write!(f, "The specified block size is less than the maximum LPC order."),
334            Self::StreamEncoderInitStatusNotStreamable => write!(f, "The encoder is bound to the Subset but other settings violate it."),
335            Self::StreamEncoderInitStatusInvalidMetadata => write!(f, "The metadata input to the encoder is invalid, in one of the following ways:\n\n* FLAC__stream_encoder_set_metadata() was called with a null pointer but a block count > 0\n* One of the metadata blocks contains an undefined type\n* It contains an illegal CUESHEET as checked by FLAC__format_cuesheet_is_legal()\n* It contains an illegal SEEKTABLE as checked by FLAC__format_seektable_is_legal()\n* It contains more than one SEEKTABLE block or more than one VORBIS_COMMENT block\n* FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED\n* FLAC__stream_encoder_init_*() was called when the encoder was already initialized, usually because FLAC__stream_encoder_finish() was not called."),
336            Self::StreamEncoderInitStatusAlreadyInitialized => write!(f, "FLAC__stream_encoder_init_*() was called when the encoder was already initialized, usually because FLAC__stream_encoder_finish() was not called."),
337        }
338    }
339}
340
341impl From<u32> for FlacEncoderInitErrorCode {
342    fn from(code: u32) -> Self {
343        use FlacEncoderInitErrorCode::*;
344        match code {
345            FLAC__STREAM_ENCODER_INIT_STATUS_OK => StreamEncoderInitStatusOk,
346            FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR => StreamEncoderInitStatusEncoderError,
347            FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER => StreamEncoderInitStatusUnsupportedContainer,
348            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS => StreamEncoderInitStatusInvalidCallbacks,
349            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS => StreamEncoderInitStatusInvalidNumberOfChannels,
350            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE => StreamEncoderInitStatusInvalidBitsPerSample,
351            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE => StreamEncoderInitStatusInvalidSampleRate,
352            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE => StreamEncoderInitStatusInvalidBlockSize,
353            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER => StreamEncoderInitStatusInvalidMaxLpcOrder,
354            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION => StreamEncoderInitStatusInvalidQlpCoeffPrecision,
355            FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER => StreamEncoderInitStatusBlockSizeTooSmallForLpcOrder,
356            FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE => StreamEncoderInitStatusNotStreamable,
357            FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA => StreamEncoderInitStatusInvalidMetadata,
358            FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED => StreamEncoderInitStatusAlreadyInitialized,
359            o => panic!("Not an encoder init error code: {o}."),
360        }
361    }
362}
363
364impl std::error::Error for FlacEncoderInitErrorCode {}
365
366impl From<FlacEncoderError> for FlacEncoderInitError {
367    fn from(err: FlacEncoderError) -> Self {
368        Self {
369            code: err.code,
370            message: err.message,
371            function: err.function,
372        }
373    }
374}
375
376impl From<FlacEncoderInitError> for FlacEncoderError {
377    fn from(err: FlacEncoderInitError) -> Self {
378        Self {
379            code: err.code,
380            message: err.message,
381            function: err.function,
382        }
383    }
384}
385
386/// ## Available comment keys for metadata usage.
387pub const COMMENT_KEYS: [&str; 33] = [
388    "ACTOR",
389    "ALBUM",
390    "ARTIST",
391    "ALBUMARTIST",
392    "COMMENT",
393    "COMPOSER",
394    "CONTACT",
395    "COPYRIGHT",
396    "COVERART",
397    "COVERARTMIME",
398    "DATE",
399    "DESCRIPTION",
400    "DIRECTOR",
401    "ENCODED_BY",
402    "ENCODED_USING",
403    "ENCODER",
404    "ENCODER_OPTIONS",
405    "GENRE",
406    "ISRC",
407    "LICENSE",
408    "LOCATION",
409    "ORGANIZATION",
410    "PERFORMER",
411    "PRODUCER",
412    "REPLAYGAIN_ALBUM_GAIN",
413    "REPLAYGAIN_ALBUM_PEAK",
414    "REPLAYGAIN_TRACK_GAIN",
415    "REPLAYGAIN_TRACK_PEAK",
416    "TITLE",
417    "TRACKNUMBER",
418    "TRACKTOTAL",
419    "VERSION",
420    "vendor"
421];
422
423/// ## Picture data, normally the cover of the CD
424#[derive(Clone)]
425pub struct PictureData {
426    /// * The binary picture data as a byte array
427    pub picture: Vec<u8>,
428
429    /// * The mime type of the picture data
430    pub mime_type: String,
431
432    /// * The description
433    pub description: String,
434
435    /// * The width of the picture
436    pub width: u32,
437
438    /// * The height of the picture
439    pub height: u32,
440
441    /// * The color depth of the picture
442    pub depth: u32,
443
444    /// * How many colors in the picture
445    pub colors: u32,
446}
447
448impl Debug for PictureData {
449    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
450        fmt.debug_struct("PictureData")
451            .field("picture", &format_args!("[u8; {}]", self.picture.len()))
452            .field("mime_type", &self.mime_type)
453            .field("description", &self.description)
454            .field("width", &self.width)
455            .field("height", &self.height)
456            .field("depth", &self.depth)
457            .field("colors", &self.colors)
458            .finish()
459    }
460}
461
462impl PictureData {
463    pub fn new() -> Self {
464        Self {
465            picture: Vec::<u8>::new(),
466            mime_type: "".to_owned(),
467            description: "".to_owned(),
468            width: 0,
469            height: 0,
470            depth: 0,
471            colors: 0,
472        }
473    }
474
475    pub fn is_empty(&self) -> bool {
476        self.picture.is_empty()
477    }
478}
479
480impl Default for PictureData {
481    fn default() -> Self {
482        Self::new()
483    }
484}
485
486#[derive(Debug)]
487#[repr(C)]
488struct FlacMetadata {
489    /// * See [https://xiph.org/flac/api/group__flac__metadata__object.html]
490    metadata: *mut FLAC__StreamMetadata,
491}
492
493#[derive(Debug)]
494#[repr(C)]
495struct FlacCueTrackWrap {
496    track: *mut FLAC__StreamMetadata_CueSheet_Track,
497}
498
499impl FlacCueTrackWrap {
500    pub fn new() -> Result<Self, FlacEncoderError> {
501        let ret = Self {
502            track: unsafe {FLAC__metadata_object_cuesheet_track_new()},
503        };
504        if ret.track.is_null() {
505            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_cuesheet_track_new"))
506        } else {
507            Ok(ret)
508        }
509    }
510
511    pub fn get_ref_mut(&mut self) -> &mut FLAC__StreamMetadata_CueSheet_Track {
512        unsafe {&mut *self.track}
513    }
514
515    pub fn get_ptr(&self) -> *const FLAC__StreamMetadata_CueSheet_Track{
516        self.track as *const FLAC__StreamMetadata_CueSheet_Track
517    }
518
519    pub fn get_mut_ptr(&self) -> *mut FLAC__StreamMetadata_CueSheet_Track{
520        self.track
521    }
522}
523
524impl Default for FlacCueTrackWrap {
525    fn default() -> Self {
526        Self {
527            track: ptr::null_mut(),
528        }
529    }
530}
531
532impl Drop for FlacCueTrackWrap {
533    fn drop(&mut self) {
534        if !self.track.is_null() {
535            unsafe {FLAC__metadata_object_cuesheet_track_delete(self.track)};
536            self.track = ptr::null_mut();
537        }
538    }
539}
540
541fn make_sz(s: &str) -> String {
542    let mut s = s.to_owned();
543    if !s.ends_with('\0') {s.push('\0');}
544    s
545}
546
547/// ## The track type
548#[derive(Debug, Clone, Copy)]
549pub enum FlacTrackType {
550    Audio,
551    NonAudio,
552}
553
554impl Display for FlacTrackType {
555    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
556        match self {
557            Self::Audio => write!(f, "audio"),
558            Self::NonAudio => write!(f, "non-audio"),
559        }
560    }
561}
562
563#[derive(Debug, Clone, Copy)]
564#[repr(C)]
565pub struct FlacCueSheetIndex {
566    /// * Offset in samples, relative to the track offset, of the index point.
567    pub offset: u64,
568
569    /// * The index point number
570    pub number: u8,
571}
572
573#[derive(Clone)]
574#[repr(C)]
575pub struct FlacCueTrack {
576    /// * In samples
577    pub offset: u64,
578
579    /// * Track number
580    pub track_no: u8,
581
582    /// * ISRC
583    pub isrc: [i8; 13],
584
585    /// * What type is this track, is it audio or not.
586    pub type_: FlacTrackType,
587
588    /// * Pre_emphasis
589    pub pre_emphasis: bool,
590
591    /// * Indices
592    pub indices: Vec<FlacCueSheetIndex>,
593}
594
595impl FlacCueTrack {
596    pub fn get_isrc(&self) -> String {
597        String::from_utf8_lossy(&self.isrc.iter().map(|c|{*c as u8}).collect::<Vec<u8>>()).to_string()
598    }
599}
600
601impl Debug for FlacCueTrack {
602    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
603        f.debug_struct("FlacCueTrack")
604            .field("offset", &self.offset)
605            .field("track_no", &self.track_no)
606            .field("isrc", &self.get_isrc())
607            .field("type_", &self.type_)
608            .field("pre_emphasis", &self.pre_emphasis)
609            .field("indices", &self.indices)
610            .finish()
611    }
612}
613
614impl Display for FlacCueTrack {
615    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
616        f.debug_struct("FlacCueTrack")
617            .field("offset", &self.offset)
618            .field("track_no", &self.track_no)
619            .field("isrc", &self.get_isrc())
620            .field("type_", &self.type_)
621            .field("pre_emphasis", &self.pre_emphasis)
622            .field("indices", &self.indices)
623            .finish()
624    }
625}
626
627/// ## Cue sheet for the FLAC audio
628#[derive(Clone)]
629pub struct FlacCueSheet {
630    /// * media_catalog_number
631    pub media_catalog_number: [i8; 129],
632
633    /// * In samples
634    pub lead_in: u64,
635
636    /// * Is this FLAC file from a CD or not.
637    pub is_cd: bool,
638
639    /// * The tracks
640    pub tracks: BTreeMap<u8, FlacCueTrack>,
641}
642
643impl FlacCueSheet {
644    pub fn get_media_catalog_number(&self) -> String {
645        String::from_utf8_lossy(&self.media_catalog_number.iter().map(|c|{*c as u8}).collect::<Vec<u8>>()).to_string()
646    }
647}
648
649impl Debug for FlacCueSheet {
650    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
651        f.debug_struct("FlacCueSheet")
652            .field("media_catalog_number", &self.get_media_catalog_number())
653            .field("lead_in", &self.lead_in)
654            .field("is_cd", &self.is_cd)
655            .field("tracks", &self.tracks)
656            .finish()
657    }
658}
659
660impl Display for FlacCueSheet {
661    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
662        f.debug_struct("FlacCueSheet")
663            .field("media_catalog_number", &self.get_media_catalog_number())
664            .field("lead_in", &self.lead_in)
665            .field("is_cd", &self.is_cd)
666            .field("tracks", &self.tracks)
667            .finish()
668    }
669}
670
671impl FlacMetadata {
672    pub fn new_vorbis_comment() -> Result<Self, FlacEncoderError> {
673        let ret = Self {
674            metadata: unsafe {FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)},
675        };
676        if ret.metadata.is_null() {
677            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)"))
678        } else {
679            Ok(ret)
680        }
681    }
682
683    pub fn new_cue_sheet() -> Result<Self, FlacEncoderError> {
684        let ret = Self {
685            metadata: unsafe {FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)},
686        };
687        if ret.metadata.is_null() {
688            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)"))
689        } else {
690            Ok(ret)
691        }
692    }
693
694    pub fn new_picture() -> Result<Self, FlacEncoderError> {
695        let ret = Self {
696            metadata: unsafe {FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)},
697        };
698        if ret.metadata.is_null() {
699            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)"))
700        } else {
701            Ok(ret)
702        }
703    }
704
705    pub fn insert_comments(&self, key: &'static str, value: &str) -> Result<(), FlacEncoderError> {
706        unsafe {
707            // ATTENTION:
708            // Any strings to be added to the entry must be NUL terminated.
709            // Or you can see the `FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR` due to the failure to find the NUL terminator.
710            let szkey = make_sz(key);
711            let szvalue = make_sz(value);
712            let mut entry = FLAC__StreamMetadata_VorbisComment_Entry{length: 0, entry: ptr::null_mut()};
713            if FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair (
714                &mut entry as *mut FLAC__StreamMetadata_VorbisComment_Entry,
715                szkey.as_ptr() as *mut i8,
716                szvalue.as_ptr() as *mut i8
717            ) == 0 {
718                eprintln!("On set comment {key}: {value}: {:?}", FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair"));
719            }
720            if FLAC__metadata_object_vorbiscomment_append_comment(self.metadata, entry, 0) == 0 {
721                eprintln!("On set comment {key}: {value}: {:?}", FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_vorbiscomment_append_comment"));
722            }
723        }
724        Ok(())
725    }
726
727    pub fn insert_cue_track(&mut self, track_no: u8, cue_track: &FlacCueTrack) -> Result<(), FlacEncoderError> {
728        unsafe {
729            let mut track = FlacCueTrackWrap::new()?;
730            let track_data = track.get_ref_mut();
731            track_data.offset = cue_track.offset;
732            track_data.number = track_no;
733            track_data.isrc = cue_track.isrc;
734            track_data.set_type(match cue_track.type_ {
735                FlacTrackType::Audio => 0,
736                FlacTrackType::NonAudio => 1,
737            });
738            track_data.set_pre_emphasis(match cue_track.pre_emphasis {
739                true => 1,
740                false => 0,
741            });
742            track_data.num_indices = cue_track.indices.len() as u8;
743            let mut indices: Vec<FLAC__StreamMetadata_CueSheet_Index> = cue_track.indices.iter().map(|index| -> FLAC__StreamMetadata_CueSheet_Index {
744                FLAC__StreamMetadata_CueSheet_Index {
745                    offset: index.offset,
746                    number: index.number,
747                }
748            }).collect();
749            track_data.indices = indices.as_mut_ptr();
750            if FLAC__metadata_object_cuesheet_set_track(self.metadata, track_no as u32, track.get_mut_ptr(), 1) == 0 {
751                eprintln!("Failed to create new cuesheet track for {track_no} {cue_track}:  {:?}", FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_cuesheet_set_track"));
752            }
753        }
754        Ok(())
755    }
756
757    pub fn set_picture(&mut self, picture_binary: &mut [u8], description: &mut str, mime_type: &mut str) -> Result<(), FlacEncoderError> {
758        let mut desc_sz = make_sz(description);
759        let mut mime_sz = make_sz(mime_type);
760        unsafe {
761            if FLAC__metadata_object_picture_set_data(self.metadata, picture_binary.as_mut_ptr(), picture_binary.len() as u32, 0) == 0 {
762                Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_picture_set_data"))
763            } else if FLAC__metadata_object_picture_set_mime_type(self.metadata, desc_sz.as_mut_ptr() as *mut i8, 0) == 0 {
764                Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_picture_set_mime_type"))
765            } else if FLAC__metadata_object_picture_set_description(self.metadata, mime_sz.as_mut_ptr(), 0) == 0 {
766                Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__metadata_object_picture_set_description"))
767            } else {
768                Ok(())
769            }
770        }
771    }
772}
773
774impl Default for FlacMetadata {
775    fn default() -> Self {
776        Self {
777            metadata: ptr::null_mut(),
778        }
779    }
780}
781
782impl Drop for FlacMetadata {
783    fn drop(&mut self) {
784        if !self.metadata.is_null() {
785            unsafe {FLAC__metadata_object_delete(self.metadata)};
786            self.metadata = ptr::null_mut();
787        }
788    }
789}
790
791/// ## The encoder's core structure, but can't move after `initialize()` has been called.
792/// Use a `Box` to contain it, or just don't move it will be fine.
793pub struct FlacEncoderUnmovable<'a, WriteSeek>
794where
795    WriteSeek: Write + Seek + Debug {
796    /// * See: <https://xiph.org/flac/api/group__flac__stream__encoder.html>
797    encoder: *mut FLAC__StreamEncoder,
798
799    /// * This is a piece of allocated memory as the libFLAC form, for libFLAC to access the metadata that you provided to it.
800    metadata: Vec<FlacMetadata>,
801
802    /// * Is encoder initialized or not
803    encoder_initialized: bool,
804
805    /// * The parameters you provided to create the encoder.
806    params: FlacEncoderParams,
807
808    /// * The encoder uses this `writer` to write the FLAC file.
809    writer: WriteSeek,
810
811    /// * Your `on_write()` closure, to receive the encoded FLAC file pieces.
812    /// * Instead of just writing the data to the `writer`, you can do what you want to do to the data, and return a proper `Result`.
813    on_write: Box<dyn FnMut(&mut WriteSeek, &[u8]) -> Result<(), io::Error> + 'a>,
814
815    /// * Your `on_seek()` closure. Often works by calling `writer.seek()` to help your encoder to move the file pointer.
816    on_seek: Box<dyn FnMut(&mut WriteSeek, u64) -> Result<(), io::Error> + 'a>,
817
818    /// * Your `on_tell()` closure. Often works by calling `writer.stream_position()` to help your encoder to know the current write position.
819    on_tell: Box<dyn FnMut(&mut WriteSeek) -> Result<u64, io::Error> + 'a>,
820
821    /// * The metadata to be added to the FLAC file. You can only add the metadata before calling `initialize()`
822    comments: BTreeMap<&'static str, String>,
823
824    /// * The cue sheets to be added to the FLAC file. You can only add the cue sheets before calling `initialize()`
825    cue_sheets: Vec<FlacCueSheet>,
826
827    /// * The pictures to be added to the FLAC file. You can only add the pictures before calling `initialize()`
828    pictures: Vec<PictureData>,
829
830    /// * Did you called `finish()`. This variable prevents a duplicated finish.
831    finished: bool,
832}
833
834impl<'a, WriteSeek> FlacEncoderUnmovable<'a, WriteSeek>
835where
836    WriteSeek: Write + Seek + Debug {
837    pub fn new(
838        writer: WriteSeek,
839        on_write: Box<dyn FnMut(&mut WriteSeek, &[u8]) -> Result<(), io::Error> + 'a>,
840        on_seek: Box<dyn FnMut(&mut WriteSeek, u64) -> Result<(), io::Error> + 'a>,
841        on_tell: Box<dyn FnMut(&mut WriteSeek) -> Result<u64, io::Error> + 'a>,
842        params: &FlacEncoderParams
843    ) -> Result<Self, FlacEncoderError> {
844        let ret = Self {
845            encoder: unsafe {FLAC__stream_encoder_new()},
846            metadata: Vec::<FlacMetadata>::new(),
847            encoder_initialized: false,
848            params: *params,
849            writer,
850            on_write,
851            on_seek,
852            on_tell,
853            comments: BTreeMap::new(),
854            cue_sheets: Vec::new(),
855            pictures: Vec::new(),
856            finished: false,
857        };
858        if ret.encoder.is_null() {
859            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR, "FLAC__stream_encoder_new"))
860        } else {
861            Ok(ret)
862        }
863    }
864
865    /// * If the status code is ok then return `Ok(())` else return `Err()`
866    pub fn get_status_as_result(&self, function: &'static str) -> Result<(), FlacEncoderError> {
867        let code = unsafe {FLAC__stream_encoder_get_state(self.encoder)};
868        if code == 0 {
869            Ok(())
870        } else {
871            Err(FlacEncoderError::new(code, function))
872        }
873    }
874
875    /// * Regardless of the status code, just return it as an `Err()`
876    pub fn get_status_as_error(&self, function: &'static str) -> Result<(), FlacEncoderError> {
877        let code = unsafe {FLAC__stream_encoder_get_state(self.encoder)};
878        Err(FlacEncoderError::new(code, function))
879    }
880
881    /// * The pointer to the struct, as `client_data` to be transferred to a field of the libFLAC encoder `private_` struct.
882    /// * All of the callback functions need the `client_data` to retrieve `self`, and libFLAC forgot to provide a function for us to change the `client_data`
883    /// * That's why our struct is `Unmovable`
884    pub fn as_ptr(&self) -> *const Self {
885        self as *const Self
886    }
887
888    /// * The pointer to the struct, as `client_data` to be transferred to a field of the libFLAC encoder `private_` struct.
889    /// * All of the callback functions need the `client_data` to retrieve `self`, and libFLAC forgot to provide a function for us to change the `client_data`
890    /// * That's why our struct is `Unmovable`
891    pub fn as_mut_ptr(&mut self) -> *mut Self {
892        self as *mut Self
893    }
894
895    /// * Insert a metadata key-value pair before calling to `initialize()`
896    pub fn insert_comments(&mut self, key: &'static str, value: &str) -> Result<(), FlacEncoderInitError> {
897        if self.encoder_initialized {
898            Err(FlacEncoderInitError::new(FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED, "FlacEncoderUnmovable::insert_comments"))
899        } else {
900            if let Some(old_value) = self.comments.insert(key, value.to_owned()) {
901                eprintln!("\"{key}\" is changed to \"{value}\" from \"{old_value}\"");
902            }
903            Ok(())
904        }
905    }
906
907    /// * Insert a cue sheet before calling to `initialize()`
908    pub fn insert_cue_sheet(&mut self, cue_sheet: &FlacCueSheet) -> Result<(), FlacEncoderInitError> {
909        if self.encoder_initialized {
910            Err(FlacEncoderInitError::new(FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED, "FlacEncoderUnmovable::insert_cue_track"))
911        } else {
912            self.cue_sheets.push(cue_sheet.clone());
913            Ok(())
914        }
915    }
916
917    /// * Add a picture before calling to `initialize()`
918    pub fn add_picture(&mut self, picture_binary: &[u8], description: &str, mime_type: &str, width: u32, height: u32, depth: u32, colors: u32) -> Result<(), FlacEncoderInitError> {
919        if self.encoder_initialized {
920            Err(FlacEncoderInitError::new(FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED, "FlacEncoderUnmovable::set_picture"))
921        } else {
922            self.pictures.push(PictureData{
923                picture: picture_binary.to_vec(),
924                description: description.to_owned(),
925                mime_type: mime_type.to_owned(),
926                width,
927                height,
928                depth,
929                colors
930            });
931            Ok(())
932        }
933    }
934
935    #[cfg(feature = "id3")]
936    pub fn inherit_metadata_from_id3(&mut self, tag: &id3::Tag) -> Result<(), FlacEncoderInitError> {
937        if let Some(artist) = tag.artist() {self.insert_comments("ARTIST", artist)?;}
938        if let Some(album) = tag.album() {self.insert_comments("ALBUM", album)?;}
939        if let Some(title) = tag.title() {self.insert_comments("TITLE", title)?;}
940        if let Some(genre) = tag.genre() {self.insert_comments("GENRE", genre)?;}
941        for picture in tag.pictures() {
942            self.add_picture(&picture.data, &picture.description, &picture.mime_type, 0, 0, 0, 0)?;
943        }
944        let comm_str = tag.comments().enumerate().map(|(i, comment)| -> String {
945            let lang = &comment.lang;
946            let desc = &comment.description;
947            let text = &comment.text;
948            format!("Comment {i}:\n\tlang: {lang}\n\tdesc: {desc}\n\ttext: {text}")
949        }).collect::<Vec<String>>().join("\n");
950        if !comm_str.is_empty() {self.insert_comments("COMMENT", &comm_str)?;}
951        Ok(())
952    }
953
954    /// * The `initialize()` function. Sets up all of the callback functions, transfers all of the metadata to the encoder, and then sets `client_data` to the address of the `self` struct.
955    pub fn initialize(&mut self) -> Result<(), FlacEncoderError> {
956        if self.encoder_initialized {
957            return Err(FlacEncoderInitError::new(FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED, "FlacEncoderUnmovable::init").into())
958        }
959        unsafe {
960            if FLAC__stream_encoder_set_verify(self.encoder, if self.params.verify_decoded {1} else {0}) == 0 {
961                return self.get_status_as_error("FLAC__stream_encoder_set_verify");
962            }
963            if FLAC__stream_encoder_set_compression_level(self.encoder, self.params.compression as u32) == 0 {
964                return self.get_status_as_error("FLAC__stream_encoder_set_compression_level");
965            }
966            if FLAC__stream_encoder_set_channels(self.encoder, self.params.channels as u32) == 0 {
967                return self.get_status_as_error("FLAC__stream_encoder_set_channels");
968            }
969            if FLAC__stream_encoder_set_bits_per_sample(self.encoder, self.params.bits_per_sample) == 0 {
970                return self.get_status_as_error("FLAC__stream_encoder_set_bits_per_sample");
971            }
972            if FLAC__stream_encoder_set_sample_rate(self.encoder, self.params.sample_rate) == 0 {
973                return self.get_status_as_error("FLAC__stream_encoder_set_sample_rate");
974            }
975            if self.params.total_samples_estimate > 0 && FLAC__stream_encoder_set_total_samples_estimate(self.encoder, self.params.total_samples_estimate) == 0 {
976                return self.get_status_as_error("FLAC__stream_encoder_set_total_samples_estimate");
977            }
978
979            let set_metadata: Result<(), FlacEncoderError> = {
980                if !self.comments.is_empty() {
981                    let metadata = FlacMetadata::new_vorbis_comment()?;
982                    for (key, value) in self.comments.iter() {
983                        metadata.insert_comments(key, value)?;
984                    }
985                    self.metadata.push(metadata);
986                }
987                for cue_sheet in self.cue_sheets.iter() {
988                    let mut metadata = FlacMetadata::new_cue_sheet()?;
989                    for (track_no, cue_track) in cue_sheet.tracks.iter() {
990                        metadata.insert_cue_track(*track_no, cue_track)?;
991                    }
992                    self.metadata.push(metadata);
993                }
994                for picture in self.pictures.iter_mut() {
995                    let mut metadata = FlacMetadata::new_picture()?;
996                    metadata.set_picture(&mut picture.picture, &mut picture.description, &mut picture.mime_type)?;
997                    self.metadata.push(metadata);
998                }
999                if !self.metadata.is_empty() {
1000                    if FLAC__stream_encoder_set_metadata(self.encoder, self.metadata.as_mut_ptr() as *mut *mut FLAC__StreamMetadata, self.metadata.len() as u32) == 0 {
1001                        Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED, "FLAC__stream_encoder_set_metadata"))
1002                    } else {
1003                        Ok(())
1004                    }
1005                } else {
1006                    Ok(())
1007                }
1008            };
1009            if let Err(e) = set_metadata {
1010                eprintln!("When setting the metadata: {:?}", e);
1011            }
1012            let ret = FLAC__stream_encoder_init_stream(self.encoder,
1013                Some(Self::write_callback),
1014                Some(Self::seek_callback),
1015                Some(Self::tell_callback),
1016                Some(Self::metadata_callback),
1017                self.as_mut_ptr() as *mut c_void,
1018            );
1019            if ret != 0 {
1020                return Err(FlacEncoderInitError::new(ret, "FLAC__stream_encoder_init_stream").into());
1021            } else {
1022                self.encoder_initialized = true;
1023            }
1024        }
1025        self.finished = false;
1026        self.get_status_as_result("FlacEncoderUnmovable::Init()")
1027    }
1028
1029    /// * Retrieve the params from the encoder where you provided it for the creation of the encoder.
1030    pub fn get_params(&self) -> FlacEncoderParams {
1031        self.params
1032    }
1033
1034    unsafe extern "C" fn write_callback(_encoder: *const FLAC__StreamEncoder, buffer: *const u8, bytes: usize, _samples: u32, _current_frame: u32, client_data: *mut c_void) -> u32 {
1035        #[cfg(debug_assertions)]
1036        if SHOW_CALLBACKS {println!("write_callback([u8; {bytes}])");}
1037        let this = unsafe {&mut *(client_data as *mut Self)};
1038        match (this.on_write)(&mut this.writer, unsafe {slice::from_raw_parts(buffer, bytes)}) {
1039            Ok(_) => FLAC__STREAM_ENCODER_WRITE_STATUS_OK,
1040            Err(e) => {
1041                eprintln!("On `write_callback()`: {:?}", e);
1042                FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR
1043            },
1044        }
1045    }
1046
1047    unsafe extern "C" fn seek_callback(_encoder: *const FLAC__StreamEncoder, absolute_byte_offset: u64, client_data: *mut c_void) -> u32 {
1048        #[cfg(debug_assertions)]
1049        if SHOW_CALLBACKS {println!("seek_callback({absolute_byte_offset})");}
1050        let this = unsafe {&mut *(client_data as *mut Self)};
1051        match (this.on_seek)(&mut this.writer, absolute_byte_offset) {
1052            Ok(_) => FLAC__STREAM_ENCODER_SEEK_STATUS_OK,
1053            Err(e) => {
1054                match e.kind() {
1055                    io::ErrorKind::NotSeekable => FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED,
1056                    _ => FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR,
1057                }
1058            },
1059        }
1060    }
1061
1062    unsafe extern "C" fn tell_callback(_encoder: *const FLAC__StreamEncoder, absolute_byte_offset: *mut u64, client_data: *mut c_void) -> u32 {
1063        let this = unsafe {&mut *(client_data as *mut Self)};
1064        match (this.on_tell)(&mut this.writer) {
1065            Ok(offset) => {
1066                #[cfg(debug_assertions)]
1067                if SHOW_CALLBACKS {println!("tell_callback() == {offset}");}
1068                unsafe {*absolute_byte_offset = offset};
1069                FLAC__STREAM_ENCODER_TELL_STATUS_OK
1070            },
1071            Err(e) => {
1072                match e.kind() {
1073                    io::ErrorKind::NotSeekable => FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED,
1074                    _ => FLAC__STREAM_ENCODER_TELL_STATUS_ERROR,
1075                }
1076            },
1077        }
1078    }
1079
1080    unsafe extern "C" fn metadata_callback(_encoder: *const FLAC__StreamEncoder, metadata: *const FLAC__StreamMetadata, client_data: *mut c_void) {
1081        let _this = unsafe {&mut *(client_data as *mut Self)};
1082        let _meta = unsafe {*metadata};
1083        #[cfg(debug_assertions)]
1084        if SHOW_CALLBACKS {println!("{:?}", WrappedStreamMetadata(_meta))}
1085    }
1086
1087    /// * Calls your `on_tell()` closure to get the current writing position.
1088    pub fn tell(&mut self) -> Result<u64, io::Error> {
1089        (self.on_tell)(&mut self.writer)
1090    }
1091
1092    /// * Encode the interleaved samples (interleaved by channels)
1093    /// * See `FlacEncoderParams` for the information on how to provide your samples in the `[i32]` array.
1094    pub fn write_interleaved_samples(&mut self, samples: &[i32]) -> Result<(), FlacEncoderError> {
1095        #[cfg(debug_assertions)]
1096        if SHOW_CALLBACKS {println!("write_interleaved_samples([i32; {}])", samples.len());}
1097        if samples.is_empty() {return Ok(())}
1098        if samples.len() % self.params.channels as usize != 0 {
1099            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_FRAMING_ERROR, "FlacEncoderUnmovable::write_interleaved_samples"))
1100        } else {
1101            unsafe {
1102                if FLAC__stream_encoder_process_interleaved(self.encoder, samples.as_ptr(), samples.len() as u32 / self.params.channels as u32) == 0 {
1103                    return self.get_status_as_error("FLAC__stream_encoder_process_interleaved");
1104                }
1105            }
1106            Ok(())
1107        }
1108    }
1109
1110    /// * Encode mono audio. Regardless of the channel setting of the FLAC encoder, the sample will be duplicated to the number of channels to accomplish the encoding
1111    /// * See `FlacEncoderParams` for the information on how to provide your samples in the `[i32]` array.
1112    pub fn write_mono_channel(&mut self, monos: &[i32]) -> Result<(), FlacEncoderError> {
1113        #[cfg(debug_assertions)]
1114        if SHOW_CALLBACKS {println!("write_mono_channel([i32; {}])", monos.len());}
1115        if monos.is_empty() {return Ok(())}
1116        match self.params.channels {
1117            1 => unsafe {
1118                if FLAC__stream_encoder_process_interleaved(self.encoder, monos.as_ptr(), monos.len() as u32) == 0 {
1119                    return self.get_status_as_error("FLAC__stream_encoder_process_interleaved");
1120                }
1121                Ok(())
1122            },
1123            2 => self.write_stereos(&monos.iter().map(|mono| -> (i32, i32){(*mono, *mono)}).collect::<Vec<(i32, i32)>>()),
1124            o => self.write_frames(&monos.iter().map(|mono| -> Vec<i32> {(0..o).map(|_|{*mono}).collect()}).collect::<Vec<Vec<i32>>>()),
1125        }
1126    }
1127
1128    /// * Encode stereo audio, if the channels of the encoder are mono, the stereo samples will be turned to mono samples to encode.
1129    /// * If the channels of the encoder are stereo, then the samples will be encoded as it is.
1130    /// * If the encoder is multi-channel other than mono and stereo, an error is returned.
1131    /// * See `FlacEncoderParams` for the information on how to provide your samples in the `i32` way.
1132    pub fn write_stereos(&mut self, stereos: &[(i32, i32)]) -> Result<(), FlacEncoderError> {
1133        #[cfg(debug_assertions)]
1134        if SHOW_CALLBACKS {println!("write_stereos([(i32, i32); {}])", stereos.len());}
1135        if stereos.is_empty() {return Ok(())}
1136        match self.params.channels {
1137            1 => self.write_mono_channel(&stereos.iter().map(|(l, r): &(i32, i32)| -> i32 {((*l as i64 + *r as i64) / 2) as i32}).collect::<Vec<i32>>()),
1138            2 => unsafe {
1139                let samples: Vec<i32> = stereos.iter().flat_map(|(l, r): &(i32, i32)| -> [i32; 2] {[*l, *r]}).collect();
1140                if FLAC__stream_encoder_process_interleaved(self.encoder, samples.as_ptr(), stereos.len() as u32) == 0 {
1141                    return self.get_status_as_error("FLAC__stream_encoder_process_interleaved");
1142                }
1143                Ok(())
1144            },
1145            o => panic!("Can't turn stereo audio into {o} channels audio."),
1146        }
1147    }
1148
1149    /// * Encode multiple mono channels into the multi-channel encoder.
1150    /// * See `FlacEncoderParams` for the information on how to provide your samples in the `i32` way.
1151    pub fn write_monos(&mut self, monos: &[Vec<i32>]) -> Result<(), FlacEncoderError> {
1152        #[cfg(debug_assertions)]
1153        if SHOW_CALLBACKS {println!("write_monos([Vec<i32>; {}])", monos.len());}
1154        if monos.len() != self.params.channels as usize {
1155            Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_FRAMING_ERROR, "FlacEncoderUnmovable::write_monos"))
1156        } else {
1157            unsafe {
1158                let len = monos[0].len();
1159                for mono in monos.iter() {
1160                    if mono.len() != len {
1161                        return Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_FRAMING_ERROR, "FlacEncoderUnmovable::write_monos"));
1162                    }
1163                }
1164                let ptr_arr: Vec<*const i32> = monos.iter().map(|v|{v.as_ptr()}).collect();
1165                if FLAC__stream_encoder_process(self.encoder, ptr_arr.as_ptr(), len as u32) == 0 {
1166                    self.get_status_as_error("FLAC__stream_encoder_process")
1167                } else {
1168                    Ok(())
1169                }
1170            }
1171        }
1172    }
1173
1174    /// * Encode samples by the audio frame array. Each audio frame contains one sample for every channel.
1175    /// * See `FlacEncoderParams` for the information on how to provide your samples in the `i32` way.
1176    pub fn write_frames(&mut self, frames: &[Vec<i32>]) -> Result<(), FlacEncoderError> {
1177        #[cfg(debug_assertions)]
1178        if SHOW_CALLBACKS {println!("write_frames([Vec<i32>; {}])", frames.len());}
1179        if frames.is_empty() {return Ok(())}
1180        let samples: Vec<i32> = frames.iter().flat_map(|frame: &Vec<i32>| -> Vec<i32> {
1181            if frame.len() != self.params.channels as usize {
1182                panic!("On FlacEncoderUnmovable::write_frames(): a frame size {} does not match the encoder channels.", frame.len())
1183            } else {frame.to_vec()}
1184        }).collect();
1185        unsafe {
1186            if FLAC__stream_encoder_process_interleaved(self.encoder, samples.as_ptr(), frames.len() as u32) == 0 {
1187                return self.get_status_as_error("FLAC__stream_encoder_process_interleaved");
1188            }
1189        }
1190        Ok(())
1191    }
1192
1193    /// * After sending all of the samples to encode, must call `finish()` to complete encoding.
1194    pub fn finish(&mut self) -> Result<(), FlacEncoderError> {
1195        if self.finished {
1196            return Ok(())
1197        }
1198        #[cfg(debug_assertions)]
1199        if SHOW_CALLBACKS {println!("finish()");}
1200        unsafe {
1201            if FLAC__stream_encoder_finish(self.encoder) != 0 {
1202                match self.writer.seek(SeekFrom::End(0)) {
1203                    Ok(_) => {self.finished = true; Ok(())},
1204                    Err(_) => Err(FlacEncoderError::new(FLAC__STREAM_ENCODER_IO_ERROR, "self.writer.seek(SeekFrom::End(0))")),
1205                }
1206            } else {
1207                self.get_status_as_error("FLAC__stream_encoder_finish")
1208            }
1209        }
1210    }
1211
1212    fn on_drop(&mut self) {
1213        unsafe {
1214            if let Err(e) = self.finish() {
1215                eprintln!("On FlacEncoderUnmovable::finish(): {:?}", e);
1216            }
1217
1218            self.metadata.clear();
1219            FLAC__stream_encoder_delete(self.encoder);
1220        };
1221    }
1222
1223    /// * Call this function if you don't want the encoder anymore.
1224    pub fn finalize(self) {}
1225}
1226
1227impl<'a, WriteSeek> Debug for FlacEncoderUnmovable<'_, WriteSeek>
1228where
1229    WriteSeek: Write + Seek + Debug {
1230    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1231        fmt.debug_struct("FlacEncoderUnmovable")
1232            .field("encoder", &self.encoder)
1233            .field("params", &self.params)
1234            .field("writer", &self.writer)
1235            .field("on_write", &"{{closure}}")
1236            .field("on_seek", &"{{closure}}")
1237            .field("on_tell", &"{{closure}}")
1238            .field("comments", &self.comments)
1239            .field("cue_sheets", &self.cue_sheets)
1240            .field("pictures", &format_args!("..."))
1241            .field("finished", &self.finished)
1242            .finish()
1243    }
1244}
1245
1246impl<'a, WriteSeek> Drop for FlacEncoderUnmovable<'_, WriteSeek>
1247where
1248    WriteSeek: Write + Seek + Debug {
1249    fn drop(&mut self) {
1250        self.on_drop();
1251    }
1252}
1253
1254/// ## A wrapper for `FlacEncoderUnmovable`, which provides a Box to make `FlacEncoderUnmovable` never move.
1255/// This is the struct that should be mainly used by you.
1256pub struct FlacEncoder<'a, WriteSeek>
1257where
1258    WriteSeek: Write + Seek + Debug {
1259    encoder: Box<FlacEncoderUnmovable<'a, WriteSeek>>,
1260}
1261
1262impl<'a, WriteSeek> FlacEncoder<'a, WriteSeek>
1263where
1264    WriteSeek: Write + Seek + Debug {
1265    pub fn new(
1266        writer: WriteSeek,
1267        on_write: Box<dyn FnMut(&mut WriteSeek, &[u8]) -> Result<(), io::Error> + 'a>,
1268        on_seek: Box<dyn FnMut(&mut WriteSeek, u64) -> Result<(), io::Error> + 'a>,
1269        on_tell: Box<dyn FnMut(&mut WriteSeek) -> Result<u64, io::Error> + 'a>,
1270        params: &FlacEncoderParams
1271    ) -> Result<Self, FlacEncoderError> {
1272        Ok(Self {
1273            encoder: Box::new(FlacEncoderUnmovable::new(writer, on_write, on_seek, on_tell, params)?)
1274        })
1275    }
1276
1277    /// * Call this function if you don't want the encoder anymore.
1278    pub fn finalize(self) {}
1279}
1280
1281impl<'a, WriteSeek> Debug for FlacEncoder<'_, WriteSeek>
1282where
1283    WriteSeek: Write + Seek + Debug {
1284    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
1285        fmt.debug_struct("FlacEncoder")
1286            .field("encoder", &self.encoder)
1287            .finish()
1288    }
1289}
1290
1291impl<'a, WriteSeek> Deref for FlacEncoder<'a, WriteSeek>
1292where
1293    WriteSeek: Write + Seek + Debug {
1294    type Target = FlacEncoderUnmovable<'a, WriteSeek>;
1295    fn deref(&self) -> &FlacEncoderUnmovable<'a, WriteSeek> {
1296        &self.encoder
1297    }
1298}
1299
1300impl<'a, WriteSeek> DerefMut for FlacEncoder<'a, WriteSeek>
1301where
1302    WriteSeek: Write + Seek + Debug {
1303    fn deref_mut(&mut self) -> &mut FlacEncoderUnmovable<'a, WriteSeek> {
1304        &mut self.encoder
1305    }
1306}
1307
1308#[derive(Debug, Clone, Copy)]
1309pub struct FlacDecoderError {
1310    /// * This code is actually `FlacDecoderErrorCode`
1311    pub code: u32,
1312
1313    /// * The description of the status, as a constant string from `libflac-sys`
1314    pub message: &'static str,
1315
1316    /// * Which function generates this error
1317    pub function: &'static str,
1318}
1319
1320impl FlacDecoderError {
1321    pub fn new(code: u32, function: &'static str) -> Self {
1322        Self {
1323            code,
1324            message: Self::get_message_from_code(code),
1325            function,
1326        }
1327    }
1328
1329    pub fn get_message_from_code(code: u32) -> &'static str {
1330        unsafe {
1331            CStr::from_ptr(*FLAC__StreamDecoderStateString.as_ptr().add(code as usize)).to_str().unwrap()
1332        }
1333    }
1334}
1335
1336impl_FlacError!(FlacDecoderError);
1337
1338#[derive(Debug, Clone, Copy)]
1339pub enum FlacDecoderErrorCode {
1340    /// * The decoder is ready to search for metadata.
1341    StreamDecoderSearchForMetadata = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA as isize,
1342
1343    /// * The decoder is ready to or is in the process of reading metadata.
1344    StreamDecoderReadMetadata = FLAC__STREAM_DECODER_READ_METADATA as isize,
1345
1346    /// * The decoder is ready to or is in the process of searching for the frame sync code.
1347    StreamDecoderSearchForFrameSync = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC as isize,
1348
1349    /// * The decoder is ready to or is in the process of reading a frame.
1350    StreamDecoderReadFrame = FLAC__STREAM_DECODER_READ_FRAME as isize,
1351
1352    /// * The decoder has reached the end of the stream.
1353    StreamDecoderEndOfStream = FLAC__STREAM_DECODER_END_OF_STREAM as isize,
1354
1355    /// * An error occurred in the underlying Ogg layer.
1356    StreamDecoderOggError = FLAC__STREAM_DECODER_OGG_ERROR as isize,
1357
1358    /// * An error occurred while seeking. The decoder must be flushed with FLAC__stream_decoder_flush() or reset with FLAC__stream_decoder_reset() before decoding can continue.
1359    StreamDecoderSeekError = FLAC__STREAM_DECODER_SEEK_ERROR as isize,
1360
1361    /// * The decoder was aborted by the read or write callback.
1362    StreamDecoderAborted = FLAC__STREAM_DECODER_ABORTED as isize,
1363
1364    /// * An error occurred allocating memory. The decoder is in an invalid state and can no longer be used.
1365    StreamDecoderMemoryAllocationError = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR as isize,
1366
1367    /// * The decoder is in the uninitialized state; one of the FLAC__stream_decoder_init_*() functions must be called before samples can be processed.
1368    StreamDecoderUninitialized = FLAC__STREAM_DECODER_UNINITIALIZED as isize,
1369}
1370
1371impl Display for FlacDecoderErrorCode {
1372    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1373        match self {
1374            Self::StreamDecoderSearchForMetadata => write!(f, "The decoder is ready to search for metadata."),
1375            Self::StreamDecoderReadMetadata => write!(f, "The decoder is ready to or is in the process of reading metadata."),
1376            Self::StreamDecoderSearchForFrameSync => write!(f, "The decoder is ready to or is in the process of searching for the frame sync code."),
1377            Self::StreamDecoderReadFrame => write!(f, "The decoder is ready to or is in the process of reading a frame."),
1378            Self::StreamDecoderEndOfStream => write!(f, "The decoder has reached the end of the stream."),
1379            Self::StreamDecoderOggError => write!(f, "An error occurred in the underlying Ogg layer."),
1380            Self::StreamDecoderSeekError => write!(f, "An error occurred while seeking. The decoder must be flushed with FLAC__stream_decoder_flush() or reset with FLAC__stream_decoder_reset() before decoding can continue."),
1381            Self::StreamDecoderAborted => write!(f, "The decoder was aborted by the read or write callback."),
1382            Self::StreamDecoderMemoryAllocationError => write!(f, "An error occurred allocating memory. The decoder is in an invalid state and can no longer be used."),
1383            Self::StreamDecoderUninitialized => write!(f, "The decoder is in the uninitialized state; one of the FLAC__stream_decoder_init_*() functions must be called before samples can be processed."),
1384        }
1385    }
1386}
1387
1388impl From<u32> for FlacDecoderErrorCode {
1389    fn from(code: u32) -> Self {
1390        use FlacDecoderErrorCode::*;
1391        match code {
1392            FLAC__STREAM_DECODER_SEARCH_FOR_METADATA => StreamDecoderSearchForMetadata,
1393            FLAC__STREAM_DECODER_READ_METADATA => StreamDecoderReadMetadata,
1394            FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC => StreamDecoderSearchForFrameSync,
1395            FLAC__STREAM_DECODER_READ_FRAME => StreamDecoderReadFrame,
1396            FLAC__STREAM_DECODER_END_OF_STREAM => StreamDecoderEndOfStream,
1397            FLAC__STREAM_DECODER_OGG_ERROR => StreamDecoderOggError,
1398            FLAC__STREAM_DECODER_SEEK_ERROR => StreamDecoderSeekError,
1399            FLAC__STREAM_DECODER_ABORTED => StreamDecoderAborted,
1400            FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR => StreamDecoderMemoryAllocationError,
1401            FLAC__STREAM_DECODER_UNINITIALIZED => StreamDecoderUninitialized,
1402            o => panic!("Not an decoder error code: {o}."),
1403        }
1404    }
1405}
1406
1407impl std::error::Error for FlacDecoderErrorCode {}
1408
1409#[derive(Debug, Clone, Copy)]
1410pub struct FlacDecoderInitError {
1411    /// * This code is actually `FlacDecoderInitErrorCode`
1412    pub code: u32,
1413
1414    /// * The description of the status, as a constant string from `libflac-sys`
1415    pub message: &'static str,
1416
1417    /// * Which function generates this error
1418    pub function: &'static str,
1419}
1420
1421impl FlacDecoderInitError {
1422    pub fn new(code: u32, function: &'static str) -> Self {
1423        Self {
1424            code,
1425            message: Self::get_message_from_code(code),
1426            function,
1427        }
1428    }
1429
1430    pub fn get_message_from_code(code: u32) -> &'static str {
1431        unsafe {
1432            CStr::from_ptr(*FLAC__StreamDecoderInitStatusString.as_ptr().add(code as usize)).to_str().unwrap()
1433        }
1434    }
1435}
1436
1437impl_FlacError!(FlacDecoderInitError);
1438
1439#[derive(Debug, Clone, Copy)]
1440pub enum FlacDecoderInitErrorCode {
1441    StreamDecoderInitStatusOk = FLAC__STREAM_DECODER_INIT_STATUS_OK as isize,
1442    StreamDecoderInitStatusUnsupportedContainer = FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER as isize,
1443    StreamDecoderInitStatusInvalidCallbacks = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS as isize,
1444    StreamDecoderInitStatusMemoryAllocationError = FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR as isize,
1445    StreamDecoderInitStatusErrorOpeningFile = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE as isize,
1446    StreamDecoderInitStatusAlreadyInitialized = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED as isize,
1447}
1448
1449impl Display for FlacDecoderInitErrorCode {
1450    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1451        match self {
1452            Self::StreamDecoderInitStatusOk => write!(f, "Initialization was successful."),
1453            Self::StreamDecoderInitStatusUnsupportedContainer => write!(f, "The library was not compiled with support for the given container format."),
1454            Self::StreamDecoderInitStatusInvalidCallbacks => write!(f, "A required callback was not supplied."),
1455            Self::StreamDecoderInitStatusMemoryAllocationError => write!(f, "An error occurred allocating memory."),
1456            Self::StreamDecoderInitStatusErrorOpeningFile => write!(f, "fopen() failed in FLAC__stream_decoder_init_file() or FLAC__stream_decoder_init_ogg_file()."),
1457            Self::StreamDecoderInitStatusAlreadyInitialized => write!(f, "FLAC__stream_decoder_init_*() was called when the decoder was already initialized, usually because FLAC__stream_decoder_finish() was not called."),
1458        }
1459    }
1460}
1461
1462impl From<u32> for FlacDecoderInitErrorCode {
1463    fn from(code: u32) -> Self {
1464        use FlacDecoderInitErrorCode::*;
1465        match code {
1466            FLAC__STREAM_DECODER_INIT_STATUS_OK => StreamDecoderInitStatusOk,
1467            FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER => StreamDecoderInitStatusUnsupportedContainer,
1468            FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS => StreamDecoderInitStatusInvalidCallbacks,
1469            FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR => StreamDecoderInitStatusMemoryAllocationError,
1470            FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE => StreamDecoderInitStatusErrorOpeningFile,
1471            FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED => StreamDecoderInitStatusAlreadyInitialized,
1472            o => panic!("Not an decoder init error code: {o}."),
1473        }
1474    }
1475}
1476
1477impl std::error::Error for FlacDecoderInitErrorCode {}
1478
1479impl From<FlacDecoderError> for FlacDecoderInitError {
1480    fn from(err: FlacDecoderError) -> Self {
1481        Self {
1482            code: err.code,
1483            message: err.message,
1484            function: err.function,
1485        }
1486    }
1487}
1488
1489impl From<FlacDecoderInitError> for FlacDecoderError {
1490    fn from(err: FlacDecoderInitError) -> Self {
1491        Self {
1492            code: err.code,
1493            message: err.message,
1494            function: err.function,
1495        }
1496    }
1497}
1498
1499/// ## The result value for your `on_read()` closure to return
1500#[derive(Debug, Clone, Copy)]
1501pub enum FlacReadStatus {
1502    /// * Let the FLAC codec continue to process
1503    GoOn,
1504
1505    /// * Hit the end of the file
1506    Eof,
1507
1508    /// * Error occurred, let the FLAC codec abort the process
1509    Abort,
1510}
1511
1512impl Display for FlacReadStatus {
1513    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1514        match self {
1515            Self::GoOn => write!(f, "go_on"),
1516            Self::Eof => write!(f, "eof"),
1517            Self::Abort => write!(f, "abort"),
1518        }
1519    }
1520}
1521
1522/// ## The FLAC decoder internal error value for your `on_error()` closure to report.
1523#[derive(Debug, Clone, Copy)]
1524pub enum FlacInternalDecoderError {
1525    /// * An error in the stream caused the decoder to lose synchronization.
1526    LostSync,
1527
1528    /// * The decoder encountered a corrupted frame header.
1529    BadHeader,
1530
1531    /// * The frame's data did not match the CRC in the footer.
1532    FrameCrcMismatch,
1533
1534    /// * The decoder encountered reserved fields in use in the stream.
1535    UnparseableStream,
1536
1537    /// * The decoder encountered a corrupted metadata block.
1538    BadMetadata,
1539
1540    /// * The decoder encountered a otherwise valid frame in which the decoded samples exceeded the range offered by the stated bit depth.
1541    OutOfBounds,
1542}
1543
1544impl Display for FlacInternalDecoderError {
1545    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1546        match self {
1547            Self::LostSync => write!(f, "An error in the stream caused the decoder to lose synchronization."),
1548            Self::BadHeader => write!(f, "The decoder encountered a corrupted frame header."),
1549            Self::FrameCrcMismatch => write!(f, "The frame's data did not match the CRC in the footer."),
1550            Self::UnparseableStream => write!(f, "The decoder encountered reserved fields in use in the stream."),
1551            Self::BadMetadata => write!(f, "The decoder encountered a corrupted metadata block."),
1552            Self::OutOfBounds => write!(f, "The decoder encountered a otherwise valid frame in which the decoded samples exceeded the range offered by the stated bit depth."),
1553        }
1554    }
1555}
1556
1557impl std::error::Error for FlacInternalDecoderError {}
1558
1559/// ## The form of audio samples
1560#[derive(Debug, Clone, Copy)]
1561pub enum FlacAudioForm {
1562    /// * For the frame array, each audio frame is one sample per channel.
1563    /// * For example, a stereo frame has two samples, one for left, and one for right.
1564    FrameArray,
1565
1566    /// * For channel array, each element of the array is one channel of the audio.
1567    /// * For example, if the audio is mono, the array only contains one element, that element is the only channel for the mono audio.
1568    ChannelArray,
1569}
1570
1571#[derive(Debug, Clone, Copy)]
1572pub struct SamplesInfo {
1573    /// * Number of samples per channel decoded from the FLAC frame
1574    pub samples: u32,
1575
1576    /// * Number of channels in the FLAC frame
1577    pub channels: u32,
1578
1579    /// * The sample rate of the FLAC frame.
1580    pub sample_rate: u32,
1581
1582    /// * How many bits in an `i32` are valid for a sample. The decoder only excretes `[i32]` for you.
1583    /// * For example, the value is 16, but you got a `[i32]`, which means each `i32` is in the range of -32768 to 32767, you can then just cast the `i32` to `i16` for your convenience.
1584    pub bits_per_sample: u32,
1585
1586    /// * How are the audio data forms, audio frame array, or channel array.
1587    pub audio_form: FlacAudioForm,
1588}
1589
1590fn entry_to_str(entry: &FLAC__StreamMetadata_VorbisComment_Entry) -> Cow<'_, str> {
1591    unsafe{String::from_utf8_lossy(slice::from_raw_parts(entry.entry, entry.length as usize))}
1592}
1593
1594fn entry_to_string(entry: &FLAC__StreamMetadata_VorbisComment_Entry) -> String {
1595    entry_to_str(entry).to_string()
1596}
1597
1598/// ## The decoder's core structure, but can't move after `initialize()` has been called.
1599/// Use a `Box` to contain it, or just don't move it will be fine.
1600pub struct FlacDecoderUnmovable<'a, ReadSeek>
1601where
1602    ReadSeek: Read + Seek + Debug {
1603    /// * See <https://xiph.org/flac/api/group__flac__stream__decoder.html>
1604    decoder: *mut FLAC__StreamDecoder,
1605
1606    /// * The reader to read the FLAC file
1607    reader: ReadSeek,
1608
1609    /// * Your `on_read()` closure, read from the `reader` and return how many bytes you read, and what is the current read status.
1610    on_read: Box<dyn FnMut(&mut ReadSeek, &mut [u8]) -> (usize, FlacReadStatus) + 'a>,
1611
1612    /// * Your `on_seek()` closure, helps the decoder to set the file pointer.
1613    on_seek: Box<dyn FnMut(&mut ReadSeek, u64) -> Result<(), io::Error> + 'a>,
1614
1615    /// * Your `on_tell()` closure, returns the current read position.
1616    on_tell: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
1617
1618    /// * Your `on_length()` closure. You only need to return the file length through this closure.
1619    on_length: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
1620
1621    /// * Your `on_eof()` closure, if the `reader` hits the end of the file, the closure returns true. Otherwise returns false indicates that there's still data to be read by the decoder.
1622    on_eof: Box<dyn FnMut(&mut ReadSeek) -> bool + 'a>,
1623
1624    /// * Your `on_write()` closure, it's not for you to "write", but it's the decoder returns the decoded samples for you to use.
1625    on_write: Box<dyn FnMut(&[Vec<i32>], &SamplesInfo) -> Result<(), io::Error> + 'a>,
1626
1627    /// * Your `on_error()` closure. Normally it won't be called.
1628    on_error: Box<dyn FnMut(FlacInternalDecoderError) + 'a>,
1629
1630    /// * Set to true to let the decoder check the MD5 sum of the decoded samples.
1631    md5_checking: bool,
1632
1633    /// * Is this decoder finished decoding?
1634    finished: bool,
1635
1636    /// * Scale to `i32` range or not, if set to true, the sample will be scaled to the whole range of `i32` [-2147483648, +2147483647] if bits per sample is not 32.
1637    pub scale_to_i32_range: bool,
1638
1639    /// * The desired form of audio you want to receive.
1640    pub desired_audio_form: FlacAudioForm,
1641
1642    /// * The vendor string read from the FLAC file.
1643    pub vendor_string: Option<String>,
1644
1645    /// * The comments, or metadata read from the FLAC file.
1646    pub comments: BTreeMap<String, String>,
1647
1648    /// * The pictures, or CD cover read from the FLAC file.
1649    pub pictures: Vec<PictureData>,
1650
1651    /// * The cue sheets read from the FLAC file.
1652    pub cue_sheets: Vec<FlacCueSheet>,
1653}
1654
1655impl<'a, ReadSeek> FlacDecoderUnmovable<'a, ReadSeek>
1656where
1657    ReadSeek: Read + Seek + Debug {
1658    pub fn new(
1659        reader: ReadSeek,
1660        on_read: Box<dyn FnMut(&mut ReadSeek, &mut [u8]) -> (usize, FlacReadStatus) + 'a>,
1661        on_seek: Box<dyn FnMut(&mut ReadSeek, u64) -> Result<(), io::Error> + 'a>,
1662        on_tell: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
1663        on_length: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
1664        on_eof: Box<dyn FnMut(&mut ReadSeek) -> bool + 'a>,
1665        on_write: Box<dyn FnMut(&[Vec<i32>], &SamplesInfo) -> Result<(), io::Error> + 'a>,
1666        on_error: Box<dyn FnMut(FlacInternalDecoderError) + 'a>,
1667        md5_checking: bool,
1668        scale_to_i32_range: bool,
1669        desired_audio_form: FlacAudioForm,
1670    ) -> Result<Self, FlacDecoderError> {
1671        let ret = Self {
1672            decoder: unsafe {FLAC__stream_decoder_new()},
1673            reader,
1674            on_read,
1675            on_seek,
1676            on_tell,
1677            on_length,
1678            on_eof,
1679            on_write,
1680            on_error,
1681            md5_checking,
1682            finished: false,
1683            scale_to_i32_range,
1684            desired_audio_form,
1685            vendor_string: None,
1686            comments: BTreeMap::new(),
1687            pictures: Vec::<PictureData>::new(),
1688            cue_sheets: Vec::<FlacCueSheet>::new(),
1689        };
1690        if ret.decoder.is_null() {
1691            Err(FlacDecoderError::new(FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, "FLAC__stream_decoder_new"))
1692        } else {
1693            Ok(ret)
1694        }
1695    }
1696
1697    fn get_status_as_result(&self, function: &'static str) -> Result<(), FlacDecoderError> {
1698        let code = unsafe {FLAC__stream_decoder_get_state(self.decoder)};
1699        if code == 0 {
1700            Ok(())
1701        } else {
1702            Err(FlacDecoderError::new(code, function))
1703        }
1704    }
1705
1706    fn get_status_as_error(&self, function: &'static str) -> Result<(), FlacDecoderError> {
1707        let code = unsafe {FLAC__stream_decoder_get_state(self.decoder)};
1708        Err(FlacDecoderError::new(code, function))
1709    }
1710
1711    fn as_ptr(&self) -> *const Self {
1712        self as *const Self
1713    }
1714
1715    fn as_mut_ptr(&mut self) -> *mut Self {
1716        self as *mut Self
1717    }
1718
1719    unsafe extern "C" fn read_callback(_decoder: *const FLAC__StreamDecoder, buffer: *mut u8, bytes: *mut usize, client_data: *mut c_void) -> u32 {
1720        let this = unsafe {&mut *(client_data as *mut Self)};
1721        if unsafe {*bytes} == 0 {
1722            FLAC__STREAM_DECODER_READ_STATUS_ABORT
1723        } else {
1724            let buf = unsafe {slice::from_raw_parts_mut(buffer, *bytes)};
1725            let (bytes_read, status) = (this.on_read)(&mut this.reader, buf);
1726            let ret = match status{
1727                FlacReadStatus::GoOn => FLAC__STREAM_DECODER_READ_STATUS_CONTINUE,
1728                FlacReadStatus::Eof => FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM,
1729                FlacReadStatus::Abort => FLAC__STREAM_DECODER_READ_STATUS_ABORT,
1730            };
1731
1732            unsafe {*bytes = bytes_read};
1733            ret
1734        }
1735    }
1736
1737    unsafe extern "C" fn seek_callback(_decoder: *const FLAC__StreamDecoder, absolute_byte_offset: u64, client_data: *mut c_void) -> u32 {
1738        let this = unsafe {&mut *(client_data as *mut Self)};
1739        match (this.on_seek)(&mut this.reader, absolute_byte_offset) {
1740            Ok(_) => FLAC__STREAM_DECODER_SEEK_STATUS_OK,
1741            Err(e) => {
1742                match e.kind() {
1743                    io::ErrorKind::NotSeekable => FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED,
1744                    _ => FLAC__STREAM_DECODER_SEEK_STATUS_ERROR,
1745                }
1746            },
1747        }
1748    }
1749
1750    unsafe extern "C" fn tell_callback(_decoder: *const FLAC__StreamDecoder, absolute_byte_offset: *mut u64, client_data: *mut c_void) -> u32 {
1751        let this = unsafe {&mut *(client_data as *mut Self)};
1752        match (this.on_tell)(&mut this.reader) {
1753            Ok(offset) => {
1754                unsafe {*absolute_byte_offset = offset};
1755                FLAC__STREAM_DECODER_TELL_STATUS_OK
1756            },
1757            Err(e) => {
1758                match e.kind() {
1759                    io::ErrorKind::NotSeekable => FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED,
1760                    _ => FLAC__STREAM_DECODER_TELL_STATUS_ERROR,
1761                }
1762            },
1763        }
1764    }
1765
1766    unsafe extern "C" fn length_callback(_decoder: *const FLAC__StreamDecoder, stream_length: *mut u64, client_data: *mut c_void) -> u32 {
1767        let this = unsafe {&mut *(client_data as *mut Self)};
1768        match (this.on_length)(&mut this.reader) {
1769            Ok(length) => {
1770                unsafe {*stream_length = length};
1771                FLAC__STREAM_DECODER_LENGTH_STATUS_OK
1772            },
1773            Err(e) => {
1774                match e.kind() {
1775                    io::ErrorKind::NotSeekable => FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED,
1776                    _ => FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR,
1777                }
1778            },
1779        }
1780    }
1781
1782    unsafe extern "C" fn eof_callback(_decoder: *const FLAC__StreamDecoder, client_data: *mut c_void) -> i32 {
1783        let this = unsafe {&mut *(client_data as *mut Self)};
1784        if (this.on_eof)(&mut this.reader) {1} else {0}
1785    }
1786
1787    unsafe extern "C" fn write_callback(_decoder: *const FLAC__StreamDecoder, frame: *const FLAC__Frame, buffer: *const *const i32, client_data: *mut c_void) -> u32 {
1788        // Scales signed PCM samples to full i32 dynamic range.
1789        // - `bits`: Valid bits in `sample` (1-32).
1790        // - Example: 8-bit samples [-128, 127] → [i32::MIN, i32::MAX]
1791        fn scale_to_i32(sample: i32, bits: u32) -> i32 {
1792            assert!(bits <= 32);
1793            if bits == 32 {
1794                sample
1795            } else {
1796                fn scale_to_unsigned(sample: i32, bits: u32) -> u32 {
1797                    let mask = (1u32 << bits) - 1;
1798                    let mid_number = 1u32 << (bits - 1);
1799                    ((sample as u32).wrapping_add(mid_number) & mask) << (32 - bits)
1800                }
1801                let mut lower_fill = scale_to_unsigned(sample, bits);
1802                let mut result = (sample as u32) << (32 - bits);
1803                while lower_fill > 0 {
1804                    lower_fill >>= bits;
1805                    result |= lower_fill;
1806                }
1807                result as i32
1808            }
1809        }
1810
1811        let this = unsafe {&mut *(client_data as *mut Self)};
1812        let frame = unsafe {*frame};
1813        let samples = frame.header.blocksize;
1814        let channels = frame.header.channels;
1815        let sample_rate = frame.header.sample_rate;
1816        let bits_per_sample = frame.header.bits_per_sample;
1817
1818        let mut samples_info = SamplesInfo {
1819            samples,
1820            channels,
1821            sample_rate,
1822            bits_per_sample,
1823            audio_form: this.desired_audio_form,
1824        };
1825
1826        let mut ret: Vec<Vec<i32>>;
1827        match this.desired_audio_form {
1828            FlacAudioForm::FrameArray => {
1829                // Each `frame` contains one sample for each channel
1830                ret = vec![Vec::<i32>::new(); samples as usize];
1831                for s in 0..samples {
1832                    for c in 0..channels {
1833                        let channel = unsafe {*buffer.add(c as usize)};
1834                        ret[s as usize].push(unsafe {*channel.add(s as usize)});
1835                    }
1836                }
1837            },
1838            FlacAudioForm::ChannelArray => {
1839                // Each `channel` contains all samples for the channel
1840                ret = vec![Vec::<i32>::new(); channels as usize];
1841                for c in 0..channels {
1842                    ret[c as usize] = unsafe {slice::from_raw_parts(*buffer.add(c as usize), samples as usize)}.to_vec();
1843                }
1844            }
1845        }
1846
1847        // Whatever it was, now it's just a two-dimensional array
1848        if this.scale_to_i32_range {
1849            for x in ret.iter_mut() {
1850                for y in x.iter_mut() {
1851                    *y = scale_to_i32(*y, bits_per_sample);
1852                }
1853            }
1854            samples_info.bits_per_sample = 32;
1855        }
1856
1857        match (this.on_write)(&ret, &samples_info) {
1858            Ok(_) => FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE,
1859            Err(e) => {
1860                eprintln!("On `write_callback()`: {:?}", e);
1861                FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
1862            },
1863        }
1864    }
1865
1866    unsafe extern "C" fn metadata_callback(_decoder: *const FLAC__StreamDecoder, metadata: *const FLAC__StreamMetadata, client_data: *mut c_void) {
1867        let this = unsafe {&mut *(client_data as *mut Self)};
1868        let metadata = unsafe {*metadata};
1869        match metadata.type_ {
1870            FLAC__METADATA_TYPE_VORBIS_COMMENT => unsafe {
1871                let comments = metadata.data.vorbis_comment;
1872
1873                // First retrieve the vendor string
1874                this.vendor_string = Some(entry_to_string(&comments.vendor_string));
1875
1876                // Then to get all of the key pairs, the key pairs should be all uppercase, but some of them are not.
1877                // Read both the uppercase keys and the lowercase keys and store them, if it won't overwrite then we convert
1878                // the key to uppercase and store it again.
1879                let mut uppercase_keypairs = Vec::<(String, String)>::new();
1880                for i in 0..comments.num_comments {
1881                    let comment = entry_to_string(&*comments.comments.add(i as usize));
1882
1883                    // The key pair is split by the equal notation
1884                    let mut iter = comment.split("=");
1885                    if let Some(key) = iter.next() {
1886                        let key = key.to_owned();
1887
1888                        // Ignore the later equal notations.
1889                        let val = iter.map(|s: &str|{s.to_string()}).collect::<Vec<String>>().join("=");
1890                        let key_upper = key.to_uppercase();
1891                        if key != key_upper {
1892                            uppercase_keypairs.push((key_upper, val.clone()));
1893                        }
1894
1895                        // Duplication check
1896                        let if_dup = format!("Duplicated comments: new comment is {key}: {val}, the previous is {key}: ");
1897                        if let Some(old) = this.comments.insert(key, val) {
1898                            eprintln!("{if_dup}{old}");
1899                        }
1900                    } else {
1901                        // No equal notation here
1902                        eprintln!("Invalid comment: {comment}");
1903                    }
1904                }
1905
1906                // If it lacks the uppercase key pairs, we add it to the map.
1907                for (key_upper, val) in uppercase_keypairs {
1908                    if this.comments.contains_key(&key_upper) {
1909                        continue;
1910                    } else {
1911                        this.comments.insert(key_upper, val);
1912                    }
1913                }
1914            },
1915            FLAC__METADATA_TYPE_PICTURE => unsafe {
1916                let picture = metadata.data.picture;
1917                this.pictures.push(PictureData{
1918                    picture: slice::from_raw_parts(picture.data, picture.data_length as usize).to_vec(),
1919                    description: CStr::from_ptr(picture.description as *const i8).to_string_lossy().to_string(),
1920                    mime_type: CStr::from_ptr(picture.mime_type).to_string_lossy().to_string(),
1921                    width: picture.width,
1922                    height: picture.height,
1923                    depth: picture.depth,
1924                    colors: picture.colors,
1925                });
1926            },
1927            FLAC__METADATA_TYPE_CUESHEET => unsafe {
1928                let cue_sheet = metadata.data.cue_sheet;
1929                this.cue_sheets.push(FlacCueSheet{
1930                    media_catalog_number: cue_sheet.media_catalog_number,
1931                    lead_in: cue_sheet.lead_in,
1932                    is_cd: cue_sheet.is_cd != 0,
1933                    tracks: (0..cue_sheet.num_tracks).map(|i| -> (u8, FlacCueTrack) {
1934                        let track = *cue_sheet.tracks.add(i as usize);
1935                        (track.number, FlacCueTrack {
1936                            offset: track.offset,
1937                            track_no: track.number,
1938                            isrc: track.isrc,
1939                            type_: match track.type_() {
1940                                0 => FlacTrackType::Audio,
1941                                _ => FlacTrackType::NonAudio,
1942                            },
1943                            pre_emphasis: track.pre_emphasis() != 0,
1944                            indices: (0..track.num_indices).map(|i| -> FlacCueSheetIndex {
1945                                let index = *track.indices.add(i as usize);
1946                                FlacCueSheetIndex {
1947                                    offset: index.offset,
1948                                    number: index.number,
1949                                }
1950                            }).collect()
1951                        })
1952                    }).collect(),
1953                });
1954            },
1955            _ => {
1956                #[cfg(debug_assertions)]
1957                if SHOW_CALLBACKS {println!("On `metadata_callback()`: {:?}", WrappedStreamMetadata(metadata));}
1958            },
1959        }
1960    }
1961
1962    unsafe extern "C" fn error_callback(_decoder: *const FLAC__StreamDecoder, status: u32, client_data: *mut c_void) {
1963        let this = unsafe {&mut *(client_data as *mut Self)};
1964        (this.on_error)(match status {
1965            FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC => FlacInternalDecoderError::LostSync,
1966            FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER => FlacInternalDecoderError::BadHeader,
1967            FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH => FlacInternalDecoderError::FrameCrcMismatch,
1968            FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM => FlacInternalDecoderError::UnparseableStream,
1969            FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA => FlacInternalDecoderError::BadMetadata,
1970            o => panic!("Unknown value of `FLAC__StreamDecodeErrorStatus`: {o}"),
1971        });
1972    }
1973
1974    /// * The `initialize()` function. Sets up all of the callback functions, sets `client_data` to the address of the `self` struct.
1975    pub fn initialize(&mut self) -> Result<(), FlacDecoderError> {
1976        unsafe {
1977            if FLAC__stream_decoder_set_md5_checking(self.decoder, self.md5_checking as i32) == 0 {
1978                return self.get_status_as_error("FLAC__stream_decoder_set_md5_checking");
1979            }
1980            if FLAC__stream_decoder_set_metadata_respond_all(self.decoder) == 0 {
1981                return self.get_status_as_error("FLAC__stream_decoder_set_metadata_respond_all");
1982            }
1983            let ret = FLAC__stream_decoder_init_stream(
1984                self.decoder,
1985                Some(Self::read_callback),
1986                Some(Self::seek_callback),
1987                Some(Self::tell_callback),
1988                Some(Self::length_callback),
1989                Some(Self::eof_callback),
1990                Some(Self::write_callback),
1991                Some(Self::metadata_callback),
1992                Some(Self::error_callback),
1993                self.as_mut_ptr() as *mut c_void,
1994            );
1995            if ret != 0 {
1996                return Err(FlacDecoderError {
1997                    code: ret,
1998                    message: FlacDecoderInitError::get_message_from_code(ret),
1999                    function: "FLAC__stream_decoder_init_stream",
2000                });
2001            }
2002        }
2003        self.finished = false;
2004        self.get_status_as_result("FlacDecoderUnmovable::Init()")
2005    }
2006
2007    /// * Seek to the specific sample position, may fail.
2008    pub fn seek(&mut self, frame_index: u64) -> Result<(), FlacDecoderError> {
2009        for _retry in 0..3 {
2010            unsafe {
2011                if FLAC__stream_decoder_seek_absolute(self.decoder, frame_index) == 0 {
2012                    match FLAC__stream_decoder_get_state(self.decoder) {
2013                        FLAC__STREAM_DECODER_SEEK_STATUS_OK => panic!("`FLAC__stream_decoder_seek_absolute()` returned false, but the status of the decoder is `OK`"),
2014                        FLAC__STREAM_DECODER_SEEK_ERROR => {
2015                            if FLAC__stream_decoder_reset(self.decoder) == 0 {
2016                                return self.get_status_as_error("FLAC__stream_decoder_reset");
2017                            } else {
2018                                continue;
2019                            }
2020                        },
2021                        o => return Err(FlacDecoderError::new(o, "FLAC__stream_decoder_seek_absolute")),
2022                    }
2023                } else {
2024                    return Ok(())
2025                }
2026            }
2027        }
2028        Err(FlacDecoderError::new(FLAC__STREAM_DECODER_SEEK_ERROR, "FLAC__stream_decoder_seek_absolute"))
2029    }
2030
2031    /// * Calls your `on_tell()` closure to get the read position
2032    pub fn tell(&mut self) -> Result<u64, io::Error> {
2033        (self.on_tell)(&mut self.reader)
2034    }
2035
2036    /// * Calls your `on_length()` closure to get the length of the file
2037    pub fn length(&mut self) -> Result<u64, io::Error> {
2038        (self.on_length)(&mut self.reader)
2039    }
2040
2041    /// * Calls your `on_eof()` closure to check if `reader` hits the end of the file.
2042    pub fn eof(&mut self) -> bool {
2043        (self.on_eof)(&mut self.reader)
2044    }
2045
2046    /// * Get the vendor string.
2047    pub fn get_vendor_string(&self) -> &Option<String> {
2048        &self.vendor_string
2049    }
2050
2051    /// * Get all of the comments or metadata.
2052    pub fn get_comments(&self) -> &BTreeMap<String, String> {
2053        &self.comments
2054    }
2055
2056    /// * Get all of the pictures
2057    pub fn get_pictures(&self) -> &Vec<PictureData> {
2058        &self.pictures
2059    }
2060
2061    /// * Get all of the cue sheets
2062    pub fn get_cue_sheets(&self) -> &Vec<FlacCueSheet> {
2063        &self.cue_sheets
2064    }
2065
2066    /// * Decode one FLAC frame, may get an audio frame or a metadata frame.
2067    /// * Your closures will be called by the decoder when you call this method.
2068    pub fn decode(&mut self) -> Result<bool, FlacDecoderError> {
2069        if unsafe {FLAC__stream_decoder_process_single(self.decoder) != 0} {
2070            Ok(true)
2071        } else {
2072            match self.get_status_as_result("FLAC__stream_decoder_process_single") {
2073                Ok(_) => Ok(false),
2074                Err(e) => Err(e),
2075            }
2076        }
2077    }
2078
2079    /// * Decode all of the FLAC frames, get all of the samples and metadata and pictures and cue sheets, etc.
2080    pub fn decode_all(&mut self) -> Result<bool, FlacDecoderError> {
2081        if unsafe {FLAC__stream_decoder_process_until_end_of_stream(self.decoder) != 0} {
2082            Ok(true)
2083        } else {
2084            match self.get_status_as_result("FLAC__stream_decoder_process_until_end_of_stream") {
2085                Ok(_) => Ok(false),
2086                Err(e) => Err(e),
2087            }
2088        }
2089    }
2090
2091    /// * Finish decoding the FLAC file, the remaining samples will be returned to you via your `on_write()` closure.
2092    pub fn finish(&mut self) -> Result<(), FlacDecoderError> {
2093        if !self.finished {
2094            if unsafe {FLAC__stream_decoder_finish(self.decoder) != 0} {
2095                self.finished = true;
2096                Ok(())
2097            } else {
2098                self.get_status_as_result("FLAC__stream_decoder_finish")
2099            }
2100        } else {
2101            Ok(())
2102        }
2103    }
2104
2105    fn on_drop(&mut self) {
2106        unsafe {
2107            if let Err(e) =  self.finish() {
2108                eprintln!("On FlacDecoderUnmovable::finish(): {:?}", e);
2109            }
2110
2111            // Must delete `self.decoder` even `self.finish()` fails.
2112            FLAC__stream_decoder_delete(self.decoder);
2113        };
2114    }
2115
2116    /// * Call this function if you don't want the decoder anymore.
2117    pub fn finalize(self) {}
2118}
2119
2120impl<'a, ReadSeek> Debug for FlacDecoderUnmovable<'_, ReadSeek>
2121where
2122    ReadSeek: Read + Seek + Debug {
2123    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2124        fmt.debug_struct("FlacDecoderUnmovable")
2125            .field("decoder", &self.decoder)
2126            .field("reader", &self.reader)
2127            .field("on_read", &"{{closure}}")
2128            .field("on_seek", &"{{closure}}")
2129            .field("on_tell", &"{{closure}}")
2130            .field("on_length", &"{{closure}}")
2131            .field("on_eof", &"{{closure}}")
2132            .field("on_write", &"{{closure}}")
2133            .field("on_error", &"{{closure}}")
2134            .field("md5_checking", &self.md5_checking)
2135            .field("finished", &self.finished)
2136            .field("scale_to_i32_range", &self.scale_to_i32_range)
2137            .field("desired_audio_form", &self.desired_audio_form)
2138            .field("vendor_string", &self.vendor_string)
2139            .field("comments", &self.comments)
2140            .field("pictures", &self.pictures)
2141            .field("cue_sheets", &self.cue_sheets)
2142            .finish()
2143    }
2144}
2145
2146impl<'a, ReadSeek> Drop for FlacDecoderUnmovable<'_, ReadSeek>
2147where
2148    ReadSeek: Read + Seek + Debug {
2149    fn drop(&mut self) {
2150        self.on_drop();
2151    }
2152}
2153
2154/// ## A wrapper for `FlacDecoderUnmovable`, which provides a Box to make `FlacDecoderUnmovable` never move.
2155/// This is the struct that should be mainly used by you.
2156pub struct FlacDecoder<'a, ReadSeek>
2157where
2158    ReadSeek: Read + Seek + Debug {
2159    decoder: Box<FlacDecoderUnmovable<'a, ReadSeek>>,
2160}
2161
2162impl<'a, ReadSeek> FlacDecoder<'a, ReadSeek>
2163where
2164    ReadSeek: Read + Seek + Debug {
2165    pub fn new(
2166        reader: ReadSeek,
2167        on_read: Box<dyn FnMut(&mut ReadSeek, &mut [u8]) -> (usize, FlacReadStatus) + 'a>,
2168        on_seek: Box<dyn FnMut(&mut ReadSeek, u64) -> Result<(), io::Error> + 'a>,
2169        on_tell: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
2170        on_length: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
2171        on_eof: Box<dyn FnMut(&mut ReadSeek) -> bool + 'a>,
2172        on_write: Box<dyn FnMut(&[Vec<i32>], &SamplesInfo) -> Result<(), io::Error> + 'a>,
2173        on_error: Box<dyn FnMut(FlacInternalDecoderError) + 'a>,
2174        md5_checking: bool,
2175        scale_to_i32_range: bool,
2176        desired_audio_form: FlacAudioForm,
2177    ) -> Result<Self, FlacDecoderError> {
2178        let mut ret = Self {
2179            decoder: Box::new(FlacDecoderUnmovable::<'a>::new(
2180                reader,
2181                on_read,
2182                on_seek,
2183                on_tell,
2184                on_length,
2185                on_eof,
2186                on_write,
2187                on_error,
2188                md5_checking,
2189                scale_to_i32_range,
2190                desired_audio_form,
2191            )?),
2192        };
2193        ret.decoder.initialize()?;
2194        Ok(ret)
2195    }
2196
2197    /// * Call this function if you don't want the decoder anymore.
2198    pub fn finalize(self) {}
2199}
2200
2201impl<'a, ReadSeek> Debug for FlacDecoder<'_, ReadSeek>
2202where
2203    ReadSeek: Read + Seek + Debug {
2204    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2205        fmt.debug_struct("FlacDecoder")
2206            .field("decoder", &self.decoder)
2207            .finish()
2208    }
2209}
2210
2211impl<'a, ReadSeek> Deref for FlacDecoder<'a, ReadSeek>
2212where
2213    ReadSeek: Read + Seek + Debug {
2214    type Target = FlacDecoderUnmovable<'a, ReadSeek>;
2215    fn deref(&self) -> &FlacDecoderUnmovable<'a, ReadSeek> {
2216        &self.decoder
2217    }
2218}
2219
2220impl<'a, ReadSeek> DerefMut for FlacDecoder<'a, ReadSeek>
2221where
2222    ReadSeek: Read + Seek + Debug {
2223    fn deref_mut(&mut self) -> &mut FlacDecoderUnmovable<'a, ReadSeek> {
2224        &mut self.decoder
2225    }
2226}
2227
2228#[derive(Clone, Copy)]
2229struct WrappedStreamInfo(FLAC__StreamMetadata_StreamInfo);
2230
2231impl Debug for WrappedStreamInfo {
2232    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2233        fmt.debug_struct("FLAC__StreamMetadata_StreamInfo")
2234            .field("min_blocksize", &self.0.min_blocksize)
2235            .field("max_blocksize", &self.0.max_blocksize)
2236            .field("min_framesize", &self.0.min_framesize)
2237            .field("max_framesize", &self.0.max_framesize)
2238            .field("sample_rate", &self.0.sample_rate)
2239            .field("channels", &self.0.channels)
2240            .field("bits_per_sample", &self.0.bits_per_sample)
2241            .field("total_samples", &self.0.total_samples)
2242            .field("md5sum", &format_args!("{}", self.0.md5sum.iter().map(|x|{format!("{:02x}", x)}).collect::<Vec<String>>().join("")))
2243            .finish()
2244    }
2245}
2246
2247#[derive(Clone, Copy)]
2248struct WrappedPadding(FLAC__StreamMetadata_Padding);
2249impl Debug for WrappedPadding {
2250    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2251        fmt.debug_struct("FLAC__StreamMetadata_Padding")
2252            .field("dummy", &self.0.dummy)
2253            .finish()
2254    }
2255}
2256
2257#[derive(Clone, Copy)]
2258struct WrappedApplication(FLAC__StreamMetadata_Application, u32);
2259impl WrappedApplication {
2260    pub fn get_header(&self) -> String {
2261        String::from_utf8_lossy(&self.0.id).to_string()
2262    }
2263    pub fn get_data(&self) -> Vec<u8> {
2264        let n = self.1 - 4;
2265        unsafe {slice::from_raw_parts(self.0.data, n as usize)}.to_vec()
2266    }
2267}
2268
2269impl Debug for WrappedApplication {
2270    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2271        fmt.debug_struct("FLAC__StreamMetadata_Application")
2272            .field("id", &self.get_header())
2273            .field("data", &String::from_utf8_lossy(&self.get_data()))
2274            .finish()
2275    }
2276}
2277
2278#[derive(Clone, Copy)]
2279struct WrappedSeekPoint(FLAC__StreamMetadata_SeekPoint);
2280impl Debug for WrappedSeekPoint {
2281    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2282        fmt.debug_struct("FLAC__StreamMetadata_SeekPoint")
2283            .field("sample_number", &self.0.sample_number)
2284            .field("stream_offset", &self.0.stream_offset)
2285            .field("frame_samples", &self.0.frame_samples)
2286            .finish()
2287    }
2288}
2289
2290#[derive(Clone, Copy)]
2291struct WrappedSeekTable(FLAC__StreamMetadata_SeekTable);
2292impl Debug for WrappedSeekTable {
2293    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2294        let points: Vec<WrappedSeekPoint> = unsafe {slice::from_raw_parts(self.0.points, self.0.num_points as usize).iter().map(|p|{WrappedSeekPoint(*p)}).collect()};
2295        fmt.debug_struct("FLAC__StreamMetadata_SeekTable")
2296            .field("num_points", &self.0.num_points)
2297            .field("points", &format_args!("{:?}", points))
2298            .finish()
2299    }
2300}
2301
2302#[derive(Clone, Copy)]
2303struct WrappedVorbisComment(FLAC__StreamMetadata_VorbisComment);
2304impl Debug for WrappedVorbisComment {
2305    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2306        fmt.debug_struct("FLAC__StreamMetadata_VorbisComment")
2307            .field("vendor_string", &entry_to_string(&self.0.vendor_string))
2308            .field("num_comments", &self.0.num_comments)
2309            .field("comments", &format_args!("[{}]", (0..self.0.num_comments).map(|i|unsafe{entry_to_string(&*self.0.comments.add(i as usize))}).collect::<Vec<String>>().join(", ")))
2310            .finish()
2311    }
2312}
2313
2314#[derive(Clone, Copy)]
2315struct WrappedCueSheet(FLAC__StreamMetadata_CueSheet);
2316impl Debug for WrappedCueSheet {
2317    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2318        fmt.debug_struct("FLAC__StreamMetadata_CueSheet")
2319            .field("media_catalog_number", &String::from_utf8_lossy(&self.0.media_catalog_number.into_iter().map(|c|{c as u8}).collect::<Vec<u8>>()))
2320            .field("lead_in", &self.0.lead_in)
2321            .field("is_cd", &self.0.is_cd)
2322            .field("num_tracks", &self.0.num_tracks)
2323            .field("tracks", &format_args!("[{}]", (0..self.0.num_tracks).map(|i|format!("{:?}", unsafe{*self.0.tracks.add(i as usize)})).collect::<Vec<String>>().join(", ")))
2324            .finish()
2325    }
2326}
2327
2328#[derive(Clone, Copy)]
2329struct WrappedCueSheetTrack(FLAC__StreamMetadata_CueSheet_Track);
2330impl Debug for WrappedCueSheetTrack {
2331    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2332        fmt.debug_struct("FLAC__StreamMetadata_CueSheet_Track")
2333            .field("offset", &self.0.offset)
2334            .field("number", &self.0.number)
2335            .field("isrc", &self.0.isrc)
2336            .field("type", &self.0.type_())
2337            .field("pre_emphasis", &self.0.pre_emphasis())
2338            .field("num_indices", &self.0.num_indices)
2339            .field("indices", &format_args!("[{}]", (0..self.0.num_indices).map(|i|format!("{:?}", unsafe{*self.0.indices.add(i as usize)})).collect::<Vec<String>>().join(", ")))
2340            .finish()
2341    }
2342}
2343
2344#[derive(Clone, Copy)]
2345struct WrappedCueSheetIndex(FLAC__StreamMetadata_CueSheet_Index);
2346impl Debug for WrappedCueSheetIndex {
2347    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2348        fmt.debug_struct("FLAC__StreamMetadata_CueSheet_Index")
2349            .field("offset", &self.0.offset)
2350            .field("number", &self.0.number)
2351            .finish()
2352    }
2353}
2354
2355fn picture_type_to_str(pictype: u32) -> &'static str {
2356    match pictype {
2357        FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD => "32x32 pixels 'file icon' (PNG only)",
2358        FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON => "Other file icon",
2359        FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER => "Cover (front)",
2360        FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER => "Cover (back)",
2361        FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE => "Leaflet page",
2362        FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA => "Media (e.g. label side of CD)",
2363        FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST => "Lead artist/lead performer/soloist",
2364        FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST => "Artist/performer",
2365        FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR => "Conductor",
2366        FLAC__STREAM_METADATA_PICTURE_TYPE_BAND => "Band/Orchestra",
2367        FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER => "Composer",
2368        FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST => "Lyricist/text writer",
2369        FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION => "Recording Location",
2370        FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING => "During recording",
2371        FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE => "During performance",
2372        FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE => "Movie/video screen capture",
2373        FLAC__STREAM_METADATA_PICTURE_TYPE_FISH => "A bright coloured fish",
2374        FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION => "Illustration",
2375        FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE => "Band/artist logotype",
2376        FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE => "Publisher/Studio logotype",
2377        _ => "Other",
2378    }
2379}
2380
2381#[derive(Clone, Copy)]
2382struct WrappedPicture(FLAC__StreamMetadata_Picture);
2383impl Debug for WrappedPicture {
2384    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2385        fmt.debug_struct("FLAC__StreamMetadata_Picture")
2386            .field("type_", &picture_type_to_str(self.0.type_))
2387            .field("mime_type", &unsafe{CStr::from_ptr(self.0.mime_type).to_str()})
2388            .field("description", &unsafe{CStr::from_ptr(self.0.description as *const i8).to_str()})
2389            .field("width", &self.0.width)
2390            .field("height", &self.0.height)
2391            .field("depth", &self.0.depth)
2392            .field("colors", &self.0.colors)
2393            .field("data_length", &self.0.data_length)
2394            .field("data", &format_args!("[u8; {}]", self.0.data_length))
2395            .finish()
2396    }
2397}
2398
2399#[derive(Clone, Copy)]
2400struct WrappedUnknown(FLAC__StreamMetadata_Unknown);
2401impl Debug for WrappedUnknown {
2402    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2403        fmt.debug_struct("FLAC__StreamMetadata_Unknown")
2404            .finish_non_exhaustive()
2405    }
2406}
2407
2408#[derive(Clone, Copy)]
2409struct WrappedStreamMetadata(FLAC__StreamMetadata);
2410
2411impl Debug for WrappedStreamMetadata {
2412    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
2413        fmt.debug_struct("FLAC__StreamMetadata")
2414            .field("type_", &self.0.type_)
2415            .field("is_last", &self.0.is_last)
2416            .field("length", &self.0.length)
2417            .field("data", &match self.0.type_ {
2418                FLAC__METADATA_TYPE_STREAMINFO => format!("{:?}", unsafe{WrappedStreamInfo(self.0.data.stream_info)}),
2419                FLAC__METADATA_TYPE_PADDING => format!("{:?}", unsafe{WrappedPadding(self.0.data.padding)}),
2420                FLAC__METADATA_TYPE_APPLICATION => format!("{:?}", unsafe{WrappedApplication(self.0.data.application, self.0.length)}),
2421                FLAC__METADATA_TYPE_SEEKTABLE => format!("{:?}", unsafe{WrappedSeekTable(self.0.data.seek_table)}),
2422                FLAC__METADATA_TYPE_VORBIS_COMMENT => format!("{:?}", unsafe{WrappedVorbisComment(self.0.data.vorbis_comment)}),
2423                FLAC__METADATA_TYPE_CUESHEET => format!("{:?}", unsafe{WrappedCueSheet(self.0.data.cue_sheet)}),
2424                FLAC__METADATA_TYPE_PICTURE => format!("{:?}", unsafe{WrappedPicture(self.0.data.picture)}),
2425                FLAC__METADATA_TYPE_UNDEFINED => format!("{:?}", unsafe{WrappedUnknown(self.0.data.unknown)}),
2426                o => format!("Unknown metadata type {o}"),
2427            })
2428            .finish()
2429    }
2430}