8000 Develop by corecoding · Pull Request #407 · corecoding/Vitals · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Develop #407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1859663
brings back nvidia code
corecoding Mar 11, 2023
fc60df5
change nvidia language
corecoding Mar 11, 2023
f2c390e
adds GPU checkbox
corecoding Mar 19, 2023
fd728b1
fixes GPU section crash
corecoding Mar 19, 2023
ce9e237
moves gpu queries into gpu function
corecoding Mar 19, 2023
11eefd7
remove query-nvidia-smi setting
corecoding Mar 19, 2023
283002f
refactor gpu menu
Aug 27, 2023
77742c4
gpu icon
xulres Aug 27, 2023
5979496
recompile schemas
Arastais Dec 14, 2023
6851fe1
remove duplicate 'include-static-info' settings entry
Arastais Dec 14, 2023
53b9eb8
restore no data text for gpu
Arastais Dec 14, 2023
66ea365
add missing subprocess import
Arastais Dec 15, 2023
cc1693b
change gpu monitor setting to be more consistent
Arastais Dec 15, 2023
578517a
correct gpu power value
Arastais Dec 15, 2023
ca323dc
add missing gpu group status
Arastais Dec 15, 2023
afa31a2
simplified gpu query code
8000 Arastais Dec 15, 2023
3582110
refactor gpu sensor names
Arastais Dec 15, 2023
b7d410d
correct hot label alignment for gpu hot items
Arastais Dec 17, 2023
1f73cc8
add multi gpu support
Arastais Jan 5, 2024
45eb699
add many more gpu measurements (including static info)
Arastais Jan 6, 2024
87c66df
add failsafe for anomalous nvidia-smi readings
Arastais Jan 6, 2024
45d1068
add failsafe for multi-line nvidia-smi readings
Arastais Jan 8, 2024
ebcce02
ignore `N/A` or `NaN` values
Arastais Jan 15, 2024
902a50a
Merge pull request #397 from Arastais/nvidia
corecoding Feb 1, 2024
b38f788
Update metadata.json version
corecoding Feb 1, 2024
f5da050
Merge pull request #404 from corecoding/develop
corecoding Feb 1, 2024
f26068f
nvidia pref button round
corecoding Feb 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 87 additions & 25 deletions extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ var VitalsMenuButton = GObject.registerClass({
'icon-rx': 'network-download-symbolic.svg',
'icon-tx': 'network-upload-symbolic.svg' },
'storage' : { 'icon': 'storage-symbolic.svg' },
'battery' : { 'icon': 'battery-symbolic.svg' }
'battery' : { 'icon': 'battery-symbolic.svg' },
'gpu' : { 'icon': 'gpu-symbolic.svg' }
}

