E_EVENT_POWERSAVE_UPDATE for the masses

cpufreq auto-changes the governor depending on the powersave mode


SVN revision: 37788
This commit is contained in:
Viktor Kojouharov 2008-11-24 08:32:34 +00:00
parent 6b4213e1b1
commit 8087cda39d
4 changed files with 180 additions and 8 deletions

View File

@ -13,8 +13,10 @@ struct _E_Powersave_Deferred_Action
/* local subsystem functions */
static int _e_powersave_cb_deferred_timer(void *data);
static void _e_powersave_mode_eval(void);
static void _e_powersave_event_update_free(void *data __UNUSED__, void *event);
/* local subsystem globals */
EAPI int E_EVENT_POWERSAVE_UPDATE = 0;
static int walking_deferred_actions = 0;
static Eina_List *deferred_actions = NULL;
static Ecore_Timer *deferred_timer = NULL;
@ -28,6 +30,7 @@ EAPI int
e_powersave_init(void)
{
_e_powersave_mode_eval();
E_EVENT_POWERSAVE_UPDATE = ecore_event_type_new();
return 1;
}
@ -94,11 +97,17 @@ e_powersave_mode_max_set(E_Powersave_Mode mode)
EAPI void
e_powersave_mode_set(E_Powersave_Mode mode)
{
E_Event_Powersave_Update *ev;
if (mode < powersave_mode_min) mode = powersave_mode_min;
else if (mode > powersave_mode_max) mode = powersave_mode_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);
_e_powersave_mode_eval();
}
@ -175,3 +184,9 @@ _e_powersave_mode_eval(void)
NULL);
}
}
static void
_e_powersave_event_update_free(void *data __UNUSED__, void *event)
{
free(event);
}

View File

@ -13,11 +13,19 @@ typedef enum _E_Powersave_Mode
} E_Powersave_Mode;
typedef struct _E_Powersave_Deferred_Action E_Powersave_Deferred_Action;
typedef struct _E_Event_Powersave_Update E_Event_Powersave_Update;
#else
#ifndef E_POWERSAVE_H
#define E_POWERSAVE_H
extern EAPI int E_EVENT_POWERSAVE_UPDATE;
struct _E_Event_Powersave_Update
{
E_Powersave_Mode mode;
};
EAPI int e_powersave_init(void);
EAPI int e_powersave_shutdown(void);

View File

@ -57,6 +57,7 @@ static void _cpufreq_face_update_available(Instance *inst);
static void _cpufreq_face_update_current(Instance *inst);
static void _cpufreq_face_cb_set_frequency(void *data, Evas_Object *o, const char *emission, const char *source);
static void _cpufreq_face_cb_set_governor(void *data, Evas_Object *o, const char *emission, const char *source);
static int _cpufreq_event_cb_powersave(void *data __UNUSED__, int type, void *event);
static void _cpufreq_menu_fast(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_medium(void *data, E_Menu *m, E_Menu_Item *mi);
@ -64,7 +65,9 @@ static void _cpufreq_menu_normal(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_slow(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_very_slow(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_restore_governor(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_auto_powersave(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_governor(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_powersave_governor(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_frequency(void *data, E_Menu *m, E_Menu_Item *mi);
static E_Config_DD *conf_edd = NULL;
@ -100,6 +103,9 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
cpufreq_config->status = _cpufreq_status_new();
_cpufreq_cb_check(NULL);
_cpufreq_face_update_available(inst);
cpufreq_config->handler = ecore_event_handler_add(E_EVENT_POWERSAVE_UPDATE,
_cpufreq_event_cb_powersave, NULL);
return gcc;
}
@ -112,6 +118,8 @@ _gc_shutdown(E_Gadcon_Client *gcc)
cpufreq_config->instances = eina_list_remove(cpufreq_config->instances, inst);
evas_object_del(inst->o_cpu);
free(inst);
if (cpufreq_config->handler) ecore_event_handler_del(cpufreq_config->handler);
}
static void
@ -232,6 +240,50 @@ _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _cpufreq_menu_governor, l->data);
}
e_menu_item_separator_set(e_menu_item_new(mn), 1);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Restore CPU Power Policy"));
e_menu_item_check_set(mi, 1);
e_menu_item_toggle_set(mi, cpufreq_config->restore_governor);
e_menu_item_callback_set(mi, _cpufreq_menu_restore_governor, NULL);
mn = e_menu_new();
cpufreq_config->menu_powersave = mn;
e_menu_title_set(mn, _("Powersaving policy"));
for (l = cpufreq_config->status->governors; l; l = l->next)
{
if (!strcmp(l->data, "userspace"))
continue;
mi = e_menu_item_new(mn);
if (!strcmp(l->data, "ondemand"))
e_menu_item_label_set(mi, _("Automatic"));
else if (!strcmp(l->data, "conservative"))
e_menu_item_label_set(mi, _("Lower Power Automatic"));
else if (!strcmp(l->data, "powersave"))
e_menu_item_label_set(mi, _("Minimum Speed"));
else if (!strcmp(l->data, "performance"))
e_menu_item_label_set(mi, _("Maximum Speed"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (cpufreq_config->powersave_governor
&& !strcmp(cpufreq_config->powersave_governor, l->data))
e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _cpufreq_menu_powersave_governor, l->data);
}
e_menu_item_separator_set(e_menu_item_new(mn), 1);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Automatic powersaving"));
e_menu_item_check_set(mi, 1);
e_menu_item_toggle_set(mi, cpufreq_config->auto_powersave);
e_menu_item_callback_set(mi, _cpufreq_menu_auto_powersave, NULL);
}
if ((cpufreq_config->status->frequencies) &&
@ -271,12 +323,6 @@ _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
if (cpufreq_config->menu_governor)
{
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Restore CPU Power Policy"));
e_menu_item_check_set(mi, 1);
e_menu_item_toggle_set(mi, cpufreq_config->restore_governor);
e_menu_item_callback_set(mi, _cpufreq_menu_restore_governor, NULL);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Set CPU Power Policy"));
e_menu_item_submenu_set(mi, cpufreq_config->menu_governor);
@ -288,6 +334,12 @@ _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
e_menu_item_label_set(mi, _("Set CPU Speed"));
e_menu_item_submenu_set(mi, cpufreq_config->menu_frequency);
}
if (cpufreq_config->menu_powersave)
{
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Powersaving behavior"));
e_menu_item_submenu_set(mi, cpufreq_config->menu_powersave);
}
e_gadcon_client_util_menu_items_append(inst->gcc, mn, 0);
@ -313,6 +365,8 @@ _menu_cb_post(void *data, E_Menu *m)
cpufreq_config->menu_governor = NULL;
if (cpufreq_config->menu_frequency) e_object_del(E_OBJECT(cpufreq_config->menu_frequency));
cpufreq_config->menu_frequency = NULL;
if (cpufreq_config->menu_powersave) e_object_del(E_OBJECT(cpufreq_config->menu_powersave));
cpufreq_config->menu_powersave = NULL;
}
static void
@ -442,6 +496,7 @@ _cpufreq_status_free(Status *s)
eina_list_free(s->governors);
}
if (s->cur_governor) free(s->cur_governor);
if (s->orig_governor) eina_stringshare_del(s->orig_governor);
free(s);
}
@ -751,6 +806,55 @@ _cpufreq_face_cb_set_governor(void *data, Evas_Object *obj, const char *emission
if (next_governor != NULL) _cpufreq_set_governor(next_governor);
}
static int
_cpufreq_event_cb_powersave(void *data __UNUSED__, int type, void *event)
{
E_Event_Powersave_Update *ev;
Eina_List *l;
Eina_Bool has_powersave, has_conservative;
if (type != E_EVENT_POWERSAVE_UPDATE) return 1;
if (!cpufreq_config->auto_powersave) return 1;
ev = event;
if (!cpufreq_config->status->orig_governor)
cpufreq_config->status->orig_governor = eina_stringshare_add(cpufreq_config->status->cur_governor);
for (l = cpufreq_config->status->governors; l; l = l->next)
{
if (!strcmp(l->data, "conservative"))
has_conservative = EINA_TRUE;
else if (!strcmp(l->data, "powersave"))
has_powersave = EINA_TRUE;
}
switch(ev->mode)
{
case E_POWERSAVE_MODE_NONE:
case E_POWERSAVE_MODE_LOW:
_cpufreq_set_governor(cpufreq_config->status->orig_governor);
eina_stringshare_del(cpufreq_config->status->orig_governor);
cpufreq_config->status->orig_governor = NULL;
break;
case E_POWERSAVE_MODE_MEDIUM:
case E_POWERSAVE_MODE_HIGH:
if (cpufreq_config->powersave_governor || has_conservative)
{
if (cpufreq_config->powersave_governor)
_cpufreq_set_governor(cpufreq_config->powersave_governor);
else
_cpufreq_set_governor("conservative");
break;
}
case E_POWERSAVE_MODE_EXTREME:
if (has_powersave)
_cpufreq_set_governor("powersave");
break;
}
return 1;
}
static void
_cpufreq_menu_fast(void *data, E_Menu *m, E_Menu_Item *mi)
{
@ -819,10 +923,17 @@ _cpufreq_menu_restore_governor(void *data, E_Menu *m, E_Menu_Item *mi)
e_config_save_queue();
}
static void
_cpufreq_menu_auto_powersave(void *data, E_Menu *m, E_Menu_Item *mi)
{
cpufreq_config->auto_powersave = e_menu_item_toggle_get(mi);
e_config_save_queue();
}
static void
_cpufreq_menu_governor(void *data, E_Menu *m, E_Menu_Item *mi)
{
char *governor;
const char *governor;
governor = data;
if (governor)
@ -834,6 +945,21 @@ _cpufreq_menu_governor(void *data, E_Menu *m, E_Menu_Item *mi)
e_config_save_queue();
}
static void
_cpufreq_menu_powersave_governor(void *data, E_Menu *m, E_Menu_Item *mi)
{
const char *governor;
governor = data;
if (governor)
{
if (cpufreq_config->powersave_governor)
eina_stringshare_del(cpufreq_config->powersave_governor);
cpufreq_config->powersave_governor = eina_stringshare_add(governor);
}
e_config_save_queue();
}
static void
_cpufreq_menu_frequency(void * data, E_Menu *m, E_Menu_Item *mi)
{
@ -863,16 +989,25 @@ e_modapi_init(E_Module *m)
#undef D
#define T Config
#define D conf_edd
E_CONFIG_VAL(D, T, config_version, INT);
E_CONFIG_VAL(D, T, poll_interval, INT);
E_CONFIG_VAL(D, T, restore_governor, INT);
E_CONFIG_VAL(D, T, auto_powersave, INT);
E_CONFIG_VAL(D, T, powersave_governor, STR);
E_CONFIG_VAL(D, T, governor, STR);
cpufreq_config = e_config_domain_load("module.cpufreq", conf_edd);
if (cpufreq_config && cpufreq_config->config_version != CPUFREQ_CONFIG_VERSION)
E_FREE(cpufreq_config);
if (!cpufreq_config)
{
cpufreq_config = E_NEW(Config, 1);
cpufreq_config->config_version = CPUFREQ_CONFIG_VERSION;
cpufreq_config->poll_interval = 32;
cpufreq_config->restore_governor = 0;
cpufreq_config->auto_powersave = 1;
cpufreq_config->powersave_governor = NULL;
cpufreq_config->governor = NULL;
}
E_CONFIG_LIMIT(cpufreq_config->poll_interval, 1, 1024);
@ -901,7 +1036,7 @@ e_modapi_init(E_Module *m)
}
cpufreq_config->module = m;
e_gadcon_provider_register(&_gadcon_class);
return m;
}
@ -937,6 +1072,12 @@ e_modapi_shutdown(E_Module *m)
e_object_del(E_OBJECT(cpufreq_config->menu_frequency));
cpufreq_config->menu_frequency = NULL;
}
if (cpufreq_config->menu_powersave)
{
e_menu_post_deactivate_callback_set(cpufreq_config->menu_powersave, NULL, NULL);
e_object_del(E_OBJECT(cpufreq_config->menu_powersave));
cpufreq_config->menu_powersave = NULL;
}
if (cpufreq_config->governor)
eina_stringshare_del(cpufreq_config->governor);
if (cpufreq_config->status) _cpufreq_status_free(cpufreq_config->status);

View File

@ -4,6 +4,8 @@
typedef struct _Status Status;
typedef struct _Config Config;
#define CPUFREQ_CONFIG_VERSION 1
struct _Status
{
Eina_List *frequencies;
@ -11,14 +13,18 @@ struct _Status
int cur_frequency;
int can_set_frequency;
char *cur_governor;
const char *orig_governor;
unsigned char active;
};
struct _Config
{
/* saved * loaded config values */
int config_version;
int poll_interval;
int restore_governor;
int auto_powersave;
const char *powersave_governor;
const char *governor;
/* just config state */
E_Module *module;
@ -27,9 +33,11 @@ struct _Config
E_Menu *menu_poll;
E_Menu *menu_governor;
E_Menu *menu_frequency;
E_Menu *menu_powersave;
Status *status;
char *set_exe_path;
Ecore_Poller *frequency_check_poller;
Ecore_Event_Handler *handler;
};
EAPI extern E_Module_Api e_modapi;