Files
jellytau/src-tauri/src/commands/player/settings.rs
T
dtourolle c543f90ad3 feat(audio): graphic equalizer with presets and custom bands
Adds a 10-band graphic equalizer to AudioSettings (enabled flag +
per-band dB gains, normalised to 10 entries and clamped to range).
Presets return gain curves; the settings page gains EQ UI. libmpv
applies the filter on Linux (Android parity pending). Old persisted
settings without EQ fields load as disabled + flat.

Also includes the requirements/traceability/ux-flows doc updates for
this feature and the home long-press routing (UR-058/DR-087).

TRACES: UR-027 | IR-020, DR-030 | UT-079, UT-080, UT-081, UT-082
2026-07-24 23:49:13 +02:00

84 lines
2.7 KiB
Rust

//! Audio and video playback settings commands.
//!
//! TRACES: UR-022, UR-027, UR-031, UR-032, UR-033 | DR-025, DR-030, DR-034, DR-035, DR-036, IR-020
use tauri::State;
use super::{PlayerStateWrapper, VideoSettingsWrapper};
use crate::player::AutoplaySettings;
use crate::settings::{AudioSettings, EqPreset, VideoSettings};
#[tauri::command]
#[specta::specta]
pub async fn player_set_audio_settings(
player: State<'_, PlayerStateWrapper>,
settings: AudioSettings,
) -> Result<AudioSettings, String> {
// Validate/normalise domain values before applying: clamp crossfade to its
// range and normalise the equalizer band vector (length + gain clamps).
let validated = settings
.with_crossfade_clamped()
.with_equalizer_normalised();
let mut controller = player.0.lock().await;
controller
.set_audio_settings(&validated)
.map_err(|e| e.to_string())?;
Ok(controller.audio_settings())
}
/// The built-in equalizer presets and their per-band gain curves (dB), for the
/// settings UI. The curve numbers are domain data defined by the band layout,
/// so the frontend reads them here rather than encoding them.
///
/// TRACES: UR-027 | DR-030
#[tauri::command]
#[specta::specta]
pub async fn player_get_eq_presets() -> Result<Vec<(EqPreset, Vec<f32>)>, String> {
Ok(EqPreset::ALL
.iter()
.map(|p| (*p, p.gains().to_vec()))
.collect())
}
#[tauri::command]
#[specta::specta]
pub async fn player_get_audio_settings(
player: State<'_, PlayerStateWrapper>,
) -> Result<AudioSettings, String> {
let controller = player.0.lock().await;
Ok(controller.audio_settings())
}
#[tauri::command]
#[specta::specta]
pub async fn player_set_video_settings(
video_settings: State<'_, VideoSettingsWrapper>,
player: State<'_, PlayerStateWrapper>,
settings: VideoSettings,
) -> Result<VideoSettings, String> {
let validated = settings.with_countdown_clamped();
{
let mut current = video_settings.0.lock().map_err(|e| e.to_string())?;
*current = validated.clone();
} // Drop MutexGuard before await
// Sync to PlayerController's autoplay settings so on_playback_ended() uses current values
let controller = player.0.lock().await;
controller.set_autoplay_settings(AutoplaySettings {
enabled: validated.auto_play_next_episode,
countdown_seconds: validated.auto_play_countdown_seconds,
max_episodes: validated.auto_play_max_episodes,
});
Ok(validated)
}
#[tauri::command]
#[specta::specta]
pub async fn player_get_video_settings(
video_settings: State<'_, VideoSettingsWrapper>,
) -> Result<VideoSettings, String> {
let current = video_settings.0.lock().map_err(|e| e.to_string())?;
Ok(current.clone())
}