Linux PipeWire深度解析之pw_properties_iterate调用流程与实战(六十五)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀

Android Audio工程师专栏地址:Audio工程师进阶系列原创干货持续更新中...... 】🚀

Android多媒体专栏地址:多媒体系统工程师系列原创干货持续更新中...... 】🚀

专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀

专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀

专题四:Android15快速自定义与集成音效实战课 🚀

专题五:Android15音频策略实战课 🚀

专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

🌻1.前言

本篇目的:

Linux PipeWire深度解析之pw_properties_iterate调用流程与实战。

要点概括

  • 核心功能:遍历pw_properties对象中的key/value属性集合,逐个取出属性key。

  • 工作机制:调用者准备一个void*类型的迭代状态变量,并初始化为NULL;每次调用函数返回一个key,同时更新state,直到返回NULL表示遍历结束。

  • 典型用途:调试PipeWire对象属性、打印Stream/Node/Device参数、过滤指定属性、复制Properties内容、构造运行时配置。

pw_properties_iterate的本质是"遍历属性key",不是"读取属性value"。它每次返回的是属性名,也就是key;如果要拿到对应value,还需要使用pw_properties_get继续查询。

它也不是Properties对象的创建接口。Properties对象通常由pw_properties_new、pw_properties_new_dict、pw_properties_copy或框架内部传入,pw_properties_iterate只负责在已有Properties对象上移动遍历游标。

它和pw_properties_get的区别很明确:pw_properties_get是按指定key读取value;pw_properties_iterate是不知道key名称时,逐个枚举全部key。一个解决"点查",一个解决"遍历"。

它和spa_dict遍历也有边界区别。pw_properties底层包含spa_dict,但pw_properties_iterate隐藏了内部遍历细节,应用侧只需要维护state即可,不必直接关心spa_dict_item数组如何组织。

🌻2.应用场景与用法

pw_properties_iterate

是PipeWire Properties API中用于遍历属性集合的接口。

PipeWire中大量对象都会携带Properties,例如Context、Core、Stream、Node、Device、Port、Client、Module等。Properties用于描述对象名称、媒体类型、角色、设备信息、应用信息、路由参数和调试信息。

在调试PipeWire对象时,经常需要把Properties完整打印出来。此时应用并不知道对象里有哪些key,不能只靠pw_properties_get固定读取某几个字段,就需要使用pw_properties_iterate逐个枚举。

pw_properties_iterate用于遍历pw_properties中的全部属性key。

函数原型

c 复制代码
const char *pw_properties_iterate(const struct pw_properties *properties,
                                  void **state);

参数说明

c 复制代码
const struct pw_properties *properties;

properties表示要遍历的Properties对象。

它必须指向一个有效的pw_properties对象。该函数不会创建Properties,也不会修改Properties内容,只是在已有对象上执行遍历。

c 复制代码
void **state;

state表示遍历状态游标。

调用者需要先定义一个void*变量,并初始化为NULL:

c 复制代码
void *state = NULL;

然后把它的地址传给pw_properties_iterate:

c 复制代码
key = pw_properties_iterate(props, &state);

第一次调用时,state内部值为NULL,函数从第一个属性开始遍历。后续每次调用时,函数根据state继续向后移动。返回NULL后表示遍历结束。

如果要重新开始遍历,需要重新把state设置为NULL。

返回值

成功时返回:

c 复制代码
const char *

表示当前遍历到的属性key。

返回NULL表示没有更多属性可以遍历。它只是正常的遍历结束条件,不代表Properties对象一定异常。

需要注意,返回值只是key,不是value。要读取value,需要继续调用:

c 复制代码
const char *value = pw_properties_get(properties, key);

返回的key和value通常由Properties内部持有,调用者不要直接free。如果要长期保存,应该复制字符串。

应用场景

第一类场景是打印PipeWire对象属性。

例如调试Stream创建参数、Node属性、Device属性时,可以通过pw_properties_iterate把所有key枚举出来,再配合pw_properties_get打印value。

第二类场景是复制属性。

当应用需要把一个Properties对象中的部分key/value复制到另一个Properties对象时,可以先遍历全部key,再按规则筛选和写入。

第三类场景是过滤属性。

例如只保留以media.、node.、application.、audio.开头的属性,用于构造更干净的Stream参数或调试输出。

第四类场景是诊断配置问题。

PipeWire很多行为由Properties驱动,例如media.class、media.type、node.name、node.description、application.name等。如果对象创建结果不符合预期,遍历Properties可以快速确认关键字段是否设置正确。

🌻3.调用流程剖析

🌻3.1核心步骤

1.调用者准备一个有效的pw_properties对象。

2.定义void*类型的state变量,并初始化为NULL。

3.调用pw_properties_iterate(properties,&state)。

4.函数根据state定位当前属性项。

5.如果找到属性项,返回当前属性的key。

6.调用者拿到key后,可以使用pw_properties_get(properties,key)读取value。

7.调用者处理key/value,例如打印、过滤、复制或转换。

8.再次调用pw_properties_iterate(properties,&state),继续遍历下一个属性。

9.当函数返回NULL时,表示全部属性已经遍历完成。

