aboutsummaryrefslogtreecommitdiff
path: root/src/common/device_power_state.cpp
blob: 2dfa7dc305e5c4dc2c898c175fcbbda1b56acbe5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

#include "device_power_state.h"

#if defined(_WIN32)
#include <windows.h>

#elif defined(__ANDROID__)
#include <atomic>
extern std::atomic<int> g_battery_percentage;
extern std::atomic<bool> g_is_charging;
extern std::atomic<bool> g_has_battery;

#elif defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_OS_MAC
#include <IOKit/ps/IOPSKeys.h>
#include <IOKit/ps/IOPowerSources.h>
#endif

#elif defined(__linux__)
#include <fstream>
#include <string>
#include <dirent.h>
#endif

namespace Common {

    PowerStatus GetPowerStatus()
    {
        PowerStatus info;

#if defined(_WIN32)
        SYSTEM_POWER_STATUS status;
        if (GetSystemPowerStatus(&status)) {
            if (status.BatteryFlag == 128) {
                info.has_battery = false;
            } else {
                info.percentage = status.BatteryLifePercent;
                info.charging = (status.BatteryFlag & 8) != 0;
            }
        } else {
            info.has_battery = false;
        }

#elif defined(__ANDROID__)
        info.percentage = g_battery_percentage.load(std::memory_order_relaxed);
        info.charging = g_is_charging.load(std::memory_order_relaxed);
        info.has_battery = g_has_battery.load(std::memory_order_relaxed);

#elif defined(__APPLE__) && TARGET_OS_MAC
        CFTypeRef info_ref = IOPSCopyPowerSourcesInfo();
        CFArrayRef sources = IOPSCopyPowerSourcesList(info_ref);
        if (CFArrayGetCount(sources) > 0) {
            CFDictionaryRef battery =
                IOPSGetPowerSourceDescription(info_ref, CFArrayGetValueAtIndex(sources, 0));

            CFNumberRef curNum =
                (CFNumberRef)CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey));
            CFNumberRef maxNum =
                (CFNumberRef)CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey));
            int cur = 0, max = 0;
            CFNumberGetValue(curNum, kCFNumberIntType, &cur);
            CFNumberGetValue(maxNum, kCFNumberIntType, &max);

            if (max > 0)
                info.percentage = (cur * 100) / max;

            CFBooleanRef isCharging =
                (CFBooleanRef)CFDictionaryGetValue(battery, CFSTR(kIOPSIsChargingKey));
            info.charging = CFBooleanGetValue(isCharging);
        } else {
            info.has_battery = false;
        }
        CFRelease(sources);
        CFRelease(info_ref);

#elif defined(__linux__)
        const char* battery_path = "/sys/class/power_supply/BAT0/";

        std::ifstream capFile(std::string(battery_path) + "capacity");
        if (capFile) {
            capFile >> info.percentage;
        }
        else {
            info.has_battery = false;
        }

        std::ifstream statFile(std::string(battery_path) + "status");
        if (statFile) {
            std::string status;
            std::getline(statFile, status);
            info.charging = (status == "Charging");
        }
#else
        info.has_battery = false;
#endif

        return info;
    }
}