diff options
Diffstat (limited to '')
-rw-r--r-- | src/blueshift_vidmode.pyx | 74 | ||||
-rw-r--r-- | src/blueshift_vidmode_c.c | 151 | ||||
-rw-r--r-- | src/monitor.py | 35 |
3 files changed, 259 insertions, 1 deletions
diff --git a/src/blueshift_vidmode.pyx b/src/blueshift_vidmode.pyx new file mode 100644 index 0000000..7d29655 --- /dev/null +++ b/src/blueshift_vidmode.pyx @@ -0,0 +1,74 @@ +# -*- python -*- + +# Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +cimport cython +from libc.stdlib cimport malloc, free + + +cdef extern int blueshift_vidmode_open(int use_screen) +cdef extern int blueshift_vidmode_apply(unsigned long long int use_crtcs, + unsigned short int* r_curve, + unsigned short int* g_curve, + unsigned short int* b_curve) +cdef extern void blueshift_vidmode_close() + + +def vidmode_open(int use_screen): + ''' + Start stage of colour curve control + + @param use_screen The screen to use + @return Zero on success + ''' + return blueshift_vidmode_open(use_screen) + + +def vidmode_apply(unsigned long long use_crtcs, r_curve, g_curve, b_curve): + ''' + Apply stage of colour curve control + + @param use_crtcs Mask of CRTC:s to use + @param r_curve:list<unsigned short int> The red colour curve + @param g_curve:list<unsigned short int> The green colour curve + @param b_curve:list<unsigned short int> The blue colour curve + @return Zero on success + ''' + cdef unsigned short int* r + cdef unsigned short int* g + cdef unsigned short int* b + r = <unsigned short int*>malloc(256 * 2) + g = <unsigned short int*>malloc(256 * 2) + b = <unsigned short int*>malloc(256 * 2) + if (r is NULL) or (g is NULL) or (b is NULL): + raise MemoryError() + for i in range(256): + r[i] = r_curve[i] & 0xFFFF + g[i] = g_curve[i] & 0xFFFF + b[i] = b_curve[i] & 0xFFFF + rc = blueshift_vidmode_apply(use_crtcs, r, g, b) + free(r) + free(g) + free(b) + return rc + + +def vidmode_close(): + ''' + Resource freeing stage of colour curve control + ''' + blueshift_vidmode_close() + diff --git a/src/blueshift_vidmode_c.c b/src/blueshift_vidmode_c.c new file mode 100644 index 0000000..b160e7e --- /dev/null +++ b/src/blueshift_vidmode_c.c @@ -0,0 +1,151 @@ +/** + * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <stdlib.h> +#include <stdio.h> +#include <inttypes.h> + +#include <X11/Xlib.h> +#include <X11/extensions/xf86vmode.h> + + + +/** + * The X server display + */ +static Display* display; + +/** + * The X screen + */ +static int screen; + +/** + * Size of colour curves on the X-axis + */ +static int curve_size; + + + +/** + * Start stage of colour curve control + * + * @param use_screen The screen to use + * @return Zero on success + */ +int blueshift_vidmode_open(int use_screen) +{ + int _major, _minor; + uint16_t* r_gamma; + uint16_t* g_gamma; + uint16_t* b_gamma; + + + /* Get X display */ + + if ((display = XOpenDisplay(NULL)) == NULL) + { + fprintf(stderr, "Cannot open X display\n"); + return 1; + } + + + /* Check for VidMode extension */ + + if (XF86VidModeQueryVersion(display, &_major, &_minor) == 0) + { + fprintf(stderr, "VidMode version query failed\n"); + XCloseDisplay(display); + return 1; + } + + + /* Get curve X-axis size */ + + screen = use_screen; + if (XF86VidModeGetGammaRampSize(display, screen, &curve_size) == 0) + { + fprintf(stderr, "VidMode gamma size query failed\n"); + XCloseDisplay(display); + return 1; + } + + if (curve_size < 1) + { + fprintf(stderr, "VidMode gamma size query failed\n"); + XCloseDisplay(display); + return 1; + } + + + /* Acquire curve control */ + + r_gamma = malloc(3 * curve_size * sizeof(uint16_t)); + if (r_gamma == NULL) + { + fprintf(stderr, "Out of memory\n"); + return 1; + } + g_gamma = r_gamma + curve_size; + b_gamma = g_gamma + curve_size; + if (XF86VidModeGetGammaRamp(display, screen, curve_size, r_gamma, g_gamma, b_gamma) == 0) + { + fprintf(stderr, "VidMode gamma query failed\n"); + free(r_gamma); + XCloseDisplay(display); + return 1; + } + free(r_gamma); + + return 0; +} + + +/** + * Apply stage of colour curve control + * + * @param use_crtcs Mask of CRTC:s to use + * @param r_curve The red colour curve + * @param g_curve The green colour curve + * @param b_curve The blue colour curve + * @return Zero on success + */ +int blueshift_vidmode_apply(uint64_t use_crtcs, uint16_t* r_curve, uint16_t* g_curve, uint16_t* b_curve) +{ + (void) use_crtcs; + + /* Apply curves */ + + if (XF86VidModeSetGammaRamp(display, screen, curve_size, r_curve, g_curve, b_curve) == 0) + { + fprintf(stderr, "VidMode gamma control failed\n"); + return 1; + } + + return 0; +} + + +/** + * Resource freeing stage of colour curve control + */ +void blueshift_vidmode_close(void) +{ + /* Free remaining resources */ + + XCloseDisplay(display); +} + diff --git a/src/monitor.py b/src/monitor.py index 87a2290..ecc827b 100644 --- a/src/monitor.py +++ b/src/monitor.py @@ -24,6 +24,7 @@ LIBDIR = 'bin' sys.path.append(LIBDIR) randr_opened = None +vidmode_opened = None def translate_to_integers(): @@ -46,11 +47,15 @@ def close_c_bindings(): ''' Close all C bindings and let them free resources and close connections ''' - global randr_opened + global randr_opened, vidmode_opened if randr_opened is not None: from blueshift_randr import randr_close randr_opened = None randr_close() + if vidmode_opened is not None: + from blueshift_vidmode import vidmode_close + vidmode_opened = None + vidmode_close() def randr(*crtcs, screen = 0): @@ -81,6 +86,34 @@ def randr(*crtcs, screen = 0): pass # Happens on exit by TERM signal +def vidmode(*crtcs, screen = 0): + ''' + Applies colour curves using the X11 extension vidmode + + @param *crtcs The CRT controllers to use, all are used if none are specified + @param screen The screen that the monitors belong to + ''' + from blueshift_vidmode import vidmode_open, vidmode_apply, vidmode_close + global vidmode_opened + crtcs = sum([1 << i for i in list(crtcs)]) + if crtcs == 0: + crtcs = (1 << 64) - 1 + + (R_curve, G_curve, B_curve) = translate_to_integers() + if (vidmode_opened is None) or not (vidmode_opened == screen): + if vidmode_opened is not None: + vidmode_close() + if vidmode_open(screen) == 0: + vidmode_opened = screen + else: + sys.exit(1) + try: + if not vidmode_apply(crtcs, R_curve, G_curve, B_curve) == 0: + sys.exit(1) + except OverflowError: + pass # Happens on exit by TERM signal + + def print_curves(*crtcs, screen = 0): ''' Prints the curves to stdout |