Files
community-plugins/audio-switcher/widget.luau
T
HiImKobeAndandGitHub d6603f03cf feat: add toggle for notifications on device switch and toggle for keybinds in tooltip (#122)
* feat(audio-switcher): add toggle for notifications on device switch

* feat(audio-switcher): add toggle for actions in tooltip and change appearance of tooltip

* chore(audio-switcher): bump version to 0.2.0

* fix(audio-switcher): add missing translation keys
2026-07-28 21:16:34 -04:00

130 lines
4.2 KiB
Luau

--!nonstrict
local PANEL_ID = "blackbartblues/audio-switcher:audio-switcher"
local SNAPSHOT_KEY = "audio_switcher_snapshot"
local COMMAND_KEY = "audio_switcher_command"
local RESULT_KEY = "audio_switcher_result"
local snapshot = noctalia.state.get(SNAPSHOT_KEY) or {
available = false,
loading = true,
outputs = {},
inputs = {},
outputVolume = 0,
inputVolume = 0,
outputMuted = false,
}
local requestId = 0
local outputVolumeDraft = nil
local function activeDevice(devices, fallback)
for _, device in ipairs(type(devices) == "table" and devices or {}) do
if device.active == true then return device end
end
return nil
end
local function percent(value)
return tostring(math.floor((tonumber(value) or 0) + 0.5)) .. "%"
end
local function render()
local outputDevice = activeDevice(snapshot.outputs)
local inputDevice = activeDevice(snapshot.inputs)
local outputName = outputDevice and tostring(outputDevice.name or "") or noctalia.tr("panel.no_output")
local inputName = inputDevice and tostring(inputDevice.name or "") or noctalia.tr("panel.no_input")
local outputVolume = percent(outputVolumeDraft or snapshot.outputVolume)
local inputVolume = percent(snapshot.inputVolume)
local glyph = snapshot.outputMuted == true and "volume-off" or "volume"
if outputDevice ~= nil and snapshot.outputMuted ~= true then
glyph = tostring(outputDevice.icon or "volume")
end
barWidget.setGlyph(glyph)
if snapshot.busy == true then
barWidget.setGlyphColor("secondary")
elseif snapshot.available == true then
barWidget.setGlyphColor("primary")
else
barWidget.setGlyphColor("error")
end
local showPercentage = noctalia.getConfig("show_percentage") ~= false
barWidget.setText(showPercentage and not barWidget.isVertical() and outputVolume or "")
local tooltipItems = {{key = noctalia.tr("widget.output"), value = `{outputName} ({outputVolume})`},
{key = noctalia.tr("widget.input"), value = `{inputName} ({inputVolume})`}}
if noctalia.getConfig("show_actions_in_tooltip") == true then
table.insert(tooltipItems, {key = noctalia.tr("widget.action.scroll.key"), value = noctalia.tr("widget.action.scroll.description")})
table.insert(tooltipItems, {key = noctalia.tr("widget.action.left_click.key"), value = noctalia.tr("widget.action.left_click.description")})
table.insert(tooltipItems, {key = noctalia.tr("widget.action.right_click.key"), value = noctalia.tr("widget.action.right_click.description")})
table.insert(tooltipItems, {key = noctalia.tr("widget.action.middle_click.key"), value = noctalia.tr("widget.action.middle_click.description")})
end
barWidget.setTooltip(tooltipItems)
end
local function dispatch(action)
requestId += 1
noctalia.state.set(COMMAND_KEY, {
action = action,
requestId = "widget-" .. tostring(os.time()) .. "-" .. tostring(requestId),
})
end
noctalia.state.watch(SNAPSHOT_KEY, function(value)
if type(value) == "table" then
if outputVolumeDraft ~= nil and tonumber(value.outputVolume) == outputVolumeDraft then
outputVolumeDraft = nil
end
snapshot = value
render()
end
end)
noctalia.state.watch(RESULT_KEY, function(result)
if type(result) ~= "table" or not tostring(result.requestId or ""):match("^widget%-scroll%-") then return end
if result.ok ~= true then
outputVolumeDraft = nil
render()
end
end)
function update()
render()
end
function onConfigChanged()
render()
end
function onClick()
noctalia.togglePanel(PANEL_ID)
end
function onRightClick()
dispatch("cycle_output")
end
function onMiddleClick()
dispatch("cycle_input")
end
function onScroll(axis, steps)
if axis ~= "vertical" then return end
local detents = tonumber(steps) or 0
if detents == 0 then return end
local step = math.max(1, math.min(25, math.floor(tonumber(noctalia.getConfig("scroll_step")) or 5)))
local current = tonumber(outputVolumeDraft or snapshot.outputVolume) or 0
outputVolumeDraft = math.max(0, math.min(100, math.floor(current - detents * step + 0.5)))
render()
requestId += 1
noctalia.state.set(COMMAND_KEY, {
action = "set_output_volume",
value = outputVolumeDraft,
requestId = "widget-scroll-" .. tostring(os.time()) .. "-" .. tostring(requestId),
})
end
noctalia.setUpdateInterval(60000)
render()