use std::{
path::{Path, PathBuf},
sync::{OnceLock, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use lunar_lib::{
config::{Config, ConfigError},
debug,
};
use selene_core::runtime_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() -> Option<&'static Path> {
Some(selene_core::config_dir())
}
}
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 socket_path: PathBuf,
}
impl Default for MainSettings {
fn default() -> Self {
Self {
socket_path: runtime_dir().join("selene.sock"),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PlaybackSettings {
pub audio_buffer_size: usize,
pub restart_on_previous_thresh: Option<f64>,
}
impl Default for PlaybackSettings {
fn default() -> Self {
Self {
audio_buffer_size: 16,
restart_on_previous_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(),
}
}
}