[SOLVED]How do I automatically switch audio output depending on what HDMI device is connected?

All Gurus once were Newbies
Forum rules
There are no such things as "stupid" questions. However if you think your question is a bit stupid, then this is the right place for you to post it. Please stick to easy to-the-point questions that you feel people can answer fast. For long and complicated questions prefer the other forums within the support section.
Before you post please read how to get help
Post Reply
FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

[SOLVED]How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

Hey, so I recently ditched Windows in favor of Linux Mint 19.3 Cinnamon

I have a laptop with one HDMI out and a set of speakers connected to it. When I'm at my desk I plug in my monitor and when I'm going to bed I plug in my TV.
In Windows if I had the monitor plugged in, sound was coming from the speakers, and when I plugged the TV in the sound output automatically switched to TV.
That's not the case on Linux though.

So basically I think that I'm looking for a script that would run in the background and switched the sound output depending on what HDMI device is connected.

Any help would be appreciated.
Last edited by FluidExtractor on Mon May 25, 2020 5:18 pm, edited 1 time in total.

FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

So far I solved half of the problem. I managed to create a script that changes the audio output based on which screen is connected. It's probably not a very professional solution but it works.

Code: Select all

#!/bin/bash
xrandr --listmonitors > /home/fluidextractor/Scripts/Resources/monitor
s="$(sed '2q;d' /home/fluidextractor/Scripts/resources/mainmonitor)"
d="$(sed '2q;d' /home/fluidextractor/Scripts/resources/monitor)"
if [ "$d" == "$s" ] ;then
    pacmd set-card-profile 1 "output:analog-stereo"
else
    pacmd set-card-profile 1 "output:hdmi-stereo"
fi
I tried automatically running the script on HDMI state change using an udev rule, but I just can't get it to work for some reason.

Code: Select all

KERNEL=="card0", SUBSYSTEM=="drm", ACTION=="change", RUN+="/bin/sh /home/fluidextractor/Scripts/monitor.sh"
Any suggestions on what I should do?

User avatar
MrEen
Level 19
Level 19
Posts: 9765
Joined: Mon Jun 12, 2017 8:39 pm

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by MrEen »

Hi FluidExtractor, and welcome to the forum.

I'm not up too much on creating udev rules, but let's make sure your built-in audio and HDMI audio are indeed on the same card for starters. Please post the output of pacmd list-cards

FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

Here's the output of pacmd list-cards

Code: Select all

