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 387ed541caSmrg#ifndef HAVE_STRTOF 397ed541caSmrg#define strtof(a, n) (float)atof(a) 407ed541caSmrg#endif 417ed541caSmrg 42dd77ae96Smrgstatic char *ProgramName; 43dd77ae96Smrgstatic int MajorVersion, MinorVersion; 44dd77ae96Smrgstatic int EventBase, ErrorBase; 4572b4363aSmrg 4672b4363aSmrg/* Minimum extension version required */ 4772b4363aSmrg#define MINMAJOR 2 4872b4363aSmrg#define MINMINOR 0 4972b4363aSmrg 5072b4363aSmrg/* Maximum and Minimum gamma values */ 517ed541caSmrg#define GAMMA_MIN 0.1f 527ed541caSmrg#define GAMMA_MAX 10.0f 5372b4363aSmrg 5433dddc75Smrgstatic void _X_NORETURN 5533dddc75SmrgSyntax(const char *errmsg) 5672b4363aSmrg{ 5733dddc75Smrg if (errmsg != NULL) 5833dddc75Smrg fprintf (stderr, "%s: %s\n\n", ProgramName, errmsg); 5933dddc75Smrg 6033dddc75Smrg fprintf (stderr, "usage: %s [-options]\n\n%s", ProgramName, 6133dddc75Smrg "where the available options are:\n" 6233dddc75Smrg " -display host:dpy or -d\n" 6333dddc75Smrg " -quiet or -q\n" 6433dddc75Smrg " -screen or -s\n" 6533dddc75Smrg " -version or -v\n" 6633dddc75Smrg " -gamma f.f Gamma Value\n" 6733dddc75Smrg " -rgamma f.f Red Gamma Value\n" 6833dddc75Smrg " -ggamma f.f Green Gamma Value\n" 6933dddc75Smrg " -bgamma f.f Blue Gamma Value\n\n" 7033dddc75Smrg "If no gamma is specified, returns the current setting\n"); 7172b4363aSmrg exit (1); 7272b4363aSmrg} 7372b4363aSmrg 7472b4363aSmrg 7572b4363aSmrg/* 7672b4363aSmrg * The following is a hack until XrmParseCommand is ready. It determines 7772b4363aSmrg * whether or not the given string is an abbreviation of the arg. 7872b4363aSmrg */ 7972b4363aSmrg 8072b4363aSmrgstatic Bool 8133dddc75Smrgisabbreviation(const char *arg, const char *s, size_t minslen) 8272b4363aSmrg{ 8333dddc75Smrg size_t arglen; 8433dddc75Smrg size_t slen; 8572b4363aSmrg 8672b4363aSmrg /* exact match */ 8772b4363aSmrg if (strcmp (arg, s) == 0) return (True); 8872b4363aSmrg 8972b4363aSmrg arglen = strlen (arg); 9072b4363aSmrg slen = strlen (s); 9172b4363aSmrg 9272b4363aSmrg /* too long or too short */ 9372b4363aSmrg if (slen >= arglen || slen < minslen) return (False); 9472b4363aSmrg 9572b4363aSmrg /* abbreviation */ 9672b4363aSmrg if (strncmp (arg, s, slen) == 0) return (True); 9772b4363aSmrg 9872b4363aSmrg /* bad */ 9972b4363aSmrg return (False); 10072b4363aSmrg} 10172b4363aSmrg 10272b4363aSmrgint 10372b4363aSmrgmain(int argc, char *argv[]) 10472b4363aSmrg{ 1057ed541caSmrg int ret = 2; 10672b4363aSmrg char *displayname = NULL; 10772b4363aSmrg Display *dpy; 1087ed541caSmrg float gam = -1.0f, rgam = -1.0f, ggam = -1.0f, bgam = -1.0f; 10972b4363aSmrg XF86VidModeGamma gamma; 11072b4363aSmrg Bool quiet = False; 11172b4363aSmrg int screen = -1; 11272b4363aSmrg 11372b4363aSmrg ProgramName = argv[0]; 1147ed541caSmrg for (int i = 1; i < argc; i++) { 11572b4363aSmrg char *arg = argv[i]; 11672b4363aSmrg 11772b4363aSmrg if (arg[0] == '-') { 11872b4363aSmrg if (isabbreviation ("-display", arg, 1)) { 11933dddc75Smrg if (++i >= argc) Syntax ("-display requires an argument"); 12072b4363aSmrg displayname = argv[i]; 12172b4363aSmrg continue; 12272b4363aSmrg } else if (isabbreviation ("-quiet", arg, 1)) { 12372b4363aSmrg quiet = True; 12472b4363aSmrg continue; 12533dddc75Smrg } else if (isabbreviation ("-version", arg, 1)) { 12633dddc75Smrg puts(PACKAGE_STRING); 12733dddc75Smrg exit(0); 12872b4363aSmrg } else if (isabbreviation ("-screen", arg, 1)) { 12933dddc75Smrg if (++i >= argc) Syntax ("-screen requires an argument"); 13072b4363aSmrg screen = atoi(argv[i]); 13172b4363aSmrg continue; 13272b4363aSmrg } else if (isabbreviation ("-gamma", arg, 2)) { 13333dddc75Smrg if (++i >= argc) Syntax ("-gamma requires an argument"); 1347ed541caSmrg if ((rgam >= 0.0f) || (ggam >= 0.0f) || (bgam >= 0.0f)) 13533dddc75Smrg Syntax ("-gamma cannot be used with -rgamma, -ggamma, or -bgamma"); 1367ed541caSmrg gam = strtof(argv[i], NULL); 13772b4363aSmrg if ((gam < GAMMA_MIN) || (gam > GAMMA_MAX)) { 13872b4363aSmrg fprintf(stderr, 13972b4363aSmrg "Gamma values must be between %6.3f and %6.3f\n", 1407ed541caSmrg (double)GAMMA_MIN, (double)GAMMA_MAX); 14172b4363aSmrg exit(1); 14272b4363aSmrg } 14372b4363aSmrg continue; 14472b4363aSmrg } else if (isabbreviation ("-rgamma", arg, 2)) { 14533dddc75Smrg if (++i >= argc) Syntax ("-rgamma requires an argument"); 1467ed541caSmrg if (gam >= 0.0f) Syntax ("cannot set both -gamma and -rgamma"); 1477ed541caSmrg rgam = strtof(argv[i], NULL); 14872b4363aSmrg if ((rgam < GAMMA_MIN) || (rgam > GAMMA_MAX)) { 14972b4363aSmrg fprintf(stderr, 15072b4363aSmrg "Gamma values must be between %6.3f and %6.3f\n", 1517ed541caSmrg (double)GAMMA_MIN, (double)GAMMA_MAX); 15272b4363aSmrg exit(1); 15372b4363aSmrg } 15472b4363aSmrg continue; 15572b4363aSmrg } else if (isabbreviation ("-ggamma", arg, 2)) { 15633dddc75Smrg if (++i >= argc) Syntax ("-ggamma requires an argument"); 1577ed541caSmrg if (gam >= 0.0f) Syntax ("cannot set both -gamma and -ggamma"); 1587ed541caSmrg ggam = strtof(argv[i], NULL); 15972b4363aSmrg if ((ggam < GAMMA_MIN) || (ggam > GAMMA_MAX)) { 16072b4363aSmrg fprintf(stderr, 16172b4363aSmrg "Gamma values must be between %6.3f and %6.3f\n", 1627ed541caSmrg (double)GAMMA_MIN, (double)GAMMA_MAX); 16372b4363aSmrg exit(1); 16472b4363aSmrg } 16572b4363aSmrg continue; 16672b4363aSmrg } else if (isabbreviation ("-bgamma", arg, 2)) { 16733dddc75Smrg if (++i >= argc) Syntax ("-bgamma requires an argument"); 1687ed541caSmrg if (gam >= 0.0f) Syntax ("cannot set both -gamma and -bgamma"); 1697ed541caSmrg bgam = strtof(argv[i], NULL); 17072b4363aSmrg if ((bgam < GAMMA_MIN) || (bgam > GAMMA_MAX)) { 17172b4363aSmrg fprintf(stderr, 17272b4363aSmrg "Gamma values must be between %6.3f and %6.3f\n", 1737ed541caSmrg (double)GAMMA_MIN, (double)GAMMA_MAX); 17472b4363aSmrg exit(1); 17572b4363aSmrg } 17672b4363aSmrg continue; 17733dddc75Smrg } else { 17833dddc75Smrg if (!isabbreviation ("-help", arg, 1)) 17933dddc75Smrg fprintf (stderr, "%s: unrecognized argument %s\n\n", 18033dddc75Smrg ProgramName, arg); 18133dddc75Smrg Syntax (NULL); 18233dddc75Smrg } 18333dddc75Smrg } else { 18433dddc75Smrg fprintf (stderr, "%s: unrecognized argument %s\n\n", 18533dddc75Smrg ProgramName, arg); 18633dddc75Smrg Syntax (NULL); 18733dddc75Smrg } 18872b4363aSmrg } 18972b4363aSmrg 19072b4363aSmrg if ((dpy = XOpenDisplay(displayname)) == NULL) { 19172b4363aSmrg fprintf (stderr, "%s: unable to open display '%s'\n", 19272b4363aSmrg ProgramName, XDisplayName (displayname)); 19372b4363aSmrg exit(1); 19472b4363aSmrg } else if (screen == -1) 19572b4363aSmrg screen = DefaultScreen(dpy); 19672b4363aSmrg 19772b4363aSmrg if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 19872b4363aSmrg fprintf(stderr, "Unable to query video extension version\n"); 1997ed541caSmrg goto finish; 20072b4363aSmrg } 20172b4363aSmrg 20272b4363aSmrg if (!XF86VidModeQueryExtension(dpy, &EventBase, &ErrorBase)) { 20372b4363aSmrg fprintf(stderr, "Unable to query video extension information\n"); 2047ed541caSmrg goto finish; 20572b4363aSmrg } 20672b4363aSmrg 20772b4363aSmrg /* Fail if the extension version in the server is too old */ 20872b4363aSmrg if (MajorVersion < MINMAJOR || 20972b4363aSmrg (MajorVersion == MINMAJOR && MinorVersion < MINMINOR)) { 21072b4363aSmrg fprintf(stderr, 21172b4363aSmrg "Xserver is running an old XFree86-VidModeExtension version" 21272b4363aSmrg " (%d.%d)\n", MajorVersion, MinorVersion); 21372b4363aSmrg fprintf(stderr, "Minimum required version is %d.%d\n", 21472b4363aSmrg MINMAJOR, MINMINOR); 2157ed541caSmrg goto finish; 21672b4363aSmrg } 21772b4363aSmrg 21872b4363aSmrg if (!XF86VidModeGetGamma(dpy, screen, &gamma)) { 21972b4363aSmrg fprintf(stderr, "Unable to query gamma correction\n"); 2207ed541caSmrg goto finish; 22172b4363aSmrg } else if (!quiet) 2227ed541caSmrg fprintf(stderr, "-> Red %6.3f, Green %6.3f, Blue %6.3f\n", 2237ed541caSmrg (double)gamma.red, (double)gamma.green, (double)gamma.blue); 22472b4363aSmrg 2257ed541caSmrg if (gam >= 0.0f) { 22672b4363aSmrg gamma.red = gam; 22772b4363aSmrg gamma.green = gam; 22872b4363aSmrg gamma.blue = gam; 2297ed541caSmrg } else if ((rgam >= 0.0f) || (ggam >= 0.0f) || (bgam >= 0.0f)) { 2307ed541caSmrg if (rgam >= 0.0f) gamma.red = rgam; 2317ed541caSmrg if (ggam >= 0.0f) gamma.green = ggam; 2327ed541caSmrg if (bgam >= 0.0f) gamma.blue = bgam; 2337ed541caSmrg } else { 2347ed541caSmrg /* Not changing gamma, all done */ 2357ed541caSmrg ret = 0; 2367ed541caSmrg goto finish; 2377ed541caSmrg } 2387ed541caSmrg 2397ed541caSmrg /* Change gamma now */ 2407ed541caSmrg if (!XF86VidModeSetGamma(dpy, screen, &gamma)) { 2417ed541caSmrg fprintf(stderr, "Unable to set gamma correction\n"); 2427ed541caSmrg } else { 2437ed541caSmrg if (!XF86VidModeGetGamma(dpy, screen, &gamma)) { 2447ed541caSmrg fprintf(stderr, "Unable to query gamma correction\n"); 24572b4363aSmrg } else { 2467ed541caSmrg ret = 0; /* Success! */ 2477ed541caSmrg if (!quiet) { 24872b4363aSmrg fprintf(stderr, "<- Red %6.3f, Green %6.3f, Blue %6.3f\n", 2497ed541caSmrg (double)gamma.red, (double)gamma.green, 2507ed541caSmrg (double)gamma.blue); 2517ed541caSmrg } 25272b4363aSmrg } 25372b4363aSmrg } 25472b4363aSmrg 2557ed541caSmrg finish: 25672b4363aSmrg XCloseDisplay (dpy); 25772b4363aSmrg exit (ret); 25872b4363aSmrg} 25972b4363aSmrg 260