jonls / redshift

Redshift adjusts the color temperature of your screen according to your surroundings. This may help your eyes hurt less if you are working in front of the screen at night.
http://jonls.dk/redshift
GNU General Public License v3.0
5.9k stars 428 forks source link

Adjust backlight of external monitors #436

Open pkkm opened 7 years ago

pkkm commented 7 years ago

Redshift currently adjusts brightness by darkening the image sent to the screens, which is sometimes not enough. It would be nice to control monitor backlight (it would also be a "killer feature" for Redshift — none of the similar programs implement this).

This can be achieved using the DDC/CI protocol, which allows sending commands to external monitors over DVI and VGA cables. There's a Linux library and command-line utility for this called ddccontrol. Here's how to try it out (I'm on Debian, but the procedure should be similar on other distros):

pkkm@pkkm-box:~$ sudo apt-get install ddccontrol libi2c-dev
[snip]
pkkm@pkkm-box:~$ sudo modprobe i2c-dev
pkkm@pkkm-box:~$ sudo ddccontrol -p -d # Probe monitors and their controls.
[snip]
Detected monitors :
 - Device: dev:/dev/i2c-1
   DDC/CI supported: Yes
   Monitor Name: VESA standard monitor
   Input type: Digital
  (Automatically selected)
 - Device: dev:/dev/i2c-0
   DDC/CI supported: Yes
   Monitor Name: Samsung SyncMaster 930BF (VGA)
   Input type: Digital
[snip]
Controls (valid/current/max) [Description - Value name]:
[snip]
Control 0x10: +/25/100 C [Brightness]
[snip]
pkkm@pkkm-box:~$ sudo ddccontrol dev:/dev/i2c-1 -r 0x10 -w 25 # Set brightness to 25%.
[snip]
Writing 0x10, 0x19(25)...
Control 0x10: +/25/100 C [Brightness]
ypossem commented 7 years ago

I was going to come and say the same thing. However, when trying it on my monitor it comes up with a warning that "There is no support for your monitor in the database, but ddccontrol is using a basic generic profile. Many controls will not be supported, and some controls may not work as expected."

Having tried it out, it does work, but this will not be universal. I'm going to have to take a stab and suggest that this is going to have to be a manually enabled feature, but I'd sure love to see the code paths for it available.

As an aside, colour profiles (RGB) of my screens are also adjustable via DDC, which might also make a nice feature, though this might use a different ramp to the ones set via redshift/xrandr ?

ypossem commented 7 years ago

Having played some more with ddccontrol with my screens (I have three), despite them all being one model, one of them has a tendency to reset to 100% brightness without input. I do not know if this is model specific or an artifact of the graphics card. However, it does mean that if this method were to be used, something would have to watch carefully for screen wakeup or similar events and respond to unexpected changes, as behaviours may not be consistent. I think it also didn't respond to a command issued to it once too.

pkkm commented 7 years ago

I get this warning too, but it shouldn't ever be a problem because control 0x10 is defined to mean brightness by the MCCS standard since 1998 (according to the USB Monitor Control Class Specification, section 6.3). I don't know if color profiles can be controlled in a similarly universal way.

I agree that the feature shouldn't be enabled by default; what I have in mind is an additional option, e.g. redshift -d 25:18 for brightness 25 during the day and 18 during the night.

pkkm commented 7 years ago

By the way, I found two other interesting DDC/CI-related projects: ddcutil and ddcci-driver-linux (though only the former works on my machine).

GoodMirek commented 7 years ago

There was also attempt to add DDC/CI/MCCS support to kernel backlight api: https://patchwork.kernel.org/patch/9530565/

anarcat commented 6 years ago

also note there is a PR for sysfs-based backlight support which, combined with kernel work, could provide one unified interface for this, in #512.

rnhmjoj commented 6 years ago

I have been using a redshift hook to do this and I was wondering whether it could be implemented in the program itself. It works fine however you need to load the i2c-dev kernel module and change the permissions of /dev/i2c-* (otherwise ddcutil need to run as root).

cat ~/.config/redshift/hooks/brightness:

#!/bin/sh

# Set brightness for DDC/CI enabled monitors

# brightness values
night=30
transition=45
daytime=60

deref() {
  eval "echo \$$1"
}

fade_to() {
  current=$(ddcutil get 10 | cut -d, -f1 | cut -d= -f2)
  [ "$current" -gt "$1" ] && step=-1 || step=1
  for i in $(seq "$current" "$step" "$1"); do
    ddcutil set 10 $i
    sleep 1
  done
}

if [ "$1" = "period-changed" ]; then
  fade_to "$(deref "$3")"
fi

udev rule:

ACTION=="add", KERNEL=="i2c-[0-9]*", GROUP="wheel", MODE="666"
FedeDP commented 6 years ago

I feel kind of sorry for the self promotion but you may find Clight useful, as it can adjust backlight on external monitors using ddcutil C api. It uses webcam to correctly retrieve ambient brightness, and users can specify backlight-to-brightness curve points to match ambient brightness to a certain backlight level.

I arrived here looking for ddcci-driver references on google as i was researching whether i could drop ddcutil (that is a build time dependency even on laptops) in favour of ddcci backlight driver (that would be a runtime dependency instead), but i cannot get it to work for now.

GoodMirek commented 6 years ago

@FedeDP Federico, thanks for the note. I will try Clight, it sounds as a great idea to me.

mirh commented 5 years ago

Just for the records, ddcutil was added into KDE powerdevil And ddccontrol got a rootless daemon (that avoids the "grant unfettered access to all your i2c devices" problem)

GoodMirek commented 5 years ago

@mirh I appreciate all the great progress and all the work behind.

Please could you let me know whether in plasma 5.16.4 and powerdevil 5.16.4 (I am currently running Fedora 31 beta with these versions) external monitor backlight should be adjustable with KDE native Battery and Brightness widget in system tray?

Currently, it does not work for me. I have an external monitor connected to docked laptop.