lumina-desktop / lumina

Lumina Desktop Environment
http://lumina-desktop.org
BSD 3-Clause "New" or "Revised" License
531 stars 116 forks source link

Lumina thinks my iMac G5 has a battery #765

Open outpaddling opened 3 years ago

outpaddling commented 3 years ago

Just installed Lumina on an iMac G5 via desktop-installer. Works just about perfectly, except for thinking that the system should have a battery and stunning me with the gulag firing squad drum roll every time I log in.

imac-g5

"sysctl -a | grep batt" shows nothing, so I'm wondering how Lumina determines that a system has a battery?

outpaddling commented 2 years ago

I dug into the code and discovered that battery monitoring is implemented by shelling out an apm command. Biggest problem here is that apm does not exist on powerpc, arm, or riscv. It's also an inefficient way to get battery info and has been superseded by the ACPI interface.

The patches below should work on any platform and perform better.

src-cpp/framework-OSInterface-FreeBSD.cpp does not appear to be used anymore, but I patched it just in case.

I was also getting intermittent false alarms about low battery with the apm implementation when the system was under heavy load and I'm hoping this will eliminate those as well. I'll report back if the false alarms continue.

--- ../src-cpp/framework-OSInterface-FreeBSD.cpp.orig   2021-12-25 20:33:45.000000000 -0600
+++ ../src-cpp/framework-OSInterface-FreeBSD.cpp        2022-02-17 08:14:20.413578000 -0600
@@ -21,24 +21,34 @@
 bool OSInterface::OS_batteryAvailable(){
   static int bat_avail = -1; //this will not change during a single session - keep later calls fast
   if(bat_avail < 0){
-    int val = getCmdOutput("apm -l").join("").toInt();
-    bat_avail = ((val >= 0 && val <= 100) ? 1 : 0 );
+    bat_avail = (sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) == 0);
   }
   return (bat_avail==1);
 }

 float OSInterface::OS_batteryCharge(){
-  int charge = getCmdOutput("apm -l").join("").toInt();
-  if(charge > 100){ charge = -1; } //invalid charge
-  return charge;
+  int life;
+  if ( (sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) != 0) ||
+       (life > 100) )
+    life = -1
+  return life;
 }

 bool OSInterface::OS_batteryCharging(){
-  return (getCmdOutput("apm -a").join("").simplified() == "1");
+  if ( (sysctlbyname("hw.acpi.battery.state", &state, &len, NULL, 0) == 0) &&
+       (state == ACPI_BATT_STAT_CHARGING) )
+    return true;
+  else
+    return false;
 }

 double OSInterface::OS_batterySecondsLeft(){ //Returns: estimated number of seconds remaining
-  return getCmdOutput("apm -t").join("").toDouble();
+  int min, sec;
+  if ( sysctlbyname("hw.acpi.battery.time", &min, &len, NULL, 0) == 0 )
+    sec = min * 60;
+  else
+    sec = -1
+  return sec;
 }

 // = Volume =
...skipping...
--- libLumina/LuminaOS-FreeBSD.cpp.orig 2021-12-26 02:33:45 UTC
+++ libLumina/LuminaOS-FreeBSD.cpp
@@ -9,6 +9,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/sysctl.h>
+#include <dev/acpica/acpiio.h>

 #include <QDebug>
 //can't read xbrightness settings - assume invalid until set
@@ -289,31 +290,52 @@ void LOS::systemSuspend(){
 }

 //Battery Availability
+// apm command is not available on powerpc or arm
 bool LOS::hasBattery(){
   static int hasbat = -1;
+  int        life;
+  size_t     len = sizeof(life);
   if(hasbat < 0 ){
-    int val = batteryCharge();
-    if(val >= 0 && val <= 100){ hasbat = 1; }
-    else{ hasbat = 0; }
+    if ( sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) == 0 )
+      hasbat = 1;
+    else
+      hasbat = 0;
   }
   return (hasbat==1);
 }

 //Battery Charge Level
+// apm command is not available on powerpc or arm
 int LOS::batteryCharge(){ //Returns: percent charge (0-100), anything outside that range is counted as an error
-  int charge = LUtils::getCmdOutput("apm -l").join("").toInt();
-  if(charge > 100){ charge = -1; } //invalid charge
-  return charge;
+  int    life; // sysctl name
+  size_t len = sizeof(life);
+  if ( (sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0) != 0) ||
+       (life > 100) )
+     life = -1; //invalid charge
+  return life;
 }

 //Battery Charging State
+// apm command is not available on powerpc or arm
 bool LOS::batteryIsCharging(){
-  return (LUtils::getCmdOutput("apm -a").join("").simplified() == "1");
+  int   state;
+  size_t len = sizeof(state);
+  if ( (sysctlbyname("hw.acpi.battery.state", &state, &len, NULL, 0) == 0) &&
+       (state == ACPI_BATT_STAT_CHARGING) )
+    return true;
+  else
+    return false;
 }

 //Battery Time Remaining
+// apm command is not available on powerpc or arm
 int LOS::batterySecondsLeft(){ //Returns: estimated number of seconds remaining
-  return LUtils::getCmdOutput("apm -t").join("").toInt();
+  int   min;
+  size_t len = sizeof(min);
+  if ( sysctlbyname("hw.acpi.battery.time", &min, &len, NULL, 0) == 0 )
+    return min * 60;
+  else
+    return -1;
 }

 //File Checksums
outpaddling commented 2 years ago

Also relates to #349.

outpaddling commented 2 years ago

FYI, this seems to have eliminated the minor CPU spikes (usually to around 3%) I had always seen under "top". Since reinstalling with these patches, the CPU stays consistently at a small fraction of a percent.

The patched 1.6.2 port is here, BTW: https://github.com/outpaddling/freebsd-ports-wip/tree/master/lumina-core