You are not logged in.

#1 2017-05-13 13:00:21

Denshou
Member
Registered: 2017-01-17
Posts: 25

[SOLVED] HDMI - Udev rule only partially working

Hi everyone ! smile

A while ago, I set up a script and a Udev rule to extend my screen when plugging a HDMI cable. This worked perfectly, but the sound still came from my computer instead of the external monitor, so today, I decided to work on that.

Analog and HDMI sound outputs are handled by two different cards on my laptop, so the only thing I could do to be able to switch sound outputs for already running applications was to install pacswitch from the AUR. I tested it and it worked fine, so I added it to my script, saved the changes and reloaded my rules.

However, when the rule is triggered, only the screen display changes, the sound keep coming from my computer or my external monitor, according to which was the last one handling the sound when the rule was triggered.

Now what's really weird is that manually starting the script works properly. Both display and sound are changed accordingly, so I guess this is more likely an issue with the rule, but I don't get what causes this issue.

Here's the said Udev rule, located at /etc/udev/rules.d/99-hdmicheck.rules :

SUBSYSTEM=="drm", ACTION=="change", RUN+="/usr/local/bin/hdmicheck"

And here's my script  :

#!/bin/bash

# udev rules are run as Root, who can't act on user display if he doesn't know where it is
export XAUTHORITY=/home/me/.Xauthority
export DISPLAY=:0

STATUS=$(xrandr | grep HDMI-1 | cut -d " " -f 2)

# check if concerned output is connected
if [[ $STATUS == connected ]]
then
	xrandr --output eDP-1 --auto --output HDMI-1 --auto --left-of eDP-1 && paswitch alsa_output.pci-0000_00_03.0.hdmi-stereo
else
	xrandr --output eDP-1 --auto --output HDMI-1 --off && paswitch alsa_output.pci-0000_00_1b.0.analog-stereo
fi

I really have no idea about what is wrong, especially since the script works fine when I start it myself, so I hope someone can help me with this. smile

Thank you !

Last edited by Denshou (2017-05-13 20:53:11)

Offline

#2 2017-05-13 14:58:48

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 19,769

Re: [SOLVED] HDMI - Udev rule only partially working

I know nothing of pacswitch, but I would guess this is a dbus problem.  When your script is run from the udev infrastructure, it has no access to your user's session or it's dbus instance. 
Check to see if pacswich uses the dbus by running a tool like dbus-monitor in a separate window while you run your script by hand.  If there is dbus activity, this is likely your problem.

Edit:  Another possibility:  You are using && to string two commands together.  If xrandr were, for some reason, to return a failure code then your pacswitch command will not execute.  Don't have any clue why xranrd would do that, but I have seen some bizarre things happen and I am just thinking out loud.

Last edited by ewaller (2017-05-13 15:03:58)


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#3 2017-05-13 15:32:28

Denshou
Member
Registered: 2017-01-17
Posts: 25

Re: [SOLVED] HDMI - Udev rule only partially working

ewaller wrote:

I know nothing of pacswitch, but I would guess this is a dbus problem.  When your script is run from the udev infrastructure, it has no access to your user's session or it's dbus instance. 
Check to see if pacswich uses the dbus by running a tool like dbus-monitor in a separate window while you run your script by hand.  If there is dbus activity, this is likely your problem.

Thanks for your answer. I just tried, but dbus-monitor didn't show anything when I launched my script.

ewaller wrote:

Edit:  Another possibility:  You are using && to string two commands together.  If xrandr were, for some reason, to return a failure code then your pacswitch command will not execute.  Don't have any clue why xranrd would do that, but I have seen some bizarre things happen and I am just thinking out loud.

I'm kind of new to this so I'm not always sure about how to string commands together. I tried with a pipe beforehand, but with not luck. Do you have any other suggestion ?

Offline

#4 2017-05-13 15:51:04

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 19,769

Re: [SOLVED] HDMI - Udev rule only partially working

