Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doesn't alter the brightness on Wayland. #25

Open
RokeJulianLockhart opened this issue Jan 17, 2023 · 7 comments
Open

Doesn't alter the brightness on Wayland. #25

RokeJulianLockhart opened this issue Jan 17, 2023 · 7 comments

Comments

@RokeJulianLockhart
Copy link

RokeJulianLockhart commented Jan 17, 2023

>>> import screen_brightness_control as sbc
>>> sbc.set_brightness(40)
>>> sbc.get_brightness()
[40]

As previously demonstrated, the code operates without error, yet the brightness of my screen is not modified despite the value consistently returning the integer of the brightness that I have previously instructed it to apply. This code operates on X.

@Crozzers
Copy link
Owner

Wasn't this one fixed by using the method='ddcutil' kwarg or is this a continuation of the hanging/freezing discussion?

Also which screen is this, the USB-C screen? I know I have a similar issue on one of my monitors where the library sets the brightness and the display also says the brightness has been set, but doesn't apply it until I power cycle the display

@RokeJulianLockhart
Copy link
Author

RokeJulianLockhart commented Jan 22, 2023

I've had to abandon ddcutil for now, because invoking it from this library rather reliably hangs my PC; it rarely works anyway; because configuring the i2c group works for my user account; and the default method works for the superuser now.

Therefore, I refer solely to the default method – when the function is invoked without arguments. It definitely works on X, but not Wayland.

Same monitor, although I've tested the code on some different Windows machines (with different monitors) and it works, because of course Windows works and Linux doesn't – it's always the way.

@Crozzers
Copy link
Owner

So if I'm understanding this correctly:

  • ddcutil (the program) works super/normal user on X and wayland
  • method='ddcutil' (this library) doesn't work at all/only occasionally
  • No method (this library) works on X but not wayland, super and non-super

...when the function is invoked without arguments. It definitely works on X, but not Wayland.

I guess this is XRandr doing its thing. Xrandr tends to work great on X because it doesn't actually change the brightness, just applies a filter to make the screen look dimmer. Unfortunately, XRandr doesn't work on wayland.
If you run the same debug code as before, you should see the "filtered_monitors" section of the debug info mostly contain monitors with the XRandr method.

I expect that this is a bug in how screen_brightness_control communicates with ddcutil, since I remain able to invoke ddcutil from any terminal without problem.

The only difference this library makes when calling ddcutil is retrying upon failure and adjusting a few performance parameters. Here are the parameters the library sets:

  • --sleep-multiplier=0.5 - halves the amount of time ddcutil spends waiting, at the expense of higher failure rates
  • --async - used when 3+ monitors detected

You could try adjusting the sleep multiplier. I've pushed an update to the issue25 branch that should allow you to do this:

import screen_brightness_control as sbc
sbc.linux.DDCUtil.sleep_multiplier = 1  # change the sleep multiplier back to default
sbc.linux.DDCUtil.cmd_max_tries = 3  # set max retries to 3, default is 10
sbc.linux.DDCUtil.enable_async = False  # disable setting the --async flag
sbc.set_brightness(40, method='ddcutil')
sbc.get_brightness(method='ddcutil')

You can see if this makes a difference.

Also, out of curiosity, the screen doesn't have any sort of auto brightness/dimming feature enabled?

@RokeJulianLockhart
Copy link
Author

RokeJulianLockhart commented Apr 4, 2023

@Crozzers,

Wayland

No method (this library) works on X but not wayland, super and non-super

sbc at least invokes from my (i2c group-member) user rokejulianlockhart. However, it doesn't work when invoked by root, which is the superuser of this device.

PS /home/rokejulianlockhart> groups $Env:USER
rokejulianlockhart : rokejulianlockhart users wheel vboxusers i2c
PS /root> groups $Env:USER
root : root i2c

This appears to be, due to the delay when invoking it as root (I expect caused by --sleep-multiplier=0.5) because it appears to default to ddcutil regardless of whether installed or not. Adding root to i2c doesn't change anything, nor does installing ddcutil.

And indeed, no matter whether it invokes or not, it doesn't actually change the brightness.

I've recently changed from Fedora to OpenSUSE, so something might have changed, but this seems consistent with what I've previously witnessed too.

I did manage a moment ago to get an error messsage though:

>>> sbc.get_brightness(method='ddcutil')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/rokejulianlockhart/.local/lib/python3.10/site-packages/screen_brightness_control/__init__.py", line 50, in get_brightness
    return __brightness(display=display, method=method, meta_method='get', verbose_error=verbose_error)
  File "/home/rokejulianlockhart/.local/lib/python3.10/site-packages/screen_brightness_control/__init__.py", line 769, in __brightness
    for monitor in filter_monitors(display=display, method=method):
  File "/home/rokejulianlockhart/.local/lib/python3.10/site-packages/screen_brightness_control/__init__.py", line 737, in filter_monitors
    raise NoValidDisplayError(msg)
