Fix duplicate device names in dropdown - append device ID
UX Problem: - 4 devices all showed "Cambridge Audio USB Audio 2.0" - Selecting one would select all (Map key collision) - User couldn't distinguish between hw:4,0, front:CARD=C20, iec958:CARD=C20 Solution: - Detect duplicate display names in deviceOptions - Append [device_id] to duplicates for uniqueness - Example: "Cambridge Audio USB Audio 2.0 (Direct Hardware - Bit-perfect) [hw:4,0]" Now User Sees: - Cambridge Audio USB Audio 2.0 (Direct Hardware - Bit-perfect) [hw:4,0] ← TRUE bit-perfect - Cambridge Audio USB Audio 2.0 [front:CARD=C20,DEV=0] ← Front output with plugins - Cambridge Audio USB Audio 2.0 [iec958:CARD=C20,DEV=0] ← S/PDIF with plugins - Cambridge Audio USB Audio 2.0 [sysdefault:CARD=C20] ← System default with dmix Each option is now unique and selectable. The hw:4,0 option is clearly marked as "Direct Hardware - Bit-perfect" for audiophiles.
This commit is contained in:
1 parent
39a661417d
commit
c93226718f
1 file changed
+37
-10
@@ -231,27 +231,54 @@
|
||||
// For ALSA: use description from aplay -L if available, otherwise translate
|
||||
// For PipeWire/PulseAudio: names are already friendly
|
||||
let deviceOptions = $derived.by(() => {
|
||||
const names = backendDevices.map(d => {
|
||||
// If backend provides description (ALSA via aplay -L), use it
|
||||
// First pass: generate display names
|
||||
const displayNames = backendDevices.map(d => {
|
||||
if (d.description && selectedBackend === 'ALSA Direct') {
|
||||
return d.description;
|
||||
}
|
||||
// Otherwise apply translation if needed
|
||||
return needsTranslation(d.name) ? getDevicePrettyName(d.name) : d.name;
|
||||
});
|
||||
return ['System Default', ...names];
|
||||
|
||||
// Second pass: check for duplicates and make unique if needed
|
||||
const counts = new Map<string, number>();
|
||||
const uniqueNames = displayNames.map((name, idx) => {
|
||||
const count = counts.get(name) || 0;
|
||||
counts.set(name, count + 1);
|
||||
|
||||
// If duplicate, append device ID to make it unique
|
||||
if (displayNames.filter(n => n === name).length > 1) {
|
||||
const device = backendDevices[idx];
|
||||
return `${name} [${device.name}]`;
|
||||
}
|
||||
return name;
|
||||
});
|
||||
|
||||
return ['System Default', ...uniqueNames];
|
||||
});
|
||||
|
||||
// Map display name -> device for lookup when user selects
|
||||
let deviceByDisplayName = $derived.by(() => {
|
||||
const map = new Map<string, AudioDevice>();
|
||||
for (const device of backendDevices) {
|
||||
// Same logic: prefer description for ALSA
|
||||
const displayName = (device.description && selectedBackend === 'ALSA Direct')
|
||||
? device.description
|
||||
: (needsTranslation(device.name) ? getDevicePrettyName(device.name) : device.name);
|
||||
|
||||
// Use same logic as deviceOptions to generate unique names
|
||||
const displayNames = backendDevices.map(d => {
|
||||
if (d.description && selectedBackend === 'ALSA Direct') {
|
||||
return d.description;
|
||||
}
|
||||
return needsTranslation(d.name) ? getDevicePrettyName(d.name) : d.name;
|
||||
});
|
||||
|
||||
backendDevices.forEach((device, idx) => {
|
||||
let displayName = displayNames[idx];
|
||||
|
||||
// If duplicate, append device ID
|
||||
if (displayNames.filter(n => n === displayName).length > 1) {
|
||||
displayName = `${displayName} [${device.name}]`;
|
||||
}
|
||||
|
||||
map.set(displayName, device);
|
||||
}
|
||||
});
|
||||
|
||||
return map;
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user