--]]
-local newtimer = require("lain.helpers").newtimer
-local read_pipe = require("lain.helpers").read_pipe
-
+local helpers = require("lain.helpers")
local awful = require("awful")
-local beautiful = require("beautiful")
local naughty = require("naughty")
-
+local wibox = require("wibox")
local math = { modf = math.modf }
-local mouse = mouse
local string = { format = string.format,
+ gmatch = string.gmatch,
match = string.match,
rep = string.rep }
+local type = type
local tonumber = tonumber
-
local setmetatable = setmetatable
--- ALSA volume bar
+-- Pulseaudio volume bar
-- lain.widgets.pulsebar
local pulsebar = {
- sink = 0,
-
colors = {
- background = beautiful.bg_normal,
+ background = "#000000",
mute = "#EB8F8F",
unmute = "#A4CE8A"
},
- mixer = "pavucontrol",
-
- notifications = {
- font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
- font_size = "11",
- color = beautiful.fg_normal,
- bar_size = 18,
- screen = 1
- },
-
_current_level = 0,
_muted = false
}
-function pulsebar.notify()
- pulsebar.update()
-
- local preset = {
- title = "",
- text = "",
- timeout = 5,
- screen = pulsebar.notifications.screen,
- font = pulsebar.notifications.font .. " " ..
- pulsebar.notifications.font_size,
- fg = pulsebar.notifications.color
- }
-
- if pulsebar._muted
- then
- preset.title = "Sink " .. pulsebar.sink .. " - Muted"
- else
- preset.title = "Sink " .. pulsebar.sink .. " - " .. pulsebar._current_level .. "%"
- end
-
- int = math.modf((pulsebar._current_level / 100) * pulsebar.notifications.bar_size)
- preset.text = "["
- .. string.rep("|", int)
- .. string.rep(" ", pulsebar.notifications.bar_size - int)
- .. "]"
-
- if pulsebar.followmouse then
- preset.screen = mouse.screen
- end
-
- if pulsebar._notify ~= nil then
- pulsebar._notify = naughty.notify ({
- replaces_id = pulsebar._notify.id,
- preset = preset,
- })
- else
- pulsebar._notify = naughty.notify ({
- preset = preset,
- })
- end
-end
-
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
local vertical = args.vertical or false
local scallback = args.scallback
- pulsebar.cmd = args.cmd or string.format("pacmd list-sinks | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p'")
- pulsebar.colors = args.colors or pulsebar.colors
- pulsebar.notifications = args.notifications or pulsebar.notifications
+ pulsebar.cmd = args.cmd or "pacmd list-sinks | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
pulsebar.sink = args.sink or 0
- pulsebar.followmouse = args.followmouse or false
+ pulsebar.colors = args.colors or pulsebar.colors
+ pulsebar.followtag = args.followtag or false
+ pulsebar.notifications = args.notification_preset
- pulsebar.bar = awful.widget.progressbar()
+ if not pulsebar.notification_preset then
+ pulsebar.notification_preset = {}
+ pulsebar.notification_preset.font = "Monospace 10"
+ end
+
+ pulsebar.bar = wibox.widget {
+ forced_height = height,
+ forced_width = width,
+ color = pulsebar.colors.unmute,
+ background_color = pulsebar.colors.background,
+ margins = 1,
+ paddings = 1,
+ ticks = ticks,
+ ticks_size = ticks_size,
+ widget = wibox.widget.progressbar,
+ layout = vertical and wibox.container.rotate
+ }
- pulsebar.bar:set_background_color(pulsebar.colors.background)
- pulsebar.bar:set_color(pulsebar.colors.unmute)
pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
- pulsebar.bar:set_width(width)
- pulsebar.bar:set_height(height)
- pulsebar.bar:set_ticks(ticks)
- pulsebar.bar:set_ticks_size(ticks_size)
- pulsebar.bar:set_vertical(vertical)
- function pulsebar.update()
+ function pulsebar.update(callback)
if scallback then pulseaudio.cmd = scallback() end
- local s = read_pipe(pulsebar.cmd)
-
- volume_now = {}
- volume_now.left = tonumber(string.match(s, ":.-(%d+)%%"))
- volume_now.right = tonumber(string.match(s, ":.-(%d+)%%"))
- volume_now.muted = string.match(s, "muted: (%S+)")
-
- local volu = volume_now.left
- local mute = volume_now.muted
-
- if (volu and volu ~= pulsebar._current_level) or (mute and mute ~= pulsebar._muted)
- then
- pulsebar._current_level = volu
- pulsebar.bar:set_value(pulsebar._current_level / 100)
- if not mute and volu == 0 or mute == "yes"
- then
- pulsebar._muted = true
- pulsebar.tooltip:set_text (" [Muted] ")
- pulsebar.bar:set_color(pulsebar.colors.mute)
- else
- pulsebar._muted = false
- pulsebar.tooltip:set_text(string.format(" %s:%s ", pulsebar.sink, volu))
- pulsebar.bar:set_color(pulsebar.colors.unmute)
+
+ helpers.async({ awful.util.shell, "-c", pulsebar.cmd }, function(s)
+ volume_now = {
+ index = string.match(s, "index: (%S+)") or "N/A",
+ sink = string.match(s, "device.string = \"(%S+)\"") or "N/A",
+ muted = string.match(s, "muted: (%S+)") or "N/A"
+ }
+
+ local ch = 1
+ volume_now.channel = {}
+ for v in string.gmatch(s, ":.-(%d+)%%") do
+ volume_now.channel[ch] = v
+ ch = ch + 1
end
- settings()
- end
+
+ volume_now.left = volume_now.channel[1] or "N/A"
+ volume_now.right = volume_now.channel[2] or "N/A"
+
+ local volu = volume_now.left
+ local mute = volume_now.muted
+
+ if (volu and volu ~= pulsebar._current_level) or (mute and mute ~= pulsebar._muted) then
+ pulsebar._current_level = volu
+ pulsebar.bar:set_value(pulsebar._current_level / 100)
+ if (not mute and volu == 0) or mute == "yes" then
+ pulsebar._muted = true
+ pulsebar.tooltip:set_text ("[Muted]")
+ pulsebar.bar.color = pulsebar.colors.mute
+ else
+ pulsebar._muted = false
+ pulsebar.tooltip:set_text(string.format("%s: %s", pulsebar.sink, volu))
+ pulsebar.bar.color = pulsebar.colors.unmute
+ end
+
+ settings()
+
+ if type(callback) == "function" then callback() end
+ end
+ end)
end
- pulsebar.bar:buttons (awful.util.table.join (
- awful.button ({}, 1, function()
- awful.util.spawn(pulsebar.mixer)
- end)
- ))
+ function pulsebar.notify()
+ pulsebar.update(function()
+ local preset = pulsebar.notification_preset
+
+ if pulsebar._muted then
+ preset.title = string.format("Sink %s - Muted", pulsebar.sink)
+ else
+ preset.title = string.format("%s - %s%%", pulsebar.sink, pulsebar._current_level)
+ end
+
+ int = math.modf((pulsebar._current_level / 100) * awful.screen.focused().mywibox.height)
+ preset.text = string.format("[%s%s]", string.rep("|", int),
+ string.rep(" ", awful.screen.focused().mywibox.height - int))
- timer_id = string.format("pulsebar-%s", pulsebar.sink)
+ if pulsebar.followtag then preset.screen = awful.screen.focused() end
+
+ if not pulsebar.notification then
+ pulsebar.notification = naughty.notify {
+ preset = preset,
+ destroy = function() pulsebar.notification = nil end
+ }
+ else
+ naughty.replace_text(pulsebar.notification, preset.title, preset.text)
+ naughty.reset_timeout(pulsebar.notification, preset.timeout)
+ end
+ end)
+ end
- newtimer(timer_id, timeout, pulsebar.update)
+ helpers.newtimer(string.format("pulsebar-%s", pulsebar.sink), timeout, pulsebar.update)
return pulsebar
end