diff --git a/src/common/parsing.c b/src/common/parsing.c index ec58f9fa2..50f1a54aa 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -190,6 +190,48 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co } } +void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result) +{ + if(days == 0 && hours == 0 && minutes == 0) + { + ffStrbufAppendF(result, "%u seconds", seconds); + return; + } + + if(days > 0) + { + ffStrbufAppendF(result, "%u day", days); + + if(days > 1) + ffStrbufAppendC(result, 's'); + + if(days >= 100) + ffStrbufAppendS(result, "(!)"); + + if(hours > 0 || minutes > 0) + ffStrbufAppendS(result, ", "); + } + + if(hours > 0) + { + ffStrbufAppendF(result, "%u hour", hours); + + if(hours > 1) + ffStrbufAppendC(result, 's'); + + if(minutes > 0) + ffStrbufAppendS(result, ", "); + } + + if(minutes > 0) + { + ffStrbufAppendF(result, "%u min", minutes); + + if(minutes > 1) + ffStrbufAppendC(result, 's'); + } +} + #ifdef _WIN32 #pragma GCC diagnostic pop #endif diff --git a/src/common/parsing.h b/src/common/parsing.h index 722969ffb..bc04cf2f0 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -27,3 +27,4 @@ int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2); void ffParseSize(uint64_t bytes, FFstrbuf* result); bool ffParseFrequency(uint32_t mhz, FFstrbuf* result); +void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result); diff --git a/src/detection/battery/battery.h b/src/detection/battery/battery.h index 2f4c8e3f1..d31a7ef71 100644 --- a/src/detection/battery/battery.h +++ b/src/detection/battery/battery.h @@ -15,6 +15,7 @@ typedef struct FFBatteryResult double capacity; double temperature; uint32_t cycleCount; + int32_t timeRemaining; } FFBatteryResult; const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results); diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 4f3d809b6..942f4b570 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -43,6 +43,11 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName); ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial); ffCfDictGetString(properties, CFSTR(kIOPMPSManufacturerKey), &battery->manufacturer); + ffCfDictGetInt(properties, CFSTR(kIOPMPSTimeRemainingKey), &battery->timeRemaining); // in minutes + if (battery->timeRemaining == 0xFFFF) + battery->timeRemaining = -1; + else + battery->timeRemaining *= 60; if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue) { diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 6c7298231..101bd6dea 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -121,6 +121,13 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results battery->temperature = temp / 10.0 - 273.15; } + { + bqi.InformationLevel = BatteryEstimatedTime; + ULONG time; + if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &time, sizeof(time), &dwOut, NULL)) + battery->timeRemaining = time == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) time; + } + { BATTERY_STATUS bs; BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag }; @@ -241,6 +248,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF ffStrbufInit(&battery->serial); battery->temperature = FF_BATTERY_TEMP_UNSET; battery->cycleCount = 0; + battery->timeRemaining = info.EstimatedTime == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) info.EstimatedTime; battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity; if(info.AcOnLine) @@ -252,6 +260,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF else if(info.Discharging) ffStrbufAppendS(&battery->status, "Discharging"); + detectBySmbios(battery); return NULL; diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 743c098e2..25cf8d8cc 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -7,7 +7,7 @@ #include "modules/battery/battery.h" #include "util/stringUtils.h" -#define FF_BATTERY_NUM_FORMAT_ARGS 10 +#define FF_BATTERY_NUM_FORMAT_ARGS 14 static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index) { @@ -28,6 +28,17 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin })); } + + uint32_t timeRemaining = result->timeRemaining < 0 ? 0 : (uint32_t) result->timeRemaining; + + uint32_t seconds = timeRemaining % 60; + timeRemaining /= 60; + uint32_t minutes = timeRemaining % 60; + timeRemaining /= 60; + uint32_t hours = timeRemaining % 24; + timeRemaining /= 24; + uint32_t days = timeRemaining; + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); @@ -52,6 +63,15 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin ffPercentAppendNum(&str, result->capacity, options->percent, str.length > 0, &options->moduleArgs); } + + if(result->timeRemaining > 0) + { + if(str.length > 0) + ffStrbufAppendS(&str, " ("); + + ffParseDuration(days, hours, minutes, seconds, &str); + ffStrbufAppendS(&str, " remaining)"); + } } if(showStatus) @@ -91,6 +111,10 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin FF_FORMAT_ARG(result->serial, "serial"), FF_FORMAT_ARG(result->manufactureDate, "manufacture-date"), FF_FORMAT_ARG(capacityBar, "capacity-bar"), + FF_FORMAT_ARG(days, "time-days"), + FF_FORMAT_ARG(hours, "time-hours"), + FF_FORMAT_ARG(minutes, "time-minutes"), + FF_FORMAT_ARG(seconds, "time-seconds"), })); } } @@ -226,6 +250,7 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "serial", &battery->serial); yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); yyjson_mut_obj_add_uint(doc, obj, "cycleCount", battery->cycleCount); + yyjson_mut_obj_add_int(doc, obj, "timeRemaining", battery->timeRemaining); } FF_LIST_FOR_EACH(FFBatteryResult, battery, results) @@ -241,7 +266,7 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, void ffPrintBatteryHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BATTERY_MODULE_NAME, "{4}, {5}", FF_BATTERY_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BATTERY_MODULE_NAME, "{4} ({12} hours {13} mins) [{5}]", FF_BATTERY_NUM_FORMAT_ARGS, ((const char* []) { "Battery manufacturer - manufacturer", "Battery model name - model-name", "Battery technology - technology", @@ -252,6 +277,10 @@ void ffPrintBatteryHelpFormat(void) "Battery serial number - serial", "Battery manufactor date - manufacture-date", "Battery capacity (percentage bar) - capacity-bar", + "Battery time remaining days - time-days", + "Battery time remaining hours - time-hours", + "Battery time remaining minutes - time-minutes", + "Battery time remaining seconds - time-seconds", })); } diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index caccc1f86..935957df1 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -34,47 +34,10 @@ void ffPrintUptime(FFUptimeOptions* options) if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + ffParseDuration(days, hours, minutes, seconds, &buffer); - if(days == 0 && hours == 0 && minutes == 0) - { - printf("%u seconds\n", seconds); - return; - } - - if(days > 0) - { - printf("%u day", days); - - if(days > 1) - putchar('s'); - - if(days >= 100) - fputs("(!)", stdout); - - if(hours > 0 || minutes > 0) - fputs(", ", stdout); - } - - if(hours > 0) - { - printf("%u hour", hours); - - if(hours > 1) - putchar('s'); - - if(minutes > 0) - fputs(", ", stdout); - } - - if(minutes > 0) - { - printf("%u min", minutes); - - if(minutes > 1) - putchar('s'); - } - - putchar('\n'); + ffStrbufPutTo(&buffer, stdout); } else {