Large update to configs
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}"] =
|
||||
-- Get power info
|
||||
_data["{method}"] =
|
||||
pm.power_method and string.sub(pm.power_method, 1, -2) or "N/A"
|
||||
_data["{dpm_state}"] =
|
||||
_data["{dpm_state}"] =
|
||||
pm.power_dpm_state and string.sub(pm.power_dpm_state, 1, -2) or "N/A"
|
||||
_data["{dpm_perf_level}"] =
|
||||
_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}"] =
|
||||
_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
|
||||
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
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
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"}
|
||||
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
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
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
|
||||
-- }}}
|
||||
|
||||
|
@ -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())
|
||||
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
|
||||
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)
|
||||
while #disk_total[disk] < #disk_lines[disk] do
|
||||
table.insert(disk_total[disk], 0)
|
||||
end
|
||||
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,29 +20,29 @@ 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"}
|
||||
end
|
||||
-- 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)
|
||||
-- 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)}
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return {helpers.escape(np)}
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(mpc, { __call = function(_, ...) return worker(...) end })
|
||||
return setmetatable(mpc, { __call = function(_, ...) return worker(...) 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
|
||||
|
||||
-- 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
|
||||
|
||||
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
|
||||
if not tignorelist then
|
||||
tignorelist = {"lo", "wmaster0"}
|
||||
end
|
||||
for k, i in pairs(tignorelist) do
|
||||
tignore[i] = true
|
||||
end
|
||||
end
|
||||
|
||||
helpers.uformat(args, "total rx", total_rx, unit)
|
||||
helpers.uformat(args, "total tx", total_tx, unit)
|
||||
-- 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 nets["total"] == nil then
|
||||
-- Default values on the first run
|
||||
nets["total"] = {}
|
||||
if not tignore[name] then
|
||||
total_rx = total_rx + recv
|
||||
total_tx = total_tx + send
|
||||
end
|
||||
|
||||
helpers.uformat(args, "total down", 0, unit)
|
||||
helpers.uformat(args, "total up", 0, unit)
|
||||
args["{total carrier}"] = 0
|
||||
helpers.uformat(args, name .. " rx", recv, unit)
|
||||
helpers.uformat(args, name .. " tx", send, unit)
|
||||
|
||||
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()
|
||||
if nets[name] == nil then
|
||||
-- Default values on the first run
|
||||
nets[name] = {}
|
||||
|
||||
local down = (total_rx - nets["total"][1]) / interval
|
||||
local up = (total_tx - nets["total"][2]) / interval
|
||||
helpers.uformat(args, name .. " down", 0, unit)
|
||||
helpers.uformat(args, name .. " up", 0, unit)
|
||||
args["{"..name.." carrier}"] = 0
|
||||
|
||||
helpers.uformat(args, "total down", down, unit)
|
||||
helpers.uformat(args, "total up", up, unit)
|
||||
args["{total carrier}"] = any_up
|
||||
end
|
||||
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()
|
||||
|
||||
-- Store totals
|
||||
nets["total"][1] = total_rx
|
||||
nets["total"][2] = total_tx
|
||||
local down = (recv - nets[name][1]) / interval
|
||||
local up = (send - nets[name][2]) / interval
|
||||
|
||||
return args
|
||||
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
|
||||
-- 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)
|
||||
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
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
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
|
||||
_wdata["{city}"] = -- City name
|
||||
string.match(ws, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
|
||||
_wdata["{wind deg}"] = -- Wind degrees
|
||||
_wdata["{wind deg}"] = -- Wind degrees
|
||||
string.match(ws, '"deg":([%d]+)') or _wdata["{wind deg}"]
|
||||
_wdata["{wind mps}"] = -- Wind speed in meters per second
|
||||
_wdata["{wind mps}"] = -- Wind speed in meters per second
|
||||
string.match(ws, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
|
||||
_wdata["{sky}"] = -- Sky conditions
|
||||
_wdata["{sky}"] = -- Sky conditions
|
||||
string.match(ws, '"main":"([%a]+)"') or _wdata["{sky}"]
|
||||
_wdata["{weather}"] = -- Weather description
|
||||
_wdata["{weather}"] = -- Weather description
|
||||
string.match(ws, '"description":"([%a%s]+)"') or _wdata["{weather}"]
|
||||
_wdata["{temp c}"] = -- Temperature in celsius
|
||||
_wdata["{temp c}"] = -- Temperature in celsius
|
||||
string.match(ws, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
|
||||
_wdata["{humid}"] = -- Relative humidity in percent
|
||||
_wdata["{humid}"] = -- Relative humidity in percent
|
||||
string.match(ws, '"humidity":([%d]+)') or _wdata["{humid}"]
|
||||
_wdata["{press}"] = -- Pressure in hPa
|
||||
_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]
|
||||
-- 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
|
||||
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
|
||||
-- }}}
|
||||
|
||||
|
@ -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 = {}
|
||||
|
||||
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
|
||||
-- Initialise tables
|
||||
local out = {}
|
||||
|
||||
for _, v in pairs(fields) do
|
||||
out[v][k] = ob:match("<" .. v .. ">(.*)</" .. v .. ">")
|
||||
out[v] = {}
|
||||
end
|
||||
|
||||
k = k+1
|
||||
i = j+1
|
||||
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 "
|
||||
|
||||
-- Update the entity count
|
||||
out.count = k
|
||||
-- Get the feed
|
||||
local f = io.popen(curl .. '"' .. feed .. '"')
|
||||
local feed = f:read("*all")
|
||||
f:close()
|
||||
|
||||
return out
|
||||
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
|
||||
end
|
||||
-- }}}
|
||||
|
||||
|
Reference in New Issue
Block a user