Merge branch 'master' into gregoa
[gregoa/zavai.git] / src / power.vala
index 2e6edae55f8b899464026d705b9aa57e77ef9b4e..55711179666fbf4b54287c8070b02f2e18b30b9e 100644 (file)
@@ -23,15 +23,30 @@ using GLib;
 namespace zavai {
 namespace power {
 
-class Power : Service
+public class Power : Service
 {
+    public enum State
+    {
+        UNKNOWN,
+        CHARGING,
+        DISCHARGING,
+        FULLY_CHARGED,
+    }
+
     protected string battery_device;
     protected uint timeout;
+    public signal void changed();
+    public State state;
+    public int percentage;
 
     public Power()
     {
-        battery_device = "";
+        battery_device = "/sys/class/power_supply/battery/";
+        if (Posix.access(battery_device, Posix.R_OK) != 0)
+            battery_device = null;
         timeout = 0;
+        state = State.UNKNOWN;
+        percentage = 0;
     }
 
     /// Activate the service
@@ -42,19 +57,30 @@ class Power : Service
         uint poll_time;
         if (uevent.uevent != null)
         {
+            zavai.log.info("We have uevent: poll rarely");
             uevent.uevent.event += on_uevent;
             uevent.uevent.request("zavai.power");
             // If we can get plug/unplug notifications, it's ok to just poll
             // every 5 minutes
             poll_time = 300 * 1000;
         } else {
-            // Else poll every 30 seconds to be somehow reactive to plug/unplug
-            // events
-            poll_time = 30 * 1000;
+            if (battery_device == null)
+            {
+                zavai.log.warning("No battery device found that I know how to read: try building with devkit-power");
+                poll_time = 0;
+            } else {
+                zavai.log.info("Polling battery device only");
+                // Else poll every 30 seconds to be somehow reactive to plug/unplug
+                // events
+                poll_time = 30 * 1000;
+            }
         }
 
+        poll();
+
         // Poll battery every minute
-        timeout = Timeout.add(poll_time, on_timeout);
+        if (poll_time != 0)
+            timeout = Timeout.add(poll_time, on_timeout);
 
         base.start();
     }
@@ -65,7 +91,8 @@ class Power : Service
         if (!started) return;
 
         // Stop polling
-        Source.remove(timeout);
+        if (timeout != 0)
+            Source.remove(timeout);
 
         if (uevent.uevent != null)
         {
@@ -76,18 +103,85 @@ class Power : Service
         base.stop();
     }
 
-    bool on_timeout()
+    protected void poll()
     {
+        if (battery_device == null)
+            return;
+
+        char buf[200];
+        State new_state = State.UNKNOWN;
+        int new_percentage = 0;
+
+        FileStream state_fd = FileStream.open(battery_device + "/status", "r");
+        string val = state_fd.gets(buf);
+        if (val == "Charging")
+            new_state = State.CHARGING;
+        else if (val == "Discharging")
+            new_state = State.DISCHARGING;
+        else if (val == "Not charging")
+            new_state = State.FULLY_CHARGED;
+
+        FileStream cap_fd = FileStream.open(battery_device + "/capacity", "r");
+        val = cap_fd.gets(buf);
+        new_percentage = val.to_int();
+
+        if (new_state != state || new_percentage != percentage)
+        {
+            state = new_state;
+            percentage = new_percentage;
+            changed();
+        }
+    }
+
+    protected bool on_timeout()
+    {
+        poll();
         return true;
     }
 
-    void on_uevent()
+    protected void on_uevent()
     {
-stderr.printf("EVENT %s\n", uevent.uevent.event_data.buffer);
+        /* if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/ac"))
+        {
+            changed();
+        }
+        else */
+        if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/battery"))
+        {
+            State new_state = State.UNKNOWN;
+            int new_percentage = 0;
+
+            Omhacks.UEvent.parse(ref uevent.uevent.event_data);
+            for (int i = 0; uevent.uevent.event_data.envp[i] != null; ++i)
+            {
+                if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_STATUS="))
+                {
+                    var val = uevent.uevent.event_data.envp[i].offset(20);
+                    if (val == "Charging")
+                        new_state = State.CHARGING;
+                    else if (val == "Discharging")
+                        new_state = State.DISCHARGING;
+                    else if (val == "Not charging")
+                        new_state = State.FULLY_CHARGED;
+                    else
+                        zavai.log.warning("Unknown state: " + uevent.uevent.event_data.envp[i]);
+                }
+                else if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_CAPACITY="))
+                {
+                    new_percentage = uevent.uevent.event_data.envp[i].offset(22).to_int();
+                }
+            }
+            if (new_state != state || new_percentage != percentage)
+            {
+                state = new_state;
+                percentage = new_percentage;
+                changed();
+            }
+        }
     }
 }
 
-Power power;
+public Power power;
 
 public void init()
 {