feat: built-in volume management
- Volume slider on every node (green bar, draggable)
- Mute toggle button (M/m) on every node
- Backend: read volume/mute from PipeWire node props
- Backend: POST /api/volume {node_id, volume} to set volume
- Backend: POST /api/mute {node_id, mute} to toggle mute
- Graph JSON includes volume and mute fields per node
- Slider supports drag-to-adjust with mouse
This commit is contained in:
@@ -109,6 +109,8 @@ std::string WebServer::buildGraphJson() const {
|
||||
<< ",\"media_name\":\"" << escapeJson(n.media_name) << "\""
|
||||
<< ",\"mode\":\"" << portModeStr(n.mode) << "\""
|
||||
<< ",\"node_type\":\"" << nodeTypeStr(n.node_type) << "\""
|
||||
<< ",\"volume\":" << n.volume
|
||||
<< ",\"mute\":" << (n.mute ? "true" : "false")
|
||||
<< ",\"port_ids\":[";
|
||||
bool first_p = true;
|
||||
for (uint32_t pid : n.port_ids) {
|
||||
@@ -403,6 +405,47 @@ void WebServer::setupRoutes() {
|
||||
res.set_content(buf, "application/json");
|
||||
res.set_header("Access-Control-Allow-Origin", "*");
|
||||
});
|
||||
|
||||
// Volume: POST /api/volume {"node_id": N, "volume": 0.0-1.0}
|
||||
m_http.Post("/api/volume", [this](const httplib::Request &req, httplib::Response &res) {
|
||||
uint32_t node_id = 0;
|
||||
float volume = 0;
|
||||
if (sscanf(req.body.c_str(),
|
||||
"{\"node_id\":%u,\"volume\":%f}", &node_id, &volume) == 2 ||
|
||||
sscanf(req.body.c_str(),
|
||||
"{\"node_id\":%u, \"volume\":%f}", &node_id, &volume) == 2)
|
||||
{
|
||||
if (volume < 0) volume = 0;
|
||||
if (volume > 1.5) volume = 1.5;
|
||||
bool ok = m_engine.setNodeVolume(node_id, volume);
|
||||
if (ok) broadcastGraph();
|
||||
res.set_content(ok ? "{\"ok\":true}" : "{\"ok\":false}", "application/json");
|
||||
} else {
|
||||
res.status = 400;
|
||||
res.set_content("{\"error\":\"invalid json\"}", "application/json");
|
||||
}
|
||||
res.set_header("Access-Control-Allow-Origin", "*");
|
||||
});
|
||||
|
||||
// Mute: POST /api/mute {"node_id": N, "mute": true/false}
|
||||
m_http.Post("/api/mute", [this](const httplib::Request &req, httplib::Response &res) {
|
||||
uint32_t node_id = 0;
|
||||
if (sscanf(req.body.c_str(), "{\"node_id\":%u", &node_id) == 1 ||
|
||||
sscanf(req.body.c_str(), "{\"node_id\": %u", &node_id) == 1)
|
||||
{
|
||||
bool mute = req.body.find("true") != std::string::npos;
|
||||
bool ok = m_engine.setNodeMute(node_id, mute);
|
||||
if (ok) broadcastGraph();
|
||||
res.set_content(ok ? "{\"ok\":true}" : "{\"ok\":false}", "application/json");
|
||||
} else {
|
||||
res.status = 400;
|
||||
res.set_content("{\"error\":\"invalid json\"}", "application/json");
|
||||
}
|
||||
res.set_header("Access-Control-Allow-Origin", "*");
|
||||
});
|
||||
|
||||
m_http.Options("/api/volume", cors_handler);
|
||||
m_http.Options("/api/mute", cors_handler);
|
||||
}
|
||||
|
||||
// end of web_server.cpp
|
||||
|
||||
Reference in New Issue
Block a user