| 1 |
/* gcc -std=c99 -o brightness brightness.c -framework IOKit -framework ApplicationServices */ |
|---|
| 2 |
|
|---|
| 3 |
#include <stdio.h> |
|---|
| 4 |
#include <unistd.h> |
|---|
| 5 |
#include <IOKit/graphics/IOGraphicsLib.h> |
|---|
| 6 |
#include <ApplicationServices/ApplicationServices.h> |
|---|
| 7 |
|
|---|
| 8 |
const int kMaxDisplays = 16; |
|---|
| 9 |
const CFStringRef kDisplayBrightness = CFSTR(kIODisplayBrightnessKey); |
|---|
| 10 |
const char *APP_NAME; |
|---|
| 11 |
|
|---|
| 12 |
void errexit(const char *fmt, ...) { |
|---|
| 13 |
va_list ap; |
|---|
| 14 |
va_start(ap, fmt); |
|---|
| 15 |
fprintf(stderr, "%s: ", APP_NAME); |
|---|
| 16 |
vfprintf(stderr, fmt, ap); |
|---|
| 17 |
fprintf(stderr, "\n"); |
|---|
| 18 |
exit(1); |
|---|
| 19 |
} |
|---|
| 20 |
|
|---|
| 21 |
void usage() { |
|---|
| 22 |
fprintf(stderr, "usage: %s [-m|-d display] [-v] <brightness>\n", APP_NAME); |
|---|
| 23 |
fprintf(stderr, " or: %s -l [-v]\n", APP_NAME); |
|---|
| 24 |
exit(1); |
|---|
| 25 |
} |
|---|
| 26 |
|
|---|
| 27 |
int main(int argc, char * const argv[]) { |
|---|
| 28 |
APP_NAME = argv[0]; |
|---|
| 29 |
if (argc == 1) |
|---|
| 30 |
usage(); |
|---|
| 31 |
|
|---|
| 32 |
int verbose = 0; |
|---|
| 33 |
unsigned long displayToSet = 0; |
|---|
| 34 |
enum { ACTION_LIST, ACTION_SET_ALL, ACTION_SET_ONE } action = ACTION_SET_ALL; |
|---|
| 35 |
extern char *optarg; |
|---|
| 36 |
extern int optind; |
|---|
| 37 |
int ch; |
|---|
| 38 |
|
|---|
| 39 |
while ( (ch = getopt(argc, argv, "lmvd:")) != -1) { |
|---|
| 40 |
switch (ch) { |
|---|
| 41 |
case 'l': |
|---|
| 42 |
if (action == ACTION_SET_ONE) usage(); |
|---|
| 43 |
action = ACTION_LIST; |
|---|
| 44 |
break; |
|---|
| 45 |
case 'v': |
|---|
| 46 |
verbose = 1; |
|---|
| 47 |
break; |
|---|
| 48 |
case 'm': |
|---|
| 49 |
if (action != ACTION_SET_ALL) usage(); |
|---|
| 50 |
action = ACTION_SET_ONE; |
|---|
| 51 |
displayToSet = (unsigned long)CGMainDisplayID(); |
|---|
| 52 |
break; |
|---|
| 53 |
case 'd': |
|---|
| 54 |
if (action != ACTION_SET_ALL) usage(); |
|---|
| 55 |
action = ACTION_SET_ONE; |
|---|
| 56 |
errno = 0; |
|---|
| 57 |
displayToSet = strtoul(optarg, NULL, 0); |
|---|
| 58 |
if (errno == EINVAL || errno == ERANGE) |
|---|
| 59 |
errexit("display must be an integer index (0) or a hexadecimal ID (0x4270a80)"); |
|---|
| 60 |
break; |
|---|
| 61 |
default: usage(); |
|---|
| 62 |
} |
|---|
| 63 |
} |
|---|
| 64 |
|
|---|
| 65 |
argc -= optind; |
|---|
| 66 |
argv += optind; |
|---|
| 67 |
|
|---|
| 68 |
float brightness; |
|---|
| 69 |
if (action == ACTION_LIST) { |
|---|
| 70 |
if (argc > 0) usage(); |
|---|
| 71 |
} else { |
|---|
| 72 |
if (argc != 1) usage(); |
|---|
| 73 |
|
|---|
| 74 |
errno = 0; |
|---|
| 75 |
brightness = strtof(argv[0], NULL); |
|---|
| 76 |
if (errno == ERANGE) |
|---|
| 77 |
usage(); |
|---|
| 78 |
if (brightness < 0 || brightness > 1) |
|---|
| 79 |
errexit("brightness must be between 0 and 1"); |
|---|
| 80 |
} |
|---|
| 81 |
|
|---|
| 82 |
CGDirectDisplayID display[kMaxDisplays]; |
|---|
| 83 |
CGDisplayCount numDisplays; |
|---|
| 84 |
CGDisplayErr err; |
|---|
| 85 |
err = CGGetActiveDisplayList(kMaxDisplays, display, &numDisplays); |
|---|
| 86 |
if (err != CGDisplayNoErr) |
|---|
| 87 |
errexit("cannot get list of displays (error %d)\n", err); |
|---|
| 88 |
|
|---|
| 89 |
CFWriteStreamRef stdoutStream = NULL; |
|---|
| 90 |
if (verbose) { |
|---|
| 91 |
CFURLRef devStdout = |
|---|
| 92 |
CFURLCreateWithFileSystemPath(NULL, CFSTR("/dev/stdout"), |
|---|
| 93 |
kCFURLPOSIXPathStyle, false); |
|---|
| 94 |
stdoutStream = CFWriteStreamCreateWithFile(NULL, devStdout); |
|---|
| 95 |
if (stdoutStream == NULL) |
|---|
| 96 |
errexit("cannot create CFWriteStream for /dev/stdout"); |
|---|
| 97 |
if (!CFWriteStreamOpen(stdoutStream)) |
|---|
| 98 |
errexit("cannot open CFWriteStream for /dev/stdout"); |
|---|
| 99 |
} |
|---|
| 100 |
|
|---|
| 101 |
for (CGDisplayCount i = 0; i < numDisplays; ++i) { |
|---|
| 102 |
CGDirectDisplayID dspy = display[i]; |
|---|
| 103 |
CFDictionaryRef originalMode = CGDisplayCurrentMode(dspy); |
|---|
| 104 |
if (originalMode == NULL) |
|---|
| 105 |
continue; |
|---|
| 106 |
|
|---|
| 107 |
if (action == ACTION_LIST) { |
|---|
| 108 |
printf("display %d: ", i); |
|---|
| 109 |
if (CGMainDisplayID() == dspy) |
|---|
| 110 |
printf("main display, "); |
|---|
| 111 |
printf("ID 0x%x\n", (unsigned int)dspy); |
|---|
| 112 |
if (verbose) { |
|---|
| 113 |
CFStringRef error = NULL; |
|---|
| 114 |
CFPropertyListWriteToStream(originalMode, stdoutStream, |
|---|
| 115 |
kCFPropertyListXMLFormat_v1_0, &error); |
|---|
| 116 |
if (error != NULL) |
|---|
| 117 |
errexit("failed to write display info (%s)", |
|---|
| 118 |
CFStringGetCStringPtr(error, |
|---|
| 119 |
CFStringGetFastestEncoding(error))); |
|---|
| 120 |
} |
|---|
| 121 |
} |
|---|
| 122 |
|
|---|
| 123 |
io_service_t service = CGDisplayIOServicePort(dspy); |
|---|
| 124 |
switch (action) { |
|---|
| 125 |
case ACTION_SET_ONE: |
|---|
| 126 |
if ((CGDirectDisplayID)displayToSet != dspy && displayToSet != i) |
|---|
| 127 |
continue; |
|---|
| 128 |
case ACTION_SET_ALL: |
|---|
| 129 |
err = IODisplaySetFloatParameter(service, kNilOptions, kDisplayBrightness, |
|---|
| 130 |
brightness); |
|---|
| 131 |
if (err != kIOReturnSuccess) { |
|---|
| 132 |
fprintf(stderr, |
|---|
| 133 |
"%s: failed to set brightness of display 0x%x (error %d)", |
|---|
| 134 |
APP_NAME, (unsigned int)dspy, err); |
|---|
| 135 |
continue; |
|---|
| 136 |
} |
|---|
| 137 |
if (!verbose) continue; |
|---|
| 138 |
case ACTION_LIST: |
|---|
| 139 |
err = IODisplayGetFloatParameter(service, kNilOptions, kDisplayBrightness, |
|---|
| 140 |
&brightness); |
|---|
| 141 |
if (err != kIOReturnSuccess) { |
|---|
| 142 |
fprintf(stderr, |
|---|
| 143 |
"%s: failed to get brightness of display 0x%x (error %d)", |
|---|
| 144 |
APP_NAME, (unsigned int)dspy, err); |
|---|
| 145 |
continue; |
|---|
| 146 |
} |
|---|
| 147 |
printf("display %d: brightness %f\n", i, brightness); |
|---|
| 148 |
} |
|---|
| 149 |
} |
|---|
| 150 |
|
|---|
| 151 |
return 0; |
|---|
| 152 |
} |
|---|