Browse Source

big update

master
Yessiest 3 months ago
parent
commit
7d60e5625f
  1. 5
      README.md
  2. 11
      desktop.conf
  3. 6
      libs/asckey.lua
  4. 16
      libs/awmtk2.lua
  5. 169
      libs/parser_test.lua
  6. 53
      libs/parsers.lua
  7. 3
      libs/syscontrol.lua
  8. 19
      modules/binds.lua
  9. 8
      modules/desktop.lua
  10. 10
      modules/global.lua
  11. 63
      modules/powermanX.lua
  12. 1
      rc.lua
  13. 1
      themes/unity/config/client_menu.json
  14. 19
      themes/unity/theme.lua
  15. 63
      widgets/battery.lua
  16. 154
      widgets/clientvolume.lua
  17. 32
      widgets/soundclown.lua

5
README.md

@ -23,6 +23,11 @@ The installation process is not much different from the previous iteration, exce
3. Install AwesomeWM (version 4.3 as of right now)
4. (Optional) Read additional installation steps in `extra/README.md`
## Keybindings and user guide
- press win+s
- read extra/README.md
- enjoy
## Roadmap
- [x] Port widgets from original config to AWMTK2

11
desktop.conf

@ -26,11 +26,20 @@ modkey+b = ":client.below"
modkey+f = ":client.fullscreen"
modkey+n = ":client.minimize"
modkey+m = ":client.maximize"
modkey+p = ":client.pin"
modkey+y = ":client.toggle_titlebars"
# Widget keys
modkey+r = ":dismal.run"
modkey+s = ":help.show"
Control+XF86AudioRaiseVolume = ":client.volume_up"
Control+XF86AudioLowerVolume = ":client.volume_down"
Control+XF86AudioMute = ":client.volume_mute"
XF86MonBrightnessUp = ":battery.brightness_up"
XF86MonBrightnessDown = ":battery.brightness_down"
XF86AudioPlay = ":mpc.play"
XF86AudioPrev = ":mpc.prev"
XF86AudioNext = ":mpc.next"
# Custom keys
Print = "flameshot gui"
Shift+Print = "flameshot launcher"

6
libs/asckey.lua

