Linux PipeWire深度解析之pw_properties_set调用流程与实战(六十二) 简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1.前言要点概括2.应用场景与用法函数原型参数说明返回值应用场景3.调用流程剖析3.1核心步骤3.2调用流程图3.3生命周期图4.实战应用案例5.一句话总结1.前言本篇目的Linux PipeWire深度解析之pw_properties_set调用流程与实战。要点概括核心功能设置pw_properties中的单个key/value属性。工作机制根据key查找已有属性如果key不存在则新增如果key已存在则更新如果value为NULL则删除该属性。典型用途设置Stream、Node、Context、Module等对象创建前的属性例如stream.name、node.name、media.type、media.role等。pw_properties_set的本质是“单个属性写入接口”。它不是批量合并接口也不是只读查询接口而是直接修改一个pw_properties对象中的某个key/value。它常用于对象创建前的属性准备阶段。PipeWire很多对象都会携带properties例如Stream属性、Node属性、Device属性、Module属性。调用方可以通过pw_properties_set逐项设置对象名称、媒体类型、角色、分类、应用名称等元数据。它和pw_properties_get的区别是get只读取属性不修改propertiesset会修改properties。它和pw_properties_add的区别是add只补充缺失key不覆盖已有属性set面向单个key可以新增也可以覆盖。它和pw_properties_update的区别是update面向一个spa_dict批量更新set只处理一个key/value。它和pw_properties_setf的区别是set直接传入字符串valuesetf使用格式化字符串生成value适合把数字、状态、组合字段写成属性。2.应用场景与用法pw_properties_set是PipeWirePropertiesAPI中用于设置单个属性的接口。它位于PipeWire对象属性构造链路中。应用、模块或框架代码通常先创建pw_properties对象再通过pw_properties_set写入关键属性最后把properties传给Stream、Context、Module、Factory或其他对象创建接口。pw_properties_set用于设置、更新或删除pw_properties中的单个key/value属性。函数原型intpw_properties_set(structpw_properties*properties,constchar*key,constchar*value);参数说明structpw_properties*properties;properties表示目标属性集合。该对象是被修改的一方。函数会在这个properties中查找key并根据value决定新增、更新或删除属性。constchar*key;key表示属性名称。key不能为空。PipeWire中常见key包括media.type、media.category、media.role、node.name、application.name、stream.name等。constchar*value;value表示属性值。value为非NULL时函数会把key对应的属性设置为该值。value为NULL时函数会删除key对应的属性。返回值返回值类型为int一般可按下面语义理解0表示属性集合发生变化例如新增、更新或删除了属性。0表示属性集合没有变化例如设置的value与原值相同或者删除一个不存在的key。0表示设置失败例如参数非法或内存分配失败。工程上通常不需要把返回值当作属性值使用而是把它当作“属性集合是否发生变化”的状态判断。应用场景第一类场景是设置Stream名称。创建播放流或录音流前可以通过pw_properties_set设置stream.name方便后续调试、路由识别和策略管理。第二类场景是设置Node名称。PipeWireGraph中的很多对象最终会表现为Node。设置node.name可以帮助开发者在pw-cli、pw-dump、WirePlumber策略和日志中识别对象。第三类场景是设置媒体属性。media.type、media.category、media.role这类属性会影响对象分类和策略处理。例如音频播放流、录音流、通信流、音乐流可以通过这些属性区分。第四类场景是覆盖已有属性。如果properties中已经存在某个keypw_properties_set会把它改成新value。这适合明确指定“以当前设置为准”的场景。第五类场景是删除属性。当value传NULL时pw_properties_set可以删除指定key。这适合清理不希望继续传递的属性。3.调用流程剖析3.1核心步骤1.调用方准备一个pw_properties对象。2.调用方确定要设置的key。3.调用方确定value是否为NULL。4.调用pw_properties_set(properties,key,value)。5.函数检查properties和key是否合法。6.函数在properties内部查找是否已经存在该key。7.如果value为NULL进入删除路径。8.如果key不存在且value非NULL进入新增路径。9.如果key已存在且value非NULL比较旧值和新值。10.如果新旧值相同不修改properties。11.如果新旧值不同释放旧value并保存新value。12.函数返回属性集合是否发生变化。3.2调用流程图3.3生命周期图4.实战应用案例下面以“创建播放Stream前设置属性”为例说明pw_properties_set的实际用法。应用创建Stream之前通常需要准备一组属性用来告诉PipeWire和WirePlumber这个流是什么类型、属于什么角色、叫什么名字。#includepipewire/pipewire.hstaticstructpw_properties*create_playback_props(void){structpw_properties*props;propspw_properties_new(NULL,NULL);if(propsNULL)returnNULL;pw_properties_set(props,PW_KEY_MEDIA_TYPE,Audio);pw_properties_set(props,PW_KEY_MEDIA_CATEGORY,Playback);pw_properties_set(props,PW_KEY_MEDIA_ROLE,Music);pw_properties_set(props,PW_KEY_STREAM_NAME,demo-playback-stream);pw_properties_set(props,PW_KEY_NODE_NAME,demo-playback-node);pw_properties_set(props,PW_KEY_APP_NAME,pipewire-demo);returnprops;}这段代码的重点不在创建Stream本身而在属性构造。PW_KEY_MEDIA_TYPE表示媒体类型这里是Audio。PW_KEY_MEDIA_CATEGORY表示媒体分类这里是Playback。PW_KEY_MEDIA_ROLE表示媒体角色这里是Music。PW_KEY_STREAM_NAME表示Stream名称。PW_KEY_NODE_NAME表示Node名称。PW_KEY_APP_NAME表示应用名称。这些属性会进入PipeWire对象创建链路后续在对象命名、策略选择、调试分析中都会用到。再看覆盖已有属性的场景staticvoidchange_stream_role(structpw_properties*props){pw_properties_set(props,PW_KEY_MEDIA_ROLE,Communication);}如果原来的media.role是Music这次调用会把它改成Communication。这个语义和pw_properties_add不同。add不会覆盖已有key而set会明确覆盖。删除属性时可以把value传NULLstaticvoidremove_node_name(structpw_properties*props){pw_properties_set(props,PW_KEY_NODE_NAME,NULL);}这个写法表示从properties中删除node.name。它不是把node.name设置为空字符串而是移除这个key。空字符串和NULL语义不同staticvoidset_empty_name(structpw_properties*props){pw_properties_set(props,PW_KEY_NODE_NAME,);}这表示key仍然存在只是value为空字符串。所以工程上要注意pw_properties_set(props,key,NULL);表示删除属性。pw_properties_set(props,key,);表示保留属性但属性值为空。再看一个更完整的封装方式structplayback_config{constchar*stream_name;constchar*node_name;constchar*app_name;constchar*role;};staticstructpw_properties*build_playback_properties(conststructplayback_config*config){structpw_properties*props;propspw_properties_new(NULL,NULL);if(propsNULL)returnNULL;pw_properties_set(props,PW_KEY_MEDIA_TYPE,Audio);pw_properties_set(props,PW_KEY_MEDIA_CATEGORY,Playback);if(config-role!NULL)pw_properties_set(props,PW_KEY_MEDIA_ROLE,config-role);elsepw_properties_set(props,PW_KEY_MEDIA_ROLE,Music);if(config-stream_name!NULL)pw_properties_set(props,PW_KEY_STREAM_NAME,config-stream_name);if(config-node_name!NULL)pw_properties_set(props,PW_KEY_NODE_NAME,config-node_name);if(config-app_name!NULL)pw_properties_set(props,PW_KEY_APP_NAME,config-app_name);returnprops;}这个封装适合播放器、录音工具、测试程序或中间件使用。调用方只需要传入业务配置内部统一把配置转换成PipeWireProperties。如果后续要创建Streamprops可以传给Stream创建接口structpw_stream*stream;streampw_stream_new(core,demo-stream,props);这里props的所有权边界要特别注意。对象创建接口是否接管properties需要根据具体接口约定处理。工程代码中不要随意重复释放也不要在对象已经使用后继续假设properties还能影响已经创建完成的对象。pw_properties_set只修改当前properties对象本身。对象创建完成后再修改原来的临时properties通常不会自动改变已经创建好的PipeWire对象状态。要修改运行中的对象属性应走对应对象的参数更新、属性更新或协议接口而不是单纯修改旧properties指针。在实际开发中pw_properties_set最适合做三件事第一创建对象前明确写入关键属性。第二覆盖已有单个属性。第三通过value为NULL删除不需要继续携带的属性。不适合用它做大批量属性合并。如果要合并一组属性应优先考虑pw_properties_update、pw_properties_add或pw_properties_add_keys。5.一句话总结pw_properties_set是PipeWireProperties中最基础的单属性写入接口value非NULL时新增或覆盖keyvalue为NULL时删除key适合在对象创建前精确设置Stream、Node、Module、Context等对象的关键属性。