Linux Pulseaudio深度解析之pa_mainloop_get_api调用流程与实战(六十七)
简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录1. 前言要点概括2. 应用场景与用法函数原型参数说明返回值应用场景3. 调用流程剖析3.1 核心步骤1. 应用层创建 mainloop2. 获取 mainloop API3. 传给 pa_context_new4. context 使用 API 注册事件5. mainloop 开始运行6. 事件被触发7. 回调进入应用层8. 退出与释放3.2 调用流程图3.3 Mainloop API 获取生命周期图4. 实战应用案例5. 一句话总结1. 前言本篇目的Linux PulseAudio 深度解析之pa_mainloop_get_api调用流程与实战。要点概括核心功能从pa_mainloop对象中获取pa_mainloop_api事件接口表。工作机制pa_mainloop_new()创建 mainloop 时内部已经初始化好一套事件 APIpa_mainloop_get_api()只是把这套 API 表返回给上层使用。典型用途创建pa_context、注册 IO 事件、注册 Time 事件、注册 Defer 事件、让 libpulse 能接入 mainloop 事件循环。2. 应用场景与用法pa_mainloop_get_api()是 PulseAudio mainloop 体系中的核心辅助接口。在 PulseAudio 中pa_context、pa_stream、Socket 连接、异步回调、Defer 事件等都需要依赖 mainloop 提供事件驱动能力。而该接口用于从pa_mainloop中取出事件 API 表交给后续模块使用。函数原型pa_mainloop_api*pa_mainloop_get_api(pa_mainloop*m);参数说明m:目标 pa_mainloop 对象返回值返回 pa_mainloop_api 指针用于让上层模块注册和管理IO 事件Time 事件Defer 事件quit 退出事件循环应用场景pa_mainloop_get_api()常见应用场景主要有三类。第一类是创建pa_context。应用程序通常先调用pa_mainloop_new()创建事件循环对象然后通过pa_mainloop_get_api(mainloop)获取pa_mainloop_api最后把这个 API 指针传给pa_context_new(api, name)。这样pa_context后续才能把 socket 事件、连接事件、状态变化事件注册到 mainloop 中。第二类是让 libpulse 接入事件循环。PulseAudio 客户端并不是同步阻塞式工作模型而是依赖 mainloop 处理 IO、Time、Defer 事件。pa_mainloop_get_api()返回的不是普通配置参数而是一组事件操作函数表libpulse 会通过它创建事件、启用事件、释放事件并最终由pa_mainloop_run()驱动这些事件执行。第三类是理解 PulseAudio 异步模型。在分析pa_context_connect()、pa_stream_connect_playback()、pa_stream_write()等异步 API 时必须先理解pa_mainloop_get_api()的作用它把 mainloop 的事件能力暴露给 context 和 stream使后续连接、回调、请求、响应都能被 mainloop 调度起来。3. 调用流程剖析3.1 核心步骤1. 应用层创建 mainlooppa_mainloop*mainloop;mainlooppa_mainloop_new();此时pa_mainloop内部已经准备好事件 API 表。2. 获取 mainloop APIpa_mainloop_api*api;apipa_mainloop_get_api(mainloop);这一步只是返回mainloop 内部的 api 指针3. 传给 pa_context_newpa_context*context;contextpa_context_new(api,pa_mainloop_get_api_demo);pa_context保存这个 API 后后续才能向 mainloop 注册事件。4. context 使用 API 注册事件后续连接过程中pa_context_connect()会继续创建 socket client、defer event、io event 等对象。这些事件最终都依赖pa_mainloop_api提供的事件操作函数。5. mainloop 开始运行pa_mainloop_run(mainloop,NULL);mainloop 进入事件循环后会统一处理 IO、Time、Defer 事件。6. 事件被触发当 socket 可读、连接完成、defer 事件触发、状态变化时mainloop 会执行对应回调。7. 回调进入应用层例如context_cb(...)被触发应用程序继续创建 stream 或执行后续逻辑。8. 退出与释放应用结束时释放pa_context_unref(context);pa_mainloop_free(mainloop);3.2 调用流程图3.3 Mainloop API 获取生命周期图4. 实战应用案例#includepulse/pulseaudio.h#includestdio.hstaticvoidcontext_cb(pa_context*c,void*userdata){pa_context_state_tstate;statepa_context_get_state(c);if(statePA_CONTEXT_READY)printf(context ready\n);}intmain(){pa_mainloop*mainloop;pa_mainloop_api*api;pa_context*context;/* * 创建 mainloop 对象 */mainlooppa_mainloop_new();/* * 从 mainloop 中获取事件 API 表 */apipa_mainloop_get_api(mainloop);/* * 把 API 表交给 pa_context */contextpa_context_new(api,pa_mainloop_get_api_demo);/* * 注册 context 状态回调 */pa_context_set_state_callback(context,context_cb,NULL);/* * 发起连接 */pa_context_connect(context,NULL,0,NULL);/* * 运行事件循环 */pa_mainloop_run(mainloop,NULL);return0;}5. 一句话总结pa_mainloop_get_api()本质上是“从 pa_mainloop 中取出事件 API 表交给 context、stream 等模块使用”。它本身不创建 mainloop也不启动事件循环只负责把pa_mainloop内部的事件能力暴露出来。后续pa_context_new()、pa_context_connect()、socket 事件、defer 事件和回调触发才会依赖这套 API 接入并运行在 mainloop 事件循环中。

相关新闻