From e6e79af05202cfa518c32844027e792a1723d60d Mon Sep 17 00:00:00 2001 From: Yessiest Date: Tue, 22 Mar 2022 23:33:06 +0400 Subject: [PATCH] Added the volume bars to window context menu --- core/titlebar.lua | 3 + themes/carbon/icons/warning.svg | 116 ++++++++++++---------- themes/icons.lua | 1 + widgets/client-volume.lua | 169 +++++++++++++++----------------- 4 files changed, 148 insertions(+), 141 deletions(-) diff --git a/core/titlebar.lua b/core/titlebar.lua index ed185f2..45662df 100644 --- a/core/titlebar.lua +++ b/core/titlebar.lua @@ -53,6 +53,9 @@ local menu_widget = menu({ before = { controls_widget }, + after = { + require("widgets.client-volume")({}) + }, items = { { "Move to tag" , move_screentags diff --git a/themes/carbon/icons/warning.svg b/themes/carbon/icons/warning.svg index 85ed7e4..3db37e7 100644 --- a/themes/carbon/icons/warning.svg +++ b/themes/carbon/icons/warning.svg @@ -6,7 +6,7 @@ height="48" viewBox="0 0 12.7 12.7" version="1.1" - id="svg5" + id="svg837" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" sodipodi:docname="warning.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" @@ -14,7 +14,7 @@ xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> + id="grid902" /> + id="defs834"> + - + id="mask-powermask-path-effect1796"> + + + + + + - ! + d="M -0.70621928,-0.70618839 H 13.406219 V 13.40625 H -0.70621928 Z" /> + + + + @@ -98,23 +125,12 @@ inkscape:groupmode="layer" id="layer1"> + id="rect1016" + 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" + d="M 0.79374983,11.90625 6.3499999,0.79374983 11.90625,11.90625 Z" + sodipodi:nodetypes="cccc" + mask="url(#mask-powermask-path-effect2659)" + inkscape:path-effect="#path-effect2659" + inkscape:original-d="M 0.79374983,11.90625 6.3499999,0.79374983 11.90625,11.90625 Z" /> diff --git a/themes/icons.lua b/themes/icons.lua index be002a3..f53c1a7 100644 --- a/themes/icons.lua +++ b/themes/icons.lua @@ -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_closed_icon = gears.color.recolor_image(beautiful.icon_dir.."drawer-closed.svg",beautiful.fg_normal) -- Generic icons +print(beautiful.icon_dir.."warning.svg") beautiful.warning_icon = gears.color.recolor_image(beautiful.icon_dir.."warning.svg",beautiful.fg_normal) diff --git a/widgets/client-volume.lua b/widgets/client-volume.lua index 94c6b0c..23b655a 100644 --- a/widgets/client-volume.lua +++ b/widgets/client-volume.lua @@ -4,22 +4,37 @@ local wibox = require("wibox") local awmtk = require("awmtk") local get_app_volume = function(pid) - -- If pactl is accessible - if os.execute("pactl --version") then - -- Generate pactl sink-inputs data - local pactl_process = io.popen("pactl list sink-inputs","r") - local pactl_data = pactl_process:read("*a") - pactl_process:close() - while pactl_data:match("^(%w.-\n)%w") do - local test = pactl_data:match("^(%w.-\n)%w") - 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") + -- 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") + -- Return volume + if test:match("application.process.id = \""..tostring(pid).."\"") then + return test:match("Volume: .-(%d?%d?%d)%%") end - return nil, "Process doesn't play audio" - else - return nil, "pactl command is not available" + pactl_data = pactl_data:gsub("^%w.-\n(%w)","%1") + end + -- 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 @@ -27,11 +42,11 @@ return function(args) local style = awmtk.style(awmtk.defaults, args.style or {},"client_volume_") local device = args.device or "default" local icons = args.icons or { - high = style.client_volume_icon_high, - medium = style.client_volume_icon_medium, - low = style.client_volume_icon_low, - muted = style.client_volume_icon_muted, - warn = style.client_volume_warning_icon + high = style.volume_icon_high, + medium = style.volume_icon_medium, + low = style.volume_icon_low, + muted = style.volume_icon_muted, + warn = style.warning_icon } local function get_icon(percent) if percent >= 66 then @@ -44,82 +59,54 @@ return function(args) return icons.muted 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 } - for k,v in pairs(controls) do - local widget = wibox.widget({ - { - widget = wibox.widget.textbox, - markup = v, - ellipsize = "end", - font = style.volume_font - }, - { - { - widget = wibox.widget.slider, - 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 + if os.execute("pactl --version") then + client.connect_signal("focus",function(c) + local value,err = get_app_volume(c.pid) + if value then + slider.value = value + widget.children[2] = slider + widget.children[1].image = get_icon(tonumber(value)) + else + warning_text.markup = err + widget.children[2] = warning_text + widget.children[1].image = icons.warn end - slider.value = volume_percent end) slider:connect_signal("widget::redraw_needed",function() - awful.spawn(commands.set..v.." "..slider.value.."%") + set_app_volume(client.focus.pid,slider.value) 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 - local tweaker_popup = awful.popup(style.container(list,{ - 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 + return widget end