aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DESIGN10
-rw-r--r--HACKING18
-rw-r--r--Makefile.am27
-rw-r--r--NEWS2
-rw-r--r--configure.ac48
-rw-r--r--contrib/redshift.spec.in17
-rw-r--r--data/systemd/redshift-gtk.service.in11
-rw-r--r--data/systemd/redshift.service.in11
-rw-r--r--po/POTFILES.in1
-rw-r--r--po/de.po2
-rw-r--r--po/fr.po2
-rw-r--r--po/pt_BR.po2
-rw-r--r--po/ru.po2
-rw-r--r--redshift.14
-rw-r--r--src/Makefile.am10
-rw-r--r--src/gamma-drm.c280
-rw-r--r--src/gamma-drm.h58
-rw-r--r--src/gamma-dummy.c2
-rw-r--r--src/redshift-gtk/statusicon.py3
-rw-r--r--src/redshift-gtk/utils.py14
-rw-r--r--src/redshift.c19
21 files changed, 515 insertions, 28 deletions
diff --git a/DESIGN b/DESIGN
index 0fdf6a0..1b88aba 100644
--- a/DESIGN
+++ b/DESIGN
@@ -58,11 +58,11 @@ I've been mostly consistent with the naming throughout the source code
(I hope).
First adjustment methods: There is "randr" which is the preferred
-because it has some features that are lacking in "vidmode" (IIRC it
-has to do with multiple monitors). Both are APIs in the X server that
-allow for manipulation of gamma ramps, which is what Redshift uses to
-change the screen color temperature. There's also "wingdi" which is
-for the Windows version.
+because it has support for multiple outputs per X screen whic is lacking
+in "vidmode". Both are APIs in the X server that allow for manipulation
+of gamma ramps, which is what Redshift uses to change the screen color
+temperature. There's also "wingdi" which is for the Windows version,
+and "drm" which allows manipulation of gamma ramps in a TTY in Linux.
Then there are location providers: "manual", "gnome-clock" and
"geoclue". Some time ago there was only one way to specify the
diff --git a/HACKING b/HACKING
index a6b0a93..127cd29 100644
--- a/HACKING
+++ b/HACKING
@@ -8,9 +8,17 @@ The bootstrap script will use autotools to set up the build environment
and create the `configure` script.
Use `./configure --help' for options. Use `--prefix' to make an install in
-your home directory. This is necessary to test python scripts. Example:
+your home directory. This is necessary to test python scripts. The systemd
+user unit directory should be set to avoid writing to the system location.
- $ ./configure --prefix=$HOME/redshift/root
+Systemd will look for the unit files in `~/.config/systemd/user` so this
+directory can be used as a target if the unit files will be used. Otherwise
+the location can be set to `no` to disable the systemd files.
+
+Example:
+
+ $ ./configure --prefix=$HOME/redshift/root \
+ --with-systemduserunitdir=$HOME/.config/systemd/user
Now, build the files:
@@ -21,16 +29,16 @@ prefix directory run:
$ make install
-You can now run the python scripts. Example:
+You can now run the python script. Example:
- $ PYTHONHOME=$HOME/redshift/root/lib/python2.7/site-packages \
- $HOME/redshift/root/bin/redshift-gtk
+ $ $HOME/redshift/root/bin/redshift-gtk
Depenencies
-----------
* autotools, gettext
+* libdrm (Optional, for DRM support)
* libxcb, libxcb-randr (Optional, for RandR support)
* libX11, libXxf86vm (Optional, for VidMode support)
* geoclue (Optional, for geoclue support)
diff --git a/Makefile.am b/Makefile.am
index f3109ed..675fda8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,6 +2,10 @@
SUBDIRS = src po
ACLOCAL_AMFLAGS = -I m4
+# Install systemd user unit files locally for distcheck
+DISTCHECK_CONFIGURE_FLAGS = \
+ --with-systemduserunitdir=$$dc_install_base/$(systemduserunitdir)
+
UPDATE_ICON_CACHE = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor || :
EXTRA_ROOTDOC_FILES = \
@@ -25,6 +29,10 @@ _UBUNTU_MONO_LIGHT_FILES = \
_DESKTOP_FILES = \
data/applications/redshift-gtk.desktop
+SYSTEMD_USER_UNIT_IN_FILES = \
+ data/systemd/redshift.service.in \
+ data/systemd/redshift-gtk.service.in
+
# Icons
if ENABLE_GUI
@@ -55,15 +63,32 @@ uninstall-hook:
$(UPDATE_ICON_CACHE);
endif
+
# man page
dist_man1_MANS = redshift.1
+
+# Systemd service files
+if ENABLE_SYSTEMD
+systemduserunit_DATA = $(SYSTEMD_USER_UNIT_IN_FILES:.service.in=.service)
+endif
+
+$(systemduserunit_DATA): $(SYSTEMD_USER_UNIT_IN_FILES) Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && \
+ sed -e "s|\@bindir\@|$(bindir)|g" $< > $@
+
+
+
EXTRA_DIST = \
$(EXTRA_ROOTDOC_FILES) \
$(_HICOLOR_FILES) \
$(_UBUNTU_MONO_DARK_FILES) \
$(_UBUNTU_MONO_LIGHT_FILES) \
- $(_DESKTOP_FILES)
+ $(_DESKTOP_FILES) \
+ $(SYSTEMD_USER_UNIT_IN_FILES)
+
+CLEANFILES = $(systemduserunit_DATA)
+
# Update PO translations
.PHONY: update-po
diff --git a/NEWS b/NEWS
index 121afe7..64dded0 100644
--- a/NEWS
+++ b/NEWS
@@ -88,7 +88,7 @@ v0.4 (2010-01-07)
* Restore gamma ramps on program exit.
v0.3 (2009-12-28)
-* Continously adjust color temperature. One shot mode can be selected
+* Continuously adjust color temperature. One shot mode can be selected
with a command line switch.
* Allow selection of X screen to apply adjustments to.
diff --git a/configure.ac b/configure.ac
index 550ed0f..8c6b079 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
-AC_INIT([redshift], [1.8], [https://bugs.launchpad.net/redshift])
+AC_INIT([redshift], [1.8], [https://github.com/jonls/redshift/issues])
AC_CONFIG_SRCDIR([src/redshift.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz])
@@ -16,6 +16,7 @@ AC_PROG_CC_C99
AM_GNU_GETTEXT_VERSION([0.17])
AM_GNU_GETTEXT([external])
+PKG_CHECK_MODULES([DRM], [libdrm], [have_drm=yes], [have_drm=no])
PKG_CHECK_MODULES([X11], [x11], [have_x11=yes], [have_x11=no])
PKG_CHECK_MODULES([XF86VM], [xxf86vm], [have_xf86vm=yes], [have_xf86vm=no])
PKG_CHECK_MODULES([XCB], [xcb], [have_xcb=yes], [have_xcb=no])
@@ -29,6 +30,30 @@ AC_CHECK_HEADER([windows.h], [have_windows_h=yes], [have_windows_h=no])
# Check for Python
AM_PATH_PYTHON([3.3], [have_python=yes], [have_python=no])
+# Check DRM method
+AC_MSG_CHECKING([whether to enable DRM method])
+AC_ARG_ENABLE([drm], [AC_HELP_STRING([--enable-drm],
+ [enable DRM method])],
+ [enable_drm=$enableval],[enable_drm=maybe])
+AS_IF([test "x$enable_drm" != xno], [
+ AS_IF([test $have_drm = yes], [
+ AC_DEFINE([ENABLE_DRM], 1,
+ [Define to 1 to enable DRM method])
+ AC_MSG_RESULT([yes])
+ enable_drm=yes
+ ], [
+ AC_MSG_RESULT([missing dependencies])
+ AS_IF([test "x$enable_drm" = xyes], [
+ AC_MSG_ERROR([missing dependencies for DRM method])
+ ])
+ enable_drm=no
+ ])
+], [
+ AC_MSG_RESULT([no])
+ enable_drm=no
+])
+AM_CONDITIONAL([ENABLE_DRM], [test "x$enable_drm" = xyes])
+
# Check RANDR method
AC_MSG_CHECKING([whether to enable RANDR method])
AC_ARG_ENABLE([randr], [AC_HELP_STRING([--enable-randr],
@@ -161,6 +186,25 @@ AS_IF([test "x$enable_ubuntu" != xno], [
])
AM_CONDITIONAL([ENABLE_UBUNTU], [test "x$enable_ubuntu" != xno])
+
+# Check for systemd
+PKG_PROG_PKG_CONFIG
+AC_MSG_CHECKING([Directory to install systemd user unit files])
+AC_ARG_WITH([systemduserunitdir],
+ [AS_HELP_STRING([--with-systemduserunitdir=<dir>],
+ [Directory for systemd user unit files])],
+ [], [with_systemduserunitdir=$($PKG_CONFIG --variable=systemduserunitdir systemd)])
+AS_IF([test -n "$with_systemduserunitdir" -a "x$with_systemduserunitdir" != xno], [
+ AC_SUBST([systemduserunitdir], [$with_systemduserunitdir])
+ AC_MSG_RESULT([$systemduserunitdir])
+ enable_systemd=yes
+], [
+ AC_MSG_RESULT([not enabled])
+ enable_systemd=no
+])
+AM_CONDITIONAL([ENABLE_SYSTEMD], [test "x$enable_systemd" != xno])
+
+
# Checks for header files.
AC_CHECK_HEADERS([locale.h stdint.h stdlib.h string.h unistd.h signal.h])
@@ -191,6 +235,7 @@ echo "
ldflags: ${LDFLAGS}
Adjustment methods:
+ DRM: ${enable_drm}
RANDR: ${enable_randr}
VidMode: ${enable_vidmode}
WinGDI: ${enable_wingdi}
@@ -200,4 +245,5 @@ echo "
GUI: ${enable_gui}
Ubuntu icons: ${enable_ubuntu}
+ systemd units: ${enable_systemd} ${systemduserunitdir}
"
diff --git a/contrib/redshift.spec.in b/contrib/redshift.spec.in
index 0f4b896..3557d3e 100644
--- a/contrib/redshift.spec.in
+++ b/contrib/redshift.spec.in
@@ -7,9 +7,11 @@ License: GPLv3+
URL: http://jonls.dk/redshift/
Source0: http://launchpad.net/redshift/trunk/%{version}/+download/%{name}-%{version}.tar.bz2
BuildRequires: gettext-devel
-BuildRequires: libXrandr-devel
+BuildRequires: libX11-devel
BuildRequires: libXxf86vm-devel
+BuildRequires: libxcb-devel
BuildRequires: geoclue-devel
+BuildRequires: systemd
%description
Redshift adjusts the color temperature of your screen according to your
@@ -27,10 +29,10 @@ This package provides the base program.
%package -n %{name}-gtk
Summary: GTK integration for Redshift
Group: Applications/System
-BuildRequires: python2
+BuildRequires: python3-devel >= 3.3
BuildRequires: desktop-file-utils
-Requires: pygobject3-base
-Requires: pyxdg
+Requires: python3-gobject
+Requires: python3-pyxdg
Requires: %{name} = %{version}-%{release}
Obsoletes: gtk-redshift < %{version}-%{release}
@@ -42,7 +44,7 @@ temperature adjustment program.
%setup -q
%build
-%configure --enable-gui --enable-geoclue --enable-randr --enable-vidmode
+%configure --enable-gui --enable-geoclue --enable-randr --enable-vidmode --with-systemduserunitdir=%{_userunitdir}
make %{?_smp_mflags} V=1
%install
@@ -68,11 +70,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%doc COPYING NEWS README README-colorramp
%{_bindir}/redshift
%{_mandir}/man1/*
+%{_userunitdir}/*
%files -n %{name}-gtk
%defattr(-,root,root,-)
%{_bindir}/redshift-gtk
-%{python_sitelib}/*
+%{python3_sitelib}/redshift_gtk/
%{_datadir}/icons/hicolor/scalable/apps/redshift*.svg
%{_datadir}/applications/redshift-gtk.desktop
@@ -99,7 +102,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Change default geoclue provider from Ubuntu GeoIP to Hostip
- Remove manual Ubuntu icons uninstall
-* Sun Feb 28 2011 Milos Komarcevic <kmilos@gmail.com> - 1.6-3
+* Mon Feb 28 2011 Milos Komarcevic <kmilos@gmail.com> - 1.6-3
- Fix for clock applet detection (#661145)
- Require pyxdg explicitly (#675804)
diff --git a/data/systemd/redshift-gtk.service.in b/data/systemd/redshift-gtk.service.in
new file mode 100644
index 0000000..4675ccf
--- /dev/null
+++ b/data/systemd/redshift-gtk.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=Redshift display colour temperature adjustment (GUI)
+Documentation=http://jonls.dk/redshift/
+After=display-manager.service
+
+[Service]
+ExecStart=@bindir@/redshift-gtk
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/data/systemd/redshift.service.in b/data/systemd/redshift.service.in
new file mode 100644
index 0000000..bc51514
--- /dev/null
+++ b/data/systemd/redshift.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=Redshift display colour temperature adjustment
+Documentation=http://jonls.dk/redshift/
+After=display-manager.service
+
+[Service]
+ExecStart=@bindir@/redshift
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 65a04b1..814d7ca 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,6 +4,7 @@ src/redshift.c
src/config-ini.c
+src/gamma-drm.c
src/gamma-randr.c
src/gamma-vidmode.c
src/gamma-w32gdi.c
diff --git a/po/de.po b/po/de.po
index 93f0589..7f0cc02 100644
--- a/po/de.po
+++ b/po/de.po
@@ -630,7 +630,7 @@ msgstr "Standort: %f, %f\n"
#~ " \t\t(Type `list' to see available providers)\n"
#~ " -m METHOD\tMethod to use to set color temperature\n"
#~ " \t\t(Type `list' to see available methods)\n"
-#~ " -o\t\tOne shot mode (do not continously adjust color temperature)\n"
+#~ " -o\t\tOne shot mode (do not continuously adjust color temperature)\n"
#~ " -x\t\tReset mode (remove adjustment from screen)\n"
#~ " -r\t\tDisable temperature transitions\n"
#~ " -t DAY:NIGHT\tColor temperature to set at daytime/night\n"
diff --git a/po/fr.po b/po/fr.po
index ee0b5e2..24a517f 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -641,7 +641,7 @@ msgstr "Localisation: %f, %f\n"
#~ " \t\t(Type `list' to see available providers)\n"
#~ " -m METHOD\tMethod to use to set color temperature\n"
#~ " \t\t(Type `list' to see available methods)\n"
-#~ " -o\t\tOne shot mode (do not continously adjust color temperature)\n"
+#~ " -o\t\tOne shot mode (do not continuously adjust color temperature)\n"
#~ " -x\t\tReset mode (remove adjustment from screen)\n"
#~ " -r\t\tDisable temperature transitions\n"
#~ " -t DAY:NIGHT\tColor temperature to set at daytime/night\n"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 60fbd9d..c42d2e3 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -637,7 +637,7 @@ msgstr "Localização: %fº, %fº\n"
#~ " \t\t(Type `list' to see available providers)\n"
#~ " -m METHOD\tMethod to use to set color temperature\n"
#~ " \t\t(Type `list' to see available methods)\n"
-#~ " -o\t\tOne shot mode (do not continously adjust color temperature)\n"
+#~ " -o\t\tOne shot mode (do not continuously adjust color temperature)\n"
#~ " -x\t\tReset mode (remove adjustment from screen)\n"
#~ " -r\t\tDisable temperature transitions\n"
#~ " -t DAY:NIGHT\tColor temperature to set at daytime/night\n"
diff --git a/po/ru.po b/po/ru.po
index b268910..2c18ee6 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -641,7 +641,7 @@ msgstr "Местоположение: %f°, %f°\n"
#~ " -g R:G:B\tAdditional gamma correction to apply\n"
#~ " -l LAT:LON\tYour current location\n"
#~ " -m METHOD\tMethod to use to set color temperature (randr or vidmode)\n"
-#~ " -o\t\tOne shot mode (do not continously adjust color temperature)\n"
+#~ " -o\t\tOne shot mode (do not continuously adjust color temperature)\n"
#~ " -r\t\tDisable initial temperature transition\n"
#~ " -s SCREEN\tX screen to apply adjustments to\n"
#~ " -t DAY:NIGHT\tColor temperature to set at daytime/night\n"
diff --git a/redshift.1 b/redshift.1
index f650d8d..fbf7bdf 100644
--- a/redshift.1
+++ b/redshift.1
@@ -55,7 +55,7 @@ Method to use to set color temperature
(Type `list' to see available methods)
.TP
\fB\-o\fR
-One shot mode (do not continously adjust color temperature)
+One shot mode (do not continuously adjust color temperature)
.TP
\fB\-O\fR TEMP
One shot manual mode (set color temperature)
@@ -129,7 +129,7 @@ command line:
temp\-day=5700
temp\-night=3600
gamma=0.8
-adjustment\-method=vidmode
+adjustment\-method=randr
location\-provider=manual
[\fBmanual\fR]
diff --git a/src/Makefile.am b/src/Makefile.am
index 15caf2c..e83073b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS = redshift-gtk
# I18n
localedir = $(datadir)/locale
-INCLUDES = -DLOCALEDIR=\"$(localedir)\"
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
# redshift Program
bin_PROGRAMS = redshift
@@ -18,6 +18,7 @@ redshift_SOURCES = \
gamma-dummy.c gamma-dummy.h
EXTRA_redshift_SOURCES = \
+ gamma-drm.c gamma-drm.h \
gamma-randr.c gamma-randr.h \
gamma-vidmode.c gamma-vidmode.h \
gamma-w32gdi.c gamma-w32gdi.h \
@@ -27,6 +28,13 @@ AM_CFLAGS =
redshift_LDADD = @LIBINTL@
EXTRA_DIST =
+if ENABLE_DRM
+redshift_SOURCES += gamma-drm.c gamma-drm.h
+AM_CFLAGS += $(DRM_CFLAGS)
+redshift_LDADD += \
+ $(DRM_LIBS) $(DRM_CFLAGS)
+endif
+
if ENABLE_RANDR
redshift_SOURCES += gamma-randr.c gamma-randr.h
AM_CFLAGS += $(XCB_CFLAGS) $(XCB_RANDR_CFLAGS)
diff --git a/src/gamma-drm.c b/src/gamma-drm.c
new file mode 100644
index 0000000..e784b47
--- /dev/null
+++ b/src/gamma-drm.c
@@ -0,0 +1,280 @@
+/* gamma-drm.c -- DRM gamma adjustment source
+ This file is part of Redshift.
+
+ Redshift is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Redshift is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Redshift. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright (c) 2014 Mattias Andrée <maandree@member.fsf.org>
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <alloca.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
+
+#ifndef O_CLOEXEC
+ #define O_CLOEXEC 02000000
+#endif
+
+#include "gamma-drm.h"
+#include "colorramp.h"
+
+
+int
+drm_init(drm_state_t *state)
+{
+ /* Initialize state. */
+ state->card_num = 0;
+ state->crtc_num = -1;
+ state->fd = -1;
+ state->res = NULL;
+ state->crtcs = NULL;
+
+ return 0;
+}
+
+int
+drm_start(drm_state_t *state)
+{
+ /* Acquire access to a graphics card. */
+ long maxlen = strlen(DRM_DIR_NAME) + strlen(DRM_DEV_NAME) + 10;
+ char *pathname = alloca(maxlen * sizeof(char));
+
+ sprintf(pathname, DRM_DEV_NAME, DRM_DIR_NAME, state->card_num);
+
+ state->fd = open(pathname, O_RDWR | O_CLOEXEC);
+ if (state->fd < 0) {
+ /* TODO check if access permissions, normally root or
+ membership of the video group is required. */
+ perror("open");
+ return -1;
+ }
+
+ /* Acquire mode resources. */
+ state->res = drmModeGetResources(state->fd);
+ if (state->res == NULL) {
+ fprintf(stderr, _("Failed to get DRM mode resources\n"));
+ close(state->fd);
+ state->fd = -1;
+ return -1;
+ }
+
+ /* Create entries for selected CRTCs. */
+ int crtc_count = state->res->count_crtcs;
+ if (state->crtc_num >= 0) {
+ if (state->crtc_num >= crtc_count) {
+ fprintf(stderr, _("CRTC %d does not exist. "),
+ state->crtc_num);
+ if (crtc_count > 1) {
+ fprintf(stderr, _("Valid CRTCs are [0-%d].\n"),
+ crtc_count-1);
+ } else {
+ fprintf(stderr, _("Only CRTC 0 exists.\n"));
+ }
+ close(state->fd);
+ state->fd = -1;
+ drmModeFreeResources(state->res);
+ state->res = NULL;
+ return -1;
+ }
+
+ state->crtcs = malloc(2 * sizeof(drm_crtc_state_t));
+ state->crtcs[1].crtc_num = -1;
+
+ state->crtcs->crtc_num = state->crtc_num;
+ state->crtcs->crtc_id = -1;
+ state->crtcs->gamma_size = -1;
+ state->crtcs->r_gamma = NULL;
+ state->crtcs->g_gamma = NULL;
+ state->crtcs->b_gamma = NULL;
+ } else {
+ int crtc_num;
+ state->crtcs = malloc((crtc_count + 1) * sizeof(drm_crtc_state_t));
+ state->crtcs[crtc_count].crtc_num = -1;
+ for (crtc_num = 0; crtc_num < crtc_count; crtc_num++) {
+ state->crtcs[crtc_num].crtc_num = crtc_num;
+ state->crtcs[crtc_num].crtc_id = -1;
+ state->crtcs[crtc_num].gamma_size = -1;
+ state->crtcs[crtc_num].r_gamma = NULL;
+ state->crtcs[crtc_num].g_gamma = NULL;
+ state->crtcs[crtc_num].b_gamma = NULL;
+ }
+ }
+
+ /* Load CRTC information and gamma ramps. */
+ drm_crtc_state_t *crtcs = state->crtcs;
+ for (; crtcs->crtc_num >= 0; crtcs++) {
+ crtcs->crtc_id = state->res->crtcs[crtcs->crtc_num];
+ drmModeCrtc* crtc_info = drmModeGetCrtc(state->fd, crtcs->crtc_id);
+ if (crtc_info == NULL) {
+ fprintf(stderr, _("CRTC %i lost, skipping\n"), crtcs->crtc_num);
+ continue;
+ }
+ crtcs->gamma_size = crtc_info->gamma_size;
+ drmModeFreeCrtc(crtc_info);
+ if (crtcs->gamma_size <= 1) {
+ fprintf(stderr, _("Could not get gamma ramp size for CRTC %i\n"
+ "on graphics card %i, ignoring device.\n"),
+ crtcs->crtc_num, state->card_num);
+ continue;
+ }
+ /* Valgrind complains about us reading uninitialize memory if we just use malloc. */
+ crtcs->r_gamma = calloc(3 * crtcs->gamma_size, sizeof(uint16_t));
+ crtcs->g_gamma = crtcs->r_gamma + crtcs->gamma_size;
+ crtcs->b_gamma = crtcs->g_gamma + crtcs->gamma_size;
+ if (crtcs->r_gamma != NULL) {
+ int r = drmModeCrtcGetGamma(state->fd, crtcs->crtc_id, crtcs->gamma_size,
+ crtcs->r_gamma, crtcs->g_gamma, crtcs->b_gamma);
+ if (r < 0) {
+ fprintf(stderr, _("DRM could not read gamma ramps on CRTC %i on\n"
+ "graphics card %i, ignoring device.\n"),
+ crtcs->crtc_num, state->card_num);
+ free(crtcs->r_gamma);
+ crtcs->r_gamma = NULL;
+ }
+ } else {
+ perror("malloc");
+ drmModeFreeResources(state->res);
+ state->res = NULL;
+ close(state->fd);
+ state->fd = -1;
+ while (crtcs-- != state->crtcs)
+ free(crtcs->r_gamma);
+ free(state->crtcs);
+ state->crtcs = NULL;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+void
+drm_restore(drm_state_t *state)
+{
+ drm_crtc_state_t *crtcs = state->crtcs;
+ while (crtcs->crtc_num >= 0) {
+ if (crtcs->r_gamma != NULL) {
+ drmModeCrtcSetGamma(state->fd, crtcs->crtc_id, crtcs->gamma_size,
+ crtcs->r_gamma, crtcs->g_gamma, crtcs->b_gamma);
+ }
+ crtcs++;
+ }
+}
+
+void
+drm_free(drm_state_t *state)
+{
+ if (state->crtcs != NULL) {
+ drm_crtc_state_t *crtcs = state->crtcs;
+ while (crtcs->crtc_num >= 0) {
+ if (crtcs->r_gamma != NULL)
+ free(crtcs->r_gamma);
+ crtcs->crtc_num = -1;
+ crtcs++;
+ }
+ free(state->crtcs);
+ state->crtcs = NULL;
+ }
+ if (state->res != NULL) {
+ drmModeFreeResources(state->res);
+ state->res = NULL;
+ }
+ if (state->fd >= 0) {
+ close(state->fd);
+ state->fd = -1;
+ }
+}
+
+void
+drm_print_help(FILE *f)
+{
+ fputs(_("Adjust gamma ramps with Direct Rendering Manager.\n"), f);
+ fputs("\n", f);
+
+ /* TRANSLATORS: DRM help output
+ left column must not be translated */
+ fputs(_(" card=N\tGraphics card to apply adjustments to\n"
+ " crtc=N\tCRTC to apply adjustments to\n"), f);
+ fputs("\n", f);
+}
+
+int
+drm_set_option(drm_state_t *state, const char *key, const char *value)
+{
+ if (strcasecmp(key, "card") == 0) {
+ state->card_num = atoi(value);
+ } else if (strcasecmp(key, "crtc") == 0) {
+ state->crtc_num = atoi(value);
+ if (state->crtc_num < 0) {
+ fprintf(stderr, _("CRTC must be a non-negative integer\n"));
+ return -1;
+ }
+ } else {
+ fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+drm_set_temperature(drm_state_t *state, int temp, float brightness, const float gamma[3])
+{
+ drm_crtc_state_t *crtcs = state->crtcs;
+ int last_gamma_size = 0;
+ uint16_t *r_gamma = NULL;
+ uint16_t *g_gamma = NULL;
+ uint16_t *b_gamma = NULL;
+
+ for (; crtcs->crtc_num >= 0; crtcs++) {
+ if (crtcs->gamma_size <= 1)
+ continue;
+ if (crtcs->gamma_size != last_gamma_size) {
+ if (last_gamma_size == 0) {
+ r_gamma = malloc(3 * crtcs->gamma_size * sizeof(uint16_t));
+ g_gamma = r_gamma + crtcs->gamma_size;
+ b_gamma = g_gamma + crtcs->gamma_size;
+ } else if (crtcs->gamma_size > last_gamma_size) {
+ r_gamma = realloc(r_gamma, 3 * crtcs->gamma_size * sizeof(uint16_t));
+ g_gamma = r_gamma + crtcs->gamma_size;
+ b_gamma = g_gamma + crtcs->gamma_size;
+ }
+ if (r_gamma == NULL) {
+ perror(last_gamma_size == 0 ? "malloc" : "realloc");
+ return -1;
+ }
+ last_gamma_size = crtcs->gamma_size;
+ }
+ colorramp_fill(r_gamma, g_gamma, b_gamma, crtcs->gamma_size,
+ temp, brightness, gamma);
+ drmModeCrtcSetGamma(state->fd, crtcs->crtc_id, crtcs->gamma_size,
+ r_gamma, g_gamma, b_gamma);
+ }
+
+ free(r_gamma);
+
+ return 0;
+}
diff --git a/src/gamma-drm.h b/src/gamma-drm.h
new file mode 100644
index 0000000..8ef0ba5
--- /dev/null
+++ b/src/gamma-drm.h
@@ -0,0 +1,58 @@
+/* gamma-drm.h -- DRM gamma adjustment header
+ This file is part of Redshift.
+
+ Redshift is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Redshift is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Redshift. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright (c) 2014 Mattias Andrée <maandree@member.fsf.org>
+*/
+
+#ifndef _REDSHIFT_GAMMA_DRM_H
+#define _REDSHIFT_GAMMA_DRM_H
+
+#include <stdint.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+
+typedef struct {
+ int crtc_num;
+ int crtc_id;
+ int gamma_size;
+ uint16_t* r_gamma;
+ uint16_t* g_gamma;
+ uint16_t* b_gamma;
+} drm_crtc_state_t;
+
+typedef struct {
+ int card_num;
+ int crtc_num;
+ int fd;
+ drmModeRes* res;
+ drm_crtc_state_t* crtcs;
+} drm_state_t;
+
+
+int drm_init(drm_state_t *state);
+int drm_start(drm_state_t *state);
+void drm_free(drm_state_t *state);
+
+void drm_print_help(FILE *f);
+int drm_set_option(drm_state_t *state, const char *key, const char *value);
+
+void drm_restore(drm_state_t *state);
+int drm_set_temperature(drm_state_t *state, int temp, float brightness, const float gamma[3]);
+
+
+#endif /* ! _REDSHIFT_GAMMA_DRM_H */
diff --git a/src/gamma-dummy.c b/src/gamma-dummy.c
index 536b044..0ebb12d 100644
--- a/src/gamma-dummy.c
+++ b/src/gamma-dummy.c
@@ -1,4 +1,4 @@
-/* gamma-randr.c -- No-op gamma adjustment
+/* gamma-dummy.c -- No-op gamma adjustment
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
diff --git a/src/redshift-gtk/statusicon.py b/src/redshift-gtk/statusicon.py
index 6174aec..6877eac 100644
--- a/src/redshift-gtk/statusicon.py
+++ b/src/redshift-gtk/statusicon.py
@@ -316,7 +316,10 @@ class RedshiftStatusIcon(object):
os.kill(self.process[0], signal.SIGINT)
os.waitpid(self.process[0], 0)
+
def run():
+ utils.setproctitle('redshift-gtk')
+
# Internationalisation
gettext.bindtextdomain('redshift', defs.LOCALEDIR)
gettext.textdomain('redshift')
diff --git a/src/redshift-gtk/utils.py b/src/redshift-gtk/utils.py
index 723d4d8..4d3b619 100644
--- a/src/redshift-gtk/utils.py
+++ b/src/redshift-gtk/utils.py
@@ -17,7 +17,9 @@
# Copyright (c) 2010 Francesco Marella <francesco.marella@gmail.com>
# Copyright (c) 2011 Jon Lund Steffensen <jonlst@gmail.com>
+import ctypes
import os
+import sys
from xdg import BaseDirectory as base
from xdg import DesktopEntry as desktop
@@ -62,3 +64,15 @@ def set_autostart(active):
for key, values in AUTOSTART_KEYS:
dfile.set(key, values[active])
dfile.write(filename=path)
+
+
+def setproctitle(title):
+ try:
+ libc = ctypes.cdll.LoadLibrary("libc.so.6")
+ except OSError:
+ return
+ buf = ctypes.create_string_buffer(title.encode(sys.getdefaultencoding()))
+ try:
+ libc.prctl(15, ctypes.byref(buf), 0, 0, 0)
+ except AttributeError:
+ return # Strange libc, just skip this
diff --git a/src/redshift.c b/src/redshift.c
index e4143fc..beecd35 100644
--- a/src/redshift.c
+++ b/src/redshift.c
@@ -53,6 +53,10 @@
#include "gamma-dummy.h"
+#ifdef ENABLE_DRM
+# include "gamma-drm.h"
+#endif
+
#ifdef ENABLE_RANDR
# include "gamma-randr.h"
#endif
@@ -75,6 +79,9 @@
/* Union of state data for gamma adjustment methods */
typedef union {
+#ifdef ENABLE_DRM
+ drm_state_t drm;
+#endif
#ifdef ENABLE_RANDR
randr_state_t randr;
#endif
@@ -89,6 +96,18 @@ typedef union {
/* Gamma adjustment method structs */
static const gamma_method_t gamma_methods[] = {
+#ifdef ENABLE_DRM
+ {
+ "drm", 0,
+ (gamma_method_init_func *)drm_init,
+ (gamma_method_start_func *)drm_start,
+ (gamma_method_free_func *)drm_free,
+ (gamma_method_print_help_func *)drm_print_help,
+ (gamma_method_set_option_func *)drm_set_option,
+ (gamma_method_restore_func *)drm_restore,
+ (gamma_method_set_temperature_func *)drm_set_temperature
+ },
+#endif
#ifdef ENABLE_RANDR
{
"randr", 1,