comparison 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
comparison
equal deleted inserted replaced
3169:f294338ca6eb 3170:b7a48f533966
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #ifndef SDL_POWER_DISABLED
25 #ifdef SDL_POWER_MACOSX
26
27 #include <Carbon/Carbon.h>
28 #include <IOKit/ps/IOPowerSources.h>
29 #include <IOKit/ps/IOPSKeys.h>
30
31 #include "SDL_power.h"
32
33 /* Carbon is so verbose... */
34 #define STRMATCH(a,b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo)
35 #define GETVAL(k,v) \
36 CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **) v)
37
38 /* Note that AC power sources also include a laptop battery it is charging. */
39 static void
40 checkps(CFDictionaryRef dict, SDL_bool *have_ac, SDL_bool *have_battery,
41 SDL_bool *charging, int *seconds, int *percent)
42 {
43 CFStringRef strval; /* don't CFRelease() this. */
44 CFBooleanRef bval;
45 CFNumberRef numval;
46 SDL_bool charge = SDL_FALSE;
47 SDL_bool choose = SDL_FALSE;
48 SDL_bool is_ac = SDL_FALSE;
49 int secs = -1;
50 int maxpct = -1;
51 int pct = -1;
52
53 if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) {
54 return; /* nothing to see here. */
55 }
56
57 if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) {
58 return;
59 }
60
61 if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) {
62 is_ac = *have_ac = SDL_TRUE;
63 } else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) {
64 return; /* not a battery? */
65 }
66
67 if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) {
68 charge = SDL_TRUE;
69 }
70
71 if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
72 SInt32 val = -1;
73 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
74 if (val > 0) {
75 *have_battery = SDL_TRUE;
76 maxpct = (int) val;
77 }
78 }
79
80 if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
81 SInt32 val = -1;
82 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
83 if (val > 0) {
84 *have_battery = SDL_TRUE;
85 maxpct = (int) val;
86 }
87 }
88
89 if (GETVAL(kIOPSTimeToEmptyKey, &numval)) {
90 SInt32 val = -1;
91 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
92
93 /* Mac OS X reports 0 minutes until empty if you're plugged in. :( */
94 if ((val == 0) && (is_ac)) {
95 val = -1; /* !!! FIXME: calc from timeToFull and capacity? */
96 }
97
98 secs = (int) val;
99 if (secs > 0) {
100 secs *= 60; /* value is in minutes, so convert to seconds. */
101 }
102 }
103
104 if (GETVAL(kIOPSCurrentCapacityKey, &numval)) {
105 SInt32 val = -1;
106 CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
107 pct = (int) val;
108 }
109
110 if ((pct > 0) && (maxpct > 0)) {
111 pct = (int) ((((double)pct)/((double)maxpct)) * 100.0);
112 }
113
114 if (pct > 100) {
115 pct = 100;
116 }
117
118 /*
119 * We pick the battery that claims to have the most minutes left.
120 * (failing a report of minutes, we'll take the highest percent.)
121 */
122 if ((secs < 0) && (*seconds < 0)) {
123 if ((pct < 0) && (*percent < 0)) {
124 choose = SDL_TRUE; /* at least we know there's a battery. */
125 }
126 if (pct > *percent) {
127 choose = SDL_TRUE;
128 }
129 } else if (secs > *seconds) {
130 choose = SDL_TRUE;
131 }
132
133 if (choose) {
134 *seconds = secs;
135 *percent = pct;
136 *charging = charge;
137 }
138 }
139
140 #undef GETVAL
141 #undef STRMATCH
142
143
144 SDL_bool
145 SDL_GetPowerInfo_MacOSX(SDL_PowerState *state, int *seconds, int *percent)
146 {
147 CFTypeRef blob = IOPSCopyPowerSourcesInfo();
148
149 *seconds = -1;
150 *percent = -1;
151 *state = SDL_POWERSTATE_UNKNOWN;
152
153 if (blob != NULL) {
154 CFArrayRef list = IOPSCopyPowerSourcesList(blob);
155 if (list != NULL) {
156 /* don't CFRelease() the list items, or dictionaries! */
157 SDL_bool have_ac = SDL_FALSE;
158 SDL_bool have_battery = SDL_FALSE;
159 SDL_bool charging = SDL_FALSE;
160 const CFIndex total = CFArrayGetCount(list);
161 CFIndex i;
162 for (i = 0; i < total; i++) {
163 CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i);
164 CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps);
165 if (dict != NULL) {
166 checkps(dict, &have_ac, &have_battery, &charging,
167 seconds, percent);
168 }
169 }
170
171 if (!have_battery) {
172 *state = SDL_POWERSTATE_NO_BATTERY;
173 } else if (charging) {
174 *state = SDL_POWERSTATE_CHARGING;
175 } else if (have_ac) {
176 *state = SDL_POWERSTATE_CHARGED;
177 } else {
178 *state = SDL_POWERSTATE_ON_BATTERY;
179 }
180
181 CFRelease(list);
182 }
183 CFRelease(blob);
184 }
185
186 return SDL_TRUE; /* always the definitive answer on Mac OS X. */
187 }
188
189 #endif /* SDL_POWER_MACOSX */
190 #endif /* SDL_POWER_DISABLED */
191
192 /* vi: set ts=4 sw=4 expandtab: */
193