* Now asks for confirmation before exiting after a mode set. This will time out

after ten seconds, and revert to the original mode.
* Added option -q resp. --dont-confirm which turns off that confirmation.
* Added option -m resp. --modeline that allows you to specify and dump X-style
  modelines.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42736 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2011-09-11 11:07:19 +00:00
parent df9db7862b
commit 02f248105a
1 changed files with 176 additions and 41 deletions

View File

@ -1,9 +1,10 @@
/* /*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. * Copyright 2008-2011, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <ctype.h>
#include <getopt.h> #include <getopt.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -18,6 +19,8 @@
static struct option const kLongOptions[] = { static struct option const kLongOptions[] = {
{"fall-back", no_argument, 0, 'f'}, {"fall-back", no_argument, 0, 'f'},
{"dont-confirm", no_argument, 0, 'q'},
{"modeline", no_argument, 0, 'm'},
{"short", no_argument, 0, 's'}, {"short", no_argument, 0, 's'},
{"list", no_argument, 0, 'l'}, {"list", no_argument, 0, 'l'},
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
@ -47,6 +50,36 @@ color_space_for_depth(int32 depth)
} }
static void
print_mode(const screen_mode& mode, bool shortOutput)
{
const char* format
= shortOutput ? "%ld %ld %ld %g\n" : "%ld %ld, %ld bits, %g Hz\n";
printf(format, mode.width, mode.height, mode.BitsPerPixel(), mode.refresh);
}
static void
print_mode(const display_mode& displayMode, const screen_mode& mode)
{
const display_timing& timing = displayMode.timing;
printf("%lu %u %u %u %u %u %u %u %u ", timing.pixel_clock / 1000,
timing.h_display, timing.h_sync_start, timing.h_sync_end,
timing.h_total, timing.v_display, timing.v_sync_start,
timing.v_sync_end, timing.v_total);
// TODO: more flags?
if ((timing.flags & B_POSITIVE_HSYNC) != 0)
printf(" +HSync");
if ((timing.flags & B_POSITIVE_VSYNC) != 0)
printf(" +VSync");
if ((timing.flags & B_TIMING_INTERLACED) != 0)
printf(" Interlace");
printf(" %lu\n", mode.BitsPerPixel());
}
static void static void
usage(int status) usage(int status)
{ {
@ -55,11 +88,18 @@ usage(int status)
"Sets the specified screen mode. When no screen mode has been chosen,\n" "Sets the specified screen mode. When no screen mode has been chosen,\n"
"the current one is printed. <mode> takes the form: <width> <height>\n" "the current one is printed. <mode> takes the form: <width> <height>\n"
"<depth> <refresh-rate>, or <width>x<height>, etc.\n" "<depth> <refresh-rate>, or <width>x<height>, etc.\n"
" --fall-back\tchanges to the standard fallback mode, and displays a\n" " --fall-back\tchanges to the standard fallback mode, and "
"displays a\n"
"\t\t\tnotification requester.\n" "\t\t\tnotification requester.\n"
" -s --short\t\twhen no mode is given the current screen mode is\n" " -s --short\t\twhen no mode is given the current screen mode is\n"
"\t\t\tprinted in short form.\n" "\t\t\tprinted in short form.\n"
" -l --list\t\tdisplay a list of the available modes\n", " -l --list\t\tdisplay a list of the available modes.\n"
" -q --dont-confirm\tdo not confirm the mode after setting it.\n"
" -m --modeline\taccept and print X-style modeline modes:\n"
"\t\t\t <pclk> <h-display> <h-sync-start> <h-sync-end> <h-total>\n"
"\t\t\t <v-disp> <v-sync-start> <v-sync-end> <v-total> [flags] "
"[depth]\n"
"\t\t\t(supported flags are: +/-HSync, +/-VSync, Interlace)\n",
kProgramName); kProgramName);
exit(status); exit(status);
@ -73,16 +113,19 @@ main(int argc, char** argv)
bool setMode = false; bool setMode = false;
bool shortOutput = false; bool shortOutput = false;
bool listModes = false; bool listModes = false;
bool modeLine = false;
bool confirm = true;
int width = -1; int width = -1;
int height = -1; int height = -1;
int depth = -1; int depth = -1;
float refresh = -1; float refresh = -1;
display_mode mode;
// TODO: add a possibility to set a virtual screen size in addition to // TODO: add a possibility to set a virtual screen size in addition to
// the display resolution! // the display resolution!
int c; int c;
while ((c = getopt_long(argc, argv, "shlf", kLongOptions, NULL)) != -1) { while ((c = getopt_long(argc, argv, "shlfqm", kLongOptions, NULL)) != -1) {
switch (c) { switch (c) {
case 0: case 0:
break; break;
@ -96,6 +139,12 @@ main(int argc, char** argv)
case 'l': case 'l':
listModes = true; listModes = true;
break; break;
case 'm':
modeLine = true;
break;
case 'q':
confirm = false;
break;
case 'h': case 'h':
usage(0); usage(0);
break; break;
@ -109,7 +158,10 @@ main(int argc, char** argv)
int depthIndex = -1; int depthIndex = -1;
// arguments to specify the mode are following // arguments to specify the mode are following
int parsed = sscanf(argv[optind], "%dx%dx%d", &width, &height, &depth);
if (!modeLine) {
int parsed = sscanf(argv[optind], "%dx%dx%d", &width, &height,
&depth);
if (parsed == 2) if (parsed == 2)
depthIndex = optind + 1; depthIndex = optind + 1;
else if (parsed == 1) { else if (parsed == 1) {
@ -125,6 +177,51 @@ main(int argc, char** argv)
depth = strtol(argv[depthIndex], NULL, 0); depth = strtol(argv[depthIndex], NULL, 0);
if (depthIndex + 1 < argc) if (depthIndex + 1 < argc)
refresh = strtod(argv[depthIndex + 1], NULL); refresh = strtod(argv[depthIndex + 1], NULL);
} else {
// parse mode line
if (argc - optind < 9)
usage(1);
mode.timing.pixel_clock = strtol(argv[optind], NULL, 0) * 1000;
mode.timing.h_display = strtol(argv[optind + 1], NULL, 0);
mode.timing.h_sync_start = strtol(argv[optind + 2], NULL, 0);
mode.timing.h_sync_end = strtol(argv[optind + 3], NULL, 0);
mode.timing.h_total = strtol(argv[optind + 4], NULL, 0);
mode.timing.h_display = strtol(argv[optind + 5], NULL, 0);
mode.timing.h_sync_start = strtol(argv[optind + 6], NULL, 0);
mode.timing.h_sync_end = strtol(argv[optind + 7], NULL, 0);
mode.timing.h_total = strtol(argv[optind + 8], NULL, 0);
mode.timing.flags = 0;
mode.space = B_RGB32;
int i = optind + 9;
while (i < argc) {
if (!strcasecmp(argv[i], "+HSync"))
mode.timing.flags |= B_POSITIVE_HSYNC;
else if (!strcasecmp(argv[i], "+VSync"))
mode.timing.flags |= B_POSITIVE_VSYNC;
else if (!strcasecmp(argv[i], "Interlace"))
mode.timing.flags |= B_TIMING_INTERLACED;
else if (!strcasecmp(argv[i], "-VSync")
|| !strcasecmp(argv[i], "-HSync")) {
// okay, but nothing to do
} else if (isdigit(argv[i][0]) && i + 1 == argc) {
// bits per pixel
mode.space
= color_space_for_depth(strtoul(argv[i], NULL, 0));
} else {
fprintf(stderr, "Unknown flag: %s\n", argv[i]);
exit(1);
}
i++;
}
mode.virtual_width = mode.timing.h_display;
mode.virtual_height = mode.timing.v_display;
mode.h_display_start = 0;
mode.v_display_start = 0;
}
setMode = true; setMode = true;
} }
@ -135,29 +232,39 @@ main(int argc, char** argv)
screen_mode currentMode; screen_mode currentMode;
screenMode.Get(currentMode); screenMode.Get(currentMode);
if ((!setMode) && (!listModes)) { if (listModes) {
const char* format = shortOutput // List all reported modes
? "%ld %ld %ld %g\n" : "Resolution: %ld %ld, %ld bits, %g Hz\n"; if (!shortOutput)
printf(format, currentMode.width, currentMode.height, printf("Available screen modes:\n");
currentMode.BitsPerPixel(), currentMode.refresh);
for (int index = 0; index < screenMode.CountModes(); index++) {
if (modeLine) {
print_mode(screenMode.DisplayModeAt(index),
screenMode.ModeAt(index));
} else
print_mode(screenMode.ModeAt(index), shortOutput);
}
return 0;
}
if (!setMode) {
// Just print the current mode
if (modeLine) {
display_mode mode;
screenMode.Get(mode);
print_mode(mode, currentMode);
} else {
if (!shortOutput)
printf("Resolution: ");
print_mode(currentMode, shortOutput);
}
return 0; return 0;
} }
screen_mode newMode = currentMode; screen_mode newMode = currentMode;
if (listModes) { if (fallbackMode) {
const int modeCount = screenMode.CountModes();
printf("Available screen modes :\n");
for (int modeNumber = 0; modeNumber < modeCount; modeNumber++) {
currentMode = screenMode.ModeAt(modeNumber);
const char* format = shortOutput
? "%ld %ld %ld %g\n" : "%ld %ld, %ld bits, %g Hz\n";
printf(format, currentMode.width, currentMode.height,
currentMode.BitsPerPixel(), currentMode.refresh);
}
return 0;
} else if (fallbackMode) {
if (currentMode.width == 800 && currentMode.height == 600) { if (currentMode.width == 800 && currentMode.height == 600) {
newMode.width = 640; newMode.width = 640;
newMode.height = 480; newMode.height = 480;
@ -169,6 +276,10 @@ main(int argc, char** argv)
newMode.space = B_RGB16; newMode.space = B_RGB16;
newMode.refresh = 60; newMode.refresh = 60;
} }
} else if (modeLine) {
display_mode currentDisplayMode;
if (screenMode.Get(currentDisplayMode) == B_OK)
mode.flags = currentDisplayMode.flags;
} else { } else {
newMode.width = width; newMode.width = width;
newMode.height = height; newMode.height = height;
@ -184,9 +295,33 @@ main(int argc, char** argv)
newMode.refresh = 60; newMode.refresh = 60;
} }
status_t status = screenMode.Set(newMode); status_t status;
if (status != B_OK) { if (modeLine)
fprintf(stderr, "%s: Could not set screen mode %ldx%ldx%ldx: %s\n", status = screenMode.Set(mode);
else
status = screenMode.Set(newMode);
if (status == B_OK) {
if (confirm) {
printf("Is this mode okay (Y/n - will revert after 10 seconds)? ");
fflush(stdout);
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
bigtime_t end = system_time() + 10000000LL;
int c = 'n';
while (system_time() < end) {
c = getchar();
if (c != -1)
break;
}
if (c != '\n' && c != 'y')
screenMode.Revert();
}
} else {
fprintf(stderr, "%s: Could not set screen mode %ldx%ldx%ld: %s\n",
kProgramName, newMode.width, newMode.height, newMode.BitsPerPixel(), kProgramName, newMode.width, newMode.height, newMode.BitsPerPixel(),
strerror(status)); strerror(status));
return 1; return 1;