screen_brightness_control.exceptions.NoValidDisplayError: no displays detected with method: 'ddcutil'
>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> sbc.get_brightness(method='ddcutil')
DEBUG:screen_brightness_control:brightness get request display None with method ddcutil
DEBUG:screen_brightness_control.helpers:cache get 'ddcutil_monitors_info' = [KeyError]
WARNING:screen_brightness_control.linux:error grabbing display info from <class 'screen_brightness_control.linux.DDCUtil'> - TypeError: CalledProcessError.__init__() missing 1 required positional argument: 'cmd'
DEBUG:screen_brightness_control.helpers:cache get 'ddcutil_monitors_info' = [KeyError]
WARNING:screen_brightness_control.linux:error grabbing display info from <class 'screen_brightness_control.linux.DDCUtil'> - TypeError: CalledProcessError.__init__() missing 1 required positional argument: 'cmd'
DEBUG:screen_brightness_control.helpers:cache get 'ddcutil_monitors_info' = [KeyError]
WARNING:screen_brightness_control.linux:error grabbing display info from <class 'screen_brightness_control.linux.DDCUtil'> - TypeError: CalledProcessError.__init__() missing 1 required positional argument: 'cmd'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/rokejulianlockhart/.local/lib/python3.10/site-packages/screen_brightness_control/__init__.py", line 50, in get_brightness
    return __brightness(display=display, method=method, meta_method='get', verbose_error=verbose_error)
  File "/home/rokejulianlockhart/.local/lib/python3.10/site-packages/screen_brightness_control/__init__.py", line 769, in __brightness
    for monitor in filter_monitors(display=display, method=method):
  File "/home/rokejulianlockhart/.local/lib/python3.10/site-packages/screen_brightness_control/__init__.py", line 737, in filter_monitors
    raise NoValidDisplayError(msg)
screen_brightness_control.exceptions.NoValidDisplayError: no displays detected with method: 'ddcutil'
>>>

X

>>> sbc.list_monitors()
['Q3279WG5B']

with the portable monitor attached

>>> sbc.list_monitors()
['Q3279WG5B', 'Pi-X3']

This appears to demonstrate that on X, the names of the devices are passed to sbc rather than the connection protocol used to connect them.


Also, out of curiosity, the screen doesn't have any sort of auto brightness/dimming feature enabled?

Not that I know of.
>>> sbc.list_monitors()
['DP-2']

337054710_1426023074812273_7759285255292483949_n
337048216_571532295073638_7543167350818508666_n


>>> sbc.list_monitors()
['DP-2', 'HDMI-A-1']

https://www.amazon.co.uk/gp/product/B0B4276QBW/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&th=1#:~:text=for%20brightness%20adjustment.%2C-,it%20doesn't%20include%20(even%20a%20cheap)%20brightness%20sensor,-%2C%20which%20means%20that


I've pushed an update to the issue25 branch that should allow you to do this

I dare say that I've little experience even pulling a branch from git. I currently use sbc from pip3 install screen_brightness_control. Since that seems like useful functionality, is there any chance you could push it to master?


Also, per https://crozzers.github.io/screen_brightness_control/extras/Installing%20On%20Linux.html, is there a way of discovering the potential methods? I'd like to try each independently.

@Crozzers
Copy link
Owner

Crozzers commented Apr 8, 2023

And indeed, no matter whether it invokes or not, it doesn't actually change the brightness.

Have you tried power cycling the display? I have occasionally found that to help

Since that seems like useful functionality, is there any chance you could push it to master?

I've pushed the remaining changes to main, since most of it was already there. If you have git installed you can follow the instructions on the readme for cloning the repo.

The only thing now on main that isn't part of the latest release is the enable_async flag.

is there a way of discovering the potential methods? I'd like to try each independently.

The get_methods function will return a dictionary of brightness methods and their names. You can pass one of the names in anywhere a method kwarg is accepted.

If you could go through each method and figure out which ones work on X, which ones work on Wayland and put it all in a table or something that would be helpful. The root/non root stuff I'm not as concerned about since that is probably a permissions issue.

@RokeJulianLockhart
Copy link
Author

RokeJulianLockhart commented Apr 10, 2023

@Crozzers, I've executed the example at the get_methods function via konsole below:

PS /home/rokejulianlockhart> Write-Output "$Env:USER"
rokejulianlockhart

X

