diff options
Diffstat (limited to 'lib/pavolctld.lua')
-rw-r--r-- | lib/pavolctld.lua | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/pavolctld.lua b/lib/pavolctld.lua new file mode 100644 index 0000000..b6b6237 --- /dev/null +++ b/lib/pavolctld.lua @@ -0,0 +1,107 @@ +local awful = require("awful") +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 + +-- 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 + +-- return table +local pavolctld = { _cb = {}, sinks = sinks } + +-- callbacks +function pavolctld.set_volume_change_callback(cb) pavolctld._cb['v'] = cb end +function pavolctld.set_sink_change_callback(cb) pavolctld._cb['s'] = cb end +function pavolctld.set_default_sink_change_callback(cb) pavolctld._cb['f'] = cb end +function pavolctld.set_sink_remove_callback(cb) pavolctld._cb['x'] = cb 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()) + -- 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) + -- set command sink to default sink for now TODO change later + send_cmd("s") + -- sink removed + elseif cmd == 'x' then + local x = tonumber(s:sub(2)) + table.remove(sinks.sinks, x) + -- unrecognized cmd + else + naughty.notify({ + preset = naughty.config.presets.critical, + title = "pavolctld error", + text = s + }) + end + -- run command callback + if pavolctld._cb[cmd] then + pavolctld._cb[cmd]() + end +end) + +-- pavolctld takes commands in using stdin +function send_cmd(cmd) + local _, err = stdin:write_all(cmd .. "\n", nil) + + if err then return nil end + return true +end + +function pavolctld.volume_inc(vol) return send_cmd("v+" .. vol) end +function pavolctld.volume_dec(vol) return send_cmd("v-" .. vol) end +function pavolctld.volume_set(vol) return send_cmd("v" .. vol) end +function pavolctld.mute_set(muted) return send_cmd("m" .. muted and 1 or 0) end +function pavolctld.mute_toggle() return send_cmd("m") end +function pavolctld.default_sink_set(i) return send_cmd("f" .. i) end + +return pavolctld |