conky-config/module/Graphics.lua

334 lines
8.0 KiB
Lua
Raw Normal View History

2017-07-15 20:08:39 -04:00
local Widget = require 'Widget'
local CriticalText = require 'CriticalText'
local Text = require 'Text'
local TextColumn = require 'TextColumn'
local Line = require 'Line'
local LabelPlot = require 'LabelPlot'
local util = require 'util'
local schema = require 'default_patterns'
2017-07-16 15:17:09 -04:00
local __tonumber = tonumber
local __string_find = string.find
local __string_match = string.match
2017-07-15 20:08:39 -04:00
2017-07-16 15:17:09 -04:00
local _MODULE_Y_ = 145
local _SEPARATOR_SPACING_ = 20
local _TEXT_SPACING_ = 20
local _PLOT_SEC_BREAK_ = 20
local _PLOT_HEIGHT_ = 56
2017-07-15 20:08:39 -04:00
local header = Widget.Header{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _MODULE_Y_,
2017-07-16 14:50:33 -04:00
width = _G_INIT_DATA_.SECTION_WIDTH,
2017-07-15 20:08:39 -04:00
header = 'NVIDIA GRAPHICS'
}
2017-07-16 15:17:09 -04:00
local _RIGHT_X_ = _G_INIT_DATA_.LEFT_X + _G_INIT_DATA_.SECTION_WIDTH
2017-07-15 20:08:39 -04:00
local status = {
label = Widget.Text{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-15 20:08:39 -04:00
y = header.bottom_y,
text = 'Status'
},
value = Widget.Text{
2017-07-16 15:17:09 -04:00
x = _RIGHT_X_,
2017-07-15 20:08:39 -04:00
y = header.bottom_y,
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
text = '<status>'
}
}
2017-07-16 15:17:09 -04:00
local _SEP_Y_1_ = header.bottom_y + _SEPARATOR_SPACING_
2017-07-15 20:08:39 -04:00
local separator1 = Widget.Line{
2017-07-16 15:17:09 -04:00
p1 = {x = _G_INIT_DATA_.LEFT_X, y = _SEP_Y_1_},
p2 = {x = _RIGHT_X_, y = _SEP_Y_1_}
2017-07-15 20:08:39 -04:00
}
2017-07-16 15:17:09 -04:00
local _INTERNAL_TEMP_Y_ = _SEP_Y_1_ + _SEPARATOR_SPACING_
2017-07-15 20:08:39 -04:00
local internal_temp = {
label = Widget.Text{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _INTERNAL_TEMP_Y_,
2017-07-15 20:08:39 -04:00
text = 'Internal Temperature'
},
value = Widget.CriticalText{
2017-07-16 15:17:09 -04:00
x = _RIGHT_X_,
y = _INTERNAL_TEMP_Y_,
2017-07-15 20:08:39 -04:00
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
text = '<gpu_temp>'
}
}
2017-07-16 15:17:09 -04:00
local _PCI_UTIL_Y_ = _INTERNAL_TEMP_Y_ + _TEXT_SPACING_
2017-07-15 20:08:39 -04:00
local pci_util = {
label = Widget.Text{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _PCI_UTIL_Y_,
2017-07-15 20:08:39 -04:00
text = 'PCI Utilization'
},
value = Widget.Text{
2017-07-16 15:17:09 -04:00
x = _RIGHT_X_,
y = _PCI_UTIL_Y_,
2017-07-15 20:08:39 -04:00
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
text = '<pci_util>'
}
}
2017-07-16 15:17:09 -04:00
local _SEP_Y_2_ = _PCI_UTIL_Y_ + _SEPARATOR_SPACING_
2017-07-15 20:08:39 -04:00
local separator2 = Widget.Line{
2017-07-16 15:17:09 -04:00
p1 = {x = _G_INIT_DATA_.LEFT_X, y = _SEP_Y_2_},
p2 = {x = _RIGHT_X_, y = _SEP_Y_2_}
2017-07-15 20:08:39 -04:00
}
2017-07-16 15:17:09 -04:00
local _CLOCK_SPEED_Y_ = _SEP_Y_2_ + _SEPARATOR_SPACING_
2017-07-15 20:08:39 -04:00
local clock_speed = {
labels = Widget.TextColumn{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _CLOCK_SPEED_Y_,
spacing = _TEXT_SPACING_,
2017-07-15 20:08:39 -04:00
'GPU Clock Speed',
'Memory Clock Speed'
},
values = Widget.TextColumn{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X + _G_INIT_DATA_.SECTION_WIDTH,
2017-07-16 15:17:09 -04:00
y = _CLOCK_SPEED_Y_,
spacing = _TEXT_SPACING_,
2017-07-15 20:08:39 -04:00
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
num_rows = 2
}
}
2017-07-16 15:17:09 -04:00
local _SEP_Y_3_ = _CLOCK_SPEED_Y_ + _TEXT_SPACING_ * 2
2017-07-15 20:08:39 -04:00
local separator3 = Widget.Line{
2017-07-16 15:17:09 -04:00
p1 = {x = _G_INIT_DATA_.LEFT_X, y = _SEP_Y_3_},
p2 = {x = _RIGHT_X_, y = _SEP_Y_3_}
2017-07-15 20:08:39 -04:00
}
2017-07-16 15:17:09 -04:00
local _GPU_UTIL_Y_ = _SEP_Y_3_ + _SEPARATOR_SPACING_
2017-07-15 20:08:39 -04:00
local gpu_util = {
label = Widget.Text{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _GPU_UTIL_Y_,
2017-07-15 20:08:39 -04:00
text = 'GPU Utilization'
},
value = Widget.Text{
2017-07-16 15:17:09 -04:00
x = _RIGHT_X_,
y = _GPU_UTIL_Y_,
2017-07-15 20:08:39 -04:00
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
text = '<gpu_util>'
},
plot = Widget.LabelPlot{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _GPU_UTIL_Y_ + _PLOT_SEC_BREAK_,
2017-07-16 14:50:33 -04:00
width = _G_INIT_DATA_.SECTION_WIDTH,
2017-07-16 15:17:09 -04:00
height = _PLOT_HEIGHT_
2017-07-15 20:08:39 -04:00
}
}
2017-07-16 15:17:09 -04:00
local _MEM_UTIL_Y_ = _GPU_UTIL_Y_ + _PLOT_HEIGHT_ + _PLOT_SEC_BREAK_ * 2
2017-07-15 20:08:39 -04:00
local mem_util = {
label = Widget.Text{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _MEM_UTIL_Y_,
2017-07-15 20:08:39 -04:00
text = 'Memory Utilization'
},
value = Widget.Text{
2017-07-16 15:17:09 -04:00
x = _RIGHT_X_,
y = _MEM_UTIL_Y_,
2017-07-15 20:08:39 -04:00
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
text = '<mem_util>'
},
plot = Widget.LabelPlot{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _MEM_UTIL_Y_ + _PLOT_SEC_BREAK_,
2017-07-16 14:50:33 -04:00
width = _G_INIT_DATA_.SECTION_WIDTH,
2017-07-16 15:17:09 -04:00
height = _PLOT_HEIGHT_
2017-07-15 20:08:39 -04:00
}
}
2017-07-16 15:17:09 -04:00
local _VID_UTIL_Y_ = _MEM_UTIL_Y_ + _PLOT_HEIGHT_ + _PLOT_SEC_BREAK_ * 2
2017-07-15 20:08:39 -04:00
local vid_util = {
label = Widget.Text{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _VID_UTIL_Y_,
2017-07-15 20:08:39 -04:00
text = 'Video Utilization'
},
value = Widget.Text{
2017-07-16 15:17:09 -04:00
x = _RIGHT_X_,
y = _VID_UTIL_Y_,
2017-07-15 20:08:39 -04:00
x_align = 'right',
2017-07-19 00:27:37 -04:00
text_color = schema.BLUE,
2017-07-15 20:08:39 -04:00
text = '<vid_util>'
},
plot = Widget.LabelPlot{
2017-07-16 14:50:33 -04:00
x = _G_INIT_DATA_.LEFT_X,
2017-07-16 15:17:09 -04:00
y = _VID_UTIL_Y_ + _PLOT_SEC_BREAK_,
2017-07-16 14:50:33 -04:00
width = _G_INIT_DATA_.SECTION_WIDTH,
2017-07-16 15:17:09 -04:00
height = _PLOT_HEIGHT_
2017-07-15 20:08:39 -04:00
}
}
--[[
vars to process the nv settings glob
glob will be of the form:
<used_mem>
<total_mem>
<temp>
<gpu_freq>,<mem_freq>
graphics=<gpu_util>, memory=<mem_util>, video=<vid_util>, PCIe=<pci_util>
--]]
local NV_QUERY = 'optirun nvidia-settings -c :8 -t'..
' -q UsedDedicatedGPUMemory'..
' -q TotalDedicatedGPUMemory'..
' -q ThermalSensorReading'..
' -q [gpu:0]/GPUCurrentClockFreqs'..
' -q [gpu:0]/GPUUtilization'
local NV_REGEX = '(%d+)\n'..
'(%d+)\n'..
'(%d+)\n'..
'(%d+),(%d+)\n'..
'graphics=(%d+), memory=%d+, video=(%d+), PCIe=(%d+)\n'
2017-07-16 15:23:34 -04:00
local NA = 'N/A'
2017-07-15 20:08:39 -04:00
2017-07-16 15:17:09 -04:00
local nvidia_off = function(cr)
CriticalText.set(internal_temp.value, cr, NA, 1)
Text.set(pci_util.value, cr, NA)
2017-07-15 20:08:39 -04:00
2017-07-16 15:17:09 -04:00
TextColumn.set(clock_speed.values, cr, 1, NA)
TextColumn.set(clock_speed.values, cr, 2, NA)
Text.set(gpu_util.value, cr, NA)
Text.set(mem_util.value, cr, NA)
Text.set(vid_util.value, cr, NA)
2017-07-15 20:08:39 -04:00
LabelPlot.update(gpu_util.plot, 0)
LabelPlot.update(mem_util.plot, 0)
LabelPlot.update(vid_util.plot, 0)
end
2017-07-16 15:17:09 -04:00
local update = function(cr)
2017-07-16 15:23:34 -04:00
-- check if bbswitch is on
2017-07-15 20:08:39 -04:00
if util.read_file('/proc/acpi/bbswitch', '.+%s+(%u+)') == 'ON' then
2017-07-16 15:23:34 -04:00
-- bbswitch might be on, but only because conky is constantly querying
-- it and there appears to be some lag between closing all optirun
-- processes and flipping bbswitch off. If bbswitch is on and there are
-- no optirun processes, we call this "Mixed." In this case we don't
-- check anything (to allow bbswitch to actually switch off) and set all
-- values to N/A and 0.
2017-07-16 15:17:09 -04:00
if __string_find(util.execute_cmd('ps -A -o comm'), 'optirun') == nil then
2017-07-15 20:08:39 -04:00
Text.set(status.value, cr, 'Mixed')
2017-07-16 15:17:09 -04:00
nvidia_off(cr)
2017-07-15 20:08:39 -04:00
else
Text.set(status.value, cr, 'On')
local nvidia_settings_glob = util.execute_cmd(NV_QUERY)
local used_memory, total_memory, temp_reading, gpu_frequency,
memory_frequency, gpu_utilization, vid_utilization,
2017-07-16 15:17:09 -04:00
pci_utilization = __string_match(nvidia_settings_glob, NV_REGEX)
2017-07-15 20:08:39 -04:00
2017-07-16 15:17:09 -04:00
local is_critical = 1
if __tonumber(temp_reading) > 80 then is_critical = 0 end
2017-07-15 20:08:39 -04:00
2017-07-16 15:17:09 -04:00
CriticalText.set(internal_temp.value, cr, temp_reading..'°C', is_critical)
2017-07-15 20:08:39 -04:00
Text.set(pci_util.value, cr, pci_utilization..'%')
TextColumn.set(clock_speed.values, cr, 1, gpu_frequency..' Mhz')
TextColumn.set(clock_speed.values, cr, 2, memory_frequency..' Mhz')
local percent_used_memory = used_memory / total_memory
Text.set(gpu_util.value, cr, gpu_utilization..'%')
Text.set(mem_util.value, cr, util.round(percent_used_memory * 100)..'%')
Text.set(vid_util.value, cr, vid_utilization..'%')
LabelPlot.update(gpu_util.plot, gpu_utilization * 0.01)
LabelPlot.update(mem_util.plot, percent_used_memory)
LabelPlot.update(vid_util.plot, vid_utilization * 0.01)
end
else
Text.set(status.value, cr, 'Off')
2017-07-16 15:17:09 -04:00
nvidia_off(cr)
2017-07-15 20:08:39 -04:00
end
end
Widget = nil
schema = nil
2017-07-16 15:17:09 -04:00
_MODULE_Y_ = nil
_SEPARATOR_SPACING_ = nil
_TEXT_SPACING_ = nil
_PLOT_SEC_BREAK_ = nil
_PLOT_HEIGHT_ = nil
_RIGHT_X_ = nil
_SEP_Y_1_ = nil
_SEP_Y_2_ = nil
_SEP_Y_3_ = nil
_INTERNAL_TEMP_Y_ = nil
_PCI_UTIL_Y_ = nil
_CLOCK_SPEED_Y_ = nil
_GPU_UTIL_Y_ = nil
_MEM_UTIL_Y_ = nil
_VID_UTIL_Y_ = nil
2017-07-15 20:08:39 -04:00
local draw = function(cr, current_interface)
2017-07-16 15:17:09 -04:00
update(cr)
2017-07-15 20:08:39 -04:00
if current_interface == 0 then
Text.draw(header.text, cr)
Line.draw(header.underline, cr)
Text.draw(status.label, cr)
Text.draw(status.value, cr)
Line.draw(separator1, cr)
Text.draw(internal_temp.label, cr)
Text.draw(internal_temp.value, cr)
Text.draw(pci_util.label, cr)
Text.draw(pci_util.value, cr)
Line.draw(separator2, cr)
TextColumn.draw(clock_speed.labels, cr)
TextColumn.draw(clock_speed.values, cr)
Line.draw(separator3, cr)
Text.draw(gpu_util.label, cr)
Text.draw(gpu_util.value, cr)
LabelPlot.draw(gpu_util.plot, cr)
Text.draw(mem_util.label, cr)
Text.draw(mem_util.value, cr)
LabelPlot.draw(mem_util.plot, cr)
Text.draw(vid_util.label, cr)
Text.draw(vid_util.value, cr)
LabelPlot.draw(vid_util.plot, cr)
end
end
return draw