Update users home folder, clean up some scripts and add comments
This commit is contained in:
@ -9,9 +9,9 @@ local io = { open = io.open }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local string = {
|
||||
sub = string.sub,
|
||||
match = string.match,
|
||||
gmatch = string.gmatch
|
||||
sub = string.sub,
|
||||
match = string.match,
|
||||
gmatch = string.gmatch
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -23,56 +23,56 @@ local ati = {}
|
||||
|
||||
-- {{{ Define variables
|
||||
local _units = { clock = { ["khz"] = 1, ["mhz"] = 1000 },
|
||||
voltage = { ["v"] = 1, ["mv"] = 1000 } }
|
||||
voltage = { ["v"] = 1, ["mv"] = 1000 } }
|
||||
local _reps = {
|
||||
["sclk"] = { name = "engine_clock", units = _units.clock, mul = 10 },
|
||||
["mclk"] = { name = "memory_clock", units = _units.clock, mul = 10 },
|
||||
["vddc"] = { name = "voltage", units = _units.voltage },
|
||||
["voltage"] = { name = "voltage", units = _units.voltage },
|
||||
["current engine clock"] = { name = "engine_clock", units = _units.clock },
|
||||
["current memory clock"] = { name = "memory_clock", units = _units.clock }
|
||||
["sclk"] = { name = "engine_clock", units = _units.clock, mul = 10 },
|
||||
["mclk"] = { name = "memory_clock", units = _units.clock, mul = 10 },
|
||||
["vddc"] = { name = "voltage", units = _units.voltage },
|
||||
["voltage"] = { name = "voltage", units = _units.voltage },
|
||||
["current engine clock"] = { name = "engine_clock", units = _units.clock },
|
||||
["current memory clock"] = { name = "memory_clock", units = _units.clock }
|
||||
}
|
||||
-- }}}
|
||||
|
||||
-- {{{ ATI widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
local pm = helpers.pathtotable("/sys/class/drm/"..warg.."/device")
|
||||
local _data = {}
|
||||
local pm = helpers.pathtotable("/sys/class/drm/"..warg.."/device")
|
||||
local _data = {}
|
||||
|
||||
-- Get power info
|
||||
_data["{method}"] =
|
||||
pm.power_method and string.sub(pm.power_method, 1, -2) or "N/A"
|
||||
_data["{dpm_state}"] =
|
||||
pm.power_dpm_state and string.sub(pm.power_dpm_state, 1, -2) or "N/A"
|
||||
_data["{dpm_perf_level}"] =
|
||||
pm.power_dpm_force_performance_level and
|
||||
string.sub(pm.power_dpm_force_performance_level, 1, -2) or "N/A"
|
||||
_data["{profile}"] =
|
||||
pm.power_profile and string.sub(pm.power_profile, 1, -2) or "N/A"
|
||||
-- Get power info
|
||||
_data["{method}"] =
|
||||
pm.power_method and string.sub(pm.power_method, 1, -2) or "N/A"
|
||||
_data["{dpm_state}"] =
|
||||
pm.power_dpm_state and string.sub(pm.power_dpm_state, 1, -2) or "N/A"
|
||||
_data["{dpm_perf_level}"] =
|
||||
pm.power_dpm_force_performance_level and
|
||||
string.sub(pm.power_dpm_force_performance_level, 1, -2) or "N/A"
|
||||
_data["{profile}"] =
|
||||
pm.power_profile and string.sub(pm.power_profile, 1, -2) or "N/A"
|
||||
|
||||
local f = io.open("/sys/kernel/debug/dri/64/radeon_pm_info", "r")
|
||||
if f then -- Get ATI info from the debug filesystem
|
||||
for line in f:lines() do
|
||||
for k, unit in string.gmatch(line, "(%a+[%a%s]*):[%s]+([%d]+)") do
|
||||
unit = tonumber(unit)
|
||||
local f = io.open("/sys/kernel/debug/dri/64/radeon_pm_info", "r")
|
||||
if f then -- Get ATI info from the debug filesystem
|
||||
for line in f:lines() do
|
||||
for k, unit in string.gmatch(line, "(%a+[%a%s]*):[%s]+([%d]+)") do
|
||||
unit = tonumber(unit)
|
||||
|
||||
_data["{dpm_power_level}"] = -- DPM active?
|
||||
tonumber(string.match(line, "power level ([%d])")) or "N/A"
|
||||
_data["{dpm_power_level}"] = -- DPM active?
|
||||
tonumber(string.match(line, "power level ([%d])")) or "N/A"
|
||||
|
||||
if _reps[k] then
|
||||
for u, v in pairs(_reps[k].units) do
|
||||
_data["{".._reps[k].name.." "..u.."}"] =
|
||||
(unit * (_reps[k].mul or 1)) / v
|
||||
end
|
||||
end
|
||||
end
|
||||
if _reps[k] then
|
||||
for u, v in pairs(_reps[k].units) do
|
||||
_data["{".._reps[k].name.." "..u.."}"] =
|
||||
(unit * (_reps[k].mul or 1)) / v
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
|
||||
return _data
|
||||
return _data
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,33 +19,33 @@ local batacpi = {}
|
||||
|
||||
-- {{{ Battery widget type
|
||||
local function worker(format)
|
||||
local battery_info = {}
|
||||
local battery_state = {
|
||||
["full"] = "↯",
|
||||
["unknown"] = "⌁",
|
||||
["charged"] = "↯",
|
||||
["charging"] = "+",
|
||||
["discharging"] = "-"
|
||||
}
|
||||
local battery_info = {}
|
||||
local battery_state = {
|
||||
["full"] = "↯",
|
||||
["unknown"] = "⌁",
|
||||
["charged"] = "↯",
|
||||
["charging"] = "+",
|
||||
["discharging"] = "-"
|
||||
}
|
||||
|
||||
-- Get data from acpitool
|
||||
local f = io.popen("acpitool -b")
|
||||
-- Get data from acpitool
|
||||
local f = io.popen("acpitool -b")
|
||||
|
||||
for line in f:lines() do
|
||||
-- Check if the battery is present
|
||||
if string.match(line, "^[%s]+Battery.*") then
|
||||
-- Store state and charge information
|
||||
table.insert(battery_info, (battery_state[string.match(line, "([%a]*),") or "unknown"]))
|
||||
table.insert(battery_info, (tonumber(string.match(line, "([%d]?[%d]?[%d])%.")) or 0))
|
||||
-- Store remaining time information
|
||||
table.insert(battery_info, (string.match(line, "%%,%s(.*)") or "N/A"))
|
||||
else
|
||||
return {battery_state["unknown"], 0, "N/A"}
|
||||
end
|
||||
for line in f:lines() do
|
||||
-- Check if the battery is present
|
||||
if string.match(line, "^[%s]+Battery.*") then
|
||||
-- Store state and charge information
|
||||
table.insert(battery_info, (battery_state[string.match(line, "([%a]*),") or "unknown"]))
|
||||
table.insert(battery_info, (tonumber(string.match(line, "([%d]?[%d]?[%d])%.")) or 0))
|
||||
-- Store remaining time information
|
||||
table.insert(battery_info, (string.match(line, "%%,%s(.*)") or "N/A"))
|
||||
else
|
||||
return {battery_state["unknown"], 0, "N/A"}
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
return battery_info
|
||||
return battery_info
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -8,13 +8,13 @@ local tonumber = tonumber
|
||||
local io = { open = io.open }
|
||||
local setmetatable = setmetatable
|
||||
local math = {
|
||||
min = math.min,
|
||||
floor = math.floor
|
||||
min = math.min,
|
||||
floor = math.floor
|
||||
}
|
||||
local string = {
|
||||
find = string.find,
|
||||
match = string.match,
|
||||
format = string.format
|
||||
find = string.find,
|
||||
match = string.match,
|
||||
format = string.format
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -26,53 +26,53 @@ local batpmu = {}
|
||||
|
||||
-- {{{ Battery widget type
|
||||
local function worker(format, batid)
|
||||
local battery_state = {
|
||||
["full"] = "↯",
|
||||
["unknown"] = "⌁",
|
||||
["00000013"] = "+",
|
||||
["00000011"] = "-"
|
||||
}
|
||||
local battery_state = {
|
||||
["full"] = "↯",
|
||||
["unknown"] = "⌁",
|
||||
["00000013"] = "+",
|
||||
["00000011"] = "-"
|
||||
}
|
||||
|
||||
-- Get /proc/pmu/battery* state
|
||||
local f = io.open("/proc/pmu/" .. batid)
|
||||
-- Handler for incompetent users
|
||||
if not f then return {battery_state["unknown"], 0, "N/A"} end
|
||||
local statefile = f:read("*all")
|
||||
f:close()
|
||||
-- Get /proc/pmu/battery* state
|
||||
local f = io.open("/proc/pmu/" .. batid)
|
||||
-- Handler for incompetent users
|
||||
if not f then return {battery_state["unknown"], 0, "N/A"} end
|
||||
local statefile = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Get /proc/pmu/info data
|
||||
local f = io.open("/proc/pmu/info")
|
||||
local infofile = f:read("*all")
|
||||
f:close()
|
||||
-- Get /proc/pmu/info data
|
||||
local f = io.open("/proc/pmu/info")
|
||||
local infofile = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Check if the battery is present
|
||||
if infofile == nil or string.find(infofile, "Battery count[%s]+:[%s]0") then
|
||||
return {battery_state["unknown"], 0, "N/A"}
|
||||
end
|
||||
-- Check if the battery is present
|
||||
if infofile == nil or string.find(infofile, "Battery count[%s]+:[%s]0") then
|
||||
return {battery_state["unknown"], 0, "N/A"}
|
||||
end
|
||||
|
||||
|
||||
-- Get capacity and charge information
|
||||
local capacity = string.match(statefile, "max_charge[%s]+:[%s]([%d]+).*")
|
||||
local remaining = string.match(statefile, "charge[%s]+:[%s]([%d]+).*")
|
||||
-- Get capacity and charge information
|
||||
local capacity = string.match(statefile, "max_charge[%s]+:[%s]([%d]+).*")
|
||||
local remaining = string.match(statefile, "charge[%s]+:[%s]([%d]+).*")
|
||||
|
||||
-- Calculate percentage
|
||||
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||
-- Calculate percentage
|
||||
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||
|
||||
|
||||
-- Get timer information
|
||||
local timer = string.match(statefile, "time rem%.[%s]+:[%s]([%d]+).*")
|
||||
if timer == "0" then return {battery_state["full"], percent, "N/A"} end
|
||||
-- Get timer information
|
||||
local timer = string.match(statefile, "time rem%.[%s]+:[%s]([%d]+).*")
|
||||
if timer == "0" then return {battery_state["full"], percent, "N/A"} end
|
||||
|
||||
-- Get state information
|
||||
local state = string.match(statefile, "flags[%s]+:[%s]([%d]+).*")
|
||||
local state = battery_state[state] or battery_state["unknown"]
|
||||
-- Get state information
|
||||
local state = string.match(statefile, "flags[%s]+:[%s]([%d]+).*")
|
||||
local state = battery_state[state] or battery_state["unknown"]
|
||||
|
||||
-- Calculate remaining (charging or discharging) time
|
||||
local hoursleft = math.floor(tonumber(timer) / 3600)
|
||||
local minutesleft = math.floor((tonumber(timer) / 60) % 60)
|
||||
local time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||
-- Calculate remaining (charging or discharging) time
|
||||
local hoursleft = math.floor(tonumber(timer) / 3600)
|
||||
local minutesleft = math.floor((tonumber(timer) / 60) % 60)
|
||||
local time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||
|
||||
return {state, percent, time}
|
||||
return {state, percent, time}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -8,13 +8,13 @@ local tonumber = tonumber
|
||||
local io = { open = io.open }
|
||||
local setmetatable = setmetatable
|
||||
local math = {
|
||||
min = math.min,
|
||||
floor = math.floor
|
||||
min = math.min,
|
||||
floor = math.floor
|
||||
}
|
||||
local string = {
|
||||
find = string.find,
|
||||
match = string.match,
|
||||
format = string.format
|
||||
find = string.find,
|
||||
match = string.match,
|
||||
format = string.format
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -26,60 +26,60 @@ local batproc = {}
|
||||
|
||||
-- {{{ Battery widget type
|
||||
local function worker(format, batid)
|
||||
local battery_state = {
|
||||
["full"] = "↯",
|
||||
["unknown"] = "⌁",
|
||||
["charged"] = "↯",
|
||||
["charging"] = "+",
|
||||
["discharging"] = "-"
|
||||
}
|
||||
local battery_state = {
|
||||
["full"] = "↯",
|
||||
["unknown"] = "⌁",
|
||||
["charged"] = "↯",
|
||||
["charging"] = "+",
|
||||
["discharging"] = "-"
|
||||
}
|
||||
|
||||
-- Get /proc/acpi/battery info
|
||||
local f = io.open("/proc/acpi/battery/"..batid.."/info")
|
||||
-- Handler for incompetent users
|
||||
if not f then return {battery_state["unknown"], 0, "N/A"} end
|
||||
local infofile = f:read("*all")
|
||||
f:close()
|
||||
-- Get /proc/acpi/battery info
|
||||
local f = io.open("/proc/acpi/battery/"..batid.."/info")
|
||||
-- Handler for incompetent users
|
||||
if not f then return {battery_state["unknown"], 0, "N/A"} end
|
||||
local infofile = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Check if the battery is present
|
||||
if infofile == nil or string.find(infofile, "present:[%s]+no") then
|
||||
return {battery_state["unknown"], 0, "N/A"}
|
||||
end
|
||||
-- Check if the battery is present
|
||||
if infofile == nil or string.find(infofile, "present:[%s]+no") then
|
||||
return {battery_state["unknown"], 0, "N/A"}
|
||||
end
|
||||
|
||||
-- Get capacity information
|
||||
local capacity = string.match(infofile, "last full capacity:[%s]+([%d]+).*")
|
||||
-- Get capacity information
|
||||
local capacity = string.match(infofile, "last full capacity:[%s]+([%d]+).*")
|
||||
|
||||
|
||||
-- Get /proc/acpi/battery state
|
||||
local f = io.open("/proc/acpi/battery/"..batid.."/state")
|
||||
local statefile = f:read("*all")
|
||||
f:close()
|
||||
-- Get /proc/acpi/battery state
|
||||
local f = io.open("/proc/acpi/battery/"..batid.."/state")
|
||||
local statefile = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Get state information
|
||||
local state = string.match(statefile, "charging state:[%s]+([%a]+).*")
|
||||
local state = battery_state[state] or battery_state["unknown"]
|
||||
-- Get state information
|
||||
local state = string.match(statefile, "charging state:[%s]+([%a]+).*")
|
||||
local state = battery_state[state] or battery_state["unknown"]
|
||||
|
||||
-- Get charge information
|
||||
local rate = string.match(statefile, "present rate:[%s]+([%d]+).*")
|
||||
local remaining = string.match(statefile, "remaining capacity:[%s]+([%d]+).*")
|
||||
-- Get charge information
|
||||
local rate = string.match(statefile, "present rate:[%s]+([%d]+).*")
|
||||
local remaining = string.match(statefile, "remaining capacity:[%s]+([%d]+).*")
|
||||
|
||||
|
||||
-- Calculate percentage (but work around broken BAT/ACPI implementations)
|
||||
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||
-- Calculate percentage (but work around broken BAT/ACPI implementations)
|
||||
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||
|
||||
-- Calculate remaining (charging or discharging) time
|
||||
if state == "+" then
|
||||
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
|
||||
elseif state == "-" then
|
||||
timeleft = tonumber(remaining) / tonumber(rate)
|
||||
else
|
||||
return {state, percent, "N/A"}
|
||||
end
|
||||
local hoursleft = math.floor(timeleft)
|
||||
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
|
||||
local time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||
-- Calculate remaining (charging or discharging) time
|
||||
if state == "+" then
|
||||
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
|
||||
elseif state == "-" then
|
||||
timeleft = tonumber(remaining) / tonumber(rate)
|
||||
else
|
||||
return {state, percent, "N/A"}
|
||||
end
|
||||
local hoursleft = math.floor(timeleft)
|
||||
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
|
||||
local time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||
|
||||
return {state, percent, time}
|
||||
return {state, percent, time}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -26,161 +26,160 @@ BB = {}
|
||||
BB.__index = BB
|
||||
|
||||
function BB.create(url, builder)
|
||||
local b = {}
|
||||
setmetatable(b,BB)
|
||||
b.url = url -- buildbot url
|
||||
b.builder = builder -- builder name
|
||||
b.lastChecked = 0 -- last checked build number
|
||||
b.lastSuccessful = 0 -- last successful build number
|
||||
b.lastResult = nil -- last json parsed result
|
||||
b.lastError = nil -- last error string or nil if no error
|
||||
return b
|
||||
local b = {}
|
||||
setmetatable(b,BB)
|
||||
b.url = url -- buildbot url
|
||||
b.builder = builder -- builder name
|
||||
b.lastChecked = 0 -- last checked build number
|
||||
b.lastSuccessful = 0 -- last successful build number
|
||||
b.lastResult = nil -- last json parsed result
|
||||
b.lastError = nil -- last error string or nil if no error
|
||||
return b
|
||||
end
|
||||
|
||||
function BB:_queryBuildbot(build_number)
|
||||
local f = io.popen("curl --connect-timeout 1 "..self.url.."/json/builders/"..self.builder.."/builds/"..build_number)
|
||||
local jsbuilder = f:read("*all")
|
||||
f:close()
|
||||
if #jsbuilder == 0 then
|
||||
return false, "can't read from url"
|
||||
end
|
||||
local f = io.popen("curl --connect-timeout 1 "..self.url.."/json/builders/"..self.builder.."/builds/"..build_number)
|
||||
local jsbuilder = f:read("*all")
|
||||
f:close()
|
||||
if #jsbuilder == 0 then
|
||||
return false, "can't read from url"
|
||||
end
|
||||
|
||||
local result_status, result = pcall(json.decode, jsbuilder, false)
|
||||
if not result_status then
|
||||
return false, "can't parse json data"
|
||||
end
|
||||
return true, result
|
||||
local result_status, result = pcall(json.decode, jsbuilder, false)
|
||||
if not result_status then
|
||||
return false, "can't parse json data"
|
||||
end
|
||||
return true, result
|
||||
end
|
||||
|
||||
function BB:_getBuildStatus(result)
|
||||
if #result['text'] > 0 then
|
||||
local text = result['text']
|
||||
if text[1] == "build" and text[2] == "successful" and #text == 2 then
|
||||
--successful
|
||||
return bs.OK
|
||||
else
|
||||
--failed
|
||||
return bs.FAILED
|
||||
end
|
||||
if #result['text'] > 0 then
|
||||
local text = result['text']
|
||||
if text[1] == "build" and text[2] == "successful" and #text == 2 then
|
||||
--successful
|
||||
return bs.OK
|
||||
else
|
||||
--in progress
|
||||
return bs.RUNNING
|
||||
--failed
|
||||
return bs.FAILED
|
||||
end
|
||||
else
|
||||
--in progress
|
||||
return bs.RUNNING
|
||||
end
|
||||
end
|
||||
|
||||
-- Function queries buildbot to refresh builds status.
|
||||
-- * if build is successful or failed it will not be queried again, number is stored in lasteChecked
|
||||
-- * up to 10 last builds will be checked to find last successful build
|
||||
function BB:refresh()
|
||||
local last_pass_fail = 0
|
||||
local nr = -1
|
||||
local last_result
|
||||
local iter_counter = 0
|
||||
local last_pass_fail = 0
|
||||
local nr = -1
|
||||
local last_result
|
||||
local iter_counter = 0
|
||||
|
||||
self.lastError = nil
|
||||
self.lastResult = nil
|
||||
--- there is a gap to fill in, iterate all not checked builds starting from latest
|
||||
while nr > self.lastChecked or nr == -1 do
|
||||
local r_status, r = self:_queryBuildbot(nr)
|
||||
local s
|
||||
self.lastError = nil
|
||||
self.lastResult = nil
|
||||
--- there is a gap to fill in, iterate all not checked builds starting from latest
|
||||
while nr > self.lastChecked or nr == -1 do
|
||||
local r_status, r = self:_queryBuildbot(nr)
|
||||
local s
|
||||
|
||||
if not r_status then
|
||||
self.lastError = r
|
||||
return
|
||||
end
|
||||
if not r_status then
|
||||
self.lastError = r
|
||||
return
|
||||
end
|
||||
|
||||
s = self:_getBuildStatus(r)
|
||||
if not last_result then
|
||||
last_result = r
|
||||
end
|
||||
nr = r['number']
|
||||
assert(nr > 0)
|
||||
if last_pass_fail == 0 and (s == bs.OK or s == bs.FAILED) then
|
||||
last_pass_fail = nr
|
||||
end
|
||||
if s == bs.OK then --successful
|
||||
self.lastSuccessful = nr
|
||||
break;
|
||||
end
|
||||
nr = nr - 1
|
||||
iter_counter = iter_counter + 1
|
||||
if iter_counter > 10 then --check max last 10 builds when searching for successful build
|
||||
break;
|
||||
end
|
||||
end
|
||||
if last_pass_fail ~= 0 then
|
||||
self.lastChecked = last_pass_fail
|
||||
end
|
||||
if last_result then
|
||||
self.lastResult = last_result
|
||||
end
|
||||
s = self:_getBuildStatus(r)
|
||||
if not last_result then
|
||||
last_result = r
|
||||
end
|
||||
nr = r['number']
|
||||
assert(nr > 0)
|
||||
if last_pass_fail == 0 and (s == bs.OK or s == bs.FAILED) then
|
||||
last_pass_fail = nr
|
||||
end
|
||||
if s == bs.OK then --successful
|
||||
self.lastSuccessful = nr
|
||||
break;
|
||||
end
|
||||
nr = nr - 1
|
||||
iter_counter = iter_counter + 1
|
||||
if iter_counter > 10 then --check max last 10 builds when searching for successful build
|
||||
break;
|
||||
end
|
||||
end
|
||||
if last_pass_fail ~= 0 then
|
||||
self.lastChecked = last_pass_fail
|
||||
end
|
||||
if last_result then
|
||||
self.lastResult = last_result
|
||||
end
|
||||
end
|
||||
|
||||
function BB:getLastSuccessful()
|
||||
return self.lastSuccessful
|
||||
return self.lastSuccessful
|
||||
end
|
||||
|
||||
function BB:getCurrent()
|
||||
return self.lastResult['number']
|
||||
return self.lastResult['number']
|
||||
end
|
||||
|
||||
function BB:getCurrentStatus()
|
||||
return self:_getBuildStatus(self.lastResult)
|
||||
return self:_getBuildStatus(self.lastResult)
|
||||
end
|
||||
|
||||
function BB:getBuilder()
|
||||
return self.builder
|
||||
return self.builder
|
||||
end
|
||||
|
||||
function BB:getError()
|
||||
return self.lastError
|
||||
return self.lastError
|
||||
end
|
||||
|
||||
|
||||
local function getBuilderStatus(b)
|
||||
local s = "[" .. b:getBuilder()
|
||||
--check if json library was loaded correctly
|
||||
if not json_status then
|
||||
return s .. ".<span color=\"orange\">can't find libluaX.X-json</span>]"
|
||||
end
|
||||
local s = "[" .. b:getBuilder()
|
||||
--check if json library was loaded correctly
|
||||
if not json_status then
|
||||
return s .. ".<span color=\"orange\">can't find libluaX.X-json</span>]"
|
||||
end
|
||||
|
||||
local err = b:getError()
|
||||
if err then
|
||||
return s .. ".<span color=\"orange\">" .. err .. "</span>]"
|
||||
end
|
||||
local err = b:getError()
|
||||
if err then
|
||||
return s .. ".<span color=\"orange\">" .. err .. "</span>]"
|
||||
end
|
||||
|
||||
if b:getLastSuccessful() ~= 0 then
|
||||
success_build_nr_str = "<span color=\"green\">".. b:getLastSuccessful() .."</span>"
|
||||
else
|
||||
success_build_nr_str = "-"
|
||||
end
|
||||
if b:getLastSuccessful() ~= 0 then
|
||||
success_build_nr_str = "<span color=\"green\">".. b:getLastSuccessful() .."</span>"
|
||||
else
|
||||
success_build_nr_str = "-"
|
||||
end
|
||||
|
||||
local current_build_color = bc[b:getCurrentStatus()]
|
||||
current_build_nr_str = "<span color=\""..current_build_color.."\">"..b:getCurrent().."</span>"
|
||||
local current_build_color = bc[b:getCurrentStatus()]
|
||||
current_build_nr_str = "<span color=\""..current_build_color.."\">"..b:getCurrent().."</span>"
|
||||
|
||||
if current_build_color ~= "green" then
|
||||
s = s .. "." .. current_build_nr_str
|
||||
end
|
||||
return s .. "." .. success_build_nr_str .. "]"
|
||||
if current_build_color ~= "green" then
|
||||
s = s .. "." .. current_build_nr_str
|
||||
end
|
||||
return s .. "." .. success_build_nr_str .. "]"
|
||||
end
|
||||
|
||||
|
||||
-- {{{ Buildbot widget type
|
||||
local function worker(format, warg)
|
||||
if #bb == 0 then --fill up bb with builders when worker function is run for the first time
|
||||
for i,v in pairs(warg) do
|
||||
bb[#bb+1] = BB.create(v["url"], v["builder"])
|
||||
end
|
||||
if #bb == 0 then --fill up bb with builders when worker function is run for the first time
|
||||
for i,v in pairs(warg) do
|
||||
bb[#bb+1] = BB.create(v["url"], v["builder"])
|
||||
end
|
||||
end
|
||||
|
||||
local str = ""
|
||||
for i,v in pairs(bb) do
|
||||
v:refresh()
|
||||
str = str .. " " .. getBuilderStatus(v)
|
||||
end
|
||||
return {str .. " "}
|
||||
local str = ""
|
||||
for i,v in pairs(bb) do
|
||||
v:refresh()
|
||||
str = str .. " " .. getBuilderStatus(v)
|
||||
end
|
||||
return {str .. " "}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
setmetatable(_M, { __call = function(_, ...) return worker(...) end })
|
||||
|
||||
|
@ -25,48 +25,48 @@ local unit = { ["s"] = 1, ["kb"] = 2, ["mb"] = 2048 }
|
||||
|
||||
-- {{{ Disk I/O widget type
|
||||
local function worker(format, disk)
|
||||
if not disk then return end
|
||||
if not disk then return end
|
||||
|
||||
local disk_lines = { [disk] = {} }
|
||||
local disk_stats = helpers.pathtotable("/sys/block/" .. disk)
|
||||
local disk_lines = { [disk] = {} }
|
||||
local disk_stats = helpers.pathtotable("/sys/block/" .. disk)
|
||||
|
||||
if disk_stats.stat then
|
||||
local match = string.gmatch(disk_stats.stat, "[%s]+([%d]+)")
|
||||
for i = 1, 11 do -- Store disk stats
|
||||
table.insert(disk_lines[disk], match())
|
||||
end
|
||||
if disk_stats.stat then
|
||||
local match = string.gmatch(disk_stats.stat, "[%s]+([%d]+)")
|
||||
for i = 1, 11 do -- Store disk stats
|
||||
table.insert(disk_lines[disk], match())
|
||||
end
|
||||
end
|
||||
|
||||
-- Ensure tables are initialized correctly
|
||||
local diff_total = { [disk] = {} }
|
||||
if not disk_total[disk] then
|
||||
disk_usage[disk] = {}
|
||||
disk_total[disk] = {}
|
||||
-- Ensure tables are initialized correctly
|
||||
local diff_total = { [disk] = {} }
|
||||
if not disk_total[disk] then
|
||||
disk_usage[disk] = {}
|
||||
disk_total[disk] = {}
|
||||
|
||||
while #disk_total[disk] < #disk_lines[disk] do
|
||||
table.insert(disk_total[disk], 0)
|
||||
end
|
||||
while #disk_total[disk] < #disk_lines[disk] do
|
||||
table.insert(disk_total[disk], 0)
|
||||
end
|
||||
end
|
||||
|
||||
for i, v in ipairs(disk_lines[disk]) do
|
||||
-- Diskstats are absolute, substract our last reading
|
||||
diff_total[disk][i] = v - disk_total[disk][i]
|
||||
for i, v in ipairs(disk_lines[disk]) do
|
||||
-- Diskstats are absolute, substract our last reading
|
||||
diff_total[disk][i] = v - disk_total[disk][i]
|
||||
|
||||
-- Store totals
|
||||
disk_total[disk][i] = v
|
||||
end
|
||||
-- Store totals
|
||||
disk_total[disk][i] = v
|
||||
end
|
||||
|
||||
-- Calculate and store I/O
|
||||
helpers.uformat(disk_usage[disk], "read", diff_total[disk][3], unit)
|
||||
helpers.uformat(disk_usage[disk], "write", diff_total[disk][7], unit)
|
||||
helpers.uformat(disk_usage[disk], "total", diff_total[disk][7] + diff_total[disk][3], unit)
|
||||
-- Calculate and store I/O
|
||||
helpers.uformat(disk_usage[disk], "read", diff_total[disk][3], unit)
|
||||
helpers.uformat(disk_usage[disk], "write", diff_total[disk][7], unit)
|
||||
helpers.uformat(disk_usage[disk], "total", diff_total[disk][7] + diff_total[disk][3], unit)
|
||||
|
||||
-- Store I/O scheduler
|
||||
if disk_stats.queue and disk_stats.queue.scheduler then
|
||||
disk_usage[disk]["{sched}"] = string.gmatch(disk_stats.queue.scheduler, "%[([%a]+)%]")
|
||||
end
|
||||
-- Store I/O scheduler
|
||||
if disk_stats.queue and disk_stats.queue.scheduler then
|
||||
disk_usage[disk]["{sched}"] = string.gmatch(disk_stats.queue.scheduler, "%[([%a]+)%]")
|
||||
end
|
||||
|
||||
return disk_usage[disk]
|
||||
return disk_usage[disk]
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -20,28 +20,28 @@ local mpc = {}
|
||||
|
||||
-- {{{ MPC widget type
|
||||
local function worker(format, warg)
|
||||
-- Get data from mpd
|
||||
local f = io.popen("mpc")
|
||||
local np = f:read("*line")
|
||||
f:close()
|
||||
-- Get data from mpd
|
||||
local f = io.popen("mpc")
|
||||
local np = f:read("*line")
|
||||
f:close()
|
||||
|
||||
-- Not installed,
|
||||
if np == nil or -- off or stoppped.
|
||||
(string.find(np, "MPD_HOST") or string.find(np, "volume:"))
|
||||
then
|
||||
return {"Stopped"}
|
||||
-- Not installed,
|
||||
if np == nil or -- off or stoppped.
|
||||
(string.find(np, "MPD_HOST") or string.find(np, "volume:"))
|
||||
then
|
||||
return {"Stopped"}
|
||||
end
|
||||
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if warg then
|
||||
if type(warg) == "table" then
|
||||
np = helpers.scroll(np, warg[1], warg[2])
|
||||
else
|
||||
np = helpers.truncate(np, warg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if warg then
|
||||
if type(warg) == "table" then
|
||||
np = helpers.scroll(np, warg[1], warg[2])
|
||||
else
|
||||
np = helpers.truncate(np, warg)
|
||||
end
|
||||
end
|
||||
|
||||
return {helpers.escape(np)}
|
||||
return {helpers.escape(np)}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -25,114 +25,114 @@ local net = {}
|
||||
local nets = {}
|
||||
-- Variable definitions
|
||||
local unit = { ["b"] = 1, ["kb"] = 1024,
|
||||
["mb"] = 1024^2, ["gb"] = 1024^3
|
||||
["mb"] = 1024^2, ["gb"] = 1024^3
|
||||
}
|
||||
|
||||
-- {{{ Net widget type
|
||||
local function worker(format, tignorelist)
|
||||
local args = {}
|
||||
local tignore = {}
|
||||
local total_rx = 0
|
||||
local total_tx = 0
|
||||
local any_up = 0
|
||||
local args = {}
|
||||
local tignore = {}
|
||||
local total_rx = 0
|
||||
local total_tx = 0
|
||||
local any_up = 0
|
||||
|
||||
if not tignorelist then
|
||||
tignorelist = {"lo", "wmaster0"}
|
||||
end
|
||||
for k, i in pairs(tignorelist) do
|
||||
tignore[i] = true
|
||||
end
|
||||
if not tignorelist then
|
||||
tignorelist = {"lo", "wmaster0"}
|
||||
end
|
||||
for k, i in pairs(tignorelist) do
|
||||
tignore[i] = true
|
||||
end
|
||||
|
||||
-- Get NET stats
|
||||
for line in io.lines("/proc/net/dev") do
|
||||
-- Match wmaster0 as well as rt0 (multiple leading spaces)
|
||||
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
|
||||
if name ~= nil then
|
||||
-- Received bytes, first value after the name
|
||||
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
|
||||
-- Transmited bytes, 7 fields from end of the line
|
||||
local send = tonumber(string.match(line,
|
||||
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
|
||||
-- Get NET stats
|
||||
for line in io.lines("/proc/net/dev") do
|
||||
-- Match wmaster0 as well as rt0 (multiple leading spaces)
|
||||
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
|
||||
if name ~= nil then
|
||||
-- Received bytes, first value after the name
|
||||
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
|
||||
-- Transmited bytes, 7 fields from end of the line
|
||||
local send = tonumber(string.match(line,
|
||||
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
|
||||
|
||||
if not tignore[name] then
|
||||
total_rx = total_rx + recv
|
||||
total_tx = total_tx + send
|
||||
end
|
||||
if not tignore[name] then
|
||||
total_rx = total_rx + recv
|
||||
total_tx = total_tx + send
|
||||
end
|
||||
|
||||
helpers.uformat(args, name .. " rx", recv, unit)
|
||||
helpers.uformat(args, name .. " tx", send, unit)
|
||||
helpers.uformat(args, name .. " rx", recv, unit)
|
||||
helpers.uformat(args, name .. " tx", send, unit)
|
||||
|
||||
if nets[name] == nil then
|
||||
-- Default values on the first run
|
||||
nets[name] = {}
|
||||
|
||||
helpers.uformat(args, name .. " down", 0, unit)
|
||||
helpers.uformat(args, name .. " up", 0, unit)
|
||||
args["{"..name.." carrier}"] = 0
|
||||
|
||||
nets[name].time = os.time()
|
||||
else -- Net stats are absolute, substract our last reading
|
||||
local interval = os.time() - nets[name].time > 0 and
|
||||
os.time() - nets[name].time or 1
|
||||
nets[name].time = os.time()
|
||||
|
||||
local down = (recv - nets[name][1]) / interval
|
||||
local up = (send - nets[name][2]) / interval
|
||||
|
||||
helpers.uformat(args, name .. " down", down, unit)
|
||||
helpers.uformat(args, name .. " up", up, unit)
|
||||
|
||||
-- Carrier detection
|
||||
sysnet = helpers.pathtotable("/sys/class/net/" .. name)
|
||||
|
||||
if sysnet.carrier then
|
||||
ccarrier = tonumber(sysnet.carrier)
|
||||
|
||||
args["{"..name.." carrier}"] = ccarrier
|
||||
if ccarrier ~= 0 and not tignore[name] then
|
||||
any_up = 1
|
||||
end
|
||||
else
|
||||
args["{"..name.." carrier}"] = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Store totals
|
||||
nets[name][1] = recv
|
||||
nets[name][2] = send
|
||||
end
|
||||
end
|
||||
|
||||
helpers.uformat(args, "total rx", total_rx, unit)
|
||||
helpers.uformat(args, "total tx", total_tx, unit)
|
||||
|
||||
if nets["total"] == nil then
|
||||
if nets[name] == nil then
|
||||
-- Default values on the first run
|
||||
nets["total"] = {}
|
||||
nets[name] = {}
|
||||
|
||||
helpers.uformat(args, "total down", 0, unit)
|
||||
helpers.uformat(args, "total up", 0, unit)
|
||||
args["{total carrier}"] = 0
|
||||
helpers.uformat(args, name .. " down", 0, unit)
|
||||
helpers.uformat(args, name .. " up", 0, unit)
|
||||
args["{"..name.." carrier}"] = 0
|
||||
|
||||
nets["total"].time = os.time()
|
||||
else -- Net stats are absolute, substract our last reading
|
||||
local interval = os.time() - nets["total"].time > 0 and
|
||||
os.time() - nets["total"].time or 1
|
||||
nets["total"].time = os.time()
|
||||
nets[name].time = os.time()
|
||||
else -- Net stats are absolute, substract our last reading
|
||||
local interval = os.time() - nets[name].time > 0 and
|
||||
os.time() - nets[name].time or 1
|
||||
nets[name].time = os.time()
|
||||
|
||||
local down = (total_rx - nets["total"][1]) / interval
|
||||
local up = (total_tx - nets["total"][2]) / interval
|
||||
local down = (recv - nets[name][1]) / interval
|
||||
local up = (send - nets[name][2]) / interval
|
||||
|
||||
helpers.uformat(args, "total down", down, unit)
|
||||
helpers.uformat(args, "total up", up, unit)
|
||||
args["{total carrier}"] = any_up
|
||||
helpers.uformat(args, name .. " down", down, unit)
|
||||
helpers.uformat(args, name .. " up", up, unit)
|
||||
|
||||
-- Carrier detection
|
||||
sysnet = helpers.pathtotable("/sys/class/net/" .. name)
|
||||
|
||||
if sysnet.carrier then
|
||||
ccarrier = tonumber(sysnet.carrier)
|
||||
|
||||
args["{"..name.." carrier}"] = ccarrier
|
||||
if ccarrier ~= 0 and not tignore[name] then
|
||||
any_up = 1
|
||||
end
|
||||
else
|
||||
args["{"..name.." carrier}"] = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Store totals
|
||||
nets[name][1] = recv
|
||||
nets[name][2] = send
|
||||
end
|
||||
end
|
||||
|
||||
-- Store totals
|
||||
nets["total"][1] = total_rx
|
||||
nets["total"][2] = total_tx
|
||||
helpers.uformat(args, "total rx", total_rx, unit)
|
||||
helpers.uformat(args, "total tx", total_tx, unit)
|
||||
|
||||
return args
|
||||
if nets["total"] == nil then
|
||||
-- Default values on the first run
|
||||
nets["total"] = {}
|
||||
|
||||
helpers.uformat(args, "total down", 0, unit)
|
||||
helpers.uformat(args, "total up", 0, unit)
|
||||
args["{total carrier}"] = 0
|
||||
|
||||
nets["total"].time = os.time()
|
||||
else -- Net stats are absolute, substract our last reading
|
||||
local interval = os.time() - nets["total"].time > 0 and
|
||||
os.time() - nets["total"].time or 1
|
||||
nets["total"].time = os.time()
|
||||
|
||||
local down = (total_rx - nets["total"][1]) / interval
|
||||
local up = (total_tx - nets["total"][2]) / interval
|
||||
|
||||
helpers.uformat(args, "total down", down, unit)
|
||||
helpers.uformat(args, "total up", up, unit)
|
||||
args["{total carrier}"] = any_up
|
||||
end
|
||||
|
||||
-- Store totals
|
||||
nets["total"][1] = total_rx
|
||||
nets["total"][2] = total_tx
|
||||
|
||||
return args
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -17,18 +17,18 @@ local netcfg = {}
|
||||
|
||||
-- {{{ Netcfg widget type
|
||||
local function worker(format)
|
||||
-- Initialize counters
|
||||
local profiles = {}
|
||||
-- Initialize counters
|
||||
local profiles = {}
|
||||
|
||||
local f = io.popen("ls -1 /var/run/network/profiles")
|
||||
for line in f:lines() do
|
||||
if line ~= nil then
|
||||
table.insert(profiles, line)
|
||||
end
|
||||
local f = io.popen("ls -1 /var/run/network/profiles")
|
||||
for line in f:lines() do
|
||||
if line ~= nil then
|
||||
table.insert(profiles, line)
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
return profiles
|
||||
return profiles
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -18,24 +18,24 @@ local nvsmi = {}
|
||||
|
||||
-- {{{ GPU Information widget type
|
||||
local function worker(format, warg)
|
||||
-- Fallback to querying first device
|
||||
if not warg then warg = "0" end
|
||||
-- Fallback to querying first device
|
||||
if not warg then warg = "0" end
|
||||
|
||||
-- Get data from smi
|
||||
-- * Todo: support more; MEMORY,UTILIZATION,ECC,POWER,CLOCK,COMPUTE,PIDS,PERFORMANCE
|
||||
local f = io.popen("nvidia-smi -q -d TEMPERATURE -i " .. warg)
|
||||
local smi = f:read("*all")
|
||||
f:close()
|
||||
-- Get data from smi
|
||||
-- * Todo: support more; MEMORY,UTILIZATION,ECC,POWER,CLOCK,COMPUTE,PIDS,PERFORMANCE
|
||||
local f = io.popen("nvidia-smi -q -d TEMPERATURE -i " .. warg)
|
||||
local smi = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Not installed
|
||||
if smi == nil then return {0} end
|
||||
-- Not installed
|
||||
if smi == nil then return {0} end
|
||||
|
||||
-- Get temperature information
|
||||
local _thermal = string.match(smi, "Gpu[%s]+:[%s]([%d]+)[%s]C")
|
||||
-- Handle devices without data
|
||||
if _thermal == nil then return {0} end
|
||||
-- Get temperature information
|
||||
local _thermal = string.match(smi, "Gpu[%s]+:[%s]([%d]+)[%s]C")
|
||||
-- Handle devices without data
|
||||
if _thermal == nil then return {0} end
|
||||
|
||||
return {tonumber(_thermal)}
|
||||
return {tonumber(_thermal)}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -9,8 +9,8 @@ local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { match = string.match }
|
||||
local math = {
|
||||
ceil = math.ceil,
|
||||
floor = math.floor
|
||||
ceil = math.ceil,
|
||||
floor = math.floor
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -23,71 +23,71 @@ local openweather = {}
|
||||
-- Initialize function tables
|
||||
local _wdirs = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" }
|
||||
local _wdata = {
|
||||
["{city}"] = "N/A",
|
||||
["{wind deg}"] = "N/A",
|
||||
["{wind aim}"] = "N/A",
|
||||
["{wind mps}"] = "N/A",
|
||||
["{wind kmh}"] = "N/A",
|
||||
["{sky}"] = "N/A",
|
||||
["{weather}"] = "N/A",
|
||||
["{temp c}"] = "N/A",
|
||||
["{humid}"] = "N/A",
|
||||
["{press}"] = "N/A"
|
||||
["{city}"] = "N/A",
|
||||
["{wind deg}"] = "N/A",
|
||||
["{wind aim}"] = "N/A",
|
||||
["{wind mps}"] = "N/A",
|
||||
["{wind kmh}"] = "N/A",
|
||||
["{sky}"] = "N/A",
|
||||
["{weather}"] = "N/A",
|
||||
["{temp c}"] = "N/A",
|
||||
["{humid}"] = "N/A",
|
||||
["{press}"] = "N/A"
|
||||
}
|
||||
|
||||
-- {{{ Openweather widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Get weather forceast using the city ID code, from:
|
||||
-- * OpenWeatherMap.org
|
||||
local openweather = "http://api.openweathermap.org/data/2.5/weather?id="..warg.."&mode=json&units=metric"
|
||||
local f = io.popen("curl --connect-timeout 1 -fsm 3 '"..openweather.."'")
|
||||
local ws = f:read("*all")
|
||||
f:close()
|
||||
-- Get weather forceast using the city ID code, from:
|
||||
-- * OpenWeatherMap.org
|
||||
local openweather = "http://api.openweathermap.org/data/2.5/weather?id="..warg.."&mode=json&units=metric"
|
||||
local f = io.popen("curl --connect-timeout 1 -fsm 3 '"..openweather.."'")
|
||||
local ws = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Check if there was a timeout or a problem with the station
|
||||
if ws == nil then return _wdata end
|
||||
-- Check if there was a timeout or a problem with the station
|
||||
if ws == nil then return _wdata end
|
||||
|
||||
_wdata["{city}"] = -- City name
|
||||
string.match(ws, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
|
||||
_wdata["{wind deg}"] = -- Wind degrees
|
||||
string.match(ws, '"deg":([%d]+)') or _wdata["{wind deg}"]
|
||||
_wdata["{wind mps}"] = -- Wind speed in meters per second
|
||||
string.match(ws, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
|
||||
_wdata["{sky}"] = -- Sky conditions
|
||||
string.match(ws, '"main":"([%a]+)"') or _wdata["{sky}"]
|
||||
_wdata["{weather}"] = -- Weather description
|
||||
string.match(ws, '"description":"([%a%s]+)"') or _wdata["{weather}"]
|
||||
_wdata["{temp c}"] = -- Temperature in celsius
|
||||
string.match(ws, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
|
||||
_wdata["{humid}"] = -- Relative humidity in percent
|
||||
string.match(ws, '"humidity":([%d]+)') or _wdata["{humid}"]
|
||||
_wdata["{press}"] = -- Pressure in hPa
|
||||
string.match(ws, '"pressure":([%d%.]+)') or _wdata["{press}"]
|
||||
_wdata["{city}"] = -- City name
|
||||
string.match(ws, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
|
||||
_wdata["{wind deg}"] = -- Wind degrees
|
||||
string.match(ws, '"deg":([%d]+)') or _wdata["{wind deg}"]
|
||||
_wdata["{wind mps}"] = -- Wind speed in meters per second
|
||||
string.match(ws, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
|
||||
_wdata["{sky}"] = -- Sky conditions
|
||||
string.match(ws, '"main":"([%a]+)"') or _wdata["{sky}"]
|
||||
_wdata["{weather}"] = -- Weather description
|
||||
string.match(ws, '"description":"([%a%s]+)"') or _wdata["{weather}"]
|
||||
_wdata["{temp c}"] = -- Temperature in celsius
|
||||
string.match(ws, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
|
||||
_wdata["{humid}"] = -- Relative humidity in percent
|
||||
string.match(ws, '"humidity":([%d]+)') or _wdata["{humid}"]
|
||||
_wdata["{press}"] = -- Pressure in hPa
|
||||
string.match(ws, '"pressure":([%d%.]+)') or _wdata["{press}"]
|
||||
|
||||
-- Wind speed in km/h
|
||||
if _wdata["{wind mps}"] ~= "N/A" then
|
||||
_wdata["{wind mps}"] = math.floor(tonumber(_wdata["{wind mps}"]) + .5)
|
||||
_wdata["{wind kmh}"] = math.ceil(_wdata["{wind mps}"] * 3.6)
|
||||
end -- Temperature in °C
|
||||
if _wdata["{temp c}"] ~= "N/A" then
|
||||
_wdata["{temp c}"] = math.floor(tonumber(_wdata["{temp c}"]) + .5)
|
||||
end -- Calculate wind direction
|
||||
if _wdata["{wind deg}"] ~= "N/A" then
|
||||
_wdata["{wind deg}"] = tonumber(_wdata["{wind deg}"])
|
||||
-- Wind speed in km/h
|
||||
if _wdata["{wind mps}"] ~= "N/A" then
|
||||
_wdata["{wind mps}"] = math.floor(tonumber(_wdata["{wind mps}"]) + .5)
|
||||
_wdata["{wind kmh}"] = math.ceil(_wdata["{wind mps}"] * 3.6)
|
||||
end -- Temperature in °C
|
||||
if _wdata["{temp c}"] ~= "N/A" then
|
||||
_wdata["{temp c}"] = math.floor(tonumber(_wdata["{temp c}"]) + .5)
|
||||
end -- Calculate wind direction
|
||||
if _wdata["{wind deg}"] ~= "N/A" then
|
||||
_wdata["{wind deg}"] = tonumber(_wdata["{wind deg}"])
|
||||
|
||||
-- Lua tables start at [1]
|
||||
if (_wdata["{wind deg}"] / 45)%1 == 0 then
|
||||
_wdata["{wind aim}"] = _wdirs[_wdata["{wind deg}"] / 45 + 1]
|
||||
else
|
||||
_wdata["{wind aim}"] =
|
||||
_wdirs[math.ceil(_wdata["{wind deg}"] / 45) + 1]..
|
||||
_wdirs[math.floor(_wdata["{wind deg}"] / 45) + 1]
|
||||
end
|
||||
-- Lua tables start at [1]
|
||||
if (_wdata["{wind deg}"] / 45)%1 == 0 then
|
||||
_wdata["{wind aim}"] = _wdirs[_wdata["{wind deg}"] / 45 + 1]
|
||||
else
|
||||
_wdata["{wind aim}"] =
|
||||
_wdirs[math.ceil(_wdata["{wind deg}"] / 45) + 1]..
|
||||
_wdirs[math.floor(_wdata["{wind deg}"] / 45) + 1]
|
||||
end
|
||||
end
|
||||
|
||||
return _wdata
|
||||
return _wdata
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -18,36 +18,36 @@ local ossvol = {}
|
||||
|
||||
-- {{{ Volume widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
local mixer_state = {
|
||||
["on"] = "♫", -- "",
|
||||
["off"] = "♩" -- "M"
|
||||
}
|
||||
local mixer_state = {
|
||||
["on"] = "♫", -- "",
|
||||
["off"] = "♩" -- "M"
|
||||
}
|
||||
|
||||
-- Get mixer control contents
|
||||
local f = io.popen("ossmix -c")
|
||||
local mixer = f:read("*all")
|
||||
f:close()
|
||||
-- Get mixer control contents
|
||||
local f = io.popen("ossmix -c")
|
||||
local mixer = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Capture mixer control state
|
||||
local volu = tonumber(string.match(mixer, warg .. "[%s]([%d%.]+)"))/0.25
|
||||
local mute = string.match(mixer, "vol%.mute[%s]([%a]+)")
|
||||
-- Handle mixers without data
|
||||
if volu == nil then
|
||||
return {0, mixer_state["off"]}
|
||||
end
|
||||
-- Capture mixer control state
|
||||
local volu = tonumber(string.match(mixer, warg .. "[%s]([%d%.]+)"))/0.25
|
||||
local mute = string.match(mixer, "vol%.mute[%s]([%a]+)")
|
||||
-- Handle mixers without data
|
||||
if volu == nil then
|
||||
return {0, mixer_state["off"]}
|
||||
end
|
||||
|
||||
-- Handle mixers without mute
|
||||
if mute == "OFF" and volu == "0"
|
||||
-- Handle mixers that are muted
|
||||
or mute == "ON" then
|
||||
mute = mixer_state["off"]
|
||||
else
|
||||
mute = mixer_state["on"]
|
||||
end
|
||||
-- Handle mixers without mute
|
||||
if mute == "OFF" and volu == "0"
|
||||
-- Handle mixers that are muted
|
||||
or mute == "ON" then
|
||||
mute = mixer_state["off"]
|
||||
else
|
||||
mute = mixer_state["on"]
|
||||
end
|
||||
|
||||
return {volu, mute}
|
||||
return {volu, mute}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -25,30 +25,30 @@ local pop = {}
|
||||
|
||||
-- {{{ POP3 count widget type
|
||||
local function worker(format, warg)
|
||||
if not sock_avail or (not warg or #warg ~= 4) then
|
||||
return {"N/A"}
|
||||
end
|
||||
if not sock_avail or (not warg or #warg ~= 4) then
|
||||
return {"N/A"}
|
||||
end
|
||||
|
||||
local host, port = warg[1], tonumber(warg[2])
|
||||
local user, pass = warg[3], warg[4]
|
||||
local host, port = warg[1], tonumber(warg[2])
|
||||
local user, pass = warg[3], warg[4]
|
||||
|
||||
local client = socket.tcp()
|
||||
client:settimeout(3)
|
||||
client:connect(host, port)
|
||||
client:receive("*l")
|
||||
client:send("USER " .. user .. "\r\n")
|
||||
client:receive("*l")
|
||||
client:send("PASS " .. pass .. "\r\n")
|
||||
client:receive("*l")
|
||||
client:send("STAT" .. "\r\n")
|
||||
local response = client:receive("*l")
|
||||
client:close()
|
||||
local client = socket.tcp()
|
||||
client:settimeout(3)
|
||||
client:connect(host, port)
|
||||
client:receive("*l")
|
||||
client:send("USER " .. user .. "\r\n")
|
||||
client:receive("*l")
|
||||
client:send("PASS " .. pass .. "\r\n")
|
||||
client:receive("*l")
|
||||
client:send("STAT" .. "\r\n")
|
||||
local response = client:receive("*l")
|
||||
client:close()
|
||||
|
||||
if response:find("%+OK") then
|
||||
response = response:match("%+OK (%d+)")
|
||||
end
|
||||
if response:find("%+OK") then
|
||||
response = response:match("%+OK (%d+)")
|
||||
end
|
||||
|
||||
return {response}
|
||||
return {response}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -12,13 +12,13 @@ local setmetatable = setmetatable
|
||||
local os = { execute = os.execute }
|
||||
local table = { insert = table.insert }
|
||||
local string = {
|
||||
find = string.find,
|
||||
match = string.match,
|
||||
format = string.format,
|
||||
gmatch = string.gmatch
|
||||
find = string.find,
|
||||
match = string.match,
|
||||
format = string.format,
|
||||
gmatch = string.gmatch
|
||||
}
|
||||
local math = {
|
||||
floor = math.floor
|
||||
floor = math.floor
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -29,36 +29,36 @@ local pulse = {}
|
||||
|
||||
-- {{{ Helper function
|
||||
local function pacmd(args)
|
||||
local f = io.popen("pacmd "..args)
|
||||
if f == nil then
|
||||
return nil
|
||||
else
|
||||
local line = f:read("*all")
|
||||
f:close()
|
||||
return line
|
||||
end
|
||||
local f = io.popen("pacmd "..args)
|
||||
if f == nil then
|
||||
return nil
|
||||
else
|
||||
local line = f:read("*all")
|
||||
f:close()
|
||||
return line
|
||||
end
|
||||
end
|
||||
|
||||
local function escape(text)
|
||||
local special_chars = { ["."] = "%.", ["-"] = "%-" }
|
||||
return text:gsub("[%.%-]", special_chars)
|
||||
local special_chars = { ["."] = "%.", ["-"] = "%-" }
|
||||
return text:gsub("[%.%-]", special_chars)
|
||||
end
|
||||
|
||||
local cached_sinks = {}
|
||||
local function get_sink_name(sink)
|
||||
if type(sink) == "string" then return sink end
|
||||
-- avoid nil keys
|
||||
local key = sink or 1
|
||||
-- Cache requests
|
||||
if not cached_sinks[key] then
|
||||
local line = pacmd("list-sinks")
|
||||
if line == nil then return nil end
|
||||
for s in string.gmatch(line, "name: <(.-)>") do
|
||||
table.insert(cached_sinks, s)
|
||||
end
|
||||
if type(sink) == "string" then return sink end
|
||||
-- avoid nil keys
|
||||
local key = sink or 1
|
||||
-- Cache requests
|
||||
if not cached_sinks[key] then
|
||||
local line = pacmd("list-sinks")
|
||||
if line == nil then return nil end
|
||||
for s in string.gmatch(line, "name: <(.-)>") do
|
||||
table.insert(cached_sinks, s)
|
||||
end
|
||||
end
|
||||
|
||||
return cached_sinks[key]
|
||||
return cached_sinks[key]
|
||||
end
|
||||
|
||||
|
||||
@ -66,55 +66,55 @@ end
|
||||
|
||||
-- {{{ Pulseaudio widget type
|
||||
local function worker(format, sink)
|
||||
sink = get_sink_name(sink)
|
||||
if sink == nil then return {0, "unknown"} end
|
||||
sink = get_sink_name(sink)
|
||||
if sink == nil then return {0, "unknown"} end
|
||||
|
||||
-- Get sink data
|
||||
local data = pacmd("dump")
|
||||
if sink == nil then return {0, "unknown"} end
|
||||
-- Get sink data
|
||||
local data = pacmd("dump")
|
||||
if sink == nil then return {0, "unknown"} end
|
||||
|
||||
-- If mute return 0 (not "Mute") so we don't break progressbars
|
||||
if string.find(data,"set%-sink%-mute "..escape(sink).." yes") then
|
||||
return {0, "off"}
|
||||
end
|
||||
-- If mute return 0 (not "Mute") so we don't break progressbars
|
||||
if string.find(data,"set%-sink%-mute "..escape(sink).." yes") then
|
||||
return {0, "off"}
|
||||
end
|
||||
|
||||
local vol = tonumber(string.match(data, "set%-sink%-volume "..escape(sink).." (0x[%x]+)"))
|
||||
if vol == nil then vol = 0 end
|
||||
local vol = tonumber(string.match(data, "set%-sink%-volume "..escape(sink).." (0x[%x]+)"))
|
||||
if vol == nil then vol = 0 end
|
||||
|
||||
return { math.floor(vol/0x10000*100), "on"}
|
||||
return { math.floor(vol/0x10000*100), "on"}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Volume control helper
|
||||
function pulse.add(percent, sink)
|
||||
sink = get_sink_name(sink)
|
||||
if sink == nil then return end
|
||||
sink = get_sink_name(sink)
|
||||
if sink == nil then return end
|
||||
|
||||
local data = pacmd("dump")
|
||||
local data = pacmd("dump")
|
||||
|
||||
local pattern = "set%-sink%-volume "..escape(sink).." (0x[%x]+)"
|
||||
local initial_vol = tonumber(string.match(data, pattern))
|
||||
local pattern = "set%-sink%-volume "..escape(sink).." (0x[%x]+)"
|
||||
local initial_vol = tonumber(string.match(data, pattern))
|
||||
|
||||
local vol = initial_vol + percent/100*0x10000
|
||||
if vol > 0x10000 then vol = 0x10000 end
|
||||
if vol < 0 then vol = 0 end
|
||||
local vol = initial_vol + percent/100*0x10000
|
||||
if vol > 0x10000 then vol = 0x10000 end
|
||||
if vol < 0 then vol = 0 end
|
||||
|
||||
local cmd = string.format("pacmd set-sink-volume %s 0x%x >/dev/null", sink, vol)
|
||||
return os.execute(cmd)
|
||||
local cmd = string.format("pacmd set-sink-volume %s 0x%x >/dev/null", sink, vol)
|
||||
return os.execute(cmd)
|
||||
end
|
||||
|
||||
function pulse.toggle(sink)
|
||||
sink = get_sink_name(sink)
|
||||
if sink == nil then return end
|
||||
sink = get_sink_name(sink)
|
||||
if sink == nil then return end
|
||||
|
||||
local data = pacmd("dump")
|
||||
local pattern = "set%-sink%-mute "..escape(sink).." (%a%a%a?)"
|
||||
local mute = string.match(data, pattern)
|
||||
local data = pacmd("dump")
|
||||
local pattern = "set%-sink%-mute "..escape(sink).." (%a%a%a?)"
|
||||
local mute = string.match(data, pattern)
|
||||
|
||||
-- 0 to enable a sink or 1 to mute it.
|
||||
local state = { yes = 0, no = 1}
|
||||
local cmd = string.format("pacmd set-sink-mute %s %d", sink, state[mute])
|
||||
return os.execute(cmd)
|
||||
-- 0 to enable a sink or 1 to mute it.
|
||||
local state = { yes = 0, no = 1}
|
||||
local cmd = string.format("pacmd set-sink-mute %s %d", sink, state[mute])
|
||||
return os.execute(cmd)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -20,48 +20,48 @@ local rss = {}
|
||||
|
||||
-- {{{ RSS widget type
|
||||
local function worker(format, input)
|
||||
-- input: * feed - feed url
|
||||
-- * object - entity to look for (typically: 'item')
|
||||
-- * fields - fields to read (example: 'link', 'title', 'description')
|
||||
-- output: * count - number of entities found
|
||||
-- * one table for each field, containing wanted values
|
||||
local feed = input.feed
|
||||
local object = input.object
|
||||
local fields = input.fields
|
||||
-- input: * feed - feed url
|
||||
-- * object - entity to look for (typically: 'item')
|
||||
-- * fields - fields to read (example: 'link', 'title', 'description')
|
||||
-- output: * count - number of entities found
|
||||
-- * one table for each field, containing wanted values
|
||||
local feed = input.feed
|
||||
local object = input.object
|
||||
local fields = input.fields
|
||||
|
||||
-- Initialise tables
|
||||
local out = {}
|
||||
-- Initialise tables
|
||||
local out = {}
|
||||
|
||||
for _, v in pairs(fields) do
|
||||
out[v] = {}
|
||||
end
|
||||
|
||||
-- Initialise variables
|
||||
local ob = nil
|
||||
local i,j,k = 1, 1, 0
|
||||
local curl = "curl -A 'Mozilla/4.0' -fsm 5 --connect-timeout 3 "
|
||||
|
||||
-- Get the feed
|
||||
local f = io.popen(curl .. '"' .. feed .. '"')
|
||||
local feed = f:read("*all")
|
||||
f:close()
|
||||
|
||||
while true do
|
||||
i, j, ob = feed.find(feed, "<" .. object .. ">(.-)</" .. object .. ">", i)
|
||||
if not ob then break end
|
||||
|
||||
for _, v in pairs(fields) do
|
||||
out[v] = {}
|
||||
out[v][k] = ob:match("<" .. v .. ">(.*)</" .. v .. ">")
|
||||
end
|
||||
|
||||
-- Initialise variables
|
||||
local ob = nil
|
||||
local i,j,k = 1, 1, 0
|
||||
local curl = "curl -A 'Mozilla/4.0' -fsm 5 --connect-timeout 3 "
|
||||
k = k+1
|
||||
i = j+1
|
||||
end
|
||||
|
||||
-- Get the feed
|
||||
local f = io.popen(curl .. '"' .. feed .. '"')
|
||||
local feed = f:read("*all")
|
||||
f:close()
|
||||
-- Update the entity count
|
||||
out.count = k
|
||||
|
||||
while true do
|
||||
i, j, ob = feed.find(feed, "<" .. object .. ">(.-)</" .. object .. ">", i)
|
||||
if not ob then break end
|
||||
|
||||
for _, v in pairs(fields) do
|
||||
out[v][k] = ob:match("<" .. v .. ">(.*)</" .. v .. ">")
|
||||
end
|
||||
|
||||
k = k+1
|
||||
i = j+1
|
||||
end
|
||||
|
||||
-- Update the entity count
|
||||
out.count = k
|
||||
|
||||
return out
|
||||
return out
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -9,8 +9,8 @@ local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local table = { insert = table.insert }
|
||||
local string = {
|
||||
gsub = string.gsub,
|
||||
match = string.match
|
||||
gsub = string.gsub,
|
||||
match = string.match
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -22,47 +22,47 @@ local sensors = {}
|
||||
|
||||
-- {{{ Split helper function
|
||||
local function datasplit(str)
|
||||
-- Splitting strings into associative array
|
||||
-- with some magic to get the values right.
|
||||
str = string.gsub(str, "\n", ":")
|
||||
-- Splitting strings into associative array
|
||||
-- with some magic to get the values right.
|
||||
str = string.gsub(str, "\n", ":")
|
||||
|
||||
local tbl = {}
|
||||
string.gsub(str, "([^:]*)", function (v)
|
||||
if string.match(v, ".") then
|
||||
table.insert(tbl, v)
|
||||
end
|
||||
end)
|
||||
local tbl = {}
|
||||
string.gsub(str, "([^:]*)", function (v)
|
||||
if string.match(v, ".") then
|
||||
table.insert(tbl, v)
|
||||
end
|
||||
end)
|
||||
|
||||
local assoc = {}
|
||||
for c = 1, #tbl, 2 do
|
||||
local k = string.gsub(tbl[c], ".*_", "")
|
||||
local v = tonumber(string.match(tbl[c+1], "[%d]+"))
|
||||
assoc[k] = v
|
||||
end
|
||||
local assoc = {}
|
||||
for c = 1, #tbl, 2 do
|
||||
local k = string.gsub(tbl[c], ".*_", "")
|
||||
local v = tonumber(string.match(tbl[c+1], "[%d]+"))
|
||||
assoc[k] = v
|
||||
end
|
||||
|
||||
return assoc
|
||||
return assoc
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Sensors widget type
|
||||
local function worker(format, warg)
|
||||
-- Get data from all sensors
|
||||
local f = io.popen("LANG=C sensors -uA")
|
||||
local lm_sensors = f:read("*all")
|
||||
f:close()
|
||||
-- Get data from all sensors
|
||||
local f = io.popen("LANG=C sensors -uA")
|
||||
local lm_sensors = f:read("*all")
|
||||
f:close()
|
||||
|
||||
local sensor_data = string.gsub(
|
||||
string.match(lm_sensors, warg..":\n(%s%s.-)\n[^ ]"), " ", "")
|
||||
local sensor_data = string.gsub(
|
||||
string.match(lm_sensors, warg..":\n(%s%s.-)\n[^ ]"), " ", "")
|
||||
|
||||
-- One of: crit, max
|
||||
local divisor = "crit"
|
||||
local s_data = datasplit(sensor_data)
|
||||
-- One of: crit, max
|
||||
local divisor = "crit"
|
||||
local s_data = datasplit(sensor_data)
|
||||
|
||||
if s_data[divisor] and s_data[divisor] > 0 then
|
||||
s_data.percent = s_data.input / s_data[divisor] * 100
|
||||
end
|
||||
if s_data[divisor] and s_data[divisor] > 0 then
|
||||
s_data.percent = s_data.input / s_data[divisor] * 100
|
||||
end
|
||||
|
||||
return {s_data.input, tonumber(s_data.percent)}
|
||||
return {s_data.input, tonumber(s_data.percent)}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -13,8 +13,8 @@ local tonumber = tonumber
|
||||
local timer = (type(timer) == 'table' and timer or require("gears.timer"))
|
||||
local os = { time = os.time }
|
||||
local table = {
|
||||
insert = table.insert,
|
||||
remove = table.remove
|
||||
insert = table.insert,
|
||||
remove = table.remove
|
||||
}
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
@ -34,108 +34,108 @@ local widget_cache = {}
|
||||
-- {{{ Local functions
|
||||
-- {{{ Update a widget
|
||||
local function update(widget, reg, disablecache)
|
||||
-- Check if there are any equal widgets
|
||||
if reg == nil then
|
||||
for w, i in pairs(registered) do
|
||||
if w == widget then
|
||||
for _, r in pairs(i) do
|
||||
update(w, r, disablecache)
|
||||
end
|
||||
end
|
||||
-- Check if there are any equal widgets
|
||||
if reg == nil then
|
||||
for w, i in pairs(registered) do
|
||||
if w == widget then
|
||||
for _, r in pairs(i) do
|
||||
update(w, r, disablecache)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local t = os.time()
|
||||
local data = {}
|
||||
return
|
||||
end
|
||||
|
||||
-- Check for chached output newer than the last update
|
||||
if widget_cache[reg.wtype] ~= nil then
|
||||
local c = widget_cache[reg.wtype]
|
||||
local t = os.time()
|
||||
local data = {}
|
||||
|
||||
if (c.time == nil or c.time <= t-reg.timer) or disablecache then
|
||||
c.time, c.data = t, reg.wtype(reg.format, reg.warg)
|
||||
end
|
||||
-- Check for chached output newer than the last update
|
||||
if widget_cache[reg.wtype] ~= nil then
|
||||
local c = widget_cache[reg.wtype]
|
||||
|
||||
data = c.data
|
||||
else
|
||||
data = reg.wtype and reg.wtype(reg.format, reg.warg)
|
||||
if (c.time == nil or c.time <= t-reg.timer) or disablecache then
|
||||
c.time, c.data = t, reg.wtype(reg.format, reg.warg)
|
||||
end
|
||||
|
||||
if type(data) == "table" then
|
||||
if type(reg.format) == "string" then
|
||||
data = helpers.format(reg.format, data)
|
||||
elseif type(reg.format) == "function" then
|
||||
data = reg.format(widget, data)
|
||||
end
|
||||
end
|
||||
data = c.data
|
||||
else
|
||||
data = reg.wtype and reg.wtype(reg.format, reg.warg)
|
||||
end
|
||||
|
||||
if widget.add_value ~= nil then
|
||||
widget:add_value(tonumber(data) and tonumber(data)/100)
|
||||
elseif widget.set_value ~= nil then
|
||||
widget:set_value(tonumber(data) and tonumber(data)/100)
|
||||
elseif widget.set_markup ~= nil then
|
||||
widget:set_markup(data)
|
||||
else
|
||||
widget.text = data
|
||||
if type(data) == "table" then
|
||||
if type(reg.format) == "string" then
|
||||
data = helpers.format(reg.format, data)
|
||||
elseif type(reg.format) == "function" then
|
||||
data = reg.format(widget, data)
|
||||
end
|
||||
end
|
||||
|
||||
return data
|
||||
if widget.add_value ~= nil then
|
||||
widget:add_value(tonumber(data) and tonumber(data)/100)
|
||||
elseif widget.set_value ~= nil then
|
||||
widget:set_value(tonumber(data) and tonumber(data)/100)
|
||||
elseif widget.set_markup ~= nil then
|
||||
widget:set_markup(data)
|
||||
else
|
||||
widget.text = data
|
||||
end
|
||||
|
||||
return data
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Register from reg object
|
||||
local function regregister(reg)
|
||||
if not reg.running then
|
||||
if registered[reg.widget] == nil then
|
||||
registered[reg.widget] = {}
|
||||
table.insert(registered[reg.widget], reg)
|
||||
else
|
||||
local already = false
|
||||
if not reg.running then
|
||||
if registered[reg.widget] == nil then
|
||||
registered[reg.widget] = {}
|
||||
table.insert(registered[reg.widget], reg)
|
||||
else
|
||||
local already = false
|
||||
|
||||
for w, i in pairs(registered) do
|
||||
if w == reg.widget then
|
||||
for _, v in pairs(i) do
|
||||
if v == reg then
|
||||
already = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if already then
|
||||
break
|
||||
end
|
||||
end
|
||||
for w, i in pairs(registered) do
|
||||
if w == reg.widget then
|
||||
for _, v in pairs(i) do
|
||||
if v == reg then
|
||||
already = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not already then
|
||||
table.insert(registered[reg.widget], reg)
|
||||
end
|
||||
if already then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Start the timer
|
||||
if reg.timer > 0 then
|
||||
local tm = timers[reg.timer] and timers[reg.timer].timer
|
||||
tm = tm or timer({ timeout = reg.timer })
|
||||
if tm.connect_signal then
|
||||
tm:connect_signal("timeout", reg.update)
|
||||
else
|
||||
tm:add_signal("timeout", reg.update)
|
||||
end
|
||||
if not timers[reg.timer] then
|
||||
timers[reg.timer] = { timer = tm, refs = 1 }
|
||||
else
|
||||
timers[reg.timer].refs = timers[reg.timer].refs + 1
|
||||
end
|
||||
if not tm.started then
|
||||
tm:start()
|
||||
end
|
||||
-- Initial update
|
||||
reg.update()
|
||||
end
|
||||
reg.running = true
|
||||
if not already then
|
||||
table.insert(registered[reg.widget], reg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Start the timer
|
||||
if reg.timer > 0 then
|
||||
local tm = timers[reg.timer] and timers[reg.timer].timer
|
||||
tm = tm or timer({ timeout = reg.timer })
|
||||
if tm.connect_signal then
|
||||
tm:connect_signal("timeout", reg.update)
|
||||
else
|
||||
tm:add_signal("timeout", reg.update)
|
||||
end
|
||||
if not timers[reg.timer] then
|
||||
timers[reg.timer] = { timer = tm, refs = 1 }
|
||||
else
|
||||
timers[reg.timer].refs = timers[reg.timer].refs + 1
|
||||
end
|
||||
if not tm.started then
|
||||
tm:start()
|
||||
end
|
||||
-- Initial update
|
||||
reg.update()
|
||||
end
|
||||
reg.running = true
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
@ -144,120 +144,120 @@ end
|
||||
-- {{{ Global functions
|
||||
-- {{{ Register a widget
|
||||
function vicious.register(widget, wtype, format, timer, warg)
|
||||
local widget = widget
|
||||
local reg = {
|
||||
-- Set properties
|
||||
wtype = wtype,
|
||||
format = format,
|
||||
timer = timer,
|
||||
warg = warg,
|
||||
widget = widget,
|
||||
}
|
||||
-- Set functions
|
||||
reg.update = function ()
|
||||
update(widget, reg)
|
||||
end
|
||||
local widget = widget
|
||||
local reg = {
|
||||
-- Set properties
|
||||
wtype = wtype,
|
||||
format = format,
|
||||
timer = timer,
|
||||
warg = warg,
|
||||
widget = widget,
|
||||
}
|
||||
-- Set functions
|
||||
reg.update = function ()
|
||||
update(widget, reg)
|
||||
end
|
||||
|
||||
-- Default to 2s timer
|
||||
if reg.timer == nil then
|
||||
reg.timer = 2
|
||||
end
|
||||
-- Default to 2s timer
|
||||
if reg.timer == nil then
|
||||
reg.timer = 2
|
||||
end
|
||||
|
||||
-- Register a reg object
|
||||
regregister(reg)
|
||||
-- Register a reg object
|
||||
regregister(reg)
|
||||
|
||||
-- Return a reg object for reuse
|
||||
return reg
|
||||
-- Return a reg object for reuse
|
||||
return reg
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Unregister a widget
|
||||
function vicious.unregister(widget, keep, reg)
|
||||
if reg == nil then
|
||||
for w, i in pairs(registered) do
|
||||
if w == widget then
|
||||
for _, v in pairs(i) do
|
||||
reg = vicious.unregister(w, keep, v)
|
||||
end
|
||||
end
|
||||
if reg == nil then
|
||||
for w, i in pairs(registered) do
|
||||
if w == widget then
|
||||
for _, v in pairs(i) do
|
||||
reg = vicious.unregister(w, keep, v)
|
||||
end
|
||||
|
||||
return reg
|
||||
end
|
||||
|
||||
if not keep then
|
||||
for w, i in pairs(registered) do
|
||||
if w == widget then
|
||||
for k, v in pairs(i) do
|
||||
if v == reg then
|
||||
table.remove(registered[w], k)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not reg.running then
|
||||
return reg
|
||||
end
|
||||
|
||||
-- Disconnect from timer
|
||||
local tm = timers[reg.timer]
|
||||
if tm.timer.disconnect_signal then
|
||||
tm.timer:disconnect_signal("timeout", reg.update)
|
||||
else
|
||||
tm.timer:remove_signal("timeout", reg.update)
|
||||
end
|
||||
reg.running = false
|
||||
-- Stop the timer
|
||||
tm.refs = tm.refs - 1
|
||||
if tm.refs == 0 and tm.timer.started then
|
||||
tm.timer:stop()
|
||||
end
|
||||
end
|
||||
|
||||
return reg
|
||||
end
|
||||
|
||||
if not keep then
|
||||
for w, i in pairs(registered) do
|
||||
if w == widget then
|
||||
for k, v in pairs(i) do
|
||||
if v == reg then
|
||||
table.remove(registered[w], k)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not reg.running then
|
||||
return reg
|
||||
end
|
||||
|
||||
-- Disconnect from timer
|
||||
local tm = timers[reg.timer]
|
||||
if tm.timer.disconnect_signal then
|
||||
tm.timer:disconnect_signal("timeout", reg.update)
|
||||
else
|
||||
tm.timer:remove_signal("timeout", reg.update)
|
||||
end
|
||||
reg.running = false
|
||||
-- Stop the timer
|
||||
tm.refs = tm.refs - 1
|
||||
if tm.refs == 0 and tm.timer.started then
|
||||
tm.timer:stop()
|
||||
end
|
||||
|
||||
return reg
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Enable caching of a widget type
|
||||
function vicious.cache(wtype)
|
||||
if wtype ~= nil then
|
||||
if widget_cache[wtype] == nil then
|
||||
widget_cache[wtype] = {}
|
||||
end
|
||||
if wtype ~= nil then
|
||||
if widget_cache[wtype] == nil then
|
||||
widget_cache[wtype] = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Force update of widgets
|
||||
function vicious.force(wtable)
|
||||
if type(wtable) == "table" then
|
||||
for _, w in pairs(wtable) do
|
||||
update(w, nil, true)
|
||||
end
|
||||
if type(wtable) == "table" then
|
||||
for _, w in pairs(wtable) do
|
||||
update(w, nil, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Suspend all widgets
|
||||
function vicious.suspend()
|
||||
for w, i in pairs(registered) do
|
||||
for _, v in pairs(i) do
|
||||
vicious.unregister(w, true, v)
|
||||
end
|
||||
for w, i in pairs(registered) do
|
||||
for _, v in pairs(i) do
|
||||
vicious.unregister(w, true, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Activate a widget
|
||||
function vicious.activate(widget)
|
||||
for w, i in pairs(registered) do
|
||||
if widget == nil or w == widget then
|
||||
for _, v in pairs(i) do
|
||||
regregister(v)
|
||||
end
|
||||
end
|
||||
for w, i in pairs(registered) do
|
||||
if widget == nil or w == widget then
|
||||
for _, v in pairs(i) do
|
||||
regregister(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -10,8 +10,8 @@ local setmetatable = setmetatable
|
||||
local string = { format = string.format }
|
||||
local helpers = require("vicious.helpers")
|
||||
local math = {
|
||||
min = math.min,
|
||||
floor = math.floor
|
||||
min = math.min,
|
||||
floor = math.floor
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -23,71 +23,71 @@ local bat = {}
|
||||
|
||||
-- {{{ Battery widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
local battery = helpers.pathtotable("/sys/class/power_supply/"..warg)
|
||||
local battery_state = {
|
||||
["Full\n"] = "↯",
|
||||
["Unknown\n"] = "⌁",
|
||||
["Charged\n"] = "↯",
|
||||
["Charging\n"] = "+",
|
||||
["Discharging\n"] = "−"
|
||||
}
|
||||
local battery = helpers.pathtotable("/sys/class/power_supply/"..warg)
|
||||
local battery_state = {
|
||||
["Full\n"] = "↯",
|
||||
["Unknown\n"] = "⌁",
|
||||
["Charged\n"] = "↯",
|
||||
["Charging\n"] = "+",
|
||||
["Discharging\n"] = "−"
|
||||
}
|
||||
|
||||
-- Check if the battery is present
|
||||
if battery.present ~= "1\n" then
|
||||
return {battery_state["Unknown\n"], 0, "N/A", 0}
|
||||
end
|
||||
-- Check if the battery is present
|
||||
if battery.present ~= "1\n" then
|
||||
return {battery_state["Unknown\n"], 0, "N/A", 0}
|
||||
end
|
||||
|
||||
|
||||
-- Get state information
|
||||
local state = battery_state[battery.status] or battery_state["Unknown\n"]
|
||||
-- Get state information
|
||||
local state = battery_state[battery.status] or battery_state["Unknown\n"]
|
||||
|
||||
-- Get capacity information
|
||||
if battery.charge_now then
|
||||
remaining, capacity = battery.charge_now, battery.charge_full
|
||||
capacity_design = battery.charge_full_design or capacity
|
||||
elseif battery.energy_now then
|
||||
remaining, capacity = battery.energy_now, battery.energy_full
|
||||
capacity_design = battery.energy_full_design or capacity
|
||||
-- Get capacity information
|
||||
if battery.charge_now then
|
||||
remaining, capacity = battery.charge_now, battery.charge_full
|
||||
capacity_design = battery.charge_full_design or capacity
|
||||
elseif battery.energy_now then
|
||||
remaining, capacity = battery.energy_now, battery.energy_full
|
||||
capacity_design = battery.energy_full_design or capacity
|
||||
else
|
||||
return {battery_state["Unknown\n"], 0, "N/A", 0}
|
||||
end
|
||||
|
||||
-- Calculate capacity and wear percentage (but work around broken BAT/ACPI implementations)
|
||||
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||
local wear = math.floor(100 - capacity / capacity_design * 100)
|
||||
|
||||
|
||||
-- Get charge information
|
||||
if battery.current_now then
|
||||
rate = tonumber(battery.current_now)
|
||||
elseif battery.power_now then
|
||||
rate = tonumber(battery.power_now)
|
||||
else
|
||||
return {state, percent, "N/A", wear}
|
||||
end
|
||||
|
||||
-- Calculate remaining (charging or discharging) time
|
||||
local time = "N/A"
|
||||
|
||||
if rate ~= nil and rate ~= 0 then
|
||||
if state == "+" then
|
||||
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
|
||||
elseif state == "−" then
|
||||
timeleft = tonumber(remaining) / tonumber(rate)
|
||||
else
|
||||
return {battery_state["Unknown\n"], 0, "N/A", 0}
|
||||
return {state, percent, time, wear}
|
||||
end
|
||||
|
||||
-- Calculate capacity and wear percentage (but work around broken BAT/ACPI implementations)
|
||||
local percent = math.min(math.floor(remaining / capacity * 100), 100)
|
||||
local wear = math.floor(100 - capacity / capacity_design * 100)
|
||||
-- Calculate time
|
||||
local hoursleft = math.floor(timeleft)
|
||||
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
|
||||
|
||||
time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||
end
|
||||
|
||||
-- Get charge information
|
||||
if battery.current_now then
|
||||
rate = tonumber(battery.current_now)
|
||||
elseif battery.power_now then
|
||||
rate = tonumber(battery.power_now)
|
||||
else
|
||||
return {state, percent, "N/A", wear}
|
||||
end
|
||||
|
||||
-- Calculate remaining (charging or discharging) time
|
||||
local time = "N/A"
|
||||
|
||||
if rate ~= nil and rate ~= 0 then
|
||||
if state == "+" then
|
||||
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
|
||||
elseif state == "−" then
|
||||
timeleft = tonumber(remaining) / tonumber(rate)
|
||||
else
|
||||
return {state, percent, time, wear}
|
||||
end
|
||||
|
||||
-- Calculate time
|
||||
local hoursleft = math.floor(timeleft)
|
||||
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
|
||||
|
||||
time = string.format("%02d:%02d", hoursleft, minutesleft)
|
||||
end
|
||||
|
||||
return {state, percent, time, wear}
|
||||
return {state, percent, time, wear}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -12,8 +12,8 @@ local setmetatable = setmetatable
|
||||
local math = { floor = math.floor }
|
||||
local table = { insert = table.insert }
|
||||
local string = {
|
||||
sub = string.sub,
|
||||
gmatch = string.gmatch
|
||||
sub = string.sub,
|
||||
gmatch = string.gmatch
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -30,50 +30,50 @@ local cpu_active = {}
|
||||
|
||||
-- {{{ CPU widget type
|
||||
local function worker(format)
|
||||
local cpu_lines = {}
|
||||
local cpu_lines = {}
|
||||
|
||||
-- Get CPU stats
|
||||
local f = io.open("/proc/stat")
|
||||
for line in f:lines() do
|
||||
if string.sub(line, 1, 3) ~= "cpu" then break end
|
||||
-- Get CPU stats
|
||||
local f = io.open("/proc/stat")
|
||||
for line in f:lines() do
|
||||
if string.sub(line, 1, 3) ~= "cpu" then break end
|
||||
|
||||
cpu_lines[#cpu_lines+1] = {}
|
||||
cpu_lines[#cpu_lines+1] = {}
|
||||
|
||||
for i in string.gmatch(line, "[%s]+([^%s]+)") do
|
||||
table.insert(cpu_lines[#cpu_lines], i)
|
||||
end
|
||||
for i in string.gmatch(line, "[%s]+([^%s]+)") do
|
||||
table.insert(cpu_lines[#cpu_lines], i)
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
-- Ensure tables are initialized correctly
|
||||
for i = #cpu_total + 1, #cpu_lines do
|
||||
cpu_total[i] = 0
|
||||
cpu_usage[i] = 0
|
||||
cpu_active[i] = 0
|
||||
-- Ensure tables are initialized correctly
|
||||
for i = #cpu_total + 1, #cpu_lines do
|
||||
cpu_total[i] = 0
|
||||
cpu_usage[i] = 0
|
||||
cpu_active[i] = 0
|
||||
end
|
||||
|
||||
|
||||
for i, v in ipairs(cpu_lines) do
|
||||
-- Calculate totals
|
||||
local total_new = 0
|
||||
for j = 1, #v do
|
||||
total_new = total_new + v[j]
|
||||
end
|
||||
local active_new = total_new - (v[4] + v[5])
|
||||
|
||||
-- Calculate percentage
|
||||
local diff_total = total_new - cpu_total[i]
|
||||
local diff_active = active_new - cpu_active[i]
|
||||
|
||||
for i, v in ipairs(cpu_lines) do
|
||||
-- Calculate totals
|
||||
local total_new = 0
|
||||
for j = 1, #v do
|
||||
total_new = total_new + v[j]
|
||||
end
|
||||
local active_new = total_new - (v[4] + v[5])
|
||||
if diff_total == 0 then diff_total = 1E-6 end
|
||||
cpu_usage[i] = math.floor((diff_active / diff_total) * 100)
|
||||
|
||||
-- Calculate percentage
|
||||
local diff_total = total_new - cpu_total[i]
|
||||
local diff_active = active_new - cpu_active[i]
|
||||
-- Store totals
|
||||
cpu_total[i] = total_new
|
||||
cpu_active[i] = active_new
|
||||
end
|
||||
|
||||
if diff_total == 0 then diff_total = 1E-6 end
|
||||
cpu_usage[i] = math.floor((diff_active / diff_total) * 100)
|
||||
|
||||
-- Store totals
|
||||
cpu_total[i] = total_new
|
||||
cpu_active[i] = active_new
|
||||
end
|
||||
|
||||
return cpu_usage
|
||||
return cpu_usage
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -18,43 +18,43 @@ local cpufreq = {}
|
||||
|
||||
-- {{{ CPU frequency widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
local _cpufreq = helpers.pathtotable("/sys/devices/system/cpu/"..warg.."/cpufreq")
|
||||
local governor_state = {
|
||||
["ondemand\n"] = "↯",
|
||||
["powersave\n"] = "⌁",
|
||||
["userspace\n"] = "¤",
|
||||
["performance\n"] = "⚡",
|
||||
["conservative\n"] = "⊚"
|
||||
}
|
||||
-- Default frequency and voltage values
|
||||
local freqv = {
|
||||
["mhz"] = "N/A", ["ghz"] = "N/A",
|
||||
["v"] = "N/A", ["mv"] = "N/A",
|
||||
}
|
||||
local _cpufreq = helpers.pathtotable("/sys/devices/system/cpu/"..warg.."/cpufreq")
|
||||
local governor_state = {
|
||||
["ondemand\n"] = "↯",
|
||||
["powersave\n"] = "⌁",
|
||||
["userspace\n"] = "¤",
|
||||
["performance\n"] = "⚡",
|
||||
["conservative\n"] = "⊚"
|
||||
}
|
||||
-- Default frequency and voltage values
|
||||
local freqv = {
|
||||
["mhz"] = "N/A", ["ghz"] = "N/A",
|
||||
["v"] = "N/A", ["mv"] = "N/A",
|
||||
}
|
||||
|
||||
-- Get the current frequency
|
||||
local freq = tonumber(_cpufreq.scaling_cur_freq)
|
||||
-- Calculate MHz and GHz
|
||||
if freq then
|
||||
freqv.mhz = freq / 1000
|
||||
freqv.ghz = freqv.mhz / 1000
|
||||
-- Get the current frequency
|
||||
local freq = tonumber(_cpufreq.scaling_cur_freq)
|
||||
-- Calculate MHz and GHz
|
||||
if freq then
|
||||
freqv.mhz = freq / 1000
|
||||
freqv.ghz = freqv.mhz / 1000
|
||||
|
||||
-- Get the current voltage
|
||||
if _cpufreq.scaling_voltages then
|
||||
freqv.mv = tonumber(string.match(_cpufreq.scaling_voltages, freq.."[%s]([%d]+)"))
|
||||
-- Calculate voltage from mV
|
||||
freqv.v = freqv.mv / 1000
|
||||
end
|
||||
-- Get the current voltage
|
||||
if _cpufreq.scaling_voltages then
|
||||
freqv.mv = tonumber(string.match(_cpufreq.scaling_voltages, freq.."[%s]([%d]+)"))
|
||||
-- Calculate voltage from mV
|
||||
freqv.v = freqv.mv / 1000
|
||||
end
|
||||
end
|
||||
|
||||
-- Get the current governor
|
||||
local governor = _cpufreq.scaling_governor
|
||||
-- Represent the governor as a symbol
|
||||
governor = governor_state[governor] or governor or "N/A"
|
||||
-- Get the current governor
|
||||
local governor = _cpufreq.scaling_governor
|
||||
-- Represent the governor as a symbol
|
||||
governor = governor_state[governor] or governor or "N/A"
|
||||
|
||||
return {freqv.mhz, freqv.ghz, freqv.mv, freqv.v, governor}
|
||||
return {freqv.mhz, freqv.ghz, freqv.mv, freqv.v, governor}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -18,26 +18,26 @@ local cpuinf = {}
|
||||
|
||||
-- {{{ CPU Information widget type
|
||||
local function worker(format)
|
||||
local id = nil
|
||||
local id = nil
|
||||
|
||||
local cpu_info = {} -- Get CPU info
|
||||
for line in io.lines("/proc/cpuinfo") do
|
||||
for k, v in string.gmatch(line, "([%a%s]+)[%s]+:[%s]([%d]+).-$") do
|
||||
if k == "processor" then
|
||||
id = v
|
||||
elseif k == "cpu MHz\t" or k == "cpu MHz" then
|
||||
local speed = tonumber(v)
|
||||
cpu_info["{cpu"..id.." mhz}"] = speed
|
||||
cpu_info["{cpu"..id.." ghz}"] = speed / 1000
|
||||
elseif k == "cache size" then
|
||||
local cache = tonumber(v)
|
||||
cpu_info["{cpu"..id.." kb}"] = cache
|
||||
cpu_info["{cpu"..id.." mb}"] = cache / 1024
|
||||
end
|
||||
end
|
||||
local cpu_info = {} -- Get CPU info
|
||||
for line in io.lines("/proc/cpuinfo") do
|
||||
for k, v in string.gmatch(line, "([%a%s]+)[%s]+:[%s]([%d]+).-$") do
|
||||
if k == "processor" then
|
||||
id = v
|
||||
elseif k == "cpu MHz\t" or k == "cpu MHz" then
|
||||
local speed = tonumber(v)
|
||||
cpu_info["{cpu"..id.." mhz}"] = speed
|
||||
cpu_info["{cpu"..id.." ghz}"] = speed / 1000
|
||||
elseif k == "cache size" then
|
||||
local cache = tonumber(v)
|
||||
cpu_info["{cpu"..id.." kb}"] = cache
|
||||
cpu_info["{cpu"..id.." mb}"] = cache / 1024
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return cpu_info
|
||||
return cpu_info
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
-- {{{ Grab environment
|
||||
local setmetatable = setmetatable
|
||||
local os = {
|
||||
date = os.date,
|
||||
time = os.time
|
||||
date = os.date,
|
||||
time = os.time
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -20,7 +20,7 @@ local date = {}
|
||||
|
||||
-- {{{ Date widget type
|
||||
local function worker(format, warg)
|
||||
return os.date(format or nil, warg and os.time()+warg or nil)
|
||||
return os.date(format or nil, warg and os.time()+warg or nil)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -10,8 +10,8 @@ local setmetatable = setmetatable
|
||||
local string = { match = string.match }
|
||||
local helpers = require("vicious.helpers")
|
||||
local os = {
|
||||
time = os.time,
|
||||
difftime = os.difftime
|
||||
time = os.time,
|
||||
difftime = os.difftime
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -30,43 +30,43 @@ local unit = { ["s"] = 1, ["kb"] = 2, ["mb"] = 2048 }
|
||||
|
||||
-- {{{ Disk I/O widget type
|
||||
local function worker(format)
|
||||
local disk_lines = {}
|
||||
local disk_lines = {}
|
||||
|
||||
for line in io.lines("/proc/diskstats") do
|
||||
local device, read, write =
|
||||
-- Linux kernel documentation: Documentation/iostats.txt
|
||||
string.match(line, "([^%s]+) %d+ %d+ (%d+) %d+ %d+ %d+ (%d+)")
|
||||
disk_lines[device] = { read, write }
|
||||
for line in io.lines("/proc/diskstats") do
|
||||
local device, read, write =
|
||||
-- Linux kernel documentation: Documentation/iostats.txt
|
||||
string.match(line, "([^%s]+) %d+ %d+ (%d+) %d+ %d+ %d+ (%d+)")
|
||||
disk_lines[device] = { read, write }
|
||||
end
|
||||
|
||||
local time = os.time()
|
||||
local interval = os.difftime(time, disk_time)
|
||||
if interval == 0 then interval = 1 end
|
||||
|
||||
for device, stats in pairs(disk_lines) do
|
||||
-- Avoid insane values on startup
|
||||
local last_stats = disk_stats[device] or stats
|
||||
|
||||
-- Check for overflows and counter resets (> 2^32)
|
||||
if stats[1] < last_stats[1] or stats[2] < last_stats[2] then
|
||||
last_stats[1], last_stats[2] = stats[1], stats[2]
|
||||
end
|
||||
|
||||
local time = os.time()
|
||||
local interval = os.difftime(time, disk_time)
|
||||
if interval == 0 then interval = 1 end
|
||||
-- Diskstats are absolute, substract our last reading
|
||||
-- * divide by timediff because we don't know the timer value
|
||||
local read = (stats[1] - last_stats[1]) / interval
|
||||
local write = (stats[2] - last_stats[2]) / interval
|
||||
|
||||
for device, stats in pairs(disk_lines) do
|
||||
-- Avoid insane values on startup
|
||||
local last_stats = disk_stats[device] or stats
|
||||
-- Calculate and store I/O
|
||||
helpers.uformat(disk_usage, device.." read", read, unit)
|
||||
helpers.uformat(disk_usage, device.." write", write, unit)
|
||||
helpers.uformat(disk_usage, device.." total", read + write, unit)
|
||||
end
|
||||
|
||||
-- Check for overflows and counter resets (> 2^32)
|
||||
if stats[1] < last_stats[1] or stats[2] < last_stats[2] then
|
||||
last_stats[1], last_stats[2] = stats[1], stats[2]
|
||||
end
|
||||
disk_time = time
|
||||
disk_stats = disk_lines
|
||||
|
||||
-- Diskstats are absolute, substract our last reading
|
||||
-- * divide by timediff because we don't know the timer value
|
||||
local read = (stats[1] - last_stats[1]) / interval
|
||||
local write = (stats[2] - last_stats[2]) / interval
|
||||
|
||||
-- Calculate and store I/O
|
||||
helpers.uformat(disk_usage, device.." read", read, unit)
|
||||
helpers.uformat(disk_usage, device.." write", write, unit)
|
||||
helpers.uformat(disk_usage, device.." total", read + write, unit)
|
||||
end
|
||||
|
||||
disk_time = time
|
||||
disk_stats = disk_lines
|
||||
|
||||
return disk_usage
|
||||
return disk_usage
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -23,29 +23,29 @@ local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
|
||||
|
||||
-- {{{ Filesystem widget type
|
||||
local function worker(format, warg)
|
||||
-- Fallback to listing local filesystems
|
||||
if warg then warg = "" else warg = "-l" end
|
||||
-- Fallback to listing local filesystems
|
||||
if warg then warg = "" else warg = "-l" end
|
||||
|
||||
local fs_info = {} -- Get data from df
|
||||
local f = io.popen("LC_ALL=C df -kP " .. helpers.shellquote(warg))
|
||||
local fs_info = {} -- Get data from df
|
||||
local f = io.popen("LC_ALL=C df -kP " .. helpers.shellquote(warg))
|
||||
|
||||
for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
|
||||
local s = string.match(line, "^.-[%s]([%d]+)")
|
||||
local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
|
||||
local m = string.match(line, "%%[%s]+([%p%w]+)")
|
||||
for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
|
||||
local s = string.match(line, "^.-[%s]([%d]+)")
|
||||
local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
|
||||
local m = string.match(line, "%%[%s]+([%p%w]+)")
|
||||
|
||||
if u and m then -- Handle 1st line and broken regexp
|
||||
helpers.uformat(fs_info, m .. " size", s, unit)
|
||||
helpers.uformat(fs_info, m .. " used", u, unit)
|
||||
helpers.uformat(fs_info, m .. " avail", a, unit)
|
||||
if u and m then -- Handle 1st line and broken regexp
|
||||
helpers.uformat(fs_info, m .. " size", s, unit)
|
||||
helpers.uformat(fs_info, m .. " used", u, unit)
|
||||
helpers.uformat(fs_info, m .. " avail", a, unit)
|
||||
|
||||
fs_info["{" .. m .. " used_p}"] = tonumber(p)
|
||||
fs_info["{" .. m .. " avail_p}"] = 100 - tonumber(p)
|
||||
end
|
||||
fs_info["{" .. m .. " used_p}"] = tonumber(p)
|
||||
fs_info["{" .. m .. " avail_p}"] = 100 - tonumber(p)
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
return fs_info
|
||||
return fs_info
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -10,7 +10,7 @@ local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local string = {
|
||||
match = string.match
|
||||
match = string.match
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -30,47 +30,47 @@ local rss = {
|
||||
-- Default is just Inbox
|
||||
local feed = rss.inbox
|
||||
local mail = {
|
||||
["{count}"] = 0,
|
||||
["{subject}"] = "N/A"
|
||||
["{count}"] = 0,
|
||||
["{subject}"] = "N/A"
|
||||
}
|
||||
-- }}}
|
||||
|
||||
|
||||
-- {{{ Gmail widget type
|
||||
local function worker(format, warg)
|
||||
-- Get info from the Gmail atom feed
|
||||
local f = io.popen("curl --connect-timeout 1 -m 3 -fsn " .. feed)
|
||||
-- Get info from the Gmail atom feed
|
||||
local f = io.popen("curl --connect-timeout 1 -m 3 -fsn " .. feed)
|
||||
|
||||
-- Could be huge don't read it all at once, info we are after is at the top
|
||||
local xml = f:read(2000)
|
||||
|
||||
if xml ~= nil then
|
||||
return mail
|
||||
end
|
||||
|
||||
mail["{count}"] = -- Count comes before messages and matches at least 0
|
||||
tonumber(string.match(xml, "<fullcount>([%d]+)</fullcount>")) or mail["{count}"]
|
||||
|
||||
-- Find subject tag
|
||||
local title = string.match(xml, "<entry>.-<title>(.-)</title>")
|
||||
|
||||
if title ~= nil then
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if warg then
|
||||
if type(warg) == "table" then
|
||||
title = helpers.scroll(title, warg[1], warg[2])
|
||||
else
|
||||
title = helpers.truncate(title, warg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Spam sanitize the subject and store
|
||||
mail["{subject}"] = helpers.escape(title)
|
||||
end
|
||||
|
||||
f:close()
|
||||
-- Could be huge don't read it all at once, info we are after is at the top
|
||||
local xml = f:read(2000)
|
||||
|
||||
if xml ~= nil then
|
||||
return mail
|
||||
end
|
||||
|
||||
mail["{count}"] = -- Count comes before messages and matches at least 0
|
||||
tonumber(string.match(xml, "<fullcount>([%d]+)</fullcount>")) or mail["{count}"]
|
||||
|
||||
-- Find subject tag
|
||||
local title = string.match(xml, "<entry>.-<title>(.-)</title>")
|
||||
|
||||
if title ~= nil then
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if warg then
|
||||
if type(warg) == "table" then
|
||||
title = helpers.scroll(title, warg[1], warg[2])
|
||||
else
|
||||
title = helpers.truncate(title, warg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Spam sanitize the subject and store
|
||||
mail["{subject}"] = helpers.escape(title)
|
||||
end
|
||||
|
||||
f:close()
|
||||
|
||||
return mail
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,21 +19,21 @@ local hddtemp = {}
|
||||
|
||||
-- {{{ HDD Temperature widget type
|
||||
local function worker(format, warg)
|
||||
-- Fallback to default hddtemp port
|
||||
if warg == nil then warg = 7634 end
|
||||
-- Fallback to default hddtemp port
|
||||
if warg == nil then warg = 7634 end
|
||||
|
||||
local hdd_temp = {} -- Get info from the hddtemp daemon
|
||||
local quoted = helpers.shellquote(warg)
|
||||
local f = io.popen("echo | curl --connect-timeout 1 -fsm 3 telnet://127.0.0.1:"..quoted)
|
||||
local hdd_temp = {} -- Get info from the hddtemp daemon
|
||||
local quoted = helpers.shellquote(warg)
|
||||
local f = io.popen("echo | curl --connect-timeout 1 -fsm 3 telnet://127.0.0.1:"..quoted)
|
||||
|
||||
for line in f:lines() do
|
||||
for d, t in string.gmatch(line, "|([%/%a%d]+)|.-|([%d]+)|[CF]+|") do
|
||||
hdd_temp["{"..d.."}"] = tonumber(t)
|
||||
end
|
||||
for line in f:lines() do
|
||||
for d, t in string.gmatch(line, "|([%/%a%d]+)|.-|([%d]+)|[CF]+|") do
|
||||
hdd_temp["{"..d.."}"] = tonumber(t)
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
return hdd_temp
|
||||
return hdd_temp
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -22,31 +22,31 @@ local subject = "N/A"
|
||||
|
||||
-- {{{ Mailbox widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- mbox could be huge, get a 30kb chunk from EOF
|
||||
if type(warg) ~= "table" then _mbox = warg end
|
||||
-- * attachment could be much bigger than 30kb
|
||||
local f = io.open(_mbox or warg[1])
|
||||
f:seek("end", -30720)
|
||||
local txt = f:read("*all")
|
||||
f:close()
|
||||
-- mbox could be huge, get a 30kb chunk from EOF
|
||||
if type(warg) ~= "table" then _mbox = warg end
|
||||
-- * attachment could be much bigger than 30kb
|
||||
local f = io.open(_mbox or warg[1])
|
||||
f:seek("end", -30720)
|
||||
local txt = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Find all Subject lines
|
||||
for i in string.gfind(txt, "Subject: ([^\n]*)") do
|
||||
subject = i
|
||||
-- Find all Subject lines
|
||||
for i in string.gfind(txt, "Subject: ([^\n]*)") do
|
||||
subject = i
|
||||
end
|
||||
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if type(warg) == "table" then
|
||||
if warg[3] ~= nil then
|
||||
subject = helpers.scroll(subject, warg[2], warg[3])
|
||||
else
|
||||
subject = helpers.truncate(subject, warg[2])
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if type(warg) == "table" then
|
||||
if warg[3] ~= nil then
|
||||
subject = helpers.scroll(subject, warg[2], warg[3])
|
||||
else
|
||||
subject = helpers.truncate(subject, warg[2])
|
||||
end
|
||||
end
|
||||
|
||||
return {helpers.escape(subject)}
|
||||
return {helpers.escape(subject)}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -17,41 +17,41 @@ local mboxc = {}
|
||||
|
||||
-- {{{ Mbox count widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Initialize counters
|
||||
local count = { old = 0, total = 0, new = 0 }
|
||||
-- Initialize counters
|
||||
local count = { old = 0, total = 0, new = 0 }
|
||||
|
||||
-- Get data from mbox files
|
||||
for i=1, #warg do
|
||||
local f = io.open(warg[i])
|
||||
-- Get data from mbox files
|
||||
for i=1, #warg do
|
||||
local f = io.open(warg[i])
|
||||
|
||||
while true do
|
||||
-- Read the mbox line by line, if we are going to read
|
||||
-- some *HUGE* folders then switch to reading chunks
|
||||
local lines = f:read("*line")
|
||||
if not lines then break end
|
||||
while true do
|
||||
-- Read the mbox line by line, if we are going to read
|
||||
-- some *HUGE* folders then switch to reading chunks
|
||||
local lines = f:read("*line")
|
||||
if not lines then break end
|
||||
|
||||
-- Find all messages
|
||||
-- * http://www.jwz.org/doc/content-length.html
|
||||
local _, from = string.find(lines, "^From[%s]")
|
||||
if from ~= nil then count.total = count.total + 1 end
|
||||
-- Find all messages
|
||||
-- * http://www.jwz.org/doc/content-length.html
|
||||
local _, from = string.find(lines, "^From[%s]")
|
||||
if from ~= nil then count.total = count.total + 1 end
|
||||
|
||||
-- Read messages have the Status header
|
||||
local _, status = string.find(lines, "^Status:[%s]RO$")
|
||||
if status ~= nil then count.old = count.old + 1 end
|
||||
-- Read messages have the Status header
|
||||
local _, status = string.find(lines, "^Status:[%s]RO$")
|
||||
if status ~= nil then count.old = count.old + 1 end
|
||||
|
||||
-- Skip the folder internal data
|
||||
local _, int = string.find(lines, "^Subject:[%s].*FOLDER[%s]INTERNAL[%s]DATA")
|
||||
if int ~= nil then count.total = count.total - 1 end
|
||||
end
|
||||
f:close()
|
||||
-- Skip the folder internal data
|
||||
local _, int = string.find(lines, "^Subject:[%s].*FOLDER[%s]INTERNAL[%s]DATA")
|
||||
if int ~= nil then count.total = count.total - 1 end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
|
||||
-- Substract total from old to get the new count
|
||||
count.new = count.total - count.old
|
||||
-- Substract total from old to get the new count
|
||||
count.new = count.total - count.old
|
||||
|
||||
return {count.total, count.old, count.new}
|
||||
return {count.total, count.old, count.new}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -18,25 +18,25 @@ local mdir = {}
|
||||
|
||||
-- {{{ Maildir widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Initialize counters
|
||||
local count = { new = 0, cur = 0 }
|
||||
-- Initialize counters
|
||||
local count = { new = 0, cur = 0 }
|
||||
|
||||
for i=1, #warg do
|
||||
quoted_path = helpers.shellquote(warg[i])
|
||||
-- Recursively find new messages
|
||||
local f = io.popen("find "..quoted_path.." -type f -wholename '*/new/*'")
|
||||
for line in f:lines() do count.new = count.new + 1 end
|
||||
f:close()
|
||||
for i=1, #warg do
|
||||
quoted_path = helpers.shellquote(warg[i])
|
||||
-- Recursively find new messages
|
||||
local f = io.popen("find "..quoted_path.." -type f -wholename '*/new/*'")
|
||||
for line in f:lines() do count.new = count.new + 1 end
|
||||
f:close()
|
||||
|
||||
-- Recursively find "old" messages lacking the Seen flag
|
||||
local f = io.popen("find "..quoted_path.." -type f -regex '.*/cur/.*2,[^S]*$'")
|
||||
for line in f:lines() do count.cur = count.cur + 1 end
|
||||
f:close()
|
||||
end
|
||||
-- Recursively find "old" messages lacking the Seen flag
|
||||
local f = io.popen("find "..quoted_path.." -type f -regex '.*/cur/.*2,[^S]*$'")
|
||||
for line in f:lines() do count.cur = count.cur + 1 end
|
||||
f:close()
|
||||
end
|
||||
|
||||
return {count.new, count.cur}
|
||||
return {count.new, count.cur}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,33 +19,33 @@ local mem = {}
|
||||
|
||||
-- {{{ Memory widget type
|
||||
local function worker(format)
|
||||
local _mem = { buf = {}, swp = {} }
|
||||
local _mem = { buf = {}, swp = {} }
|
||||
|
||||
-- Get MEM info
|
||||
for line in io.lines("/proc/meminfo") do
|
||||
for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") do
|
||||
if k == "MemTotal" then _mem.total = math.floor(v/1024)
|
||||
elseif k == "MemFree" then _mem.buf.f = math.floor(v/1024)
|
||||
elseif k == "Buffers" then _mem.buf.b = math.floor(v/1024)
|
||||
elseif k == "Cached" then _mem.buf.c = math.floor(v/1024)
|
||||
elseif k == "SwapTotal" then _mem.swp.t = math.floor(v/1024)
|
||||
elseif k == "SwapFree" then _mem.swp.f = math.floor(v/1024)
|
||||
end
|
||||
end
|
||||
-- Get MEM info
|
||||
for line in io.lines("/proc/meminfo") do
|
||||
for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") do
|
||||
if k == "MemTotal" then _mem.total = math.floor(v/1024)
|
||||
elseif k == "MemFree" then _mem.buf.f = math.floor(v/1024)
|
||||
elseif k == "Buffers" then _mem.buf.b = math.floor(v/1024)
|
||||
elseif k == "Cached" then _mem.buf.c = math.floor(v/1024)
|
||||
elseif k == "SwapTotal" then _mem.swp.t = math.floor(v/1024)
|
||||
elseif k == "SwapFree" then _mem.swp.f = math.floor(v/1024)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Calculate memory percentage
|
||||
_mem.free = _mem.buf.f + _mem.buf.b + _mem.buf.c
|
||||
_mem.inuse = _mem.total - _mem.free
|
||||
_mem.bcuse = _mem.total - _mem.buf.f
|
||||
_mem.usep = math.floor(_mem.inuse / _mem.total * 100)
|
||||
-- Calculate swap percentage
|
||||
_mem.swp.inuse = _mem.swp.t - _mem.swp.f
|
||||
_mem.swp.usep = math.floor(_mem.swp.inuse / _mem.swp.t * 100)
|
||||
-- Calculate memory percentage
|
||||
_mem.free = _mem.buf.f + _mem.buf.b + _mem.buf.c
|
||||
_mem.inuse = _mem.total - _mem.free
|
||||
_mem.bcuse = _mem.total - _mem.buf.f
|
||||
_mem.usep = math.floor(_mem.inuse / _mem.total * 100)
|
||||
-- Calculate swap percentage
|
||||
_mem.swp.inuse = _mem.swp.t - _mem.swp.f
|
||||
_mem.swp.usep = math.floor(_mem.swp.inuse / _mem.swp.t * 100)
|
||||
|
||||
return {_mem.usep, _mem.inuse, _mem.total, _mem.free,
|
||||
_mem.swp.usep, _mem.swp.inuse, _mem.swp.t, _mem.swp.f,
|
||||
_mem.bcuse }
|
||||
return {_mem.usep, _mem.inuse, _mem.total, _mem.free,
|
||||
_mem.swp.usep, _mem.swp.inuse, _mem.swp.t, _mem.swp.f,
|
||||
_mem.bcuse }
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,45 +19,45 @@ local mpd = {}
|
||||
|
||||
-- {{{ MPD widget type
|
||||
local function worker(format, warg)
|
||||
local mpd_state = {
|
||||
["{volume}"] = 0,
|
||||
["{state}"] = "N/A",
|
||||
["{Artist}"] = "N/A",
|
||||
["{Title}"] = "N/A",
|
||||
["{Album}"] = "N/A",
|
||||
["{Genre}"] = "N/A",
|
||||
--["{Name}"] = "N/A",
|
||||
--["{file}"] = "N/A",
|
||||
}
|
||||
local mpd_state = {
|
||||
["{volume}"] = 0,
|
||||
["{state}"] = "N/A",
|
||||
["{Artist}"] = "N/A",
|
||||
["{Title}"] = "N/A",
|
||||
["{Album}"] = "N/A",
|
||||
["{Genre}"] = "N/A",
|
||||
--["{Name}"] = "N/A",
|
||||
--["{file}"] = "N/A",
|
||||
}
|
||||
|
||||
-- Fallback to MPD defaults
|
||||
local pass = warg and (warg.password or warg[1]) or "\"\""
|
||||
local host = warg and (warg.host or warg[2]) or "127.0.0.1"
|
||||
local port = warg and (warg.port or warg[3]) or "6600"
|
||||
-- Fallback to MPD defaults
|
||||
local pass = warg and (warg.password or warg[1]) or "\"\""
|
||||
local host = warg and (warg.host or warg[2]) or "127.0.0.1"
|
||||
local port = warg and (warg.port or warg[3]) or "6600"
|
||||
|
||||
-- Construct MPD client options
|
||||
local mpdh = "telnet://"..host..":"..port
|
||||
local echo = "echo 'password "..pass.."\nstatus\ncurrentsong\nclose'"
|
||||
-- Construct MPD client options
|
||||
local mpdh = "telnet://"..host..":"..port
|
||||
local echo = "echo 'password "..pass.."\nstatus\ncurrentsong\nclose'"
|
||||
|
||||
-- Get data from MPD server
|
||||
local f = io.popen(echo.." | curl --connect-timeout 1 -fsm 3 "..mpdh)
|
||||
-- Get data from MPD server
|
||||
local f = io.popen(echo.." | curl --connect-timeout 1 -fsm 3 "..mpdh)
|
||||
|
||||
for line in f:lines() do
|
||||
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
|
||||
if k == "volume" then mpd_state["{"..k.."}"] = v and tonumber(v)
|
||||
elseif k == "state" then mpd_state["{"..k.."}"] = helpers.capitalize(v)
|
||||
elseif k == "Artist" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
elseif k == "Title" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
elseif k == "Album" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
elseif k == "Genre" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
--elseif k == "Name" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
--elseif k == "file" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
end
|
||||
end
|
||||
for line in f:lines() do
|
||||
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
|
||||
if k == "volume" then mpd_state["{"..k.."}"] = v and tonumber(v)
|
||||
elseif k == "state" then mpd_state["{"..k.."}"] = helpers.capitalize(v)
|
||||
elseif k == "Artist" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
elseif k == "Title" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
elseif k == "Album" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
elseif k == "Genre" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
--elseif k == "Name" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
--elseif k == "file" then mpd_state["{"..k.."}"] = helpers.escape(v)
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
return mpd_state
|
||||
return mpd_state
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -23,57 +23,57 @@ local net = {}
|
||||
local nets = {}
|
||||
-- Variable definitions
|
||||
local unit = { ["b"] = 1, ["kb"] = 1024,
|
||||
["mb"] = 1024^2, ["gb"] = 1024^3
|
||||
["mb"] = 1024^2, ["gb"] = 1024^3
|
||||
}
|
||||
|
||||
-- {{{ Net widget type
|
||||
local function worker(format)
|
||||
local args = {}
|
||||
local args = {}
|
||||
|
||||
-- Get NET stats
|
||||
for line in io.lines("/proc/net/dev") do
|
||||
-- Match wmaster0 as well as rt0 (multiple leading spaces)
|
||||
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
|
||||
if name ~= nil then
|
||||
-- Received bytes, first value after the name
|
||||
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
|
||||
-- Transmited bytes, 7 fields from end of the line
|
||||
local send = tonumber(string.match(line,
|
||||
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
|
||||
-- Get NET stats
|
||||
for line in io.lines("/proc/net/dev") do
|
||||
-- Match wmaster0 as well as rt0 (multiple leading spaces)
|
||||
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
|
||||
if name ~= nil then
|
||||
-- Received bytes, first value after the name
|
||||
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
|
||||
-- Transmited bytes, 7 fields from end of the line
|
||||
local send = tonumber(string.match(line,
|
||||
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
|
||||
|
||||
helpers.uformat(args, name .. " rx", recv, unit)
|
||||
helpers.uformat(args, name .. " tx", send, unit)
|
||||
helpers.uformat(args, name .. " rx", recv, unit)
|
||||
helpers.uformat(args, name .. " tx", send, unit)
|
||||
|
||||
-- Operational state and carrier detection
|
||||
local sysnet = helpers.pathtotable("/sys/class/net/" .. name)
|
||||
args["{"..name.." carrier}"] = tonumber(sysnet.carrier) or 0
|
||||
-- Operational state and carrier detection
|
||||
local sysnet = helpers.pathtotable("/sys/class/net/" .. name)
|
||||
args["{"..name.." carrier}"] = tonumber(sysnet.carrier) or 0
|
||||
|
||||
local now = os.time()
|
||||
if nets[name] == nil then
|
||||
-- Default values on the first run
|
||||
nets[name] = {}
|
||||
helpers.uformat(args, name .. " down", 0, unit)
|
||||
helpers.uformat(args, name .. " up", 0, unit)
|
||||
else -- Net stats are absolute, substract our last reading
|
||||
local interval = now - nets[name].time
|
||||
if interval <= 0 then interval = 1 end
|
||||
local now = os.time()
|
||||
if nets[name] == nil then
|
||||
-- Default values on the first run
|
||||
nets[name] = {}
|
||||
helpers.uformat(args, name .. " down", 0, unit)
|
||||
helpers.uformat(args, name .. " up", 0, unit)
|
||||
else -- Net stats are absolute, substract our last reading
|
||||
local interval = now - nets[name].time
|
||||
if interval <= 0 then interval = 1 end
|
||||
|
||||
local down = (recv - nets[name][1]) / interval
|
||||
local up = (send - nets[name][2]) / interval
|
||||
local down = (recv - nets[name][1]) / interval
|
||||
local up = (send - nets[name][2]) / interval
|
||||
|
||||
helpers.uformat(args, name .. " down", down, unit)
|
||||
helpers.uformat(args, name .. " up", up, unit)
|
||||
end
|
||||
helpers.uformat(args, name .. " down", down, unit)
|
||||
helpers.uformat(args, name .. " up", up, unit)
|
||||
end
|
||||
|
||||
nets[name].time = now
|
||||
nets[name].time = now
|
||||
|
||||
-- Store totals
|
||||
nets[name][1] = recv
|
||||
nets[name][2] = send
|
||||
end
|
||||
-- Store totals
|
||||
nets[name][1] = recv
|
||||
nets[name][2] = send
|
||||
end
|
||||
end
|
||||
|
||||
return args
|
||||
return args
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -9,8 +9,8 @@ local io = { lines = io.lines }
|
||||
local setmetatable = setmetatable
|
||||
local string = { find = string.find }
|
||||
local os = {
|
||||
time = os.time,
|
||||
date = os.date
|
||||
time = os.time,
|
||||
date = os.date
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -22,40 +22,40 @@ local org = {}
|
||||
|
||||
-- {{{ OrgMode widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Compute delays
|
||||
local today = os.time{ year=os.date("%Y"), month=os.date("%m"), day=os.date("%d") }
|
||||
local soon = today + 24 * 3600 * 3 -- 3 days ahead is close
|
||||
local future = today + 24 * 3600 * 7 -- 7 days ahead is maximum
|
||||
-- Compute delays
|
||||
local today = os.time{ year=os.date("%Y"), month=os.date("%m"), day=os.date("%d") }
|
||||
local soon = today + 24 * 3600 * 3 -- 3 days ahead is close
|
||||
local future = today + 24 * 3600 * 7 -- 7 days ahead is maximum
|
||||
|
||||
-- Initialize counters
|
||||
local count = { past = 0, today = 0, soon = 0, future = 0 }
|
||||
-- Initialize counters
|
||||
local count = { past = 0, today = 0, soon = 0, future = 0 }
|
||||
|
||||
-- Get data from agenda files
|
||||
for i=1, #warg do
|
||||
for line in io.lines(warg[i]) do
|
||||
local scheduled = string.find(line, "SCHEDULED:")
|
||||
local closed = string.find(line, "CLOSED:")
|
||||
local deadline = string.find(line, "DEADLINE:")
|
||||
-- Get data from agenda files
|
||||
for i=1, #warg do
|
||||
for line in io.lines(warg[i]) do
|
||||
local scheduled = string.find(line, "SCHEDULED:")
|
||||
local closed = string.find(line, "CLOSED:")
|
||||
local deadline = string.find(line, "DEADLINE:")
|
||||
|
||||
if (scheduled and not closed) or (deadline and not closed) then
|
||||
local b, e, y, m, d = string.find(line, "(%d%d%d%d)-(%d%d)-(%d%d)")
|
||||
if (scheduled and not closed) or (deadline and not closed) then
|
||||
local b, e, y, m, d = string.find(line, "(%d%d%d%d)-(%d%d)-(%d%d)")
|
||||
|
||||
if b then
|
||||
local t = os.time{ year = y, month = m, day = d }
|
||||
if b then
|
||||
local t = os.time{ year = y, month = m, day = d }
|
||||
|
||||
if t < today then count.past = count.past + 1
|
||||
elseif t == today then count.today = count.today + 1
|
||||
elseif t <= soon then count.soon = count.soon + 1
|
||||
elseif t <= future then count.future = count.future + 1
|
||||
end
|
||||
end
|
||||
if t < today then count.past = count.past + 1
|
||||
elseif t == today then count.today = count.today + 1
|
||||
elseif t <= soon then count.soon = count.soon + 1
|
||||
elseif t <= future then count.future = count.future + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {count.past, count.today, count.soon, count.future}
|
||||
return {count.past, count.today, count.soon, count.future}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -12,8 +12,8 @@ local los = { getenv = os.getenv }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local string = {
|
||||
gsub = string.gsub,
|
||||
match = string.match
|
||||
gsub = string.gsub,
|
||||
match = string.match
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -25,48 +25,48 @@ local os = {}
|
||||
|
||||
-- {{{ Operating system widget type
|
||||
local function worker(format)
|
||||
local system = {
|
||||
["ostype"] = "N/A",
|
||||
["hostname"] = "N/A",
|
||||
["osrelease"] = "N/A",
|
||||
["username"] = "N/A",
|
||||
["entropy"] = "N/A",
|
||||
["entropy_p"] = "N/A"
|
||||
}
|
||||
local system = {
|
||||
["ostype"] = "N/A",
|
||||
["hostname"] = "N/A",
|
||||
["osrelease"] = "N/A",
|
||||
["username"] = "N/A",
|
||||
["entropy"] = "N/A",
|
||||
["entropy_p"] = "N/A"
|
||||
}
|
||||
|
||||
-- Linux manual page: uname(2)
|
||||
local kernel = helpers.pathtotable("/proc/sys/kernel")
|
||||
for k, v in pairs(system) do
|
||||
if kernel[k] then
|
||||
system[k] = string.gsub(kernel[k], "[%s]*$", "")
|
||||
end
|
||||
-- Linux manual page: uname(2)
|
||||
local kernel = helpers.pathtotable("/proc/sys/kernel")
|
||||
for k, v in pairs(system) do
|
||||
if kernel[k] then
|
||||
system[k] = string.gsub(kernel[k], "[%s]*$", "")
|
||||
end
|
||||
end
|
||||
|
||||
-- BSD manual page: uname(1)
|
||||
if system["ostype"] == "N/A" then
|
||||
local f = io.popen("uname -snr")
|
||||
local uname = f:read("*line")
|
||||
f:close()
|
||||
-- BSD manual page: uname(1)
|
||||
if system["ostype"] == "N/A" then
|
||||
local f = io.popen("uname -snr")
|
||||
local uname = f:read("*line")
|
||||
f:close()
|
||||
|
||||
system["ostype"], system["hostname"], system["osrelease"] =
|
||||
string.match(uname, "([%w]+)[%s]([%w%p]+)[%s]([%w%p]+)")
|
||||
end
|
||||
system["ostype"], system["hostname"], system["osrelease"] =
|
||||
string.match(uname, "([%w]+)[%s]([%w%p]+)[%s]([%w%p]+)")
|
||||
end
|
||||
|
||||
-- Linux manual page: random(4)
|
||||
if kernel.random then
|
||||
-- Linux 2.6 default entropy pool is 4096-bits
|
||||
local poolsize = tonumber(kernel.random.poolsize)
|
||||
-- Linux manual page: random(4)
|
||||
if kernel.random then
|
||||
-- Linux 2.6 default entropy pool is 4096-bits
|
||||
local poolsize = tonumber(kernel.random.poolsize)
|
||||
|
||||
-- Get available entropy and calculate percentage
|
||||
system["entropy"] = tonumber(kernel.random.entropy_avail)
|
||||
system["entropy_p"] = math.ceil(system["entropy"] * 100 / poolsize)
|
||||
end
|
||||
-- Get available entropy and calculate percentage
|
||||
system["entropy"] = tonumber(kernel.random.entropy_avail)
|
||||
system["entropy_p"] = math.ceil(system["entropy"] * 100 / poolsize)
|
||||
end
|
||||
|
||||
-- Get user from the environment
|
||||
system["username"] = los.getenv("USER")
|
||||
-- Get user from the environment
|
||||
system["username"] = los.getenv("USER")
|
||||
|
||||
return {system["ostype"], system["osrelease"], system["username"],
|
||||
system["hostname"], system["entropy"], system["entropy_p"]}
|
||||
return {system["ostype"], system["osrelease"], system["username"],
|
||||
system["hostname"], system["entropy"], system["entropy_p"]}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -17,31 +17,31 @@ local pkg = {}
|
||||
|
||||
-- {{{ Packages widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Initialize counters
|
||||
local updates = 0
|
||||
local manager = {
|
||||
["Arch"] = { cmd = "pacman -Qu" },
|
||||
["Arch C"] = { cmd = "checkupdates" },
|
||||
["Arch S"] = { cmd = "yes | pacman -Sup", sub = 1 },
|
||||
["Debian"] = { cmd = "apt-show-versions -u -b" },
|
||||
["Ubuntu"] = { cmd = "aptitude search '~U'" },
|
||||
["Fedora"] = { cmd = "yum list updates", sub = 3 },
|
||||
["FreeBSD"] ={ cmd = "pkg_version -I -l '<'" },
|
||||
["Mandriva"]={ cmd = "urpmq --auto-select" }
|
||||
}
|
||||
-- Initialize counters
|
||||
local updates = 0
|
||||
local manager = {
|
||||
["Arch"] = { cmd = "pacman -Qu" },
|
||||
["Arch C"] = { cmd = "checkupdates" },
|
||||
["Arch S"] = { cmd = "yes | pacman -Sup", sub = 1 },
|
||||
["Debian"] = { cmd = "apt-show-versions -u -b" },
|
||||
["Ubuntu"] = { cmd = "aptitude search '~U'" },
|
||||
["Fedora"] = { cmd = "yum list updates", sub = 3 },
|
||||
["FreeBSD"] ={ cmd = "pkg_version -I -l '<'" },
|
||||
["Mandriva"]={ cmd = "urpmq --auto-select" }
|
||||
}
|
||||
|
||||
-- Check if updates are available
|
||||
local _pkg = manager[warg]
|
||||
local f = io.popen(_pkg.cmd)
|
||||
-- Check if updates are available
|
||||
local _pkg = manager[warg]
|
||||
local f = io.popen(_pkg.cmd)
|
||||
|
||||
for line in f:lines() do
|
||||
updates = updates + 1
|
||||
end
|
||||
f:close()
|
||||
for line in f:lines() do
|
||||
updates = updates + 1
|
||||
end
|
||||
f:close()
|
||||
|
||||
return {_pkg.sub and math.max(updates-_pkg.sub, 0) or updates}
|
||||
return {_pkg.sub and math.max(updates-_pkg.sub, 0) or updates}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -7,10 +7,10 @@
|
||||
local io = { open = io.open }
|
||||
local setmetatable = setmetatable
|
||||
local string = {
|
||||
len = string.len,
|
||||
sub = string.sub,
|
||||
match = string.match,
|
||||
gmatch = string.gmatch
|
||||
len = string.len,
|
||||
sub = string.sub,
|
||||
match = string.match,
|
||||
gmatch = string.gmatch
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -25,35 +25,35 @@ local mddev = {}
|
||||
|
||||
-- {{{ RAID widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
mddev[warg] = {
|
||||
["found"] = false,
|
||||
["active"] = 0,
|
||||
["assigned"] = 0
|
||||
}
|
||||
if not warg then return end
|
||||
mddev[warg] = {
|
||||
["found"] = false,
|
||||
["active"] = 0,
|
||||
["assigned"] = 0
|
||||
}
|
||||
|
||||
-- Linux manual page: md(4)
|
||||
local f = io.open("/proc/mdstat")
|
||||
for line in f:lines() do
|
||||
if mddev[warg]["found"] then
|
||||
local updev = string.match(line, "%[[_U]+%]")
|
||||
-- Linux manual page: md(4)
|
||||
local f = io.open("/proc/mdstat")
|
||||
for line in f:lines() do
|
||||
if mddev[warg]["found"] then
|
||||
local updev = string.match(line, "%[[_U]+%]")
|
||||
|
||||
for i in string.gmatch(updev, "U") do
|
||||
mddev[warg]["active"] = mddev[warg]["active"] + 1
|
||||
end
|
||||
for i in string.gmatch(updev, "U") do
|
||||
mddev[warg]["active"] = mddev[warg]["active"] + 1
|
||||
end
|
||||
|
||||
break
|
||||
elseif string.sub(line, 1, string.len(warg)) == warg then
|
||||
mddev[warg]["found"] = true
|
||||
break
|
||||
elseif string.sub(line, 1, string.len(warg)) == warg then
|
||||
mddev[warg]["found"] = true
|
||||
|
||||
for i in string.gmatch(line, "%[[%d]%]") do
|
||||
mddev[warg]["assigned"] = mddev[warg]["assigned"] + 1
|
||||
end
|
||||
end
|
||||
for i in string.gmatch(line, "%[[%d]%]") do
|
||||
mddev[warg]["assigned"] = mddev[warg]["assigned"] + 1
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
f:close()
|
||||
|
||||
return {mddev[warg]["assigned"], mddev[warg]["active"]}
|
||||
return {mddev[warg]["assigned"], mddev[warg]["active"]}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,28 +19,28 @@ local thermal = {}
|
||||
|
||||
-- {{{ Thermal widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
local zone = { -- Known temperature data sources
|
||||
["sys"] = {"/sys/class/thermal/", file = "temp", div = 1000},
|
||||
["core"] = {"/sys/devices/platform/", file = "temp2_input",div = 1000},
|
||||
["proc"] = {"/proc/acpi/thermal_zone/",file = "temperature"}
|
||||
} -- Default to /sys/class/thermal
|
||||
warg = type(warg) == "table" and warg or { warg, "sys" }
|
||||
local zone = { -- Known temperature data sources
|
||||
["sys"] = {"/sys/class/thermal/", file = "temp", div = 1000},
|
||||
["core"] = {"/sys/devices/platform/", file = "temp2_input",div = 1000},
|
||||
["proc"] = {"/proc/acpi/thermal_zone/",file = "temperature"}
|
||||
} -- Default to /sys/class/thermal
|
||||
warg = type(warg) == "table" and warg or { warg, "sys" }
|
||||
|
||||
-- Get temperature from thermal zone
|
||||
local _thermal = helpers.pathtotable(zone[warg[2]][1] .. warg[1])
|
||||
-- Get temperature from thermal zone
|
||||
local _thermal = helpers.pathtotable(zone[warg[2]][1] .. warg[1])
|
||||
|
||||
local data = warg[3] and _thermal[warg[3]] or _thermal[zone[warg[2]].file]
|
||||
if data then
|
||||
if zone[warg[2]].div then
|
||||
return {data / zone[warg[2]].div}
|
||||
else -- /proc/acpi "temperature: N C"
|
||||
return {tonumber(string.match(data, "[%d]+"))}
|
||||
end
|
||||
local data = warg[3] and _thermal[warg[3]] or _thermal[zone[warg[2]].file]
|
||||
if data then
|
||||
if zone[warg[2]].div then
|
||||
return {data / zone[warg[2]].div}
|
||||
else -- /proc/acpi "temperature: N C"
|
||||
return {tonumber(string.match(data, "[%d]+"))}
|
||||
end
|
||||
end
|
||||
|
||||
return {0}
|
||||
return {0}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,17 +19,17 @@ local uptime = {}
|
||||
|
||||
-- {{{ Uptime widget type
|
||||
local function worker(format)
|
||||
local proc = helpers.pathtotable("/proc")
|
||||
local proc = helpers.pathtotable("/proc")
|
||||
|
||||
-- Get system uptime
|
||||
local up_t = math.floor(string.match(proc.uptime, "[%d]+"))
|
||||
local up_d = math.floor(up_t / (3600 * 24))
|
||||
local up_h = math.floor((up_t % (3600 * 24)) / 3600)
|
||||
local up_m = math.floor(((up_t % (3600 * 24)) % 3600) / 60)
|
||||
-- Get system uptime
|
||||
local up_t = math.floor(string.match(proc.uptime, "[%d]+"))
|
||||
local up_d = math.floor(up_t / (3600 * 24))
|
||||
local up_h = math.floor((up_t % (3600 * 24)) / 3600)
|
||||
local up_m = math.floor(((up_t % (3600 * 24)) % 3600) / 60)
|
||||
|
||||
local l1, l5, l15 = -- Get load averages for past 1, 5 and 15 minutes
|
||||
string.match(proc.loadavg, "([%d%.]+)[%s]([%d%.]+)[%s]([%d%.]+)")
|
||||
return {up_d, up_h, up_m, l1, l5, l15}
|
||||
local l1, l5, l15 = -- Get load averages for past 1, 5 and 15 minutes
|
||||
string.match(proc.loadavg, "([%d%.]+)[%s]([%d%.]+)[%s]([%d%.]+)")
|
||||
return {up_d, up_h, up_m, l1, l5, l15}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -19,35 +19,35 @@ local volume = {}
|
||||
|
||||
-- {{{ Volume widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
local mixer_state = {
|
||||
["on"] = "♫", -- "",
|
||||
["off"] = "♩" -- "M"
|
||||
}
|
||||
local mixer_state = {
|
||||
["on"] = "♫", -- "",
|
||||
["off"] = "♩" -- "M"
|
||||
}
|
||||
|
||||
-- Get mixer control contents
|
||||
local f = io.popen("amixer -M get " .. helpers.shellquote(warg))
|
||||
local mixer = f:read("*all")
|
||||
f:close()
|
||||
-- Get mixer control contents
|
||||
local f = io.popen("amixer -M get " .. helpers.shellquote(warg))
|
||||
local mixer = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Capture mixer control state: [5%] ... ... [on]
|
||||
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
||||
-- Handle mixers without data
|
||||
if volu == nil then
|
||||
return {0, mixer_state["off"]}
|
||||
end
|
||||
-- Capture mixer control state: [5%] ... ... [on]
|
||||
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
|
||||
-- Handle mixers without data
|
||||
if volu == nil then
|
||||
return {0, mixer_state["off"]}
|
||||
end
|
||||
|
||||
-- Handle mixers without mute
|
||||
if mute == "" and volu == "0"
|
||||
-- Handle mixers that are muted
|
||||
or mute == "off" then
|
||||
mute = mixer_state["off"]
|
||||
else
|
||||
mute = mixer_state["on"]
|
||||
end
|
||||
-- Handle mixers without mute
|
||||
if mute == "" and volu == "0"
|
||||
-- Handle mixers that are muted
|
||||
or mute == "off" then
|
||||
mute = mixer_state["off"]
|
||||
else
|
||||
mute = mixer_state["on"]
|
||||
end
|
||||
|
||||
return {tonumber(volu), mute}
|
||||
return {tonumber(volu), mute}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -20,74 +20,74 @@ local weather = {}
|
||||
|
||||
-- Initialize function tables
|
||||
local _weather = {
|
||||
["{city}"] = "N/A",
|
||||
["{wind}"] = "N/A",
|
||||
["{windmph}"] = "N/A",
|
||||
["{windkmh}"] = "N/A",
|
||||
["{sky}"] = "N/A",
|
||||
["{weather}"] = "N/A",
|
||||
["{tempf}"] = "N/A",
|
||||
["{tempc}"] = "N/A",
|
||||
["{dewf}"] = "N/A",
|
||||
["{dewc}"] = "N/A",
|
||||
["{humid}"] = "N/A",
|
||||
["{press}"] = "N/A"
|
||||
["{city}"] = "N/A",
|
||||
["{wind}"] = "N/A",
|
||||
["{windmph}"] = "N/A",
|
||||
["{windkmh}"] = "N/A",
|
||||
["{sky}"] = "N/A",
|
||||
["{weather}"] = "N/A",
|
||||
["{tempf}"] = "N/A",
|
||||
["{tempc}"] = "N/A",
|
||||
["{dewf}"] = "N/A",
|
||||
["{dewc}"] = "N/A",
|
||||
["{humid}"] = "N/A",
|
||||
["{press}"] = "N/A"
|
||||
}
|
||||
|
||||
-- {{{ Weather widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Get weather forceast by the station ICAO code, from:
|
||||
-- * US National Oceanic and Atmospheric Administration
|
||||
local url = "http://weather.noaa.gov/pub/data/observations/metar/decoded/"..warg
|
||||
local f = io.popen("curl --connect-timeout 1 -fsm 3 "..helpers.shellquote(url)..".TXT")
|
||||
local ws = f:read("*all")
|
||||
f:close()
|
||||
-- Get weather forceast by the station ICAO code, from:
|
||||
-- * US National Oceanic and Atmospheric Administration
|
||||
local url = "http://weather.noaa.gov/pub/data/observations/metar/decoded/"..warg
|
||||
local f = io.popen("curl --connect-timeout 1 -fsm 3 "..helpers.shellquote(url)..".TXT")
|
||||
local ws = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- Check if there was a timeout or a problem with the station
|
||||
if ws == nil then return _weather end
|
||||
-- Check if there was a timeout or a problem with the station
|
||||
if ws == nil then return _weather end
|
||||
|
||||
_weather["{city}"] = -- City and/or area
|
||||
string.match(ws, "^(.+)%,.*%([%u]+%)") or _weather["{city}"]
|
||||
_weather["{wind}"] = -- Wind direction and degrees if available
|
||||
string.match(ws, "Wind:[%s][%a]+[%s][%a]+[%s](.+)[%s]at.+$") or _weather["{wind}"]
|
||||
_weather["{windmph}"] = -- Wind speed in MPH if available
|
||||
string.match(ws, "Wind:[%s].+[%s]at[%s]([%d]+)[%s]MPH") or _weather["{windmph}"]
|
||||
_weather["{sky}"] = -- Sky conditions if available
|
||||
string.match(ws, "Sky[%s]conditions:[%s](.-)[%c]") or _weather["{sky}"]
|
||||
_weather["{weather}"] = -- Weather conditions if available
|
||||
string.match(ws, "Weather:[%s](.-)[%c]") or _weather["{weather}"]
|
||||
_weather["{tempf}"] = -- Temperature in fahrenheit
|
||||
string.match(ws, "Temperature:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{tempf}"]
|
||||
_weather["{dewf}"] = -- Dew Point in fahrenheit
|
||||
string.match(ws, "Dew[%s]Point:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{dewf}"]
|
||||
_weather["{humid}"] = -- Relative humidity in percent
|
||||
string.match(ws, "Relative[%s]Humidity:[%s]([%d]+)%%") or _weather["{humid}"]
|
||||
_weather["{press}"] = -- Pressure in hPa
|
||||
string.match(ws, "Pressure[%s].+%((.+)[%s]hPa%)") or _weather["{press}"]
|
||||
_weather["{city}"] = -- City and/or area
|
||||
string.match(ws, "^(.+)%,.*%([%u]+%)") or _weather["{city}"]
|
||||
_weather["{wind}"] = -- Wind direction and degrees if available
|
||||
string.match(ws, "Wind:[%s][%a]+[%s][%a]+[%s](.+)[%s]at.+$") or _weather["{wind}"]
|
||||
_weather["{windmph}"] = -- Wind speed in MPH if available
|
||||
string.match(ws, "Wind:[%s].+[%s]at[%s]([%d]+)[%s]MPH") or _weather["{windmph}"]
|
||||
_weather["{sky}"] = -- Sky conditions if available
|
||||
string.match(ws, "Sky[%s]conditions:[%s](.-)[%c]") or _weather["{sky}"]
|
||||
_weather["{weather}"] = -- Weather conditions if available
|
||||
string.match(ws, "Weather:[%s](.-)[%c]") or _weather["{weather}"]
|
||||
_weather["{tempf}"] = -- Temperature in fahrenheit
|
||||
string.match(ws, "Temperature:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{tempf}"]
|
||||
_weather["{dewf}"] = -- Dew Point in fahrenheit
|
||||
string.match(ws, "Dew[%s]Point:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{dewf}"]
|
||||
_weather["{humid}"] = -- Relative humidity in percent
|
||||
string.match(ws, "Relative[%s]Humidity:[%s]([%d]+)%%") or _weather["{humid}"]
|
||||
_weather["{press}"] = -- Pressure in hPa
|
||||
string.match(ws, "Pressure[%s].+%((.+)[%s]hPa%)") or _weather["{press}"]
|
||||
|
||||
-- Wind speed in km/h if MPH was available
|
||||
if _weather["{windmph}"] ~= "N/A" then
|
||||
_weather["{windmph}"] = tonumber(_weather["{windmph}"])
|
||||
_weather["{windkmh}"] = math.ceil(_weather["{windmph}"] * 1.6)
|
||||
end -- Temperature in °C if °F was available
|
||||
if _weather["{tempf}"] ~= "N/A" then
|
||||
_weather["{tempf}"] = tonumber(_weather["{tempf}"])
|
||||
_weather["{tempc}"] = math.ceil((_weather["{tempf}"] - 32) * 5/9)
|
||||
end -- Dew Point in °C if °F was available
|
||||
if _weather["{dewf}"] ~= "N/A" then
|
||||
_weather["{dewf}"] = tonumber(_weather["{dewf}"])
|
||||
_weather["{dewc}"] = math.ceil((_weather["{dewf}"] - 32) * 5/9)
|
||||
end -- Capitalize some stats so they don't look so out of place
|
||||
if _weather["{sky}"] ~= "N/A" then
|
||||
_weather["{sky}"] = helpers.capitalize(_weather["{sky}"])
|
||||
end
|
||||
if _weather["{weather}"] ~= "N/A" then
|
||||
_weather["{weather}"] = helpers.capitalize(_weather["{weather}"])
|
||||
end
|
||||
-- Wind speed in km/h if MPH was available
|
||||
if _weather["{windmph}"] ~= "N/A" then
|
||||
_weather["{windmph}"] = tonumber(_weather["{windmph}"])
|
||||
_weather["{windkmh}"] = math.ceil(_weather["{windmph}"] * 1.6)
|
||||
end -- Temperature in °C if °F was available
|
||||
if _weather["{tempf}"] ~= "N/A" then
|
||||
_weather["{tempf}"] = tonumber(_weather["{tempf}"])
|
||||
_weather["{tempc}"] = math.ceil((_weather["{tempf}"] - 32) * 5/9)
|
||||
end -- Dew Point in °C if °F was available
|
||||
if _weather["{dewf}"] ~= "N/A" then
|
||||
_weather["{dewf}"] = tonumber(_weather["{dewf}"])
|
||||
_weather["{dewc}"] = math.ceil((_weather["{dewf}"] - 32) * 5/9)
|
||||
end -- Capitalize some stats so they don't look so out of place
|
||||
if _weather["{sky}"] ~= "N/A" then
|
||||
_weather["{sky}"] = helpers.capitalize(_weather["{sky}"])
|
||||
end
|
||||
if _weather["{weather}"] ~= "N/A" then
|
||||
_weather["{weather}"] = helpers.capitalize(_weather["{weather}"])
|
||||
end
|
||||
|
||||
return _weather
|
||||
return _weather
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
@ -9,12 +9,12 @@ local math = { ceil = math.ceil }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local io = {
|
||||
open = io.open,
|
||||
popen = io.popen
|
||||
open = io.open,
|
||||
popen = io.popen
|
||||
}
|
||||
local string = {
|
||||
find = string.find,
|
||||
match = string.match
|
||||
find = string.find,
|
||||
match = string.match
|
||||
}
|
||||
-- }}}
|
||||
|
||||
@ -32,60 +32,60 @@ local iwcpaths = { "/sbin", "/usr/sbin", "/usr/local/sbin", "/usr/bin" }
|
||||
|
||||
-- {{{ Wireless widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
if not warg then return end
|
||||
|
||||
-- Default values
|
||||
local winfo = {
|
||||
["{ssid}"] = "N/A",
|
||||
["{mode}"] = "N/A",
|
||||
["{chan}"] = 0,
|
||||
["{rate}"] = 0,
|
||||
["{link}"] = 0,
|
||||
["{linp}"] = 0,
|
||||
["{sign}"] = 0
|
||||
}
|
||||
-- Default values
|
||||
local winfo = {
|
||||
["{ssid}"] = "N/A",
|
||||
["{mode}"] = "N/A",
|
||||
["{chan}"] = 0,
|
||||
["{rate}"] = 0,
|
||||
["{link}"] = 0,
|
||||
["{linp}"] = 0,
|
||||
["{sign}"] = 0
|
||||
}
|
||||
|
||||
-- Sbin paths aren't in user PATH, search for the binary
|
||||
if iwconfig == "iwconfig" then
|
||||
for _, p in ipairs(iwcpaths) do
|
||||
local f = io.open(p .. "/iwconfig", "rb")
|
||||
if f then
|
||||
iwconfig = p .. "/iwconfig"
|
||||
f:close()
|
||||
break
|
||||
end
|
||||
end
|
||||
-- Sbin paths aren't in user PATH, search for the binary
|
||||
if iwconfig == "iwconfig" then
|
||||
for _, p in ipairs(iwcpaths) do
|
||||
local f = io.open(p .. "/iwconfig", "rb")
|
||||
if f then
|
||||
iwconfig = p .. "/iwconfig"
|
||||
f:close()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get data from iwconfig where available
|
||||
local f = io.popen(iwconfig .." ".. helpers.shellquote(warg) .. " 2>&1")
|
||||
local iw = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- iwconfig wasn't found, isn't executable, or non-wireless interface
|
||||
if iw == nil or string.find(iw, "No such device") then
|
||||
return winfo
|
||||
end
|
||||
|
||||
-- Output differs from system to system, some stats can be
|
||||
-- separated by =, and not all drivers report all stats
|
||||
winfo["{ssid}"] = -- SSID can have almost anything in it
|
||||
helpers.escape(string.match(iw, 'ESSID[=:]"(.-)"') or winfo["{ssid}"])
|
||||
winfo["{mode}"] = -- Modes are simple, but also match the "-" in Ad-Hoc
|
||||
string.match(iw, "Mode[=:]([%w%-]*)") or winfo["{mode}"]
|
||||
winfo["{chan}"] = -- Channels are plain digits
|
||||
tonumber(string.match(iw, "Channel[=:]([%d]+)") or winfo["{chan}"])
|
||||
winfo["{rate}"] = -- Bitrate can start with a space, we don't want to display Mb/s
|
||||
tonumber(string.match(iw, "Bit Rate[=:]([%s]?[%d%.]*)") or winfo["{rate}"])
|
||||
winfo["{link}"] = -- Link quality can contain a slash (32/70), match only the first number
|
||||
tonumber(string.match(iw, "Link Quality[=:]([%d]+)") or winfo["{link}"])
|
||||
winfo["{sign}"] = -- Signal level can be a negative value, don't display decibel notation
|
||||
tonumber(string.match(iw, "Signal level[=:]([%-]?[%d]+)") or winfo["{sign}"])
|
||||
|
||||
-- Link quality percentage if quality was available
|
||||
if winfo["{link}"] ~= 0 then winfo["{linp}"] = math.ceil(winfo["{link}"] / 0.7) end
|
||||
-- Get data from iwconfig where available
|
||||
local f = io.popen(iwconfig .." ".. helpers.shellquote(warg) .. " 2>&1")
|
||||
local iw = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- iwconfig wasn't found, isn't executable, or non-wireless interface
|
||||
if iw == nil or string.find(iw, "No such device") then
|
||||
return winfo
|
||||
end
|
||||
|
||||
-- Output differs from system to system, some stats can be
|
||||
-- separated by =, and not all drivers report all stats
|
||||
winfo["{ssid}"] = -- SSID can have almost anything in it
|
||||
helpers.escape(string.match(iw, 'ESSID[=:]"(.-)"') or winfo["{ssid}"])
|
||||
winfo["{mode}"] = -- Modes are simple, but also match the "-" in Ad-Hoc
|
||||
string.match(iw, "Mode[=:]([%w%-]*)") or winfo["{mode}"]
|
||||
winfo["{chan}"] = -- Channels are plain digits
|
||||
tonumber(string.match(iw, "Channel[=:]([%d]+)") or winfo["{chan}"])
|
||||
winfo["{rate}"] = -- Bitrate can start with a space, we don't want to display Mb/s
|
||||
tonumber(string.match(iw, "Bit Rate[=:]([%s]?[%d%.]*)") or winfo["{rate}"])
|
||||
winfo["{link}"] = -- Link quality can contain a slash (32/70), match only the first number
|
||||
tonumber(string.match(iw, "Link Quality[=:]([%d]+)") or winfo["{link}"])
|
||||
winfo["{sign}"] = -- Signal level can be a negative value, don't display decibel notation
|
||||
tonumber(string.match(iw, "Signal level[=:]([%-]?[%d]+)") or winfo["{sign}"])
|
||||
|
||||
-- Link quality percentage if quality was available
|
||||
if winfo["{link}"] ~= 0 then winfo["{linp}"] = math.ceil(winfo["{link}"] / 0.7) end
|
||||
|
||||
return winfo
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
Reference in New Issue
Block a user