Skip to main content

selene_core/config/
common.rs

1use std::{
2    path::PathBuf,
3    sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard},
4};
5
6use lunar_lib::{config::Config, error};
7use serde::{Deserialize, Serialize};
8
9mod encoding;
10pub use encoding::*;
11
12static COMMON_CONFIG: LazyLock<RwLock<CommonConfig>> = LazyLock::new(|| {
13    let config = match CommonConfig::load() {
14        Ok(config) => config,
15        Err(err) => {
16            error!(
17                "Could not load common config from file, assuming defaults. Reason: {:?}",
18                err
19            );
20            CommonConfig::default()
21        }
22    };
23    RwLock::new(config)
24});
25
26/// Returns a read-only guard to the common config.
27///
28/// # Panics
29///
30/// This function will panic if the internal read/write lock is poisoned
31pub fn common_config() -> RwLockReadGuard<'static, CommonConfig> {
32    COMMON_CONFIG.read().unwrap()
33}
34
35/// Returns a mutable guard to the common config.
36///
37/// # Panics
38///
39/// This function will panic if the internal read/write lock is poisoned
40pub fn common_config_mut() -> RwLockWriteGuard<'static, CommonConfig> {
41    COMMON_CONFIG.write().unwrap()
42}
43
44mod core_impls;
45
46use crate::media_container::ContainerFormat;
47
48#[derive(Debug, Serialize, Deserialize, Default)]
49#[serde(default)]
50pub struct CommonConfig {
51    pub library: LibrarySettings,
52    pub loudnorm: LoudnormSettings,
53    pub track_name: TrackNameSettings,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
57#[serde(default)]
58pub struct LibrarySettings {
59    source_directories: Vec<PathBuf>,
60
61    file_name_format: TrackNameSettings,
62    transcode_options: Vec<TranscodeSettings>,
63}
64
65impl Default for LibrarySettings {
66    fn default() -> Self {
67        Self {
68            source_directories: Default::default(),
69            file_name_format: Default::default(),
70            transcode_options: vec![
71                // Lossless formats -> Flac
72                TranscodeSettings::to_flac(Some(ContainerFormat::Wav), None),
73                TranscodeSettings::to_flac(Some(ContainerFormat::Aiff), None),
74                TranscodeSettings::to_flac(Some(ContainerFormat::Ape), None),
75            ],
76        }
77    }
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
81#[serde(default)]
82pub struct TrackNameSettings {
83    pub format_string: String,
84    pub artist_separator: String,
85    pub alt_artist_separator: String,
86}
87
88impl Default for TrackNameSettings {
89    fn default() -> Self {
90        const DEFAULT_FORMAT_STRING: &str = if cfg!(windows) {
91            "{$album>\\\\}{$main_track_artist?UNKNOWN ARTIST} - {$title?UNKNOWN TITLE}{$feat_track_artists< (feat. >)}"
92        } else {
93            "{$album>/}{$main_track_artist?UNKNOWN ARTIST} - {$title?UNKNOWN TITLE}{$feat_track_artists< (feat. >)}"
94        };
95
96        Self {
97            format_string: DEFAULT_FORMAT_STRING.to_owned(),
98            artist_separator: ", ".to_owned(),
99            alt_artist_separator: " & ".to_owned(),
100        }
101    }
102}
103
104#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
105#[serde(default)]
106pub struct LoudnormSettings {
107    pub accurate_true_peak: bool,
108
109    pub target_offset: f64,
110    pub target_i: f64,
111    pub target_tp: f64,
112}
113
114impl Default for LoudnormSettings {
115    fn default() -> Self {
116        Self {
117            accurate_true_peak: true,
118
119            target_offset: 0.0,
120            target_i: -14.0,
121            target_tp: -2.0,
122        }
123    }
124}