Skip to main content

selene_core/
config.rs

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