Yessiest
2 years ago
17 changed files with 601 additions and 32 deletions
-
5README.md
-
11desktop.conf
-
6libs/asckey.lua
-
16libs/awmtk2.lua
-
169libs/parser_test.lua
-
53libs/parsers.lua
-
3libs/syscontrol.lua
-
19modules/binds.lua
-
8modules/desktop.lua
-
10modules/global.lua
-
63modules/powermanX.lua
-
1rc.lua
-
1themes/unity/config/client_menu.json
-
19themes/unity/theme.lua
-
63widgets/battery.lua
-
154widgets/clientvolume.lua
-
32widgets/soundclown.lua
@ -0,0 +1,63 @@ |
|||||
|
-- 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/>. |
||||
|
-- Powerman X - second generation of the power management daemon |
||||
|
local sysctl = require("syscontrol") |
||||
|
local naughty = require("naughty") |
||||
|
local gears = require("gears") |
||||
|
local awful = require("awful") |
||||
|
local batteries = sysctl.power_supply.enumerate() |
||||
|
local state_tracking = {} |
||||
|
-- Configuration variables |
||||
|
local cfg = config.powerman or {} |
||||
|
local quality_min = cfg.battery_quality_min or 33 |
||||
|
local capacity_min = cfg.battery_capacity_min or 15 |
||||
|
-- Main loop |
||||
|
local update_loop = gears.timer({ |
||||
|
timeout = 2, |
||||
|
autostart = true, |
||||
|
callback = function() |
||||
|
for k,v in pairs(batteries) do |
||||
|
local data,err = sysctl.power_supply.read_attribs(v) |
||||
|
state_tracking[v] = state_tracking[v] or {} |
||||
|
if data.type == "Battery" then |
||||
|
if (tonumber(data.quality) < quality_min) and |
||||
|
(not state_tracking[v].quality_notification) then |
||||
|
naughty.notify({ |
||||
|
title = "Critical battery condition", |
||||
|
text = "Battery "..data.name.." has reached critically low condition, seek a suitable replacement" |
||||
|
}) |
||||
|
state_tracking[v].quality_notification = true |
||||
|
end |
||||
|
if (tonumber(data.capacity) <= capacity_min) and |
||||
|
(not data.charging) and |
||||
|
(not state_tracking[v].capacity_notification) then |
||||
|
naughty.notify({ |
||||
|
title = "Battery capacity low", |
||||
|
text = "Battery "..data.name.." capacity is at "..tostring(data.capacity).."%" |
||||
|
}) |
||||
|
state_tracking[v].capacity_notification = true |
||||
|
end |
||||
|
if (tonumber(data.capacity) > capacity_min) then |
||||
|
state_tracking[v].capacity_notification = false |
||||
|
end |
||||
|
if (data.capacity == "100") and |
||||
|
(data.charging) and |
||||
|
(not state_tracking[v].charged_notification) then |
||||
|
naughty.notify({ |
||||
|
title = "Battery is completely charged", |
||||
|
text = "Disconnect the charger from the power grid to avoid passive electricity usage." |
||||
|
}) |
||||
|
end |
||||
|
if (not data.charging) then |
||||
|
state_tracking[v].charged_notification = false |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
end |
||||
|
}) |
||||
|
|
@ -0,0 +1,154 @@ |
|||||
|
-- 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 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue