update for beta release
[framework/uifw/e17.git] / src / bin / e_backlight.c
1 #include "e.h"
2 #ifdef HAVE_EEZE
3 # include <Eeze.h>
4 #endif
5
6 // FIXME: backlight should be tied per zone but this implementation is just
7 // a signleton right now as thats 99% of use cases. but api supports
8 // doing more. for now make it work in the singleton
9
10 #define MODE_NONE  -1
11 #define MODE_RANDR 0
12 #define MODE_SYS   1
13
14 static double bl_val = 1.0;
15 static double bl_animval = 1.0;
16 static E_Backlight_Mode bl_mode = E_BACKLIGHT_MODE_NORMAL;
17 static int sysmode = MODE_NONE;
18 static Ecore_Animator *bl_anim = NULL;
19
20 static void _e_backlight_update(E_Zone *zone);
21 static void _e_backlight_set(E_Zone *zone, double val);
22 static Eina_Bool _bl_anim(void *data, double pos);
23 static Eina_Bool bl_avail = EINA_FALSE;
24 #ifdef HAVE_EEZE
25 static const char *bl_sysval = NULL;
26 static Ecore_Event_Handler *bl_sys_exit_handler = NULL;
27 static Ecore_Exe *bl_sys_set_exe = NULL;
28 static Eina_Bool bl_sys_pending_set = EINA_FALSE;
29 static Eina_Bool bl_sys_set_exe_ready = EINA_TRUE;
30
31 static void _bl_sys_find(void);
32 static void _bl_sys_level_get(void);
33 static Eina_Bool _e_bl_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event);
34 static void _bl_sys_level_set(double val);
35 #endif
36
37 EINTERN int
38 e_backlight_init(void)
39 {
40 #ifdef HAVE_EEZE
41    eeze_init();
42 #endif
43    bl_avail = ecore_x_randr_output_backlight_available();
44
45    if (bl_avail == EINA_TRUE)
46      {
47         e_backlight_update();
48         e_backlight_level_set(NULL, 0.0, 0.0);
49         e_backlight_level_set(NULL, e_config->backlight.normal, 1.0);
50      }
51    return 1;
52 }
53
54 EINTERN int
55 e_backlight_shutdown(void)
56 {
57    if (bl_anim) ecore_animator_del(bl_anim);
58    bl_anim = NULL;
59 #ifdef HAVE_EEZE
60    if (bl_sysval) eina_stringshare_del(bl_sysval);
61    bl_sysval = NULL;
62    if (bl_sys_exit_handler) ecore_event_handler_del(bl_sys_exit_handler);
63    bl_sys_exit_handler = NULL;
64    bl_sys_set_exe = NULL;
65    bl_sys_pending_set = EINA_FALSE;
66    eeze_shutdown();
67 #endif
68    return 1;
69 }
70
71 EAPI Eina_Bool
72 e_backlight_exists(void)
73 {
74    if (sysmode == MODE_NONE) return EINA_FALSE;
75    return EINA_TRUE;
76 }
77
78 EAPI void
79 e_backlight_update(void)
80 {
81    Eina_List *m, *c, *z;
82    E_Manager *man;
83    E_Container *con;
84    E_Zone *zone;
85
86    if (bl_avail == EINA_TRUE)
87      {
88         EINA_LIST_FOREACH(e_manager_list(), m, man)
89           {
90              EINA_LIST_FOREACH(man->containers, c, con)
91                {
92                   EINA_LIST_FOREACH(con->zones, z, zone)
93                     {
94                        _e_backlight_update(zone);
95                     }
96                }
97           }
98      }
99 }
100
101 EAPI void
102 e_backlight_level_set(E_Zone *zone, double val, double tim)
103 {
104    double bl_now;
105    // zone == NULL == everything
106    // set backlight associated with zone to val over period of tim
107    // if tim == 0.0 - then do it instantnly, if time == -1 use some default
108    // transition time
109    if (val < 0.0) val = 0.0;
110    else if (val > 1.0) val = 1.0;
111    if (val == bl_val) return;
112    if (!zone) zone = e_util_zone_current_get(e_manager_current_get());
113    bl_now = bl_val;
114    bl_val = val;
115    if (bl_mode != E_BACKLIGHT_MODE_NORMAL) return;
116    if (tim < 0.0) tim = e_config->backlight.transition;
117    if (tim == 0.0)
118      {
119         if (bl_anim)
120           {
121              ecore_animator_del(bl_anim);
122              bl_anim = NULL;
123           }
124         _e_backlight_set(zone, val);
125        return;
126      }
127    if (bl_anim) ecore_animator_del(bl_anim);
128    bl_anim = ecore_animator_timeline_add(tim, _bl_anim, zone);
129    bl_animval = bl_now;
130 }
131
132 EAPI double
133 e_backlight_level_get(E_Zone *zone __UNUSED__)
134 {
135    // zone == NULL == everything
136    return bl_val;
137 }
138
139 EAPI void
140 e_backlight_mode_set(E_Zone *zone, E_Backlight_Mode mode)
141 {
142    // zone == NULL == everything
143    if (bl_mode == mode) return;
144    bl_mode = mode;
145    if      (bl_mode == E_BACKLIGHT_MODE_NORMAL)
146       e_backlight_level_set(zone, bl_val, -1.0);
147    else if (bl_mode == E_BACKLIGHT_MODE_OFF)
148       e_backlight_level_set(zone, 0.0, -1.0);
149    else if (bl_mode == E_BACKLIGHT_MODE_DIM)
150       e_backlight_level_set(zone, e_config->backlight.dim, -1.0);
151    else if (bl_mode == E_BACKLIGHT_MODE_MAX)
152       e_backlight_level_set(zone, 1.0, -1.0);
153 }
154
155 EAPI E_Backlight_Mode
156 e_backlight_mode_get(E_Zone *zone __UNUSED__)
157 {
158    // zone == NULL == everything
159    return bl_mode;
160 }
161
162 /* local subsystem functions */
163
164 static void
165 _e_backlight_update(E_Zone *zone)
166 {
167    double x_bl = -1.0;
168    Ecore_X_Window root;
169    Ecore_X_Randr_Output *out;
170    int num = 0;
171
172    root = zone->container->manager->root;
173    // try randr
174    out = ecore_x_randr_window_outputs_get(root, &num);
175    if ((out) && (num > 0))
176       x_bl = ecore_x_randr_output_backlight_level_get(root, out[0]);
177    if (out) free(out);
178    if (x_bl >= 0.0)
179      {
180         bl_val = x_bl;
181         sysmode = MODE_RANDR;
182      }
183 #ifdef HAVE_EEZE
184    else
185      {
186         _bl_sys_find();
187         if (bl_sysval)
188           {
189              sysmode = MODE_SYS;
190              _bl_sys_level_get();
191           }
192      }
193 #endif
194 }
195
196 static void
197 _e_backlight_set(E_Zone *zone, double val)
198 {
199    if (sysmode == MODE_RANDR)
200      {
201         Ecore_X_Window root;
202         Ecore_X_Randr_Output *out;
203         int num = 0;
204         
205         root = zone->container->manager->root;
206         out = ecore_x_randr_window_outputs_get(root, &num);
207         if ((out) && (num > 0))
208           {
209              ecore_x_randr_output_backlight_level_set(root, out[0], val);
210           }
211         if (out) free(out);
212      }
213 #ifdef HAVE_EEZE
214    else if (sysmode == MODE_SYS)
215      {
216         if (bl_sysval)
217           {
218              _bl_sys_level_set(val);
219           }
220      }
221 #endif
222 }
223
224 static Eina_Bool
225 _bl_anim(void *data, double pos)
226 {
227    E_Zone *zone = data;
228    double v;
229    
230    // FIXME: if zone is deleted while anim going... bad things.
231    pos = ecore_animator_pos_map(pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
232    v = (bl_animval * (1.0 - pos)) + (bl_val *pos);
233    _e_backlight_set(zone, v);
234    if (pos >= 1.0)
235      {
236         bl_anim = NULL;
237         return EINA_FALSE;
238      }
239    return EINA_TRUE;
240 }
241
242 #ifdef HAVE_EEZE
243 static void
244 _bl_sys_find(void)
245 {
246    Eina_List *devs;
247    const char *f;
248
249    devs = eeze_udev_find_by_filter("backlight", NULL, NULL);
250    if (!devs) return;
251    EINA_LIST_FREE(devs, f)
252      bl_sysval = f;
253 }
254
255 static void
256 _bl_sys_level_get(void)
257 {
258    int maxval, val;
259    const char *str;
260
261    str = eeze_udev_syspath_get_sysattr(bl_sysval, "max_brightness");
262    if (!str) return;
263
264    maxval = atoi(str);
265    eina_stringshare_del(str);
266    if (maxval <= 0) maxval = 255;
267    str = eeze_udev_syspath_get_sysattr(bl_sysval, "brightness");
268    if (!str) return;
269
270    val = atoi(str);
271    eina_stringshare_del(str);
272    if ((val >= 0) && (val <= maxval))
273      bl_val = (double)val / (double)maxval;
274 // printf("GET: %i/%i (%1.3f)\n", val, maxval, bl_val);
275 }
276
277 static Eina_Bool
278 _e_bl_cb_ext_delay(void *data __UNUSED__)
279 {
280    bl_sys_set_exe_ready = EINA_TRUE;
281    if (bl_sys_pending_set)
282      {
283         bl_sys_pending_set = EINA_FALSE;
284         _bl_sys_level_set(bl_val);
285      }
286    return EINA_FALSE;
287 }
288
289 static Eina_Bool
290 _e_bl_cb_exit(void *data __UNUSED__, int type __UNUSED__, void *event)
291 {
292    Ecore_Exe_Event_Del *ev;
293    
294    ev = event;
295    if (ev->exe == bl_sys_set_exe)
296      {
297         bl_sys_set_exe_ready = EINA_FALSE;
298         bl_sys_set_exe = NULL;
299         ecore_timer_add(0.1, _e_bl_cb_ext_delay, NULL);
300      }
301    return ECORE_CALLBACK_RENEW;
302 }
303
304 static void
305 _bl_sys_level_set(double val)
306 {
307    char buf[PATH_MAX];
308    
309    if (!bl_sys_exit_handler)
310       bl_sys_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
311                                                     _e_bl_cb_exit, NULL);
312    if ((bl_sys_set_exe) || (!bl_sys_set_exe_ready))
313      {
314         bl_sys_pending_set = EINA_TRUE;
315         return;
316      }
317 //   printf("SET: %1.3f\n", val);
318    snprintf(buf, sizeof(buf), 
319             "%s/enlightenment/utils/enlightenment_backlight %i", 
320             e_prefix_lib_get(), (int)(val * 1000.0));
321    bl_sys_set_exe = ecore_exe_run(buf, NULL);
322 }
323 #endif