PowerShell 7.4.0-preview.2
PS /home/rokejulianlockhart> script -c pwsh                                                                   Script started, output log file is 'typescript'.
PowerShell 7.4.0-preview.2
PS /home/rokejulianlockhart> python3
Python 3.10.10 (main, Mar 01 2023, 21:10:14) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import screen_brightness_control as sbc
>>> import screen_brightness_control as sbc
>>> 
>>> all_methods = sbc.get_methods()
>>> 
>>> for method_name, method_class in all_methods.items():
...     print('Method:', method_name)
...     print('Class:', method_class)
...     print('Associated monitors:', sbc.list_monitors(method=method_name))
... 
Method: sysfiles
Class: <class 'screen_brightness_control.linux.SysFiles'>
Associated monitors: []
Method: i2c
Class: <class 'screen_brightness_control.linux.I2C'>
Associated monitors: []
Method: xrandr
Class: <class 'screen_brightness_control.linux.XRandr'>
Associated monitors: ['Q3279WG5B']
Method: ddcutil
Class: <class 'screen_brightness_control.linux.DDCUtil'>
Associated monitors: []
Method: light
Class: <class 'screen_brightness_control.linux.Light'>
Associated monitors: []
>>> exit()
PS /home/rokejulianlockhart> tty            
/dev/pts/4

Wayland

PowerShell 7.4.0-preview.2
PS /home/rokejulianlockhart> python3
Python 3.10.10 (main, Mar 01 2023, 21:10:14) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import screen_brightness_control as sbc
>>> all_methods = sbc.get_methods()
>>> for method_name, method_class in all_methods.items():
...     print('Method:', method_name)
...     print('Class:', method_class)
...     print('Associated monitors:', sbc.list_monitors(method=method_name))
... 
Method: sysfiles
Class: <class 'screen_brightness_control.linux.SysFiles'>
Associated monitors: []
Method: i2c
Class: <class 'screen_brightness_control.linux.I2C'>
Associated monitors: []
Method: xrandr
Class: <class 'screen_brightness_control.linux.XRandr'>
Associated monitors: ['DP-2']
Method: ddcutil
Class: <class 'screen_brightness_control.linux.DDCUtil'>
Associated monitors: []
Method: light
Class: <class 'screen_brightness_control.linux.Light'>
Associated monitors: []
>>> exit()
PS /home/rokejulianlockhart> tty
/dev/pts/2

Aren't these results weird? I didn't expect XRandr to work on Wayland, much less it to be the only one that actually outputs anything.


I realize that you weren't particularly interested in the differences between the superuser and regular users, but I just wanted to include some results in here with the answer to your comment anyway:

root

PS /root> Write-Output "$Env:USER"
root

Wayland

PS /home/rokejulianlockhart> sudo -i                                                                          [sudo] password for root: 
RQN6C6:~ # python3
Python 3.10.10 (main, Mar 01 2023, 21:10:14) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import screen_brightness_control as sbc
>>> 
>>> all_methods = sbc.get_methods()
>>> 
>>> for method_name, method_class in all_methods.items():
...     print('Method:', method_name)
...     print('Class:', method_class)
...     print('Associated monitors:', sbc.list_monitors(method=method_name))
... 
Method: sysfiles
Class: <class 'screen_brightness_control.linux.SysFiles'>
Associated monitors: []
Method: i2c
Class: <class 'screen_brightness_control.linux.I2C'>
Associated monitors: []
Method: xrandr
Class: <class 'screen_brightness_control.linux.XRandr'>
Associated monitors: []
Method: ddcutil
Class: <class 'screen_brightness_control.linux.DDCUtil'>
Associated monitors: []
Method: light
Class: <class 'screen_brightness_control.linux.Light'>
Associated monitors: []
>>>

@Crozzers
Copy link
Owner

Crozzers commented Apr 15, 2023

Do you have ddcutil installed on your new OS with all the right permissions? Xrandr won't work correctly on wayland and so the only other ways of changing the brightness for your monitor will be DDCUtil or I2C.

I remember there were some issues with DDCUtil hanging the system but you could try experimenting with the flags I added to see if you can alleviate the issues. If you play around with different values in the flags within this code snippet:

import logging
logging.basicConfig(filename='test.log', level=logging.DEBUG, filemode='w')
import screen_brightness_control as sbc
sbc.linux.DDCUtil.sleep_multiplier = 1  # change the sleep multiplier back to default (0.5 means half the usual time)
sbc.linux.DDCUtil.cmd_max_tries = 3  # set max retries to 3, default is 10
sbc.linux.DDCUtil.enable_async = False  # disable setting the --async flag
sbc.set_brightness(40, method='ddcutil')
print(sbc.get_brightness(method='ddcutil'))
print('===================LOGS===================')
with open('test.log', 'r') as f:
    print(f.read())

And of course, if you could make sure to do this in some test script, not as part of another program, like the GUI app you were developing. This issue has gone so many ways with so much going on, I'd like to just make sure we're doing the same stuff.

My thinking for pushing ddcutil is that if ddcutil works but is hanging when called from this library, then all we need to do is fix the hanging. Root or non-root doesn't matter, that's a permissions issue that I cannot do much about. As long as there is a way to get it working then we can build from there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants