Skip to main content

selene_core/config/
common.rs

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