Skip to content

Commit 59ebc74

Browse files
Merge pull request #235 from CarterLi/master
macOS: add battery info support; fix GPU detection; various improvements
2 parents df9aec6 + 09f3bd5 commit 59ebc74

26 files changed

+404
-208
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,18 @@ if(APPLE)
240240
src/detection/os/os_apple.c
241241
src/detection/cpu/cpu_apple.c
242242
src/detection/gpu/gpu_apple.c
243+
src/detection/battery/battery_apple.c
243244
src/detection/memory/memory_apple.c
244245
src/detection/displayserver/displayserver_apple.c
246+
src/util/apple/cfdict_helpers.c
245247
)
246248
elseif(ANDROID)
247249
list(APPEND LIBFASTFETCH_SRC
248250
src/detection/host/host_android.c
249251
src/detection/os/os_android.c
250252
src/detection/cpu/cpu_linux.c
251253
src/detection/gpu/gpu_android.c
254+
src/detection/battery/battery_android.c
252255
src/detection/memory/memory_linux.c
253256
src/detection/displayserver/displayserver_android.c
254257
)
@@ -259,6 +262,7 @@ else()
259262
src/detection/cpu/cpu_linux.c
260263
src/detection/gpu/gpu_linux.c
261264
src/detection/memory/memory_linux.c
265+
src/detection/battery/battery_linux.c
262266
src/detection/displayserver/linux/displayserver_linux.c
263267
src/detection/displayserver/linux/wayland.c
264268
src/detection/displayserver/linux/xcb.c

presets/verbose

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
--terminal-font-format Raw: {}; Name: {}; Size: {}; Styles: {}; Pretty: {}
1818
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
1919
--cpu-usage-format Percentage: {}
20-
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}
20+
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}
2121
--memory-format Used: {}; Total: {}; Percentage: {}
2222
--disk-format Used: {}; Total: {}; Files: {}; Percentage: {}
2323
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}

src/common/io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ bool ffFileExists(const char* fileName, mode_t mode);
1919
// Not thread safe!
2020
void ffSuppressIO(bool suppress);
2121

22-
void ffGetTerminalResponse(const char* request, const char* format, ...);
22+
FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...);
2323

2424
#endif

src/common/printing.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat);
1010
void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments);
1111
void ffPrintFormat(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments);
12-
void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...);
13-
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
12+
FF_C_PRINTF(6, 7) void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customErrorFormat, const char* message, ...);
13+
FF_C_PRINTF(5, 6) void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
1414
void ffPrintColor(const FFstrbuf* colorValue);
1515
void ffPrintCharTimes(char c, uint32_t times);
1616
void ffPrintUserString(const char* str);

