cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_syspower.c (5879B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../../SDL_internal.h"
     22
     23#ifndef SDL_POWER_DISABLED
     24#if SDL_POWER_MACOSX
     25
     26#include <Carbon/Carbon.h>
     27#include <IOKit/ps/IOPowerSources.h>
     28#include <IOKit/ps/IOPSKeys.h>
     29
     30#include "SDL_power.h"
     31
     32/* Carbon is so verbose... */
     33#define STRMATCH(a,b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo)
     34#define GETVAL(k,v) \
     35    CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **) v)
     36
     37/* Note that AC power sources also include a laptop battery it is charging. */
     38static void
     39checkps(CFDictionaryRef dict, SDL_bool * have_ac, SDL_bool * have_battery,
     40        SDL_bool * charging, int *seconds, int *percent)
     41{
     42    CFStringRef strval;         /* don't CFRelease() this. */
     43    CFBooleanRef bval;
     44    CFNumberRef numval;
     45    SDL_bool charge = SDL_FALSE;
     46    SDL_bool choose = SDL_FALSE;
     47    SDL_bool is_ac = SDL_FALSE;
     48    int secs = -1;
     49    int maxpct = -1;
     50    int pct = -1;
     51
     52    if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) {
     53        return;                 /* nothing to see here. */
     54    }
     55
     56    if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) {
     57        return;
     58    }
     59
     60    if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) {
     61        is_ac = *have_ac = SDL_TRUE;
     62    } else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) {
     63        return;                 /* not a battery? */
     64    }
     65
     66    if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) {
     67        charge = SDL_TRUE;
     68    }
     69
     70    if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
     71        SInt32 val = -1;
     72        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
     73        if (val > 0) {
     74            *have_battery = SDL_TRUE;
     75            maxpct = (int) val;
     76        }
     77    }
     78
     79    if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
     80        SInt32 val = -1;
     81        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
     82        if (val > 0) {
     83            *have_battery = SDL_TRUE;
     84            maxpct = (int) val;
     85        }
     86    }
     87
     88    if (GETVAL(kIOPSTimeToEmptyKey, &numval)) {
     89        SInt32 val = -1;
     90        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
     91
     92        /* Mac OS X reports 0 minutes until empty if you're plugged in. :( */
     93        if ((val == 0) && (is_ac)) {
     94            val = -1;           /* !!! FIXME: calc from timeToFull and capacity? */
     95        }
     96
     97        secs = (int) val;
     98        if (secs > 0) {
     99            secs *= 60;         /* value is in minutes, so convert to seconds. */
    100        }
    101    }
    102
    103    if (GETVAL(kIOPSCurrentCapacityKey, &numval)) {
    104        SInt32 val = -1;
    105        CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
    106        pct = (int) val;
    107    }
    108
    109    if ((pct > 0) && (maxpct > 0)) {
    110        pct = (int) ((((double) pct) / ((double) maxpct)) * 100.0);
    111    }
    112
    113    if (pct > 100) {
    114        pct = 100;
    115    }
    116
    117    /*
    118     * We pick the battery that claims to have the most minutes left.
    119     *  (failing a report of minutes, we'll take the highest percent.)
    120     */
    121    if ((secs < 0) && (*seconds < 0)) {
    122        if ((pct < 0) && (*percent < 0)) {
    123            choose = SDL_TRUE;  /* at least we know there's a battery. */
    124        }
    125        if (pct > *percent) {
    126            choose = SDL_TRUE;
    127        }
    128    } else if (secs > *seconds) {
    129        choose = SDL_TRUE;
    130    }
    131
    132    if (choose) {
    133        *seconds = secs;
    134        *percent = pct;
    135        *charging = charge;
    136    }
    137}
    138
    139#undef GETVAL
    140#undef STRMATCH
    141
    142
    143SDL_bool
    144SDL_GetPowerInfo_MacOSX(SDL_PowerState * state, int *seconds, int *percent)
    145{
    146    CFTypeRef blob = IOPSCopyPowerSourcesInfo();
    147
    148    *seconds = -1;
    149    *percent = -1;
    150    *state = SDL_POWERSTATE_UNKNOWN;
    151
    152    if (blob != NULL) {
    153        CFArrayRef list = IOPSCopyPowerSourcesList(blob);
    154        if (list != NULL) {
    155            /* don't CFRelease() the list items, or dictionaries! */
    156            SDL_bool have_ac = SDL_FALSE;
    157            SDL_bool have_battery = SDL_FALSE;
    158            SDL_bool charging = SDL_FALSE;
    159            const CFIndex total = CFArrayGetCount(list);
    160            CFIndex i;
    161            for (i = 0; i < total; i++) {
    162                CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i);
    163                CFDictionaryRef dict =
    164                    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: */