It probably won't help, as I say I was thinking out loud, but you might try || instead of &&.

Other possibilities are a user permission problem or an environment problem.  Your script is running as the user root and does not have access to your environmental variables


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#5 2017-05-13 17:19:11

Denshou
Member
Registered: 2017-01-17
Posts: 25

Re: [SOLVED] HDMI - Udev rule only partially working

ewaller wrote:

It probably won't help, as I say I was thinking out loud, but you might try || instead of &&.

Other possibilities are a user permission problem or an environment problem.  Your script is running as the user root and does not have access to your environmental variables

I already tried to pipe the commands, as I stated. But I think you're correct, this has to do with environment variable. Still can't seem to find any working solution to this... Any idea ?

Again, thank you for your time and your help so far.

Offline

#6 2017-05-13 17:27:38

toz
Member
Registered: 2011-10-28
Posts: 497

Re: [SOLVED] HDMI - Udev rule only partially working

Following up on ewaller's suggestion, try also exporting your user DBUS_SESSION_BUS_ADDRESS value.

Offline

#7 2017-05-13 17:53:25

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 19,769

Re: [SOLVED] HDMI - Udev rule only partially working

Denshou wrote:

I already tried to pipe the commands, as I stated.

For clarification, a pipe is a single | and implies that the std out of the first command is used as the std in of the second command
A &&  (the AND operator) runs the second command if, and only if, the first command returns zero.
A || (the OR operator) runs the second command if, and only if, the first command returns non-zero.

In retrospect, I guess that || is not the operator you want to use.
You probably want to use a semicolon betwixt the commands.   
Again, this is probably all a red herring, I venture that xrandr is returning 0.


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#8 2017-05-13 17:54:47

V1del
Forum Moderator
Registered: 2012-10-16
Posts: 21,627

Re: [SOLVED] HDMI - Udev rule only partially working

+1 on the exporting DBUS session, another possibility would be using the PULSE_RUNTIME_PATH to the location of your user as well as execute the command as your user with su, like e.g. done here: https://bbs.archlinux.org/viewtopic.php … 4#p1646244

Offline

#9 2017-05-13 20:50:51

Denshou
Member
Registered: 2017-01-17
Posts: 25

Re: [SOLVED] HDMI - Udev rule only partially working

ewaller wrote:
Denshou wrote:

I already tried to pipe the commands, as I stated.

For clarification, a pipe is a single | and implies that the std out of the first command is used as the std in of the second command
A &&  (the AND operator) runs the second command if, and only if, the first command returns zero.
A || (the OR operator) runs the second command if, and only if, the first command returns non-zero.

In retrospect, I guess that || is not the operator you want to use.
You probably want to use a semicolon betwixt the commands.   
Again, this is probably all a red herring, I venture that xrandr is returning 0.

Thanks for this clarification. Although I already know that stuff, a reminder is always welcome. I misread your last statement and thought you suggested me to use a single "|" instead. My bad.
While I do know about "||" which is kind of a "or" statement, I never saw ";" inside an if statement before. In what is it different than "&&", may I ask ?

toz wrote:

Following up on ewaller's suggestion, try also exporting your user DBUS_SESSION_BUS_ADDRESS value.

I tried that, but unfortunately, it didn't work. Thanks anyway !

V1del wrote:

another possibility would be using the PULSE_RUNTIME_PATH to the location of your user as well as execute the command as your user with su, like e.g. done here: https://bbs.archlinux.org/viewtopic.php … 4#p1646244

Wow, that did it ! Thanks a lot ! Here is the working script in case this can help someone in the future :

#!/bin/bash

# udev rules are run as Root, who can't act on user display if he doesn't know where it is
export XAUTHORITY=/home/user/.Xauthority
export DISPLAY=:0

STATUS=$(xrandr | grep HDMI-1 | cut -d " " -f 2)
USER=$(ps axc -o command,user | grep pulseaudio | tr -s ' ' | cut -f2 -d ' ' | sort | uniq)

