From d727af55c0f4f6749b1a2b97a721cc69963ddeeb Mon Sep 17 00:00:00 2001 From: Stefan Huber Date: Wed, 25 Jan 2023 15:36:38 +0100 Subject: [PATCH] pactl: Do not call pactl get-* commands Older versions of pactl, like the one shipped by Debian Bullseye, do not provide the get-* commands, like get-sink-volume or get-sink-mute. Work around them by relying on `pactl list` and `pactl info` only. This commit increases code complexity significantly and reimplementing pactl-logic in lua impairs performance compared to a modern pactl, where this workaround would not be needed. Fixes issue #390. --- pactl-widget/pactl.lua | 61 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/pactl-widget/pactl.lua b/pactl-widget/pactl.lua index 638dc7e5..53dbcd8b 100644 --- a/pactl-widget/pactl.lua +++ b/pactl-widget/pactl.lua @@ -16,15 +16,40 @@ function pactl.mute_toggle(device) spawn('pactl set-sink-mute ' .. device .. ' toggle', false) end +function pactl.get_default_sink() + local line = utils.popen_and_return('pactl info'):match('Default Sink: [^\n]*') + if line == nil then + return "none" + end + + local t = utils.split(line, ':') + return utils.trim(t[2]) +end + function pactl.get_volume(device) - local stdout = utils.popen_and_return('pactl get-sink-volume ' .. device) + if device == '@DEFAULT_SINK@' then + device = pactl.get_default_sink() + end local volsum, volcnt = 0, 0 - for vol in string.gmatch(stdout, "(%d?%d?%d)%%") do - vol = tonumber(vol) - if vol ~= nil then - volsum = volsum + vol - volcnt = volcnt + 1 + local matched_sink = false + for line in utils.popen_and_return('pactl list sinks'):gmatch('([^\r\n]*)[\r\n]') do + local linetrim = utils.trim(line) + + if linetrim == "Name: " .. device then + matched_sink = true + end + + if matched_sink and linetrim:match("^Volume:") then + + for vol in string.gmatch(linetrim, "(%d?%d?%d)%%") do + vol = tonumber(vol) + if vol ~= nil then + volsum = volsum + vol + volcnt = volcnt + 1 + end + end + break end end @@ -36,12 +61,26 @@ function pactl.get_volume(device) end function pactl.get_mute(device) - local stdout = utils.popen_and_return('pactl get-sink-mute ' .. device) - if string.find(stdout, "yes") then - return true - else - return false + + if device == '@DEFAULT_SINK@' then + device = pactl.get_default_sink() end + + local volsum, volcnt = 0, 0 + local matched_sink = false + for line in utils.popen_and_return('pactl list sinks'):gmatch('([^\r\n]*)[\r\n]') do + local linetrim = utils.trim(line) + + if linetrim == "Name: " .. device then + matched_sink = true + end + + if matched_sink and linetrim == "Mute: yes" then + return true + end + end + + return false end function pactl.get_sinks_and_sources()