N
N
nckma2019-07-16 10:11:29
ALSA
nckma, 2019-07-16 10:11:29

Is there a uniform way to switch ALSA sound output from a script?

I need to prepare two scripts that
1) list the available ALSA audio outputs
2) be able to switch the audio output to a given output.
It would seem that there are no problems here and everything can be done with the aplay and amixer commands.
But something doesn't work. The problem is the following.
For example, the Raspberry Pi3 has an HDMI output and there is a Jack connector.
aplay output:

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

It would seem that you can play on HDMI with the command aplay -D hw:0,1 music.wav and play on analog Jack
with the command aplay -D hw:0,0 music.wav
But it doesn’t work like that.
The only way I found to switch the output is
amixer cset numid=3 2 for jack output or
amixer cset numid=3 1 for HDMI output.
And it doesn’t matter if I play aplay through hw: 0,0 or hw: 0,1
numid, you still need to know something, for example, the numid list is like this:
$ amixer controls
numid=3,iface=MIXER,name='PCM Playback Route'
numid=2,iface=MIXER,name='PCM Playback Switch'
numid=1,iface=MIXER,name='PCM Playback Volume'
numid=5,iface=PCM,name='IEC958 Playback Con Mask'
numid=4,iface=PCM,name='IEC958 Playback Default'

But I need the scripts to work on the x86 platform, it is not known in advance what audio devices will be installed there. On my test laptop, amixer shows the following:
$ amixer controls
numid=23,iface=CARD,name='HDMI/DP,pcm=3 Jack'
numid=19,iface=CARD,name='Headphone Jack'
numid=17,iface=CARD,name='Internal Mic Phantom Jack'
numid=18,iface=CARD,name='Mic Jack'
numid=20,iface=CARD,name='Speaker Phantom Jack'
numid=16,iface=MIXER,name='Master Playback Switch'
numid=15,iface=MIXER,name='Master Playback Volume'
numid=2,iface=MIXER,name='Headphone Playback Switch'
numid=1,iface=MIXER,name='Headphone Playback Volume'
numid=14,iface=MIXER,name='Mic Boost Volume'
numid=9,iface=MIXER,name='Mic Playback Switch'
numid=8,iface=MIXER,name='Mic Playback Volume'
numid=12,iface=MIXER,name='Capture Switch'
numid=11,iface=MIXER,name='Capture Volume'
numid=5,iface=MIXER,name='Loopback Mixing'
numid=24,iface=MIXER,name='IEC958 Playback Con Mask'
numid=25,iface=MIXER,name='IEC958 Playback Pro Mask'
numid=26,iface=MIXER,name='IEC958 Playback Default'
numid=27,iface=MIXER,name='IEC958 Playback Switch'
numid=10,iface=MIXER,name='Auto-Mute Mode'
numid=13,iface=MIXER,name='Internal Mic Boost Volume'
numid=7,iface=MIXER,name='Internal Mic Playback Switch'
numid=6,iface=MIXER,name='Internal Mic Playback Volume'
numid=4,iface=MIXER,name='Speaker Playback Switch'
numid=3,iface=MIXER,name='Speaker Playback Volume'
numid=22,iface=PCM,name='Capture Channel Map'
numid=21,iface=PCM,name='Playback Channel Map'
numid=28,iface=PCM,name='ELD',device=3
numid=29,iface=PCM,name='Playback Channel Map',device=3

That is, here on this platform there is no such ROUTE parameter at all. And how then to switch from HDMI to Jack on a laptop? The system is built in buildroot, that is, it is not a ready-made distribution kit like ubuntu or debian.
A universal solution (scripts) is required that would work on different platforms and could display a list of audio outputs to the console and switch audio output to a given output.
How can this be done?

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question