Superkaramba: add GPU load sensor

The sensor has a required `driver` parameter and an optional `gpu` parameter.
- The former specifies the backend to use to query the system about GPU load.
- The latter specifies the id of the GPU to check. If left out, the backend default will be used.

For now it only supports NVidia GPUs via the `nvidia` driver, but it can be extended.

Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
pull/86/head
Mavridis Philippe 2 months ago
parent 5965e6b752
commit 480f195dde
Signed by: blu.256
GPG Key ID: F8D2D7E2F989A494

@ -53,8 +53,8 @@ tde_add_executable( superkaramba AUTOMOC
sknewstuff.h sknewstuff.cpp
superkarambasettings.kcfgc themelocale.cpp
input.cpp sklineedit.cpp input_python.cpp
svcgrp_python.cpp
LINK tdeio-shared ${PYTHON_LIBRARIES}
svcgrp_python.cpp gpusensor.cpp
LINK tdeio-shared ${PYTHON_LIBRARIES}
${TDENEWSTUFF_LIBRARIES}
${LIBKVM_LIBRARIES}
DESTINATION ${BIN_INSTALL_DIR}

@ -0,0 +1,129 @@
/*******************************************************************************
GPU sensor
Copyright (C) 2024 Mavridis Philippe <mavridisf@gmail.com>
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
Improvements and feedback are welcome!
*******************************************************************************/
// TQt
#include <tqregexp.h>
// TDE
#include <kstandarddirs.h>
#include <kdebug.h>
// Superkaramba
#include "gpusensor.h"
GPUSensor::GPUSensor(TQString gpuDriver, TQString gpuId, int interval)
: Sensor(interval), m_gpuDriver(gpuDriver), m_gpuId(gpuId)
{
if (m_gpuDriver.lower() == "nvidia")
{
TQString nvsmi = TDEStandardDirs::findExe("nvidia-smi");
if (nvsmi.isNull())
{
kdError() << "The NVidia System Management Interface software is not avaiable." << endl;
return;
}
m_command << nvsmi << "--query-gpu" << "utilization.gpu"
<< "--format=csv,noheader";
if (!m_gpuId.isNull())
{
m_command << TQString("--id=%1").arg(m_gpuId);
}
}
else
{
kdError() << "Unsupported driver specified for GPU sensor (" << m_gpuDriver << ");" << endl
<< "\tSupported drivers are: nvidia" << endl;
}
connect(&m_proc, TQ_SIGNAL(receivedStdout(TDEProcess*, char*, int)),
this, TQ_SLOT(receivedStdout(TDEProcess*, char*, int)));
connect(&m_proc, TQ_SIGNAL(processExited(TDEProcess*)),
this, TQ_SLOT(processExited(TDEProcess*)));
}
GPUSensor::~GPUSensor()
{
}
void GPUSensor::update()
{
if (m_command.isEmpty()) return;
m_proc.clearArguments();
m_proc << m_command;
m_proc.start(TDEProcess::NotifyOnExit, TDEProcess::Stdout);
}
void GPUSensor::receivedStdout(TDEProcess *proc, char *buffer, int buflen)
{
buffer[buflen] = 0;
m_buffer += TQCString(buffer);
}
TQString GPUSensor::getLoad()
{
if (m_gpuDriver.lower() == "nvidia")
{
return m_buffer.left(m_buffer.length() - 3);
}
return TQString::null;
}
#define SUB_FORMAT_STR(fstring, value) \
format.replace(TQRegExp(#fstring, false), value)
void GPUSensor::processExited(TDEProcess *proc)
{
SensorParams *sp;
Meter *meter;
TQString format;
TQString load = getLoad();
m_buffer = TQString::null;
TQObjectListIt it(*objList);
while (it != 0)
{
sp = (SensorParams*)(*it);
meter = sp->getMeter();
format = sp->getParam("FORMAT");
if( format.length() == 0)
{
format = "%v";
}
SUB_FORMAT_STR(%load, load);
SUB_FORMAT_STR(%v, load);
meter->setValue(format);
++it;
}
}
#undef SUB_FORMAT_STR
void GPUSensor::setMaxValue(SensorParams *sp)
{
sp->getMeter()->setMax(100);
}
#include "gpusensor.moc"

@ -0,0 +1,52 @@
/*******************************************************************************
GPU sensor
Copyright (C) 2024 Mavridis Philippe <mavridisf@gmail.com>
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
Improvements and feedback are welcome!
*******************************************************************************/
#ifndef GPUSENSOR_H
#define GPUSENSOR_H
// TDE
#include <kprocess.h>
// Superkaramba
#include "sensor.h"
class GPUSensor : public Sensor
{
TQ_OBJECT
public:
GPUSensor(TQString driver, TQString gpuId, int interval = 1000);
~GPUSensor();
void update();
void setMaxValue(SensorParams *sp);
protected:
TQString getLoad();
private:
TQString m_gpuDriver, m_gpuId, m_buffer;
TQStringList m_command;
TDEProcess m_proc;
public slots:
void receivedStdout(TDEProcess *proc, char *buffer, int buflen);
void processExited(TDEProcess *proc);
};
#endif // GPUSENSOR_H

@ -988,6 +988,26 @@ void karamba::setSensor(const LineParser& lineParser, Meter* meter)
}
if (sens == "GPU")
{
TQString gpuId = lineParser.getString("GPU");
TQString gpuDriver = lineParser.getString("DRIVER");
TQString sensorId = TQString("GPU_%1_%2").arg(gpuDriver, gpuId);
sensor = sensorMap[sensorId];
if (sensor == 0)
{
int interval = lineParser.getInt("INTERVAL");
interval = (interval == 0) ? 1000 : interval;
sensor = (sensorMap[sensorId] = new GPUSensor(gpuDriver, gpuId, interval));
sensorList->append(sensor);
}
SensorParams *sp = new SensorParams(meter);
sp->addParam("FORMAT", m_theme.locale()->translate(lineParser.getString("FORMAT").ascii()));
sensor->addMeter(sp);
sensor->setMaxValue(sp);
}
if( sens == "MEMORY" )
{
sensor = sensorMap["MEMORY"];

@ -82,6 +82,7 @@
#include "uptimesensor.h"
#include "memsensor.h"
#include "cpusensor.h"
#include "gpusensor.h"
#include "networksensor.h"
#include "xmmssensor.h"
#include "noatunsensor.h"
@ -112,7 +113,7 @@ class LineParser;
class karamba : public TQWidget
{
TQ_OBJECT
public:
karamba(TQString fn, TQString name, bool reloading = false,
@ -327,7 +328,7 @@ private slots:
class DesktopChangeSlot : public TQObject
{
TQ_OBJECT
public:
DesktopChangeSlot(TQObject *parent, int desktop_id);
@ -348,7 +349,7 @@ class DesktopChangeSlot : public TQObject
class SignalBridge : public TQObject
{
TQ_OBJECT
public:
SignalBridge(TQObject* parent, TQString, TDEActionCollection*);

Loading…
Cancel
Save