this._warnings = [];
Expand All @@ -49,6 +50,9 @@ var VitalsMenuButton = GObject.registerClass({
this._hotIcons = {};
this._groups = {};
this._widths = {};
this._numGpus = 1;
this._newGpuDetected = false;
this._newGpuDetectedCount = 0;
this._last_query = new Date().getTime();

this._sensors = new Sensors.Sensors(this._settings, this._sensorIcons);
Expand All @@ -72,7 +76,7 @@ var VitalsMenuButton = GObject.registerClass({
this._addSettingChangedSignal('position-in-panel', this._positionInPanelChanged.bind(this));
this._addSettingChangedSignal('menu-centered', this._positionInPanelChanged.bind(this));

let settings = [ 'use-higher-precision', 'alphabetize', 'hide-zeros', 'fixed-widths', 'hide-icons', 'unit', 'memory-measurement', 'include-public-ip', 'network-speed-format', 'storage-measurement', 'include-static-info' ];
let settings = [ 'use-higher-precision', 'alphabetize', 'hide-zeros', 'fixed-widths', 'hide-icons', 'unit', 'memory-measurement', 'include-public-ip', 'network-speed-format', 'storage-measurement', 'include-static-info', 'include-static-gpu-info' ];
for (let setting of Object.values(settings))
this._addSettingChangedSignal(setting, this._redrawMenu.bind(this));

Expand All @@ -95,21 +99,14 @@ var VitalsMenuButton = GObject.registerClass({
// groups associated sensors under accordion menu
if (sensor in this._groups) continue;

this._groups[sensor] = new PopupMenu.PopupSubMenuMenuItem(_(this._ucFirst(sensor)), true);
this._groups[sensor].icon.gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons[sensor]['icon']);
//handle gpus separately.
if (sensor === 'gpu') continue;

// hide menu items that user has requested to not include
if (!this._settings.get_boolean('show-' + sensor))
this._groups[sensor].actor.hide();

if (!this._groups[sensor].status) {
this._groups[sensor].status = this._defaultLabel();
this._groups[sensor].actor.insert_child_at_index(this._groups[sensor].status, 4);
this._groups[sensor].status.text = _('No Data');
}

this.menu.addMenuItem(this._groups[sensor]);
this._initializeMenuGroup(sensor, sensor);
}

for (let i = 1; i <= this._numGpus; i++)
this._initializeMenuGroup('gpu#' + i, 'gpu', (this._numGpus > 1 ? ' ' + i : ''));

// add separator
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
Expand All @@ -135,7 +132,7 @@ var VitalsMenuButton = GObject.registerClass({
refreshButton.connect('clicked', (self) => {
// force refresh by clearing history
this._sensors.resetHistory();
this._values.resetHistory();
this._values.resetHistory(this._numGpus);

// make sure timer fires at next full interval
this._updateTimeChanged();
Expand Down Expand Up @@ -179,6 +176,24 @@ var VitalsMenuButton = GObject.registerClass({
});
}

_initializeMenuGroup(groupName, optionName, menuSuffix = '', position = -1) {
this._groups[groupName] = new PopupMenu.PopupSubMenuMenuItem(_(this._ucFirst(groupName) + menuSuffix), true);
this._groups[groupName].icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(groupName));

// hide menu items that user has requested to not include
if (!this._settings.get_boolean('show-' + optionName))
this._groups[groupName].actor.hide();

if (!this._groups[groupName].status) {
this._groups[groupName].status = this._defaultLabel();
this._groups[groupName].actor.insert_child_at_index(this._groups[groupName].status, 4);
this._groups[groupName].status.text = _('No Data');
}

if(position == -1) this.menu.addMenuItem(this._groups[groupName]);
else this.menu.addMenuItem(this._groups[groupName], position);
}

_createRoundButton(iconName) {
let button = new St.Button({
style_class: 'message-list-clear-button button vitals-button-action'
Expand Down Expand Up @@ -248,7 +263,7 @@ var VitalsMenuButton = GObject.registerClass({
style_class: 'vitals-panel-label',
text: (value)?value:'\u2026', // ...
y_expand: true,
y_align: Clutter.ActorAlign.START
y_align: Clutter.ActorAlign.CENTER
});

// attempt to prevent ellipsizes
Expand All @@ -266,7 +281,13 @@ var VitalsMenuButton = GObject.registerClass({

_showHideSensorsChanged(self, sensor) {
this._sensors.resetHistory();
this._groups[sensor.substr(5)].visible = this._settings.get_boolean(sensor);

const sensorName = sensor.substr(5);
if(sensorName === 'gpu') {
for(let i = 1; i <= this._numGpus; i++)
this._groups[sensorName + '#' + i].visible = this._settings.get_boolean(sensor);
} else
this._groups[sensorName].visible = this._settings.get_boolean(sensor);
}

_positionInPanelChanged() {
Expand Down Expand Up @@ -322,7 +343,7 @@ var VitalsMenuButton = GObject.registerClass({

this._drawMenu();
this._sensors.resetHistory();
this._values.resetHistory();
this._values.resetHistory(this._numGpus);
this._querySensors();
}

Expand Down Expand Up @@ -370,7 +391,8 @@ var VitalsMenuButton = GObject.registerClass({
}
}
}

if(key === "_gpu#1_domain_number_")
console.error('UPDATING: ', key);
// have we added this sensor before?
let item = this._sensorMenuItems[key];
if (item) {
Expand All @@ -394,7 +416,7 @@ var VitalsMenuButton = GObject.registerClass({
let split = sensor.type.split('-');
let type = split[0];
let icon = (split.length == 2)?'icon-' + split[1]:'icon';
let gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons[type][icon]);
let gicon = Gio.icon_new_for_string(this._sensorIconPath(type, icon));

let item = new MenuItem.MenuItem(gicon, key, sensor.label, sensor.value, this._hotLabels[key]);
item.connect('toggle', (self) => {
Expand Down Expand Up @@ -460,17 +482,27 @@ var VitalsMenuButton = GObject.registerClass({
});

// second condition prevents crash due to issue #225, which started when _max_ was moved to the end
if (type == 'default' || !(type in this._sensorIcons)) {
icon.gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons['system']['icon']);
// don't use the default system icon if the type is a gpu; use the universal gpu icon instead
if (type == 'default' || (!(type in this._sensorIcons) && !type.startsWith('gpu'))) {
icon.gicon = Gio.icon_new_for_string(this._sensorIconPath('system'));
} else if (!this._settings.get_boolean('hide-icons')) { // support for hide icons #80
let iconObj = (split.length == 2)?'icon-' + split[1]:'icon';
icon.gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons[type][iconObj]);
icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(type, iconObj));
}

return icon;
}

_sensorIconPath(sensor, icon = 'icon') {
// If the sensor is a numbered gpu, use the gpu icon. Otherwise use whatever icon associated with the sensor name.
let sensorKey = sensor;
if(sensor.startsWith('gpu')) sensorKey = 'gpu';

return this._extensionObject.path + '/icons/' + this._sensorIcons[sensorKey][icon];
}

_ucFirst(string) {
if(string.startsWith('gpu')) return 'Graphics';
return string.charAt(0).toUpperCase() + string.slice(1);
}

Expand Down Expand Up @@ -524,7 +556,8 @@ var VitalsMenuButton = GObject.registerClass({
this._last_query = now;

this._sensors.query((label, value, type, format) => {
let key = '_' + type.replace('-group', '') + '_' + label.replace(' ', '_').toLowerCase() + '_';
const typeKey = type.replace('-group', '');
let key = '_' + typeKey + '_' + label.replace(' ', '_').toLowerCase() + '_';

// if a sensor is disabled, gray it out
if (key in this._sensorMenuItems) {
Expand All @@ -534,11 +567,39 @@ var VitalsMenuButton = GObject.registerClass({
if (value == 'disabled') return;
}

// add/initialize any gpu groups that we haven't added yet
if(typeKey.startsWith('gpu') && typeKey !== 'gpu#1') {
const split = typeKey.split('#');
if(split.length == 2 && this._numGpus < parseInt(split[1])) {
// occasionally two lines from nvidia-smi will be read at once
// so we only actually update the number of gpus if we have recieved multiple lines at least 3 times in a row
// i.e. we make sure that mutiple queries have detected a new gpu back-to-back
if(this._newGpuDetectedCount < 2) {
this._newGpuDetected = true;
return;
}

this._numGpus = parseInt(split[1]);
this._newGpuDetectedCount = 0;
this._newGpuDetected = false;
// change label for gpu 1 from "Graphics" to "Graphics 1" since we have multiple gpus now
this._groups['gpu#1'].label.text = this._ucFirst('gpu#1') + ' 1';
for(let i = 2; i <= this._numGpus; i++)
if(!('gpu#' + i in this._groups))
this._initializeMenuGroup('gpu#' + i, 'gpu', ' ' + i, Object.keys(this._groups).length);
}
}

let items = this._values.returnIfDifferent(dwell, label, value, type, format, key);
for (let item of Object.values(items))
this._updateDisplay(_(item[0]), item[1], item[2], item[3]);
}, dwell);

//if a new gpu has been detected during the last query, then increment the amount of times we've detected a new gpu
if(this._newGpuDetected) this._newGpuDetectedCount++;
else this._newGpuDetectedCount = 0;
this._newGpuDetected = false;

if (this._warnings.length > 0) {
this._notify('Vitals', this._warnings.join("\n"), 'folder-symbolic');
this._warnings = [];
Expand All @@ -555,6 +616,7 @@ var VitalsMenuButton = GObject.registerClass({

destroy() {
this._destroyTimer();
this._sensors.destroy();

for (let signal of Object.values(this._settingChangedSignals))
this._settings.disconnect(signal);
Expand Down
66 changes: 66 additions & 0 deletions helpers/subprocess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import GLib from 'gi://GLib';
import Gio from 'gi://Gio';
const ByteArray = imports.byteArray;

var Decoder;
try {
Decoder = new TextDecoder('utf-8');
} catch(error) {}

// convert Uint8Array into a literal string
function convertUint8ArrayToString(contents) {
// Starting with Gnome 41, we use TextDecoder as ByteArray is deprecated
if (Decoder)
return Decoder.decode(contents).trim();

// Supports ByteArray on Gnome 40
// fixes #304, replaces invalid character
contents[contents.indexOf(208)] = 0;
return ByteArray.toString(contents).trim();
}

export function SubProcess(command) {
this.sub_process = Gio.Subprocess.new(command, Gio.SubprocessFlags.STDOUT_PIPE);
this.stdout = this.sub_process.get_stdout_pipe();
}

SubProcess.prototype.read = function(delimiter = '') {
return new Promise((resolve, reject) => {
this.stdout.read_bytes_async(512, GLib.PRIORITY_LOW, null, function(stdout, res) {
try {
let read_bytes = stdout.read_bytes_finish(res).get_data();

// convert contents to string
let read_str = convertUint8ArrayToString(read_bytes);

// split read_str by delimiter if passed in
if (delimiter) {
if (read_str == '')
read_str = []; // EOF, ''.split(delimiter) would return ['']
else
read_str = read_str.split(delimiter);
}

// return results
resolve(read_str);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) {
// previous read attempt is still waiting for something from stdout
// ignore second attempt, return empty data (like EOF)
if (delimiter) resolve([]);
else resolve('');
} else {
reject(e.message);
}
}
});
});
};

SubProcess.prototype.terminate = function() {
const SIGINT = 2;
this.sub_process.send_signal(SIGINT);
this.sub_process = null;
this.stdout.close_async(GLib.PRIORITY_LOW, null, null);
this.stdout = null;
};
15 changes: 15 additions & 0 deletions icons/gpu-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
],
"url": "https://github.com/corecoding/Vitals",
"uuid": "Vitals@CoreCoding.com",
"version": 63
"version": 64
}
5 changes: 3 additions & 2 deletions prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ const Settings = new GObject.Class({
'show-network', 'show-storage', 'use-higher-precision',
'alphabetize', 'hide-zeros', 'include-public-ip',
'show-battery', 'fixed-widths', 'hide-icons',
'menu-centered', 'include-static-info' ];
'menu-centered', 'include-static-info',
'show-gpu', 'include-static-gpu-info' ];

for (let key in sensors) {
let sensor = sensors[key];
Expand Down Expand Up @@ -90,7 +91,7 @@ const Settings = new GObject.Class({
}

// makes individual sensor preference boxes appear
sensors = [ 'temperature', 'network', 'storage', 'memory', 'battery', 'system', 'processor' ];
sensors = [ 'temperature', 'network', 'storage', 'memory', 'battery', 'system', 'processor', 'gpu' ];
for (let key in sensors) {
let sensor = sensors[key];

Expand Down
Loading
0