diff --git a/src/graph_engine.cpp b/src/graph_engine.cpp index b890dc9..17c5ecb 100644 --- a/src/graph_engine.cpp +++ b/src/graph_engine.cpp @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include #include @@ -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(data); + if (!obj) return; + auto *nobj = static_cast(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); + } } }