@ -12,6 +12,12 @@ local asckey = {
}
local awful = require("awful")
asckey.set_keymap = function(keymap)
for k,v in pairs(keymap) do
asckey.keymap[v] = k
end
end
asckey.get_keycomb = function(name)
local modifiers = {}
name = name:gsub("[^%s%+]+%+",function(v)

16
libs/awmtk2.lua

@ -162,6 +162,9 @@ awmtk.proto_style.center = awmtk.create_delta("center", {
awmtk.proto_style.slider = awmtk.create_delta("slider", {
margins = 1
}, awmtk.proto_style,awmtk.proto_style.base)
awmtk.proto_style.checkbox = awmtk.create_delta("checkbox", {
}, awmtk.proto_style,awmtk.proto_style.base)
-- }}}
-- {{{ Generic templates
@ -407,6 +410,19 @@ awmtk.proto_templates = {
widget = wibox.widget.slider
},args or {})
end
end,
checkbox = function(style)
return function(args)
return awmtk.merge({
color = style.checkbox.bg_focus,
padding = 2,
shape = style.checkbox.shape,
border_width = style.checkbox.shape_border_width,
bg = style.checkbox.shape_border_color,
widget = wibox.widget.checkbox
},args or {})
end
end
}

169
libs/parser_test.lua

@ -7,6 +7,15 @@
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
local parsers = require("parsers")
function rprint(t,ident)
ident = ident or 0
for k,v in pairs(t) do
print((" "):rep(ident)..k,v)
if type(v) == "table" then
rprint(v,ident+4)
end
end
end
-- Conf parser
local data = [[
# Global variables
@ -45,3 +54,163 @@ for k,v in pairs(parsers.conf(data)) do
print(kk,vv)
end
end
-- yaml-like (pactl) parser
data = [[
Sink Input #75
Driver: PipeWire
Owner Module: n/a
Client: 58
Sink: 46
Sample Specification: float32le 2ch 44100Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 38326 / 58% / -13.98 dB, front-right: 38326 / 58% / -13.98 dB
balance 0.00
Buffer Latency: 0 usec
Sink Latency: 0 usec
Resample method: PipeWire
Properties:
client.api = "pipewire-pulse"
pulse.server.type = "unix"
application.name = "LibreWolf"
application.process.id = "1756"
application.process.user = "yessiest"
application.process.host = "architect"
application.process.binary = "librewolf"
application.language = "C.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "a8099c2d12fe88c3df940ed562adbe8c"
application.process.session_id = "1"
media.name = "AudioStream"
node.rate = "1/44100"
node.latency = "3307/44100"
stream.is-live = "true"
node.name = "LibreWolf"
node.autoconnect = "true"
node.want-driver = "true"
media.class = "Stream/Output/Audio"
adapt.follower.spa-node = ""
object.register = "false"
factory.id = "6"
clock.quantum-limit = "8192"
factory.mode = "split"
audio.adapt.follower = ""
library.name = "audioconvert/libspa-audioconvert"
client.id = "56"
object.id = "57"
object.serial = "75"
pulse.attr.maxlength = "4194304"
pulse.attr.tlength = "44104"
pulse.attr.prebuf = "35296"
pulse.attr.minreq = "8816"
module-stream-restore.id = "sink-input-by-application-name:LibreWolf"
]]
rprint(parsers.yaml_pseudo(data))
-- Fast incomplete yaml parser
data = [[
Sink Input #73
Driver: PipeWire
Owner Module: n/a
Client: 58
Sink: 46
Sample Specification: float32le 2ch 44100Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 38326 / 58% / -13.98 dB, front-right: 38326 / 58% / -13.98 dB
balance 0.00
Buffer Latency: 0 usec
Sink Latency: 0 usec
Resample method: PipeWire
Properties:
client.api = "pipewire-pulse"
pulse.server.type = "unix"
application.name = "LibreWolf"
application.process.id = "1756"
application.process.user = "yessiest"
application.process.host = "architect"
application.process.binary = "librewolf"
application.language = "C.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "a8099c2d12fe88c3df940ed562adbe8c"
application.process.session_id = "1"
media.name = "AudioStream"
node.rate = "1/44100"
node.latency = "3307/44100"
stream.is-live = "true"
node.name = "LibreWolf"
node.autoconnect = "true"
node.want-driver = "true"
media.class = "Stream/Output/Audio"
adapt.follower.spa-node = ""
object.register = "false"
factory.id = "6"
clock.quantum-limit = "8192"
factory.mode = "split"
audio.adapt.follower = ""
library.name = "audioconvert/libspa-audioconvert"
client.id = "56"
object.id = "57"
object.serial = "75"
pulse.attr.maxlength = "4194304"
pulse.attr.tlength = "44104"
pulse.attr.prebuf = "35296"
pulse.attr.minreq = "8816"
module-stream-restore.id = "sink-input-by-application-name:LibreWolf"
Sink Input #75
Driver: PipeWire
Owner Module: n/a
Client: 58
Sink: 46
Sample Specification: float32le 2ch 44100Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 38326 / 58% / -13.98 dB, front-right: 38326 / 58% / -13.98 dB
balance 0.00
Buffer Latency: 0 usec
Sink Latency: 0 usec
Resample method: PipeWire
Properties:
client.api = "pipewire-pulse"
pulse.server.type = "unix"
application.name = "LibreWolf"
application.process.id = "1756"
application.process.user = "yessiest"
application.process.host = "architect"
application.process.binary = "librewolf"
application.language = "C.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "a8099c2d12fe88c3df940ed562adbe8c"
application.process.session_id = "1"
media.name = "AudioStream"
node.rate = "1/44100"
node.latency = "3307/44100"
stream.is-live = "true"
node.name = "LibreWolf"
node.autoconnect = "true"
node.want-driver = "true"
media.class = "Stream/Output/Audio"
adapt.follower.spa-node = ""
object.register = "false"
factory.id = "6"
clock.quantum-limit = "8192"
factory.mode = "split"
audio.adapt.follower = ""
library.name = "audioconvert/libspa-audioconvert"
client.id = "56"
object.id = "57"
object.serial = "75"
pulse.attr.maxlength = "4194304"
pulse.attr.tlength = "44104"
pulse.attr.prebuf = "35296"
pulse.attr.minreq = "8816"
module-stream-restore.id = "sink-input-by-application-name:LibreWolf"
]]
rprint(parsers.fast_split_yaml(data))

53
libs/parsers.lua

@ -34,7 +34,60 @@ local function split_strings(text)
return split
end
parsers.fast_split_yaml = function(cfgtext)
-- Fast yaml splitter - incomplete parsing, only first layer is parsed
-- Used within timers to find objects while decreasing CPU usage
local items = {}
local replacements = 1
cfgtext = cfgtext:gsub("^%s*","")
while replacements > 0 do
cfgtext,replacements = cfgtext:gsub("^(.-\n)(%S+)",function(struct,n)
table.insert(items,struct)
return ""..n
end)
end
table.insert(items,cfgtext)
return items
end
parsers.yaml_pseudo = function(cfgtext)
-- Somewhat yaml-like structure used by pactl
local struct = {}
local lines = {}
cfgtext:gsub("(%s*)([^\n]*)",function(spacing,line)
table.insert(lines,
{
spacing:len(),
-- key
line:match("^([^:=]-)%s*[:=]") or line,
-- value
line:match(":%s*(.-)%s*$") or
line:match("=%s*(.-)%s*$")
}
)
end)
local history = {struct}
local spacing_width = 0
for k,v in pairs(lines) do
if v[1] > spacing_width then
history[#history][lines[k-1][2]] = {
[lines[k-1][2]] = lines[k-1][3]
}
history[#history+1] = history[#history][lines[k-1][2]]
elseif v[1] < spacing_width then
history[#history] = nil
end
if v[3] and v[3]:match("^%s*\".*\"%s*$") then
history[#history][v[2]] = v[3]:match("^%s*\"(.*)\"%s*$")
else
history[#history][v[2]] = v[3]
end
spacing_width = v[1]
end
return struct
end
parsers.conf = function(cfgtext)
-- Conf style parser (not exactly TOML)
cfgtext = cfgtext:gsub("#[^\n]*","")
local split_by_strings,err = split_strings(cfgtext)
if not split_by_strings then

3
libs/syscontrol.lua

@ -10,7 +10,8 @@
local syscontrol = {
power_supply = {},
backlight = {},
hwmon = {}
hwmon = {},
pulse = {}
}
syscontrol.backlight.enumerate = function()
local lshandler = io.popen("ls -1 /sys/class/backlight","r")

19
modules/binds.lua

@ -11,7 +11,7 @@ local gears = require("gears")
local ask = require("asckey")
global.modkey = global.modkey or "Mod4"
ask.keymap = keybindings
ask.set_keymap(config.keys)
local custom_keys = ask.custom_binds()
local k = ask.k
@ -101,7 +101,22 @@ local clientkeys = gears.table.join(
c.maximized = not c.maximized
c:raise()
end ,
{description = "(un)maximize", group = "client"}))
{description = "(un)maximize", group = "client"}),
k(":client.pin",
function (c)
c.sticky = not c.sticky
end ,
{description = "(un)pin", group = "client"}),
k(":client.toggle_titlebars",
function (c)
if (not c.titlebar_top.visible) then
c:emit_signal("titlebar::unhide")
else
c:emit_signal("titlebar::hide")
end
end ,
{description = "(un)hide titlebars", group = "client"}))
awful.rules.rules[1].properties.keys = clientkeys
local clientbuttons = gears.table.join(

8
modules/desktop.lua

@ -156,7 +156,7 @@ client.connect_signal("request::titlebars",function(c)
fg_focus = style[v].fg_focus,
font = style[v].font
})
titlebar:setup(t.titlebar(contents))
c[v] = titlebar:setup(t.titlebar(contents))
awful.rules.rules[1].properties.placement(c)
if style[v].onfocus then
c:connect_signal("focus",function()
@ -168,6 +168,12 @@ client.connect_signal("request::titlebars",function(c)
style[v].onunfocus(titlebar)
end)
end
c:connect_signal("titlebar::hide",function(c)
c[v].visible = false
end)
c:connect_signal("titlebar::unhide",function(c)
c[v].visible = true
end)
end
end)
end --}}}

10
modules/global.lua

@ -12,16 +12,8 @@ local conf_file = io.open(root_path.."/desktop.conf","r")
if not conf_file then
error("desktop.conf is missing or not readable")
end
local config = conf(conf_file:read("*a"))
config = conf(conf_file:read("*a"))
conf_file:close()
global = config.global
global.terminal = envsub(global.terminal)
global.browser = envsub(global.browser)
local function invert(t)
local new_t = {}
for k,v in pairs(t) do
new_t[v] = k
end
return new_t
end
keybindings = invert(config.keys)

63
modules/powermanX.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
})

