CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/Battery/AppleBatteryClient.m
Views: 1401
//1// AppleBatteryClient.m2// PPSSPP3//4// Created by Serena on 24/01/2023.5//67#include "Battery.h"8#import <Foundation/Foundation.h>910#if PPSSPP_PLATFORM(MAC)11#include <IOKit/ps/IOPSKeys.h>12#include <IOKit/ps/IOPowerSources.h>13#elif PPSSPP_PLATFORM(IOS)14#import <UIKit/UIKit.h>15#endif1617@interface AppleBatteryClient : NSObject18+(instancetype)sharedClient;19-(void)setNeedsToUpdateLevel;20@property int batteryLevel;21@end2223void _powerSourceRunLoopCallback(void * __unused ctx) {24// IOKit has told us that battery information has changed, now update the batteryLevel var25[[AppleBatteryClient sharedClient] setNeedsToUpdateLevel];26}2728// You may ask,29// "Why an entire class?30// Why not just call the UIDevice/IOKitPowerSource functions every time getCurrentBatteryCapacity() is called?"31// Well, calling the UIDevice/IOKitPowerSource functions very frequently (every second, it seems?) is expensive32// So, instead, I made a class with a cached batteryLevel property33// that only gets set when it needs to.34@implementation AppleBatteryClient3536+ (instancetype)sharedClient {37static AppleBatteryClient *client;38static dispatch_once_t onceToken;39dispatch_once(&onceToken, ^{40client = [AppleBatteryClient new];41[client initialSetup];42[client setNeedsToUpdateLevel];43});4445return client;46}4748-(void)initialSetup {49#if TARGET_OS_IOS50// on iOS, this needs to be true to get the battery level51// and it needs to be set just once, so do it here52UIDevice.currentDevice.batteryMonitoringEnabled = YES;53// Register for when the battery % changes54[[NSNotificationCenter defaultCenter] addObserver:self55selector:@selector(setNeedsToUpdateLevel)56name:UIDeviceBatteryLevelDidChangeNotification object:nil];5758#elif TARGET_OS_MAC59CFRunLoopSourceRef loop = IOPSNotificationCreateRunLoopSource(_powerSourceRunLoopCallback, nil);60CFRunLoopAddSource(CFRunLoopGetMain(), loop, kCFRunLoopDefaultMode);61#endif62}6364- (void)setNeedsToUpdateLevel {65#if TARGET_OS_IOS66// `-[UIDevice batteryLevel]` returns the % like '0.(actual %)' (ie, 0.28 when the battery is 28%)67// so multiply it by 100 to get a visually appropriate version68self.batteryLevel = [[UIDevice currentDevice] batteryLevel] * 100;69#elif TARGET_OS_MAC70CFTypeRef snapshot = IOPSCopyPowerSourcesInfo();71NSArray *sourceList = (__bridge NSArray *)IOPSCopyPowerSourcesList(snapshot);72if (!sourceList) {73if (snapshot) CFRelease(snapshot);74return;75}7677for (NSDictionary *source in sourceList) {78// kIOPSCurrentCapacityKey = battery level79NSNumber *currentCapacity = [source objectForKey:@(kIOPSCurrentCapacityKey)];80if (currentCapacity) {81// we found what we want82self.batteryLevel = currentCapacity.intValue;83break;84}85}86CFRelease(snapshot);87#endif88}8990@end919293int getCurrentBatteryCapacity() {94return [[AppleBatteryClient sharedClient] batteryLevel];95}969798