Index: trunk/LocationDo/brightness.m
===================================================================
--- trunk/LocationDo/brightness.m	(revision 547)
+++ trunk/LocationDo/brightness.m	(revision 548)
@@ -1,5 +1,6 @@
-/* gcc -o brightness -framework Cocoa -framework DisplayServices -F/System/Library/PrivateFrameworks brightness.m */
+/* gcc -std=c99 -o brightness -framework Cocoa -framework DisplayServices -F/System/Library/PrivateFrameworks brightness.m */
 
 #import <Foundation/Foundation.h>
+#include <crt_externs.h>
 
 @interface O3Manager : NSObject
@@ -20,46 +21,118 @@
 const int kMaxDisplays = 16;
 
-int main(int argc, const char *argv[])
-{
-  CGDirectDisplayID display[kMaxDisplays];
-  CGDisplayCount numDisplays;
-  CGDisplayCount i;
-  CGDisplayErr err;
+#define APP_NAME *(_NSGetProgname())
+
+void errexit(const char *fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  fprintf(stderr, "%s: ", APP_NAME);
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, "\n");
+  exit(1);
+}
+
+void usage() {
+  fprintf(stderr, "usage: %s [-m|-d display] [-v] <brightness>\n", APP_NAME);
+  fprintf(stderr, "   or: %s -l [-v]\n", APP_NAME);
+  exit(1);
+}
+
+int main(int argc, char * const argv[]) {
+  if (argc == 1)
+    usage();
   
+  BOOL verbose = NO;
+  unsigned long displayToSet = 0;
+  enum { ACTION_LIST, ACTION_SET_ALL, ACTION_SET_ONE } action = ACTION_SET_ALL;
+  extern char *optarg;
+  extern int optind;
+  int ch;
+
+  while ( (ch = getopt(argc, argv, "lmvd:")) != -1) {
+    switch (ch) {
+    case 'l':
+      if (action == ACTION_SET_ONE) usage();
+      action = ACTION_LIST;
+      break;
+    case 'v':
+      verbose = YES;
+      break;
+    case 'm':
+      if (action != ACTION_SET_ALL) usage();
+      action = ACTION_SET_ONE;
+      displayToSet = (unsigned long)CGMainDisplayID();
+      break;
+    case 'd':
+      if (action != ACTION_SET_ALL) usage();
+      action = ACTION_SET_ONE;
+      errno = 0;
+      displayToSet = strtoul(optarg, NULL, 0);
+      if (errno == EINVAL || errno == ERANGE)
+	errexit("display must be an integer index (0) or a hexadecimal ID (0x4270a80)");
+      break;
+    default: usage();
+    }
+  }
+  
+  argc -= optind;
+  argv += optind;
+
+  float brightness;
+  if (action == ACTION_LIST) {
+    if (argc > 0) usage();
+  } else {
+    if (argc != 1) usage();
+
+    errno = 0;
+    brightness = strtof(argv[0], NULL);
+    if (errno == ERANGE)
+      usage();
+    if (brightness < 0 || brightness > 1)
+      errexit("brightness must be between 0 and 1");
+  }
+
   [[NSAutoreleasePool alloc] init];
   [O3Manager initialize];
 
+  CGDirectDisplayID display[kMaxDisplays];
+  CGDisplayCount numDisplays;
+  CGDisplayErr err;
   err = CGGetActiveDisplayList(kMaxDisplays, display, &numDisplays);
-  if (err != CGDisplayNoErr) {
-      NSLog(@"Cannot get displays (%d)", err);
-      exit(1);
-  }
-  printf("%d displays found", (int)numDisplays);
-  for ( i = 0; i < numDisplays; ++i ) {
-      CGDirectDisplayID dspy = display[i];
-      CFDictionaryRef originalMode;
+  if (err != CGDisplayNoErr)
+    errexit("cannot get list of displays (error %d)\n", err);
 
-      originalMode = CGDisplayCurrentMode(dspy);
-      if (originalMode == NULL)
-	continue;
+  for (CGDisplayCount i = 0; i < numDisplays; ++i) {
+    CGDirectDisplayID dspy = display[i];
+    CFDictionaryRef originalMode = CGDisplayCurrentMode(dspy);
+    if (originalMode == NULL)
+      continue;
 
-      NSLog(@"Display 0x%x: %@", (unsigned int)dspy, originalMode);
-
-      if ([[(NSDictionary *)originalMode objectForKey: @"RefreshRate"] intValue] == 0) {
-	id<BrightnessEngineWireProtocol> engine =
-	  [O3Manager engineOfClass: @"BrightnessEngine" forDisplayID: dspy];
-	NSLog(@"Engine: %@", engine);
-	NSLog(@"Brightness was %f", [engine brightness]);
-	if (argc == 2) {
-	  float newBrightness = [[NSString stringWithCString: argv[1]] floatValue];
-	  if (newBrightness < 0. || newBrightness > 1.) {
-	    NSLog(@"Brightness should be between 0 and 1");
-	    exit(1);
-	  }
-	  [engine setBrightness: newBrightness];
-	  NSLog(@"Brightness is now %f", [engine brightness]);
-	}
+    if (action == ACTION_LIST) {
+      printf("display %d: ", i);
+      if (CGMainDisplayID() == dspy)
+	printf("main display, ");
+      printf("ID 0x%x\n", (unsigned int)dspy);
+      if (verbose) {
+        puts([[(NSDictionary *)originalMode description] UTF8String]);
       }
     }
-  exit(0);
+
+    if ([[(NSDictionary *)originalMode objectForKey: @"RefreshRate"] intValue] != 0)
+      continue;
+
+    id<BrightnessEngineWireProtocol> engine =
+      [O3Manager engineOfClass: @"BrightnessEngine" forDisplayID: dspy];
+
+    switch (action) {
+    case ACTION_SET_ONE:
+      if ((CGDirectDisplayID)displayToSet != dspy && displayToSet != i)
+	continue;
+    case ACTION_SET_ALL:
+      [engine setBrightness: brightness];
+      if (!verbose) continue;
+    case ACTION_LIST:
+      printf("display %d: brightness %f\n", i, [engine brightness]);
+    }
+  }
+  return 0;
 }
