☰
Linux PipeWire深度解析之pw_core_get_registry调用流程与实战(九十一)
2026/10/19 17:11:23 网站建设 项目流程

简介: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_core_get_registry调用流程与实战。

要点概括

  • 核心功能:从已连接的pw_core对象中获取Registry代理对象,用于发现PipeWire服务端已经注册的全局对象。

  • 工作机制:客户端通过Core接口创建pw_registry代理,再给Registry注册监听器,由服务端异步回调global和global_remove事件。

  • 典型用途:枚举Node、Device、Port、Link、Factory等全局对象,并根据对象id按需调用pw_registry_bind绑定成具体代理对象。

pw_core_get_registry的本质不是“直接获取所有对象列表”,而是“创建一个Registry代理对象”。真正的对象枚举结果不会作为函数返回值同步返回,而是通过Registry事件异步通知给客户端。

它位于客户端连接PipeWire服务端之后。应用先通过pw_context_connect得到pw_core,然后通过pw_core_get_registry得到pw_registry,再通过pw_registry_add_listener接收服务端全局对象变化。

它和pw_registry_bind的职责不同。pw_core_get_registry负责获取“对象目录入口”,pw_registry_bind负责根据Registry事件中的全局对象id绑定具体对象。它和pw_core_sync也不同,pw_core_sync用于做客户端和服务端的往返同步,不负责发现对象。

🌻2.应用场景与用法

pw_core_get_registry

是PipeWireCore API中用于获取Registry代理对象的接口。

它处于PipeWire客户端发现服务端对象的入口位置。客户端连接PipeWire服务端后,并不知道服务端当前有哪些Node、Device、Factory、Link等对象。应用需要先获取Registry,再监听Registry事件,才能拿到这些全局对象的id、type、version、permissions和properties。

pw_core_get_registry用于从pw_core获取pw_registry代理对象。

函数原型

structpw_registry*pw_core_get_registry(structpw_core*core,uint32_tversion,size_tuser_data_size);

参数说明

structpw_core*core;

core表示已经连接成功的PipeWireCore代理对象。

该对象通常由pw_context_connect返回。只有拿到有效core之后,客户端才具备和PipeWire服务端通信的基础能力。pw_core_get_registry依赖这个core向服务端发起get_registry请求。

uint32_tversion;

version表示客户端希望使用的Registry接口版本。

实际开发中通常传入:

PW_VERSION_REGISTRY

它用于声明客户端期望的pw_registry接口版本,便于协议层做版本匹配。

size_tuser_data_size;

user_data_size表示为返回的Registry代理对象附加的用户数据大小。

如果不需要给Registry代理对象附加私有数据,可以传入0。它不是Buffer大小,也不是对象枚举结果大小,只是代理对象私有数据区域大小。

返回值

成功时返回:

structpw_registry*

表示创建成功的Registry代理对象。

失败时返回NULL。

需要注意,返回非NULL只表示Registry代理对象创建成功,并不表示已经拿到了全部全局对象。全局对象信息需要通过pw_registry_add_listener注册监听器后,由global事件异步返回。

应用场景

第一类场景是枚举PipeWire服务端对象。

调试工具、图形化监控工具、设备管理程序通常需要获取服务端当前有哪些Node、Device、Port、Link和Factory。它们会先调用pw_core_get_registry获取Registry,再监听global事件构建设备和Graph视图。

第二类场景是查找目标播放或录音Node。

客户端可以通过Registry事件遍历所有Node,根据media.class、node.name、object.path等属性判断目标对象,再调用pw_registry_bind绑定该Node。

第三类场景是实现设备热插拔监听。

设备新增、删除、Link变化、Node变化都会通过Registry事件体现。客户端不需要轮询服务端,而是通过global和global_remove事件维护本地对象缓存。

第四类场景是开发PipeWire策略或诊断工具。

WirePlumber、调试程序、测试工具、对象分析工具都需要依赖Registry理解当前PipeWire服务端状态。Registry相当于服务端全局对象目录,是客户端理解PipeWire运行状态的入口。

🌻3.调用流程剖析

🌻3.1核心步骤

1.应用调用pw_init初始化PipeWire运行环境。

2.应用创建MainLoop和Context。

3.应用调用pw_context_connect连接PipeWire服务端,成功后得到pw_core对象。

4.应用调用pw_core_get_registry,从pw_core创建pw_registry代理对象。

5.应用调用pw_registry_add_listener,为Registry注册事件监听器。

6.PipeWire服务端通过Registry向客户端发送global事件,通知当前已经存在的全局对象。

7.应用在global回调中读取id、permissions、type、version和props。

