GUI M8e
This commit is contained in:
parent
a07f94c93d
commit
ecec82c70e
10 changed files with 809 additions and 21 deletions
|
|
@ -1,5 +1,6 @@
|
|||
#include <warppipe/warppipe.hpp>
|
||||
|
||||
#include "../../gui/AudioLevelMeter.h"
|
||||
#include "../../gui/GraphEditorWidget.h"
|
||||
#include "../../gui/PresetManager.h"
|
||||
#include "../../gui/VolumeWidgets.h"
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QStandardPaths>
|
||||
#include <QTabWidget>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
|
@ -1151,6 +1153,81 @@ TEST_CASE("preset saves and loads volume state") {
|
|||
QFile::remove(path);
|
||||
}
|
||||
|
||||
TEST_CASE("AudioLevelMeter setLevel clamps to 0-1") {
|
||||
ensureApp();
|
||||
AudioLevelMeter meter;
|
||||
meter.setLevel(0.5f);
|
||||
REQUIRE(meter.level() == Catch::Approx(0.5f));
|
||||
meter.setLevel(-0.5f);
|
||||
REQUIRE(meter.level() == Catch::Approx(0.0f));
|
||||
meter.setLevel(1.5f);
|
||||
REQUIRE(meter.level() == Catch::Approx(1.0f));
|
||||
}
|
||||
|
||||
TEST_CASE("AudioLevelMeter peak hold tracks maximum") {
|
||||
ensureApp();
|
||||
AudioLevelMeter meter;
|
||||
meter.setLevel(0.8f);
|
||||
REQUIRE(meter.peakHold() == Catch::Approx(0.8f));
|
||||
meter.setLevel(0.3f);
|
||||
REQUIRE(meter.peakHold() == Catch::Approx(0.8f));
|
||||
meter.setLevel(0.9f);
|
||||
REQUIRE(meter.peakHold() == Catch::Approx(0.9f));
|
||||
}
|
||||
|
||||
TEST_CASE("AudioLevelMeter peak decays after hold period") {
|
||||
ensureApp();
|
||||
AudioLevelMeter meter;
|
||||
meter.setLevel(0.5f);
|
||||
REQUIRE(meter.peakHold() == Catch::Approx(0.5f));
|
||||
for (int i = 0; i < 7; ++i)
|
||||
meter.setLevel(0.0f);
|
||||
REQUIRE(meter.peakHold() < 0.5f);
|
||||
REQUIRE(meter.peakHold() > 0.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("AudioLevelMeter resetPeakHold clears peak") {
|
||||
ensureApp();
|
||||
AudioLevelMeter meter;
|
||||
meter.setLevel(0.7f);
|
||||
REQUIRE(meter.peakHold() == Catch::Approx(0.7f));
|
||||
meter.resetPeakHold();
|
||||
REQUIRE(meter.peakHold() == Catch::Approx(0.0f));
|
||||
}
|
||||
|
||||
TEST_CASE("GraphEditorWidget has METERS tab") {
|
||||
auto tc = TestClient::Create();
|
||||
if (!tc.available()) { SUCCEED("PipeWire unavailable"); return; }
|
||||
ensureApp();
|
||||
|
||||
GraphEditorWidget widget(tc.client.get());
|
||||
auto *sidebar = widget.findChild<QTabWidget *>();
|
||||
REQUIRE(sidebar != nullptr);
|
||||
bool found = false;
|
||||
for (int i = 0; i < sidebar->count(); ++i) {
|
||||
if (sidebar->tabText(i) == "METERS") {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
REQUIRE(found);
|
||||
}
|
||||
|
||||
TEST_CASE("node meter rows created for injected nodes") {
|
||||
auto tc = TestClient::Create();
|
||||
if (!tc.available()) { SUCCEED("PipeWire unavailable"); return; }
|
||||
ensureApp();
|
||||
|
||||
REQUIRE(tc.client->Test_InsertNode(
|
||||
MakeNode(100700, "meter-node", "Audio/Sink")).ok());
|
||||
REQUIRE(tc.client->Test_InsertPort(
|
||||
MakePort(100701, 100700, "FL", true)).ok());
|
||||
|
||||
GraphEditorWidget widget(tc.client.get());
|
||||
auto meters = widget.findChildren<AudioLevelMeter *>();
|
||||
REQUIRE(meters.size() >= 3);
|
||||
}
|
||||
|
||||
TEST_CASE("volume state cleaned up on node deletion") {
|
||||
auto tc = TestClient::Create();
|
||||
if (!tc.available()) { SUCCEED("PipeWire unavailable"); return; }
|
||||
|
|
|
|||
|
|
@ -853,3 +853,109 @@ TEST_CASE("Test_SetNodeVolume fails for nonexistent node") {
|
|||
REQUIRE_FALSE(status.ok());
|
||||
REQUIRE(status.code == warppipe::StatusCode::kNotFound);
|
||||
}
|
||||
|
||||
TEST_CASE("EnsureNodeMeter and NodeMeterPeak round-trip") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
auto &client = result.value;
|
||||
|
||||
warppipe::NodeInfo node;
|
||||
node.id = warppipe::NodeId{950};
|
||||
node.name = "meter-test";
|
||||
node.media_class = "Audio/Sink";
|
||||
REQUIRE(client->Test_InsertNode(node).ok());
|
||||
|
||||
REQUIRE(client->EnsureNodeMeter(warppipe::NodeId{950}).ok());
|
||||
|
||||
auto peak = client->NodeMeterPeak(warppipe::NodeId{950});
|
||||
REQUIRE(peak.ok());
|
||||
REQUIRE(peak.value.peak_left == Catch::Approx(0.0f));
|
||||
REQUIRE(peak.value.peak_right == Catch::Approx(0.0f));
|
||||
}
|
||||
|
||||
TEST_CASE("Test_SetNodeMeterPeak updates peaks") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
auto &client = result.value;
|
||||
|
||||
warppipe::NodeInfo node;
|
||||
node.id = warppipe::NodeId{951};
|
||||
node.name = "meter-set";
|
||||
node.media_class = "Audio/Sink";
|
||||
REQUIRE(client->Test_InsertNode(node).ok());
|
||||
|
||||
REQUIRE(client->Test_SetNodeMeterPeak(warppipe::NodeId{951}, 0.6f, 0.8f).ok());
|
||||
|
||||
auto peak = client->NodeMeterPeak(warppipe::NodeId{951});
|
||||
REQUIRE(peak.ok());
|
||||
REQUIRE(peak.value.peak_left == Catch::Approx(0.6f));
|
||||
REQUIRE(peak.value.peak_right == Catch::Approx(0.8f));
|
||||
}
|
||||
|
||||
TEST_CASE("DisableNodeMeter removes metering") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
auto &client = result.value;
|
||||
|
||||
warppipe::NodeInfo node;
|
||||
node.id = warppipe::NodeId{952};
|
||||
node.name = "meter-disable";
|
||||
node.media_class = "Audio/Sink";
|
||||
REQUIRE(client->Test_InsertNode(node).ok());
|
||||
REQUIRE(client->EnsureNodeMeter(warppipe::NodeId{952}).ok());
|
||||
REQUIRE(client->DisableNodeMeter(warppipe::NodeId{952}).ok());
|
||||
|
||||
auto peak = client->NodeMeterPeak(warppipe::NodeId{952});
|
||||
REQUIRE_FALSE(peak.ok());
|
||||
REQUIRE(peak.status.code == warppipe::StatusCode::kNotFound);
|
||||
}
|
||||
|
||||
TEST_CASE("MasterMeterPeak defaults to zero") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
|
||||
auto peak = result.value->MeterPeak();
|
||||
REQUIRE(peak.ok());
|
||||
REQUIRE(peak.value.peak_left == Catch::Approx(0.0f));
|
||||
REQUIRE(peak.value.peak_right == Catch::Approx(0.0f));
|
||||
}
|
||||
|
||||
TEST_CASE("Test_SetMasterMeterPeak updates master peaks") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
|
||||
REQUIRE(result.value->Test_SetMasterMeterPeak(0.9f, 0.7f).ok());
|
||||
|
||||
auto peak = result.value->MeterPeak();
|
||||
REQUIRE(peak.ok());
|
||||
REQUIRE(peak.value.peak_left == Catch::Approx(0.9f));
|
||||
REQUIRE(peak.value.peak_right == Catch::Approx(0.7f));
|
||||
}
|
||||
|
||||
TEST_CASE("Test_SetNodeMeterPeak clamps values") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
auto &client = result.value;
|
||||
|
||||
warppipe::NodeInfo node;
|
||||
node.id = warppipe::NodeId{953};
|
||||
node.name = "meter-clamp";
|
||||
node.media_class = "Audio/Sink";
|
||||
REQUIRE(client->Test_InsertNode(node).ok());
|
||||
|
||||
REQUIRE(client->Test_SetNodeMeterPeak(warppipe::NodeId{953}, 1.5f, -0.5f).ok());
|
||||
|
||||
auto peak = client->NodeMeterPeak(warppipe::NodeId{953});
|
||||
REQUIRE(peak.ok());
|
||||
REQUIRE(peak.value.peak_left == Catch::Approx(1.0f));
|
||||
REQUIRE(peak.value.peak_right == Catch::Approx(0.0f));
|
||||
}
|
||||
|
||||
TEST_CASE("EnsureNodeMeter fails for nonexistent node") {
|
||||
auto result = warppipe::Client::Create(DefaultOptions());
|
||||
REQUIRE(result.ok());
|
||||
|
||||
auto status = result.value->EnsureNodeMeter(warppipe::NodeId{999});
|
||||
REQUIRE_FALSE(status.ok());
|
||||
REQUIRE(status.code == warppipe::StatusCode::kNotFound);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue