xgamma.c revision 33dddc75
172b4363aSmrg/*
272b4363aSmrg * Copyright 1999  The XFree86 Project
372b4363aSmrg *
472b4363aSmrg * Permission is hereby granted, free of charge, to any person obtaining a
572b4363aSmrg * copy of this software and associated documentation files (the "Software"),
672b4363aSmrg * to deal in the Software without restriction, including without limitation
772b4363aSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
872b4363aSmrg * and/or sell copies of the Software, and to permit persons to whom the
972b4363aSmrg * Software is furnished to do so, subject to the following conditions:
1072b4363aSmrg *
1172b4363aSmrg * The above copyright notice and this permission notice shall be included in
1272b4363aSmrg * all copies or substantial portions of the Software.
1372b4363aSmrg *
1472b4363aSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1572b4363aSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1672b4363aSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1772b4363aSmrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1872b4363aSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1972b4363aSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2072b4363aSmrg * SOFTWARE.
2172b4363aSmrg *
2272b4363aSmrg * Written by David Bateman
2372b4363aSmrg */
2472b4363aSmrg
2533dddc75Smrg#ifdef HAVE_CONFIG_H
2633dddc75Smrg# include "config.h"
2733dddc75Smrg#endif
2833dddc75Smrg
2972b4363aSmrg#include <stdio.h>
3072b4363aSmrg#include <errno.h>
3172b4363aSmrg#include <X11/Xos.h>
3272b4363aSmrg#include <X11/Xlib.h>
3372b4363aSmrg#include <X11/Xutil.h>
3472b4363aSmrg#include <X11/extensions/xf86vmode.h>
3572b4363aSmrg#include <ctype.h>
3672b4363aSmrg#include <stdlib.h>
3772b4363aSmrg
38dd77ae96Smrgstatic char *ProgramName;
39dd77ae96Smrgstatic int MajorVersion, MinorVersion;
40dd77ae96Smrgstatic int EventBase, ErrorBase;
4172b4363aSmrg
4272b4363aSmrg/* Minimum extension version required */
4372b4363aSmrg#define MINMAJOR 2
4472b4363aSmrg#define MINMINOR 0
4572b4363aSmrg
4672b4363aSmrg/* Maximum and Minimum gamma values */
4772b4363aSmrg#define GAMMA_MIN 0.1
4872b4363aSmrg#define GAMMA_MAX 10.0
4972b4363aSmrg
5033dddc75Smrgstatic void _X_NORETURN
5133dddc75SmrgSyntax(const char *errmsg)
5272b4363aSmrg{
5333dddc75Smrg    if (errmsg != NULL)
5433dddc75Smrg        fprintf (stderr, "%s: %s\n\n", ProgramName, errmsg);
5533dddc75Smrg
5633dddc75Smrg    fprintf (stderr, "usage:  %s [-options]\n\n%s", ProgramName,
5733dddc75Smrg             "where the available options are:\n"
5833dddc75Smrg             "    -display host:dpy       or -d\n"
5933dddc75Smrg             "    -quiet                  or -q\n"
6033dddc75Smrg             "    -screen                 or -s\n"
6133dddc75Smrg             "    -version                or -v\n"
6233dddc75Smrg             "    -gamma f.f              Gamma Value\n"
6333dddc75Smrg             "    -rgamma f.f             Red Gamma Value\n"
6433dddc75Smrg             "    -ggamma f.f             Green Gamma Value\n"
6533dddc75Smrg             "    -bgamma f.f             Blue Gamma Value\n\n"
6633dddc75Smrg             "If no gamma is specified, returns the current setting\n");
6772b4363aSmrg    exit (1);
6872b4363aSmrg}
6972b4363aSmrg
7072b4363aSmrg
7172b4363aSmrg/*
7272b4363aSmrg * The following is a hack until XrmParseCommand is ready.  It determines
7372b4363aSmrg * whether or not the given string is an abbreviation of the arg.
7472b4363aSmrg */
7572b4363aSmrg
7672b4363aSmrgstatic Bool
7733dddc75Smrgisabbreviation(const char *arg, const char *s, size_t minslen)
7872b4363aSmrg{
7933dddc75Smrg    size_t arglen;
8033dddc75Smrg    size_t slen;
8172b4363aSmrg
8272b4363aSmrg    /* exact match */
8372b4363aSmrg    if (strcmp (arg, s) == 0) return (True);
8472b4363aSmrg
8572b4363aSmrg    arglen = strlen (arg);
8672b4363aSmrg    slen = strlen (s);
8772b4363aSmrg
8872b4363aSmrg    /* too long or too short */
8972b4363aSmrg    if (slen >= arglen || slen < minslen) return (False);
9072b4363aSmrg
9172b4363aSmrg    /* abbreviation */
9272b4363aSmrg    if (strncmp (arg, s, slen) == 0) return (True);
9372b4363aSmrg
9472b4363aSmrg    /* bad */
9572b4363aSmrg    return (False);
9672b4363aSmrg}
9772b4363aSmrg
9872b4363aSmrgint
9972b4363aSmrgmain(int argc, char *argv[])
10072b4363aSmrg{
10172b4363aSmrg    int i, ret;
10272b4363aSmrg    char *displayname = NULL;
10372b4363aSmrg    Display *dpy;
10472b4363aSmrg    float gam = -1., rgam = -1., ggam = -1., bgam = -1.;
10572b4363aSmrg    XF86VidModeGamma gamma;
10672b4363aSmrg    Bool quiet = False;
10772b4363aSmrg    int screen = -1;
10872b4363aSmrg
10972b4363aSmrg    ProgramName = argv[0];
11072b4363aSmrg    for (i = 1; i < argc; i++) {
11172b4363aSmrg	char *arg = argv[i];
11272b4363aSmrg
11372b4363aSmrg	if (arg[0] == '-') {
11472b4363aSmrg	    if (isabbreviation ("-display", arg, 1)) {
11533dddc75Smrg		if (++i >= argc) Syntax ("-display requires an argument");
11672b4363aSmrg		displayname = argv[i];
11772b4363aSmrg		continue;
11872b4363aSmrg	    } else if (isabbreviation ("-quiet", arg, 1)) {
11972b4363aSmrg		quiet = True;
12072b4363aSmrg		continue;
12133dddc75Smrg	    } else if (isabbreviation ("-version", arg, 1)) {
12233dddc75Smrg		puts(PACKAGE_STRING);
12333dddc75Smrg		exit(0);
12472b4363aSmrg	    } else if (isabbreviation ("-screen", arg, 1)) {
12533dddc75Smrg		if (++i >= argc) Syntax ("-screen requires an argument");
12672b4363aSmrg		screen = atoi(argv[i]);
12772b4363aSmrg		continue;
12872b4363aSmrg	    } else if (isabbreviation ("-gamma", arg, 2)) {
12933dddc75Smrg		if (++i >= argc) Syntax ("-gamma requires an argument");
13072b4363aSmrg		if ((rgam >= 0.) || (ggam >= 0.) || (bgam >= 0.))
13133dddc75Smrg		    Syntax ("-gamma cannot be used with -rgamma, -ggamma, or -bgamma");
13272b4363aSmrg		gam = (float)atof(argv[i]);
13372b4363aSmrg		if ((gam < GAMMA_MIN) || (gam > GAMMA_MAX)) {
13472b4363aSmrg		    fprintf(stderr,
13572b4363aSmrg			    "Gamma values must be between %6.3f and %6.3f\n",
13672b4363aSmrg			    GAMMA_MIN, GAMMA_MAX);
13772b4363aSmrg		    exit(1);
13872b4363aSmrg		}
13972b4363aSmrg		continue;
14072b4363aSmrg	    } else if (isabbreviation ("-rgamma", arg, 2)) {
14133dddc75Smrg		if (++i >= argc) Syntax ("-rgamma requires an argument");
14233dddc75Smrg		if (gam >= 0.) Syntax ("cannot set both -gamma and -rgamma");
14372b4363aSmrg		rgam = (float)atof(argv[i]);
14472b4363aSmrg		if ((rgam < GAMMA_MIN) || (rgam > GAMMA_MAX)) {
14572b4363aSmrg		    fprintf(stderr,
14672b4363aSmrg			    "Gamma values must be between %6.3f and %6.3f\n",
14772b4363aSmrg			    GAMMA_MIN, GAMMA_MAX);
14872b4363aSmrg		    exit(1);
14972b4363aSmrg		}
15072b4363aSmrg		continue;
15172b4363aSmrg	    } else if (isabbreviation ("-ggamma", arg, 2)) {
15233dddc75Smrg		if (++i >= argc) Syntax ("-ggamma requires an argument");
15333dddc75Smrg		if (gam >= 0.) Syntax ("cannot set both -gamma and -ggamma");
15472b4363aSmrg		ggam = (float)atof(argv[i]);
15572b4363aSmrg		if ((ggam < GAMMA_MIN) || (ggam > GAMMA_MAX)) {
15672b4363aSmrg		    fprintf(stderr,
15772b4363aSmrg			    "Gamma values must be between %6.3f and %6.3f\n",
15872b4363aSmrg			    GAMMA_MIN, GAMMA_MAX);
15972b4363aSmrg		    exit(1);
16072b4363aSmrg		}
16172b4363aSmrg		continue;
16272b4363aSmrg	    } else if (isabbreviation ("-bgamma", arg, 2)) {
16333dddc75Smrg		if (++i >= argc) Syntax ("-bgamma requires an argument");
16433dddc75Smrg		if (gam >= 0.) Syntax ("cannot set both -gamma and -bgamma");
16572b4363aSmrg		bgam = (float)atof(argv[i]);
16672b4363aSmrg		if ((bgam < GAMMA_MIN) || (bgam > GAMMA_MAX)) {
16772b4363aSmrg		    fprintf(stderr,
16872b4363aSmrg			    "Gamma values must be between %6.3f and %6.3f\n",
16972b4363aSmrg			    GAMMA_MIN, GAMMA_MAX);
17072b4363aSmrg		    exit(1);
17172b4363aSmrg		}
17272b4363aSmrg		continue;
17333dddc75Smrg	    } else {
17433dddc75Smrg		if (!isabbreviation ("-help", arg, 1))
17533dddc75Smrg		    fprintf (stderr, "%s: unrecognized argument %s\n\n",
17633dddc75Smrg			     ProgramName, arg);
17733dddc75Smrg		Syntax (NULL);
17833dddc75Smrg	    }
17933dddc75Smrg	} else {
18033dddc75Smrg	    fprintf (stderr, "%s: unrecognized argument %s\n\n",
18133dddc75Smrg		     ProgramName, arg);
18233dddc75Smrg	    Syntax (NULL);
18333dddc75Smrg	}
18472b4363aSmrg    }
18572b4363aSmrg
18672b4363aSmrg    if ((dpy = XOpenDisplay(displayname)) == NULL) {
18772b4363aSmrg	fprintf (stderr, "%s:  unable to open display '%s'\n",
18872b4363aSmrg		 ProgramName, XDisplayName (displayname));
18972b4363aSmrg	exit(1);
19072b4363aSmrg    } else if (screen == -1)
19172b4363aSmrg	screen = DefaultScreen(dpy);
19272b4363aSmrg
19372b4363aSmrg    if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
19472b4363aSmrg	fprintf(stderr, "Unable to query video extension version\n");
19572b4363aSmrg	exit(2);
19672b4363aSmrg    }
19772b4363aSmrg
19872b4363aSmrg    if (!XF86VidModeQueryExtension(dpy, &EventBase, &ErrorBase)) {
19972b4363aSmrg	fprintf(stderr, "Unable to query video extension information\n");
20072b4363aSmrg	exit(2);
20172b4363aSmrg    }
20272b4363aSmrg
20372b4363aSmrg    /* Fail if the extension version in the server is too old */
20472b4363aSmrg    if (MajorVersion < MINMAJOR ||
20572b4363aSmrg	(MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
20672b4363aSmrg	fprintf(stderr,
20772b4363aSmrg		"Xserver is running an old XFree86-VidModeExtension version"
20872b4363aSmrg		" (%d.%d)\n", MajorVersion, MinorVersion);
20972b4363aSmrg	fprintf(stderr, "Minimum required version is %d.%d\n",
21072b4363aSmrg		MINMAJOR, MINMINOR);
21172b4363aSmrg	exit(2);
21272b4363aSmrg    }
21372b4363aSmrg
21472b4363aSmrg    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
21572b4363aSmrg	fprintf(stderr, "Unable to query gamma correction\n");
21672b4363aSmrg	XCloseDisplay (dpy);
21772b4363aSmrg	exit (2);
21872b4363aSmrg    } else if (!quiet)
21972b4363aSmrg	fprintf(stderr, "-> Red %6.3f, Green %6.3f, Blue %6.3f\n", gamma.red,
22072b4363aSmrg		gamma.green, gamma.blue);
22172b4363aSmrg
22272b4363aSmrg    ret = 0;
22372b4363aSmrg    if (gam >= 0.) {
22472b4363aSmrg	gamma.red = gam;
22572b4363aSmrg	gamma.green = gam;
22672b4363aSmrg	gamma.blue = gam;
22772b4363aSmrg	if (!XF86VidModeSetGamma(dpy, screen, &gamma)) {
22872b4363aSmrg	    fprintf(stderr, "Unable to set gamma correction\n");
22972b4363aSmrg	    ret = 2;
23072b4363aSmrg	} else {
23172b4363aSmrg	    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
23272b4363aSmrg		fprintf(stderr, "Unable to query gamma correction\n");
23372b4363aSmrg		ret = 2;
23472b4363aSmrg	    } else if (!quiet)
23572b4363aSmrg		fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n",
23672b4363aSmrg		        gamma.red, gamma.green, gamma.blue);
23772b4363aSmrg	}
23872b4363aSmrg    } else if ((rgam >= 0.) || (ggam >= 0.) || (bgam >= 0.)) {
23972b4363aSmrg	if (rgam >= 0.) gamma.red = rgam;
24072b4363aSmrg	if (ggam >= 0.) gamma.green = ggam;
24172b4363aSmrg	if (bgam >= 0.) gamma.blue = bgam;
24272b4363aSmrg	if (!XF86VidModeSetGamma(dpy, screen, &gamma)) {
24372b4363aSmrg	    fprintf(stderr, "Unable to set gamma correction\n");
24472b4363aSmrg	    ret = 2;
24572b4363aSmrg	} else {
24672b4363aSmrg	    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
24772b4363aSmrg		fprintf(stderr, "Unable to query gamma correction\n");
24872b4363aSmrg		ret = 2;
24972b4363aSmrg	    } else if (!quiet)
25072b4363aSmrg		fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n",
25172b4363aSmrg		        gamma.red, gamma.green, gamma.blue);
25272b4363aSmrg	}
25372b4363aSmrg    }
25472b4363aSmrg
25572b4363aSmrg    XCloseDisplay (dpy);
25672b4363aSmrg    exit (ret);
25772b4363aSmrg}
25872b4363aSmrg
259