10.遍历结束后,Properties对象仍然由原所有者管理,pw_properties_iterate不会释放它。

🌻3.2调用流程图

🌻3.3生命周期图

🌻4.实战应用案例

下面以"打印PipeWire对象Properties"为例,说明pw_properties_iterate的典型用法。

在PipeWire调试中,我们经常需要确认一个对象到底携带了哪些属性。例如Stream创建时传入的application.name、media.type、media.category、media.role、node.name是否正确。固定读取某几个字段不够通用,因此更适合使用遍历方式。

c 复制代码
#include <stdio.h>
#include <pipewire/pipewire.h>

static void dump_properties(const struct pw_properties *props)
{
    void *state = NULL;
    const char *key;

    if (props == NULL)
        return;

    while ((key = pw_properties_iterate(props, &state)) != NULL) {
        const char *value;

        value = pw_properties_get(props, key);
        printf("%s = %s\n", key, value ? value : "");
    }
}

这个函数的关键点不在printf,而在state的使用方式。

c 复制代码
void *state = NULL;

state必须在第一次遍历前初始化为NULL。它表示当前遍历位置,由pw_properties_iterate内部更新。调用者不需要解析state的内容,也不应该修改它。

c 复制代码
while ((key = pw_properties_iterate(props, &state)) != NULL)

这个循环每次取出一个key。只要返回值不是NULL,就说明当前还有属性可以处理。返回NULL后,遍历结束。

c 复制代码
value = pw_properties_get(props, key);

pw_properties_iterate只返回key,不返回value。因此读取value时必须再调用pw_properties_get。

下面是一个更贴近实际工程的例子:只复制以media.和node.开头的属性。

c 复制代码
#include <string.h>
#include <pipewire/pipewire.h>

static int starts_with(const char *s, const char *prefix)
{
    return strncmp(s, prefix, strlen(prefix)) == 0;
}

static struct pw_properties *
copy_media_node_properties(const struct pw_properties *src)
{
    struct pw_properties *dst;
    void *state = NULL;
    const char *key;

    if (src == NULL)
        return NULL;

    dst = pw_properties_new(NULL, NULL);
    if (dst == NULL)
        return NULL;

    while ((key = pw_properties_iterate(src, &state)) != NULL) {
        const char *value;

        if (!starts_with(key, "media.") &&
            !starts_with(key, "node."))
            continue;

        value = pw_properties_get(src, key);
        if (value != NULL)
            pw_properties_set(dst, key, value);
    }

    return dst;
}

这个例子体现了pw_properties_iterate在工程中的一个常见用途:从一个完整Properties对象中筛选出业务真正需要的字段。

在PipeWire开发中,Properties经常既包含框架字段,也包含应用字段。直接整体复制可能会带来无关参数,甚至覆盖目标对象已有配置。通过遍历加过滤,可以把属性传递控制得更精确。

使用pw_properties_iterate时,要注意四个细节。

第一,state要独立使用。一次遍历对应一个state变量。嵌套遍历或多轮遍历时,不要复用同一个未重置的state。

第二,返回NULL只是遍历结束。不要把它简单理解为错误。

第三,遍历期间不要随意修改同一个Properties对象。尤其不要一边遍历一边删除当前对象中的属性,否则容易造成遍历状态不符合预期。

第四,不要长期保存返回的key指针。如果后续Properties被释放或修改,内部字符串指针可能失效。需要长期使用时,应主动复制key和value。

🌻5.一句话总结

pw_properties_iterate是PipeWire Properties API中的属性遍历接口:它通过调用者维护的state游标逐个返回key,适合调试、打印、复制和过滤Properties内容,读取value时需要配合pw_properties_get使用。

相关推荐
名字还没想好☜11 小时前
用 systemd 托管后台服务:Restart 策略、日志接管、资源限制与开机自启全踩一遍
运维·docker·kubernetes
乌恩大侠11 小时前
GH200 新增 NVMe SSD 分区、格式化与挂载完整流程
运维·服务器·前端
tangwangbi12 小时前
Linux 系统配置文件:/etc/profile、~/.bashrc 和 ~/.bash_profile 三者之间的区别与作用
linux·运维·bash
蜀道山老天师12 小时前
Shell Bash变量与运算符(含条件测试与流程控制)
linux·运维·bash
Mr.朱鹏12 小时前
Linux 服务器 LVM 根分区在线动态扩容
linux·服务器·数据库
草邦设计开发团队_媒体资源平台12 小时前
GEO 信源整合一键发布软文:从内容生产到流量获客的自动化实践
运维·人工智能·自动化
zhou lily12 小时前
非标自动化管理系统ERP如何选?2026年10大ERP软件对比分析
运维·自动化
mengge.cloud12 小时前
存储技术基础小白教程
linux·运维·服务器·wpf·存储
云贝贝贝13 小时前
腾讯云 TDSQL(MySQL 版)运维高频 6 坑:代理路由、读写分离、分片键、监控、PITR
运维·mysql·腾讯云
小五传输13 小时前
FTP替代怎么做?医院文件安全传输选型与迁移指南
大数据·运维·安全