HDMI presentation setup on Linux, Part II: problems and tips
In Part I of HDMI Presentation Setup on Linux, I covered the basics of getting video and audio working over HDMI. Now I want to cover some finer-grained details: some problems I had, and ways to make it easier to enable HDMI when you need it.
Testing follies, delays, and screen blinking/flashing woes
While I was initially trying to get this working, I was using my own
short sound clip (one of the alerts I use for IRC) and it wasn't
working. Then I tried the test I showed in part I,
$ aplay -D plughw:0,3 /usr/share/sounds/alsa/Front_Center.wav
and that worked fine.
Tried my sound clip again -- nothing. I noticed that my clip was mono
and 8-bit while the ALSA sample was stereo and 16-bit, and I wasted a
lot of time in web searches on why HDMI would play one and not the other.
Eventually I figured out that the reason my short clip wasn't playing was that there's a delay when switching on HDMI sound, and the first second two two of any audio may be skipped. I found lots of complaints about people missing the first few seconds of sound over HDMI, so this problem is quite common, and I haven't found a solution.
So if you're giving a talk where you need to play short clips -- for
instance, a talk on bird calls -- be aware of this. I'm probably
going to make a clip of a few seconds of silence, so I can play silence
before every short clip to make sure I'm fully switched over to HDMI
before the clip starts:
aplay -D plughw:0,3 silence.wav osprey.wav
Another problem, probably related, when first starting an audio file: the screen blinks brieftly off then on again, then blinks again a little while after the clip ends. ("Flicker" turns out to be a better term to use when web searching, though I just see a single blink, not continued flickering). It's possible this is something about my home TV, and I will have to try it with another monitor somewhere to see if it's universal. It sounds like kernel bug 51421: Enabling HDMI sound makes HDMI video flicker, but that bug was marked resolved in 2012 and I'm seeing this in 2015 on Debian Jessie.
Making HDMI the sound default
What a pain, to have to remember to add -D plughw:0,3 every time you play a sound. And what do you do for other programs that don't have that argument?
Fortunately, you can make HDMI your default sound output. Create a file in your home directory called .asoundrc with this in it (you may be able to edit this down -- I didn't try) and then all audio will go to HDMI:
pcm.dmixer { type dmix ipc_key 1024 ipc_key_add_uid false ipc_perm 0660 slave { pcm "hw:0,3" rate 48000 channels 2 period_time 0 period_size 1024 buffer_time 0 buffer_size 4096 } } pcm. !default { type plug slave.pcm "dmixer" }
Great! But what about after you disconnect? Audio will still be going to HDMI ... in other words, nowhere. So rename that file:
$ mv .asoundrc asoundrc-hdmiThen when you connect to HDMI, you can copy it back:
$ cp asoundrc-hdmi .asoundrc
What a pain, you say again! This should happen automatically!
That's possible, but tricky: you have to set up udev rules and scripts. See this Arch Linux discussion on HDMI audio output switching automatically for the gory details. I haven't bothered, since this is something I'll do only rarely, when I want to give one of those multimedia presentations I sometimes contemplate but never actually give. So for me, it's not worth fighting with udev when, by the time I actually need HDMI audio, the udev syntax probably will have changed again.
Aliases to make switching easy
But when I finally do break down and design a multimedia presentation, I'm not going to be wanting to do all this fiddling in the presentation room right before the talk. I want to set up aliases to make it easy.
There are two things that need to be done in that case: make HDMI output the default, and make sure it's unmuted.
Muting can be done automatically with amixer. First run amixer
with no arguments to find out the channel name (it gives a lot of output,
but look through the "Simple mixer control" lines, or speed that up
with amixer | grep control
.
Once you know the channel name (IEC958 on my laptop), you can run:
amixer sset IEC958 unmute
The rest of the alias is just shell hackery to create a file called
.asoundrc with the right stuff in it, and saving .asoundrc before
overwriting it. My alias in .zshrc is set up so that I can
say hdmisound on or hdmisound off (with no arguments, it
assumes on), and it looks like this:
# Send all audio output to HDMI. # Usage: hdmisound [on|off], default is on. hdmisound() { if [[ $1 == 'off' ]]; then if [[ -f ~/.asoundrc ]]; then mv ~/.asoundrc ~/.asoundrc.hdmi fi amixer sset IEC958 mmute else if [[ -f ~/.asoundrc ]]; then mv ~/.asoundrc ~/.asoundrc.nohdmi fi cat >> ~/.asoundrc <<EOF pcm.dmixer { type dmix ipc_key 1024 ipc_key_add_uid false ipc_perm 0660 slave { pcm "hw:0,3" rate 48000 channels 2 period_time 0 period_size 1024 buffer_time 0 buffer_size 4096 } } pcm. !default { type plug slave.pcm "dmixer" } EOF amixer sset IEC958 unmute fi }
Of course, I could put all that .asoundrc content into a file and just copy/rename it each time. But then I have another file I need to make sure is in place on every laptop; I decided I'd rather make the alias self-contained in my .zshrc.
[ 11:57 Oct 30, 2015 More linux/laptop | permalink to this entry | ]