aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/e_powersave.c
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2017-07-10 09:05:12 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2017-07-10 10:18:50 +0900
commit7caf5c8ff40ef0f2423f7f80a83686f56a331f80 (patch)
treea9ec32dfcf2090cf38c2aac297279e5a41a7320d /src/bin/e_powersave.c
parente widget entry: fix the compilation warning (diff)
downloadenlightenment-7caf5c8ff40ef0f2423f7f80a83686f56a331f80.tar.gz
add new powersave features for supporting a live sleep mode
so new laptops now seem to no longer support S3 sleep. sleeping is done basically by going as idle as possible. you can ask the kernel to freeze execution BUT this seems to use about the same power as staying alive in my tests. to support this add 2 things: 1. a FREEZE powersave mode which implies we're alive but want to really stay as idle as absolutely possible. 2. powersave aware sleep functions that replace the usleeps in threads so they can switch from being super sleepy when in freeze mode to normal.
Diffstat (limited to 'src/bin/e_powersave.c')
-rw-r--r--src/bin/e_powersave.c124
1 files changed, 105 insertions, 19 deletions
diff --git a/src/bin/e_powersave.c b/src/bin/e_powersave.c
index be622b577..03a1b91ea 100644
--- a/src/bin/e_powersave.c
+++ b/src/bin/e_powersave.c
@@ -8,9 +8,12 @@ struct _E_Powersave_Deferred_Action
};
/* local subsystem functions */
+static void _e_powersave_sleeper_cb_dummy(void *data EINA_UNUSED, void *buffer EINA_UNUSED, unsigned int bytes EINA_UNUSED);
static Eina_Bool _e_powersave_cb_deferred_timer(void *data);
static void _e_powersave_mode_eval(void);
static void _e_powersave_event_update_free(void *data EINA_UNUSED, void *event);
+static void _e_powersave_event_change_send(E_Powersave_Mode mode);
+static void _e_powersave_sleepers_wake(void);
/* local subsystem globals */
E_API int E_EVENT_POWERSAVE_UPDATE = 0;
@@ -19,7 +22,10 @@ static int walking_deferred_actions = 0;
static Eina_List *deferred_actions = NULL;
static Ecore_Timer *deferred_timer = NULL;
static E_Powersave_Mode powersave_mode = E_POWERSAVE_MODE_LOW;
+static E_Powersave_Mode powersave_mode_force = E_POWERSAVE_MODE_NONE;
static double defer_time = 5.0;
+static Eina_Bool powersave_force = EINA_FALSE;
+static Eina_List *powersave_sleepers = NULL;
/* externally accessible functions */
EINTERN int
@@ -46,8 +52,8 @@ e_powersave_deferred_action_add(void (*func)(void *data), const void *data)
if (!pa) return NULL;
if (deferred_timer) ecore_timer_del(deferred_timer);
deferred_timer = ecore_timer_loop_add(defer_time,
- _e_powersave_cb_deferred_timer,
- NULL);
+ _e_powersave_cb_deferred_timer,
+ NULL);
pa->func = func;
pa->data = data;
deferred_actions = eina_list_append(deferred_actions, pa);
@@ -80,41 +86,101 @@ e_powersave_deferred_action_del(E_Powersave_Deferred_Action *pa)
E_API void
e_powersave_mode_set(E_Powersave_Mode mode)
{
- E_Event_Powersave_Update *ev;
-
if (mode < e_config->powersave.min) mode = e_config->powersave.min;
- else if (mode > e_config->powersave.max)
- mode = e_config->powersave.max;
+ else if (mode > e_config->powersave.max) mode = e_config->powersave.max;
+
if (powersave_mode == mode) return;
- printf("CHANGE PW SAVE MODE TO %i / %i\n", (int)mode, E_POWERSAVE_MODE_EXTREME);
powersave_mode = mode;
- ev = E_NEW(E_Event_Powersave_Update, 1);
- ev->mode = mode;
- ecore_event_add(E_EVENT_POWERSAVE_UPDATE, ev, _e_powersave_event_update_free, NULL);
+ if (powersave_force) return;
+ _e_powersave_event_change_send(powersave_mode);
_e_powersave_mode_eval();
}
E_API E_Powersave_Mode
e_powersave_mode_get(void)
{
+ if (powersave_force) return powersave_mode_force;
return powersave_mode;
}
-E_API E_Powersave_Mode
-e_powersave_mode_min_get(void)
+E_API void
+e_powersave_mode_force(E_Powersave_Mode mode)
{
- return e_config->powersave.min;
+ if (mode == powersave_mode_force) return;
+ powersave_force = EINA_TRUE;
+ powersave_mode_force = mode;
+ _e_powersave_event_change_send(powersave_mode_force);
+ _e_powersave_mode_eval();
}
-E_API E_Powersave_Mode
-e_powersave_mode_max_get(void)
+E_API void
+e_powersave_mode_unforce(void)
{
- return e_config->powersave.max;
+ if (!powersave_force) return;
+ powersave_force = EINA_FALSE;
+ if (powersave_mode_force != powersave_mode)
+ {
+ _e_powersave_event_change_send(powersave_mode);
+ _e_powersave_mode_eval();
+ }
+ powersave_mode_force = E_POWERSAVE_MODE_NONE;
+}
+
+E_API E_Powersave_Sleeper *
+e_powersave_sleeper_new(void)
+{
+ Ecore_Pipe *pipe;
+
+ pipe = ecore_pipe_add(_e_powersave_sleeper_cb_dummy, NULL);
+ powersave_sleepers = eina_list_append(powersave_sleepers, pipe);
+ return (E_Powersave_Sleeper *)pipe;
+}
+
+E_API void
+e_powersave_sleeper_free(E_Powersave_Sleeper *sleeper)
+{
+ Ecore_Pipe *pipe = (Ecore_Pipe *)sleeper;
+
+ if (!pipe) return;
+ powersave_sleepers = eina_list_remove(powersave_sleepers, pipe);
+ ecore_pipe_del(pipe);
+}
+
+E_API void
+e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval)
+{
+ Ecore_Pipe *pipe = (Ecore_Pipe *)sleeper;
+ double tim, now;
+
+ if (!pipe) return;
+ if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE) tim = 3600;
+ else tim = (double)poll_interval / 8.0;
+ now = ecore_time_get();
+ tim = fmod(now, tim);
+ ecore_pipe_wait(pipe, 1, tim);
}
/* local subsystem functions */
+static void
+_e_powersave_sleepers_wake(void)
+{
+ Ecore_Pipe *pipe;
+ Eina_List *l;
+ char buf[1] = { 1 };
+
+ EINA_LIST_FOREACH(powersave_sleepers, l, pipe)
+ {
+ ecore_pipe_write(pipe, buf, 1);
+ }
+}
+
+static void
+_e_powersave_sleeper_cb_dummy(void *data EINA_UNUSED, void *buffer EINA_UNUSED, unsigned int bytes EINA_UNUSED)
+{
+}
+
static Eina_Bool
_e_powersave_cb_deferred_timer(void *data EINA_UNUSED)
{
@@ -135,8 +201,12 @@ static void
_e_powersave_mode_eval(void)
{
double t = 0.0;
+ E_Powersave_Mode mode;
- switch (powersave_mode)
+ if (powersave_force) mode = powersave_mode_force;
+ else mode = powersave_mode;
+
+ switch (mode)
{
case E_POWERSAVE_MODE_NONE:
t = e_config->powersave.none; /* time to defer "power expensive" activities */
@@ -158,6 +228,10 @@ _e_powersave_mode_eval(void)
t = e_config->powersave.extreme;
break;
+ case E_POWERSAVE_MODE_FREEZE:
+ t = 3600;
+ break;
+
default:
return;
break;
@@ -166,8 +240,8 @@ _e_powersave_mode_eval(void)
{
if (deferred_timer) ecore_timer_del(deferred_timer);
deferred_timer = ecore_timer_loop_add(defer_time,
- _e_powersave_cb_deferred_timer,
- NULL);
+ _e_powersave_cb_deferred_timer,
+ NULL);
defer_time = t;
}
}
@@ -178,3 +252,15 @@ _e_powersave_event_update_free(void *data EINA_UNUSED, void *event)
free(event);
}
+static void
+_e_powersave_event_change_send(E_Powersave_Mode mode)
+{
+ E_Event_Powersave_Update *ev;
+
+ printf("CHANGE PW SAVE MODE TO %i / %i\n",
+ (int)mode, E_POWERSAVE_MODE_EXTREME);
+ ev = E_NEW(E_Event_Powersave_Update, 1);
+ ev->mode = mode;
+ ecore_event_add(E_EVENT_POWERSAVE_UPDATE, ev, _e_powersave_event_update_free, NULL);
+ _e_powersave_sleepers_wake();
+}