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#[derive(Debug, Clone, Copy, PartialEq)]
25pub enum FlacCompression {
26 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 Level8 = 8
38}
39
40#[derive(Debug, Clone, Copy, PartialEq)]
42pub struct FlacEncoderParams {
43 pub verify_decoded: bool,
45
46 pub compression: FlacCompression,
48
49 pub channels: u16,
51
52 pub sample_rate: u32,
54
55 pub bits_per_sample: u32,
59
60 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
88pub trait FlacError: Any {
91 fn as_any(&self) -> &dyn Any;
93
94 fn get_code(&self) -> u32;
96
97 fn get_message(&self) -> &'static str;
99
100 fn get_function(&self) -> &'static str;
102
103 fn get_message_from_code(&self) -> &'static str;
105
106 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#[derive(Debug, Clone, Copy)]
140pub struct FlacEncoderError {
141 pub code: u32,
143
144 pub message: &'static str,
146
147 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#[derive(Debug, Clone, Copy)]
171pub enum FlacEncoderErrorCode {
172 StreamEncoderOk = FLAC__STREAM_ENCODER_OK as isize,
174
175 StreamEncoderUninitialized = FLAC__STREAM_ENCODER_UNINITIALIZED as isize,
177
178 StreamEncoderOggError = FLAC__STREAM_ENCODER_OGG_ERROR as isize,
180
181 StreamEncoderVerifyDecoderError = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR as isize,
183
184 StreamEncoderVerifyMismatchInAudioData = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA as isize,
186
187 StreamEncoderClientError = FLAC__STREAM_ENCODER_CLIENT_ERROR as isize,
189
190 StreamEncoderIOError = FLAC__STREAM_ENCODER_IO_ERROR as isize,
192
193 StreamEncoderFramingError = FLAC__STREAM_ENCODER_FRAMING_ERROR as isize,
195
196 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#[derive(Debug, Clone, Copy)]
238pub struct FlacEncoderInitError {
239 pub code: u32,
241
242 pub message: &'static str,
244
245 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#[derive(Debug, Clone, Copy)]
269pub enum FlacEncoderInitErrorCode {
270 StreamEncoderInitStatusOk = FLAC__STREAM_ENCODER_INIT_STATUS_OK as isize,
272
273 StreamEncoderInitStatusEncoderError = FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR as isize,
275
276 StreamEncoderInitStatusUnsupportedContainer = FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER as isize,
278
279 StreamEncoderInitStatusInvalidCallbacks = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS as isize,
281
282 StreamEncoderInitStatusInvalidNumberOfChannels = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS as isize,
284
285 StreamEncoderInitStatusInvalidBitsPerSample = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE as isize,
287
288 StreamEncoderInitStatusInvalidSampleRate = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE as isize,
290
291 StreamEncoderInitStatusInvalidBlockSize = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE as isize,
293
294 StreamEncoderInitStatusInvalidMaxLpcOrder = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER as isize,
296
297 StreamEncoderInitStatusInvalidQlpCoeffPrecision = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION as isize,
299
300 StreamEncoderInitStatusBlockSizeTooSmallForLpcOrder = FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER as isize,
302
303 StreamEncoderInitStatusNotStreamable = FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE as isize,
305
306 StreamEncoderInitStatusInvalidMetadata = FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA as isize,
315
316 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
386pub 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#[derive(Clone)]
425pub struct PictureData {
426 pub picture: Vec<u8>,
428
429 pub mime_type: String,
431
432 pub description: String,
434
435 pub width: u32,
437
438 pub height: u32,
440
441 pub depth: u32,
443
444 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 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#[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 pub offset: u64,
568
569 pub number: u8,
571}
572
573#[derive(Clone)]
574#[repr(C)]
575pub struct FlacCueTrack {
576 pub offset: u64,
578
579 pub track_no: u8,
581
582 pub isrc: [i8; 13],
584
585 pub type_: FlacTrackType,
587
588 pub pre_emphasis: bool,
590
591 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#[derive(Clone)]
629pub struct FlacCueSheet {
630 pub media_catalog_number: [i8; 129],
632
633 pub lead_in: u64,
635
636 pub is_cd: bool,
638
639 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 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
791pub struct FlacEncoderUnmovable<'a, WriteSeek>
794where
795 WriteSeek: Write + Seek + Debug {
796 encoder: *mut FLAC__StreamEncoder,
798
799 metadata: Vec<FlacMetadata>,
801
802 encoder_initialized: bool,
804
805 params: FlacEncoderParams,
807
808 writer: WriteSeek,
810
811 on_write: Box<dyn FnMut(&mut WriteSeek, &[u8]) -> Result<(), io::Error> + 'a>,
814
815 on_seek: Box<dyn FnMut(&mut WriteSeek, u64) -> Result<(), io::Error> + 'a>,
817
818 on_tell: Box<dyn FnMut(&mut WriteSeek) -> Result<u64, io::Error> + 'a>,
820
821 comments: BTreeMap<&'static str, String>,
823
824 cue_sheets: Vec<FlacCueSheet>,
826
827 pictures: Vec<PictureData>,
829
830 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 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 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 pub fn as_ptr(&self) -> *const Self {
885 self as *const Self
886 }
887
888 pub fn as_mut_ptr(&mut self) -> *mut Self {
892 self as *mut Self
893 }
894
895 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 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 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 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 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 pub fn tell(&mut self) -> Result<u64, io::Error> {
1089 (self.on_tell)(&mut self.writer)
1090 }
1091
1092 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 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 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 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 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 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 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
1254pub 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 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 pub code: u32,
1312
1313 pub message: &'static str,
1315
1316 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 StreamDecoderSearchForMetadata = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA as isize,
1342
1343 StreamDecoderReadMetadata = FLAC__STREAM_DECODER_READ_METADATA as isize,
1345
1346 StreamDecoderSearchForFrameSync = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC as isize,
1348
1349 StreamDecoderReadFrame = FLAC__STREAM_DECODER_READ_FRAME as isize,
1351
1352 StreamDecoderEndOfStream = FLAC__STREAM_DECODER_END_OF_STREAM as isize,
1354
1355 StreamDecoderOggError = FLAC__STREAM_DECODER_OGG_ERROR as isize,
1357
1358 StreamDecoderSeekError = FLAC__STREAM_DECODER_SEEK_ERROR as isize,
1360
1361 StreamDecoderAborted = FLAC__STREAM_DECODER_ABORTED as isize,
1363
1364 StreamDecoderMemoryAllocationError = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR as isize,
1366
1367 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 pub code: u32,
1413
1414 pub message: &'static str,
1416
1417 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#[derive(Debug, Clone, Copy)]
1501pub enum FlacReadStatus {
1502 GoOn,
1504
1505 Eof,
1507
1508 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#[derive(Debug, Clone, Copy)]
1524pub enum FlacInternalDecoderError {
1525 LostSync,
1527
1528 BadHeader,
1530
1531 FrameCrcMismatch,
1533
1534 UnparseableStream,
1536
1537 BadMetadata,
1539
1540 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#[derive(Debug, Clone, Copy)]
1561pub enum FlacAudioForm {
1562 FrameArray,
1565
1566 ChannelArray,
1569}
1570
1571#[derive(Debug, Clone, Copy)]
1572pub struct SamplesInfo {
1573 pub samples: u32,
1575
1576 pub channels: u32,
1578
1579 pub sample_rate: u32,
1581
1582 pub bits_per_sample: u32,
1585
1586 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
1598pub struct FlacDecoderUnmovable<'a, ReadSeek>
1601where
1602 ReadSeek: Read + Seek + Debug {
1603 decoder: *mut FLAC__StreamDecoder,
1605
1606 reader: ReadSeek,
1608
1609 on_read: Box<dyn FnMut(&mut ReadSeek, &mut [u8]) -> (usize, FlacReadStatus) + 'a>,
1611
1612 on_seek: Box<dyn FnMut(&mut ReadSeek, u64) -> Result<(), io::Error> + 'a>,
1614
1615 on_tell: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
1617
1618 on_length: Box<dyn FnMut(&mut ReadSeek) -> Result<u64, io::Error> + 'a>,
1620
1621 on_eof: Box<dyn FnMut(&mut ReadSeek) -> bool + 'a>,
1623
1624 on_write: Box<dyn FnMut(&[Vec<i32>], &SamplesInfo) -> Result<(), io::Error> + 'a>,
1626
1627 on_error: Box<dyn FnMut(FlacInternalDecoderError) + 'a>,
1629
1630 md5_checking: bool,
1632
1633 finished: bool,
1635
1636 pub scale_to_i32_range: bool,
1638
1639 pub desired_audio_form: FlacAudioForm,
1641
1642 pub vendor_string: Option<String>,
1644
1645 pub comments: BTreeMap<String, String>,
1647
1648 pub pictures: Vec<PictureData>,
1650
1651 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 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 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 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 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 this.vendor_string = Some(entry_to_string(&comments.vendor_string));
1875
1876 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 let mut iter = comment.split("=");
1885 if let Some(key) = iter.next() {
1886 let key = key.to_owned();
1887
1888 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 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 eprintln!("Invalid comment: {comment}");
1903 }
1904 }
1905
1906 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 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 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 pub fn tell(&mut self) -> Result<u64, io::Error> {
2033 (self.on_tell)(&mut self.reader)
2034 }
2035
2036 pub fn length(&mut self) -> Result<u64, io::Error> {
2038 (self.on_length)(&mut self.reader)
2039 }
2040
2041 pub fn eof(&mut self) -> bool {
2043 (self.on_eof)(&mut self.reader)
2044 }
2045
2046 pub fn get_vendor_string(&self) -> &Option<String> {
2048 &self.vendor_string
2049 }
2050
2051 pub fn get_comments(&self) -> &BTreeMap<String, String> {
2053 &self.comments
2054 }
2055
2056 pub fn get_pictures(&self) -> &Vec<PictureData> {
2058 &self.pictures
2059 }
2060
2061 pub fn get_cue_sheets(&self) -> &Vec<FlacCueSheet> {
2063 &self.cue_sheets
2064 }
2065
2066 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 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 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 FLAC__stream_decoder_delete(self.decoder);
2113 };
2114 }
2115
2116 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
2154pub 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 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}