Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright 1999  The XFree86 Project
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * SOFTWARE.
     21  *
     22  * Written by David Bateman
     23  */
     24 
     25 #ifdef HAVE_CONFIG_H
     26 # include "config.h"
     27 #endif
     28 
     29 #include <stdio.h>
     30 #include <errno.h>
     31 #include <X11/Xos.h>
     32 #include <X11/Xlib.h>
     33 #include <X11/Xutil.h>
     34 #include <X11/extensions/xf86vmode.h>
     35 #include <ctype.h>
     36 #include <stdlib.h>
     37 
     38 #ifndef HAVE_STRTOF
     39 #define strtof(a, n)  (float)atof(a)
     40 #endif
     41 
     42 static char *ProgramName;
     43 static int MajorVersion, MinorVersion;
     44 static int EventBase, ErrorBase;
     45 
     46 /* Minimum extension version required */
     47 #define MINMAJOR 2
     48 #define MINMINOR 0
     49 
     50 /* Maximum and Minimum gamma values */
     51 #define GAMMA_MIN 0.1f
     52 #define GAMMA_MAX 10.0f
     53 
     54 static void _X_NORETURN
     55 Syntax(const char *errmsg, int exitstatus)
     56 {
     57     if (errmsg != NULL)
     58         fprintf (stderr, "%s: %s\n\n", ProgramName, errmsg);
     59 
     60     fprintf (stderr, "usage:  %s [-options]\n\n%s", ProgramName,
     61              "where the available options are:\n"
     62              "    -display host:dpy       or -d\n"
     63              "    -quiet                  or -q\n"
     64              "    -screen                 or -s\n"
     65              "    -version                or -v\n"
     66              "    -gamma f.f              Gamma Value\n"
     67              "    -rgamma f.f             Red Gamma Value\n"
     68              "    -ggamma f.f             Green Gamma Value\n"
     69              "    -bgamma f.f             Blue Gamma Value\n\n"
     70              "If no gamma is specified, returns the current setting\n");
     71     exit (exitstatus);
     72 }
     73 
     74 
     75 /*
     76  * The following is a hack until XrmParseCommand is ready.  It determines
     77  * whether or not the given string is an abbreviation of the arg.
     78  */
     79 
     80 static Bool
     81 isabbreviation(const char *arg, const char *s, size_t minslen)
     82 {
     83     size_t arglen;
     84     size_t slen;
     85 
     86     /* exact match */
     87     if (strcmp (arg, s) == 0) return (True);
     88 
     89     arglen = strlen (arg);
     90     slen = strlen (s);
     91 
     92     /* too long or too short */
     93     if (slen >= arglen || slen < minslen) return (False);
     94 
     95     /* abbreviation */
     96     if (strncmp (arg, s, slen) == 0) return (True);
     97 
     98     /* bad */
     99     return (False);
    100 }
    101 
    102 int
    103 main(int argc, char *argv[])
    104 {
    105     int ret = 2;
    106     char *displayname = NULL;
    107     Display *dpy;
    108     float gam = -1.0f, rgam = -1.0f, ggam = -1.0f, bgam = -1.0f;
    109     XF86VidModeGamma gamma;
    110     Bool quiet = False;
    111     int screen = -1;
    112 
    113     ProgramName = argv[0];
    114     for (int i = 1; i < argc; i++) {
    115 	char *arg = argv[i];
    116 
    117 	if (arg[0] == '-') {
    118 	    if (isabbreviation ("-display", arg, 1)) {
    119 		if (++i >= argc)
    120 		    Syntax ("-display requires an argument", EXIT_FAILURE);
    121 		displayname = argv[i];
    122 		continue;
    123 	    } else if (isabbreviation ("-quiet", arg, 1)) {
    124 		quiet = True;
    125 		continue;
    126 	    } else if (isabbreviation ("-version", arg, 1) ||
    127 		       !strcmp("--version", arg)) {
    128 		puts(PACKAGE_STRING);
    129 		exit(EXIT_SUCCESS);
    130 	    } else if (isabbreviation ("-help", arg, 1) ||
    131 		       !strcmp("--help", arg)) {
    132 		Syntax(NULL, EXIT_SUCCESS);
    133 	    } else if (isabbreviation ("-screen", arg, 1)) {
    134 		if (++i >= argc)
    135 		    Syntax ("-screen requires an argument", EXIT_FAILURE);
    136 		screen = atoi(argv[i]);
    137 		continue;
    138 	    } else if (isabbreviation ("-gamma", arg, 2)) {
    139 		if (++i >= argc)
    140 		    Syntax ("-gamma requires an argument", EXIT_FAILURE);
    141 		if ((rgam >= 0.0f) || (ggam >= 0.0f) || (bgam >= 0.0f))
    142 		    Syntax ("-gamma cannot be used with -rgamma, -ggamma, or -bgamma", EXIT_FAILURE);
    143 		gam = strtof(argv[i], NULL);
    144 		if ((gam < GAMMA_MIN) || (gam > GAMMA_MAX)) {
    145 		    fprintf(stderr,
    146 			    "Gamma values must be between %6.3f and %6.3f\n",
    147 			    (double)GAMMA_MIN, (double)GAMMA_MAX);
    148 		    exit(EXIT_FAILURE);
    149 		}
    150 		continue;
    151 	    } else if (isabbreviation ("-rgamma", arg, 2)) {
    152 		if (++i >= argc)
    153 		    Syntax ("-rgamma requires an argument", EXIT_FAILURE);
    154 		if (gam >= 0.0f)
    155 		    Syntax ("cannot set both -gamma and -rgamma", EXIT_FAILURE);
    156 		rgam = strtof(argv[i], NULL);
    157 		if ((rgam < GAMMA_MIN) || (rgam > GAMMA_MAX)) {
    158 		    fprintf(stderr,
    159 			    "Gamma values must be between %6.3f and %6.3f\n",
    160 			    (double)GAMMA_MIN, (double)GAMMA_MAX);
    161 		    exit(EXIT_FAILURE);
    162 		}
    163 		continue;
    164 	    } else if (isabbreviation ("-ggamma", arg, 2)) {
    165 		if (++i >= argc)
    166 		    Syntax ("-ggamma requires an argument", EXIT_FAILURE);
    167 		if (gam >= 0.0f)
    168 		    Syntax ("cannot set both -gamma and -ggamma", EXIT_FAILURE);
    169 		ggam = strtof(argv[i], NULL);
    170 		if ((ggam < GAMMA_MIN) || (ggam > GAMMA_MAX)) {
    171 		    fprintf(stderr,
    172 			    "Gamma values must be between %6.3f and %6.3f\n",
    173 			    (double)GAMMA_MIN, (double)GAMMA_MAX);
    174 		    exit(EXIT_FAILURE);
    175 		}
    176 		continue;
    177 	    } else if (isabbreviation ("-bgamma", arg, 2)) {
    178 		if (++i >= argc)
    179 		    Syntax ("-bgamma requires an argument", EXIT_FAILURE);
    180 		if (gam >= 0.0f)
    181 		    Syntax ("cannot set both -gamma and -bgamma", EXIT_FAILURE);
    182 		bgam = strtof(argv[i], NULL);
    183 		if ((bgam < GAMMA_MIN) || (bgam > GAMMA_MAX)) {
    184 		    fprintf(stderr,
    185 			    "Gamma values must be between %6.3f and %6.3f\n",
    186 			    (double)GAMMA_MIN, (double)GAMMA_MAX);
    187 		    exit(EXIT_FAILURE);
    188 		}
    189 		continue;
    190 	    } else {
    191 		fprintf (stderr, "%s: unrecognized argument %s\n\n",
    192 			 ProgramName, arg);
    193 		Syntax (NULL, EXIT_FAILURE);
    194 	    }
    195 	} else {
    196 	    fprintf (stderr, "%s: unrecognized argument %s\n\n",
    197 		     ProgramName, arg);
    198 	    Syntax (NULL, EXIT_FAILURE);
    199 	}
    200     }
    201 
    202     if ((dpy = XOpenDisplay(displayname)) == NULL) {
    203 	fprintf (stderr, "%s:  unable to open display '%s'\n",
    204 		 ProgramName, XDisplayName (displayname));
    205 	exit(EXIT_FAILURE);
    206     } else if (screen == -1)
    207 	screen = DefaultScreen(dpy);
    208 
    209     if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
    210 	fprintf(stderr, "Unable to query video extension version\n");
    211 	goto finish;
    212     }
    213 
    214     if (!XF86VidModeQueryExtension(dpy, &EventBase, &ErrorBase)) {
    215 	fprintf(stderr, "Unable to query video extension information\n");
    216 	goto finish;
    217     }
    218 
    219     /* Fail if the extension version in the server is too old */
    220     if (MajorVersion < MINMAJOR ||
    221 	(MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
    222 	fprintf(stderr,
    223 		"Xserver is running an old XFree86-VidModeExtension version"
    224 		" (%d.%d)\n", MajorVersion, MinorVersion);
    225 	fprintf(stderr, "Minimum required version is %d.%d\n",
    226 		MINMAJOR, MINMINOR);
    227 	goto finish;
    228     }
    229 
    230     if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
    231 	fprintf(stderr, "Unable to query gamma correction\n");
    232 	goto finish;
    233     } else if (!quiet)
    234 	fprintf(stderr, "-> Red %6.3f, Green %6.3f, Blue %6.3f\n",
    235 		(double)gamma.red, (double)gamma.green, (double)gamma.blue);
    236 
    237     if (gam >= 0.0f) {
    238 	gamma.red = gam;
    239 	gamma.green = gam;
    240 	gamma.blue = gam;
    241     } else if ((rgam >= 0.0f) || (ggam >= 0.0f) || (bgam >= 0.0f)) {
    242 	if (rgam >= 0.0f) gamma.red = rgam;
    243 	if (ggam >= 0.0f) gamma.green = ggam;
    244 	if (bgam >= 0.0f) gamma.blue = bgam;
    245     } else {
    246 	/* Not changing gamma, all done */
    247 	ret = EXIT_SUCCESS;
    248 	goto finish;
    249     }
    250 
    251     /* Change gamma now */
    252     if (!XF86VidModeSetGamma(dpy, screen, &gamma)) {
    253 	fprintf(stderr, "Unable to set gamma correction\n");
    254     } else {
    255 	if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
    256 	    fprintf(stderr, "Unable to query gamma correction\n");
    257 	} else {
    258 	    ret = EXIT_SUCCESS; /* Success! */
    259 	    if (!quiet) {
    260 		fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n",
    261 			(double)gamma.red, (double)gamma.green,
    262 			(double)gamma.blue);
    263 	    }
    264 	}
    265     }
    266 
    267   finish:
    268     XCloseDisplay (dpy);
    269     exit (ret);
    270 }
    271 
    272