Why is ALSA often not reading the audio card state
1
vote
0
answers
108
views
I'm having a terrible time with ALSA on a PI5. It will play and record sound, but the control interface seems to only work sometimes. I cannot find a cause for this. I could use some help understanding what is going on.
My objective is to have a USB speaker (Polycom P3200M) reset its volume to the last volume setting on a boot. This should work with
alsactl rdaemon
. Further, there is a canned service in alsa-state.service
that should do that. It is not working. I already have /etc/asla/state-daemon.conf
in place, so the rdaemon
option should be running.
A look at ps -ef
shows:
root 660 1 0 20:06 ? 00:00:00 /usr/sbin/alsactl -E HOME=/run/alsa -E XDG_RUNTIME_DIR=/run/alsa/runtime -s -n 19 -c rdaemon
So, I have to assume the service is running correctly. The problem is that if I execute amixer -c2
I don't get the correct output. For example it will show:
Simple mixer control 'PCM',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 20
Mono: Playback 9 [45%] [-22.00dB] [on]
Simple mixer control 'Headset',0
Capabilities: cswitch cswitch-joined
Capture channels: Mono
Mono: Capture [on]
If I then change the volume on the speaker by pushing the buttons, and rerun axmixer -c2
, I get the exact same output.
By looking at the timestamp on /var/lib/alsa/asound.state
I can see that the file is only touched at boot, and then never again.
Finally, in a fit of frustration, I wrote my own code to monitor the device, and determine when the volume was changed.
#include
#include
int elem_callback(snd_mixer_elem_t *elem,unsigned int mask);
int main(int argc, char* argv[])
{
long min, max;
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *selem_name = "PCM";
long curVolume;
int res;
if(argc!=2)
{
return(1);
}
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, argv);
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);
printf("Name: %s\n",snd_mixer_selem_get_name(elem));
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
printf("max: %d\nmin:%d\n",max,min);
snd_mixer_selem_get_playback_volume(elem,SND_MIXER_SCHN_MONO,&curVolume);
printf("Current Volume: %d\n",curVolume);
snd_mixer_elem_set_callback(elem,elem_callback);
while(1)
{
res=snd_mixer_wait(handle,-1);
res=snd_mixer_handle_events(handle);
}
snd_mixer_close(handle);
return(0);
}
int elem_callback(snd_mixer_elem_t *elem,unsigned int mask)
{
long curVolume;
switch(mask)
{
case 1:
snd_mixer_selem_get_playback_volume(elem,SND_MIXER_SCHN_MONO,&curVolume);
printf("Current Volume: %d\n",curVolume);
printf("\tmask: %d\n",mask);
break;
default:
printf("Unrecognized mask: %d\n",mask);
break;
}
return (0);
}
I lifted most of this code from [link](https://stackoverflow.com/questions/6787318/set-alsa-master-volume-from-c-code)
What is truly bothersome is the above code worked. I could press the volume button on the speaker and the callback would get triggered. All was good. Then I rebooted the system and came back a day later. Now the code does nothing. It will output what it thinks the current settings are (which are not correct) but it will not react to the button presses.
I'm at a loss. Why is ALSA sometimes working?
Asked by knottied
(21 rep)
Feb 17, 2024, 06:15 PM