1 /* 2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <getopt.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include <Alert.h> 13 #include <Application.h> 14 #include <Screen.h> 15 16 #include "ScreenMode.h" 17 18 19 static struct option const kLongOptions[] = { 20 {"fall-back", no_argument, 0, 'f'}, 21 {"short", no_argument, 0, 's'}, 22 {"list", no_argument, 0, 'l'}, 23 {"help", no_argument, 0, 'h'}, 24 {NULL} 25 }; 26 27 extern const char *__progname; 28 static const char *kProgramName = __progname; 29 30 31 static color_space 32 color_space_for_depth(int32 depth) 33 { 34 switch (depth) { 35 case 8: 36 return B_CMAP8; 37 case 15: 38 return B_RGB15; 39 case 16: 40 return B_RGB16; 41 case 24: 42 return B_RGB24; 43 case 32: 44 default: 45 return B_RGB32; 46 } 47 } 48 49 50 static void 51 usage(int status) 52 { 53 fprintf(stderr, 54 "Usage: %s [options] <mode>\n" 55 "Sets the specified screen mode. When no screen mode has been chosen,\n" 56 "the current one is printed. <mode> takes the form: <width> <height>\n" 57 "<depth> <refresh-rate>, or <width>x<height>, etc.\n" 58 " --fall-back\tchanges to the standard fallback mode, and displays a\n" 59 "\t\t\tnotification requester.\n" 60 " -s --short\t\twhen no mode is given the current screen mode is\n" 61 "\t\t\tprinted in short form.\n" 62 " -l --list\t\tdisplay a list of the available modes\n", 63 kProgramName); 64 65 exit(status); 66 } 67 68 69 int 70 main(int argc, char** argv) 71 { 72 bool fallbackMode = false; 73 bool setMode = false; 74 bool shortOutput = false; 75 bool listModes = false; 76 int width = -1; 77 int height = -1; 78 int depth = -1; 79 float refresh = -1; 80 81 // TODO: add a possibility to set a virtual screen size in addition to 82 // the display resolution! 83 84 int c; 85 while ((c = getopt_long(argc, argv, "shlf", kLongOptions, NULL)) != -1) { 86 switch (c) { 87 case 0: 88 break; 89 case 'f': 90 fallbackMode = true; 91 setMode = true; 92 break; 93 case 's': 94 shortOutput = true; 95 break; 96 case 'l': 97 listModes = true; 98 break; 99 case 'h': 100 usage(0); 101 break; 102 default: 103 usage(1); 104 break; 105 } 106 } 107 108 if (argc - optind > 0) { 109 int depthIndex = -1; 110 111 // arguments to specify the mode are following 112 int parsed = sscanf(argv[optind], "%dx%dx%d", &width, &height, &depth); 113 if (parsed == 2) 114 depthIndex = optind + 1; 115 else if (parsed == 1) { 116 if (argc - optind > 1) { 117 height = strtol(argv[optind + 1], NULL, 0); 118 depthIndex = optind + 2; 119 } else 120 usage(1); 121 } else if (parsed != 3) 122 usage(1); 123 124 if (depthIndex > 0 && depthIndex < argc) 125 depth = strtol(argv[depthIndex], NULL, 0); 126 if (depthIndex + 1 < argc) 127 refresh = strtod(argv[depthIndex + 1], NULL); 128 129 setMode = true; 130 } 131 132 BApplication application("application/x-vnd.Haiku-screenmode"); 133 134 ScreenMode screenMode(NULL); 135 screen_mode currentMode; 136 screenMode.Get(currentMode); 137 138 if ((!setMode) && (!listModes)) { 139 const char* format = shortOutput 140 ? "%ld %ld %ld %g\n" : "Resolution: %ld %ld, %ld bits, %g Hz\n"; 141 printf(format, currentMode.width, currentMode.height, 142 currentMode.BitsPerPixel(), currentMode.refresh); 143 return 0; 144 } 145 146 screen_mode newMode = currentMode; 147 148 if (listModes) { 149 const int modeCount = screenMode.CountModes(); 150 printf("Available screen modes :\n"); 151 152 for (int modeNumber = 0; modeNumber < modeCount; modeNumber++) { 153 currentMode = screenMode.ModeAt(modeNumber); 154 const char* format = shortOutput 155 ? "%ld %ld %ld %g\n" : "%ld %ld, %ld bits, %g Hz\n"; 156 printf(format, currentMode.width, currentMode.height, 157 currentMode.BitsPerPixel(), currentMode.refresh); 158 } 159 return 0; 160 } else if (fallbackMode) { 161 if (currentMode.width == 800 && currentMode.height == 600) { 162 newMode.width = 640; 163 newMode.height = 480; 164 newMode.space = B_CMAP8; 165 newMode.refresh = 60; 166 } else { 167 newMode.width = 800; 168 newMode.height = 600; 169 newMode.space = B_RGB16; 170 newMode.refresh = 60; 171 } 172 } else { 173 newMode.width = width; 174 newMode.height = height; 175 176 if (depth != -1) 177 newMode.space = color_space_for_depth(depth); 178 else 179 newMode.space = B_RGB32; 180 181 if (refresh > 0) 182 newMode.refresh = refresh; 183 else 184 newMode.refresh = 60; 185 } 186 187 status_t status = screenMode.Set(newMode); 188 if (status != B_OK) { 189 fprintf(stderr, "%s: Could not set screen mode %ldx%ldx%ldx: %s\n", 190 kProgramName, newMode.width, newMode.height, newMode.BitsPerPixel(), 191 strerror(status)); 192 return 1; 193 } 194 195 if (fallbackMode) { 196 // display notification requester 197 BAlert* alert = new BAlert("screenmode", 198 "You have used the shortcut <Command><Ctrl><Escape> to reset the " 199 "screen mode to a safe fallback.", "Keep", "Revert"); 200 if (alert->Go() == 1) 201 screenMode.Revert(); 202 } 203 204 return 0; 205 } 206