如何使用 alsa 库 API 与耳机和扬声器一起使用?

Posted

技术标签:

【中文标题】如何使用 alsa 库 API 与耳机和扬声器一起使用?【英文标题】:How to use alsa library API to work with Headphone and Speaker? 【发布时间】:2019-09-14 09:37:40 【问题描述】:

我想使用 c 程序为扬声器和耳机实现(静音/取消静音和音量增大/减小)。使用 amixer 命令行实用程序,如此链接 https://askubuntu.com/questions/371970/how-to-switch-between-headphones-and-speakers-manually-from-command-line 所示,它可以工作,我需要使用 C 程序实现相同的东西.

所以我尝试了不同的方法。 我看到了这个关于 Master 音量控制的例子 Set ALSA master volume from C code

对于主控的静音/取消静音 Linux ALSA/Sound-API Questions - How do you mute?

这两种解决方案都非常适合主配置。 但在我的情况下,我想为扬声器和耳机实现相同的功能。因此,如果我用扬声器或耳机+L0 替换 selem_name 而不是“Master”,我发现使用 amixer 命令会引发错误。

这里我需要将“扬声器”或“耳机”静音/取消静音。

如果我在下面的代码中使用 *selem_name = "Speaker" 或 "Headphone",则会引发如下所示的错误:

是否给定的selem_name 无效? 如果是这样,我如何列出扬声器和耳机的有效 selem_name? 我使用它从 amixer 命令行实用程序中找到的那个。

我必须为扬声器和耳机使用什么 API?

Errorr eturn by test.c program:

alsa: simple.c:346: snd_mixer_selem_has_playback_switch: Assertion 
`elem' failed.
Aborted

//test.c

#include<stdio.h>
#include<alsa/asoundlib.h>

void SetAlsaSpeakerMute()

    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;
    const char *card = "default";

    const char *selem_name = "Speaker";

    snd_mixer_open(&handle, 0);
    snd_mixer_attach(handle, card);
    snd_mixer_selem_register(handle, NULL, NULL);
    snd_mixer_load(handle);

    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, selem_name);
    snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);

    if (snd_mixer_selem_has_playback_switch(elem)) 
        snd_mixer_selem_set_playback_switch_all(elem, 0);
    

    snd_mixer_close(handle);


int main()

    SetAlsaSpeakerMute();
    return 0;

//For const char *selem_name = "Master" this program works fine.
//This can mute Mixer of default sound card

void SetAlsaMasterMute()

    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;
    const char *card = "default";
    const char *selem_name = "Master";

    snd_mixer_open(&handle, 0);
    snd_mixer_attach(handle, card);
    snd_mixer_selem_register(handle, NULL, NULL);
    snd_mixer_load(handle);

    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, selem_name);
    snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);

    if (snd_mixer_selem_has_playback_switch(elem)) 
        snd_mixer_selem_set_playback_switch_all(elem, 0);
    

    snd_mixer_close(handle);

是否有任何解决方案可以将特定设备(扬声器和耳机)静音/取消静音?感谢所有帮助。

【问题讨论】:

哪一行是simple.c:346 返回错误信息。它显示位于 alsa 库文件 simple.c 中的 alsa 库函数 snd_mixer_selem_has_playback_switch() 给出错误。 此代码缺少错误处理。对于任何返回错误代码的函数,你必须检查它。 是的。但它只是一个示例代码。它不能解决我关于静音/取消静音耳机和扬声器@CL的问题 我认为这个问题不值得结束——它是关于(libalsa 的)编程的。 【参考方案1】:

同样,对于您正在使用的控件名称,elem 变量似乎为 NULL。

您应该检查混音器连接的控制 ID(名称、索引、接口)和控制设备。 “默认”设备名称通常重定向到脉冲音频(仅 Master / PCM 控件)。如果您对 amixer 使用 '-c 0',正确的设备名称是 'hw:0' (const char *card = "hw:0";)。

【讨论】:

以上是关于如何使用 alsa 库 API 与耳机和扬声器一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

如何从电话、电话扬声器、耳机或蓝牙设备切换音频输出

想在蓝牙耳机上播放 TTS

如何在 iPhone 应用程序中切换扬声器和耳机

同时向扬声器和耳机输出音频?

如何通过 Apple 设备的内部扬声器路由音频,避免使用耳机?

AVPlayer 不能与 AirPlay 一起使用