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:
@@ -9,6 +9,9 @@
|
|||||||
#include <spa/pod/pod.h>
|
#include <spa/pod/pod.h>
|
||||||
#include <spa/pod/builder.h>
|
#include <spa/pod/builder.h>
|
||||||
#include <spa/pod/iter.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 <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -169,9 +172,37 @@ static void on_node_info(void *data, const struct pw_node_info *info) {
|
|||||||
nobj->node.ready = true;
|
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 = {
|
static const struct pw_node_events node_events = {
|
||||||
.version = PW_VERSION_NODE_EVENTS,
|
.version = PW_VERSION_NODE_EVENTS,
|
||||||
.info = on_node_info,
|
.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);
|
&obj->object_listener, events, obj);
|
||||||
pw_proxy_add_listener(proxy,
|
pw_proxy_add_listener(proxy,
|
||||||
&obj->proxy_listener, &proxy_events, obj);
|
&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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user