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