This commit is contained in:
Joey Yakimowich-Payne 2026-01-27 18:57:54 -07:00
commit 6d74ef422d
5 changed files with 160 additions and 7 deletions

View file

@ -21,6 +21,59 @@
namespace Potato {
static constexpr uint32_t kMeterRingCapacityBytes = 4096;
static void writeRingValue(spa_ringbuffer *ring, std::vector<uint8_t> &buffer, float value)
{
if (!ring || buffer.empty()) {
return;
}
uint32_t index = 0;
const uint32_t avail = spa_ringbuffer_get_write_index(ring, &index);
if (avail < sizeof(float)) {
return;
}
const uint32_t size = static_cast<uint32_t>(buffer.size());
uint32_t offset = index & (size - 1);
if (offset + sizeof(float) <= size) {
std::memcpy(buffer.data() + offset, &value, sizeof(float));
} else {
const uint32_t first = size - offset;
std::memcpy(buffer.data() + offset, &value, first);
std::memcpy(buffer.data(), reinterpret_cast<const uint8_t*>(&value) + first, sizeof(float) - first);
}
spa_ringbuffer_write_update(ring, index + sizeof(float));
}
static bool readRingLatest(spa_ringbuffer *ring, std::vector<uint8_t> &buffer, float &value)
{
if (!ring || buffer.empty()) {
return false;
}
uint32_t index = 0;
const uint32_t avail = spa_ringbuffer_get_read_index(ring, &index);
if (avail < sizeof(float)) {
return false;
}
const uint32_t size = static_cast<uint32_t>(buffer.size());
const uint32_t latestIndex = index + (avail - sizeof(float));
uint32_t offset = latestIndex & (size - 1);
if (offset + sizeof(float) <= size) {
std::memcpy(&value, buffer.data() + offset, sizeof(float));
} else {
const uint32_t first = size - offset;
std::memcpy(&value, buffer.data() + offset, first);
std::memcpy(reinterpret_cast<uint8_t*>(&value) + first, buffer.data(), sizeof(float) - first);
}
spa_ringbuffer_read_update(ring, index + avail);
return true;
}
static QString toQString(const char *value)
{
if (!value) {
@ -150,6 +203,9 @@ void meterProcess(void *data)
}
self->m_meterPeak.store(peak, std::memory_order_relaxed);
if (self->m_meterRingReady.load(std::memory_order_relaxed)) {
writeRingValue(&self->m_meterRing, self->m_meterRingData, peak);
}
pw_stream_queue_buffer(self->m_meterStream, buf);
}
@ -217,6 +273,9 @@ PipeWireController::PipeWireController(QObject *parent)
{
m_registryListener = new spa_hook;
m_coreListener = new spa_hook;
m_meterRingData.resize(kMeterRingCapacityBytes);
spa_ringbuffer_init(&m_meterRing);
m_meterRingReady.store(true, std::memory_order_relaxed);
}
PipeWireController::~PipeWireController()
@ -340,6 +399,9 @@ void PipeWireController::shutdown()
}
pw_deinit();
m_meterRingReady.store(false, std::memory_order_relaxed);
m_meterRingData.clear();
m_initialized.storeRelaxed(false);
m_connected.storeRelaxed(false);
@ -372,7 +434,14 @@ QVector<LinkInfo> PipeWireController::links() const
float PipeWireController::meterPeak() const
{
return m_meterPeak.load(std::memory_order_relaxed);
float peak = m_meterPeak.load(std::memory_order_relaxed);
if (m_meterRingReady.load(std::memory_order_relaxed)) {
float ringPeak = 0.0f;
if (readRingLatest(&m_meterRing, m_meterRingData, ringPeak)) {
peak = ringPeak;
}
}
return peak;
}
float PipeWireController::nodeMeterPeak(uint32_t nodeId) const