9 #include <Elementary.h>
15 #include <vconf-keys.h>
24 #define APP_NAME "org.tizen.answer"
25 #define BUS_NAME "org.tizen.dialer"
27 #define IFACE "org.tizen.dialer.Control"
29 static int _log_domain = -1;
30 #define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)
31 #define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
32 #define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
34 static E_DBus_Connection *bus_conn = NULL;
36 typedef struct _Call {
37 const char *line_id, *img, *type, *name;
40 typedef struct _Call_Screen {
41 Evas_Object *win, *layout;
43 Eina_Bool screen_visible;
44 E_DBus_Signal_Handler *sig_call_add;
45 E_DBus_Signal_Handler *sig_call_removed;
46 E_DBus_Signal_Handler *sig_name_changed;
49 static void _set_notification_type(Evas_Object *win, Eina_Bool high)
54 xwin = elm_win_xwindow_get(win);
57 ecore_x_netwm_window_type_set(xwin,
58 ECORE_X_WINDOW_TYPE_NOTIFICATION);
59 utilx_set_system_notification_level(ecore_x_display_get(), xwin,
60 UTILX_NOTIFICATION_LEVEL_HIGH);
61 power_wakeup(EINA_TRUE);
63 ecore_x_netwm_window_type_set(xwin, ECORE_X_WINDOW_TYPE_NORMAL);
70 static Eina_Bool _phone_locked(void)
74 if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock) == -1)
77 if (lock == VCONFKEY_IDLE_LOCK)
82 return EINA_TRUE; /* always have it to show */
86 static Call *_call_create(DBusMessage *msg)
89 const char *img, *name, *id, *type;
92 dbus_error_init(&err);
93 dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &img,
94 DBUS_TYPE_STRING, &id, DBUS_TYPE_STRING,
95 &name, DBUS_TYPE_STRING, &type,
98 if (dbus_error_is_set(&err)) {
99 ERR("Could not parse message: %s: %s", err.name,
103 call = calloc(1, sizeof(Call));
104 EINA_SAFETY_ON_NULL_RETURN_VAL(call, NULL);
105 call->img = eina_stringshare_add(img);
106 call->line_id = eina_stringshare_add(id);
107 call->type = eina_stringshare_add(type);
108 call->name = eina_stringshare_add(name);
109 DBG("c=%p line_id=%s, name=%s, type=%s, img=%s",
110 call, call->line_id, call->name, call->type, call->img);
114 static void _call_destroy(Call *c)
116 DBG("c=%p line_id=%s, name=%s, type=%s, img=%s",
117 c, c->line_id, c->name, c->type, c->img);
118 eina_stringshare_del(c->img);
119 eina_stringshare_del(c->line_id);
120 eina_stringshare_del(c->type);
121 eina_stringshare_del(c->name);
125 static void _call_screen_show(Call_Screen *cs)
128 Evas_Object *icon = NULL;
130 INF("Show line_id=%s, name=%s, type=%s",
131 c->line_id, c->name, c->type);
133 _set_notification_type(cs->win, EINA_TRUE);
134 cs->screen_visible = EINA_TRUE;
135 elm_win_raise(cs->win);
136 elm_win_activate(cs->win);
138 if (strcmp("", c->name) == 0)
139 elm_object_part_text_set(cs->layout, "elm.text.name",
142 elm_object_part_text_set(cs->layout, "elm.text.name",
144 icon = elm_icon_add(cs->layout);
146 if (strcmp("", c->img) != 0) {
147 elm_image_file_set(icon, c->img, NULL);
149 elm_icon_standard_set(icon, "no-picture");
151 elm_object_part_text_set(cs->layout, "elm.text.state", _("Incoming..."));
152 elm_object_part_text_set(cs->layout, "elm.text.phone.type", c->type);
153 elm_object_part_content_set(cs->layout, "elm.swallow.photo", icon);
154 elm_object_signal_emit(cs->layout, "show,activecall", "gui");
155 evas_object_show(cs->win);
157 //screen can't be off
158 power_lock_state(POWER_STATE_NORMAL, 0);
162 static void _sig_call_added(void *data, DBusMessage *msg)
164 Call_Screen *cs = data;
165 Eina_Bool locked = _phone_locked();
167 DBG("previous=%p, visible=%d, locked=%d", cs->call, cs->screen_visible,
171 _call_destroy(cs->call);
172 cs->call = _call_create(msg);
177 _call_screen_show(cs);
180 static void _call_screen_hide(Call_Screen *cs)
183 cs->screen_visible = EINA_FALSE;
184 _set_notification_type(cs->win, EINA_FALSE);
185 elm_object_signal_emit(cs->layout, "hide,activecall", "gui");
186 evas_object_hide(cs->win);
188 //screen can go off again
189 power_unlock_state(POWER_STATE_NORMAL);
193 static void _sig_call_removed(void *data, DBusMessage *msg __UNUSED__)
195 Call_Screen *cs = data;
197 DBG("previous=%p, visible=%d", cs->call, cs->screen_visible);
200 _call_destroy(cs->call);
204 if (!cs->screen_visible)
207 _call_screen_hide(cs);
210 static void _signal_handlers_add(Call_Screen *cs)
212 cs->sig_call_add = e_dbus_signal_handler_add(bus_conn, BUS_NAME,
217 cs->sig_call_removed = e_dbus_signal_handler_add(bus_conn,
225 static void _signal_handlers_del(Call_Screen *cs)
227 if (cs->sig_call_add) {
228 e_dbus_signal_handler_del(bus_conn, cs->sig_call_add);
229 cs->sig_call_add = NULL;
232 if (cs->sig_call_removed) {
233 e_dbus_signal_handler_del(bus_conn, cs->sig_call_removed);
234 cs->sig_call_removed = NULL;
238 static void _daemon_method_call_reply(void *data __UNUSED__,
239 DBusMessage *msg __UNUSED__,
242 if (dbus_error_is_set(err)) {
243 ERR("Error calling remote method: %s %s", err->name,
248 static void _daemon_method_call_make_with_reply(const char *method,
249 E_DBus_Method_Return_Cb cb,
254 msg = dbus_message_new_method_call(BUS_NAME, PATH, IFACE, method);
255 INF("msg=%p name=%s, path=%s, %s.%s()",
256 msg, BUS_NAME, PATH, IFACE, method);
257 EINA_SAFETY_ON_NULL_RETURN(msg);
259 e_dbus_message_send(bus_conn, msg, cb, -1, data);
260 dbus_message_unref(msg);
263 static void _daemon_method_call_make(const char *method)
265 _daemon_method_call_make_with_reply(method, _daemon_method_call_reply,
269 static void _daemon_available_call_reply(void *data, DBusMessage *msg,
272 Call_Screen *cs = data;
274 if (dbus_error_is_set(err)) {
275 const char *err_name = "org.tizen.dialer.error.NotAvailable";
276 if (strcmp(err_name, err->name) == 0) {
277 DBG("no incoming calls");
281 ERR("Error calling remote method: %s %s", err->name,
287 _call_destroy(cs->call);
289 cs->call = _call_create(msg);
290 _call_screen_show(cs);
293 static void _service_start_reply(void *data, DBusMessage *msg __UNUSED__,
296 Call_Screen *cs = data;
297 if (dbus_error_is_set(err)) {
298 ERR("Error: %s %s", err->name, err->message);
301 _signal_handlers_add(cs);
302 _daemon_method_call_make_with_reply("GetAvailableCall",
303 _daemon_available_call_reply,
307 static void _has_owner_cb(void *data, DBusMessage *msg __UNUSED__,
312 Call_Screen *cs = data;
315 if (dbus_error_is_set(error)) {
316 ERR("Error: %s %s", error->name, error->message);
319 dbus_error_init(&err);
320 dbus_message_get_args(msg, &err, DBUS_TYPE_BOOLEAN, &online,
324 INF("no dialer, start it");
325 e_dbus_start_service_by_name(bus_conn, BUS_NAME, 0,
326 _service_start_reply, cs);
330 _signal_handlers_add(cs);
331 _daemon_method_call_make_with_reply("GetAvailableCall",
332 _daemon_available_call_reply,
336 static void _name_owner_changed(void *data, DBusMessage *msg)
338 Call_Screen *cs = data;
340 const char *name, *from, *to;
342 dbus_error_init(&err);
343 if (!dbus_message_get_args(msg, &err,
344 DBUS_TYPE_STRING, &name,
345 DBUS_TYPE_STRING, &from,
346 DBUS_TYPE_STRING, &to,
347 DBUS_TYPE_INVALID)) {
348 ERR("Could not get NameOwnerChanged arguments: %s: %s",
349 err.name, err.message);
350 dbus_error_free(&err);
354 if (strcmp(name, BUS_NAME) != 0)
357 if ((to == NULL) || (*to == '\0')) {
358 INF("missed dialer");
359 _signal_handlers_del(cs);
363 INF("got new dialer at %s", to);
364 _signal_handlers_add(cs);
365 _daemon_method_call_make_with_reply("GetAvailableCall",
366 _daemon_available_call_reply,
370 static Eina_Bool _dbus_init(Call_Screen *cs)
373 char *bus_name = BUS_NAME;
375 INF("Running on Session bus");
376 bus_conn = e_dbus_bus_get(DBUS_BUS_SESSION);
379 ERR("Could not fetch the DBus session");
383 cs->sig_name_changed = e_dbus_signal_handler_add(
384 bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH, E_DBUS_FDO_INTERFACE,
385 "NameOwnerChanged", _name_owner_changed, cs);
387 msg = dbus_message_new_method_call(E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
388 E_DBUS_FDO_INTERFACE,
391 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
393 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &bus_name,
397 e_dbus_message_send(bus_conn, msg, _has_owner_cb, -1, cs);
398 dbus_message_unref(msg);
402 dbus_message_unref(msg);
406 Evas_Object *gui_layout_add(Evas_Object *parent, const char *style)
408 Evas_Object *layout = elm_layout_add(parent);
409 if (!elm_layout_theme_set(layout, "layout", "dialer", style)) {
410 evas_object_del(layout);
417 static int _running_apps_iter(const aul_app_info *info, void *data __UNUSED__)
419 if (strcmp(info->pkg_name, "org.tizen.draglock") == 0)
420 aul_terminate_pid(info->pid);
425 static void _phone_unlock_screen(void)
427 INF("unlock screen");
429 aul_app_get_running_app_info(_running_apps_iter, NULL);
433 static void _slider_pos_changed_cb(void *data, Evas_Object *obj,
434 void *event_inf __UNUSED__)
436 Call_Screen *cs = data;
437 const char *label = elm_actionslider_selected_label_get(obj);
442 if (strcmp(label, "Answer") == 0) {
443 _daemon_method_call_make("AnswerCall");
444 elm_actionslider_indicator_pos_set(obj,
445 ELM_ACTIONSLIDER_CENTER);
446 _phone_unlock_screen();
447 _call_screen_hide(cs);
448 } else if (strcmp(label, "Hangup") == 0) {
449 _daemon_method_call_make("HangupCall");
450 elm_actionslider_indicator_pos_set(obj,
451 ELM_ACTIONSLIDER_CENTER);
455 static Eina_Bool _gui_init(Call_Screen *cs)
457 Evas_Object *win, *obj, *lay, *slider;
459 char def_theme[PATH_MAX];
460 /* should never, ever quit */
462 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_NONE);
463 elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR);
464 elm_app_compile_data_dir_set(PACKAGE_DATA_DIR);
465 elm_app_info_set(_gui_init, "answer-ofono-efl", "themes/default.edj");
467 snprintf(def_theme, sizeof(def_theme), "%s/themes/default.edj",
468 elm_app_data_dir_get());
470 elm_theme_extension_add(NULL, def_theme);
471 elm_theme_overlay_add(NULL, def_theme);
473 win = elm_win_util_standard_add("answer screen", "oFono Answer");
474 EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
475 elm_win_autodel_set(win, EINA_FALSE);
476 elm_object_part_text_set(win, "elm.text.name", _("Unknown"));
477 elm_object_part_text_set(win, "elm.text.state", _("Incoming..."));
479 lay = gui_layout_add(win, "answer");
480 EINA_SAFETY_ON_NULL_RETURN_VAL(lay, EINA_FALSE);
481 evas_object_show(lay);
483 slider = elm_actionslider_add(win);
484 EINA_SAFETY_ON_NULL_GOTO(slider, err_obj);
485 elm_object_style_set(slider, "answer");
486 elm_actionslider_indicator_pos_set(slider, ELM_ACTIONSLIDER_CENTER);
487 elm_actionslider_magnet_pos_set(slider, ELM_ACTIONSLIDER_CENTER);
488 elm_object_part_text_set(slider, "left", _("Hangup"));
489 elm_object_part_text_set(slider, "right", _("Answer"));
490 evas_object_smart_callback_add(slider, "selected",
491 _slider_pos_changed_cb, cs);
492 evas_object_show(slider);
493 elm_object_part_content_set(lay, "elm.swallow.slider", slider);
495 obj = elm_layout_edje_get(lay);
496 edje_object_size_min_get(obj, &w, &h);
497 if ((w == 0) || (h == 0))
498 edje_object_size_min_restricted_calc(obj, &w, &h, w, h);
499 if ((w == 0) || (h == 0))
500 edje_object_parts_extends_calc(obj, NULL, NULL, &w, &h);
501 evas_object_resize(lay, w, h);
502 evas_object_resize(win, w, h);
509 evas_object_del(win);
513 EAPI int elm_main(int argc __UNUSED__, char **argv __UNUSED__)
517 if (!elm_need_e_dbus()) {
518 ERR("Could not start E_dbus");
522 _log_domain = eina_log_domain_register("answer_daemon", NULL);
523 cs = calloc(1, sizeof(Call_Screen));
524 EINA_SAFETY_ON_NULL_RETURN_VAL(cs, -1);
526 EINA_SAFETY_ON_FALSE_GOTO(_dbus_init(cs), err_dbus);
527 EINA_SAFETY_ON_FALSE_GOTO(_gui_init(cs), err_dbus);
531 _signal_handlers_del(cs);
533 if (cs->sig_name_changed)
534 e_dbus_signal_handler_del(bus_conn, cs->sig_name_changed);
536 evas_object_del(cs->win);
538 _call_destroy(cs->call);