Tizen 2.1 base
[apps/core/preloaded/indicator-win.git] / modules / clock / clock.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *  http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <vconf.h>
20 #include <heynoti.h>
21 #include <runtime_info.h>
22 #include <Ecore_X.h>
23 #include <unicode/udat.h>
24 #include <unicode/udatpg.h>
25
26 #include "common.h"
27 #include "indicator.h"
28 #include "indicator_ui.h"
29 #include "indicator_gui.h"
30 #include "indicator_icon_util.h"
31 #include "modules.h"
32
33 #define SYSTEM_RESUME                           "system_wakeup"
34
35 #define TIME_FONT_SIZE_24       34
36 #define TIME_FONT_SIZE_12       30
37 #define TIME_FONT_SIZE_BATTERY  32
38 #define TIME_FONT_COLOR         243, 243, 243, 255
39
40 #define AMPM_FONT_SIZE          24
41 #define AMPM_FONT_COLOR         243, 243, 243, 255
42 #define LABEL_STRING            "<font_size=%d>%s" \
43                                 "</font_size></font>"
44
45 #define CLOCK_STR_LEN 256
46
47 enum {
48         INDICATOR_CLOCK_MODE_12H = 0,
49         INDICATOR_CLOCK_MODE_24H,
50         INDICATOR_CLOCK_MODE_MAX
51 };
52
53 static int notifd;
54 static int clock_mode = INDICATOR_CLOCK_MODE_12H;
55 static int apm_length = 0;
56 static int apm_position = 0;
57 static Ecore_Timer *timer = NULL;
58 static Ecore_Timer *battery_timer = NULL;
59
60 static int register_clock_module(void *data);
61 static int unregister_clock_module(void);
62 static int hib_enter_clock_module(void);
63 static int hib_leave_clock_module(void *data);
64 static int language_changed_cb(void *data);
65 static int region_changed_cb(void *data);
66
67 #define ICON_PRIORITY   INDICATOR_PRIORITY_FIXED6
68 #define MODULE_NAME             "clock"
69
70 static void indicator_get_time_by_region(char* output, void* data);
71 static void ICU_set_timezone(const char *timezone);
72
73 Indicator_Icon_Object sysclock[INDICATOR_WIN_MAX] = {
74 {
75         .win_type = INDICATOR_WIN_PORT,
76         .type = INDICATOR_TXT_ICON,
77         .name = MODULE_NAME,
78         .priority = ICON_PRIORITY,
79         .always_top = EINA_FALSE,
80         .txt_obj = {0,},
81         .img_obj = {0,},
82         .obj_exist = EINA_FALSE,
83         .exist_in_view = EINA_FALSE,
84         .init = register_clock_module,
85         .fini = unregister_clock_module,
86         .hib_enter = hib_enter_clock_module,
87         .hib_leave = hib_leave_clock_module,
88         .lang_changed = NULL,
89         .region_changed = region_changed_cb,
90         .lang_changed = language_changed_cb
91 },
92 {
93         .win_type = INDICATOR_WIN_LAND,
94         .type = INDICATOR_TXT_ICON,
95         .name = MODULE_NAME,
96         .priority = ICON_PRIORITY,
97         .always_top = EINA_FALSE,
98         .txt_obj = {0,},
99         .img_obj = {0,},
100         .obj_exist = EINA_FALSE,
101         .exist_in_view = EINA_FALSE,
102         .init = register_clock_module,
103         .fini = unregister_clock_module,
104         .hib_enter = hib_enter_clock_module,
105         .hib_leave = hib_leave_clock_module,
106         .lang_changed = NULL,
107         .region_changed = region_changed_cb,
108         .lang_changed = language_changed_cb
109 }
110 };
111
112 static void set_app_state(void* data)
113 {
114         int i = 0;
115
116         for (i=0 ; i<INDICATOR_WIN_MAX ; i++)
117         {
118                 sysclock[i].ad = data;
119         }
120 }
121
122 static void indicator_clock_changed_cb(void *data)
123 {
124         struct appdata *ad = (struct appdata *)data;
125         char time_str[32];
126         char time_buf[128], ampm_buf[128];
127         char buf[CLOCK_STR_LEN];
128         char icu_apm[CLOCK_STR_LEN] = {0,};
129         char apm_result[CLOCK_STR_LEN] ={0,};
130         struct tm *ts = NULL;
131         time_t ctime;
132         int len;
133         int font_size;
134
135         retif(data == NULL, , "Invalid parameter!");
136
137         if (battery_timer != NULL)
138         {
139                 DBG("battery is displaying. ignore clock callback");
140                 return;
141         }
142
143         ctime = time(NULL);
144         ts = localtime(&ctime);
145         if (ts == NULL)
146                 return;
147
148         if (timer != NULL) {
149                 ecore_timer_del(timer);
150                 timer = NULL;
151         }
152
153         memset(time_str, 0x00, sizeof(time_str));
154         memset(time_buf, 0x00, sizeof(time_buf));
155         memset(ampm_buf, 0x00, sizeof(ampm_buf));
156         memset(buf, 0x00, sizeof(buf));
157
158         timer =
159             ecore_timer_add(60 - ts->tm_sec, (void *)indicator_clock_changed_cb,
160                             data);
161
162         indicator_get_time_by_region(icu_apm,data);
163
164         if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
165                 char bf1[32] = { 0, };
166                 int hour;
167
168                 if(apm_length>0 && apm_length<=4)
169                 {
170                         snprintf(ampm_buf, sizeof(ampm_buf),LABEL_STRING, AMPM_FONT_SIZE,icu_apm);
171                 }
172                 else
173                 {
174                         if (ts->tm_hour >= 0 && ts->tm_hour < 12)
175                                 snprintf(ampm_buf, sizeof(ampm_buf),
176                                          LABEL_STRING, AMPM_FONT_SIZE,
177                                          "AM");
178                         else
179                                 snprintf(ampm_buf, sizeof(ampm_buf),
180                                          LABEL_STRING, AMPM_FONT_SIZE,
181                                          "PM");
182                 }
183
184                 strftime(bf1, sizeof(bf1), "%l", ts);
185                 hour = atoi(bf1);
186                 strftime(bf1, sizeof(bf1), ":%M", ts);
187
188                 snprintf(time_str, sizeof(time_str), "%d%s", hour, bf1);
189                 font_size = TIME_FONT_SIZE_12;
190                 indicator_signal_emit(data,"indicator.clock.ampm","indicator.prog");
191         }
192         else{
193                 font_size = TIME_FONT_SIZE_24;
194                 strftime(time_str, sizeof(time_str), "%H:%M", ts);
195                 indicator_signal_emit(data,"indicator.clock.default","indicator.prog");
196         }
197
198         snprintf(time_buf, sizeof(time_buf), LABEL_STRING, font_size, time_str);
199
200         if(apm_position == 0)
201                 len = snprintf(buf, sizeof(buf), "%s%s", ampm_buf, time_buf);
202         else
203                 len = snprintf(buf, sizeof(buf), "%s%s", time_buf, ampm_buf);
204
205         if (len < 0) {
206                 ERR("Unexpected ERROR!");
207                 return;
208         }
209
210         INFO("[CLOCK MODULE] Timer Status : %d Time: %s", timer, buf);
211
212         indicator_part_text_emit(data,"elm.text.clock", buf);
213
214         return;
215 }
216
217 static void indicator_clock_format_changed_cb(keynode_t *node, void *data)
218 {
219         retif(data == NULL, , "Invalid parameter!");
220
221         int r = -1;
222
223         bool is_24hour_enabled = false;
224
225         INFO("[Enter] indicator_clock_format_changed_cb");
226
227         r = runtime_info_get_value_bool(
228                         RUNTIME_INFO_KEY_24HOUR_CLOCK_FORMAT_ENABLED, &is_24hour_enabled);
229
230         if( r==RUNTIME_INFO_ERROR_NONE&&is_24hour_enabled==true)
231         {
232                 clock_mode = INDICATOR_CLOCK_MODE_24H;
233         }
234         else
235         {
236                 clock_mode = INDICATOR_CLOCK_MODE_12H;
237         }
238
239         char *timezone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID);
240         ICU_set_timezone(timezone);
241         indicator_clock_changed_cb(data);
242         free(timezone);
243 }
244
245 static void indicator_clock_battery_changed_cb(keynode_t *node, void *data)
246 {
247         indicator_clock_display_battery_percentage(data);
248 }
249
250 static void indicator_clock_battery_display_cb(void *data)
251 {
252         int ret = 0;
253
254         if (battery_timer != NULL) {
255                 ecore_timer_del(battery_timer);
256                 battery_timer = NULL;
257         }
258
259         ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
260                                                indicator_clock_battery_changed_cb);
261         if (ret != OK)
262                 ERR("Fail: unregister VCONFKEY_REGIONFORMAT_TIME1224");
263
264         indicator_clock_changed_cb(data);
265 }
266
267 void indicator_clock_display_battery_percentage(void *data)
268 {
269         int ret = FAIL;
270         int status = 0;
271         int battery_capa = 0;
272         char buf[256] = {0,};
273         char temp[256] = {0,};
274
275         ret = vconf_get_bool(VCONFKEY_SETAPPL_BATTERY_PERCENTAGE_BOOL, &status);
276         if (ret != OK)
277                 ERR("Fail to get [%s: %d]",
278                         VCONFKEY_SETAPPL_BATTERY_PERCENTAGE_BOOL, ret);
279
280         if(status)
281         {
282                 ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &battery_capa);
283                 if (ret != OK)
284                 {
285                         ERR("Fail to get [VCONFKEY_SYSMAN_BATTERY_CAPACITY:%d]", ret);
286                         return;
287                 }
288                 if (battery_capa < 0)
289                 {
290                         INFO("Invalid Battery Capacity: %d", battery_capa);
291                         return;
292                 }
293
294                 INFO("Battery Capacity: %d", battery_capa);
295
296                 if (battery_capa > 100)
297                         battery_capa = 100;
298
299                 snprintf(temp, sizeof(temp), "%d%%",battery_capa);
300
301                 snprintf(buf, sizeof(buf), LABEL_STRING, TIME_FONT_SIZE_BATTERY, temp);
302
303                 INFO("indicator_clock_display_battery_percentage %s", buf);
304
305                 indicator_part_text_emit(data,"elm.text.clock", buf);
306
307                 ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
308                                                indicator_clock_battery_changed_cb, data);
309                 if (ret != OK) {
310                         ERR("Fail: register VCONFKEY_REGIONFORMAT_TIME1224");
311                         return;
312                 }
313
314                 battery_timer =  ecore_timer_add(3, (void *)indicator_clock_battery_display_cb,data);
315         }
316
317 }
318
319
320 static int language_changed_cb(void *data)
321 {
322         DBG("language_changed_cb");
323         indicator_clock_changed_cb(data);
324         return OK;
325 }
326
327 static int region_changed_cb(void *data)
328 {
329         DBG("region_changed_cb");
330         indicator_clock_format_changed_cb(NULL, data);
331         return OK;
332 }
333
334 static int register_clock_module(void *data)
335 {
336         int r = 0, ret = -1;
337
338         retif(data == NULL, FAIL, "Invalid parameter!");
339
340         set_app_state(data);
341
342         notifd = heynoti_init();
343
344         if (notifd < 0) {
345                 ERR("heynoti_init is failed");
346                 return r;
347         }
348
349         ret =
350             heynoti_subscribe(notifd, SYSTEM_RESUME, indicator_clock_changed_cb,
351                               data);
352         if (ret != OK) {
353                 ERR("Fail: register SYSTEM_RESUME");
354                 r = r | ret;
355         }
356
357         ret = heynoti_attach_handler(notifd);
358         if (ret != OK) {
359                 ERR("Failed to attach heynoti handler!");
360                 r = r | ret;
361         }
362
363         ret = vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
364                                        indicator_clock_format_changed_cb, data);
365         if (ret != OK) {
366                 ERR("Fail: register VCONFKEY_SYSTEM_TIME_CHANGED");
367                 r = r | ret;
368         }
369
370         ret = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224,
371                                        indicator_clock_format_changed_cb, data);
372         if (ret != OK) {
373                 ERR("Fail: register VCONFKEY_REGIONFORMAT_TIME1224");
374                 r = r | ret;
375         }
376
377         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT,
378                                        indicator_clock_format_changed_cb, data);
379         if (ret != OK) {
380                 ERR("Fail: register VCONFKEY_SETAPPL_TIMEZONE_INT");
381                 r = r | ret;
382         }
383
384         ret = vconf_notify_key_changed(VCONFKEY_PM_STATE, indicator_clock_format_changed_cb, (void *)data);
385
386         if (ret != OK) {
387                 ERR("Fail: register VCONFKEY_PM_STATE");
388                 r = r | ret;
389         }
390
391         indicator_clock_format_changed_cb(NULL, data);
392
393         return r;
394 }
395
396 static int unregister_clock_module(void)
397 {
398         int ret;
399
400         heynoti_unsubscribe(notifd, SYSTEM_RESUME, indicator_clock_changed_cb);
401
402         heynoti_close(notifd);
403         notifd = 0;
404
405         ret = vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
406                                                indicator_clock_format_changed_cb);
407         if (ret != OK)
408                 ERR("Fail: unregister VCONFKEY_SYSTEM_TIME_CHANGED");
409
410         ret = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224,
411                                        indicator_clock_format_changed_cb);
412         if (ret != OK)
413                 ERR("Fail: unregister VCONFKEY_REGIONFORMAT_TIME1224");
414
415         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT,
416                                        indicator_clock_format_changed_cb);
417         if (ret != OK)
418                 ERR("Fail: unregister VCONFKEY_SETAPPL_TIMEZONE_INT");
419
420         ret = vconf_ignore_key_changed(VCONFKEY_PM_STATE,
421                                                indicator_clock_format_changed_cb);
422         if (ret != OK)
423                 ERR("Fail: unregister VCONFKEY_PM_STATE");
424
425         if (timer != NULL) {
426                 ecore_timer_del(timer);
427                 timer = NULL;
428         }
429         return OK;
430 }
431
432 static int hib_enter_clock_module(void)
433 {
434         int ret;
435
436         ret = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224,
437                                        indicator_clock_format_changed_cb);
438         if (ret != OK)
439                 ERR("Fail: unregister VCONFKEY_REGIONFORMAT_TIME1224");
440
441         if (timer != NULL) {
442                 ecore_timer_del(timer);
443                 timer = NULL;
444         }
445
446         return OK;
447 }
448
449 static int hib_leave_clock_module(void *data)
450 {
451         int ret;
452
453         retif(data == NULL, FAIL, "Invalid parameter!");
454
455         ret = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224,
456                                        indicator_clock_format_changed_cb, data);
457         retif(ret != OK, FAIL, "Failed to register callback!");
458
459         indicator_clock_format_changed_cb(NULL, data);
460         return OK;
461 }
462
463 void indicator_get_time_by_region(char* output,void *data)
464 {
465         retif(data == NULL, NULL, "Data parameter is NULL");
466         retif(output == NULL, NULL, "output parameter is NULL");
467
468
469         UChar customSkeleton[CLOCK_STR_LEN] = { 0, };
470         UErrorCode status = U_ZERO_ERROR;
471         UDateFormat *formatter = NULL;
472
473         UChar bestPattern[CLOCK_STR_LEN] = { 0, };
474         UChar formatted[CLOCK_STR_LEN] = { 0, };
475
476         char bestPatternString[CLOCK_STR_LEN] = { 0, };
477         char formattedString[CLOCK_STR_LEN] = { 0, };
478
479         UDateTimePatternGenerator *pattern_generator = NULL;
480
481         char *time_skeleton = "hhmm";
482
483         char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
484         if (locale == NULL) {
485                 DBG("[Error] get value of VCONFKEY_REGIONFORMAT fail.");
486         }
487
488         u_uastrncpy(customSkeleton, time_skeleton, strlen(time_skeleton));
489
490         pattern_generator = udatpg_open(locale, &status);
491
492         int32_t bestPatternCapacity = (int32_t) (sizeof(bestPattern) / sizeof((bestPattern)[0]));
493         (void)udatpg_getBestPattern(pattern_generator, customSkeleton,
494                                     u_strlen(customSkeleton), bestPattern,
495                                     bestPatternCapacity, &status);
496
497         u_austrcpy(bestPatternString, bestPattern);
498         u_uastrcpy(bestPattern,"a");
499
500         if(bestPatternString[0] == 'a')
501         {
502                 apm_position = 0;
503         }
504         else
505         {
506                 apm_position = 1;
507         }
508
509         UDate date = ucal_getNow();
510         formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale, NULL, -1, bestPattern, -1, &status);
511         int32_t formattedCapacity = (int32_t) (sizeof(formatted) / sizeof((formatted)[0]));
512         (void)udat_format(formatter, date, formatted, formattedCapacity, NULL, &status);
513         u_austrcpy(formattedString, formatted);
514
515         DBG("DATE & TIME is %s %s %d %s", locale, formattedString, u_strlen(formatted), bestPatternString);
516
517         apm_length = u_strlen(formatted);
518
519         udatpg_close(pattern_generator);
520
521         udat_close(formatter);
522
523         if(strlen(formattedString)<CLOCK_STR_LEN)
524         {
525                 strncpy(output,formattedString,strlen(formattedString));
526         }
527         else
528         {
529                 strncpy(output,formattedString,CLOCK_STR_LEN-1);
530         }
531
532         return;
533 }
534
535 static UChar *uastrcpy(const char *chars)
536 {
537         int len = 0;
538         UChar *str = NULL;
539         len = strlen(chars);
540         str = (UChar *) malloc(sizeof(UChar) *(len + 1));
541         if (!str)
542                 return NULL;
543         u_uastrcpy(str, chars);
544         return str;
545 }
546
547 static void ICU_set_timezone(const char *timezone)
548 {
549         DBG("ICU_set_timezone = %s ", timezone);
550         UErrorCode ec = U_ZERO_ERROR;
551         UChar *str = uastrcpy(timezone);
552
553         ucal_setDefaultTimeZone(str, &ec);
554         if (U_SUCCESS(ec)) {
555                 DBG("ucal_setDefaultTimeZone() SUCCESS ");
556         } else {
557                 DBG("ucal_setDefaultTimeZone() FAILED : %s ",
558                               u_errorName(ec));
559         }
560         free(str);
561 }
562
563