Fixed volume control on per-application basis

This commit is contained in:
Yessiest 2022-04-03 14:45:52 +04:00
parent 9d468be547
commit 022a6a116f
5 changed files with 96 additions and 196 deletions

View File

@ -49,53 +49,92 @@ awful.screen.connect_for_each_screen(function(s)
s.mytasklist = require("core.widgets.tasklist")(s) s.mytasklist = require("core.widgets.tasklist")(s)
-- Create the wibox -- Create the wibox
s.mywibox = awful.wibar({ s.mywibox = awful.wibar({
position = "bottom", position = "top",
screen = s, screen = s,
bg = beautiful.topbar_bg, bg = beautiful.topbar_bg,
border_width = 1,
border_color = beautiful.bg_normal
}) })
-- Add screen lock -- Add screen lock
require("widgets.lock")({screen = s, obscure = true}) require("widgets.lock")({screen = s, obscure = true})
require("widgets.unitybar")(s,{
top_widgets = {
require("widgets.polytasklist")({
vertical = true,
stretch = false,
--constraint = 180,
names = false,
margins = 5
})(s),
},
bottom_widgets = {
require("widgets.polylauncher")({vertical = true})
}
})
-- Add widgets to the wibox -- Add widgets to the wibox
s.mywibox:setup { s.mywibox:setup {
layout = wibox.layout.align.horizontal, layout = wibox.layout.align.horizontal,
{ -- Left widgets { -- Left widgets
layout = wibox.layout.fixed.horizontal, layout = wibox.layout.fixed.horizontal,
{
{
require("core.widgets.menu_launcher"), require("core.widgets.menu_launcher"),
require("widgets.polylauncher")({vertical = false}), widget = wibox.container.place,
halign = "center"
},
bg = "#26262633",
widget = wibox.container.background,
forced_width = require("beautiful.xresources").apply_dpi(61),
},
--require("widgets.polylauncher")({vertical = false}),
--s.mytaglist,
s.mypromptbox, s.mypromptbox,
spacing = 3 spacing = 3
}, },
-- Middle widget -- Middle widget
{ {
require("widgets.polytasklist")({ --[[require("widgets.polytasklist")({
vertical = false,
stretch = false,
constraint = 180, constraint = 180,
names = true, names = true,
margins = 5 margins = 5
})(s), })(s),]]
layout = wibox.layout.fixed.horizontal layout = wibox.layout.fixed.horizontal
}, },
{ -- Right widgets { -- Right widgets
layout = wibox.layout.fixed.horizontal, layout = wibox.layout.fixed.horizontal,
awful.widget.keyboardlayout(), awful.widget.keyboardlayout(),
require("widgets.drawer")({
wibox.widget.systray(),
vertical = false
}),
require("widgets.wallpapers")({ require("widgets.wallpapers")({
screen = s, screen = s,
path = os.getenv("HOME").."/Pictures/Wallpapers/", path = os.getenv("HOME").."/Pictures/Wallpapers/",
style = {
icon_bg_normal = beautiful.topbar_bg
}
}), }),
require("widgets.mailbox")({ require("widgets.mailbox")({
screen = s, screen = s,
style = {
rounding = 1,
icon_bg_normal = beautiful.topbar_bg
}
}), }),
--wibox.widget.systray(), --wibox.widget.systray(),
require("widgets.volume")({}), require("widgets.volume")({
style = {
icon_bg_normal = beautiful.topbar_bg
}
}),
require("widgets.battery")({ require("widgets.battery")({
percentage = true, percentage = true,
style = {
icon_bg_normal = beautiful.topbar_bg
}
}), }),
wibox.widget.textclock(), wibox.widget.textclock(),
require("widgets.username")({
style = {
icon_bg_normal = beautiful.topbar_bg
}
}),
s.mylayoutbox, s.mylayoutbox,
spacing = 4 spacing = 4
}, },

View File

@ -43,47 +43,6 @@ awful.screen.connect_for_each_screen(function(s)
toggle_tags toggle_tags
}) })
end) end)
local controls_widget = wibox.widget {
forced_width = 72,
forced_height = 24,
layout = wibox.layout.fixed.horizontal,
}
-- To conserve memory we keep one menu at a time
local menu_widget = menu({
before = {
controls_widget
},
after = {
require("widgets.client-volume")({})
},
items = {
{ "Move to tag" ,
move_screentags
},
{ "Toggle on tag",
toggle_screentags
},
{ "Stop task",
function()
awful.spawn("kill "..tostring(c.pid))
end
},
{ "Kill task",
function()
awful.spawn("kill -s KILL "..tostring(c.pid))
end
},
{ "Debug info",
{
before = {
require("widgets.window-debug")()
}
}
}
},
vertical = true
})
return function(c) return function(c)
local buttons = gears.table.join( local buttons = gears.table.join(
awful.button({ }, 1, function() awful.button({ }, 1, function()
@ -95,26 +54,35 @@ return function(c)
awful.mouse.client.resize(c) awful.mouse.client.resize(c)
end) end)
) )
c.menu = menu({
before = {
{
awful.titlebar.widget.floatingbutton (c),
awful.titlebar.widget.stickybutton (c),
awful.titlebar.widget.ontopbutton (c),
forced_width = 72,
forced_height = 24,
layout = wibox.layout.fixed.horizontal,
}
},
items = {
{ "Move to tag" ,
move_screentags
},
{ "Toggle on tag",
toggle_screentags
}
},
vertical = true
})
c.menu_button = awful.titlebar.widget.iconwidget(c) c.menu_button = awful.titlebar.widget.iconwidget(c)
-- A little trick we do to conserve memory and cpu usage on regenerating
-- buttons is we pop up a menu in the location of the icon
-- and insert buttons into the controls widget layout.
c.hidden_floatingbutton = awful.titlebar.widget.floatingbutton(c)
c.hidden_stickybutton = awful.titlebar.widget.stickybutton(c)
c.hidden_ontopbutton = awful.titlebar.widget.ontopbutton(c)
c.menu_button:connect_signal("button::press", function() c.menu_button:connect_signal("button::press", function()
menu_widget.toggle() c.menu.toggle()
if controls_widget then
controls_widget:reset()
controls_widget:add(c.hidden_floatingbutton)
controls_widget:add(c.hidden_stickybutton)
controls_widget:add(c.hidden_ontopbutton)
end
c:emit_signal("request::activate", "titlebar", {raise = true}) c:emit_signal("request::activate", "titlebar", {raise = true})
end) end)
c:connect_signal("unfocus",function() c:connect_signal("unfocus",function()
if menu_widget.visible then if c.menu.visible then
menu_widget.toggle(0,0) c.menu.toggle(0,0)
end end
end) end)
return awful.titlebar(c) : setup { return awful.titlebar(c) : setup {

View File

@ -5,7 +5,7 @@ global = {}
global.awesome_dir = os.getenv("HOME").."/.config/awesome/" global.awesome_dir = os.getenv("HOME").."/.config/awesome/"
global.config_dir = os.getenv("HOME").."/.awesome/" global.config_dir = os.getenv("HOME").."/.awesome/"
global.themes_dir = os.getenv("HOME").."/.config/awesome/themes/" global.themes_dir = os.getenv("HOME").."/.config/awesome/themes/"
global.theme = global.awesome_dir .. "themes/carbon/theme.lua" global.theme = global.awesome_dir .. "themes/unity/theme.lua"
global.terminal = "xterm" global.terminal = "xterm"
global.editor = os.getenv("EDITOR") or "vim" global.editor = os.getenv("EDITOR") or "vim"
global.editor_cmd = global.terminal .. " -e ".. global.editor global.editor_cmd = global.terminal .. " -e ".. global.editor

View File

@ -3,38 +3,38 @@ local gears = require("gears")
local wibox = require("wibox") local wibox = require("wibox")
local awmtk = require("awmtk") local awmtk = require("awmtk")
local get_app_volume = function(pid) local get_pactl_data = function()
-- Read pactl data -- Get pactl process data and convert it into a list
local pactl_process = io.popen("pactl list sink-inputs","r") local pactl_processes = {}
local pactl_process = io.popen("pactl list sink-inputs", "r")
local pactl_data = pactl_process:read("*a") local pactl_data = pactl_process:read("*a")
pactl_process:close() pactl_process:close()
-- Try to find a matching process
while pactl_data:match("^(%w.-\n)%w") do while pactl_data:match("^(%w.-\n)%w") do
local test = pactl_data:match("^(%w.-\n)%w") local test = pactl_data:match("^(%w.-\n)%w")
-- Return volume table.insert(pactl_processes,test)
if test:match("application.process.id = \""..tostring(pid).."\"") then
return test:match("Volume: .-(%d?%d?%d)%%")
end
pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1") pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1")
end end
table.insert(pactl_processes,pactl_data)
return pactl_processes
end
local get_app_volume = function(pid)
for key,process in pairs(get_pactl_data()) do
-- Match app by pid
if process:match("application.process.id = \""..tostring(pid).."\"") then
return process:match("Volume: .-(%d?%d?%d)%%")
end
end
-- Return nil and an error if not found matching process -- Return nil and an error if not found matching process
return nil, "Process doesn't play audio" return nil, "Process doesn't play audio"
end end
local set_app_volume = function(pid,percentage) local set_app_volume = function(pid,percentage)
-- Read pactl data for key,process in pairs(get_pactl_data()) do
local pactl_process = io.popen("pactl list sink-inputs","r") if process:match("application.process.id = \""..tostring(pid).."\"") then
local pactl_data = pactl_process:read("*a") local sink_input_id = process:match("Sink Input #(%d*)")
pactl_process:close()
-- Try to find a matching process
while pactl_data:match("^(%w.-\n)%w") do
local test = pactl_data:match("^(%w.-\n)%w")
-- If the application matches, get stream ID and set its volume
if test:match("application.process.id = \""..tostring(pid).."\"") then
local sink_input_id = test:match("Sink Input #(%d*)")
os.execute("pactl set-sink-input-volume "..sink_input_id.." "..tostring(percentage).."%") os.execute("pactl set-sink-input-volume "..sink_input_id.." "..tostring(percentage).."%")
end end
pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1")
end end
end end
@ -102,6 +102,7 @@ return function(args)
end) end)
slider:connect_signal("widget::redraw_needed",function() slider:connect_signal("widget::redraw_needed",function()
set_app_volume(client.focus.pid,slider.value) set_app_volume(client.focus.pid,slider.value)
widget.children[1].image = get_icon(tonumber(slider.value))
end) end)
else else
warning_text.markup = "pactl is not available" warning_text.markup = "pactl is not available"