2 card(s) available.
    index: 0
	name: <alsa_card.usb-ZY.Ltd_ZY_Control_Mic-00>
	driver: <module-alsa-card.c>
	owner module: 7
	properties:
		alsa.card = "1"
		alsa.card_name = "ZY Control Mic"
		alsa.long_card_name = "ZY.Ltd ZY Control Mic at usb-0000:00:1a.0-1.3, full speed"
		alsa.driver_name = "snd_usb_audio"
		device.bus_path = "pci-0000:00:1a.0-usb-0:1.3:1.0"
		sysfs.path = "/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.0/sound/card1"
		udev.id = "usb-ZY.Ltd_ZY_Control_Mic-00"
		device.bus = "usb"
		device.vendor.id = "1915"
		device.vendor.name = "Nordic Semiconductor ASA"
		device.product.id = "1025"
		device.product.name = "ZY Control Mic"
		device.serial = "ZY.Ltd_ZY_Control_Mic"
		device.string = "1"
		device.description = "ZY Control Mic"
		module-udev-detect.discovered = "1"
		device.icon_name = "audio-card-usb"
	profiles:
		input:analog-mono: Analog Mono Input (priority 2, available: unknown)
		off: Off (priority 0, available: unknown)
	active profile: <input:analog-mono>
	sources:
		alsa_input.usb-ZY.Ltd_ZY_Control_Mic-00.analog-mono/#0: ZY Control Mic Analog Mono
	ports:
		analog-input-mic: Microphone (priority 8700, latency offset 0 usec, available: unknown)
			properties:
				device.icon_name = "audio-input-microphone"
    index: 1
	name: <alsa_card.pci-0000_00_1b.0>
	driver: <module-alsa-card.c>
	owner module: 8
	properties:
		alsa.card = "0"
		alsa.card_name = "HDA Intel PCH"
		alsa.long_card_name = "HDA Intel PCH at 0xe2720000 irq 40"
		alsa.driver_name = "snd_hda_intel"
		device.bus_path = "pci-0000:00:1b.0"
		sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card0"
		device.bus = "pci"
		device.vendor.id = "8086"
		device.vendor.name = "Intel Corporation"
		device.product.id = "1c20"
		device.product.name = "6 Series/C200 Series Chipset Family High Definition Audio Controller"
		device.form_factor = "internal"
		device.string = "0"
		device.description = "Built-in Audio"
		module-udev-detect.discovered = "1"
		device.icon_name = "audio-card-pci"
	profiles:
		input:analog-stereo: Analog Stereo Input (priority 60, available: unknown)
		output:analog-stereo: Analog Stereo Output (priority 6000, available: unknown)
		output:analog-stereo+input:analog-stereo: Analog Stereo Duplex (priority 6060, available: unknown)
		output:analog-surround-40: Analog Surround 4.0 Output (priority 700, available: no)
		output:analog-surround-40+input:analog-stereo: Analog Surround 4.0 Output + Analog Stereo Input (priority 760, available: unknown)
		output:hdmi-stereo: Digital Stereo (HDMI) Output (priority 5400, available: unknown)
		output:hdmi-stereo+input:analog-stereo: Digital Stereo (HDMI) Output + Analog Stereo Input (priority 5460, available: unknown)
		output:hdmi-surround: Digital Surround 5.1 (HDMI) Output (priority 300, available: unknown)
		output:hdmi-surround+input:analog-stereo: Digital Surround 5.1 (HDMI) Output + Analog Stereo Input (priority 360, available: unknown)
		output:hdmi-surround71: Digital Surround 7.1 (HDMI) Output (priority 300, available: unknown)
		output:hdmi-surround71+input:analog-stereo: Digital Surround 7.1 (HDMI) Output + Analog Stereo Input (priority 360, available: unknown)
		off: Off (priority 0, available: unknown)
	active profile: <output:analog-stereo>
	sinks:
		alsa_output.pci-0000_00_1b.0.analog-stereo/#6: Built-in Audio Analog Stereo
	sources:
		alsa_output.pci-0000_00_1b.0.analog-stereo.monitor/#8: Monitor of Built-in Audio Analog Stereo
	ports:
		analog-input-internal-mic: Internal Microphone (priority 8900, latency offset 0 usec, available: no)
			properties:
				device.icon_name = "audio-input-microphone"
		analog-input-mic: Microphone (priority 8700, latency offset 0 usec, available: yes)
			properties:
				device.icon_name = "audio-input-microphone"
		analog-output-speaker: Speakers (priority 10000, latency offset 0 usec, available: no)
			properties:
				device.icon_name = "audio-speakers"
		analog-output-headphones: Headphones (priority 9000, latency offset 0 usec, available: yes)
			properties:
				device.icon_name = "audio-headphones"
		hdmi-output-0: HDMI / DisplayPort (priority 5900, latency offset 0 usec, available: yes)
			properties:
				device.icon_name = "video-display"
				device.product.name = "MD20461"

User avatar
MrEen
Level 19
Level 19
Posts: 9765
Joined: Mon Jun 12, 2017 8:39 pm

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by MrEen »

All right, you do indeed have both on the same card, which is unfortunate for your case.

I'm wondering if the issue is the udev rule. See if this one fires:

Code: Select all

SUBSYSTEM!="sound", GOTO="my_audio_end"
ACTION!="add", GOTO="my_audio_end"

RUN+="/bin/sh /home/fluidextractor/Scripts/monitor.sh"

LABEL="my_audio_end"

FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

Unfortunately that rule is not working. There's probably something I don't know about udev rules which makes them not work. Guess I'll have to do some more research.

User avatar
MrEen
Level 19
Level 19
Posts: 9765
Joined: Mon Jun 12, 2017 8:39 pm

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by MrEen »

Your comparison in the bash script might also be to blame. This is a weak point for me, but are you sure you want == there? Should they ever really match? I'm not sure what it's comparing which is why I ask.

You probably already know this, but you can run those lines in the terminal then echo $s and echo $d to see if it's correct. Also, did you mean to capitalize the r in Resources on the xrandr line and not on the other two lines? Case could be the issue here.

FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

The bash script itself works (I fixed the capitalization of the "r" after posting it here).

An explanation on how the script works:
If I run xrandr --listmonitors command while my desk monitor is connected, it outputs this:

Code: Select all

Monitors: 1
 0: +*HDMI-1 1920/521x1080/293+0+0  HDMI-1
