4 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 //#include <Ecore_X.h>
25 #include <unicode/udat.h>
26 #include <unicode/udatpg.h>
27 #include <unicode/ustring.h>
28 #include <system_settings.h>
31 #include "indicator.h"
33 #include "indicator_gui.h"
40 #define SYSTEM_RESUME "system_wakeup"
42 #define TIME_FONT_SIZE_24 ELM_SCALE_SIZE(30)
43 #define TIME_FONT_SIZE_12 ELM_SCALE_SIZE(30)
44 #define AMPM_FONT_SIZE ELM_SCALE_SIZE(29)
46 #define TIME_FONT_COLOR 200, 200, 200, 255
47 #define AMPM_FONT_COLOR 200, 200, 200, 255
48 #define LABEL_STRING "<font_size=%d>%s" \
50 #define LABEL_STRING_FONT "%s</font>"
52 #define BATTERY_TIMER_INTERVAL 3
53 #define BATTERY_TIMER_INTERVAL_CHARGING 30
55 #define CLOCK_STR_LEN 128
58 INDICATOR_CLOCK_MODE_12H = 0,
59 INDICATOR_CLOCK_MODE_24H,
60 INDICATOR_CLOCK_MODE_MAX
63 int clock_mode = INDICATOR_CLOCK_MODE_12H;
65 static const char *colon = ":";
66 static const char *ratio = "∶";
68 static int apm_length = 0;
69 static int apm_position = 0;
70 extern Ecore_Timer *clock_timer;
72 static UDateTimePatternGenerator *_last_generator = NULL;
73 static char *_last_locale = NULL;
74 static int battery_charging = 0;
76 static int register_clock_module(void *data);
77 static int unregister_clock_module(void);
78 static int language_changed_cb(void *data);
79 static int region_changed_cb(void *data);
80 static int wake_up_cb(void *data);
81 #ifdef _SUPPORT_SCREEN_READER
82 static int register_clock_tts(void *data,int win_type);
85 #define ICON_PRIORITY INDICATOR_PRIORITY_FIXED8
86 #define MODULE_NAME "clock"
88 static void indicator_get_apm_by_region(char* output, void* data);
89 static void indicator_get_time_by_region(char* output, void* data);
91 static void ICU_set_timezone(const char *timezone);
94 .type = INDICATOR_TXT_ICON,
96 .priority = ICON_PRIORITY,
97 .always_top = EINA_FALSE,
99 .obj_exist = EINA_FALSE,
100 .exist_in_view = EINA_FALSE,
101 .init = register_clock_module,
102 .fini = unregister_clock_module,
103 .lang_changed = NULL,
104 .region_changed = region_changed_cb,
105 .lang_changed = language_changed_cb,
106 .wake_up = wake_up_cb,
111 void cal_delete_last_generator(void)
117 if (_last_generator) {
118 udatpg_close(_last_generator);
119 _last_generator = NULL;
125 static UDateTimePatternGenerator *__cal_get_pattern_generator(const char *locale, UErrorCode *status)
127 if (!_last_generator || !_last_locale || strcmp(locale, _last_locale)) {
129 cal_delete_last_generator();
131 _last_locale = strdup(locale);
133 _last_generator = udatpg_open(locale, status);
136 return _last_generator;
141 static void set_app_state(void* data)
148 static void indicator_clock_changed_cb(void *data)
150 char time_str[CLOCK_STR_LEN] = {0,};
151 char time_buf[CLOCK_STR_LEN] = {0,};
152 char ampm_buf[CLOCK_STR_LEN] = {0,};
153 char ampm_str[CLOCK_STR_LEN] = {0,};
154 char buf[CLOCK_STR_LEN] = {0,};
155 char result[CLOCK_STR_LEN] = {0,};
156 char icu_apm[CLOCK_STR_LEN] = {0,};
158 struct tm *ts = NULL;
160 struct appdata *ad = NULL;
163 int ampm_size = AMPM_FONT_SIZE;
167 ad = (struct appdata *)data;
169 if (icon_get_update_flag() == 0) return;
173 localtime_r(&ctime, ts);
175 _E("Fail to get localtime !");
179 if (clock_timer != NULL) {
180 ecore_timer_del(clock_timer);
184 memset(time_str, 0x00, sizeof(time_str));
185 memset(ampm_str, 0x00, sizeof(ampm_str));
186 memset(time_buf, 0x00, sizeof(time_buf));
187 memset(ampm_buf, 0x00, sizeof(ampm_buf));
188 memset(buf, 0x00, sizeof(buf));
190 clock_timer = ecore_timer_add(60 - ts->tm_sec, (void *)indicator_clock_changed_cb, data);
192 _E("Fail to add timer !");
195 indicator_get_apm_by_region(icu_apm,data);
196 indicator_get_time_by_region(time_buf,data);
199 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
200 char bf1[32] = { 0, };
202 static int pre_hour = 0;
203 const char *region = NULL;
205 int bRegioncheck = 0;
206 char *lang1 = "it_IT";
208 region = vconf_get_str(VCONFKEY_REGIONFORMAT);
211 if (strncmp(region,lang1,strlen(lang1)) == 0) bRegioncheck = 1;
213 if (apm_length>=4 || bRegioncheck==1) {
214 if (ts->tm_hour >= 0 && ts->tm_hour < 12) {
215 snprintf(ampm_buf, sizeof(ampm_buf),"%s","AM");
217 snprintf(ampm_buf, sizeof(ampm_buf),"%s","PM");
220 snprintf(ampm_buf, sizeof(ampm_buf),"%s",icu_apm);
223 strftime(bf1, sizeof(bf1), "%l", ts);
225 strftime(bf1, sizeof(bf1), ":%M", ts);
227 font_size = TIME_FONT_SIZE_12;
230 if ((pre_hour<10 && hour>=10)||(pre_hour>=10 && hour<10)) {
231 box_update_display(&(ad->win));
236 font_size = TIME_FONT_SIZE_24;
239 snprintf(time_str, sizeof(time_str), LABEL_STRING, font_size, time_buf);
240 snprintf(ampm_str, sizeof(ampm_str), LABEL_STRING, ampm_size, ampm_buf);
242 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
243 if (apm_position == 0) {
244 len = snprintf(buf, sizeof(buf), "%s %s", ampm_str, time_str);
246 len = snprintf(buf, sizeof(buf), "%s %s", time_str, ampm_str);
249 len = snprintf(buf, sizeof(buf), "%s", time_str);
252 snprintf(result, sizeof(result), LABEL_STRING_FONT, buf);
254 _E("Unexpected ERROR!");
258 _D("[CLOCK MODULE] Timer Status : %d Time: %s", clock_timer, result);
259 util_part_text_emit(data, "elm.text.clock", result);
266 static void _clock_format_changed_cb(keynode_t *node, void *data)
268 struct appdata *ad = NULL;
273 ad = (struct appdata *)data;
275 if (vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224,&mode_24) < 0)
277 ERR("Error getting VCONFKEY_REGIONFORMAT_TIME1224 value");
281 /* Check Time format. If timeformat have invalid value, Set to 12H */
282 if( mode_24==VCONFKEY_TIME_FORMAT_24)
284 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
286 clock_mode = INDICATOR_CLOCK_MODE_24H;
287 box_update_display(&(ad->win));
292 if(clock_mode==INDICATOR_CLOCK_MODE_24H)
294 clock_mode = INDICATOR_CLOCK_MODE_12H;
295 box_update_display(&(ad->win));
299 char *timezone = util_get_timezone_str();
300 ICU_set_timezone(timezone);
301 indicator_clock_changed_cb(data);
308 static void indicator_clock_charging_now_cb(keynode_t *node, void *data)
312 retif(data == NULL, , "Invalid parameter!");
315 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &status);
317 battery_charging = status;
322 static int language_changed_cb(void *data)
324 const char *pa_lang = vconf_get_str(VCONFKEY_LANGSET);
325 DBG("language_changed_cb %s",pa_lang);
326 indicator_clock_changed_cb(data);
332 static int region_changed_cb(void *data)
334 _clock_format_changed_cb(NULL, data);
340 static int wake_up_cb(void *data)
342 indicator_clock_changed_cb(data);
349 /*static void _time_changed(system_settings_key_e key, void *data)
351 DBG("_time_changed");
352 _clock_format_changed_cb(NULL,data);
357 static void regionformat_changed(keynode_t *node, void *data)
359 DBG("regionformat_changed");
360 _clock_format_changed_cb(NULL,data);
365 static void timezone_int_changed(keynode_t *node, void *data)
367 DBG("timezone_int_changed");
368 _clock_format_changed_cb(NULL,data);
373 static void timezone_id_changed(keynode_t *node, void *data)
375 char *szTimezone = NULL;
376 szTimezone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID);
378 DBG("timezone_id_changed %s",szTimezone);
379 _clock_format_changed_cb(NULL,data);
384 static int register_clock_module(void *data)
388 retif(data == NULL, FAIL, "Invalid parameter!");
392 /*ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_TIME_CHANGED, _time_changed, data);
397 ret = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, regionformat_changed, data);
402 ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, timezone_int_changed, data);
407 ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, timezone_id_changed, data);
412 ret = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, regionformat_changed, data);
416 _clock_format_changed_cb(NULL, data);
417 indicator_clock_charging_now_cb(NULL,data);
424 static int unregister_clock_module(void)
428 //ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_TIME_CHANGED);
429 ret = ret | vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, regionformat_changed);
430 ret = ret | vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, timezone_int_changed);
431 ret = ret | vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, timezone_id_changed);
432 ret = ret | vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, regionformat_changed);
434 if (clock_timer != NULL) {
435 ecore_timer_del(clock_timer);
439 cal_delete_last_generator();
446 static inline char *_extend_heap(char *buffer, int *sz, int incsz)
451 tmp = realloc(buffer, *sz);
462 static char *_string_replacer(const char *src, const char *pattern, const char *replace)
479 if (!src || !pattern)
482 out_sz = strlen(src);
489 replace_len = strlen(replace);
496 for (state = STATE_START, ptr = src; state != STATE_END; ptr++) {
501 } else if (!isblank(*ptr)) {
509 } else if (*ptr == *pattern) {
516 if (out_idx == out_sz) {
517 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
529 * If there is no space for copying the replacement,
530 * Extend size of the return buffer.
532 if (out_sz - out_idx < replace_len + 1) {
533 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
541 strncpy(ret + out_idx, replace, replace_len);
542 out_idx += strlen(replace);
546 } else if (*ptr != pattern[idx]) {
549 /* Copy the first matched character */
552 if (out_idx == out_sz) {
553 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
578 void indicator_get_apm_by_region(char* output,void *data)
580 retif(data == NULL, , "Data parameter is NULL");
581 retif(output == NULL, , "output parameter is NULL");
584 UChar customSkeleton[CLOCK_STR_LEN] = { 0, };
585 UChar u_timezone[64] = {0,};
587 UErrorCode status = U_ZERO_ERROR;
588 UDateFormat *formatter = NULL;
590 UChar bestPattern[CLOCK_STR_LEN] = { 0, };
591 UChar formatted[CLOCK_STR_LEN] = { 0, };
593 char bestPatternString[CLOCK_STR_LEN] = { 0, };
594 char formattedString[CLOCK_STR_LEN] = { 0, };
596 UDateTimePatternGenerator *pattern_generator = NULL;
598 char *time_skeleton = "hhmm";
600 char* timezone_id = NULL;
601 timezone_id = util_get_timezone_str();
603 char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
606 ERR("[Error] get value of fail.");
611 /* Remove ".UTF-8" in locale */
612 char locale_tmp[32] = {0,};
613 strncpy(locale_tmp, locale, sizeof(locale_tmp)-1);
614 char *p = util_safe_str(locale_tmp, ".UTF-8");
619 u_uastrncpy(customSkeleton, time_skeleton, strlen(time_skeleton));
621 pattern_generator = __cal_get_pattern_generator (locale_tmp, &status);
622 if (pattern_generator == NULL) {
626 int32_t bestPatternCapacity = (int32_t) (sizeof(bestPattern) / sizeof((bestPattern)[0]));
627 (void)udatpg_getBestPattern(pattern_generator, customSkeleton,
628 u_strlen(customSkeleton), bestPattern,
629 bestPatternCapacity, &status);
631 u_austrcpy(bestPatternString, bestPattern);
632 u_uastrcpy(bestPattern,"a");
634 DBG("TimeZone is %s", timezone_id);
636 if(bestPatternString[0] == 'a')
645 UDate date = ucal_getNow();
648 u_uastrncpy(u_timezone, timezone_id, sizeof(u_timezone));
649 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, u_timezone, -1, bestPattern, -1, &status);
653 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, NULL, -1, bestPattern, -1, &status);
655 if (formatter == NULL) {
659 int32_t formattedCapacity = (int32_t) (sizeof(formatted) / sizeof((formatted)[0]));
660 (void)udat_format(formatter, date, formatted, formattedCapacity, NULL, &status);
661 u_austrcpy(formattedString, formatted);
663 apm_length = u_strlen(formatted);
665 udat_close(formatter);
667 if(strlen(formattedString)<CLOCK_STR_LEN)
669 strncpy(output,formattedString,strlen(formattedString));
673 strncpy(output,formattedString,CLOCK_STR_LEN-1);
681 void indicator_get_time_by_region(char* output,void *data)
683 retif(data == NULL, , "Data parameter is NULL");
684 retif(output == NULL, , "output parameter is NULL");
686 UChar customSkeleton[CLOCK_STR_LEN] = { 0, };
687 UChar u_timezone[64] = {0,};
689 UErrorCode status = U_ZERO_ERROR;
690 UDateFormat *formatter = NULL;
692 UChar bestPattern[CLOCK_STR_LEN] = { 0, };
693 UChar formatted[CLOCK_STR_LEN] = { 0, };
695 char bestPatternString[CLOCK_STR_LEN] = { 0, };
696 char formattedString[CLOCK_STR_LEN] = { 0, };
697 char* convertFormattedString = NULL;
699 char time_skeleton[20] = {0,};
700 UDateTimePatternGenerator *pattern_generator = NULL;
702 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
704 strncpy(time_skeleton,"hm", 2);
708 strncpy(time_skeleton,"Hm", 2);
710 char* timezone_id = NULL;
711 timezone_id = util_get_timezone_str();
713 char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
716 ERR("[Error] get value of fail.");
721 /* Remove ".UTF-8" in locale */
722 char locale_tmp[32] = {0,};
723 strncpy(locale_tmp, locale, sizeof(locale_tmp)-1);
724 char *p = util_safe_str(locale_tmp, ".UTF-8");
729 u_uastrncpy(customSkeleton, time_skeleton, strlen(time_skeleton));
731 pattern_generator = __cal_get_pattern_generator (locale_tmp, &status);
732 if (pattern_generator == NULL) {
736 int32_t bestPatternCapacity = (int32_t) (sizeof(bestPattern) / sizeof((bestPattern)[0]));
737 (void)udatpg_getBestPattern(pattern_generator, customSkeleton,
738 u_strlen(customSkeleton), bestPattern,
739 bestPatternCapacity, &status);
741 char a_best_pattern[64] = {0,};
742 char *last_pattern = NULL;
743 u_austrcpy(a_best_pattern, bestPattern);
744 char *a_best_pattern_fixed = strtok_r(a_best_pattern, "a", &last_pattern);
745 a_best_pattern_fixed = strtok_r(a_best_pattern_fixed, " ", &last_pattern);
746 if(a_best_pattern_fixed)
748 u_uastrcpy(bestPattern, a_best_pattern_fixed);
751 u_austrcpy(bestPatternString, bestPattern);
753 DBG("BestPattern is %s", bestPatternString);
754 DBG("TimeZone is %s", timezone_id);
756 UDate date = ucal_getNow();
759 u_uastrncpy(u_timezone, timezone_id, sizeof(u_timezone));
760 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, u_timezone, -1, bestPattern, -1, &status);
764 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, NULL, -1, bestPattern, -1, &status);
767 if (formatter == NULL) {
770 int32_t formattedCapacity = (int32_t) (sizeof(formatted) / sizeof((formatted)[0]));
771 (void)udat_format(formatter, date, formatted, formattedCapacity, NULL, &status);
772 u_austrcpy(formattedString, formatted);
773 DBG("DATE & TIME is %s %s %d %s", locale_tmp, formattedString, u_strlen(formatted), bestPatternString);
775 DBG("24H :: Before change %s", formattedString);
776 convertFormattedString = _string_replacer(formattedString, colon, ratio);
777 DBG("24H :: After change %s", convertFormattedString);
779 if(convertFormattedString == NULL)
781 DBG("_string_replacer return NULL");
782 udat_close(formatter);
786 udat_close(formatter);
788 if(strlen(convertFormattedString)<CLOCK_STR_LEN)
790 strncpy(output,convertFormattedString,strlen(convertFormattedString));
794 strncpy(output,convertFormattedString,CLOCK_STR_LEN-1);
797 if(convertFormattedString != NULL)
799 free(convertFormattedString);
800 convertFormattedString = NULL;
808 static UChar *uastrcpy(const char *chars)
813 str = (UChar *) malloc(sizeof(UChar) *(len + 1));
816 u_uastrcpy(str, chars);
822 static void ICU_set_timezone(const char *timezone)
826 ERR("TIMEZONE is NULL");
830 UErrorCode ec = U_ZERO_ERROR;
831 UChar *str = uastrcpy(timezone);
833 ucal_setDefaultTimeZone(str, &ec);
836 DBG("ucal_setDefaultTimeZone() FAILED : %s ",
844 #ifdef _SUPPORT_SCREEN_READER
845 static char *_access_info_cb(void *data, Evas_Object *obj)
847 Evas_Object *item = data;
850 char time_buf[128], ampm_buf[128];
851 char buf[CLOCK_STR_LEN];
852 char buf1[CLOCK_STR_LEN];
854 int battery_capa = 0;
857 char strHour[128] = { 0, };
858 char strMin[128] = { 0, };
861 struct tm *ts = NULL;
865 retif(data == NULL,NULL, "Invalid parameter!");
866 char *timezone = util_get_timezone_str();
867 ICU_set_timezone(timezone);
873 ts = localtime(&ctime);
877 memset(time_str, 0x00, sizeof(time_str));
878 memset(time_buf, 0x00, sizeof(time_buf));
879 memset(ampm_buf, 0x00, sizeof(ampm_buf));
880 memset(buf, 0x00, sizeof(buf));
881 memset(buf1, 0x00, sizeof(buf1));
883 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
884 char bf1[32] = { 0, };
886 if (ts->tm_hour >= 0 && ts->tm_hour < 12)
887 strncpy(ampm_buf, _("IDS_IDLE_OPT_AM_ABB"),sizeof(ampm_buf)-1);
889 strncpy(ampm_buf, _("IDS_IDLE_OPT_PM_ABB"),sizeof(ampm_buf)-1);
891 strftime(bf1, sizeof(bf1), "%l", ts);
893 strftime(bf1, sizeof(bf1), "%M", ts);
897 char bf1[32] = { 0, };
899 strftime(bf1, sizeof(bf1), "%H", ts);
901 strftime(bf1, sizeof(bf1), "%M", ts);
907 strncpy(strHour, _("IDS_COM_BODY_1_HOUR"),sizeof(strHour));
911 snprintf(strHour, sizeof(strHour), _("IDS_COM_POP_PD_HOURS"),hour);
916 strncpy(strMin, _("IDS_COM_BODY_1_MINUTE"),sizeof(strMin));
920 snprintf(strMin, sizeof(strMin), _("IDS_COM_BODY_PD_MINUTES"),minute);
923 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
924 snprintf(time_str, sizeof(time_str), "%s, %s, %s", strHour, strMin,ampm_buf);
926 snprintf(time_str, sizeof(time_str), "%s, %s", strHour, strMin);
929 ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &battery_capa);
934 if (battery_capa < 0)
939 if (battery_capa > 100)
941 snprintf(buf1, sizeof(buf1), _("IDS_IDLE_BODY_PD_PERCENT_OF_BATTERY_POWER_REMAINING"), battery_capa);
943 snprintf(buf, sizeof(buf), "%s, %s, %s", time_str, buf1, _("IDS_IDLE_BODY_STATUS_BAR_ITEM"));
947 if (!tmp) return NULL;
953 static int register_clock_tts(void *data,int win_type)
957 retif(data == NULL, FAIL, "Invalid parameter!");
959 Evas_Object *to = NULL;
960 Evas_Object *ao = NULL;
961 struct appdata *ad = data;
963 to = (Evas_Object *) edje_object_part_object_get(elm_layout_edje_get(ad->win[win_type].layout), "elm.rect.clock.access");
964 ao = util_access_object_register(to, ad->win[win_type].layout);
965 util_access_object_info_cb_set(ao,ELM_ACCESS_INFO,_access_info_cb,data);