static double getBatData() { CFTypeRef sourceInfo = IOPSCopyPowerSourcesInfo(); CFArrayRef sourceList = IOPSCopyPowerSourcesList(sourceInfo); // Loop through sources, find the first battery int count = CFArrayGetCount(sourceList); CFDictionaryRef source = NULL; for(int i=0; i < count; i++) { source = IOPSGetPowerSourceDescription(sourceInfo, CFArrayGetValueAtIndex(sourceList, i)); // Is this a battery? CFStringRef type = (CFStringRef)CFDictionaryGetValue(source, CFSTR(kIOPSTransportTypeKey)); if(kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { break; } } float percent = 0; if(source != NULL) { int curCapacity; CFNumberGetValue(CFDictionaryGetValue(source, CFSTR(kIOPSCurrentCapacityKey)), kCFNumberIntType, &curCapacity); int maxCapacity; CFNumberGetValue(CFDictionaryGetValue(source, CFSTR(kIOPSMaxCapacityKey)), kCFNumberIntType, &maxCapacity); percent = curCapacity / (float)maxCapacity*100.f; } CFRelease(sourceInfo); CFRelease(sourceList); return percent; }
/*! Copy the current power dictionary. * * Caller must release power dictionary when finished with it. */ static CFDictionaryRef copy_power_dictionary(CFTypeRef power_key) { CFTypeRef power_blob; CFDictionaryRef power_dictionary; power_blob = IOPSCopyPowerSourcesInfo(); assert(power_blob); upsdebugx(6, "%s: Got power_blob:", __func__); if(nut_debug_level >= 6) CFShow(power_blob); upsdebugx(5, "power_key = "); if(nut_debug_level >= 5) CFShow(power_key); upsdebugx(6, "end power_key"); power_dictionary = IOPSGetPowerSourceDescription(power_blob, power_key); upsdebugx(5, "Asserting 'power_dictionary': %p", power_dictionary); assert(power_dictionary); upsdebugx(5, "CFShowing 'power_dictionary'"); if(nut_debug_level >= 5) CFShow(power_dictionary); CFRetain(power_dictionary); /* Get a new power_blob next time: */ CFRelease(power_blob); return power_dictionary; }
int getPowerSource (void) // returns one of the three #defines above { int result = POWER_SOURCE_ERROR; CFTypeRef info = NULL; CFArrayRef powerSources = NULL; CFTypeRef source = NULL; CFDictionaryRef description = NULL; CFStringRef powerSourceState = NULL; info = IOPSCopyPowerSourcesInfo(); if (! info) goto ret; powerSources = IOPSCopyPowerSourcesList(info); if (! powerSources) goto ret; if (CFArrayGetCount(powerSources) == 0) goto ret; source = CFArrayGetValueAtIndex(powerSources, 0); if (! source) goto ret; description = IOPSGetPowerSourceDescription(info, source); if (! description) goto ret; powerSourceState = CFDictionaryGetValue(description, CFSTR(kIOPSPowerSourceStateKey)); if (! powerSourceState) goto ret; result = (CFStringCompare(powerSourceState, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo) ? POWER_SOURCE_AC : POWER_SOURCE_BATTERY; ret : if (info) CFRelease (info); if (powerSources) CFRelease (powerSources); //if (source) CFRelease (source); //if (description) CFRelease (description); //if (powerSourceState) CFRelease (powerSourceState); return result; }
static ACPresence chkIsOnline() { CFTypeRef sourceInfo = IOPSCopyPowerSourcesInfo(); CFArrayRef sourceList = IOPSCopyPowerSourcesList(sourceInfo); // Loop through sources, find the first battery int count = CFArrayGetCount(sourceList); CFDictionaryRef source = NULL; for(int i=0; i < count; i++) { source = IOPSGetPowerSourceDescription(sourceInfo, CFArrayGetValueAtIndex(sourceList, i)); // Is this a battery? CFStringRef type = (CFStringRef)CFDictionaryGetValue(source, CFSTR(kIOPSTransportTypeKey)); if(kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { break; } } ACPresence isOn = AC_ERROR; if(source != NULL) { CFStringRef state = CFDictionaryGetValue(source, CFSTR(kIOPSPowerSourceStateKey)); if(kCFCompareEqualTo == CFStringCompare(state, CFSTR(kIOPSACPowerValue), 0)) { isOn = AC_PRESENT; } else { isOn = AC_ABSENT; } } CFRelease(sourceInfo); CFRelease(sourceList); return isOn; }
static void get_via_io_power_sources(double *ret_charge, /* {{{ */ double *ret_current, double *ret_voltage) { CFTypeRef ps_raw; CFArrayRef ps_array; int ps_array_len; CFDictionaryRef ps_dict; CFTypeRef ps_obj; double temp_double; ps_raw = IOPSCopyPowerSourcesInfo(); ps_array = IOPSCopyPowerSourcesList(ps_raw); ps_array_len = CFArrayGetCount(ps_array); DEBUG("ps_array_len == %i", ps_array_len); for (int i = 0; i < ps_array_len; i++) { ps_obj = CFArrayGetValueAtIndex(ps_array, i); ps_dict = IOPSGetPowerSourceDescription(ps_raw, ps_obj); if (ps_dict == NULL) { DEBUG("IOPSGetPowerSourceDescription failed."); continue; } if (CFGetTypeID(ps_dict) != CFDictionaryGetTypeID()) { DEBUG("IOPSGetPowerSourceDescription did not return a CFDictionaryRef"); continue; } /* FIXME: Check if this is really an internal battery */ if (isnan(*ret_charge)) { /* This is the charge in percent. */ temp_double = dict_get_double(ps_dict, kIOPSCurrentCapacityKey); if (!isnan((temp_double)) && (temp_double >= 0.0) && (temp_double <= 100.0)) *ret_charge = temp_double; } if (isnan(*ret_current)) { temp_double = dict_get_double(ps_dict, kIOPSCurrentKey); if (!isnan(temp_double)) *ret_current = temp_double / 1000.0; } if (isnan(*ret_voltage)) { temp_double = dict_get_double(ps_dict, kIOPSVoltageKey); if (!isnan(temp_double)) *ret_voltage = temp_double / 1000.0; } } CFRelease(ps_array); CFRelease(ps_raw); } /* }}} void get_via_io_power_sources */
void CCocoaPowerSyscall::OSPowerSourceCallBack(void *refcon) { #if !defined(TARGET_DARWIN_IOS) // Called whenever any power source is added, removed, or changes. // When on battery, we get called periodically as battery level changes. CCocoaAutoPool autopool; CCocoaPowerSyscall *ctx = (CCocoaPowerSyscall*)refcon; CFTypeRef power_sources_info = IOPSCopyPowerSourcesInfo(); CFArrayRef power_sources_list = IOPSCopyPowerSourcesList(power_sources_info); for (int i = 0; i < CFArrayGetCount(power_sources_list); i++) { CFTypeRef power_source; CFDictionaryRef description; power_source = CFArrayGetValueAtIndex(power_sources_list, i); description = IOPSGetPowerSourceDescription(power_sources_info, power_source); // skip power sources that are not present (i.e. an absent second battery in a 2-battery machine) if ((CFBooleanRef)CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse) continue; if (stringsAreEqual((CFStringRef)CFDictionaryGetValue(description, CFSTR (kIOPSTransportTypeKey)), CFSTR (kIOPSInternalType))) { CFStringRef currentState = (CFStringRef)CFDictionaryGetValue(description, CFSTR (kIOPSPowerSourceStateKey)); if (stringsAreEqual (currentState, CFSTR (kIOPSACPowerValue))) { ctx->m_OnBattery = false; ctx->m_BatteryPercent = 100; ctx->m_SentBatteryMessage = false; } else if (stringsAreEqual (currentState, CFSTR (kIOPSBatteryPowerValue))) { CFNumberRef cf_number_ref; int32_t curCapacity, maxCapacity; cf_number_ref = (CFNumberRef)CFDictionaryGetValue(description, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue(cf_number_ref, kCFNumberSInt32Type, &curCapacity); cf_number_ref = (CFNumberRef)CFDictionaryGetValue(description, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue(cf_number_ref, kCFNumberSInt32Type, &maxCapacity); ctx->m_OnBattery = true; ctx->m_BatteryPercent = (int)((double)curCapacity/(double)maxCapacity * 100); } } } CFRelease(power_sources_list); CFRelease(power_sources_info); #endif }
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. */ }
// CODE CHUNK IMPORTED FROM SDL 2.0 bool power_osx::GetPowerInfo_MacOSX() { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); nsecs_left = -1; percent_left = -1; power_state = OS::POWERSTATE_UNKNOWN; if (blob != NULL) { CFArrayRef list = IOPSCopyPowerSourcesList(blob); if (list != NULL) { /* don't CFRelease() the list items, or dictionaries! */ 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); } } if (!have_battery) { power_state = OS::POWERSTATE_NO_BATTERY; } else if (charging) { power_state = OS::POWERSTATE_CHARGING; } else if (have_ac) { power_state = OS::POWERSTATE_CHARGED; } else { power_state = OS::POWERSTATE_ON_BATTERY; } CFRelease(list); } CFRelease(blob); } return true; /* always the definitive answer on Mac OS X. */ }
/* IOPSCopyUPSArray * * Argument: * CFTypeRef power_sources: The return value from IOPSCoyPowerSourcesInfo() * Return value: * CFArrayRef: all the UPS's we found * NULL if none are found */ CFArrayRef IOPSCopyUPSArray(CFTypeRef power_sources) { CFArrayRef array = isA_CFArray(IOPSCopyPowerSourcesList(power_sources)); CFMutableArrayRef ret_arr; CFTypeRef name = NULL; CFDictionaryRef ps; CFStringRef transport_type; int i, count; if(!array) return NULL; count = CFArrayGetCount(array); name = NULL; ret_arr = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); if(!ret_arr) goto exit; // Iterate through power_sources for(i=0; i<count; i++) { name = CFArrayGetValueAtIndex(array, i); ps = isA_CFDictionary(IOPSGetPowerSourceDescription(power_sources, name)); if(ps) { transport_type = isA_CFString(CFDictionaryGetValue(ps, CFSTR(kIOPSTransportTypeKey))); if(transport_type && ( CFEqual(transport_type, CFSTR(kIOPSSerialTransportType)) || CFEqual(transport_type, CFSTR(kIOPSUSBTransportType)) || CFEqual(transport_type, CFSTR(kIOPSNetworkTransportType)) ) ) { CFArrayAppendValue(ret_arr, name); } } } if(0 == CFArrayGetCount(ret_arr)) { CFRelease(ret_arr); ret_arr = NULL; } exit: CFRelease(array); return ret_arr; }
bool CScreensaver::Host_is_running_on_batteries() { CFDictionaryRef pSource = NULL; CFStringRef psState; int i; bool retval = false; CFTypeRef blob = IOPSCopyPowerSourcesInfo(); CFArrayRef list = IOPSCopyPowerSourcesList(blob); for (i=0; i<CFArrayGetCount(list); i++) { pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(list, i)); if(!pSource) break; psState = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey)); if(!CFStringCompare(psState,CFSTR(kIOPSBatteryPowerValue),0)) retval = true; } CFRelease(blob); CFRelease(list); return retval; }
/* PSLowPowerPSChange * * Is the handler that gets notified when power source (battery or UPS) * state changes. We might respond to this by posting a user notification * or performing emergency shutdown. */ __private_extern__ void PSLowPowerPSChange(CFTypeRef ps_blob) { CFTypeRef ups = NULL; CFDictionaryRef ups_info = 0; int t1, t2; CFNumberRef n1, n2; int minutes_remaining; int percent_remaining; CFBooleanRef isPresent; static int last_ups_power_source = _kIOUPSExternalPowerBit; CFStringRef power_source = 0; CFNumberRef ups_id = 0; // Bail immediately if another application (like APC's PowerChute) // is managing emergency UPS shutdown if(!_weManageUPSPower()) { goto _exit_PowerSourcesHaveChanged_; } // *** Inspect UPS power levels // We assume we're only dealing with 1 UPS for simplicity. // The "more than one UPS attached " case is undefined. if((ups = IOPSGetActiveUPS(ps_blob))) { ups_info = isA_CFDictionary(IOPSGetPowerSourceDescription(ps_blob, ups)); if(!ups_info) goto _exit_PowerSourcesHaveChanged_; ups_id = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSPowerSourceIDKey))); if(!ups_id) goto _exit_PowerSourcesHaveChanged_; // Check UPS "Is Present" key isPresent = isA_CFBoolean(CFDictionaryGetValue(ups_info, CFSTR(kIOPSIsPresentKey))); if(!isPresent || !CFBooleanGetValue(isPresent)) { #if HAVE_CF_USER_NOTIFICATION if(_UPSAlert) { CFUserNotificationCancel(_UPSAlert); _UPSAlert = 0; } #endif // If UPS isn't active or connected we shouldn't base policy decisions on it goto _exit_PowerSourcesHaveChanged_; } // Check Power Source power_source = isA_CFString(CFDictionaryGetValue(ups_info, CFSTR(kIOPSPowerSourceStateKey))); if(!power_source || !CFEqual(power_source, CFSTR(kIOPSBatteryPowerValue))) { #if HAVE_CF_USER_NOTIFICATION // Running off of AC Power if(_UPSAlert) { CFUserNotificationCancel(_UPSAlert); _UPSAlert = 0; } #endif // we have to be draining the internal battery to do a shutdown, so we'll just exit from here. goto _exit_PowerSourcesHaveChanged_; } // UPS is running off of internal battery power. Show warning if we just switched from AC to battery. if(_kIOUPSExternalPowerBit == last_ups_power_source) { _switchedToUPSPowerTime = CFAbsoluteTimeGetCurrent(); if( _thresh->haltafter[kHaltEnabled] ) { // If there's a "shutdown after X minutes on UPS power" threshold, // set a timer to remind us to check UPS state again after X minutes _reEvaluatePowerSourcesLater(5 + (60*_thresh->haltafter[kHaltValue])); } #if HAVE_CF_USER_NOTIFICATION if(!_UPSAlert) _UPSAlert = _copyUPSWarning(); #endif } // TODO: switch this battery-present check for the IOKit // private API IOPMSystemSupportsUPSShutdown // Is an internal battery present? if(kCFBooleanTrue == IOPSPowerSourceSupported(ps_blob, CFSTR(kIOPMBatteryPowerKey))) { // Do not do UPS shutdown if internal battery is present. // Internal battery may still be providing power. // Don't do any further UPS shutdown processing. // PMU will cause an emergency sleep when the battery runs out - we fall back on that // in the battery case. goto _exit_PowerSourcesHaveChanged_; } // ****** // ****** Perform emergency shutdown if any of the shutdown thresholds is true // Check to make sure that the UPS has been on battery power for a full 10 seconds before initiating a shutdown. // Certain UPS's have reported transient "on battery power with 0% capacity remaining" states for 3-5 seconds. // So we make sure not to heed this shutdown notice unless we've been on battery power for 10 seconds. if(_secondsSpentOnUPSPower() < 10) { _reEvaluatePowerSourcesLater(10); goto _exit_PowerSourcesHaveChanged_; } // Calculate battery percentage remaining n1 = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSCurrentCapacityKey))); n2 = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSMaxCapacityKey))); if(n1 && n2) { if( CFNumberGetValue(n1, kCFNumberIntType, &t1) && CFNumberGetValue(n2, kCFNumberIntType, &t2)) { percent_remaining = (int)(100.0* ((double)t1) / ((double)t2) ); if( _thresh->haltpercent[kHaltEnabled] ) { if( percent_remaining <= _thresh->haltpercent[kHaltValue] ) { _doPowerEmergencyShutdown(ups_id); } } } } // Get UPS's estimated time remaining n1 = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSTimeToEmptyKey))); if(n1) { if(CFNumberGetValue(n1, kCFNumberIntType, &minutes_remaining)) { if( _thresh->haltremain[kHaltEnabled] ) { if( minutes_remaining <= _thresh->haltremain[kHaltValue] ) { _doPowerEmergencyShutdown(ups_id); } } } } // Determine how long we've been running on UPS power if( _thresh->haltafter[kHaltEnabled] ) { if(_minutesSpentOnUPSPower() >= _thresh->haltafter[kHaltValue]) { _doPowerEmergencyShutdown(ups_id); } } } else { // No "active UPS" detected. // One could have just disappeared - if we're showing an alert, clear it. #if HAVE_CF_USER_NOTIFICATION if(_UPSAlert) { CFUserNotificationCancel(_UPSAlert); _UPSAlert = 0; } #endif } // exit point _exit_PowerSourcesHaveChanged_: if(power_source && CFEqual(power_source, CFSTR(kIOPSBatteryPowerValue))) { last_ups_power_source = _kIOUPSInternalPowerBit; } else { last_ups_power_source = _kIOUPSExternalPowerBit; } return; }
PowerInfo GetPowerState() { PowerInfo info; info.state = PowerInfo::STATE_UNKNOWN; info.seconds = 0; info.percent = 0.0f; #if defined(TARGET_OSX) CFTypeRef blob = IOPSCopyPowerSourcesInfo(); if (blob != NULL) { CFArrayRef list = IOPSCopyPowerSourcesList(blob); if (list != NULL) { /* don't CFRelease() the list items, or dictionaries! */ 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, &info.seconds, &info.percent); } } if (!have_battery) { info.state = PowerInfo::STATE_NO_BATTERY; } else if (charging) { info.state = PowerInfo::STATE_CHARGING; } else if (have_ac) { info.state = PowerInfo::STATE_CHARGED; } else { info.state = PowerInfo::STATE_ON_BATTERY; } CFRelease(list); } CFRelease(blob); } #elif defined(TARGET_LINUX) #else #endif return info; }
int OnBattery (void) { #if defined (__APPLE__) /* The following copyright applies to the battery detection code below. I did modify */ /* substantially as it did far more than I needed. */ /* Copyright (c) 2003 Thomas Runge ([email protected]) * Mach and Darwin specific code is Copyright (c) 2006 Eric Pooch ([email protected]) * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ CFTypeRef blob = IOPSCopyPowerSourcesInfo(); CFArrayRef sources = IOPSCopyPowerSourcesList(blob); int i, acstat; CFDictionaryRef pSource = NULL; const void *psValue; acstat = TRUE; for(i = 0; i < CFArrayGetCount(sources); i++) { pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i)); if(!pSource) break; psValue = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey)); if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsPresentKey), &psValue) && (CFBooleanGetValue(psValue) > 0)) { psValue = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey)); if (CFStringCompare(psValue,CFSTR(kIOPSBatteryPowerValue),0)==kCFCompareEqualTo) { /* We are running on a battery power source. */ acstat = FALSE; } } } CFRelease(blob); CFRelease(sources); return(!acstat); #elif defined (__linux__) FILE *fd; char buf[180]; int ac_state; ac_state = -1; fd = fopen ("/proc/acpi/battery/BAT0/state", "r"); if (fd != NULL) { while (fgets (buf, sizeof (buf), fd) != NULL) { char *p; p = strstr (buf, "charging state:"); if (p == NULL) continue; if (strstr (p+14, "discharging") != NULL) ac_state = 0; else if (strstr (p+14, "charging") != NULL) ac_state = 1; else if (strstr (p+14, "charged") != NULL) ac_state = 1; } fclose (fd); } return (ac_state == 0); #else return (FALSE); /* Assume we're on AC power */ #endif }
int machine_get_battstat(int *acstat, int *battflag, int *percent) { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); CFArrayRef sources = IOPSCopyPowerSourcesList(blob); int i; CFDictionaryRef pSource = NULL; const void *psValue; *acstat = LCDP_AC_ON; *battflag = LCDP_BATT_ABSENT; *percent = 100; if (CFArrayGetCount(sources) == 0) return (FALSE); for (i = 0; i < CFArrayGetCount(sources); i++) { pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i)); if (!pSource) break; psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey)); if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsPresentKey), &psValue) && (CFBooleanGetValue(psValue) > 0)) { psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey)); if (CFStringCompare(psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo) { /* We are running on a battery power source. */ *battflag = LCDP_BATT_UNKNOWN; *acstat = LCDP_AC_OFF; } else if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsChargingKey), &psValue)) { /* * We are running on an AC power source, but * we also have a battery power source * present. */ if (CFBooleanGetValue(psValue) > 0) *battflag = LCDP_BATT_CHARGING; else *battflag = LCDP_BATT_UNKNOWN; } if (*battflag != LCDP_BATT_ABSENT) { int curCapacity = 0; int maxCapacity = 0; psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue(psValue, kCFNumberSInt32Type, &curCapacity); psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue(psValue, kCFNumberSInt32Type, &maxCapacity); *percent = (int)((double)curCapacity / (double)maxCapacity * 100); /* * There is a way to check this through the * IOKit, but I am not sure what gets * returned for kIOPSLowWarnLevelKey and * kIOPSDeadWarnLevelKey, and this is easier. */ if (*battflag == LCDP_BATT_UNKNOWN) { if (*percent > 50) *battflag = LCDP_BATT_HIGH; else if (*percent > 2) *battflag = LCDP_BATT_LOW; else *battflag = LCDP_BATT_CRITICAL; } /* printf ("powerSource %d of %d: percent: %d/%d %d\n", i, CFArrayGetCount(sources), curCapacity, maxCapacity, *percent);*/ } } } CFRelease(blob); CFRelease(sources); return (TRUE); }
static void darwin_check(void) { const void *values; int device_num, device_count; int currentval = 0, maxval = 0; char buf[4096]; CFTypeRef blob; CFArrayRef sources; CFDictionaryRef device_dict; time_left = -1; battery_full = -1; have_battery = 0; have_power = 0; /* Retrieve the power source data and the array of sources. */ blob = IOPSCopyPowerSourcesInfo(); sources = IOPSCopyPowerSourcesList(blob); device_count = CFArrayGetCount(sources); for (device_num = 0; device_num < device_count; device_num++) { CFTypeRef ps; /* Retrieve a dictionary of values for this device and the count of keys in the dictionary. */ ps = CFArrayGetValueAtIndex(sources, device_num); device_dict = IOPSGetPowerSourceDescription(blob, ps); /* Retrieve the charging key and save the present charging value if one exists. */ if (CFDictionaryGetValueIfPresent(device_dict, CFSTR(kIOPSIsChargingKey), &values)) { have_battery = 1; if (CFBooleanGetValue(values) > 0) have_power = 1; break; } } if (!have_battery) { CFRelease(sources); CFRelease(blob); have_power = 1; return; } /* Retrieve the current capacity key. */ values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); /* Retrieve the max capacity key. */ values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue(values, kCFNumberSInt32Type, &maxval); /* Calculate the percentage charged. */ battery_full = (currentval * 100) / maxval; /* Retrieve the remaining battery power or time until charged in minutes. */ if (!have_power) { values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey)); CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); time_left = currentval * 60; } else { values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey)); CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); time_left = currentval * 60; } CFRelease(sources); CFRelease(blob); }
void HostPowerServiceDarwin::checkBatteryCriticalLevel(bool *pfCriticalChanged) { CFTypeRef pBlob = IOPSCopyPowerSourcesInfo(); CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob); CFDictionaryRef pSource = NULL; const void *psValue; bool result; int powerSource = POWER_SOURCE_OUTLET; bool critical = false; if (CFArrayGetCount(pSources) > 0) { for (int i = 0; i < CFArrayGetCount(pSources); ++i) { pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i)); /* If the source is empty skip over to the next one. */ if (!pSource) continue; /* Skip all power sources which are currently not present like a * second battery. */ if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse) continue; /* Only internal power types are of interest. */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue); if (result && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo) { /* First check which power source we are connect on. */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue); if (result && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo) powerSource = POWER_SOURCE_OUTLET; else if (result && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo) powerSource = POWER_SOURCE_BATTERY; int curCapacity = 0; int maxCapacity = 1; float remCapacity = 0.0f; /* Fetch the current capacity value of the power source */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSCurrentCapacityKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity); /* Fetch the maximum capacity value of the power source */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSMaxCapacityKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity); /* Calculate the remaining capacity in percent */ remCapacity = ((float)curCapacity/(float)maxCapacity * 100.0); /* Check for critical. 5 percent is default. */ int criticalValue = 5; result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue); critical = (remCapacity < criticalValue); /* We have to take action only if we are on battery, the * previous state wasn't critical, the state has changed & the * user requested that info. */ if (powerSource == POWER_SOURCE_BATTERY && mCritical == false && mCritical != critical && pfCriticalChanged) *pfCriticalChanged = true; Log(("checkBatteryCriticalLevel: Remains: %d.%d%% Critical: %d Critical State Changed: %d\n", (int)remCapacity, (int)(remCapacity * 10) % 10, critical, pfCriticalChanged?*pfCriticalChanged:-1)); } } } /* Save the new state */ mCritical = critical; CFRelease(pBlob); CFRelease(pSources); }
static void powerSourceChanged(void *context) { #pragma unused(context) CFTypeRef powerBlob = IOPSCopyPowerSourcesInfo(); CFArrayRef powerSourcesList = IOPSCopyPowerSourcesList(powerBlob); CFIndex count = CFArrayGetCount(powerSourcesList); for (CFIndex i = 0; i < count; ++i) { CFTypeRef powerSource; CFDictionaryRef description; HGPowerSource hgPowerSource; CFBooleanRef charging = kCFBooleanFalse; CFIndex batteryTime = -1; CFIndex percentageCapacity = -1; powerSource = CFArrayGetValueAtIndex(powerSourcesList, i); description = IOPSGetPowerSourceDescription(powerBlob, powerSource); //Don't display anything for power sources that aren't present (i.e. an absent second battery in a 2-battery machine) if (CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse) continue; //We only know how to handle internal (battery, a/c power) transport types. The other values indicate UPS usage. if (stringsAreEqual(CFDictionaryGetValue(description, CFSTR(kIOPSTransportTypeKey)), CFSTR(kIOPSInternalType))) { CFStringRef currentState = CFDictionaryGetValue(description, CFSTR(kIOPSPowerSourceStateKey)); if (stringsAreEqual(currentState, CFSTR(kIOPSACPowerValue))) hgPowerSource = HGACPower; else if (stringsAreEqual(currentState, CFSTR(kIOPSBatteryPowerValue))) hgPowerSource = HGBatteryPower; else hgPowerSource = HGUnknownPower; //Battery power if (CFDictionaryGetValue(description, CFSTR(kIOPSIsChargingKey)) == kCFBooleanTrue) { //Charging charging = kCFBooleanTrue; CFNumberRef timeToChargeNum = CFDictionaryGetValue(description, CFSTR(kIOPSTimeToFullChargeKey)); CFIndex timeToCharge; if (CFNumberGetValue(timeToChargeNum, kCFNumberCFIndexType, &timeToCharge)) batteryTime = timeToCharge; } else { //Not charging charging = kCFBooleanFalse; CFNumberRef timeToEmptyNum = CFDictionaryGetValue(description, CFSTR(kIOPSTimeToEmptyKey)); CFIndex timeToEmpty; if (CFNumberGetValue(timeToEmptyNum, kCFNumberCFIndexType, &timeToEmpty)) batteryTime = timeToEmpty; } /* Capacity */ CFNumberRef currentCapacityNum = CFDictionaryGetValue(description, CFSTR(kIOPSCurrentCapacityKey)); CFNumberRef maxCapacityNum = CFDictionaryGetValue(description, CFSTR(kIOPSMaxCapacityKey)); CFIndex currentCapacity, maxCapacity; if (CFNumberGetValue(currentCapacityNum, kCFNumberCFIndexType, ¤tCapacity) && CFNumberGetValue(maxCapacityNum, kCFNumberCFIndexType, &maxCapacity)) percentageCapacity = roundf((currentCapacity / (float)maxCapacity) * 100.0f); } else { //UPS power hgPowerSource = HGUPSPower; } //Avoid sending notifications on the same power source multiple times, unless the charging state or presence/absence of a time estimate has changed. if (lastPowerSource != hgPowerSource || lastChargingState != charging || (lastBatteryTime == -1) != (batteryTime == -1)) { lastPowerSource = hgPowerSource; lastChargingState = charging; lastBatteryTime = batteryTime; AppController_powerSwitched(hgPowerSource, charging, batteryTime, percentageCapacity); } } CFRelease(powerSourcesList); CFRelease(powerBlob); }