and if xrandr --listmonitors is run while the TV is connected then it outputs this:

Code: Select all

Monitors: 1
 0: +*HDMI-1 1366/607x768/345+0+0  HDMI-1
$s is the second line from a static file where I manually put the xrandr output when the desk monitor was connected
$d is the second line from a file which xrandr outputs to the start of the script

The if statement compares these two variables, if they match, that means that the desk monitor is connected so the audio output should be switched to the speakers. If they don't match, that means that the TV is connected and the audio output should be switched to HDMI.

I'm pretty bad at explaining things but I hope that this is enough.

User avatar
MrEen
Level 19
Level 19
Posts: 9765
Joined: Mon Jun 12, 2017 8:39 pm

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by MrEen »

You explained just fine (for me) and now I see your issue:

Code: Select all

pacmd set-card-profile 1
You're trying to change the profile of the wrong card. Your built-in audio card is card 0. I think you saw the index number, and used 1 because of that. See a little below that:

Code: Select all

    index: 1
	name: <alsa_card.pci-0000_00_1b.0>
	driver: <module-alsa-card.c>
	owner module: 8
	properties:
		alsa.card = "0"
EDIT: Damn. Looks like I might be wrong about that. Searching to make sure...

I think this should be the command:

Code: Select all

pacmd set-card-profile alsa_card.pci-0000_00_1b.0 output:analog-stereo
and:

Code: Select all

pacmd set-card-profile alsa_card.pci-0000_00_1b.0 output:hdmi-stereo

FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

Yeah, card 1 is the built-in one, card 0 is a USB dongle for a wireless remote with a microphone. And using card names instead of index numbers works too.

As I said, the script works fine, if I run it manually when the TV is connected the audio output switches to HDMI. I realized just now that this would be a lot easier if my desk monitor didn't have crappy built-in speakers, then after connecting it, audio output would just default to speakers because that HDMI device wouldn't be able to output audio.

I still think that there's something wrong with the udev rules I'm creating. If I run udevadm test /sys/class/drm then I can see my rule in the output, so udev sees it correctly. My only guess is that udev has some problems with actually executing the script for some reason. Could be the permissions but I already played around with those.

User avatar
MrEen
Level 19
Level 19
Posts: 9765
Joined: Mon Jun 12, 2017 8:39 pm

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by MrEen »

FluidExtractor wrote:
Sun May 24, 2020 6:48 am
Could be the permissions but I already played around with those.
Ahh, good point. The udev rule would act as root, and the pacmd commands need to be run as your user. This isn't an area I'm good at, but try preceeding the pacmd commands with sudo yourusername in the script.

And just to clarify, your built-in card is actually card 0, but is index 1. That tripped me up on my last post as the pacmd commands do use the index, not the card number. Most of the pacmd commands I use, actually use the card number (or name) instead of the index number.

One other thing I should probably mention. It's possible (but not confirmed) your script is actually working. Changing the profile won't automatically change the active streams. You can check that with pacmd list-cards | grep "active profile"

FluidExtractor
Level 1
Level 1
Posts: 7
Joined: Thu May 21, 2020 10:40 am

Re: How do I automatically switch audio output depending on what HDMI device is connected?

Post by FluidExtractor »

I had no idea that pacmd has to be run as the current user, thanks for the tip. I believe su yourusername -c "yourcommand" should be used instead of sudo yourusername.
It kinda worked but turns out that my udev rule fired only on HDMI unplug events so I decided to switch to autorandr along with autorandr-launcher to check which display is connected and I finally got it working.

Here's the final version of the script

Code: Select all

#!/bin/bash
s="$(cat /home/fluidextractor/Scripts/resources/mainmonitor)"
d="$(xrandr | grep 'HDMI-1 connected primary 1920')"

if [ "$d" == "$s" ];then
    pacmd set-card-profile alsa_card.pci-0000_00_1b.0 "output:analog-stereo"
else
    pacmd set-card-profile alsa_card.pci-0000_00_1b.0 "output:hdmi-stereo"
fi
Thanks again for all the help MrEen.

User avatar
MrEen
Level 19
Level 19
Posts: 9765
Joined: Mon Jun 12, 2017 8:39 pm

Re: [SOLVED]How do I automatically switch audio output depending on what HDMI device is connected?

Post by MrEen »

Hey, I'm glad you got it figured out. Nicely done. :D

With the sudo vs su, like I said, not my area but thanks for pointing that out.

Post Reply

Return to “Newbie Questions”