PusleAudio Demo

未分类 阅读(160)

```C
#include <pulse/pulseaudio.h>
#include <pulse/thread-mainloop.h>
#include <stdio.h>
#include <stdlib.h>

// 创建上下文
static pa_context* create_context(pa_threaded_mainloop* m);

// 等待上下文状态变为就绪
static int wait_context_state_ready(pa_threaded_mainloop* m, pa_context* ctx);

// 回调函数,在上下文状态变化时发一个信号
static void context_state_change_callback(pa_context* ctx, void* userdata);

// 回调函数,获取声卡信息
static void get_card_info_callback(pa_context *ctx, const pa_card_info* info, int state, void *userdata);


int main()
{
    pa_threaded_mainloop* m = pa_threaded_mainloop_new();
    if(m == NULL)
    {
        printf("pa_threaded_mainloop_new() failed.\b");
        return EXIT_FAILURE;
    }
    // 立即start
    pa_threaded_mainloop_start(m);

    // 创建上下文
    pa_context* ctx = create_context(m);
    if(ctx == NULL)
    {
        printf("create_context() failed.\n");
        return EXIT_FAILURE;
    }

    // 将上下文连接到服务进程
    pa_threaded_mainloop_lock(m);
    if(pa_context_connect(ctx, NULL, PA_CONTEXT_NOFAIL, NULL) < 0)
    {
        printf("pa_context_connect() failed.\n");
        return EXIT_FAILURE;
    }
    pa_threaded_mainloop_unlock(m);

    // 等待上下文就绪
    // 可以简化为
    // while(pa_context_get_state(ctx) != PA_CONTEXT_READY);
    int ret = wait_context_state_ready(m, ctx);
    if(ret == EXIT_SUCCESS)
    {
        // 获取声卡列表
        int running = 1; 
        pa_threaded_mainloop_lock(m);
        pa_operation* op = pa_context_get_card_info_list(ctx, get_card_info_callback, (void*)&running);
        pa_operation_unref(op);
        pa_threaded_mainloop_unlock(m);
        while(running);
    }

    // 释放
    pa_context_unref(ctx);
    pa_threaded_mainloop_free(m);
    return ret;
}


// 创建上下文
static pa_context* create_context(pa_threaded_mainloop* m)
{
    // 获取主循环API
    pa_threaded_mainloop_lock(m);
    pa_mainloop_api* mapi = pa_threaded_mainloop_get_api(m);
    pa_context* ctx = pa_context_new(mapi, "pulseaudio-demo");
    pa_threaded_mainloop_unlock(m);
    return ctx;
}

// 等待上下文状态变为就绪
static int wait_context_state_ready(pa_threaded_mainloop* m, pa_context* ctx)
{
    // 设置一个上下文状态改变的回调函数
    pa_threaded_mainloop_lock(m);
    pa_context_set_state_callback(ctx, context_state_change_callback, m);
    pa_threaded_mainloop_unlock(m);

    int state;
    do
    {
        pa_threaded_mainloop_lock(m);
        pa_threaded_mainloop_wait(m); // 等待 pa_threaded_mainloop_signal 发出信号
        state = pa_context_get_state(ctx); // 获取状态
        pa_threaded_mainloop_unlock(m);
        if(state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
        {
            return EXIT_FAILURE;
        }
    } while (state != PA_CONTEXT_READY);
    return EXIT_SUCCESS;
}

// 回调函数,在上下文状态变化时发一个信号
static void context_state_change_callback(pa_context* ctx, void* userdata)
{
    (void)ctx;
    pa_threaded_mainloop* loop = (pa_threaded_mainloop*)userdata;
    pa_threaded_mainloop_signal(loop, 0); // 发出一个信号,令 pa_threaded_mainloop_wait 返回
}

// 回调函数,获取声卡信息
static void get_card_info_callback(pa_context *ctx, const pa_card_info* info, int state, void *userdata)
{
    (void)ctx;
    if(state == 0)
    {
        printf("card name : %s\n",info->name);
    }
    else
    {
        (*(int*)userdata) = 0; // 令 running = 0 让程序结束
    }
}
```