use std::io::{Seek, Write};
use crate::{config::EncoderConfig, level::Level};
use super::session::Recompressor;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum RecompressMode {
Loose,
#[default]
Default,
Strict,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RecompressConfig {
mode: RecompressMode,
level: Level,
threads: usize,
block_size: Option<u16>,
}
impl Default for RecompressConfig {
fn default() -> Self {
Self {
mode: RecompressMode::Default,
level: Level::Level8,
threads: std::thread::available_parallelism()
.map(usize::from)
.unwrap_or(1),
block_size: None,
}
}
}
impl RecompressConfig {
#[must_use]
pub fn builder() -> RecompressBuilder {
RecompressBuilder::default()
}
#[must_use]
pub fn mode(self) -> RecompressMode {
self.mode
}
#[must_use]
pub fn level(self) -> Level {
self.level
}
#[must_use]
pub fn threads(self) -> usize {
self.threads
}
#[must_use]
pub fn block_size(self) -> Option<u16> {
self.block_size
}
#[must_use]
pub fn with_mode(mut self, mode: RecompressMode) -> Self {
self.mode = mode;
self
}
#[must_use]
pub fn with_level(mut self, level: Level) -> Self {
self.level = level;
self.block_size = None;
self
}
#[must_use]
pub fn with_threads(mut self, threads: usize) -> Self {
self.threads = threads.max(1);
self
}
#[must_use]
pub fn with_block_size(mut self, block_size: u16) -> Self {
self.block_size = Some(block_size);
self
}
pub fn into_recompressor<W>(self, writer: W) -> Recompressor<W>
where
W: Write + Seek,
{
Recompressor::new(writer, self)
}
pub(crate) fn flac_reader_options(self) -> crate::FlacReaderOptions {
let decode = self.decode_config();
crate::FlacReaderOptions {
strict_seektable_validation: decode.strict_seektable_validation(),
strict_channel_mask_provenance: decode.strict_channel_mask_provenance(),
}
}
pub(crate) fn decode_config(self) -> crate::DecodeConfig {
let base = crate::DecodeConfig::default().with_threads(self.threads);
match self.mode {
RecompressMode::Loose => base
.with_emit_fxmd(false)
.with_strict_channel_mask_provenance(false)
.with_strict_seektable_validation(false),
RecompressMode::Default => base
.with_emit_fxmd(true)
.with_strict_channel_mask_provenance(false)
.with_strict_seektable_validation(false),
RecompressMode::Strict => base
.with_emit_fxmd(true)
.with_strict_channel_mask_provenance(true)
.with_strict_seektable_validation(true),
}
}
pub(crate) fn encode_config(self) -> EncoderConfig {
let mut base = EncoderConfig::default()
.with_level(self.level)
.with_threads(self.threads);
if let Some(block_size) = self.block_size {
base = base.with_block_size(block_size);
}
match self.mode {
RecompressMode::Loose => base
.with_capture_fxmd(false)
.with_strict_fxmd_validation(false),
RecompressMode::Default | RecompressMode::Strict => base
.with_capture_fxmd(true)
.with_strict_fxmd_validation(true),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct RecompressBuilder {
config: RecompressConfig,
}
impl RecompressBuilder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn mode(mut self, mode: RecompressMode) -> Self {
self.config = self.config.with_mode(mode);
self
}
#[must_use]
pub fn level(mut self, level: Level) -> Self {
self.config = self.config.with_level(level);
self
}
#[must_use]
pub fn threads(mut self, threads: usize) -> Self {
self.config = self.config.with_threads(threads);
self
}
#[must_use]
pub fn block_size(mut self, block_size: u16) -> Self {
self.config = self.config.with_block_size(block_size);
self
}
#[must_use]
pub fn build(self) -> RecompressConfig {
self.config
}
pub fn into_recompressor<W>(self, writer: W) -> Recompressor<W>
where
W: Write + Seek,
{
self.build().into_recompressor(writer)
}
}