fix: read real sample rate from SPA_PARAM_Format (like pw-top)

- Subscribe to SPA_PARAM_Format on each node via pw_node_subscribe_params
- Parse audio format with spa_format_audio_raw_parse to get actual rate/channels
- Shows real negotiated rates (48000 Hz, 44100 Hz, etc.) instead of defaults
- Added spa/param/format-utils.h, audio/format-utils.h, audio/raw-types.h
This commit is contained in:
joren
2026-03-30 01:00:25 +02:00
parent 535ee058f2
commit 839eb5156a

View File

@@ -9,6 +9,9 @@
#include <spa/pod/pod.h>
#include <spa/pod/builder.h>
#include <spa/pod/iter.h>
#include <spa/param/format-utils.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/audio/raw-types.h>
#include <cstring>
#include <algorithm>
@@ -169,9 +172,37 @@ static void on_node_info(void *data, const struct pw_node_info *info) {
nobj->node.ready = true;
}
// Parse audio format param (like pw-top does)
static void on_node_param(void *data, int seq,
uint32_t id, uint32_t index, uint32_t next,
const struct spa_pod *param)
{
auto *obj = static_cast<GraphEngine::Object*>(data);
if (!obj) return;
auto *nobj = static_cast<GraphEngine::NodeObj*>(obj);
if (param == NULL) return;
if (id != SPA_PARAM_Format) return;
uint32_t media_type, media_subtype;
if (spa_format_parse(param, &media_type, &media_subtype) < 0) return;
if (media_type == SPA_MEDIA_TYPE_audio && media_subtype == SPA_MEDIA_SUBTYPE_raw) {
struct spa_audio_info_raw info;
spa_zero(info);
if (spa_format_audio_raw_parse(param, &info) >= 0) {
if (info.rate > 0) nobj->node.sample_rate = info.rate;
if (info.channels > 0) nobj->node.channels = info.channels;
nobj->node.format = spa_type_audio_format_to_short_name((uint32_t)info.format);
nobj->node.changed = true;
}
}
}
static const struct pw_node_events node_events = {
.version = PW_VERSION_NODE_EVENTS,
.info = on_node_info,
.param = on_node_param,
};
// ============================================================================
@@ -275,6 +306,12 @@ static void create_proxy_for_object(GraphEngine::Object *obj, GraphEngine *engin
&obj->object_listener, events, obj);
pw_proxy_add_listener(proxy,
&obj->proxy_listener, &proxy_events, obj);
// Subscribe to format params for nodes (like pw-top)
if (obj->type == GraphEngine::Object::ObjNode) {
uint32_t ids[1] = { SPA_PARAM_Format };
pw_node_subscribe_params((pw_node*)proxy, ids, 1);
}
}
}