Add audio output badges and pretty device names
- Add AudioOutputBadges component showing DAC/Exclusive mode status - Badges are reactive to actual player state, not just settings - Add device tooltip on hover showing current output device - Create audioDeviceNames helper for ALSA name to friendly name mapping - Use pretty names in Settings dropdown while storing raw names - Add get_audio_output_status backend command - Store current device name in player SharedState
This commit is contained in:
1 parent
4b07618ed0
commit
dd9d5558fa
7 files changed
+384
-6
No files matched your search
@@ -326,3 +326,24 @@ pub fn get_audio_devices() -> Result<Vec<AudioDevice>, String> {
|
||||
log::info!("Found {} audio output devices", devices.len());
|
||||
Ok(devices)
|
||||
}
|
||||
|
||||
/// Current audio output status
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct AudioOutputStatus {
|
||||
pub device_name: Option<String>,
|
||||
pub is_playing: bool,
|
||||
}
|
||||
|
||||
/// Get current audio output status (what device is actually being used)
|
||||
#[tauri::command]
|
||||
pub fn get_audio_output_status(
|
||||
state: tauri::State<'_, crate::AppState>,
|
||||
) -> Result<AudioOutputStatus, String> {
|
||||
let device_name = state.player.state.current_device();
|
||||
let is_playing = state.player.state.is_playing();
|
||||
|
||||
Ok(AudioOutputStatus {
|
||||
device_name,
|
||||
is_playing,
|
||||
})
|
||||
}
|
||||
@@ -234,6 +234,7 @@ pub fn run() {
|
||||
commands::get_playback_state,
|
||||
commands::set_media_metadata,
|
||||
commands::get_audio_devices,
|
||||
commands::get_audio_output_status,
|
||||
// Queue commands
|
||||
commands::add_to_queue,
|
||||
commands::add_to_queue_next,
|
||||
|
||||
@@ -63,6 +63,8 @@ pub struct SharedState {
|
||||
playback_start_millis: Arc<AtomicU64>,
|
||||
/// Position when playback was started/resumed (in seconds)
|
||||
position_at_start: Arc<AtomicU64>,
|
||||
/// Current output device name
|
||||
current_device: Arc<std::sync::RwLock<Option<String>>>,
|
||||
}
|
||||
|
||||
impl Default for SharedState {
|
||||
@@ -81,9 +83,20 @@ impl SharedState {
|
||||
volume: Arc::new(AtomicU64::new(75)),
|
||||
playback_start_millis: Arc::new(AtomicU64::new(0)),
|
||||
position_at_start: Arc::new(AtomicU64::new(0)),
|
||||
current_device: Arc::new(std::sync::RwLock::new(None)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_current_device(&self, device: Option<String>) {
|
||||
if let Ok(mut d) = self.current_device.write() {
|
||||
*d = device;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_device(&self) -> Option<String> {
|
||||
self.current_device.read().ok().and_then(|d| d.clone())
|
||||
}
|
||||
|
||||
/// Get current position based on elapsed time since playback started
|
||||
pub fn current_position(&self) -> u64 {
|
||||
if !self.is_playing.load(Ordering::SeqCst) {
|
||||
@@ -198,11 +211,13 @@ impl Player {
|
||||
Some(d) => {
|
||||
if let Ok(name) = d.name() {
|
||||
log::info!("Using audio device: {}", name);
|
||||
thread_state.set_current_device(Some(name));
|
||||
}
|
||||
d
|
||||
}
|
||||
None => {
|
||||
log::error!("No audio output device available");
|
||||
thread_state.set_current_device(None);
|
||||
// Keep thread alive to receive commands
|
||||
loop {
|
||||
match rx.recv() {
|
||||
|
||||
Reference in new issue
Block a user