summaryrefslogtreecommitdiff
path: root/widgets/pavolctld.lua
diff options
context:
space:
mode:
authorTim Keller <tjk@tjkeller.xyz>2024-10-18 21:49:17 -0500
committerTim Keller <tjk@tjkeller.xyz>2024-10-18 21:49:17 -0500
commit923eb46350b1102749eb05cd2120c96cc6a715d0 (patch)
tree811da20b4195d4b5c65c8ac0090982a4a23f6a7d /widgets/pavolctld.lua
downloadawesome-923eb46350b1102749eb05cd2120c96cc6a715d0.tar.xz
awesome-923eb46350b1102749eb05cd2120c96cc6a715d0.zip
initial commit
Diffstat (limited to 'widgets/pavolctld.lua')
-rw-r--r--widgets/pavolctld.lua104
1 files changed, 104 insertions, 0 deletions
diff --git a/widgets/pavolctld.lua b/widgets/pavolctld.lua
new file mode 100644
index 0000000..f59b27f
--- /dev/null
+++ b/widgets/pavolctld.lua
@@ -0,0 +1,104 @@
+local awful = require("awful")
+local wibox = require("wibox")
+local naughty = require("naughty")
+
+-- Gio is used to handle the subprocess instead of awful.spawn.
+-- Gio is more flexible and allows writing to stdin.
+-- also, awful.spawn.with_line_callback does not play nicely with pavolctld, as
+-- it seems to feed the stdout back into its stdin and kill performance.
+local lgi = require("lgi")
+local Gio = lgi.Gio
+
+-- return table
+local widget = {
+ textbox = wibox.widget.textbox()
+}
+
+-- start subprocess
+local p = Gio.Subprocess.new({ "pavolctld" }, Gio.SubprocessFlags.STDIN_PIPE + Gio.SubprocessFlags.STDOUT_PIPE)
+
+local stdout = p:get_stdout_pipe()
+local stdin = p:get_stdin_pipe()
+
+-- state vars
+local sinks = {
+ default = nil,
+ command = nil, -- sink being modified by commands
+ sinks = {},
+}
+
+function sinks.get(i)
+ if sinks.sinks[i] == nil then
+ sinks.sinks[i] = {
+ vol = 0,
+ db = 0.0,
+ mute = 0,
+ name = "",
+ desc = "",
+ }
+ end
+ return sinks.sinks[i]
+end
+
+-- parse output
+function parse_csv(csv)
+ return (csv .. ","):gmatch("(.-),")
+end
+
+awful.spawn.read_lines(stdout, function(s)
+ local cmd = s:sub(1, 1) -- first char of output
+ -- volume change
+ if cmd == 'v' then
+ local v = parse_csv(s:sub(2))
+ local i = tonumber(v())
+ local sink = sinks.get(i)
+ sink.vol = tonumber(v())
+ sink.db = tonumber(v())
+ sink.mute = tonumber(v())
+
+ if sink == sinks.default then
+ widget.textbox:set_text(sink.vol)
+ end
+ -- sink description change
+ elseif cmd == 's' then
+ local v = parse_csv(s:sub(2))
+ local i = tonumber(v())
+ local sink = sinks.get(i)
+ sink.name = v()
+ sink.desc = v()
+ -- default sink change
+ elseif cmd == 'f' then
+ local f = tonumber(s:sub(2))
+ sinks.default = sinks.get(f)
+ widget.textbox:set_text(sinks.default.vol)
+ -- set command sink to default sink for now TODO change later
+ pavolctld_cmd("s")
+ -- sink removed
+ elseif cmd == 'x' then
+ local x = tonumber(s:sub(2))
+ table.remove(sinks.sinks, x)
+ else
+ naughty.notify({
+ preset = naughty.config.presets.critical,
+ title = "pavolctld error",
+ text = s
+ })
+ end
+end)
+
+-- pavolctld takes commands in using stdin
+function pavolctld_cmd(cmd)
+ local _, err = stdin:write_all(cmd .. "\n", nil)
+
+ if err then return nil end
+ return true
+end
+
+function widget.volume_inc(vol) return pavolctld_cmd("v+" .. vol) end
+function widget.volume_dec(vol) return pavolctld_cmd("v-" .. vol) end
+function widget.volume_set(vol) return pavolctld_cmd("v" .. vol) end
+function widget.mute_set(muted) return pavolctld_cmd("m" .. muted and 1 or 0) end
+function widget.mute_toggle() return pavolctld_cmd("m") end
+function widget.default_sink_set(i) return pavolctld_cmd("f" .. i) end
+
+return widget