1
rc.lua

@ -16,6 +16,7 @@ package.cpath = package.cpath
-- Modules list
require("modules.collect_garbage")
require("modules.global")
require("modules.powermanX")
require("modules.errorlog")
require("modules.base")
require("modules.binds")

1
themes/unity/config/client_menu.json

@ -1,5 +1,6 @@
{
"list": [
{"widget": "widgets.clientvolume"},
{"widget": "widgets.clientcontrols"},
{"widget": "widgets.clientbuttons"}
],

19
themes/unity/theme.lua

@ -1,6 +1,6 @@
-- Reno98 - a retro replica of a very recognizable theme
-- Reno Unity - Unity theme for Reno desktop
--[[
Reno98 - A theme for Reno desktop
Reno Unity - A theme for Reno desktop
Written in 2022 by Yessiest (yessiest@memeware.net)
@ -306,11 +306,20 @@ theme.widgets = {
end,
height = 20,
width = 140,
bg_focus = theme.bg_normal,
bg_normal = theme.bg_focus,
handle_width = 8,
handle_border_color = theme.bg_focus,
handle_border_color = theme.bg_normal,
handle_border_width = 2,
bar_height = 6
}
bar_height = 6,
bar_border_color = theme.bg_focus,
bar_border_width = 2
},
checkbox = {
shape = gears.shape.circle,
shape_border_width = 3,
shaoe_border_color = theme.bg_focus
},
},
-- }}}
-- {{{ Menus

63
widgets/battery.lua

@ -12,6 +12,7 @@ local gears = require("gears")
local wibox = require("wibox")
local awmtk2 = require("awmtk2")
local syscontrol = require("syscontrol")
local ask = require("asckey")
local function get_virtual_icon(data)
-- Get an icon from a cumulative total of battery percentages and current charging state
@ -182,14 +183,25 @@ return function(args)
-- }}}
-- {{{ Backlight
local backlight_devices = syscontrol.backlight.enumerate()
local default_backlight_device
for k,v in pairs(backlight_devices) do
local data = syscontrol.backlight.read_attribs(v)
if data then
widget_map[data.name] = wibox.widget(t.container({
t.article({
icon = beautiful["backlight-symbolic"],
title = "Backlight",
}),
{
t.article({
icon = beautiful["backlight-symbolic"],
title = "Backlight",
}),
(data.writable and t.checkbox({
checked = true,
id = "checkbox",
forced_height = style.article.icon_size,
forced_width = style.article.icon_size
})),
layout = wibox.layout.fixed.horizontal,
spacing = style.base.spacing
},
t.textbox({
markup = "Brightness: "..tostring(data.brightness),
id = "brightness_id"
@ -201,7 +213,7 @@ return function(args)
(data.writable and t.slider({
minimum = data.max_brightness*0.05,
maximum = data.max_brightness,
value = data.brightness,
value = tonumber(data.brightness),
id = "slider"
})),
layout = wibox.layout.fixed.vertical
@ -210,11 +222,22 @@ return function(args)
bgimage = style.container.bgimage_highlight
}))
if data.writable then
local slider = widget_map[data.name]:get_children_by_id("slider")[1]
local w = widget_map[data.name]
local slider = w:get_children_by_id("slider")[1]
slider:connect_signal("widget::redraw_needed",function(self)
local value = self.value
syscontrol.backlight.set_brightness(data,math.floor(value))
end)
slider.value = tonumber(data.brightness)
local checkbox = w:get_children_by_id("checkbox")[1]
checkbox:connect_signal("button::press",function()
if default_backlight_device then
local check2 = widget_map[default_backlight_device.name]
:get_children_by_id("checkbox")[1]
check2.checked = false
end
default_backlight_device = data
end)
end
layout:add(widget_map[data.name])
end
@ -236,6 +259,34 @@ return function(args)
end
end
})
-- Keybindings
root.keys(gears.table.join(
root.keys(),
ask.k(":battery.brightness_up",function()
if default_backlight_device then
local data = default_backlight_device
local s = widget_map[data.name]:get_children_by_id("slider")[1]
local value = s.value+(data.max_brightness*0.05)
if value > data.max_brightness then
value = data.max_brightness
end
syscontrol.backlight.set_brightness(data,math.floor(value))
s.value = math.floor(value)
end
end,{description="increase brightness", group = "widgets"}),
ask.k(":battery.brightness_down",function()
if default_backlight_device then
local data = default_backlight_device
local s = widget_map[data.name]:get_children_by_id("slider")[1]
local value = s.value-(data.max_brightness*0.05)
if value < data.max_brightness*0.05 then
value = data.max_brightness*0.05
end
syscontrol.backlight.set_brightness(data,math.floor(value))
s.value = math.floor(value)
end
end,{description="decrease brightness", group = "widgets"})
))
-- }}}
-- We don't need this widget if we don't have anything to show
local function count(t)

