fix(audio): expand ALSA bit-perfect detection for front:CARD devices
- Add front:CARD=X,DEV=Y device enumeration from aplay -L output - Recognize front: devices as bit-perfect in AlsaDirectStream - Group front:CARD and "bit-perfect" named devices correctly in UI - Add tooltip to device dropdown showing full device name - Add current selection indicator in device dropdown - Extend dropdown idle timeout to 10 seconds for long device names Addresses issue #30 for USB DACs that expose front: but not hw: devices
This commit is contained in:
1 parent
9680bbb9cd
commit
7a76973920
3 files changed
+83
-9
No files matched your search
@@ -256,6 +256,54 @@ impl AlsaBackend {
|
||||
});
|
||||
}
|
||||
|
||||
// Fifth: Add front:CARD=X,DEV=Y devices from aplay -L (issue #30)
|
||||
// Some USB DACs (e.g., SMSL AD18) don't expose hw: devices but have working front: devices
|
||||
// DeaDBeef and Audacious use these for bit-perfect playback
|
||||
for (device_id, desc) in &description_map {
|
||||
// Match front:CARD=X,DEV=Y pattern
|
||||
if device_id.starts_with("front:CARD=") {
|
||||
// Check if we already have this device
|
||||
let already_exists = devices.iter().any(|d| d.name == *device_id);
|
||||
if already_exists {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract card name for friendly description
|
||||
// front:CARD=AMP,DEV=0 -> "AMP"
|
||||
let card_name = device_id
|
||||
.strip_prefix("front:CARD=")
|
||||
.and_then(|s| s.split(',').next())
|
||||
.unwrap_or("Unknown");
|
||||
|
||||
// Use card_map description if available, otherwise use aplay -L description
|
||||
let friendly_desc = card_map
|
||||
.iter()
|
||||
.find(|(_, card_desc)| {
|
||||
// Match by card short name in the description
|
||||
card_desc.to_lowercase().contains(&card_name.to_lowercase())
|
||||
})
|
||||
.map(|(_, card_desc)| card_desc.clone())
|
||||
.unwrap_or_else(|| desc.clone());
|
||||
|
||||
log::info!(
|
||||
"[ALSA Backend] Adding front: device for bit-perfect: {} ({})",
|
||||
device_id,
|
||||
friendly_desc
|
||||
);
|
||||
|
||||
devices.push(AudioDevice {
|
||||
id: device_id.clone(),
|
||||
name: device_id.clone(),
|
||||
description: Some(format!("{} (Direct Hardware - Bit-perfect)", friendly_desc)),
|
||||
is_default: false,
|
||||
max_sample_rate: Some(384000), // Assume high sample rate capability
|
||||
supported_sample_rates: None,
|
||||
device_bus: None,
|
||||
is_hardware: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("[ALSA Backend] Enumerated {} ALSA devices", devices.len());
|
||||
for (idx, dev) in devices.iter().enumerate() {
|
||||
log::info!(
|
||||
|
||||
@@ -285,9 +285,12 @@ impl AlsaDirectStream {
|
||||
Err(format!("No volume control found for {}. DAC may not support hardware mixer.", self.device_id))
|
||||
}
|
||||
|
||||
/// Check if device is hw: device
|
||||
/// Check if device is a bit-perfect hardware device
|
||||
/// Includes: hw:X,Y, plughw:X,Y, and front:CARD=X,DEV=Y
|
||||
pub fn is_hw_device(device_id: &str) -> bool {
|
||||
device_id.starts_with("hw:") || device_id.starts_with("plughw:")
|
||||
device_id.starts_with("hw:")
|
||||
|| device_id.starts_with("plughw:")
|
||||
|| device_id.starts_with("front:CARD=")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,6 +320,7 @@ impl AlsaDirectStream {
|
||||
2
|
||||
}
|
||||
|
||||
/// Check if device is a bit-perfect hardware device (always false on non-Linux)
|
||||
pub fn is_hw_device(_device_id: &str) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user