View File

@ -1,108 +0,0 @@
local awful = require("awful")
local beautiful = require("beautiful")
local gears = require("gears")
local spawn = require("awful.spawn")
local wibox = require("wibox")
local awmtk = require("awmtk")
local thumbnailer = require("thumbnail")
local widget = {}
local function ls(path)
local ls_data = io.popen("ls -1 "..path)
local output = {}
if ls_data then
ls_data:read("*a"):gsub("[^\n]+",function(capt) table.insert(output,capt) end)
ls_data:close()
else
error("ls "..path.." failed.")
end
return output
end
local function worker(args)
local args = args or {}
assert(type(args["screen"]) ~= "nil","Screen not specified")
assert(type(args["path"]) ~= "nil","Path to wallpapers folder not specified")
--add an extra slash to path if there is none
if not args["path"]:match("/$") then
args["path"] = args["path"].."/"
end
--create local style
local style = awmtk.style(awmtk.defaults,args.style or {},"wallpapers_")
--set wallpaper
local handler = io.open(global.config_dir.."/.wallpaper","r")
if handler then
local wallpaper_path = handler:read("*a")
gears.wallpaper.maximized(wallpaper_path,args["screen"])
end
local function update_last_wallpaper(s)
local handler = io.open(global.config_dir.."/.wallpaper","w")
handler:write(s)
handler:close()
end
--read wallpapers from the wallpaper directory
local image_list = ls(args["path"])
for k,v in pairs(image_list) do
if not (v:match("%.jpg$") or v:match("%.png$")) then
image_list[k] = nil
end
end
--generate thumbnails to save up memory
thumbnailer.generate(args["path"],args["path"]..".thumbnails",60)
--style variables
local button_bg = style.wallpapers_button_bg_focus
local function new_wallpaper_button(image,s)
local new_widget = style.button({
image = args["path"]..".thumbnails/"..image,
resize = true,
widget = wibox.widget.imagebox
},{
bg = button_bg,
forced_height = style.wallpapers_button_height or 60,
forced_width = style.wallpapers_button_width or 100
},{
function()
gears.wallpaper.maximized(args["path"]..image,s)
update_last_wallpaper(args["path"]..image)
end
})
return new_widget
end
local copy_list = {
widget = wibox.layout.grid,
forced_num_cols = args.columns or 4,
homogeneous = true,
expand = true,
orientation = "vertical",
spacing = 5
}
for k,v in pairs(image_list) do
local new_widget = new_wallpaper_button(v,args["screen"])
table.insert(copy_list,new_widget)
end
local popup = awful.popup(style.container(
copy_list,
{
visible = false,
ontop = true
}
))
local clip_widget = style.icon({
image = style["wallpapers_icon"],
resize = true,
widget = wibox.widget.imagebox
},{},{
function()
if popup.visible then
--rows = nil
popup.visible = not popup.visible
else
--init_popup()
popup:move_next_to(mouse.current_widget_geometry)
end
end
})
widget = clip_widget
return clip_widget
end
return setmetatable(widget, { __call = function(_, ...) return worker(...) end })