You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.6 KiB
154 lines
5.6 KiB
-- This file is part of Reno desktop.
|
|
--
|
|
-- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
--
|
|
-- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
|
|
-- Pulseaudio per-client volume setting
|
|
local awful = require("awful")
|
|
local gears = require("gears")
|
|
local wibox = require("wibox")
|
|
local awmtk2 = require("awmtk2")
|
|
local fastyaml = require("parsers").fast_split_yaml
|
|
local beautiful = require("beautiful")
|
|
local ask = require("asckey")
|
|
local pactl_data = {}
|
|
|
|
local test_pactl = os.execute("pactl --version")
|
|
local result = test_pactl
|
|
if _VERSION:match("5.1") then
|
|
result = (test_pactl == 0)
|
|
end
|
|
if not result then
|
|
return
|
|
end
|
|
|
|
local function get_icon(percent)
|
|
if percent >= 66 then
|
|
return beautiful["volume-high-symbolic"]
|
|
elseif percent >= 33 then
|
|
return beautiful["volume-medium-symbolic"]
|
|
elseif percent > 0 then
|
|
return beautiful["volume-low-symbolic"]
|
|
else
|
|
return beautiful["volume-muted-symbolic"]
|
|
end
|
|
end
|
|
|
|
|
|
return function(args)
|
|
local style = awmtk2.create_style("client_volume",
|
|
awmtk2.generic.oneline_widget, args.style)
|
|
local templates = awmtk2.create_template_lib("client_volume",awmtk2.templates,args.templates)
|
|
local t = awmtk2.build_templates(templates,style)
|
|
local widget = wibox.widget(t.container({
|
|
t.center({
|
|
id = "client_volume_icon",
|
|
widget = wibox.widget.imagebox
|
|
}),
|
|
t.textbox({
|
|
id = "error"
|
|
}),
|
|
t.slider({
|
|
minimum = 0,
|
|
maximum = 100,
|
|
id = "client_volume",
|
|
value = -1
|
|
}),
|
|
layout = wibox.layout.fixed.horizontal
|
|
}))
|
|
local errorbox = widget:get_children_by_id("error")[1]
|
|
local icon = widget:get_children_by_id("client_volume_icon")[1]
|
|
local slider = widget:get_children_by_id("client_volume")[1]
|
|
-- Local tracking value to prevent zero volume on start
|
|
local slider_touched = false
|
|
-- Get initial pactl data
|
|
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
|
|
local pactl_data = fastyaml(stdout)
|
|
end)
|
|
-- Attach to focus change
|
|
client.connect_signal("update_volume",function(c)
|
|
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
|
|
local pactl_data = fastyaml(stdout)
|
|
local cl
|
|
for k,v in pairs(pactl_data) do
|
|
if not c then return end
|
|
if v:match("application.process.id = \""..tostring(c.pid).."\"") then
|
|
cl = v
|
|
end
|
|
end
|
|
if not cl then
|
|
slider.visible = false
|
|
errorbox.visible = true
|
|
errorbox:set_markup("No sound/Not available")
|
|
icon:set_image(beautiful["volume-muted-symbolic"])
|
|
return
|
|
end
|
|
local volume = tonumber(cl:match("Volume:[^\n]-(%d*)%%"))
|
|
slider.visible = true
|
|
errorbox.visible = false
|
|
icon:set_image(get_icon(volume))
|
|
slider.value = volume
|
|
touched = true
|
|
end)
|
|
end)
|
|
client.connect_signal("focus",function(c)
|
|
touched = false
|
|
c:emit_signal("update_volume")
|
|
end)
|
|
local update_timer = gears.timer({
|
|
timeout = 0.5,
|
|
autostart = true,
|
|
callback = function()
|
|
if client.focus then
|
|
client.focus:emit_signal("update_volume")
|
|
end
|
|
end
|
|
})
|
|
-- Async lock to prevent callback interference
|
|
local volume_lock = false
|
|
-- Function to set client volume
|
|
local function volume(volume)
|
|
if volume_lock then return end
|
|
volume_lock = true
|
|
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
|
|
local pactl_data = fastyaml(stdout)
|
|
local cl = {}
|
|
if not (client.focus and client.focus.pid) then
|
|
volume_lock = false
|
|
return
|
|
end
|
|
for k,v in pairs(pactl_data) do
|
|
if v:match("application.process.id = \""..tostring(client.focus.pid).."\"") then
|
|
local sink_id = v:match("^%s*Sink Input #(%d+)")
|
|
if sink_id then
|
|
print(sink_id, volume)
|
|
awful.spawn("pactl set-sink-input-volume "..tostring(sink_id).." "..tostring(volume).."%")
|
|
end
|
|
end
|
|
end
|
|
volume_lock = false
|
|
end)
|
|
end
|
|
-- Attach change to slider
|
|
slider:connect_signal("widget::redraw_needed",function(widget)
|
|
if touched then
|
|
volume(slider.value)
|
|
update_timer:again()
|
|
end
|
|
end)
|
|
root.keys(gears.table.join(
|
|
root.keys(),
|
|
ask.k(":client.volume_up", function()
|
|
volume("+5")
|
|
end,{description = "increase client volume", group = "client"}),
|
|
ask.k(":client.volume_down", function()
|
|
volume("-5")
|
|
end,{description = "decrease client volume", group = "client"}),
|
|
ask.k(":client.volume_mute", function()
|
|
volume(0)
|
|
end,{description = "mute client", group = "client"})
|
|
))
|
|
return widget
|
|
end
|