diff src/power/macosx/SDL_syspower.c @ 3170:b7a48f533966

Initial work on power subsystem for SDL 1.3.
author Ryan C. Gordon <icculus@icculus.org>
date Sun, 07 Jun 2009 06:06:35 +0000
parents
children 51750b7a966f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/power/macosx/SDL_syspower.c	Sun Jun 07 06:06:35 2009 +0000
@@ -0,0 +1,193 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#ifndef SDL_POWER_DISABLED
+#ifdef SDL_POWER_MACOSX
+
+#include <Carbon/Carbon.h>
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/ps/IOPSKeys.h>
+
+#include "SDL_power.h"
+
+/* Carbon is so verbose... */
+#define STRMATCH(a,b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo)
+#define GETVAL(k,v) \
+    CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **) v)
+
+/* Note that AC power sources also include a laptop battery it is charging. */
+static void
+checkps(CFDictionaryRef dict, SDL_bool *have_ac, SDL_bool *have_battery,
+        SDL_bool *charging, int *seconds, int *percent)
+{
+    CFStringRef strval;  /* don't CFRelease() this. */
+    CFBooleanRef bval;
+    CFNumberRef numval;
+    SDL_bool charge = SDL_FALSE;
+    SDL_bool choose = SDL_FALSE;
+    SDL_bool is_ac = SDL_FALSE;
+    int secs = -1;
+    int maxpct = -1;
+    int pct = -1;
+
+    if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) {
+        return;  /* nothing to see here. */
+    }
+
+    if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) {
+        return;
+    }
+
+    if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) {
+        is_ac = *have_ac = SDL_TRUE;
+    } else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) {
+        return;  /* not a battery? */
+    }
+
+    if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) {
+        charge = SDL_TRUE;
+    }
+
+    if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
+        SInt32 val = -1;
+        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+        if (val > 0) {
+            *have_battery = SDL_TRUE;
+            maxpct = (int) val;
+        }
+    }
+
+    if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
+        SInt32 val = -1;
+        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+        if (val > 0) {
+            *have_battery = SDL_TRUE;
+            maxpct = (int) val;
+        }
+    }
+
+    if (GETVAL(kIOPSTimeToEmptyKey, &numval)) {
+        SInt32 val = -1;
+        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+
+        /* Mac OS X reports 0 minutes until empty if you're plugged in. :( */
+        if ((val == 0) && (is_ac)) {
+            val = -1;  /* !!! FIXME: calc from timeToFull and capacity? */
+        }
+
+        secs = (int) val;
+        if (secs > 0) {
+            secs *= 60;  /* value is in minutes, so convert to seconds. */
+        }
+    }
+
+    if (GETVAL(kIOPSCurrentCapacityKey, &numval)) {
+        SInt32 val = -1;
+        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+        pct = (int) val;
+    }
+
+    if ((pct > 0) && (maxpct > 0)) {
+    	pct = (int) ((((double)pct)/((double)maxpct)) * 100.0);
+    }
+
+    if (pct > 100) {
+        pct = 100;
+    }
+
+    /*
+     * We pick the battery that claims to have the most minutes left.
+     *  (failing a report of minutes, we'll take the highest percent.)
+     */
+    if ((secs < 0) && (*seconds < 0)) {
+        if ((pct < 0) && (*percent < 0)) {
+            choose = SDL_TRUE; /* at least we know there's a battery. */
+        }
+        if (pct > *percent) {
+            choose = SDL_TRUE;
+        }
+    } else if (secs > *seconds) {
+        choose = SDL_TRUE;
+    }
+
+    if (choose) {
+        *seconds = secs;
+        *percent = pct;
+        *charging = charge;
+    }
+}
+
+#undef GETVAL
+#undef STRMATCH
+
+
+SDL_bool
+SDL_GetPowerInfo_MacOSX(SDL_PowerState *state, int *seconds, int *percent)
+{
+    CFTypeRef blob = IOPSCopyPowerSourcesInfo();
+
+    *seconds = -1;
+    *percent = -1;
+    *state = SDL_POWERSTATE_UNKNOWN;
+
+    if (blob != NULL) {
+        CFArrayRef list = IOPSCopyPowerSourcesList(blob);
+        if (list != NULL) {
+            /* don't CFRelease() the list items, or dictionaries! */
+            SDL_bool have_ac = SDL_FALSE;
+            SDL_bool have_battery = SDL_FALSE;
+            SDL_bool charging = SDL_FALSE;
+            const CFIndex total = CFArrayGetCount(list);
+            CFIndex i;
+            for (i = 0; i < total; i++) {
+                CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i);
+                CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps);
+                if (dict != NULL) {
+                    checkps(dict, &have_ac, &have_battery, &charging,
+                            seconds, percent);
+                }
+            }
+
+            if (!have_battery) {
+                *state = SDL_POWERSTATE_NO_BATTERY;
+            } else if (charging) {
+                *state = SDL_POWERSTATE_CHARGING;
+            } else if (have_ac) {
+                *state = SDL_POWERSTATE_CHARGED;
+            } else {
+                *state = SDL_POWERSTATE_ON_BATTERY;
+            }
+
+            CFRelease(list);
+        }
+        CFRelease(blob);
+    }
+
+    return SDL_TRUE;  /* always the definitive answer on Mac OS X. */
+}
+
+#endif /* SDL_POWER_MACOSX */
+#endif /* SDL_POWER_DISABLED */
+
+/* vi: set ts=4 sw=4 expandtab: */
+