#include "SDL_internal.h"
#ifndef SDL_POWER_DISABLED
#ifdef SDL_POWER_MACOSX
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
#define STRMATCH(a, b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo)
#define GETVAL(k, v) \
CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **)v)
static void checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery,
bool *charging, int *seconds, int *percent)
{
CFStringRef strval; CFBooleanRef bval;
CFNumberRef numval;
bool charge = false;
bool choose = false;
bool is_ac = false;
int secs = -1;
int maxpct = -1;
int pct = -1;
if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) {
return; }
if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) {
return;
}
if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) {
is_ac = *have_ac = true;
} else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) {
return; }
if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) {
charge = true;
}
if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
SInt32 val = -1;
CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
if (val > 0) {
*have_battery = true;
maxpct = (int)val;
}
}
if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
SInt32 val = -1;
CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
if (val > 0) {
*have_battery = true;
maxpct = (int)val;
}
}
if (GETVAL(kIOPSTimeToEmptyKey, &numval)) {
SInt32 val = -1;
CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
if ((val == 0) && (is_ac)) {
val = -1; }
secs = (int)val;
if (secs > 0) {
secs *= 60; }
}
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;
}
if ((secs < 0) && (*seconds < 0)) {
if ((pct < 0) && (*percent < 0)) {
choose = true; }
if (pct > *percent) {
choose = true;
}
} else if (secs > *seconds) {
choose = true;
}
if (choose) {
*seconds = secs;
*percent = pct;
*charging = charge;
}
}
#undef GETVAL
#undef STRMATCH
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) {
bool have_ac = false;
bool have_battery = false;
bool charging = 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 true; }
#endif #endif