tidy&format(all): all files formatted and relevant warnings resolved
C++ / build (pull_request) Failing after 15s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 28s
Python / lint-format (pull_request) Successful in 45s
Python / test (pull_request) Successful in 38s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m45s
C++ / build (pull_request) Failing after 15s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 28s
Python / lint-format (pull_request) Successful in 45s
Python / test (pull_request) Successful in 38s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m45s
This commit is contained in:
@@ -23,20 +23,33 @@ PipeWireWorker::PipeWireWorker(std::stop_token token, AudioCollector* collector)
|
||||
|
||||
m_loop = pw_main_loop_new(nullptr);
|
||||
if (!m_loop) {
|
||||
qWarning() << "PipeWireWorker::init: failed to create PipeWire main loop";
|
||||
qWarning()
|
||||
<< "PipeWireWorker::init: failed to create PipeWire main loop";
|
||||
pw_deinit();
|
||||
return;
|
||||
}
|
||||
|
||||
timespec timeout = { 0, 10 * SPA_NSEC_PER_MSEC };
|
||||
m_timer = pw_loop_add_timer(pw_main_loop_get_loop(m_loop), handleTimeout, this);
|
||||
pw_loop_update_timer(pw_main_loop_get_loop(m_loop), m_timer, &timeout, &timeout, false);
|
||||
timespec timeout = {0, 10 * SPA_NSEC_PER_MSEC};
|
||||
m_timer =
|
||||
pw_loop_add_timer(pw_main_loop_get_loop(m_loop), handleTimeout, this);
|
||||
pw_loop_update_timer(
|
||||
pw_main_loop_get_loop(m_loop), m_timer, &timeout, &timeout, false);
|
||||
|
||||
auto props = pw_properties_new(
|
||||
PW_KEY_MEDIA_TYPE, "Audio", PW_KEY_MEDIA_CATEGORY, "Capture", PW_KEY_MEDIA_ROLE, "Music", nullptr);
|
||||
PW_KEY_MEDIA_TYPE,
|
||||
"Audio",
|
||||
PW_KEY_MEDIA_CATEGORY,
|
||||
"Capture",
|
||||
PW_KEY_MEDIA_ROLE,
|
||||
"Music",
|
||||
nullptr);
|
||||
pw_properties_set(props, PW_KEY_STREAM_CAPTURE_SINK, "true");
|
||||
pw_properties_setf(
|
||||
props, PW_KEY_NODE_LATENCY, "%u/%u", nextPowerOf2(512 * ac::SAMPLE_RATE / 48000), ac::SAMPLE_RATE);
|
||||
props,
|
||||
PW_KEY_NODE_LATENCY,
|
||||
"%u/%u",
|
||||
nextPowerOf2(512 * ac::SAMPLE_RATE / 48000),
|
||||
ac::SAMPLE_RATE);
|
||||
pw_properties_set(props, PW_KEY_NODE_PASSIVE, "true");
|
||||
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
||||
pw_properties_set(props, PW_KEY_STREAM_DONT_REMIX, "false");
|
||||
@@ -55,21 +68,28 @@ PipeWireWorker::PipeWireWorker(std::stop_token token, AudioCollector* collector)
|
||||
params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info);
|
||||
|
||||
pw_stream_events events{};
|
||||
events.state_changed = [](void* data, pw_stream_state, pw_stream_state state, const char*) {
|
||||
auto* self = static_cast<PipeWireWorker*>(data);
|
||||
self->streamStateChanged(state);
|
||||
};
|
||||
events.state_changed =
|
||||
[](void* data, pw_stream_state, pw_stream_state state, const char*) {
|
||||
auto* self = static_cast<PipeWireWorker*>(data);
|
||||
self->streamStateChanged(state);
|
||||
};
|
||||
events.process = [](void* data) {
|
||||
auto* self = static_cast<PipeWireWorker*>(data);
|
||||
self->processStream();
|
||||
};
|
||||
auto* self = static_cast<PipeWireWorker*>(data);
|
||||
self->processStream();
|
||||
};
|
||||
|
||||
m_stream = pw_stream_new_simple(pw_main_loop_get_loop(m_loop), "ZShell-shell", props, &events, this);
|
||||
m_stream = pw_stream_new_simple(
|
||||
pw_main_loop_get_loop(m_loop), "ZShell-shell", props, &events, this);
|
||||
|
||||
const int success = pw_stream_connect(m_stream, PW_DIRECTION_INPUT, PW_ID_ANY,
|
||||
static_cast<pw_stream_flags>(
|
||||
PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS),
|
||||
params, 1);
|
||||
const int success = pw_stream_connect(
|
||||
m_stream,
|
||||
PW_DIRECTION_INPUT,
|
||||
PW_ID_ANY,
|
||||
static_cast<pw_stream_flags>(
|
||||
PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
PW_STREAM_FLAG_RT_PROCESS),
|
||||
params,
|
||||
1);
|
||||
if (success < 0) {
|
||||
qWarning() << "PipeWireWorker::init: failed to connect stream";
|
||||
pw_stream_destroy(m_stream);
|
||||
@@ -98,8 +118,13 @@ void PipeWireWorker::handleTimeout(void* data, uint64_t expirations) {
|
||||
self->m_collector->clearBuffer();
|
||||
} else {
|
||||
self->m_idle = true;
|
||||
timespec timeout = { 0, 500 * SPA_NSEC_PER_MSEC };
|
||||
pw_loop_update_timer(pw_main_loop_get_loop(self->m_loop), self->m_timer, &timeout, &timeout, false);
|
||||
timespec timeout = {0, 500 * SPA_NSEC_PER_MSEC};
|
||||
pw_loop_update_timer(
|
||||
pw_main_loop_get_loop(self->m_loop),
|
||||
self->m_timer,
|
||||
&timeout,
|
||||
&timeout,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,12 +133,14 @@ void PipeWireWorker::streamStateChanged(pw_stream_state state) {
|
||||
m_idle = false;
|
||||
switch (state) {
|
||||
case PW_STREAM_STATE_PAUSED: {
|
||||
timespec timeout = { 0, 10 * SPA_NSEC_PER_MSEC };
|
||||
pw_loop_update_timer(pw_main_loop_get_loop(m_loop), m_timer, &timeout, &timeout, false);
|
||||
timespec timeout = {0, 10 * SPA_NSEC_PER_MSEC};
|
||||
pw_loop_update_timer(
|
||||
pw_main_loop_get_loop(m_loop), m_timer, &timeout, &timeout, false);
|
||||
break;
|
||||
}
|
||||
case PW_STREAM_STATE_STREAMING:
|
||||
pw_loop_update_timer(pw_main_loop_get_loop(m_loop), m_timer, nullptr, nullptr, false);
|
||||
pw_loop_update_timer(
|
||||
pw_main_loop_get_loop(m_loop), m_timer, nullptr, nullptr, false);
|
||||
break;
|
||||
case PW_STREAM_STATE_ERROR:
|
||||
pw_main_loop_quit(m_loop);
|
||||
@@ -171,7 +198,8 @@ void AudioCollector::clearBuffer() {
|
||||
auto* writeBuffer = m_writeBuffer.load(std::memory_order_relaxed);
|
||||
std::fill(writeBuffer->begin(), writeBuffer->end(), 0.0f);
|
||||
|
||||
auto* oldRead = m_readBuffer.exchange(writeBuffer, std::memory_order_acq_rel);
|
||||
auto* oldRead =
|
||||
m_readBuffer.exchange(writeBuffer, std::memory_order_acq_rel);
|
||||
m_writeBuffer.store(oldRead, std::memory_order_release);
|
||||
}
|
||||
|
||||
@@ -181,11 +209,13 @@ void AudioCollector::loadChunk(const qint16* samples, quint32 count) {
|
||||
}
|
||||
|
||||
auto* writeBuffer = m_writeBuffer.load(std::memory_order_relaxed);
|
||||
std::transform(samples, samples + count, writeBuffer->begin(), [](qint16 sample) {
|
||||
std::transform(
|
||||
samples, samples + count, writeBuffer->begin(), [](qint16 sample) {
|
||||
return sample / 32768.0f;
|
||||
});
|
||||
|
||||
auto* oldRead = m_readBuffer.exchange(writeBuffer, std::memory_order_acq_rel);
|
||||
auto* oldRead =
|
||||
m_readBuffer.exchange(writeBuffer, std::memory_order_acq_rel);
|
||||
m_writeBuffer.store(oldRead, std::memory_order_release);
|
||||
}
|
||||
|
||||
@@ -206,9 +236,11 @@ quint32 AudioCollector::readChunk(double* out, quint32 count) {
|
||||
}
|
||||
|
||||
auto* readBuffer = m_readBuffer.load(std::memory_order_acquire);
|
||||
std::transform(readBuffer->begin(), readBuffer->begin() + count, out, [](float sample) {
|
||||
return static_cast<double>(sample);
|
||||
});
|
||||
std::transform(
|
||||
readBuffer->begin(),
|
||||
readBuffer->begin() + count,
|
||||
out,
|
||||
[](float sample) { return static_cast<double>(sample); });
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -218,8 +250,7 @@ AudioCollector::AudioCollector(QObject* parent)
|
||||
, m_buffer1(ac::CHUNK_SIZE)
|
||||
, m_buffer2(ac::CHUNK_SIZE)
|
||||
, m_readBuffer(&m_buffer1)
|
||||
, m_writeBuffer(&m_buffer2) {
|
||||
}
|
||||
, m_writeBuffer(&m_buffer2) {}
|
||||
|
||||
AudioCollector::~AudioCollector() {
|
||||
stop();
|
||||
@@ -232,9 +263,8 @@ void AudioCollector::start() {
|
||||
|
||||
clearBuffer();
|
||||
|
||||
m_thread = std::jthread([this](std::stop_token token) {
|
||||
PipeWireWorker worker(token, this);
|
||||
});
|
||||
m_thread = std::jthread(
|
||||
[this](std::stop_token token) { PipeWireWorker worker(token, this); });
|
||||
}
|
||||
|
||||
void AudioCollector::stop() {
|
||||
|
||||
@@ -22,55 +22,55 @@ constexpr quint32 CHUNK_SIZE = 512;
|
||||
class AudioCollector;
|
||||
|
||||
class PipeWireWorker {
|
||||
public:
|
||||
explicit PipeWireWorker(std::stop_token token, AudioCollector* collector);
|
||||
public:
|
||||
explicit PipeWireWorker(std::stop_token token, AudioCollector* collector);
|
||||
|
||||
void run();
|
||||
void run();
|
||||
|
||||
private:
|
||||
pw_main_loop* m_loop;
|
||||
pw_stream* m_stream;
|
||||
spa_source* m_timer;
|
||||
bool m_idle;
|
||||
private:
|
||||
pw_main_loop* m_loop;
|
||||
pw_stream* m_stream;
|
||||
spa_source* m_timer;
|
||||
bool m_idle;
|
||||
|
||||
std::stop_token m_token;
|
||||
AudioCollector* m_collector;
|
||||
std::stop_token m_token;
|
||||
AudioCollector* m_collector;
|
||||
|
||||
static void handleTimeout(void* data, uint64_t expirations);
|
||||
void streamStateChanged(pw_stream_state state);
|
||||
void processStream();
|
||||
static void handleTimeout(void* data, uint64_t expirations);
|
||||
void streamStateChanged(pw_stream_state state);
|
||||
void processStream();
|
||||
|
||||
[[nodiscard]] unsigned int nextPowerOf2(unsigned int n);
|
||||
[[nodiscard]] unsigned int nextPowerOf2(unsigned int n);
|
||||
};
|
||||
|
||||
class AudioCollector : public Service {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AudioCollector(const AudioCollector&) = delete;
|
||||
AudioCollector& operator=(const AudioCollector&) = delete;
|
||||
public:
|
||||
AudioCollector(const AudioCollector&) = delete;
|
||||
AudioCollector& operator=(const AudioCollector&) = delete;
|
||||
|
||||
static AudioCollector& instance();
|
||||
static AudioCollector& instance();
|
||||
|
||||
void clearBuffer();
|
||||
void loadChunk(const qint16* samples, quint32 count);
|
||||
quint32 readChunk(float* out, quint32 count = 0);
|
||||
quint32 readChunk(double* out, quint32 count = 0);
|
||||
void clearBuffer();
|
||||
void loadChunk(const qint16* samples, quint32 count);
|
||||
quint32 readChunk(float* out, quint32 count = 0);
|
||||
quint32 readChunk(double* out, quint32 count = 0);
|
||||
|
||||
private:
|
||||
explicit AudioCollector(QObject* parent = nullptr);
|
||||
~AudioCollector() override;
|
||||
private:
|
||||
explicit AudioCollector(QObject* parent = nullptr);
|
||||
~AudioCollector() override;
|
||||
|
||||
std::jthread m_thread;
|
||||
std::vector<float> m_buffer1;
|
||||
std::vector<float> m_buffer2;
|
||||
std::atomic<std::vector<float>*> m_readBuffer;
|
||||
std::atomic<std::vector<float>*> m_writeBuffer;
|
||||
quint32 m_sampleCount;
|
||||
std::jthread m_thread;
|
||||
std::vector<float> m_buffer1;
|
||||
std::vector<float> m_buffer2;
|
||||
std::atomic<std::vector<float>*> m_readBuffer;
|
||||
std::atomic<std::vector<float>*> m_writeBuffer;
|
||||
quint32 m_sampleCount;
|
||||
|
||||
void reload();
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void reload();
|
||||
void start() override;
|
||||
void stop() override;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
|
||||
namespace ZShell::services {
|
||||
|
||||
AudioProcessor::AudioProcessor(QObject* parent)
|
||||
: QObject(parent) {
|
||||
}
|
||||
AudioProcessor::AudioProcessor(QObject* parent) : QObject(parent) {}
|
||||
|
||||
AudioProcessor::~AudioProcessor() {
|
||||
stop();
|
||||
@@ -17,12 +15,17 @@ AudioProcessor::~AudioProcessor() {
|
||||
|
||||
void AudioProcessor::init() {
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setInterval(static_cast<int>(ac::CHUNK_SIZE * 1000.0 / ac::SAMPLE_RATE));
|
||||
m_timer->setInterval(
|
||||
static_cast<int>(ac::CHUNK_SIZE * 1000.0 / ac::SAMPLE_RATE));
|
||||
connect(m_timer, &QTimer::timeout, this, &AudioProcessor::process);
|
||||
}
|
||||
|
||||
void AudioProcessor::start() {
|
||||
QMetaObject::invokeMethod(&AudioCollector::instance(), &AudioCollector::ref, Qt::QueuedConnection, this);
|
||||
QMetaObject::invokeMethod(
|
||||
&AudioCollector::instance(),
|
||||
&AudioCollector::ref,
|
||||
Qt::QueuedConnection,
|
||||
this);
|
||||
if (m_timer) {
|
||||
m_timer->start();
|
||||
}
|
||||
@@ -32,14 +35,15 @@ void AudioProcessor::stop() {
|
||||
if (m_timer) {
|
||||
m_timer->stop();
|
||||
}
|
||||
QMetaObject::invokeMethod(&AudioCollector::instance(), &AudioCollector::unref, Qt::QueuedConnection, this);
|
||||
QMetaObject::invokeMethod(
|
||||
&AudioCollector::instance(),
|
||||
&AudioCollector::unref,
|
||||
Qt::QueuedConnection,
|
||||
this);
|
||||
}
|
||||
|
||||
AudioProvider::AudioProvider(QObject* parent)
|
||||
: Service(parent)
|
||||
, m_processor(nullptr)
|
||||
, m_thread(nullptr) {
|
||||
}
|
||||
: Service(parent), m_processor(nullptr), m_thread(nullptr) {}
|
||||
|
||||
AudioProvider::~AudioProvider() {
|
||||
if (m_thread) {
|
||||
@@ -50,7 +54,8 @@ AudioProvider::~AudioProvider() {
|
||||
|
||||
void AudioProvider::init() {
|
||||
if (!m_processor) {
|
||||
qWarning() << "AudioProvider::init: attempted to init with no processor set";
|
||||
qWarning()
|
||||
<< "AudioProvider::init: attempted to init with no processor set";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +63,8 @@ void AudioProvider::init() {
|
||||
m_processor->moveToThread(m_thread);
|
||||
|
||||
connect(m_thread, &QThread::started, m_processor, &AudioProcessor::init);
|
||||
connect(m_thread, &QThread::finished, m_processor, &AudioProcessor::deleteLater);
|
||||
connect(
|
||||
m_thread, &QThread::finished, m_processor, &AudioProcessor::deleteLater);
|
||||
connect(m_thread, &QThread::finished, m_thread, &QThread::deleteLater);
|
||||
|
||||
m_thread->start();
|
||||
|
||||
@@ -7,41 +7,41 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class AudioProcessor : public QObject {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AudioProcessor(QObject* parent = nullptr);
|
||||
~AudioProcessor() override;
|
||||
public:
|
||||
explicit AudioProcessor(QObject* parent = nullptr);
|
||||
~AudioProcessor() override;
|
||||
|
||||
void init();
|
||||
void init();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
protected:
|
||||
virtual void process() = 0;
|
||||
protected:
|
||||
virtual void process() = 0;
|
||||
|
||||
private:
|
||||
QTimer* m_timer;
|
||||
private:
|
||||
QTimer* m_timer;
|
||||
};
|
||||
|
||||
class AudioProvider : public Service {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AudioProvider(QObject* parent = nullptr);
|
||||
~AudioProvider() override;
|
||||
public:
|
||||
explicit AudioProvider(QObject* parent = nullptr);
|
||||
~AudioProvider() override;
|
||||
|
||||
protected:
|
||||
AudioProcessor* m_processor;
|
||||
protected:
|
||||
AudioProcessor* m_processor;
|
||||
|
||||
void init();
|
||||
void init();
|
||||
|
||||
private:
|
||||
QThread* m_thread;
|
||||
private:
|
||||
QThread* m_thread;
|
||||
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void start() override;
|
||||
void stop() override;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -10,8 +10,7 @@ BeatProcessor::BeatProcessor(QObject* parent)
|
||||
: AudioProcessor(parent)
|
||||
, m_tempo(new_aubio_tempo("default", 1024, ac::CHUNK_SIZE, ac::SAMPLE_RATE))
|
||||
, m_in(new_fvec(ac::CHUNK_SIZE))
|
||||
, m_out(new_fvec(2)) {
|
||||
};
|
||||
, m_out(new_fvec(2)) {};
|
||||
|
||||
BeatProcessor::~BeatProcessor() {
|
||||
if (m_tempo) {
|
||||
@@ -36,13 +35,15 @@ void BeatProcessor::process() {
|
||||
}
|
||||
}
|
||||
|
||||
BeatTracker::BeatTracker(QObject* parent)
|
||||
: AudioProvider(parent)
|
||||
, m_bpm(120) {
|
||||
BeatTracker::BeatTracker(QObject* parent) : AudioProvider(parent), m_bpm(120) {
|
||||
m_processor = new BeatProcessor();
|
||||
init();
|
||||
|
||||
connect(static_cast<BeatProcessor*>(m_processor), &BeatProcessor::beat, this, &BeatTracker::updateBpm);
|
||||
connect(
|
||||
static_cast<BeatProcessor*>(m_processor),
|
||||
&BeatProcessor::beat,
|
||||
this,
|
||||
&BeatTracker::updateBpm);
|
||||
}
|
||||
|
||||
smpl_t BeatTracker::bpm() const {
|
||||
|
||||
@@ -7,43 +7,43 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class BeatProcessor : public AudioProcessor {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BeatProcessor(QObject* parent = nullptr);
|
||||
~BeatProcessor() override;
|
||||
public:
|
||||
explicit BeatProcessor(QObject* parent = nullptr);
|
||||
~BeatProcessor() override;
|
||||
|
||||
signals:
|
||||
void beat(smpl_t bpm);
|
||||
signals:
|
||||
void beat(smpl_t bpm);
|
||||
|
||||
protected:
|
||||
void process() override;
|
||||
protected:
|
||||
void process() override;
|
||||
|
||||
private:
|
||||
aubio_tempo_t* m_tempo;
|
||||
fvec_t* m_in;
|
||||
fvec_t* m_out;
|
||||
private:
|
||||
aubio_tempo_t* m_tempo;
|
||||
fvec_t* m_in;
|
||||
fvec_t* m_out;
|
||||
};
|
||||
|
||||
class BeatTracker : public AudioProvider {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(smpl_t bpm READ bpm NOTIFY bpmChanged)
|
||||
Q_PROPERTY(smpl_t bpm READ bpm NOTIFY bpmChanged)
|
||||
|
||||
public:
|
||||
explicit BeatTracker(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit BeatTracker(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] smpl_t bpm() const;
|
||||
[[nodiscard]] smpl_t bpm() const;
|
||||
|
||||
signals:
|
||||
void bpmChanged();
|
||||
void beat(smpl_t bpm);
|
||||
signals:
|
||||
void bpmChanged();
|
||||
void beat(smpl_t bpm);
|
||||
|
||||
private:
|
||||
smpl_t m_bpm;
|
||||
private:
|
||||
smpl_t m_bpm;
|
||||
|
||||
void updateBpm(smpl_t bpm);
|
||||
void updateBpm(smpl_t bpm);
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "audiocollector.hpp"
|
||||
#include "audioprovider.hpp"
|
||||
#include <algorithm>
|
||||
#include <cava/cavacore.h>
|
||||
#include <cstddef>
|
||||
#include <qdebug.h>
|
||||
@@ -14,8 +13,7 @@ CavaProcessor::CavaProcessor(QObject* parent)
|
||||
, m_plan(nullptr)
|
||||
, m_in(new double[ac::CHUNK_SIZE])
|
||||
, m_out(nullptr)
|
||||
, m_bars(0) {
|
||||
};
|
||||
, m_bars(0) {};
|
||||
|
||||
CavaProcessor::~CavaProcessor() {
|
||||
cleanup();
|
||||
@@ -27,7 +25,8 @@ void CavaProcessor::process() {
|
||||
return;
|
||||
}
|
||||
|
||||
const int count = static_cast<int>(AudioCollector::instance().readChunk(m_in));
|
||||
const int count =
|
||||
static_cast<int>(AudioCollector::instance().readChunk(m_in));
|
||||
|
||||
// Process in data via cava
|
||||
cava_execute(m_in, count, m_out, m_plan);
|
||||
@@ -35,7 +34,7 @@ void CavaProcessor::process() {
|
||||
// Apply monstercat filter
|
||||
QVector<double> values(m_bars);
|
||||
|
||||
for(int i = 0; i < m_bars; ++i) {
|
||||
for (int i = 0; i < m_bars; ++i) {
|
||||
values[i] = m_out[i];
|
||||
}
|
||||
|
||||
@@ -63,7 +62,8 @@ void CavaProcessor::process() {
|
||||
|
||||
void CavaProcessor::setBars(int bars) {
|
||||
if (bars < 0) {
|
||||
qWarning() << "CavaProcessor::setBars: bars must be greater than 0. Setting to 0.";
|
||||
qWarning() << "CavaProcessor::setBars: bars must be greater than 0. "
|
||||
"Setting to 0.";
|
||||
bars = 0;
|
||||
}
|
||||
|
||||
@@ -100,13 +100,15 @@ void CavaProcessor::initCava() {
|
||||
}
|
||||
|
||||
CavaProvider::CavaProvider(QObject* parent)
|
||||
: AudioProvider(parent)
|
||||
, m_bars(0)
|
||||
, m_values(m_bars, 0.0) {
|
||||
: AudioProvider(parent), m_bars(0), m_values(m_bars, 0.0) {
|
||||
m_processor = new CavaProcessor();
|
||||
init();
|
||||
|
||||
connect(static_cast<CavaProcessor*>(m_processor), &CavaProcessor::valuesChanged, this, &CavaProvider::updateValues);
|
||||
connect(
|
||||
static_cast<CavaProcessor*>(m_processor),
|
||||
&CavaProcessor::valuesChanged,
|
||||
this,
|
||||
&CavaProvider::updateValues);
|
||||
}
|
||||
|
||||
int CavaProvider::bars() const {
|
||||
@@ -115,7 +117,8 @@ int CavaProvider::bars() const {
|
||||
|
||||
void CavaProvider::setBars(int bars) {
|
||||
if (bars < 0) {
|
||||
qWarning() << "CavaProvider::setBars: bars must be greater than 0. Setting to 0.";
|
||||
qWarning() << "CavaProvider::setBars: bars must be greater than 0. "
|
||||
"Setting to 0.";
|
||||
bars = 0;
|
||||
}
|
||||
|
||||
@@ -129,7 +132,10 @@ void CavaProvider::setBars(int bars) {
|
||||
emit valuesChanged();
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
static_cast<CavaProcessor*>(m_processor), &CavaProcessor::setBars, Qt::QueuedConnection, bars);
|
||||
static_cast<CavaProcessor*>(m_processor),
|
||||
&CavaProcessor::setBars,
|
||||
Qt::QueuedConnection,
|
||||
bars);
|
||||
}
|
||||
|
||||
QVector<double> CavaProvider::values() const {
|
||||
|
||||
@@ -7,58 +7,58 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class CavaProcessor : public AudioProcessor {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CavaProcessor(QObject* parent = nullptr);
|
||||
~CavaProcessor() override;
|
||||
public:
|
||||
explicit CavaProcessor(QObject* parent = nullptr);
|
||||
~CavaProcessor() override;
|
||||
|
||||
void setBars(int bars);
|
||||
void setBars(int bars);
|
||||
|
||||
signals:
|
||||
void valuesChanged(QVector<double> values);
|
||||
signals:
|
||||
void valuesChanged(QVector<double> values);
|
||||
|
||||
protected:
|
||||
void process() override;
|
||||
protected:
|
||||
void process() override;
|
||||
|
||||
private:
|
||||
struct cava_plan* m_plan;
|
||||
double* m_in;
|
||||
double* m_out;
|
||||
private:
|
||||
struct cava_plan* m_plan;
|
||||
double* m_in;
|
||||
double* m_out;
|
||||
|
||||
int m_bars;
|
||||
QVector<double> m_values;
|
||||
int m_bars;
|
||||
QVector<double> m_values;
|
||||
|
||||
void reload();
|
||||
void initCava();
|
||||
void cleanup();
|
||||
void reload();
|
||||
void initCava();
|
||||
void cleanup();
|
||||
};
|
||||
|
||||
class CavaProvider : public AudioProvider {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(int bars READ bars WRITE setBars NOTIFY barsChanged)
|
||||
Q_PROPERTY(int bars READ bars WRITE setBars NOTIFY barsChanged)
|
||||
|
||||
Q_PROPERTY(QVector<double> values READ values NOTIFY valuesChanged)
|
||||
Q_PROPERTY(QVector<double> values READ values NOTIFY valuesChanged)
|
||||
|
||||
public:
|
||||
explicit CavaProvider(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit CavaProvider(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] int bars() const;
|
||||
void setBars(int bars);
|
||||
[[nodiscard]] int bars() const;
|
||||
void setBars(int bars);
|
||||
|
||||
[[nodiscard]] QVector<double> values() const;
|
||||
[[nodiscard]] QVector<double> values() const;
|
||||
|
||||
signals:
|
||||
void barsChanged();
|
||||
void valuesChanged();
|
||||
signals:
|
||||
void barsChanged();
|
||||
void valuesChanged();
|
||||
|
||||
private:
|
||||
int m_bars;
|
||||
QVector<double> m_values;
|
||||
private:
|
||||
int m_bars;
|
||||
QVector<double> m_values;
|
||||
|
||||
void updateValues(QVector<double> values);
|
||||
void updateValues(QVector<double> values);
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
|
||||
namespace ZShell::services {
|
||||
|
||||
Cpu::Cpu(QObject* parent)
|
||||
: TickingService(parent) {
|
||||
Cpu::Cpu(QObject* parent) : TickingService(parent) {
|
||||
readNameOnce();
|
||||
}
|
||||
|
||||
@@ -41,7 +40,8 @@ void Cpu::readNameOnce() {
|
||||
const QByteArray data = f.readAll();
|
||||
f.close();
|
||||
|
||||
static const QRegularExpression re(QStringLiteral("model name\\s*:\\s*(.+)"));
|
||||
static const QRegularExpression re(
|
||||
QStringLiteral("model name\\s*:\\s*(.+)"));
|
||||
const auto match = re.match(QString::fromLatin1(data));
|
||||
if (!match.hasMatch()) {
|
||||
return;
|
||||
@@ -64,8 +64,9 @@ void Cpu::refreshPercentage() {
|
||||
const QByteArray data = f.readAll();
|
||||
f.close();
|
||||
|
||||
static const QRegularExpression re(
|
||||
QStringLiteral("^cpu\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"));
|
||||
static const QRegularExpression re(QStringLiteral(
|
||||
"^cpu\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)"
|
||||
"\\s+(\\d+)\\s+(\\d+)"));
|
||||
const auto match = re.match(QString::fromLatin1(data));
|
||||
if (!match.hasMatch()) {
|
||||
return;
|
||||
@@ -83,7 +84,10 @@ void Cpu::refreshPercentage() {
|
||||
|
||||
const quint64 totalDiff = total > m_lastTotal ? total - m_lastTotal : 0;
|
||||
const quint64 idleDiff = idle > m_lastIdle ? idle - m_lastIdle : 0;
|
||||
const qreal newPerc = totalDiff > 0 ? 1.0 - static_cast<qreal>(idleDiff) / static_cast<qreal>(totalDiff) : 0.0;
|
||||
const qreal newPerc =
|
||||
totalDiff > 0
|
||||
? 1.0 - static_cast<qreal>(idleDiff) / static_cast<qreal>(totalDiff)
|
||||
: 0.0;
|
||||
|
||||
m_lastTotal = total;
|
||||
m_lastIdle = idle;
|
||||
@@ -105,7 +109,8 @@ void Cpu::refreshTemperature() {
|
||||
|
||||
QString Cpu::cleanName(QString s) {
|
||||
static const QRegularExpression noise(
|
||||
QStringLiteral("\\(R\\)|\\(TM\\)|CPU|\\d+(?:th|nd|rd|st) Gen |Core |Processor"),
|
||||
QStringLiteral(
|
||||
"\\(R\\)|\\(TM\\)|CPU|\\d+(?:th|nd|rd|st) Gen |Core |Processor"),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
static const QRegularExpression spaces(QStringLiteral("\\s+"));
|
||||
|
||||
|
||||
@@ -7,42 +7,42 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class Cpu : public TickingService {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
|
||||
Q_PROPERTY(qreal temperature READ temperature NOTIFY temperatureChanged)
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
|
||||
Q_PROPERTY(qreal temperature READ temperature NOTIFY temperatureChanged)
|
||||
|
||||
public:
|
||||
explicit Cpu(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit Cpu(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] QString name() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] qreal temperature() const;
|
||||
[[nodiscard]] QString name() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] qreal temperature() const;
|
||||
|
||||
signals:
|
||||
void nameChanged();
|
||||
void percentageChanged();
|
||||
void temperatureChanged();
|
||||
signals:
|
||||
void nameChanged();
|
||||
void percentageChanged();
|
||||
void temperatureChanged();
|
||||
|
||||
protected:
|
||||
void tick() override;
|
||||
protected:
|
||||
void tick() override;
|
||||
|
||||
private:
|
||||
void readNameOnce();
|
||||
void refreshPercentage();
|
||||
void refreshTemperature();
|
||||
private:
|
||||
void readNameOnce();
|
||||
void refreshPercentage();
|
||||
void refreshTemperature();
|
||||
|
||||
[[nodiscard]] static QString cleanName(QString s);
|
||||
[[nodiscard]] static QString cleanName(QString s);
|
||||
|
||||
QString m_name;
|
||||
qreal m_percentage = 0.0;
|
||||
qreal m_temperature = 0.0;
|
||||
quint64 m_lastIdle = 0;
|
||||
quint64 m_lastTotal = 0;
|
||||
bool m_nameLoaded = false;
|
||||
QString m_name;
|
||||
qreal m_percentage = 0.0;
|
||||
qreal m_temperature = 0.0;
|
||||
quint64 m_lastIdle = 0;
|
||||
quint64 m_lastTotal = 0;
|
||||
bool m_nameLoaded = false;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -17,49 +17,57 @@ struct DesktopItem {
|
||||
};
|
||||
|
||||
class DesktopModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
enum DesktopRoles {
|
||||
FileNameRole = Qt::UserRole + 1,
|
||||
FilePathRole,
|
||||
IsDirRole,
|
||||
GridXRole,
|
||||
GridYRole
|
||||
public:
|
||||
enum DesktopRoles {
|
||||
FileNameRole = Qt::UserRole + 1,
|
||||
FilePathRole,
|
||||
IsDirRole,
|
||||
GridXRole,
|
||||
GridYRole
|
||||
};
|
||||
|
||||
explicit DesktopModel(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] int rowCount(
|
||||
const QModelIndex& parent = QModelIndex()) const override;
|
||||
[[nodiscard]] QVariant data(
|
||||
const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void loadDirectory(const QString& path);
|
||||
Q_INVOKABLE void moveIcon(int index, int newX, int newY);
|
||||
Q_INVOKABLE void massMove(
|
||||
const QVariantList& selectedPathsList,
|
||||
const QString& leaderPath,
|
||||
int targetX,
|
||||
int targetY,
|
||||
int maxCol,
|
||||
int maxRow);
|
||||
|
||||
Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
|
||||
|
||||
[[nodiscard]] int rows() const { return m_rows; }
|
||||
void setRows(int r) {
|
||||
if (m_rows != r) {
|
||||
m_rows = r;
|
||||
emit rowsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
void rowsChanged();
|
||||
|
||||
private:
|
||||
int m_rows = 1;
|
||||
QList<DesktopItem> m_items;
|
||||
QString m_watchedPath;
|
||||
QFileSystemWatcher m_watcher;
|
||||
void saveCurrentLayout();
|
||||
[[nodiscard]] QPoint getEmptySpot(const QSet<QString>& occupied) const;
|
||||
void onDirectoryChanged();
|
||||
};
|
||||
|
||||
explicit DesktopModel(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void loadDirectory(const QString &path);
|
||||
Q_INVOKABLE void moveIcon(int index, int newX, int newY);
|
||||
Q_INVOKABLE void massMove(const QVariantList &selectedPathsList, const QString &leaderPath, int targetX, int targetY, int maxCol, int maxRow);
|
||||
|
||||
Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
|
||||
|
||||
public:
|
||||
[[nodiscard]] int rows() const {
|
||||
return m_rows;
|
||||
}
|
||||
void setRows(int r) {
|
||||
if (m_rows != r) { m_rows = r; emit rowsChanged(); }
|
||||
}
|
||||
|
||||
signals:
|
||||
void rowsChanged();
|
||||
|
||||
private:
|
||||
int m_rows = 1;
|
||||
QList<DesktopItem> m_items;
|
||||
QString m_watchedPath;
|
||||
QFileSystemWatcher m_watcher;
|
||||
void saveCurrentLayout();
|
||||
[[nodiscard]] QPoint getEmptySpot(const QSet<QString> &occupied) const;
|
||||
void onDirectoryChanged();
|
||||
};
|
||||
|
||||
};
|
||||
}; // namespace ZShell::services
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
|
||||
namespace ZShell::services {
|
||||
|
||||
DesktopStateManager::DesktopStateManager(QObject *parent) : QObject(parent) {
|
||||
}
|
||||
DesktopStateManager::DesktopStateManager(QObject* parent) : QObject(parent) {}
|
||||
|
||||
QString DesktopStateManager::getConfigFilePath() const {
|
||||
QString configDir = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/zshell";
|
||||
QString configDir =
|
||||
QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) +
|
||||
"/zshell";
|
||||
QDir dir(configDir);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
@@ -30,7 +31,8 @@ void DesktopStateManager::saveLayout(const QVariantMap& layout) {
|
||||
file.write(doc.toJson(QJsonDocument::Indented));
|
||||
file.close();
|
||||
} else {
|
||||
qWarning() << "zshell: Cannot save desktop layout to" << getConfigFilePath();
|
||||
qWarning() << "zshell: Cannot save desktop layout to"
|
||||
<< getConfigFilePath();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,18 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class DesktopStateManager : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
public:
|
||||
explicit DesktopStateManager(QObject *parent = nullptr);
|
||||
public:
|
||||
explicit DesktopStateManager(QObject* parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void saveLayout(const QVariantMap& layout);
|
||||
Q_INVOKABLE QVariantMap getLayout();
|
||||
Q_INVOKABLE void saveLayout(const QVariantMap& layout);
|
||||
Q_INVOKABLE QVariantMap getLayout();
|
||||
|
||||
private:
|
||||
[[nodiscard]] QString getConfigFilePath() const;
|
||||
private:
|
||||
[[nodiscard]] QString getConfigFilePath() const;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -8,13 +8,17 @@ constexpr qreal kKib = 1024.0;
|
||||
|
||||
} // namespace
|
||||
|
||||
DiskInfo::DiskInfo(QString mount, quint64 usedBytes, quint64 totalBytes, bool hasRoot, QObject* parent)
|
||||
DiskInfo::DiskInfo(
|
||||
QString mount,
|
||||
quint64 usedBytes,
|
||||
quint64 totalBytes,
|
||||
bool hasRoot,
|
||||
QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_mount(std::move(mount))
|
||||
, m_usedBytes(usedBytes)
|
||||
, m_totalBytes(totalBytes)
|
||||
, m_hasRoot(hasRoot) {
|
||||
}
|
||||
, m_hasRoot(hasRoot) {}
|
||||
|
||||
QString DiskInfo::mount() const {
|
||||
return m_mount;
|
||||
@@ -29,12 +33,15 @@ qreal DiskInfo::total() const {
|
||||
}
|
||||
|
||||
qreal DiskInfo::free() const {
|
||||
const quint64 freeBytes = m_totalBytes > m_usedBytes ? m_totalBytes - m_usedBytes : 0;
|
||||
const quint64 freeBytes =
|
||||
m_totalBytes > m_usedBytes ? m_totalBytes - m_usedBytes : 0;
|
||||
return static_cast<qreal>(freeBytes) / kKib;
|
||||
}
|
||||
|
||||
qreal DiskInfo::perc() const {
|
||||
return m_totalBytes > 0 ? static_cast<qreal>(m_usedBytes) / static_cast<qreal>(m_totalBytes) : 0.0;
|
||||
return m_totalBytes > 0 ? static_cast<qreal>(m_usedBytes) /
|
||||
static_cast<qreal>(m_totalBytes)
|
||||
: 0.0;
|
||||
}
|
||||
|
||||
bool DiskInfo::hasRoot() const {
|
||||
|
||||
@@ -6,41 +6,46 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class DiskInfo : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("DiskInfo is created by DiskUsage")
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("DiskInfo is created by DiskUsage")
|
||||
|
||||
Q_PROPERTY(QString mount READ mount CONSTANT)
|
||||
Q_PROPERTY(qreal used READ used NOTIFY usedChanged)
|
||||
Q_PROPERTY(qreal total READ total NOTIFY totalChanged)
|
||||
Q_PROPERTY(qreal free READ free NOTIFY freeChanged)
|
||||
Q_PROPERTY(qreal perc READ perc NOTIFY percChanged)
|
||||
Q_PROPERTY(bool hasRoot READ hasRoot NOTIFY hasRootChanged)
|
||||
Q_PROPERTY(QString mount READ mount CONSTANT)
|
||||
Q_PROPERTY(qreal used READ used NOTIFY usedChanged)
|
||||
Q_PROPERTY(qreal total READ total NOTIFY totalChanged)
|
||||
Q_PROPERTY(qreal free READ free NOTIFY freeChanged)
|
||||
Q_PROPERTY(qreal perc READ perc NOTIFY percChanged)
|
||||
Q_PROPERTY(bool hasRoot READ hasRoot NOTIFY hasRootChanged)
|
||||
|
||||
public:
|
||||
DiskInfo(QString mount, quint64 usedBytes, quint64 totalBytes, bool hasRoot, QObject* parent = nullptr);
|
||||
public:
|
||||
DiskInfo(
|
||||
QString mount,
|
||||
quint64 usedBytes,
|
||||
quint64 totalBytes,
|
||||
bool hasRoot,
|
||||
QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] QString mount() const;
|
||||
[[nodiscard]] qreal used() const;
|
||||
[[nodiscard]] qreal total() const;
|
||||
[[nodiscard]] qreal free() const;
|
||||
[[nodiscard]] qreal perc() const;
|
||||
[[nodiscard]] bool hasRoot() const;
|
||||
[[nodiscard]] QString mount() const;
|
||||
[[nodiscard]] qreal used() const;
|
||||
[[nodiscard]] qreal total() const;
|
||||
[[nodiscard]] qreal free() const;
|
||||
[[nodiscard]] qreal perc() const;
|
||||
[[nodiscard]] bool hasRoot() const;
|
||||
|
||||
void update(quint64 usedBytes, quint64 totalBytes, bool hasRoot);
|
||||
void update(quint64 usedBytes, quint64 totalBytes, bool hasRoot);
|
||||
|
||||
signals:
|
||||
void usedChanged();
|
||||
void totalChanged();
|
||||
void freeChanged();
|
||||
void percChanged();
|
||||
void hasRootChanged();
|
||||
signals:
|
||||
void usedChanged();
|
||||
void totalChanged();
|
||||
void freeChanged();
|
||||
void percChanged();
|
||||
void hasRootChanged();
|
||||
|
||||
private:
|
||||
QString m_mount;
|
||||
quint64 m_usedBytes;
|
||||
quint64 m_totalBytes;
|
||||
bool m_hasRoot;
|
||||
private:
|
||||
QString m_mount;
|
||||
quint64 m_usedBytes;
|
||||
quint64 m_totalBytes;
|
||||
bool m_hasRoot;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -8,81 +8,81 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class Gpu : public TickingService {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
public:
|
||||
enum Type {
|
||||
Auto, // user override is empty (config "") — defer to detected autoType
|
||||
None, // no usable GPU
|
||||
Nvidia, // queried via nvidia-smi
|
||||
Generic, // queried via /sys/class/drm/card*/device/gpu_busy_percent
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
public:
|
||||
enum Type {
|
||||
Auto, // user override is empty (config "") — defer to detected autoType
|
||||
None, // no usable GPU
|
||||
Nvidia, // queried via nvidia-smi
|
||||
Generic, // queried via /sys/class/drm/card*/device/gpu_busy_percent
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
|
||||
private:
|
||||
Q_PROPERTY(Type type READ type NOTIFY typeChanged)
|
||||
Q_PROPERTY(Type userType READ userType NOTIFY userTypeChanged)
|
||||
Q_PROPERTY(Type autoType READ autoType NOTIFY autoTypeChanged)
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
|
||||
Q_PROPERTY(qreal temperature READ temperature NOTIFY temperatureChanged)
|
||||
Q_PROPERTY(qreal memoryUsed READ memoryUsed NOTIFY memoryUsedChanged)
|
||||
Q_PROPERTY(qreal memoryTotal READ memoryTotal NOTIFY memoryTotalChanged)
|
||||
private:
|
||||
Q_PROPERTY(Type type READ type NOTIFY typeChanged)
|
||||
Q_PROPERTY(Type userType READ userType NOTIFY userTypeChanged)
|
||||
Q_PROPERTY(Type autoType READ autoType NOTIFY autoTypeChanged)
|
||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
|
||||
Q_PROPERTY(qreal temperature READ temperature NOTIFY temperatureChanged)
|
||||
Q_PROPERTY(qreal memoryUsed READ memoryUsed NOTIFY memoryUsedChanged)
|
||||
Q_PROPERTY(qreal memoryTotal READ memoryTotal NOTIFY memoryTotalChanged)
|
||||
|
||||
public:
|
||||
explicit Gpu(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit Gpu(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] Type type() const;
|
||||
[[nodiscard]] Type userType() const;
|
||||
[[nodiscard]] Type autoType() const;
|
||||
[[nodiscard]] QString name() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] qreal temperature() const;
|
||||
[[nodiscard]] qreal memoryUsed() const;
|
||||
[[nodiscard]] qreal memoryTotal() const;
|
||||
[[nodiscard]] Type type() const;
|
||||
[[nodiscard]] Type userType() const;
|
||||
[[nodiscard]] Type autoType() const;
|
||||
[[nodiscard]] QString name() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] qreal temperature() const;
|
||||
[[nodiscard]] qreal memoryUsed() const;
|
||||
[[nodiscard]] qreal memoryTotal() const;
|
||||
|
||||
signals:
|
||||
void typeChanged();
|
||||
void userTypeChanged();
|
||||
void autoTypeChanged();
|
||||
void nameChanged();
|
||||
void percentageChanged();
|
||||
void temperatureChanged();
|
||||
void memoryUsedChanged();
|
||||
void memoryTotalChanged();
|
||||
signals:
|
||||
void typeChanged();
|
||||
void userTypeChanged();
|
||||
void autoTypeChanged();
|
||||
void nameChanged();
|
||||
void percentageChanged();
|
||||
void temperatureChanged();
|
||||
void memoryUsedChanged();
|
||||
void memoryTotalChanged();
|
||||
|
||||
protected:
|
||||
void tick() override;
|
||||
protected:
|
||||
void tick() override;
|
||||
|
||||
private:
|
||||
void detectTypeOnce();
|
||||
void detectNameOnce();
|
||||
void readGenericUsage();
|
||||
void startNvidiaUsage();
|
||||
void readGpuTemperature();
|
||||
private:
|
||||
void detectTypeOnce();
|
||||
void detectNameOnce();
|
||||
void readGenericUsage();
|
||||
void startNvidiaUsage();
|
||||
void readGpuTemperature();
|
||||
|
||||
void setUserType(Type value);
|
||||
void setAutoType(Type value);
|
||||
void setName(QString value);
|
||||
void setMemoryUsed(qreal value);
|
||||
void setMemoryTotal(qreal value);
|
||||
void setUserType(Type value);
|
||||
void setAutoType(Type value);
|
||||
void setName(QString value);
|
||||
void setMemoryUsed(qreal value);
|
||||
void setMemoryTotal(qreal value);
|
||||
|
||||
[[nodiscard]] static Type parseType(const QString& s);
|
||||
[[nodiscard]] static QString cleanName(QString s);
|
||||
[[nodiscard]] static Type parseType(const QString& s);
|
||||
[[nodiscard]] static QString cleanName(QString s);
|
||||
|
||||
Type m_userType = Auto;
|
||||
Type m_autoType = None;
|
||||
QString m_name;
|
||||
qreal m_percentage = 0.0;
|
||||
qreal m_temperature = 0.0;
|
||||
qreal m_memoryUsed = 0.0;
|
||||
qreal m_memoryTotal = 0.0;
|
||||
Type m_userType = Auto;
|
||||
Type m_autoType = None;
|
||||
QString m_name;
|
||||
qreal m_percentage = 0.0;
|
||||
qreal m_temperature = 0.0;
|
||||
qreal m_memoryUsed = 0.0;
|
||||
qreal m_memoryTotal = 0.0;
|
||||
|
||||
QProcess* m_typeProc = nullptr;
|
||||
QProcess* m_nameProc = nullptr;
|
||||
QProcess* m_nvidiaProc = nullptr;
|
||||
QProcess* m_typeProc = nullptr;
|
||||
QProcess* m_nameProc = nullptr;
|
||||
QProcess* m_nvidiaProc = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -9,14 +9,14 @@ namespace ZShell::services {
|
||||
HyprsunsetManager::HyprsunsetManager(QObject* parent) : QObject(parent) {
|
||||
connect(&m_timer, &QTimer::timeout, this, &HyprsunsetManager::apply);
|
||||
connect(&m_manualTimer, &QTimer::timeout, this, [this] {
|
||||
m_manualToggle = false;
|
||||
emit manualToggleChanged();
|
||||
apply();
|
||||
});
|
||||
m_manualToggle = false;
|
||||
emit manualToggleChanged();
|
||||
apply();
|
||||
});
|
||||
connect(&m_startCooldown, &QTimer::timeout, this, [this] {
|
||||
m_startAllowed = true;
|
||||
apply();
|
||||
});
|
||||
m_startAllowed = true;
|
||||
apply();
|
||||
});
|
||||
|
||||
m_startCooldown.start(2000);
|
||||
m_manualTimer.setSingleShot(true);
|
||||
@@ -51,16 +51,14 @@ int HyprsunsetManager::temp() const {
|
||||
}
|
||||
|
||||
void HyprsunsetManager::setActiveAuto(bool activeAuto) {
|
||||
if (activeAuto == m_activeAuto)
|
||||
return;
|
||||
if (activeAuto == m_activeAuto) return;
|
||||
|
||||
m_activeAuto = activeAuto;
|
||||
emit activeAutoChanged();
|
||||
}
|
||||
|
||||
void HyprsunsetManager::setManualToggle(bool toggle) {
|
||||
if (toggle == m_manualToggle)
|
||||
return;
|
||||
if (toggle == m_manualToggle) return;
|
||||
|
||||
m_manualToggle = toggle;
|
||||
emit manualToggleChanged();
|
||||
@@ -69,8 +67,7 @@ void HyprsunsetManager::setManualToggle(bool toggle) {
|
||||
}
|
||||
|
||||
void HyprsunsetManager::setEndTime(const int& time) {
|
||||
if (time == m_endTime)
|
||||
return;
|
||||
if (time == m_endTime) return;
|
||||
|
||||
m_endTime = time;
|
||||
emit endTimeChanged();
|
||||
@@ -78,8 +75,7 @@ void HyprsunsetManager::setEndTime(const int& time) {
|
||||
}
|
||||
|
||||
void HyprsunsetManager::setStartTime(const int& time) {
|
||||
if (time == m_startTime)
|
||||
return;
|
||||
if (time == m_startTime) return;
|
||||
|
||||
m_startTime = time;
|
||||
emit startTimeChanged();
|
||||
@@ -87,8 +83,7 @@ void HyprsunsetManager::setStartTime(const int& time) {
|
||||
}
|
||||
|
||||
void HyprsunsetManager::setTemp(const int& temp) {
|
||||
if (temp == m_temp)
|
||||
return;
|
||||
if (temp == m_temp) return;
|
||||
|
||||
m_temp = temp;
|
||||
emit tempChanged();
|
||||
@@ -104,8 +99,7 @@ void HyprsunsetManager::toggle() {
|
||||
}
|
||||
|
||||
void HyprsunsetManager::start() {
|
||||
if (m_enabled && m_initialized)
|
||||
return;
|
||||
if (m_enabled && m_initialized) return;
|
||||
|
||||
m_initialized = true;
|
||||
m_enabled = true;
|
||||
@@ -113,13 +107,13 @@ void HyprsunsetManager::start() {
|
||||
emit enabledChanged();
|
||||
|
||||
m_process.setProgram("hyprctl");
|
||||
m_process.setArguments({"hyprsunset", "temperature", QString::number(m_temp)});
|
||||
m_process.setArguments(
|
||||
{"hyprsunset", "temperature", QString::number(m_temp)});
|
||||
m_process.startDetached();
|
||||
}
|
||||
|
||||
void HyprsunsetManager::end() {
|
||||
if (!m_enabled && m_initialized)
|
||||
return;
|
||||
if (!m_enabled && m_initialized) return;
|
||||
|
||||
m_initialized = true;
|
||||
m_enabled = false;
|
||||
@@ -132,12 +126,11 @@ void HyprsunsetManager::end() {
|
||||
}
|
||||
|
||||
void HyprsunsetManager::apply() {
|
||||
if (m_manualToggle || !m_activeAuto || !m_startAllowed)
|
||||
return;
|
||||
if (m_manualToggle || !m_activeAuto || !m_startAllowed) return;
|
||||
|
||||
const auto current = QTime::currentTime();
|
||||
const auto currentMin = current.hour() * 60 + current.minute();
|
||||
bool isDarkTime;
|
||||
bool isDarkTime = false;
|
||||
|
||||
if (m_startTime <= m_endTime) {
|
||||
isDarkTime = (currentMin >= m_startTime && currentMin < m_endTime);
|
||||
@@ -152,4 +145,4 @@ void HyprsunsetManager::apply() {
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}; // namespace ZShell::services
|
||||
|
||||
@@ -10,57 +10,62 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class HyprsunsetManager : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||
Q_PROPERTY(int endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
|
||||
Q_PROPERTY(int temp READ temp WRITE setTemp NOTIFY tempChanged)
|
||||
Q_PROPERTY(bool activeAuto READ activeAuto WRITE setActiveAuto NOTIFY activeAutoChanged)
|
||||
Q_PROPERTY(bool manualToggle READ manualToggle WRITE setManualToggle NOTIFY manualToggleChanged)
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(
|
||||
int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||
Q_PROPERTY(int endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
|
||||
Q_PROPERTY(int temp READ temp WRITE setTemp NOTIFY tempChanged)
|
||||
Q_PROPERTY(
|
||||
bool activeAuto READ activeAuto WRITE setActiveAuto NOTIFY
|
||||
activeAutoChanged)
|
||||
Q_PROPERTY(
|
||||
bool manualToggle READ manualToggle WRITE setManualToggle NOTIFY
|
||||
manualToggleChanged)
|
||||
|
||||
public:
|
||||
explicit HyprsunsetManager(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit HyprsunsetManager(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] int startTime() const;
|
||||
[[nodiscard]] int endTime() const;
|
||||
[[nodiscard]] bool enabled() const;
|
||||
[[nodiscard]] int temp() const;
|
||||
[[nodiscard]] bool activeAuto() const;
|
||||
[[nodiscard]] bool manualToggle() const;
|
||||
[[nodiscard]] int startTime() const;
|
||||
[[nodiscard]] int endTime() const;
|
||||
[[nodiscard]] bool enabled() const;
|
||||
[[nodiscard]] int temp() const;
|
||||
[[nodiscard]] bool activeAuto() const;
|
||||
[[nodiscard]] bool manualToggle() const;
|
||||
|
||||
Q_INVOKABLE void toggle();
|
||||
Q_INVOKABLE void apply();
|
||||
Q_INVOKABLE void toggle();
|
||||
Q_INVOKABLE void apply();
|
||||
|
||||
void setStartTime(const int& time);
|
||||
void setEndTime(const int& time);
|
||||
void setTemp(const int& temp);
|
||||
void setActiveAuto(bool activeAuto);
|
||||
void setManualToggle(bool toggle);
|
||||
void setStartTime(const int& time);
|
||||
void setEndTime(const int& time);
|
||||
void setTemp(const int& temp);
|
||||
void setActiveAuto(bool activeAuto);
|
||||
void setManualToggle(bool toggle);
|
||||
|
||||
signals:
|
||||
void enabledChanged();
|
||||
void startTimeChanged();
|
||||
void activeAutoChanged();
|
||||
void endTimeChanged();
|
||||
void tempChanged();
|
||||
void manualToggleChanged();
|
||||
signals:
|
||||
void enabledChanged();
|
||||
void startTimeChanged();
|
||||
void activeAutoChanged();
|
||||
void endTimeChanged();
|
||||
void tempChanged();
|
||||
void manualToggleChanged();
|
||||
|
||||
private:
|
||||
int m_startTime;
|
||||
int m_endTime;
|
||||
bool m_enabled = false;
|
||||
bool m_manualToggle = false;
|
||||
bool m_activeAuto;
|
||||
bool m_startAllowed = false;
|
||||
bool m_initialized = false;
|
||||
QTimer m_startCooldown;
|
||||
int m_temp;
|
||||
QProcess m_process;
|
||||
QTimer m_timer;
|
||||
QTimer m_manualTimer;
|
||||
void start();
|
||||
void end();
|
||||
private:
|
||||
int m_startTime;
|
||||
int m_endTime;
|
||||
bool m_enabled = false;
|
||||
bool m_manualToggle = false;
|
||||
bool m_activeAuto;
|
||||
bool m_startAllowed = false;
|
||||
bool m_initialized = false;
|
||||
QTimer m_startCooldown;
|
||||
int m_temp;
|
||||
QProcess m_process;
|
||||
QTimer m_timer;
|
||||
QTimer m_manualTimer;
|
||||
void start();
|
||||
void end();
|
||||
};
|
||||
|
||||
};
|
||||
}; // namespace ZShell::services
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
|
||||
namespace ZShell::services {
|
||||
|
||||
Memory::Memory(QObject* parent)
|
||||
: TickingService(parent) {
|
||||
}
|
||||
Memory::Memory(QObject* parent) : TickingService(parent) {}
|
||||
|
||||
qreal Memory::used() const {
|
||||
return m_used;
|
||||
@@ -29,8 +27,10 @@ void Memory::tick() {
|
||||
const QByteArray data = f.readAll();
|
||||
f.close();
|
||||
|
||||
static const QRegularExpression reTotal(QStringLiteral("MemTotal: *(\\d+)"));
|
||||
static const QRegularExpression reAvail(QStringLiteral("MemAvailable: *(\\d+)"));
|
||||
static const QRegularExpression reTotal(
|
||||
QStringLiteral("MemTotal: *(\\d+)"));
|
||||
static const QRegularExpression reAvail(
|
||||
QStringLiteral("MemAvailable: *(\\d+)"));
|
||||
const QString text = QString::fromLatin1(data);
|
||||
|
||||
const auto totalMatch = reTotal.match(text);
|
||||
|
||||
@@ -8,32 +8,32 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class Memory : public TickingService {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
Q_PROPERTY(qreal used READ used NOTIFY changed)
|
||||
Q_PROPERTY(qreal total READ total NOTIFY changed)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY changed)
|
||||
Q_PROPERTY(qreal used READ used NOTIFY changed)
|
||||
Q_PROPERTY(qreal total READ total NOTIFY changed)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY changed)
|
||||
|
||||
public:
|
||||
explicit Memory(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit Memory(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] qreal used() const;
|
||||
[[nodiscard]] qreal total() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] qreal used() const;
|
||||
[[nodiscard]] qreal total() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
protected:
|
||||
void tick() override;
|
||||
protected:
|
||||
void tick() override;
|
||||
|
||||
private:
|
||||
qreal m_used = 0.0;
|
||||
qreal m_total = 1.0;
|
||||
quint64 m_lastUsed = 0;
|
||||
quint64 m_lastTotal = 0;
|
||||
private:
|
||||
qreal m_used = 0.0;
|
||||
qreal m_total = 1.0;
|
||||
quint64 m_lastUsed = 0;
|
||||
quint64 m_lastTotal = 0;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ZShell::services::sensorslib {
|
||||
|
||||
namespace {
|
||||
|
||||
std::atomic<bool> g_initOk{ false };
|
||||
std::atomic<bool> g_initOk{false};
|
||||
std::once_flag g_initFlag;
|
||||
|
||||
void doInit() {
|
||||
@@ -25,14 +25,16 @@ void doInit() {
|
||||
}
|
||||
g_initOk.store(true, std::memory_order_release);
|
||||
std::atexit([] {
|
||||
if (g_initOk.load(std::memory_order_acquire)) {
|
||||
sensors_cleanup();
|
||||
}
|
||||
});
|
||||
if (g_initOk.load(std::memory_order_acquire)) {
|
||||
sensors_cleanup();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<double> readTempInput(const sensors_chip_name* chip, const sensors_feature* feat) {
|
||||
const sensors_subfeature* sf = sensors_get_subfeature(chip, feat, SENSORS_SUBFEATURE_TEMP_INPUT);
|
||||
[[nodiscard]] std::optional<double> readTempInput(
|
||||
const sensors_chip_name* chip, const sensors_feature* feat) {
|
||||
const sensors_subfeature* sf =
|
||||
sensors_get_subfeature(chip, feat, SENSORS_SUBFEATURE_TEMP_INPUT);
|
||||
if (!sf) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -43,7 +45,8 @@ void doInit() {
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]] QByteArray featureLabel(const sensors_chip_name* chip, const sensors_feature* feat) {
|
||||
[[nodiscard]] QByteArray featureLabel(
|
||||
const sensors_chip_name* chip, const sensors_feature* feat) {
|
||||
char* raw = sensors_get_label(chip, feat);
|
||||
if (!raw) {
|
||||
return {};
|
||||
@@ -59,7 +62,8 @@ bool labelEquals(const QByteArray& label, const char* literal) {
|
||||
|
||||
bool labelStartsWith(const QByteArray& label, const char* prefix) {
|
||||
const auto n = std::strlen(prefix);
|
||||
return static_cast<size_t>(label.size()) >= n && std::memcmp(label.constData(), prefix, n) == 0;
|
||||
return static_cast<size_t>(label.size()) >= n &&
|
||||
std::memcmp(label.constData(), prefix, n) == 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -74,13 +78,15 @@ std::optional<double> cpuPackageTemp() {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<double> primary; // Package id N / Tdie
|
||||
std::optional<double> primary; // Package id N / Tdie
|
||||
std::optional<double> fallback; // Tctl
|
||||
|
||||
int chipNr = 0;
|
||||
while (const sensors_chip_name* chip = sensors_get_detected_chips(nullptr, &chipNr)) {
|
||||
while (const sensors_chip_name* chip =
|
||||
sensors_get_detected_chips(nullptr, &chipNr)) {
|
||||
int featNr = 0;
|
||||
while (const sensors_feature* feat = sensors_get_features(chip, &featNr)) {
|
||||
while (const sensors_feature* feat =
|
||||
sensors_get_features(chip, &featNr)) {
|
||||
if (feat->type != SENSORS_FEATURE_TEMP) {
|
||||
continue;
|
||||
}
|
||||
@@ -89,7 +95,8 @@ std::optional<double> cpuPackageTemp() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (labelStartsWith(label, "Package id ") || labelEquals(label, "Tdie")) {
|
||||
if (labelStartsWith(label, "Package id ") ||
|
||||
labelEquals(label, "Tdie")) {
|
||||
if (auto v = readTempInput(chip, feat)) {
|
||||
primary = v;
|
||||
}
|
||||
@@ -116,13 +123,15 @@ std::optional<double> gpuPciAverageTemp() {
|
||||
int countFallback = 0;
|
||||
|
||||
int chipNr = 0;
|
||||
while (const sensors_chip_name* chip = sensors_get_detected_chips(nullptr, &chipNr)) {
|
||||
while (const sensors_chip_name* chip =
|
||||
sensors_get_detected_chips(nullptr, &chipNr)) {
|
||||
if (chip->bus.type != SENSORS_BUS_TYPE_PCI) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int featNr = 0;
|
||||
while (const sensors_feature* feat = sensors_get_features(chip, &featNr)) {
|
||||
while (const sensors_feature* feat =
|
||||
sensors_get_features(chip, &featNr)) {
|
||||
if (feat->type != SENSORS_FEATURE_TEMP) {
|
||||
continue;
|
||||
}
|
||||
@@ -131,10 +140,14 @@ std::optional<double> gpuPciAverageTemp() {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool tempIndexed = labelStartsWith(label, "temp") && label.size() > 4 &&
|
||||
std::isdigit(static_cast<unsigned char>(label[4]));
|
||||
const bool isPrimary = tempIndexed || labelEquals(label, "GPU core") || labelEquals(label, "edge");
|
||||
const bool isFallback = labelEquals(label, "junction") || labelEquals(label, "mem");
|
||||
const bool tempIndexed =
|
||||
labelStartsWith(label, "temp") && label.size() > 4 &&
|
||||
std::isdigit(static_cast<unsigned char>(label[4]));
|
||||
const bool isPrimary = tempIndexed ||
|
||||
labelEquals(label, "GPU core") ||
|
||||
labelEquals(label, "edge");
|
||||
const bool isFallback = labelEquals(label, "junction") ||
|
||||
labelEquals(label, "mem");
|
||||
|
||||
if (!isPrimary && !isFallback) {
|
||||
continue;
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
|
||||
namespace ZShell::services {
|
||||
|
||||
Service::Service(QObject* parent)
|
||||
: QObject(parent) {
|
||||
}
|
||||
Service::Service(QObject* parent) : QObject(parent) {}
|
||||
|
||||
void Service::ref(QObject* sender) {
|
||||
if (m_refs.isEmpty()) {
|
||||
|
||||
@@ -6,19 +6,19 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class Service : public QObject {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Service(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit Service(QObject* parent = nullptr);
|
||||
|
||||
void ref(QObject* sender);
|
||||
void unref(QObject* sender);
|
||||
void ref(QObject* sender);
|
||||
void unref(QObject* sender);
|
||||
|
||||
private:
|
||||
QSet<QObject*> m_refs;
|
||||
private:
|
||||
QSet<QObject*> m_refs;
|
||||
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
ServiceRef::ServiceRef(Service* service, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_service(service) {
|
||||
: QObject(parent), m_service(service) {
|
||||
if (m_service) {
|
||||
m_service->ref(this);
|
||||
}
|
||||
|
||||
@@ -7,22 +7,24 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class ServiceRef : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(ZShell::services::Service* service READ service WRITE setService NOTIFY serviceChanged)
|
||||
Q_PROPERTY(
|
||||
ZShell::services::Service* service READ service WRITE setService NOTIFY
|
||||
serviceChanged)
|
||||
|
||||
public:
|
||||
explicit ServiceRef(Service* service = nullptr, QObject* parent = nullptr);
|
||||
public:
|
||||
explicit ServiceRef(Service* service = nullptr, QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] Service* service() const;
|
||||
void setService(Service* service);
|
||||
[[nodiscard]] Service* service() const;
|
||||
void setService(Service* service);
|
||||
|
||||
signals:
|
||||
void serviceChanged();
|
||||
signals:
|
||||
void serviceChanged();
|
||||
|
||||
private:
|
||||
QPointer<Service> m_service;
|
||||
private:
|
||||
QPointer<Service> m_service;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -24,12 +24,14 @@ struct Accum {
|
||||
};
|
||||
|
||||
[[nodiscard]] QString sysfsRealPath(uint major, uint minor) {
|
||||
const QString link = QStringLiteral("/sys/dev/block/%1:%2").arg(major).arg(minor);
|
||||
const QString link =
|
||||
QStringLiteral("/sys/dev/block/%1:%2").arg(major).arg(minor);
|
||||
const QString resolved = QFileInfo(link).canonicalFilePath();
|
||||
return resolved;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool readDevtFromSysfs(const QString& sysfsBlockDir, uint& major, uint& minor) {
|
||||
[[nodiscard]] bool readDevtFromSysfs(
|
||||
const QString& sysfsBlockDir, uint& major, uint& minor) {
|
||||
QFile f(sysfsBlockDir + QStringLiteral("/dev"));
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
return false;
|
||||
@@ -50,6 +52,7 @@ struct Accum {
|
||||
|
||||
QStringList resolveByDevt(uint major, uint minor, int depth = 0);
|
||||
|
||||
// NOLINTNEXTLINE(misc-no-recursion)
|
||||
QStringList resolveAtNode(const QString& node, int depth) {
|
||||
if (node.isEmpty() || depth > 8) {
|
||||
return {};
|
||||
@@ -62,18 +65,20 @@ QStringList resolveAtNode(const QString& node, int depth) {
|
||||
|
||||
if (QFileInfo::exists(node + QStringLiteral("/partition"))) {
|
||||
const QString diskNode = nodeInfo.path();
|
||||
return { QFileInfo(diskNode).fileName() };
|
||||
return {QFileInfo(diskNode).fileName()};
|
||||
}
|
||||
|
||||
const QDir slavesDir(node + QStringLiteral("/slaves"));
|
||||
if (slavesDir.exists()) {
|
||||
const QStringList slaves = slavesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
const QStringList slaves =
|
||||
slavesDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
if (!slaves.isEmpty()) {
|
||||
QStringList out;
|
||||
for (const QString& slave : slaves) {
|
||||
uint sm = 0;
|
||||
uint sn = 0;
|
||||
const QString slaveDir = QStringLiteral("/sys/class/block/") + slave;
|
||||
const QString slaveDir =
|
||||
QStringLiteral("/sys/class/block/") + slave;
|
||||
if (!readDevtFromSysfs(slaveDir, sm, sn)) {
|
||||
continue;
|
||||
}
|
||||
@@ -88,18 +93,17 @@ QStringList resolveAtNode(const QString& node, int depth) {
|
||||
}
|
||||
}
|
||||
|
||||
return { nodeInfo.fileName() };
|
||||
return {nodeInfo.fileName()};
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(misc-no-recursion)
|
||||
QStringList resolveByDevt(uint major, uint minor, int depth) {
|
||||
return resolveAtNode(sysfsRealPath(major, minor), depth);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Storage::Storage(QObject* parent)
|
||||
: TickingService(parent) {
|
||||
}
|
||||
Storage::Storage(QObject* parent) : TickingService(parent) {}
|
||||
|
||||
qreal Storage::percentage() const {
|
||||
qreal totalUsed = 0.0;
|
||||
@@ -124,7 +128,8 @@ bool Storage::sameOrder(const QList<DiskInfo*>& a, const QList<DiskInfo*>& b) {
|
||||
}
|
||||
|
||||
QQmlListProperty<DiskInfo> Storage::disksProp() {
|
||||
return QQmlListProperty<DiskInfo>(this, nullptr, &Storage::disksCount, &Storage::disksAt);
|
||||
return QQmlListProperty<DiskInfo>(
|
||||
this, nullptr, &Storage::disksCount, &Storage::disksAt);
|
||||
}
|
||||
|
||||
qsizetype Storage::disksCount(QQmlListProperty<DiskInfo>* prop) {
|
||||
@@ -157,30 +162,11 @@ DiskInfo* Storage::primaryDisk() const {
|
||||
|
||||
bool Storage::isPseudoFs(QByteArrayView fsType) {
|
||||
static constexpr const char* kPseudo[] = {
|
||||
"tmpfs",
|
||||
"devtmpfs",
|
||||
"proc",
|
||||
"sysfs",
|
||||
"cgroup",
|
||||
"cgroup2",
|
||||
"overlay",
|
||||
"squashfs",
|
||||
"devpts",
|
||||
"mqueue",
|
||||
"ramfs",
|
||||
"rpc_pipefs",
|
||||
"autofs",
|
||||
"configfs",
|
||||
"debugfs",
|
||||
"tracefs",
|
||||
"securityfs",
|
||||
"pstore",
|
||||
"bpf",
|
||||
"binfmt_misc",
|
||||
"hugetlbfs",
|
||||
"fusectl",
|
||||
"efivarfs",
|
||||
"selinuxfs",
|
||||
"tmpfs", "devtmpfs", "proc", "sysfs", "cgroup",
|
||||
"cgroup2", "overlay", "squashfs", "devpts", "mqueue",
|
||||
"ramfs", "rpc_pipefs", "autofs", "configfs", "debugfs",
|
||||
"tracefs", "securityfs", "pstore", "bpf", "binfmt_misc",
|
||||
"hugetlbfs", "fusectl", "efivarfs", "selinuxfs",
|
||||
};
|
||||
for (const char* p : kPseudo) {
|
||||
if (fsType == QByteArrayView(p)) {
|
||||
@@ -194,7 +180,7 @@ QStringList Storage::resolveToPhysicalDisks(const QString& devicePath) {
|
||||
if (devicePath.isEmpty() || !devicePath.startsWith(QLatin1Char('/'))) {
|
||||
return {};
|
||||
}
|
||||
struct stat st {};
|
||||
struct stat st{};
|
||||
if (::stat(devicePath.toLocal8Bit().constData(), &st) != 0) {
|
||||
return {};
|
||||
}
|
||||
@@ -232,7 +218,8 @@ void Storage::tick() {
|
||||
const QByteArray device = v.device();
|
||||
const auto totalBytes = static_cast<quint64>(v.bytesTotal());
|
||||
const auto availBytes = static_cast<quint64>(v.bytesAvailable());
|
||||
const quint64 usedBytes = totalBytes > availBytes ? totalBytes - availBytes : 0;
|
||||
const quint64 usedBytes =
|
||||
totalBytes > availBytes ? totalBytes - availBytes : 0;
|
||||
const bool isRoot = v.rootPath() == QStringLiteral("/");
|
||||
|
||||
DeviceEntry& e = byDevice[device];
|
||||
@@ -244,7 +231,8 @@ void Storage::tick() {
|
||||
|
||||
for (auto it = byDevice.constBegin(); it != byDevice.constEnd(); ++it) {
|
||||
const DeviceEntry& e = it.value();
|
||||
const QStringList disks = resolveToPhysicalDisks(QString::fromLocal8Bit(e.device));
|
||||
const QStringList disks =
|
||||
resolveToPhysicalDisks(QString::fromLocal8Bit(e.device));
|
||||
if (disks.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -269,14 +257,23 @@ void Storage::tick() {
|
||||
next.reserve(byDisk.size());
|
||||
for (auto it = byDisk.constBegin(); it != byDisk.constEnd(); ++it) {
|
||||
if (DiskInfo* survivor = existing.take(it.key())) {
|
||||
survivor->update(it.value().usedBytes, it.value().totalBytes, it.value().hasRoot);
|
||||
survivor->update(
|
||||
it.value().usedBytes,
|
||||
it.value().totalBytes,
|
||||
it.value().hasRoot);
|
||||
next.append(survivor);
|
||||
} else {
|
||||
next.append(new DiskInfo(it.key(), it.value().usedBytes, it.value().totalBytes, it.value().hasRoot, this));
|
||||
next.append(new DiskInfo(
|
||||
it.key(),
|
||||
it.value().usedBytes,
|
||||
it.value().totalBytes,
|
||||
it.value().hasRoot,
|
||||
this));
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(next.begin(), next.end(), [](const DiskInfo* a, const DiskInfo* b) {
|
||||
std::sort(
|
||||
next.begin(), next.end(), [](const DiskInfo* a, const DiskInfo* b) {
|
||||
if (a->hasRoot() != b->hasRoot()) {
|
||||
return a->hasRoot();
|
||||
}
|
||||
@@ -284,7 +281,8 @@ void Storage::tick() {
|
||||
});
|
||||
|
||||
bool manualCleared = false;
|
||||
if (DiskInfo* m = m_manualPrimaryDisk.data(); m && existing.contains(m->mount())) {
|
||||
if (DiskInfo* m = m_manualPrimaryDisk.data();
|
||||
m && existing.contains(m->mount())) {
|
||||
m_manualPrimaryDisk.clear();
|
||||
manualCleared = true;
|
||||
}
|
||||
|
||||
@@ -12,44 +12,51 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class Storage : public TickingService {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
|
||||
Q_PROPERTY(QQmlListProperty<ZShell::services::DiskInfo> disks READ disksProp NOTIFY disksChanged)
|
||||
Q_PROPERTY(ZShell::services::DiskInfo* manualPrimaryDisk READ manualPrimaryDisk WRITE setManualPrimaryDisk NOTIFY
|
||||
manualPrimaryDiskChanged)
|
||||
Q_PROPERTY(ZShell::services::DiskInfo* primaryDisk READ primaryDisk NOTIFY primaryDiskChanged)
|
||||
Q_PROPERTY(qreal percentage READ percentage NOTIFY percentageChanged)
|
||||
Q_PROPERTY(
|
||||
QQmlListProperty<ZShell::services::DiskInfo> disks READ disksProp NOTIFY
|
||||
disksChanged)
|
||||
Q_PROPERTY(
|
||||
ZShell::services::DiskInfo* manualPrimaryDisk READ manualPrimaryDisk
|
||||
WRITE setManualPrimaryDisk NOTIFY manualPrimaryDiskChanged)
|
||||
Q_PROPERTY(
|
||||
ZShell::services::DiskInfo* primaryDisk READ primaryDisk NOTIFY
|
||||
primaryDiskChanged)
|
||||
|
||||
public:
|
||||
explicit Storage(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit Storage(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] QQmlListProperty<DiskInfo> disksProp();
|
||||
[[nodiscard]] DiskInfo* manualPrimaryDisk() const;
|
||||
void setManualPrimaryDisk(DiskInfo* disk);
|
||||
[[nodiscard]] DiskInfo* primaryDisk() const;
|
||||
[[nodiscard]] qreal percentage() const;
|
||||
[[nodiscard]] QQmlListProperty<DiskInfo> disksProp();
|
||||
[[nodiscard]] DiskInfo* manualPrimaryDisk() const;
|
||||
void setManualPrimaryDisk(DiskInfo* disk);
|
||||
[[nodiscard]] DiskInfo* primaryDisk() const;
|
||||
|
||||
signals:
|
||||
void disksChanged();
|
||||
void percentageChanged();
|
||||
void manualPrimaryDiskChanged();
|
||||
void primaryDiskChanged();
|
||||
signals:
|
||||
void disksChanged();
|
||||
void percentageChanged();
|
||||
void manualPrimaryDiskChanged();
|
||||
void primaryDiskChanged();
|
||||
|
||||
protected:
|
||||
void tick() override;
|
||||
protected:
|
||||
void tick() override;
|
||||
|
||||
private:
|
||||
[[nodiscard]] static QStringList resolveToPhysicalDisks(const QString& devicePath);
|
||||
[[nodiscard]] static bool isPseudoFs(QByteArrayView fsType);
|
||||
[[nodiscard]] static bool sameOrder(const QList<DiskInfo*>& a, const QList<DiskInfo*>& b);
|
||||
private:
|
||||
[[nodiscard]] static QStringList resolveToPhysicalDisks(
|
||||
const QString& devicePath);
|
||||
[[nodiscard]] static bool isPseudoFs(QByteArrayView fsType);
|
||||
[[nodiscard]] static bool sameOrder(
|
||||
const QList<DiskInfo*>& a, const QList<DiskInfo*>& b);
|
||||
|
||||
static qsizetype disksCount(QQmlListProperty<DiskInfo>* prop);
|
||||
static DiskInfo* disksAt(QQmlListProperty<DiskInfo>* prop, qsizetype i);
|
||||
static qsizetype disksCount(QQmlListProperty<DiskInfo>* prop);
|
||||
static DiskInfo* disksAt(QQmlListProperty<DiskInfo>* prop, qsizetype i);
|
||||
|
||||
QList<DiskInfo*> m_disks;
|
||||
QPointer<DiskInfo> m_manualPrimaryDisk;
|
||||
QList<DiskInfo*> m_disks;
|
||||
QPointer<DiskInfo> m_manualPrimaryDisk;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -6,30 +6,31 @@
|
||||
namespace ZShell::services {
|
||||
|
||||
class TickingService : public Service {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int updateInterval READ updateInterval NOTIFY updateIntervalChanged)
|
||||
Q_PROPERTY(
|
||||
int updateInterval READ updateInterval NOTIFY updateIntervalChanged)
|
||||
|
||||
public:
|
||||
explicit TickingService(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit TickingService(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] int updateInterval() const;
|
||||
[[nodiscard]] int updateInterval() const;
|
||||
|
||||
signals:
|
||||
void updateIntervalChanged();
|
||||
signals:
|
||||
void updateIntervalChanged();
|
||||
|
||||
protected:
|
||||
void start() final;
|
||||
void stop() final;
|
||||
protected:
|
||||
void start() final;
|
||||
void stop() final;
|
||||
|
||||
virtual void tick() = 0;
|
||||
virtual void tick() = 0;
|
||||
|
||||
private:
|
||||
void applyInterval(int ms);
|
||||
private:
|
||||
void applyInterval(int ms);
|
||||
|
||||
QTimer* m_timer;
|
||||
int m_interval = 1000;
|
||||
bool m_running = false;
|
||||
QTimer* m_timer;
|
||||
int m_interval = 1000;
|
||||
bool m_running = false;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services
|
||||
|
||||
@@ -16,18 +16,18 @@ namespace ZShell::services::usagefmt {
|
||||
|
||||
FormatResult UsageFmt::formatKib(qreal kib, qreal total) const {
|
||||
if (!finitePositive(kib) || !finitePositive(total)) {
|
||||
return { 0.0, 0.0, "KiB" };
|
||||
return {0.0, 0.0, "KiB"};
|
||||
}
|
||||
if (total >= kGib) {
|
||||
return { kib / kGib, total / kGib, "TiB" };
|
||||
return {kib / kGib, total / kGib, "TiB"};
|
||||
}
|
||||
if (total >= kMib) {
|
||||
return { kib / kMib, total / kMib, "GiB" };
|
||||
return {kib / kMib, total / kMib, "GiB"};
|
||||
}
|
||||
if (total >= kKib) {
|
||||
return { kib / kKib, total / kKib, "MiB" };
|
||||
return {kib / kKib, total / kKib, "MiB"};
|
||||
}
|
||||
return { kib, total, "KiB" };
|
||||
return {kib, total, "KiB"};
|
||||
}
|
||||
|
||||
} // namespace ZShell::services::usagefmt
|
||||
|
||||
@@ -15,19 +15,20 @@ struct FormatResult {
|
||||
Q_PROPERTY(qreal total MEMBER total CONSTANT)
|
||||
Q_PROPERTY(QString unit MEMBER unit CONSTANT)
|
||||
|
||||
public:
|
||||
public:
|
||||
qreal value;
|
||||
qreal total;
|
||||
QString unit;
|
||||
};
|
||||
|
||||
class UsageFmt : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
|
||||
public:
|
||||
Q_INVOKABLE [[nodiscard]] FormatResult formatKib(qreal kib, qreal total) const;
|
||||
public:
|
||||
Q_INVOKABLE [[nodiscard]] FormatResult formatKib(
|
||||
qreal kib, qreal total) const;
|
||||
};
|
||||
|
||||
} // namespace ZShell::services::usagefmt
|
||||
|
||||
Reference in New Issue
Block a user