summaryrefslogtreecommitdiff
path: root/widgets/pavolctld.lua
blob: f59b27f033331f34fecde903c478482a707b36ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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