src/detection/battery/battery.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#ifndef FF_INCLUDED_detection_battery_battery
4+
#define FF_INCLUDED_detection_battery_battery
5+
6+
#include "fastfetch.h"
7+
8+
typedef struct BatteryResult
9+
{
10+
FFstrbuf manufacturer;
11+
FFstrbuf modelName;
12+
FFstrbuf technology;
13+
FFstrbuf capacity;
14+
FFstrbuf status;
15+
} BatteryResult;
16+
17+
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results);
18+
19+
#endif
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "fastfetch.h"
2+
#include "common/io.h"
3+
#include "battery.h"
4+
5+
#include <dirent.h>
6+
7+
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
8+
FF_UNUSED(instance, results)
9+
return "Unimplemented";
10+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "fastfetch.h"
2+
#include "battery.h"
3+
#include "util/apple/cfdict_helpers.h"
4+
5+
#include <IOKit/IOKitLib.h>
6+
7+
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
8+
{
9+
FF_UNUSED(instance);
10+
11+
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery");
12+
if (matchDict == NULL)
13+
return "IOServiceMatching(\"AppleSmartBattery\") failed";
14+
15+
io_iterator_t iterator;
16+
if(IOServiceGetMatchingServices(0, matchDict, &iterator) != kIOReturnSuccess)
17+
return "IOServiceGetMatchingServices() failed";
18+
19+
io_registry_entry_t registryEntry;
20+
while((registryEntry = IOIteratorNext(iterator)) != 0)
21+
{
22+
CFMutableDictionaryRef properties;
23+
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
24+
{
25+
IOObjectRelease(registryEntry);
26+
continue;
27+
}
28+
29+
int intValue;
30+
bool boolValue;
31+
32+
BatteryResult* battery = ffListAdd(results);
33+
ffStrbufInit(&battery->capacity);
34+
if(ffCfDictGetInt(properties, "CurrentCapacity", &intValue))
35+
ffStrbufAppendF(&battery->capacity, "%d", intValue);
36+
37+
ffStrbufInit(&battery->manufacturer);
38+
ffStrbufInit(&battery->modelName);
39+
ffStrbufInit(&battery->technology);
40+
if (ffCfDictGetBool(properties, "built-in", &boolValue) && boolValue)
41+
{
42+
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
43+
ffStrbufAppendS(&battery->modelName, "Builtin");
44+
ffStrbufAppendS(&battery->technology, "Lithium");
45+
}
46+
else
47+
{
48+
ffStrbufAppendS(&battery->manufacturer, "Unknown");
49+
ffStrbufAppendS(&battery->modelName, "Unknown");
50+
ffStrbufAppendS(&battery->technology, "Unknown");
51+
}
52+
53+
ffStrbufInit(&battery->status);
54+
if (ffCfDictGetBool(properties, "FullyCharged", &boolValue) && boolValue)
55+
ffStrbufAppendS(&battery->status, "Fully charged");
56+
else if (ffCfDictGetBool(properties, "IsCharging", &boolValue) && boolValue)
57+
ffStrbufAppendS(&battery->status, "Charging");
58+
else
59+
ffStrbufAppendS(&battery->status, "");
60+
61+
CFRelease(properties);
62+
IOObjectRelease(registryEntry);
63+
}
64+
65+
IOObjectRelease(iterator);
66+
67+
return NULL;
68+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include "fastfetch.h"
2+
#include "common/io.h"
3+
#include "battery.h"
4+
5+
#include <dirent.h>
6+
7+
static void parseBattery(FFstrbuf* dir, FFlist* results)
8+
{
9+
uint32_t dirLength = dir->length;
10+
11+
FFstrbuf testBatteryBuffer;
12+
ffStrbufInit(&testBatteryBuffer);
13+
14+
//type must exist and be "Battery"
15+
ffStrbufAppendS(dir, "/type");
16+
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
17+
ffStrbufSubstrBefore(dir, dirLength);
18+
19+
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0)
20+
{
21+
ffStrbufDestroy(&testBatteryBuffer);
22+
return;
23+
}
24+
25+
//scope may not exist or must not be "Device"
26+
ffStrbufAppendS(dir, "/scope");
27+
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
28+
ffStrbufSubstrBefore(dir, dirLength);
29+
30+
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
31+
{
32+
ffStrbufDestroy(&testBatteryBuffer);
33+
return;
34+
}
35+
36+
ffStrbufDestroy(&testBatteryBuffer);
37+
BatteryResult* result = ffListAdd(results);
38+
39+
//capacity must exist and be not empty
40+
ffStrbufInit(&result->capacity);
41+
ffStrbufAppendS(dir, "/capacity");
42+
ffReadFileBuffer(dir->chars, &result->capacity);
43+
ffStrbufSubstrBefore(dir, dirLength);
44+
45+
if(result->capacity.length == 0)
46+
{
47+
ffStrbufDestroy(&result->capacity);
48+
--results->length;
49+
return;
50+
}
51+
52+
//At this point, we have a battery. Try to get as much values as possible.
53+
54+
ffStrbufInit(&result->manufacturer);
55+
ffStrbufAppendS(dir, "/manufacturer");
56+
ffReadFileBuffer(dir->chars, &result->manufacturer);
57+
ffStrbufSubstrBefore(dir, dirLength);
58+
59+
ffStrbufInit(&result->modelName);
60+
ffStrbufAppendS(dir, "/model_name");
61+
ffReadFileBuffer(dir->chars, &result->modelName);
62+
ffStrbufSubstrBefore(dir, dirLength);
63+
64+
ffStrbufInit(&result->technology);
65+
ffStrbufAppendS(dir, "/technology");
66+
ffReadFileBuffer(dir->chars, &result->technology);
67+
ffStrbufSubstrBefore(dir, dirLength);
68+
69+
ffStrbufInit(&result->status);
70+
ffStrbufAppendS(dir, "/status");
71+
ffReadFileBuffer(dir->chars, &result->status);
72+
ffStrbufSubstrBefore(dir, dirLength);
73+
}
74+
75+
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
76+
FFstrbuf baseDir;
77+
ffStrbufInitA(&baseDir, 64);
78+
if(instance->config.batteryDir.length > 0)
79+
{
80+
ffStrbufAppend(&baseDir, &instance->config.batteryDir);
81+
if (!ffStrbufEndsWithC(&baseDir, '/'))
82+
{
83+
ffStrbufAppendC(&baseDir, '/');
84+
}
85+
}
86+
else
87+
{
88+
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
89+
}
90+
91+
uint32_t baseDirLength = baseDir.length;
92+
93+
DIR* dirp = opendir(baseDir.chars);
94+
if(dirp == NULL)
95+
{
96+
ffStrbufDestroy(&baseDir);
97+
return "opendir(batteryDir) == NULL";
98+
}
99+
100+
struct dirent* entry;
101+
while((entry = readdir(dirp)) != NULL)
102+
{
103+
ffStrbufAppendS(&baseDir, entry->d_name);
104+
parseBattery(&baseDir, results);
105+
ffStrbufSubstrBefore(&baseDir, baseDirLength);
106+
}
107+
108+
closedir(dirp);
109+
110+
if(results->length == 0) {
111+
ffStrbufDestroy(&baseDir);
112+
return "batteryDir doesn't contain any battery folder";
113+
}
114+
115+
ffStrbufDestroy(&baseDir);
116+
return NULL;
117+
}

src/detection/gpu/gpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
#include "fastfetch.h"
77

88
#define FF_GPU_TEMP_UNSET (0/0.0)
9+
#define FF_GPU_CORE_COUNT_UNSET -1
910

1011
typedef struct FFGPUResult
1112
{
1213
FFstrbuf vendor;
1314
FFstrbuf name;
1415
FFstrbuf driver;
1516
double temperature;
17+
int coreCount;
1618
} FFGPUResult;
1719

1820
const FFlist* ffDetectGPU(const FFinstance* instance);

src/detection/gpu/gpu_android.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "gpu.h"
22

3-
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
3+
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
44
{
55
FF_UNUSED(gpus, instance);
6+
return "Unimplemented";
67
}

0 commit comments

Comments
 (0)