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(14)
43 #define TIME_FONT_SIZE_12 ELM_SCALE_SIZE(14)
44 #define AMPM_FONT_SIZE ELM_SCALE_SIZE(13)
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 ts = localtime(&ctime);
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)
477 if (!src || !pattern)
480 out_sz = strlen(src);
488 for (state = STATE_START, ptr = src; state != STATE_END; ptr++) {
493 } else if (!isblank(*ptr)) {
501 } else if (*ptr == *pattern) {
508 if (out_idx == out_sz) {
509 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
521 * If there is no space for copying the replacement,
522 * Extend size of the return buffer.
524 if (out_sz - out_idx < strlen(replace) + 1) {
525 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
533 strcpy(ret + out_idx, replace);
534 out_idx += strlen(replace);
538 } else if (*ptr != pattern[idx]) {
541 /* Copy the first matched character */
544 if (out_idx == out_sz) {
545 tmp = _extend_heap(ret, &out_sz, strlen(replace) + 1);
570 void indicator_get_apm_by_region(char* output,void *data)
572 retif(data == NULL, , "Data parameter is NULL");
573 retif(output == NULL, , "output parameter is NULL");
576 UChar customSkeleton[CLOCK_STR_LEN] = { 0, };
577 UChar u_timezone[64] = {0,};
579 UErrorCode status = U_ZERO_ERROR;
580 UDateFormat *formatter = NULL;
582 UChar bestPattern[CLOCK_STR_LEN] = { 0, };
583 UChar formatted[CLOCK_STR_LEN] = { 0, };
585 char bestPatternString[CLOCK_STR_LEN] = { 0, };
586 char formattedString[CLOCK_STR_LEN] = { 0, };
588 UDateTimePatternGenerator *pattern_generator = NULL;
590 char *time_skeleton = "hhmm";
592 char* timezone_id = NULL;
593 timezone_id = util_get_timezone_str();
595 char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
598 ERR("[Error] get value of fail.");
603 /* Remove ".UTF-8" in locale */
604 char locale_tmp[32] = {0,};
605 strncpy(locale_tmp, locale, sizeof(locale_tmp)-1);
606 char *p = util_safe_str(locale_tmp, ".UTF-8");
611 u_uastrncpy(customSkeleton, time_skeleton, strlen(time_skeleton));
613 pattern_generator = __cal_get_pattern_generator (locale_tmp, &status);
614 if (pattern_generator == NULL) {
618 int32_t bestPatternCapacity = (int32_t) (sizeof(bestPattern) / sizeof((bestPattern)[0]));
619 (void)udatpg_getBestPattern(pattern_generator, customSkeleton,
620 u_strlen(customSkeleton), bestPattern,
621 bestPatternCapacity, &status);
623 u_austrcpy(bestPatternString, bestPattern);
624 u_uastrcpy(bestPattern,"a");
626 DBG("TimeZone is %s", timezone_id);
628 if(bestPatternString[0] == 'a')
637 UDate date = ucal_getNow();
640 u_uastrncpy(u_timezone, timezone_id, sizeof(u_timezone));
641 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, u_timezone, -1, bestPattern, -1, &status);
645 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, NULL, -1, bestPattern, -1, &status);
647 if (formatter == NULL) {
651 int32_t formattedCapacity = (int32_t) (sizeof(formatted) / sizeof((formatted)[0]));
652 (void)udat_format(formatter, date, formatted, formattedCapacity, NULL, &status);
653 u_austrcpy(formattedString, formatted);
655 apm_length = u_strlen(formatted);
657 udat_close(formatter);
659 if(strlen(formattedString)<CLOCK_STR_LEN)
661 strncpy(output,formattedString,strlen(formattedString));
665 strncpy(output,formattedString,CLOCK_STR_LEN-1);
673 void indicator_get_time_by_region(char* output,void *data)
675 retif(data == NULL, , "Data parameter is NULL");
676 retif(output == NULL, , "output parameter is NULL");
678 UChar customSkeleton[CLOCK_STR_LEN] = { 0, };
679 UChar u_timezone[64] = {0,};
681 UErrorCode status = U_ZERO_ERROR;
682 UDateFormat *formatter = NULL;
684 UChar bestPattern[CLOCK_STR_LEN] = { 0, };
685 UChar formatted[CLOCK_STR_LEN] = { 0, };
687 char bestPatternString[CLOCK_STR_LEN] = { 0, };
688 char formattedString[CLOCK_STR_LEN] = { 0, };
689 char* convertFormattedString = NULL;
691 char time_skeleton[20] = {0,};
692 UDateTimePatternGenerator *pattern_generator = NULL;
694 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
696 strcpy(time_skeleton,"hm");
700 strcpy(time_skeleton,"Hm");
702 char* timezone_id = NULL;
703 timezone_id = util_get_timezone_str();
705 char *locale = vconf_get_str(VCONFKEY_REGIONFORMAT);
708 ERR("[Error] get value of fail.");
713 /* Remove ".UTF-8" in locale */
714 char locale_tmp[32] = {0,};
715 strncpy(locale_tmp, locale, sizeof(locale_tmp)-1);
716 char *p = util_safe_str(locale_tmp, ".UTF-8");
721 u_uastrncpy(customSkeleton, time_skeleton, strlen(time_skeleton));
723 pattern_generator = __cal_get_pattern_generator (locale_tmp, &status);
724 if (pattern_generator == NULL) {
728 int32_t bestPatternCapacity = (int32_t) (sizeof(bestPattern) / sizeof((bestPattern)[0]));
729 (void)udatpg_getBestPattern(pattern_generator, customSkeleton,
730 u_strlen(customSkeleton), bestPattern,
731 bestPatternCapacity, &status);
733 char a_best_pattern[64] = {0,};
734 u_austrcpy(a_best_pattern, bestPattern);
735 char *a_best_pattern_fixed = strtok(a_best_pattern, "a");
736 a_best_pattern_fixed = strtok(a_best_pattern_fixed, " ");
737 if(a_best_pattern_fixed)
739 u_uastrcpy(bestPattern, a_best_pattern_fixed);
742 u_austrcpy(bestPatternString, bestPattern);
744 DBG("BestPattern is %s", bestPatternString);
745 DBG("TimeZone is %s", timezone_id);
747 UDate date = ucal_getNow();
750 u_uastrncpy(u_timezone, timezone_id, sizeof(u_timezone));
751 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, u_timezone, -1, bestPattern, -1, &status);
755 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale_tmp, NULL, -1, bestPattern, -1, &status);
758 if (formatter == NULL) {
761 int32_t formattedCapacity = (int32_t) (sizeof(formatted) / sizeof((formatted)[0]));
762 (void)udat_format(formatter, date, formatted, formattedCapacity, NULL, &status);
763 u_austrcpy(formattedString, formatted);
764 DBG("DATE & TIME is %s %s %d %s", locale_tmp, formattedString, u_strlen(formatted), bestPatternString);
766 DBG("24H :: Before change %s", formattedString);
767 convertFormattedString = _string_replacer(formattedString, colon, ratio);
768 DBG("24H :: After change %s", convertFormattedString);
770 if(convertFormattedString == NULL)
772 DBG("_string_replacer return NULL");
773 udat_close(formatter);
777 udat_close(formatter);
779 if(strlen(convertFormattedString)<CLOCK_STR_LEN)
781 strncpy(output,convertFormattedString,strlen(convertFormattedString));
785 strncpy(output,convertFormattedString,CLOCK_STR_LEN-1);
788 if(convertFormattedString != NULL)
790 free(convertFormattedString);
791 convertFormattedString = NULL;
799 static UChar *uastrcpy(const char *chars)
804 str = (UChar *) malloc(sizeof(UChar) *(len + 1));
807 u_uastrcpy(str, chars);
813 static void ICU_set_timezone(const char *timezone)
817 ERR("TIMEZONE is NULL");
821 UErrorCode ec = U_ZERO_ERROR;
822 UChar *str = uastrcpy(timezone);
824 ucal_setDefaultTimeZone(str, &ec);
827 DBG("ucal_setDefaultTimeZone() FAILED : %s ",
835 #ifdef _SUPPORT_SCREEN_READER
836 static char *_access_info_cb(void *data, Evas_Object *obj)
838 Evas_Object *item = data;
841 char time_buf[128], ampm_buf[128];
842 char buf[CLOCK_STR_LEN];
843 char buf1[CLOCK_STR_LEN];
845 int battery_capa = 0;
848 char strHour[128] = { 0, };
849 char strMin[128] = { 0, };
852 struct tm *ts = NULL;
856 retif(data == NULL,NULL, "Invalid parameter!");
857 char *timezone = util_get_timezone_str();
858 ICU_set_timezone(timezone);
864 ts = localtime(&ctime);
868 memset(time_str, 0x00, sizeof(time_str));
869 memset(time_buf, 0x00, sizeof(time_buf));
870 memset(ampm_buf, 0x00, sizeof(ampm_buf));
871 memset(buf, 0x00, sizeof(buf));
872 memset(buf1, 0x00, sizeof(buf1));
874 if (clock_mode == INDICATOR_CLOCK_MODE_12H) {
875 char bf1[32] = { 0, };
877 if (ts->tm_hour >= 0 && ts->tm_hour < 12)
878 strncpy(ampm_buf, _("IDS_IDLE_OPT_AM_ABB"),sizeof(ampm_buf)-1);
880 strncpy(ampm_buf, _("IDS_IDLE_OPT_PM_ABB"),sizeof(ampm_buf)-1);
882 strftime(bf1, sizeof(bf1), "%l", ts);
884 strftime(bf1, sizeof(bf1), "%M", ts);
888 char bf1[32] = { 0, };
890 strftime(bf1, sizeof(bf1), "%H", ts);
892 strftime(bf1, sizeof(bf1), "%M", ts);
898 strncpy(strHour, _("IDS_COM_BODY_1_HOUR"),sizeof(strHour));
902 snprintf(strHour, sizeof(strHour), _("IDS_COM_POP_PD_HOURS"),hour);
907 strncpy(strMin, _("IDS_COM_BODY_1_MINUTE"),sizeof(strMin));
911 snprintf(strMin, sizeof(strMin), _("IDS_COM_BODY_PD_MINUTES"),minute);
914 if(clock_mode == INDICATOR_CLOCK_MODE_12H)
915 snprintf(time_str, sizeof(time_str), "%s, %s, %s", strHour, strMin,ampm_buf);
917 snprintf(time_str, sizeof(time_str), "%s, %s", strHour, strMin);
920 ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &battery_capa);
925 if (battery_capa < 0)
930 if (battery_capa > 100)
932 snprintf(buf1, sizeof(buf1), _("IDS_IDLE_BODY_PD_PERCENT_OF_BATTERY_POWER_REMAINING"), battery_capa);
934 snprintf(buf, sizeof(buf), "%s, %s, %s", time_str, buf1, _("IDS_IDLE_BODY_STATUS_BAR_ITEM"));
938 if (!tmp) return NULL;
944 static int register_clock_tts(void *data,int win_type)
948 retif(data == NULL, FAIL, "Invalid parameter!");
950 Evas_Object *to = NULL;
951 Evas_Object *ao = NULL;
952 struct appdata *ad = data;
954 to = (Evas_Object *) edje_object_part_object_get(elm_layout_edje_get(ad->win[win_type].layout), "elm.rect.clock.access");
955 ao = util_access_object_register(to, ad->win[win_type].layout);
956 util_access_object_info_cb_set(ao,ELM_ACCESS_INFO,_access_info_cb,data);