xgamma.c revision 7ed541ca
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
42static char *ProgramName;
43static int MajorVersion, MinorVersion;
44static 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
54static void _X_NORETURN
55Syntax(const char *errmsg)
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 (1);
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
80static Bool
81isabbreviation(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
102int
103main(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) Syntax ("-display requires an argument");
120		displayname = argv[i];
121		continue;
122	    } else if (isabbreviation ("-quiet", arg, 1)) {
123		quiet = True;
124		continue;
125	    } else if (isabbreviation ("-version", arg, 1)) {
126		puts(PACKAGE_STRING);
127		exit(0);
128	    } else if (isabbreviation ("-screen", arg, 1)) {
129		if (++i >= argc) Syntax ("-screen requires an argument");
130		screen = atoi(argv[i]);
131		continue;
132	    } else if (isabbreviation ("-gamma", arg, 2)) {
133		if (++i >= argc) Syntax ("-gamma requires an argument");
134		if ((rgam >= 0.0f) || (ggam >= 0.0f) || (bgam >= 0.0f))
135		    Syntax ("-gamma cannot be used with -rgamma, -ggamma, or -bgamma");
136		gam = strtof(argv[i], NULL);
137		if ((gam < GAMMA_MIN) || (gam > GAMMA_MAX)) {
138		    fprintf(stderr,
139			    "Gamma values must be between %6.3f and %6.3f\n",
140			    (double)GAMMA_MIN, (double)GAMMA_MAX);
141		    exit(1);
142		}
143		continue;
144	    } else if (isabbreviation ("-rgamma", arg, 2)) {
145		if (++i >= argc) Syntax ("-rgamma requires an argument");
146		if (gam >= 0.0f) Syntax ("cannot set both -gamma and -rgamma");
147		rgam = strtof(argv[i], NULL);
148		if ((rgam < GAMMA_MIN) || (rgam > GAMMA_MAX)) {
149		    fprintf(stderr,
150			    "Gamma values must be between %6.3f and %6.3f\n",
151			    (double)GAMMA_MIN, (double)GAMMA_MAX);
152		    exit(1);
153		}
154		continue;
155	    } else if (isabbreviation ("-ggamma", arg, 2)) {
156		if (++i >= argc) Syntax ("-ggamma requires an argument");
157		if (gam >= 0.0f) Syntax ("cannot set both -gamma and -ggamma");
158		ggam = strtof(argv[i], NULL);
159		if ((ggam < GAMMA_MIN) || (ggam > GAMMA_MAX)) {
160		    fprintf(stderr,
161			    "Gamma values must be between %6.3f and %6.3f\n",
162			    (double)GAMMA_MIN, (double)GAMMA_MAX);
163		    exit(1);
164		}
165		continue;
166	    } else if (isabbreviation ("-bgamma", arg, 2)) {
167		if (++i >= argc) Syntax ("-bgamma requires an argument");
168		if (gam >= 0.0f) Syntax ("cannot set both -gamma and -bgamma");
169		bgam = strtof(argv[i], NULL);
170		if ((bgam < GAMMA_MIN) || (bgam > 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(1);
175		}
176		continue;
177	    } else {
178		if (!isabbreviation ("-help", arg, 1))
179		    fprintf (stderr, "%s: unrecognized argument %s\n\n",
180			     ProgramName, arg);
181		Syntax (NULL);
182	    }
183	} else {
184	    fprintf (stderr, "%s: unrecognized argument %s\n\n",
185		     ProgramName, arg);
186	    Syntax (NULL);
187	}
188    }
189
190    if ((dpy = XOpenDisplay(displayname)) == NULL) {
191	fprintf (stderr, "%s:  unable to open display '%s'\n",
192		 ProgramName, XDisplayName (displayname));
193	exit(1);
194    } else if (screen == -1)
195	screen = DefaultScreen(dpy);
196
197    if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) {
198	fprintf(stderr, "Unable to query video extension version\n");
199	goto finish;
200    }
201
202    if (!XF86VidModeQueryExtension(dpy, &EventBase, &ErrorBase)) {
203	fprintf(stderr, "Unable to query video extension information\n");
204	goto finish;
205    }
206
207    /* Fail if the extension version in the server is too old */
208    if (MajorVersion < MINMAJOR ||
209	(MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) {
210	fprintf(stderr,
211		"Xserver is running an old XFree86-VidModeExtension version"
212		" (%d.%d)\n", MajorVersion, MinorVersion);
213	fprintf(stderr, "Minimum required version is %d.%d\n",
214		MINMAJOR, MINMINOR);
215	goto finish;
216    }
217
218    if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
219	fprintf(stderr, "Unable to query gamma correction\n");
220	goto finish;
221    } else if (!quiet)
222	fprintf(stderr, "-> Red %6.3f, Green %6.3f, Blue %6.3f\n",
223		(double)gamma.red, (double)gamma.green, (double)gamma.blue);
224
225    if (gam >= 0.0f) {
226	gamma.red = gam;
227	gamma.green = gam;
228	gamma.blue = gam;
229    } else if ((rgam >= 0.0f) || (ggam >= 0.0f) || (bgam >= 0.0f)) {
230	if (rgam >= 0.0f) gamma.red = rgam;
231	if (ggam >= 0.0f) gamma.green = ggam;
232	if (bgam >= 0.0f) gamma.blue = bgam;
233    } else {
234	/* Not changing gamma, all done */
235	ret = 0;
236	goto finish;
237    }
238
239    /* Change gamma now */
240    if (!XF86VidModeSetGamma(dpy, screen, &gamma)) {
241	fprintf(stderr, "Unable to set gamma correction\n");
242    } else {
243	if (!XF86VidModeGetGamma(dpy, screen, &gamma)) {
244	    fprintf(stderr, "Unable to query gamma correction\n");
245	} else {
246	    ret = 0; /* Success! */
247	    if (!quiet) {
248		fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n",
249			(double)gamma.red, (double)gamma.green,
250			(double)gamma.blue);
251	    }
252	}
253    }
254
255  finish:
256    XCloseDisplay (dpy);
257    exit (ret);
258}
259
260