Added the volume bars to window context menu

This commit is contained in:
Yessiest 2022-03-22 23:33:06 +04:00
parent 19f95b77c8
commit e6e79af052
4 changed files with 148 additions and 141 deletions

View File

@ -53,6 +53,9 @@ local menu_widget = menu({
before = { before = {
controls_widget controls_widget
}, },
after = {
require("widgets.client-volume")({})
},
items = { items = {
{ "Move to tag" , { "Move to tag" ,
move_screentags move_screentags

View File

@ -6,7 +6,7 @@
height="48" height="48"
viewBox="0 0 12.7 12.7" viewBox="0 0 12.7 12.7"
version="1.1" version="1.1"
id="svg5" id="svg837"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="warning.svg" sodipodi:docname="warning.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -14,7 +14,7 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"> xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview <sodipodi:namedview
id="namedview7" id="namedview839"
pagecolor="#ffffff" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
borderopacity="1.0" borderopacity="1.0"
@ -25,8 +25,8 @@
showgrid="true" showgrid="true"
units="px" units="px"
inkscape:zoom="12.429181" inkscape:zoom="12.429181"
inkscape:cx="32.021419" inkscape:cx="22.205807"
inkscape:cy="23.171278" inkscape:cy="27.113613"
inkscape:window-width="1866" inkscape:window-width="1866"
inkscape:window-height="1038" inkscape:window-height="1038"
inkscape:window-x="52" inkscape:window-x="52"
@ -35,60 +35,87 @@
inkscape:current-layer="layer1"> inkscape:current-layer="layer1">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid1562" /> id="grid902" />
</sodipodi:namedview> </sodipodi:namedview>
<defs <defs
id="defs2"> id="defs834">
<inkscape:path-effect <inkscape:path-effect
effect="powermask" effect="powermask"
id="path-effect28575" id="path-effect2659"
is_visible="true" is_visible="true"
lpeversion="1" lpeversion="1"
uri="#mask-powermask-path-effect28575" uri="#mask-powermask-path-effect2659"
invert="false"
hide_mask="false"
background="true"
background_color="#ffffffff" />
<inkscape:path-effect
effect="powermask"
id="path-effect1796"
is_visible="true"
lpeversion="1"
uri="#mask-powermask-path-effect1796"
invert="false" invert="false"
hide_mask="false" hide_mask="false"
background="true" background="true"
background_color="#ffffffff" /> background_color="#ffffffff" />
<rect
x="20"
y="23"
width="28"
height="29"
id="rect5107" />
<mask <mask
maskUnits="userSpaceOnUse" maskUnits="userSpaceOnUse"
id="mask-powermask-path-effect28575"> id="mask-powermask-path-effect1796">
<g
id="g1794"
transform="matrix(3.1496063,0,0,3.1496063,2.9999997,6.2500913)"
style="">
<path
style="fill:none;stroke:#000000;stroke-width:0.972208;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 6.35,3.175 V 8.4666665"
id="path1790" />
<circle
style="opacity:1;fill:#000000;stroke:none;stroke-width:1.065;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="circle1792"
cx="6.3499999"
cy="10.054167"
r="0.52916664" />
</g>
</mask>
<mask
maskUnits="userSpaceOnUse"
id="mask-powermask-path-effect2659">
<path <path
id="mask-powermask-path-effect28575_box" id="mask-powermask-path-effect2659_box"
style="fill:#ffffff;fill-opacity:1" style="fill:#ffffff;fill-opacity:1"
d="M 1.1424707,-3.0728638 H 48.857529 V 39.073072 H 1.1424707 Z" /> d="M -0.70621928,-0.70618839 H 13.406219 V 13.40625 H -0.70621928 Z" />
<text <g
xml:space="preserve" id="g2657"
style="font-size:42.6667px;line-height:1.25;font-family:sans-serif;stroke-width:0.999999" style="">
x="19.083326" <path
y="32.677097" style="fill:none;stroke:#000000;stroke-width:0.934071;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="text28573"><tspan d="M 6.3499999,3.175 V 8.4666667"
sodipodi:role="line" id="path2653" />
id="tspan28571" <circle
style="font-size:42.6667px;stroke-width:0.999999" style="opacity:1;fill:#000000;stroke:none;stroke-width:1.065;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
x="19.083326" id="circle2655"
y="32.677097">!</tspan></text> cx="6.3499999"
cy="10.163688"
r="0.52916664"
d="M 6.8791665,10.163688 A 0.52916664,0.52916664 0 0 1 6.3499999,10.692854 0.52916664,0.52916664 0 0 1 5.8208333,10.163688 0.52916664,0.52916664 0 0 1 6.3499999,9.6345211 0.52916664,0.52916664 0 0 1 6.8791665,10.163688 Z" />
</g>
</mask> </mask>
<filter <filter
id="mask-powermask-path-effect28575_inverse" id="mask-powermask-path-effect2659_inverse"
inkscape:label="filtermask-powermask-path-effect28575" inkscape:label="filtermask-powermask-path-effect2659"
style="color-interpolation-filters:sRGB" style="color-interpolation-filters:sRGB"
height="100" height="100"
width="100" width="100"
x="-50" x="-50"
y="-50"> y="-50">
<feColorMatrix <feColorMatrix
id="mask-powermask-path-effect28575_primitive1" id="mask-powermask-path-effect2659_primitive1"
values="1" values="1"
type="saturate" type="saturate"
result="fbSourceGraphic" /> result="fbSourceGraphic" />
<feColorMatrix <feColorMatrix
id="mask-powermask-path-effect28575_primitive2" id="mask-powermask-path-effect2659_primitive2"
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 " values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0 "
in="fbSourceGraphic" /> in="fbSourceGraphic" />
</filter> </filter>
@ -98,23 +125,12 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1"> id="layer1">
<path <path
sodipodi:type="star" id="rect1016"
style="fill:#000000;stroke-width:4.14614178;stroke-linecap:round;stroke:#000000;stroke-opacity:1;stroke-miterlimit:4.0999999;stroke-dasharray:none;paint-order:stroke fill markers;stroke-linejoin:round" style="stroke-width:1;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke fill markers;stroke:#000000;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;opacity:1"
id="path1855" d="M 0.79374983,11.90625 6.3499999,0.79374983 11.90625,11.90625 Z"
inkscape:flatsided="true" sodipodi:nodetypes="cccc"
sodipodi:sides="3" mask="url(#mask-powermask-path-effect2659)"
sodipodi:cx="25" inkscape:path-effect="#path-effect2659"
sodipodi:cy="24" inkscape:original-d="M 0.79374983,11.90625 6.3499999,0.79374983 11.90625,11.90625 Z" />
sodipodi:r1="24"
sodipodi:r2="12"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359878"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 25.000001,0 20.784608,36.000001 -41.569219,-2e-6 z"
transform="matrix(0.26458333,0,0,0.26458333,-0.26458316,1.5875)"
inkscape:transform-center-y="-1.5875001"
mask="url(#mask-powermask-path-effect28575)"
inkscape:path-effect="#path-effect28575" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -50,5 +50,6 @@ beautiful.username_logout_icon = gears.color.recolor_image(beautiful.icon_dir.."
beautiful.drawer_open_icon = gears.color.recolor_image(beautiful.icon_dir.."drawer-open.svg",beautiful.fg_normal) beautiful.drawer_open_icon = gears.color.recolor_image(beautiful.icon_dir.."drawer-open.svg",beautiful.fg_normal)
beautiful.drawer_closed_icon = gears.color.recolor_image(beautiful.icon_dir.."drawer-closed.svg",beautiful.fg_normal) beautiful.drawer_closed_icon = gears.color.recolor_image(beautiful.icon_dir.."drawer-closed.svg",beautiful.fg_normal)
-- Generic icons -- Generic icons
print(beautiful.icon_dir.."warning.svg")
beautiful.warning_icon = gears.color.recolor_image(beautiful.icon_dir.."warning.svg",beautiful.fg_normal) beautiful.warning_icon = gears.color.recolor_image(beautiful.icon_dir.."warning.svg",beautiful.fg_normal)

View File

@ -4,22 +4,37 @@ local wibox = require("wibox")
local awmtk = require("awmtk") local awmtk = require("awmtk")
local get_app_volume = function(pid) local get_app_volume = function(pid)
-- If pactl is accessible -- Read pactl data
if os.execute("pactl --version") then local pactl_process = io.popen("pactl list sink-inputs","r")
-- Generate pactl sink-inputs data local pactl_data = pactl_process:read("*a")
local pactl_process = io.popen("pactl list sink-inputs","r") pactl_process:close()
local pactl_data = pactl_process:read("*a") -- Try to find a matching process
pactl_process:close() 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
if test:match("application.process.id = \""..tostring(pid).."\"") then if test:match("application.process.id = \""..tostring(pid).."\"") then
return test:match("Volume: .-(%d?%d?%d%%)") return test:match("Volume: .-(%d?%d?%d)%%")
end
pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1")
end end
return nil, "Process doesn't play audio" pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1")
else end
return nil, "pactl command is not available" -- Return nil and an error if not found matching process
return nil, "Process doesn't play audio"
end
local set_app_volume = function(pid,percentage)
-- Read pactl data
local pactl_process = io.popen("pactl list sink-inputs","r")
local pactl_data = pactl_process:read("*a")
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).."%")
end
pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1")
end end
end end
@ -27,11 +42,11 @@ return function(args)
local style = awmtk.style(awmtk.defaults, args.style or {},"client_volume_") local style = awmtk.style(awmtk.defaults, args.style or {},"client_volume_")
local device = args.device or "default" local device = args.device or "default"
local icons = args.icons or { local icons = args.icons or {
high = style.client_volume_icon_high, high = style.volume_icon_high,
medium = style.client_volume_icon_medium, medium = style.volume_icon_medium,
low = style.client_volume_icon_low, low = style.volume_icon_low,
muted = style.client_volume_icon_muted, muted = style.volume_icon_muted,
warn = style.client_volume_warning_icon warn = style.warning_icon
} }
local function get_icon(percent) local function get_icon(percent)
if percent >= 66 then if percent >= 66 then
@ -44,82 +59,54 @@ return function(args)
return icons.muted return icons.muted
end end
end end
local list = { local slider = wibox.widget {
widget = wibox.widget.slider,
id = "widget_slider",
handle_width = style.client_volume_handle_width or 6,
bar_height = style.client_volumer_bar_width or 5,
bar_color = style.client_volume_bar_color or "#55CC60",
bar_shape = style.bar_shape,
handler_shape = style.handle_shape,
forced_height = 20,
forced_width = 100,
value = 100,
}
local warning_text = wibox.widget {
markup = "An unknown error has occured",
widget = wibox.widget.textbox
}
local widget = wibox.widget {
{
image = icons.warn,
resize = true,
widget = wibox.widget.imagebox,
forced_height = 20,
forced_width = 20
},
warning_text,
spacing = style.client_volume_container_spacing_horizontal,
layout = wibox.layout.fixed.horizontal layout = wibox.layout.fixed.horizontal
} }
for k,v in pairs(controls) do if os.execute("pactl --version") then
local widget = wibox.widget({ client.connect_signal("focus",function(c)
{ local value,err = get_app_volume(c.pid)
widget = wibox.widget.textbox, if value then
markup = v, slider.value = value
ellipsize = "end", widget.children[2] = slider
font = style.volume_font widget.children[1].image = get_icon(tonumber(value))
}, else
{ warning_text.markup = err
{ widget.children[2] = warning_text
widget = wibox.widget.slider, widget.children[1].image = icons.warn
id = "widget_slider",
handle_width = style.volume_handle_width or 6,
bar_height = style.volumer_bar_width or 5,
bar_color = style.volume_bar_color or "#55CC60",
bar_shape = style.bar_shape,
handler_shape = style.handle_shape,
value = 100,
},
widget = wibox.container.rotate,
direction = "east"
},
layout = wibox.layout.fixed.vertical,
spacing = style.volume_container_spacing_horizontal,
forced_width = style.volume_slider_width or 40,
forced_height = style.volume_slider_height or 120
})
local slider = widget:get_children_by_id("widget_slider")[1]
awful.spawn.easy_async_with_shell(commands.get..v,function(out)
local volume_percent = out:match("%[(%d+)%%%]") or ""
volume_percent = tonumber(volume_percent)
if not volume_percent then
return
end end
slider.value = volume_percent
end) end)
slider:connect_signal("widget::redraw_needed",function() slider:connect_signal("widget::redraw_needed",function()
awful.spawn(commands.set..v.." "..slider.value.."%") set_app_volume(client.focus.pid,slider.value)
end) end)
table.insert(list,widget) else
warning_text.markup = "pactl is not available"
widget.children[2] = warning_text
widget.children[1].image = icons.warn
end end
local tweaker_popup = awful.popup(style.container(list,{ return widget
visible = false,
ontop = true
}))
local icon = style.icon({
widget = wibox.widget.imagebox,
image = icons.muted,
id = "widget_icon"
},{},{
function()
if mouse.current_widget_geometry and (not tweaker_popup.visible) then
tweaker_popup:move_next_to(mouse.current_widget_geometry)
tweaker_popup.visible = true
else
tweaker_popup.visible = false
end
end
})
gears.timer {
autostart = true,
timeout = 0.5,
call_now = true,
callback = function()
awful.spawn.easy_async_with_shell(commands.get_master, function(out)
local volume_percent = out:match("%[(%d+)%%%]") or ""
volume_percent = tonumber(volume_percent)
if not volume_percent then
return
end
icon:get_children_by_id("widget_icon")[1].image = get_icon(volume_percent)
end)
end
}
return icon
end end