8.应用根据type和props判断对象类型,例如Node、Device、Factory、Port、Link。

9.如果应用需要访问具体对象,则调用pw_registry_bind绑定目标id。

10.绑定成功后,客户端得到对应类型的代理对象,例如pw_node、pw_device或pw_proxy。

11.当服务端对象被移除时,Registry触发global_remove事件,应用同步清理本地缓存。

12.应用退出时销毁Registry代理对象,最后断开Core连接并释放Context。

🌻3.2调用流程图

🌻3.3生命周期图

🌻4.实战应用案例

下面以“枚举PipeWire服务端全局对象”为例,说明pw_core_get_registry在真实开发中的用法。

该案例的目标是:客户端连接PipeWire服务端后,通过Registry监听服务端对象,并筛选出Node对象。Node可能表示播放流、录音流、ALSA设备Node、蓝牙音频Node、视频Node等。

#include<pipewire/pipewire.h>structapp_data{structpw_main_loop*loop;structpw_context*context;structpw_core*core;structpw_registry*registry;structspa_hookregistry_listener;};staticvoidon_registry_global(void*data,uint32_tid,uint32_tpermissions,constchar*type,uint32_tversion,conststructspa_dict*props){constchar*name;constchar*media_class;if(props==NULL)return;name=spa_dict_lookup(props,"node.name");media_class=spa_dict_lookup(props,"media.class");if(type!=NULL&&spa_streq(type,PW_TYPE_INTERFACE_Node)){/* * 这里可以记录Node对象: * * id : 服务端全局对象id * permissions : 当前客户端权限 * type : PipeWire接口类型 * version : 对象接口版本 * props : 对象属性 * * 如果后续需要真正访问该Node, * 可以使用pw_registry_bind绑定这个id。 */(void)id;(void)permissions;(void)version;(void)name;(void)media_class;}}staticvoidon_registry_global_remove(void*data,uint32_tid){/* * 服务端全局对象被移除。 * 如果本地缓存了该id,需要在这里删除。 */(void)data;(void)id;}staticconststructpw_registry_eventsregistry_events={PW_VERSION_REGISTRY_EVENTS,.global=on_registry_global,.global_remove=on_registry_global_remove,};staticintinit_registry(structapp_data*app){app->registry=pw_core_get_registry(app->core,PW_VERSION_REGISTRY,0);if(app->registry==NULL)return-1;pw_registry_add_listener(app->registry,&app->registry_listener,&registry_events,app);return0;}

这个案例只完成对象发现,不直接绑定对象。这样做的好处是边界清晰:Registry负责发现对象,bind负责访问对象。实际项目中可以先把global事件中的对象缓存到本地表,再按业务需求绑定目标对象。

如果要绑定Node对象,可以在global回调中进一步处理:

staticvoidon_registry_global(void*data,uint32_tid,uint32_tpermissions,constchar*type,uint32_tversion,conststructspa_dict*props){structapp_data*app=data;structpw_proxy*proxy;constchar*media_class;if(props==NULL)return;if(!spa_streq(type,PW_TYPE_INTERFACE_Node))return;media_class=spa_dict_lookup(props,"media.class");if(media_class==NULL)return;if(spa_streq(media_class,"Audio/Sink")){proxy=pw_registry_bind(app->registry,id,type,version,0);/* * proxy表示绑定后的Node代理对象。 * 后续可以根据需要注册Node事件监听器, * 或者保存该proxy用于后续管理。 */(void)proxy;}}

这段代码体现了pw_core_get_registry和pw_registry_bind的典型配合方式。

pw_core_get_registry只创建Registry代理,不负责筛选对象,也不负责创建Node代理。global回调负责发现对象,业务逻辑负责判断对象是否符合条件,pw_registry_bind负责把目标id绑定成客户端可操作的代理对象。

工程使用中要注意三点。

第一,不能把pw_core_get_registry理解成同步枚举接口。它返回的是Registry代理对象,不是对象列表。对象列表来自后续global事件。

第二,global事件中的id是服务端全局对象id。这个id适合传给pw_registry_bind,但不能直接当成本地指针使用。

第三,global_remove事件必须处理。PipeWire服务端对象是动态变化的,设备拔出、流退出、Link销毁都会导致对象移除。如果本地缓存不清理,后续很容易访问过期对象。

🌻5.一句话总结

pw_core_get_registry是PipeWire客户端发现服务端全局对象的入口接口:它从pw_core创建pw_registry代理,通过Registry事件异步获得Node、Device、Port、Link等对象,再按需使用pw_registry_bind绑定具体对象。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询