* 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:
parent
df9db7862b
commit
02f248105a
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -18,6 +19,8 @@
|
||||
|
||||
static struct option const kLongOptions[] = {
|
||||
{"fall-back", no_argument, 0, 'f'},
|
||||
{"dont-confirm", no_argument, 0, 'q'},
|
||||
{"modeline", no_argument, 0, 'm'},
|
||||
{"short", no_argument, 0, 's'},
|
||||
{"list", no_argument, 0, 'l'},
|
||||
{"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
|
||||
usage(int status)
|
||||
{
|
||||
@ -55,11 +88,18 @@ usage(int status)
|
||||
"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"
|
||||
"<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"
|
||||
" -s --short\t\twhen no mode is given the current screen mode is\n"
|
||||
"\t\t\tprinted in short form.\n"
|
||||
" -l --list\t\tdisplay a list of the available modes\n",
|
||||
"\t\t\tprinted in short form.\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);
|
||||
|
||||
exit(status);
|
||||
@ -73,16 +113,19 @@ main(int argc, char** argv)
|
||||
bool setMode = false;
|
||||
bool shortOutput = false;
|
||||
bool listModes = false;
|
||||
bool modeLine = false;
|
||||
bool confirm = true;
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
int depth = -1;
|
||||
float refresh = -1;
|
||||
display_mode mode;
|
||||
|
||||
// TODO: add a possibility to set a virtual screen size in addition to
|
||||
// the display resolution!
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "shlf", kLongOptions, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "shlfqm", kLongOptions, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
break;
|
||||
@ -96,6 +139,12 @@ main(int argc, char** argv)
|
||||
case 'l':
|
||||
listModes = true;
|
||||
break;
|
||||
case 'm':
|
||||
modeLine = true;
|
||||
break;
|
||||
case 'q':
|
||||
confirm = false;
|
||||
break;
|
||||
case 'h':
|
||||
usage(0);
|
||||
break;
|
||||
@ -109,22 +158,70 @@ main(int argc, char** argv)
|
||||
int depthIndex = -1;
|
||||
|
||||
// arguments to specify the mode are following
|
||||
int parsed = sscanf(argv[optind], "%dx%dx%d", &width, &height, &depth);
|
||||
if (parsed == 2)
|
||||
depthIndex = optind + 1;
|
||||
else if (parsed == 1) {
|
||||
if (argc - optind > 1) {
|
||||
height = strtol(argv[optind + 1], NULL, 0);
|
||||
depthIndex = optind + 2;
|
||||
} else
|
||||
usage(1);
|
||||
} else if (parsed != 3)
|
||||
usage(1);
|
||||
|
||||
if (depthIndex > 0 && depthIndex < argc)
|
||||
depth = strtol(argv[depthIndex], NULL, 0);
|
||||
if (depthIndex + 1 < argc)
|
||||
refresh = strtod(argv[depthIndex + 1], NULL);
|
||||
if (!modeLine) {
|
||||
int parsed = sscanf(argv[optind], "%dx%dx%d", &width, &height,
|
||||
&depth);
|
||||
if (parsed == 2)
|
||||
depthIndex = optind + 1;
|
||||
else if (parsed == 1) {
|
||||
if (argc - optind > 1) {
|
||||
height = strtol(argv[optind + 1], NULL, 0);
|
||||
depthIndex = optind + 2;
|
||||
} else
|
||||
usage(1);
|
||||
} else if (parsed != 3)
|
||||
usage(1);
|
||||
|
||||
if (depthIndex > 0 && depthIndex < argc)
|
||||
depth = strtol(argv[depthIndex], NULL, 0);
|
||||
if (depthIndex + 1 < argc)
|
||||
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;
|
||||
}
|
||||
@ -135,29 +232,39 @@ main(int argc, char** argv)
|
||||
screen_mode currentMode;
|
||||
screenMode.Get(currentMode);
|
||||
|
||||
if ((!setMode) && (!listModes)) {
|
||||
const char* format = shortOutput
|
||||
? "%ld %ld %ld %g\n" : "Resolution: %ld %ld, %ld bits, %g Hz\n";
|
||||
printf(format, currentMode.width, currentMode.height,
|
||||
currentMode.BitsPerPixel(), currentMode.refresh);
|
||||
if (listModes) {
|
||||
// List all reported modes
|
||||
if (!shortOutput)
|
||||
printf("Available screen modes:\n");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
screen_mode newMode = currentMode;
|
||||
|
||||
if (listModes) {
|
||||
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 (fallbackMode) {
|
||||
if (currentMode.width == 800 && currentMode.height == 600) {
|
||||
newMode.width = 640;
|
||||
newMode.height = 480;
|
||||
@ -169,6 +276,10 @@ main(int argc, char** argv)
|
||||
newMode.space = B_RGB16;
|
||||
newMode.refresh = 60;
|
||||
}
|
||||
} else if (modeLine) {
|
||||
display_mode currentDisplayMode;
|
||||
if (screenMode.Get(currentDisplayMode) == B_OK)
|
||||
mode.flags = currentDisplayMode.flags;
|
||||
} else {
|
||||
newMode.width = width;
|
||||
newMode.height = height;
|
||||
@ -184,9 +295,33 @@ main(int argc, char** argv)
|
||||
newMode.refresh = 60;
|
||||
}
|
||||
|
||||
status_t status = screenMode.Set(newMode);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Could not set screen mode %ldx%ldx%ldx: %s\n",
|
||||
status_t status;
|
||||
if (modeLine)
|
||||
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(),
|
||||
strerror(status));
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user