系统音量控制

环境:

嵌入式系统linux ubuntu18.04

需求:

业务层需要对系统音量进行控制

现象:

  1. alsamixer 操作音量成非线性变现
  2. supervisor管理进程下,Pulseaudio音量操作失效

解决过程:

方案一

alsamixer ,系统有对应服务

alsamixer -c 2  #选择对应声卡 出现界面,可上下键调节

命令行设置音量

amixer cset numid=2,iface=MIXER,name='Playback Channel Map' 10  #后查看音量是否变化

问题是此时音量并没有按设定的音量进行变化,并且从程序中API来看,对应关系成非线性。

方案二

Pulseaudio

pactl list sinks #查看声卡名称
pactl set-sink-volume 1 55% #命令设置音量

观察alsamixer 的图形界面,音量变化(0-100)误差在±2,±1居多,然后业务层调用命令或者相应API代码:

#include <pulse/pulseaudio.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    const char *sink_name; // 设备名
    pa_volume_t volume;    // 音量值
    pa_mainloop *mainloop; // pa_mainloop 对象
} UserData;

// 回调
void context_state_callback(pa_context *c, void *userdata) {
	UserData *m = (UserData *)userdata; 
	switch (pa_context_get_state(c)) {
        case PA_CONTEXT_READY:{
			fprintf(stderr, "Connected to PulseAudio.\n");
			pa_operation *op;
			pa_cvolume volume;
			//pa_volume_t vol = PA_VOLUME_NORM * 0.75; // 设置为 75% 音量
			// 初始化 pa_cvolume
			pa_cvolume_set(&volume, 2, m->volume); // 2 表示双声道(立体声)
			op = pa_context_set_sink_volume_by_name(c, m->sink_name, &volume, NULL, NULL);
			if (op) {
				pa_operation_unref(op);
			} else {
				fprintf(stderr, "Failed to create operation: device not found or context not ready.\n");
			}
			pa_mainloop_quit(m->mainloop, 0);
			break;
		}
		case PA_CONTEXT_FAILED:
        case PA_CONTEXT_TERMINATED:
            fprintf(stderr, "Context failed or terminated.\n");
            pa_mainloop_quit(m->mainloop, 1); 
            break;
        default:
            // 其他状态(如连接中),无需处理
            break;
	}
}
/* volume control*/
void volume_control(const string &device, int value) {
#if 0 //命令代码
	auto cmd = "pactl set-sink-volume 1  " + to_string(value)+"%";
	PrintI("set volume: cmd = %s\n", cmd);
    System::execute(cmd);
#endif
#if 1
	pa_mainloop *m = pa_mainloop_new();
    pa_mainloop_api *api = pa_mainloop_get_api(m);
    pa_context *context = pa_context_new(api, "pactl");
	float ll=(float)value/100;
	PrintI("set volume: volume = %f\n", ll);
	PrintI("set volume: name = %s\n", device.data());
	UserData data = {
        .sink_name = device.data(),//"alsa_output.platform-es8388-sound.stereo-fallback", // 设备名
        .volume = PA_VOLUME_NORM * ll, 
        .mainloop = m 
    };

    pa_context_set_state_callback(context, context_state_callback, &data);
    pa_context_connect(context, NULL, PA_CONTEXT_NOFLAGS, NULL);

	int ret = 1;
    pa_mainloop_run(m, &ret);
for (char **env = environ; *env != NULL; env++) {
        printf("%s\n", *env);
    }
    pa_context_unref(context);
    pa_mainloop_free(m);
#endif
	return ;
}

程序运行及设置均没问题
但是用supervisor管理此进程时,也就是自动启动后,音量操作失效,没有显示明显错误,最后处理方法

  1. 在应用配置文件中添加环境变量environment中
environment=DISPLAY=":0",PULSE_SERVER="/run/user/1001/pulse/native"

查看PULSE_SERVER,也就是系统中PULSE音频服务器信息 方法:

pactl info 
Server String: unix:/run/user/1000/pulse/native #Server String 就是

2.将此变量添加配置文件中command变量中

command='...export DISPLAY=:0 && export PULSE_SERVER=/run/user/1001/pulse/native  && ./bin/voice'
reboot #后系统操作音量正常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值