154
widgets/clientvolume.lua

@ -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

32
widgets/soundclown.lua

@ -12,6 +12,7 @@ local wibox = require("wibox")
local gears = require("gears")
local awful = require("awful")
local beautiful = require("beautiful")
local ask = require("asckey")
return function(args)
local style = awmtk2.create_style("soundclown",
@ -72,15 +73,16 @@ return function(args)
local bprev = widget:get_children_by_id("prev")[1]
bprev:connect_signal("button::press",style.button.onpress)
bprev:connect_signal("button::release",style.button.onrelease)
bprev:connect_signal("button::press",function()
local function prev()
awful.spawn("mpc cdprev")
end)
end
bprev:connect_signal("button::press",prev)
local pause_state = true
local icon = widget:get_children_by_id("statusicon")[1]
local bplay = widget:get_children_by_id("play")[1]
bplay:connect_signal("button::press",style.button.onpress)
bplay:connect_signal("button::release",style.button.onrelease)
bplay:connect_signal("button::press",function()
local function play()
pause_state = (not pause_state)
if pause_state == false then
icon.image = beautiful["mpc-pause-symbolic"]
@ -89,13 +91,16 @@ return function(args)
icon.image = beautiful["mpc-play-symbolic"]
awful.spawn("mpc play")
end
end)
end
bplay:connect_signal("button::press",play)
local bnext = widget:get_children_by_id("next")[1]
bnext:connect_signal("button::press",style.button.onpress)
bnext:connect_signal("button::release",style.button.onrelease)
bnext:connect_signal("button::press",function()
local function nextb()
awful.spawn("mpc next")
end)
end
bnext:connect_signal("button::press",nextb)
local update_ready = true
local function update_mpd_status()
awful.spawn.easy_async("mpc",function(out)
local status = ""
@ -104,6 +109,7 @@ return function(args)
state = true
icon.image = beautiful["mpc-play-symbolic"]
display:set_markup(status)
update_ready = true
return
else
status = status.."[PAUSED] "
@ -113,6 +119,7 @@ return function(args)
out:match("[^\n]*").." "..
out:match("%d*:%d*/%d*:%d*%s*%(%d*%%%)")
display:set_markup(status)
update_ready = true
end)
end
update_mpd_status()
@ -120,8 +127,19 @@ return function(args)
timeout = args.polling_delay or 1,
autostart = true,
callback = function()
if not update_ready then return end
update_ready = false
update_mpd_status()
end
}
}
root.keys(gears.table.join(
root.keys(),
ask.k(":mpc.prev",prev,
{description = "switch to previous MPD track",group="widgets"}),
ask.k(":mpc.play",play,
{description = "play/pause MPD",group="widgets"}),
ask.k(":mpc.next",nextb,
{description = "switch to next MPD track",group="widgets"})
))
return widget
end
Loading…
Cancel
Save