4 * Copyright (c) 2012 - 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.
29 #include "cal_typedef.h"
30 #include "cal_internal.h"
32 #include "cal_inotify.h"
34 #include "cal_db_util.h"
36 #include "cal_db_query.h"
37 #include "cal_server_reminder.h"
39 #define CAL_SEARCH_LOOP_MAX 4
44 long long int alert_utime; // to compare
47 int type; // utime, local
49 int record; // todo, event
54 // this api is necessary for repeat instance.
55 static int _cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
57 int ret = CALENDAR_ERROR_NONE;
58 char query[CAL_DB_SQL_MAX_LEN] = {0};
59 cal_db_util_error_e dbret = CAL_DB_OK;
61 ret = cal_db_util_begin_trans();
62 if (CALENDAR_ERROR_NONE != ret)
64 ERR("cal_db_util_begin_trans() Fail");
65 return CALENDAR_ERROR_DB_FAILED;
68 DBG("alarm_id(%d)", alarm_id);
70 snprintf(query, sizeof(query), "UPDATE %s SET alarm_id = 0 WHERE alarm_id =%d ",
71 CAL_TABLE_ALARM, alarm_id);
73 dbret = cal_db_util_query_exec(query);
74 if (CAL_DB_OK != dbret)
76 ERR("cal_db_util_query_exec() Fail(%d)", dbret);
79 case CAL_DB_ERROR_NO_SPACE:
80 cal_db_util_end_trans(false);
81 return CALENDAR_ERROR_FILE_NO_SPACE;
83 cal_db_util_end_trans(false);
84 return CALENDAR_ERROR_DB_FAILED;
87 cal_db_util_end_trans(true);
88 return CALENDAR_ERROR_NONE;
91 static int _cal_server_alarm_clear_all_cb(alarm_id_t alarm_id, void *data)
95 DBG("remove alarm id(%d)", alarm_id);
96 _cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
97 ret = alarmmgr_remove_alarm(alarm_id);
98 if (ret != ALARMMGR_RESULT_SUCCESS)
100 ERR("alarmmgr_remove_alarm() Fail(ret:%d)", ret);
103 return CALENDAR_ERROR_NONE;
106 static int _cal_server_alarm_update_alarm_id(int alarm_id, int event_id, int tick, int unit)
108 int ret = CALENDAR_ERROR_NONE;
109 char query[CAL_DB_SQL_MAX_LEN] = {0};
110 cal_db_util_error_e dbret = CAL_DB_OK;
112 ret = cal_db_util_begin_trans();
113 if (CALENDAR_ERROR_NONE != ret)
115 ERR("cal_db_util_begin_trans() Fail");
116 return CALENDAR_ERROR_DB_FAILED;
119 DBG("Update alarm_id(%d) in alarm table", alarm_id);
120 snprintf(query, sizeof(query), "UPDATE %s SET "
122 "WHERE event_id =%d AND remind_tick =%d AND remind_tick_unit =%d",
125 event_id, tick, unit);
127 dbret = cal_db_util_query_exec(query);
128 if (CAL_DB_OK != dbret)
130 ERR("cal_db_util_query_exec() Fail(%d)", dbret);
133 case CAL_DB_ERROR_NO_SPACE:
134 cal_db_util_end_trans(false);
135 return CALENDAR_ERROR_FILE_NO_SPACE;
137 cal_db_util_end_trans(false);
138 return CALENDAR_ERROR_DB_FAILED;
141 cal_db_util_end_trans(true);
142 return CALENDAR_ERROR_NONE;
145 static long long int _cal_server_alarm_get_alert_utime(const char *field, int event_id, time_t current)
147 char query[CAL_DB_SQL_MAX_LEN] = {0};
148 snprintf(query, sizeof(query), "SELECT %s FROM %s "
149 "WHERE event_id=%d AND %s>%ld ORDER BY %s LIMIT 1",
150 field, CAL_TABLE_NORMAL_INSTANCE, event_id, field, current, field);
152 sqlite3_stmt *stmt = NULL;
153 stmt = cal_db_util_query_prepare(query);
155 long long int utime = 0;
156 if (CAL_DB_ROW == cal_db_util_stmt_step(stmt))
157 utime = sqlite3_column_int(stmt, 0);
159 sqlite3_finalize(stmt);
163 static int _cal_server_alarm_get_alert_localtime(const char *field, int event_id, time_t current)
165 char query[CAL_DB_SQL_MAX_LEN] = {0};
168 localtime_r(¤t, &st);
169 time_t mod_current = timegm(&st);
170 snprintf(query, sizeof(query), "SELECT %s FROM %s "
171 "WHERE event_id=%d AND strftime('%%s', %s)>%ld ORDER BY %s LIMIT 1",
172 field, CAL_TABLE_ALLDAY_INSTANCE, event_id, field, mod_current, field);
174 sqlite3_stmt *stmt = NULL;
175 stmt = cal_db_util_query_prepare(query);
177 const char *datetime = NULL;
178 if (CAL_DB_ROW == cal_db_util_stmt_step(stmt))
179 datetime = (const char *)sqlite3_column_text(stmt, 0);
181 if (NULL == datetime || '\0' == *datetime) {
182 ERR("Invalid datetime [%s]", datetime);
183 sqlite3_finalize(stmt);
187 int y = 0, m = 0, d = 0;
188 int h = 0, n = 0, s = 0;
189 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
190 sqlite3_finalize(stmt);
192 st.tm_year = y - 1900;
199 return (long long int)mktime(&st);
203 * to get aler time, time(NULL) is not accurate. 1 secs diff could be occured.
204 * so, searching DB is neccessary to find alert time.
206 static int _cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
208 RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
210 char query[CAL_DB_SQL_MAX_LEN] = {0};
211 snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
212 "A.alarm_type, A.alarm_utime, A.alarm_datetime, B.system_type, "
213 "B.type, B.dtstart_type, B.dtend_type "
214 "FROM %s as A, %s as B ON A.event_id = B.id WHERE alarm_id =%d ",
215 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE, alarm_id);
217 sqlite3_stmt *stmt = NULL;
218 stmt = cal_db_util_query_prepare(query);
219 RETVM_IF(NULL == stmt, CALENDAR_ERROR_DB_FAILED, "cal_db_util_query_prepare() Fail");
225 long long int utime = 0;
226 const char *datetime = NULL;
229 int dtstart_type = 0;
233 if (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
235 event_id = sqlite3_column_int(stmt, index++);
236 unit = sqlite3_column_int(stmt, index++);
237 tick = sqlite3_column_int(stmt, index++);
238 type = sqlite3_column_int(stmt, index++);
239 utime = sqlite3_column_int64(stmt, index++);
240 datetime = (const char *)sqlite3_column_text(stmt, index++);
241 system_type = sqlite3_column_int(stmt, index++);
242 record_type = sqlite3_column_int(stmt, index++);
243 dtstart_type = sqlite3_column_int(stmt, index++);
244 dtend_type = sqlite3_column_int(stmt, index++);
247 if (NULL == tt_alert) {
248 ERR("Invalid parameter: tt_alert is NULL");
249 sqlite3_finalize(stmt);
250 return CALENDAR_ERROR_INVALID_PARAMETER;
253 if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
254 if (CALENDAR_TIME_UTIME == type) {
258 int y = 0, m = 0, d = 0;
259 int h = 0, n = 0, s = 0;
260 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
262 st.tm_year = y - 1900;
268 *tt_alert = (long long int)mktime(&st);
269 DBG("datetime[%s] to %02d:%02d:%02d (%lld)", datetime, h, n, s, *tt_alert);
271 sqlite3_finalize(stmt);
272 return CALENDAR_ERROR_NONE;
274 sqlite3_finalize(stmt);
278 time_t current = time(NULL);
279 current += (tick * unit);
280 current -= 2; // in case time passed
282 switch (record_type) {
283 case CALENDAR_BOOK_TYPE_EVENT:
284 switch (dtstart_type) {
285 case CALENDAR_TIME_UTIME:
286 utime = _cal_server_alarm_get_alert_utime("dtstart_utime", event_id, current);
289 case CALENDAR_TIME_LOCALTIME:
290 utime = _cal_server_alarm_get_alert_localtime("dtstart_datetime", event_id, current);
295 case CALENDAR_BOOK_TYPE_TODO:
296 switch (dtend_type) {
297 case CALENDAR_TIME_UTIME:
298 utime = _cal_server_alarm_get_alert_utime("dtend_utime", event_id, current);
301 case CALENDAR_TIME_LOCALTIME:
302 utime = _cal_server_alarm_get_alert_localtime("dtend_datetime", event_id, current);
307 DBG("alert_time(%lld) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, datetime, tick, unit);
309 *tt_alert = utime - (tick * unit);
310 return CALENDAR_ERROR_NONE;
313 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l) // case 1
315 char query_specific_utime[CAL_DB_SQL_MAX_LEN] = {0};
316 snprintf(query_specific_utime, sizeof(query_specific_utime),
317 // alarm utime(normal event + todo)
318 "SELECT event_id, remind_tick_unit, remind_tick, alarm_type, alarm_utime, alarm_datetime "
320 "WHERE remind_tick_unit =%d AND alarm_type =%d AND alarm_utime %s %ld %s",
322 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
323 true == get_all ? "=" : ">",
325 true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
327 sqlite3_stmt *stmt = NULL;
328 stmt = cal_db_util_query_prepare(query_specific_utime);
330 ERR("cal_db_util_query_prepare() Fail");
331 ERR("[%s]", query_specific_utime);
335 while (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
336 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
338 ERR("calloc() Fail");
339 sqlite3_finalize(stmt);
344 ad->event_id = sqlite3_column_int(stmt, index++);
345 ad->unit = sqlite3_column_int(stmt, index++);
346 ad->tick = sqlite3_column_int(stmt, index++);
347 ad->type = sqlite3_column_int(stmt, index++);
348 ad->time = (long long int)sqlite3_column_int64(stmt, index++);
349 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, index++));
350 *l = g_list_append(*l, ad);
351 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
352 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
353 ad->alert_utime = ad->time;
354 if (false == get_all) break;
356 sqlite3_finalize(stmt);
359 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
361 char query_specific_localtime[CAL_DB_SQL_MAX_LEN] = {0};
362 snprintf(query_specific_localtime, sizeof(query_specific_localtime),
363 "SELECT event_id, remind_tick_unit, remind_tick, "
364 "alarm_type, alarm_utime, alarm_datetime "
366 "WHERE remind_tick_unit=%d AND alarm_type=%d AND alarm_datetime %s '%s' %s",
368 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
369 true == get_all ? "=" : ">",
371 true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
373 sqlite3_stmt *stmt = NULL;
374 stmt = cal_db_util_query_prepare(query_specific_localtime);
376 ERR("cal_db_util_query_prepare() Fail");
377 ERR("[%s]", query_specific_localtime);
381 while (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
382 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
384 ERR("calloc() Fail");
385 sqlite3_finalize(stmt);
390 ad->event_id = sqlite3_column_int(stmt, index++);
391 ad->unit = sqlite3_column_int(stmt, index++);
392 ad->tick = sqlite3_column_int(stmt, index++);
393 ad->type = sqlite3_column_int(stmt, index++);
394 ad->time = (long long int)sqlite3_column_int64(stmt, index++);
395 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, index++));
396 *l = g_list_append(*l, ad);
397 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
398 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
400 int y = 0, m = 0, d = 0;
401 int h = 0, n = 0, s = 0;
402 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
405 st.tm_year = y - 1900;
411 ad->alert_utime = (long long int)mktime(&st);
412 if (false == get_all) break;
414 sqlite3_finalize(stmt);
417 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
419 char query_nonspecific_event_utime[CAL_DB_SQL_MAX_LEN] = {0};
420 snprintf(query_nonspecific_event_utime, sizeof(query_nonspecific_event_utime),
421 // A:alarm B:normal instance
422 "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, A.alarm_type, B.dtstart_utime, A.alarm_datetime "
423 "FROM %s as A, %s as B ON A.event_id = B.event_id "
424 "WHERE A.remind_tick_unit >%d AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
425 CAL_TABLE_ALARM, CAL_TABLE_NORMAL_INSTANCE,
426 CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
427 true == get_all ? "=" : ">",
429 true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
431 sqlite3_stmt *stmt = NULL;
432 stmt = cal_db_util_query_prepare(query_nonspecific_event_utime);
434 ERR("cal_db_util_query_prepare() Fail");
435 ERR("[%s]", query_nonspecific_event_utime);
439 while (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
440 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
442 ERR("calloc() Fail");
443 sqlite3_finalize(stmt);
448 ad->event_id = sqlite3_column_int(stmt, index++);
449 ad->unit = sqlite3_column_int(stmt, index++);
450 ad->tick = sqlite3_column_int(stmt, index++);
451 ad->type = sqlite3_column_int(stmt, index++);
452 ad->time = (long long int)sqlite3_column_int64(stmt, index++);
453 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, index++));
454 *l = g_list_append(*l, ad);
455 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
456 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
458 ad->alert_utime = ad->time - (ad->tick * ad->unit);
459 if (false == get_all) break;
461 sqlite3_finalize(stmt);
464 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
466 char query_nonspecific_event_localtime[CAL_DB_SQL_MAX_LEN] = {0};
467 snprintf(query_nonspecific_event_localtime, sizeof(query_nonspecific_event_localtime),
469 "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, A.alarm_type, A.alarm_utime, B.dtstart_datetime "
470 "FROM %s as A, %s as B ON A.event_id = B.event_id "
471 "WHERE A.remind_tick_unit >%d AND "
472 "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
473 CAL_TABLE_ALARM, CAL_TABLE_ALLDAY_INSTANCE,
474 CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
476 true == get_all ? "=" : ">",
477 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
478 sqlite3_stmt *stmt = NULL;
479 stmt = cal_db_util_query_prepare(query_nonspecific_event_localtime);
481 ERR("cal_db_util_query_prepare() Fail");
482 ERR("[%s]", query_nonspecific_event_localtime);
486 while (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
487 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
489 ERR("calloc() Fail");
490 sqlite3_finalize(stmt);
495 ad->event_id = sqlite3_column_int(stmt, index++);
496 ad->unit = sqlite3_column_int(stmt, index++);
497 ad->tick = sqlite3_column_int(stmt, index++);
498 ad->type = sqlite3_column_int(stmt, index++);
499 ad->time = (long long int)sqlite3_column_int64(stmt, index++);
500 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, index++));
501 *l = g_list_append(*l, ad);
502 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
503 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
505 int y = 0, m = 0, d = 0;
506 int h = 0, n = 0, s = 0;
507 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
510 st.tm_year = y - 1900;
516 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
517 if (false == get_all) break;
519 sqlite3_finalize(stmt);
522 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
524 char query_nonspecific_todo_utime[CAL_DB_SQL_MAX_LEN] = {0};
525 snprintf(query_nonspecific_todo_utime, sizeof(query_nonspecific_todo_utime),
526 // A:alarm B:todo(normal)
527 "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, A.alarm_type, B.dtend_utime, A.alarm_datetime "
528 "FROM %s as A, %s as B ON A.event_id = B.id "
529 "WHERE A.remind_tick_unit >%d AND B.type =%d "
530 "AND (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
531 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
532 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
533 true == get_all ? "=" : ">",
535 true == get_all ? "" : "ORDER BY (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
537 sqlite3_stmt *stmt = NULL;
538 stmt = cal_db_util_query_prepare(query_nonspecific_todo_utime);
540 ERR("cal_db_util_query_prepare() Fail");
541 ERR("[%s]", query_nonspecific_todo_utime);
545 while (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
546 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
548 ERR("calloc() Fail");
549 sqlite3_finalize(stmt);
554 ad->event_id = sqlite3_column_int(stmt, index++);
555 ad->unit = sqlite3_column_int(stmt, index++);
556 ad->tick = sqlite3_column_int(stmt, index++);
557 ad->type = sqlite3_column_int(stmt, index++);
558 ad->time = (long long int)sqlite3_column_int64(stmt, index++);
559 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, index++));
560 *l = g_list_append(*l, ad);
561 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
562 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
564 ad->alert_utime = ad->time - (ad->tick * ad->unit);
565 if (false == get_all) break;
567 sqlite3_finalize(stmt);
570 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
572 char query_nonspecific_todo_localtime[CAL_DB_SQL_MAX_LEN] = {0};
573 snprintf(query_nonspecific_todo_localtime, sizeof(query_nonspecific_todo_localtime),
574 // A:alarm B:todo(allday)
575 "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, A.alarm_type, A.alarm_utime, B.dtend_datetime "
576 "FROM %s as A, %s as B ON A.event_id = B.id "
577 "WHERE A.remind_tick_unit >%d AND B.type =%d "
578 "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
579 CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
580 CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
582 true == get_all ? "=" : ">",
583 true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
585 sqlite3_stmt *stmt = NULL;
586 stmt = cal_db_util_query_prepare(query_nonspecific_todo_localtime);
588 ERR("cal_db_util_query_prepare() Fail");
589 ERR("[%s]", query_nonspecific_todo_localtime);
593 while (CAL_DB_ROW == cal_db_util_stmt_step(stmt)) {
594 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
596 ERR("calloc() Fail");
597 sqlite3_finalize(stmt);
602 ad->event_id = sqlite3_column_int(stmt, index++);
603 ad->unit = sqlite3_column_int(stmt, index++);
604 ad->tick = sqlite3_column_int(stmt, index++);
605 ad->type = sqlite3_column_int(stmt, index++);
606 ad->time = (long long int)sqlite3_column_int64(stmt, index++);
607 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, index++));
608 *l = g_list_append(*l, ad);
609 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
610 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
612 int y = 0, m = 0, d = 0;
613 int h = 0, n = 0, s = 0;
614 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
617 st.tm_year = y - 1900;
623 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
624 if (false == get_all) break;
626 sqlite3_finalize(stmt);
629 static int _cal_server_alarm_get_alert_list(time_t utime, GList **list)
632 RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
635 struct tm st_local = {0};
636 localtime_r(&utime, &st_local);
637 char datetime[32] = {0};
638 snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
639 st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
640 st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
641 DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
645 _cal_server_alarm_get_upcoming_specific_utime(utime, true, &l);
646 _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, true, &l);
647 _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, true, &l);
649 _cal_server_alarm_get_upcoming_specific_localtime(datetime, true, &l);
650 _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, true, &l);
651 _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, true, &l);
655 return CALENDAR_ERROR_NONE;
658 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
660 struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
661 struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
662 DBG("%lld) > (%lld)",p1->alert_utime, p2->alert_utime);
664 return p1->alert_utime < p2->alert_utime ? -1 : 1;
667 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
669 struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
670 DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
671 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
675 static int _cal_server_alarm_register(GList *alarm_list)
678 RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
680 int ret = CALENDAR_ERROR_NONE;
681 GList *l = g_list_first(alarm_list);
682 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
683 RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
685 // clear all alarm which set by mine.
686 ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
687 if (ret != ALARMMGR_RESULT_SUCCESS)
689 ERR("alarmmgr_enum_alarm_ids() Fail");
693 time_t mod_time = (time_t)ad->alert_utime;
694 alarm_entry_t *alarm_info = NULL;
695 alarm_info = alarmmgr_create_alarm();
696 if (NULL == alarm_info)
698 ERR("Failed to create alarm");
699 return CALENDAR_ERROR_DB_FAILED;
702 struct tm st_alarm = {0};
704 switch (ad->system_type) {
705 case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
706 gmtime_r(&mod_time, &st_alarm);
711 localtime_r(&mod_time, &st_alarm);
715 alarm_date_t date = {0};
716 date.year = st_alarm.tm_year + 1900;
717 date.month = st_alarm.tm_mon + 1;
718 date.day = st_alarm.tm_mday;
719 date.hour = st_alarm.tm_hour;
720 date.min = st_alarm.tm_min;
721 date.sec = st_alarm.tm_sec;
722 alarmmgr_set_time(alarm_info, date);
723 DBG(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
724 ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
725 ad->time, ad->datetime, ad->tick, ad->unit);
728 ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
730 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
731 alarmmgr_free_alarm(alarm_info);
734 DBG("alarmmgr id (%d)", alarm_id);
735 _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
736 alarmmgr_free_alarm(alarm_info);
737 return CALENDAR_ERROR_NONE;
740 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
742 RETV_IF(NULL == user_data, true);
746 ret = app_control_get_mime(app_control, &mime);
747 RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
749 const char *reminder_mime = "application/x-tizen.calendar.reminder";
750 if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { // not same
751 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
757 GList *alarm_list = (GList *)user_data;
759 len = g_list_length(alarm_list);
761 DBG("len is 0, no alarm list");
765 app_control_h b = NULL;
766 app_control_create(&b);
767 app_control_set_operation(b, APP_CONTROL_OPERATION_DEFAULT);
768 app_control_set_app_id(b, package);
772 ids = calloc(len, sizeof(char *));
774 ERR("calloc() Fail");
775 app_control_destroy(b);
776 return CALENDAR_ERROR_DB_FAILED;
778 GList *l = g_list_first(alarm_list);
780 for (i = 0; i < len; i++) {
781 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
787 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
788 package, ad->time, ad->tick, ad->unit, ad->record);
790 char buf_event_id[128] = {0};
791 char buf_time[128] = {0};
792 char buf_tick[128] = {0};
793 char buf_unit[128] = {0};
794 char buf_record_type[128] = {0};
795 snprintf(buf_event_id, sizeof(buf_event_id), "%d", ad->event_id);
796 snprintf(buf_time, sizeof(buf_time), "%lld", ad->time);
797 snprintf(buf_tick, sizeof(buf_tick), "%d", ad->tick);
798 snprintf(buf_unit, sizeof(buf_unit), "%d", ad->unit);
799 snprintf(buf_record_type, sizeof(buf_record_type), "%d", ad->record);
802 cal_server_reminder_add_callback_data(&p, "id", buf_event_id);
803 cal_server_reminder_add_callback_data(&p, "time", buf_time);
804 cal_server_reminder_add_callback_data(&p, "tick", buf_tick);
805 cal_server_reminder_add_callback_data(&p, "unit", buf_unit);
806 cal_server_reminder_add_callback_data(&p, "type", buf_record_type);
808 app_control_add_extra_data(b, buf_event_id, p); // key: id, value: id=4&time=123123&..
813 ids[i] = strdup(buf_event_id);
817 app_control_add_extra_data_array(b, "ids", (const char **)ids, len);
818 app_control_send_launch_request (b, NULL, NULL);
819 app_control_destroy(b);
822 for (i = 0; i < len; i++) {
831 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
833 RETM_IF(NULL == alarm_list, "No alarm list");
835 app_control_h app_control = NULL;
836 app_control_create(&app_control);
837 app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
838 app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
839 app_control_foreach_app_matched(app_control, __app_matched_cb, alarm_list);
840 app_control_destroy(app_control);
843 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
845 RETM_IF(NULL == alarm_list, "No alarm list");
847 GList *l = g_list_first(alarm_list);
849 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
855 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
856 ad->time, ad->tick, ad->unit, ad->record);
858 char buf_event_id[128] = {0};
859 char buf_time[128] = {0};
860 char buf_tick[128] = {0};
861 char buf_unit[128] = {0};
862 char buf_record_type[128] = {0};
863 snprintf(buf_event_id, sizeof(buf_event_id), "%d", ad->event_id);
864 snprintf(buf_time, sizeof(buf_time), "%lld", ad->time);
865 snprintf(buf_tick, sizeof(buf_tick), "%d", ad->tick);
866 snprintf(buf_unit, sizeof(buf_unit), "%d", ad->unit);
867 snprintf(buf_record_type, sizeof(buf_record_type), "%d", ad->record);
870 cal_server_reminder_add_callback_data(&p, "id", buf_event_id);
871 cal_server_reminder_add_callback_data(&p, "time", buf_time);
872 cal_server_reminder_add_callback_data(&p, "tick", buf_tick);
873 cal_server_reminder_add_callback_data(&p, "unit", buf_unit);
874 cal_server_reminder_add_callback_data(&p, "type", buf_record_type);
875 cal_server_reminder_publish(p);
882 static int _cal_server_alarm_register_with_alarmmgr(time_t utime)
885 struct tm st_local = {0};
886 localtime_r(&utime, &st_local);
887 char datetime[32] = {0};
888 snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
889 st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
890 st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
891 DBG("search alarm to register with given time (%ld) datetime[%s]", utime, datetime);
895 _cal_server_alarm_get_upcoming_specific_utime(utime, false, &l);
896 _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, false, &l);
897 _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, false, &l);
899 _cal_server_alarm_get_upcoming_specific_localtime(datetime, false, &l);
900 _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, false, &l);
901 _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, false, &l);
904 DBG("No alarm list");
905 return CALENDAR_ERROR_NONE;
908 l = g_list_sort(l, _cal_server_alarm_sort_cb);
909 g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
910 _cal_server_alarm_register(l);
915 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
920 return CALENDAR_ERROR_NONE;
923 static int _alert_cb(alarm_id_t alarm_id, void *data)
928 DBG("alarm_id (%ld)", alarm_id);
930 _cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
931 _cal_server_alarm_get_alert_list(tt_alert, &l);
932 _cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
933 _cal_server_alarm_noti_with_callback(l);
934 _cal_server_alarm_noti_with_control(l);
935 _cal_server_alarm_register_with_alarmmgr(tt_alert);
939 ////////////////////////////////////////////////////////////////////
940 static void _cal_server_alarm_timechange_cb(keynode_t *node, void *data)
946 t = vconf_keynode_get_int(node);
950 ret = vconf_get_int(VCONFKEY_SYSTEM_TIMECHANGE, &t);
951 WARN_IF(0 < ret, "vconf_get_int() Fail");
956 _cal_server_alarm_register_with_alarmmgr(time(NULL));
960 DBG("system changed time(%ld)", t);
961 _cal_server_alarm_register_with_alarmmgr((time_t)t);
965 void _cal_server_alarm_set_timechange(void)
967 vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
968 _cal_server_alarm_timechange_cb, NULL);
970 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT,
971 _cal_server_alarm_timechange_cb, NULL);
972 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT,
973 _cal_server_alarm_timechange_cb, NULL);
974 vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE,
975 _cal_server_alarm_timechange_cb, NULL);
978 static void __changed_cb(const char* view_uri, void* data)
981 _cal_server_alarm_register_with_alarmmgr(time(NULL));
984 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
986 cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_EVENT_CHANGED, callback, NULL);
987 cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_TODO_CHANGED, callback, NULL);
991 int cal_server_alarm(void)
996 _cal_server_alarm_set_timechange();
997 _cal_server_alarm_set_inotify(__changed_cb);
999 ret = alarmmgr_init("calendar-service");
1000 RETVM_IF(ret < 0, ret, "alarmmgr_init() Fail");
1002 ret = alarmmgr_set_cb(_alert_cb, NULL);
1003 RETVM_IF(ret < 0, ret, "alarmmgr_set_cb() Fail");
1005 _cal_server_alarm_register_with_alarmmgr(time(NULL));
1007 return CALENDAR_ERROR_NONE;