# check if concerned output is connected
if [[ $STATUS == connected ]]
then
	xrandr --output eDP-1 --auto --output HDMI-1 --auto --left-of eDP-1 && PULSE_RUNTIME_PATH=/run/user/$(id -u $USER)/pulse su $USER -c "paswitch alsa_output.pci-0000_00_03.0.hdmi-stereo-extra1"
else
	xrandr --output eDP-1 --auto --output HDMI-1 --off && PULSE_RUNTIME_PATH=/run/user/$(id -u $USER)/pulse su $USER -c "paswitch alsa_output.pci-0000_00_1b.0.analog-stereo"
fi

Again, thank you all guys for your help and your time. Problem solved !

Last edited by Denshou (2017-05-13 20:54:12)

Offline

#10 2017-05-13 21:10:42

ewaller
Administrator
From: Pasadena, CA
Registered: 2009-07-13
Posts: 19,769

Re: [SOLVED] HDMI - Udev rule only partially working

Denshou wrote:

I never saw ";" inside an if statement before. In what is it different than "&&", may I ask ?

ewaller@turing ~ 1009 %true || echo hello  
ewaller@turing ~ 1010 %false || echo hello  
hello
ewaller@turing ~ 1011 %true && echo hello
hello
ewaller@turing ~ 1012 %false && echo hello
ewaller@turing ~ [1]1013 %true ; echo hello 
hello
ewaller@turing ~ 1014 %false ; echo hello  
hello
ewaller@turing ~ 1015 %

The semicolon ends the first statement.  The second statement is run unconditionally.  The return value to the shell is the result of the last command.
The && (And operator) checks to see if both commands return with success.  && runs the first statement and, if successful, runs the second command and returns the status of the second command.  If the first statement is not successful, there is no point in running the second command because we already know they are not both successful, so the operator stops and just returns the value of the first statement.

Edit:
The || (Or operator) checks to see if at least one of commands return with success.  || runs the first statement and, if successful, returns the value of that statement and tops -- there is no point running the second command as we allready know that one of them was successful.  If the first statement is not successful, the second command is run and the return value of that second statement is returned to the shell.

Last edited by ewaller (2017-05-13 21:14:55)


Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way

Offline

#11 2017-05-13 21:26:12

Denshou
Member
Registered: 2017-01-17
Posts: 25

Re: [SOLVED] HDMI - Udev rule only partially working

ewaller wrote:
Denshou wrote:

I never saw ";" inside an if statement before. In what is it different than "&&", may I ask ?

ewaller@turing ~ 1009 %true || echo hello  
ewaller@turing ~ 1010 %false || echo hello  
hello
ewaller@turing ~ 1011 %true && echo hello
hello
ewaller@turing ~ 1012 %false && echo hello
ewaller@turing ~ [1]1013 %true ; echo hello 
hello
ewaller@turing ~ 1014 %false ; echo hello  
hello
ewaller@turing ~ 1015 %

The semicolon ends the first statement.  The second statement is run unconditionally.  The return value to the shell is the result of the last command.
The && (And operator) checks to see if both commands return with success.  && runs the first statement and, if successful, runs the second command and returns the status of the second command.  If the first statement is not successful, there is no point in running the second command because we already know they are not both successful, so the operator stops and just returns the value of the first statement.

Edit:
The || (Or operator) checks to see if at least one of commands return with success.  || runs the first statement and, if successful, returns the value of that statement and tops -- there is no point running the second command as we allready know that one of the was successful.  If the first statement is not successful, the second command is run and the return value of that second statement is returned to the shell.

Crystal clear ! Thank you for these valuable informations ! smile

However, with that in mind, in the case of my script, it seems better to stick with "&&" instead of the semicolon. I don't want the sound output to switch if my xrandr command failed.

Offline

Board footer

Powered by FluxBB