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