feat(audio-switcher): support input ports (#287)

This commit is contained in:
blacku
2026-08-07 22:35:39 -04:00
committed by GitHub
parent 9fd283bb52
commit 3467523e00
7 changed files with 217 additions and 9 deletions
+39 -2
View File
@@ -73,6 +73,12 @@ local function activeDevice(kind)
return nil
end
local function inputDisplayName(device)
if device == nil then return "" end
local port = noctalia.string.trim(tostring(device.activePortDescription or ""))
return port ~= "" and port or tostring(device.name or "")
end
local function visibleCount(kind)
local count = 0
local devices = kind == "output" and asArray(snapshot.outputs) or asArray(snapshot.inputs)
@@ -118,7 +124,7 @@ local function volumeCard(kind)
ui.column({ flexGrow = 1, gap = 2 }, {
ui.label({ text = tr(isOutput and "panel.output_volume" or "panel.input_volume"), fontWeight = "bold" }),
ui.label({
text = device and device.name or tr("panel.no_device"),
text = device and (isOutput and device.name or inputDisplayName(device)) or tr("panel.no_device"),
fontSize = 11,
color = "on_surface_variant",
maxLines = 1,
@@ -157,7 +163,10 @@ end
local function deviceSubtitle(device)
local status = deviceStatus(device)
local description = noctalia.string.trim(tostring(device.description or ""))
local port = noctalia.string.trim(tostring(device.activePortDescription or ""))
if port ~= "" and port ~= device.name and port ~= description then status = status .. " · " .. port end
if description == "" or description == "(null)" or description:lower() == "null" then return status end
if description == device.name or description == port then return status end
return status .. " · " .. description
end
@@ -228,6 +237,21 @@ local function deviceRow(device, kind)
local disbandAction = function()
sendCommand("remove_output_group", { id = device.id })
end
local ports = kind == "input" and asArray(device.ports) or {}
local portOptions = {}
local selectedPortIndex = 0
for index, port in ipairs(ports) do
local label = tostring(port.description or port.name or "")
if port.available == false then label = tr("device.unavailable_port", { port = label }) end
portOptions[#portOptions + 1] = label
if port.active then selectedPortIndex = index - 1 end
end
local selectPortAction = function(index, _label)
local port = ports[math.floor(tonumber(index) or -1) + 1]
if port ~= nil and not port.active then
sendCommand("set_input_port", { id = device.id, port = port.name })
end
end
local actionText = device.active and tr("device.current")
or (device.bluetooth and not device.available and tr("actions.connect_and_use") or tr("actions.use"))
local actionVariant = device.active and "ghost" or "primary"
@@ -294,6 +318,18 @@ local function deviceRow(device, kind)
ui.row({ align = "center", gap = 8, padding = 7, radius = 9, border = selectedGroupOutputs[device.id] and "primary" or (device.active and "primary" or "outline/0.55"), borderWidth = 1, fill = selectedGroupOutputs[device.id] and "primary/0.1" or (device.active and "primary/0.07" or "surface/0") }, rowChildren),
})
local children = { row }
if kind == "input" and #ports > 1 then
table.insert(children, ui.row({ gap = 8, align = "center", paddingH = 8 }, {
ui.label({ text = tr("device.port"), color = "on_surface_variant", fontSize = 10 }),
ui.select({
options = portOptions,
selectedIndex = selectedPortIndex,
flexGrow = 1,
enabled = snapshot.busy ~= true,
onChange = selectPortAction,
}),
}))
end
if editingId == device.id then table.insert(children, editor(device)) end
return ui.column({ gap = 6 }, children)
end
@@ -350,7 +386,8 @@ end
local function header()
local output = activeDevice("output")
local input = activeDevice("input")
local subtitle = (output and output.name or tr("panel.no_output")) .. " · " .. (input and input.name or tr("panel.no_input"))
local subtitle = (output and output.name or tr("panel.no_output")) .. " · "
.. (input and inputDisplayName(input) or tr("panel.no_input"))
return ui.row({ align = "center", gap = 8 }, {
ui.glyph({ name = "switch-horizontal", size = 24, color = "primary" }),
ui.column({ flexGrow = 1, gap = 2 }, {