Search code examples
caudioalsalibalsaamixer

How to use alsa library API to work with Headphone and Speaker?


I want to implement (mute/unmute and volume up/down) for Speaker and Headphone using c program.Using amixer command line utility as shown in this link https://askubuntu.com/questions/371970/how-to-switch-between-headphones-and-speakers-manually-from-command-line it works ,same things I need to implement using C program.

So I tried following different ways. I seen this example for volume control of Master Set ALSA master volume from C code

and for mute/unmute of Master Linux ALSA/Sound-API Questions - How do you mute?

both solution works perfect for Master configuration. But here in my case I want to implement same functionality for speaker and headphone.So instead of "Master" if I replaced selem_name with Speaker or Headphone+L0 which I found using amixer command it throws error.

Here I need to mute/unmute "Speaker" or "Headphone".

If I use *selem_name = "Speaker" or "Headphone" in below code it throws error shown below:

Is given selem_name is invalid? If so how can I List out valid selem_name for speaker and Headphone? The one I used its figured out from amixer command line utility.

What API I have to use for Speaker and Headphone?

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);
}

Is there any solution to mute/unmute specific device(speaker and headphone)?All help appreciate thanks.


Solution

  • Again, elem variable seems to be NULL for the control name you're using.

    You should check the control ID (name, index, interface) and the control device for the mixer connection. The 'default' device name usually redirects to pulse audio (only Master / PCM controls). If you use '-c 0' for amixer, the correct device name is 'hw:0' (const char *card = "hw:0";).