use std::{
net::SocketAddr,
path::PathBuf,
sync::{OnceLock, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use lunar_lib::{
config::{Config, ConfigError},
log::debug,
paths::config_dir,
};
use serde::{Deserialize, Serialize};
pub static DAEMON_CONFIG: OnceLock<RwLock<DaemonConfig>> = OnceLock::new();
pub fn initialize_daemon_config() -> Result<(), ConfigError> {
if DAEMON_CONFIG.get().is_some() {
return Ok(());
}
let config = DaemonConfig::load()?;
let _ = DAEMON_CONFIG.set(RwLock::new(config));
Ok(())
}
pub fn daemon_config() -> RwLockReadGuard<'static, DaemonConfig> {
DAEMON_CONFIG
.get()
.expect("Config wasn't intialized")
.read()
.unwrap()
}
pub fn daemon_config_mut() -> RwLockWriteGuard<'static, DaemonConfig> {
DAEMON_CONFIG
.get()
.expect("Config wasn't initialized")
.write()
.unwrap()
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct DaemonConfig {
pub main: MainSettings,
pub playback: PlaybackSettings,
}
impl Config for DaemonConfig {
const CONFIG_FILE_NAME: &'static str = "daemon";
fn config_dir() -> PathBuf {
config_dir().clone()
}
}
impl DaemonConfig {
pub fn reload() -> Result<(), ConfigError> {
debug!("Reloading daemon config");
initialize_daemon_config()?;
let mut current_config = daemon_config_mut();
let loaded_config = Self::load()?;
*current_config = loaded_config;
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MainSettings {
pub scrobbling: bool,
pub socket_name: String,
pub host: SocketAddr,
}
impl Default for MainSettings {
fn default() -> Self {
Self {
scrobbling: true,
socket_name: "selene".to_owned(),
host: "[::1]:8080".parse().unwrap(),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PlaybackSettings {
pub audio_buffer_size: usize,
pub previous_restart_thresh: Option<f64>,
}
impl Default for PlaybackSettings {
fn default() -> Self {
Self {
audio_buffer_size: 16,
previous_restart_thresh: Some(5.0),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct NotificationSettings {
pub enabled: bool,
pub body_format: String,
pub header_format: String,
}
impl Default for NotificationSettings {
fn default() -> Self {
Self {
enabled: true,
header_format: "Now playing: {$title?UNKNOWN TITLE}".to_owned(),
body_format: "by {$main_track_artist?UNKNOWN_ARTIST} {$feat_track_artists< (feat. >)}"
.to_owned(),
}
}
}