b181804bc3f5907870f0b64fb9e59ef1c28fde30
[profile/ivi/lemolo.git] / dialer / gui.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <Elementary.h>
5
6 #include "log.h"
7 #include "gui.h"
8 #include "keypad.h"
9 #include "history.h"
10 #include "callscreen.h"
11 #include "ussd.h"
12 #include "util.h"
13 #include "simple-popup.h"
14 #include "i18n.h"
15
16 #ifdef HAVE_TIZEN
17 #include <appcore-efl.h>
18 #ifdef HAVE_UI_GADGET
19 #include <ui-gadget.h>
20 #endif
21 #include <Ecore_X.h>
22 #endif
23
24 static Evas_Object *win = NULL;
25 static Evas_Object *main_layout = NULL;
26 static Evas_Object *keypad = NULL;
27 static Evas_Object *contacts = NULL;
28 static Evas_Object *history = NULL;
29 static Evas_Object *cs = NULL;
30 static Evas_Object *flip = NULL;
31 static Evas_Object *current_view = NULL;
32
33 static OFono_Callback_List_Modem_Node *callback_node_modem_changed = NULL;
34 static OFono_Callback_List_USSD_Notify_Node *callback_node_ussd_notify = NULL;
35 static AMB_Callback_List_Node *callback_node_amb_properties_changed = NULL;
36 static Locale_Callback_List_Node *callback_node_locale_properties_changed = NULL;
37
38 /* XXX elm_flip should just do the right thing, but it does not */
39 static Eina_Bool in_call = EINA_FALSE;
40 static Eina_Bool in_flip_anim = EINA_FALSE;
41
42 static Eina_Bool night_mode = EINA_FALSE;
43
44 Contact_Info *gui_contact_search(const char *number, const char **type)
45 {
46         return contact_search(contacts, number, type);
47 }
48
49 static void _dial_reply(void *data, OFono_Error err,
50                         OFono_Call *call __UNUSED__)
51 {
52         char *number = data;
53
54         if (err != OFONO_ERROR_NONE) {
55                 char buf[1024];
56                 const char *msg = ofono_error_message_get(err);
57                 snprintf(buf, sizeof(buf), _("Could not call %s: %s"),
58                                 number, msg);
59                 gui_simple_popup(_("Error"), buf);
60         }
61
62         free(number);
63 }
64
65 OFono_Pending *gui_dial(const char *number)
66 {
67         char *copy = strdup(number);
68         return ofono_dial(copy, NULL, _dial_reply, copy);
69 }
70
71 static void _gui_set_text(void)
72 {
73         elm_object_part_text_set(cs, "label.hide-keypad", _("Hide Keypad"));
74         elm_object_part_text_set(cs, "label.answer", _("Answer"));
75         elm_object_part_text_set(cs, "label.hangup", _("Hangup"));
76         elm_object_part_text_set(cs, "label.multiparty", _("Conference"));
77         elm_object_part_text_set(cs, "label.multiparty-details-back", _("Back"));
78         elm_object_part_text_set(cs, "label.waiting", _("Waiting..."));
79         elm_object_part_text_set(cs, "elm.text.name", _("Unknown"));
80         elm_object_part_text_set(cs, "elm.text.waiting", _("Unknown"));
81
82         elm_object_part_text_set(keypad, "label.all", _("Decline"));
83         elm_object_part_text_set(keypad, "label.missed", _("Hold + Answer"));
84         elm_object_part_text_set(keypad, "label.clear", _("Hangup + Answer"));
85         elm_object_part_text_set(keypad, "label.edit,done", _("Redial"));
86
87         elm_object_part_text_set(history, "label.all", _("All"));
88         elm_object_part_text_set(history, "label.missed", _("Missed"));
89         elm_object_part_text_set(history, "label.clear", _("Clear"));
90         elm_object_part_text_set(history, "label.edit,done", _("Done"));
91 }
92
93 static void _gui_show(Evas_Object *o)
94 {
95         Last_User_Mode *last;
96
97         last = util_get_last_user_mode();
98         if (o == keypad)
99                 elm_object_signal_emit(main_layout, "show,keypad", "gui");
100         else if (o == contacts)
101                 elm_object_signal_emit(main_layout, "show,contacts", "gui");
102         else if (o == history)
103                 elm_object_signal_emit(main_layout, "show,history", "gui");
104         elm_object_focus_set(o, EINA_TRUE);
105         current_view = o;
106
107         if (last) {
108                 if (current_view == keypad)
109                         last->last_view = DIALER_LAST_VIEW_KEYPAD;
110                 else if (current_view == contacts)
111                         last->last_view = DIALER_LAST_VIEW_CONTACTS;
112                 else if (current_view == history)
113                         last->last_view = DIALER_LAST_VIEW_HISTORY;
114
115                 util_set_last_user_mode(last);
116         }
117 }
118
119 Evas_Object *gui_simple_popup(const char *title, const char *message)
120 {
121         return simple_popup_add(win, title, message);
122 }
123
124 void gui_activate(void)
125 {
126         elm_win_raise(win);
127         elm_win_activate(win);
128         evas_object_show(win);
129
130         /* Automatically enable hfp modem if app is in the foreground */
131         if (!ofono_voice_is_online()) {
132                 ofono_powered_set(EINA_TRUE, NULL, NULL);
133         }
134 }
135
136 void gui_number_set(const char *number, Eina_Bool auto_dial)
137 {
138         _gui_show(keypad);
139         keypad_number_set(keypad, number, auto_dial);
140 }
141
142 void gui_activecall_set(Evas_Object *o)
143 {
144         if (o) {
145                 elm_object_part_content_set(main_layout,
146                                                 "elm.swallow.activecall", o);
147                 elm_object_signal_emit(main_layout, "show,activecall", "gui");
148         } else {
149                 o = elm_object_part_content_unset(
150                         main_layout, "elm.swallow.activecall");
151                 elm_object_signal_emit(main_layout, "hide,activecall", "gui");
152                 evas_object_hide(o);
153         }
154 }
155
156 void gui_contacts_show(void)
157 {
158         _gui_show(contacts);
159         gui_call_exit();
160 }
161
162 void gui_call_enter(void)
163 {
164         gui_activate();
165         if (in_call)
166                 return;
167         in_call = EINA_TRUE;
168         if (in_flip_anim)
169                 return;
170         in_flip_anim = EINA_TRUE;
171         elm_flip_go(flip, ELM_FLIP_ROTATE_Y_CENTER_AXIS);
172         elm_object_focus_set(cs, EINA_TRUE);
173 }
174
175 void gui_call_exit(void)
176 {
177         if (!in_call)
178                 return;
179         in_call = EINA_FALSE;
180         if (in_flip_anim)
181                 return;
182         in_flip_anim = EINA_TRUE;
183         elm_flip_go(flip, ELM_FLIP_ROTATE_Y_CENTER_AXIS);
184         elm_object_focus_set(cs, EINA_FALSE);
185 }
186
187 static void _gui_call_sync(void *data __UNUSED__, Evas_Object *o __UNUSED__,
188                                 void *event_info __UNUSED__)
189 {
190         Eina_Bool showing_call = !elm_flip_front_visible_get(flip);
191
192         if (showing_call ^ in_call) {
193                 DBG("Flip back to sync");
194                 elm_flip_go(flip, ELM_FLIP_ROTATE_Y_CENTER_AXIS);
195                 elm_object_focus_set(cs, in_call);
196         }
197         in_flip_anim = EINA_FALSE;
198 }
199
200 static void _gui_voicemail(void)
201 {
202         const char *number = ofono_voicemail_number_get();
203         EINA_SAFETY_ON_NULL_RETURN(number);
204         EINA_SAFETY_ON_FALSE_RETURN(*number != '\0');
205
206         gui_dial(number);
207 }
208
209 static void _gui_quit(void)
210 {
211         elm_exit();
212 }
213
214 static void _on_del(void *data __UNUSED__, Evas *e __UNUSED__,
215                         Evas_Object *obj __UNUSED__, void *event __UNUSED__)
216 {
217         _gui_quit();
218 }
219
220 static void _on_clicked(void *data __UNUSED__, Evas_Object *o __UNUSED__,
221                         const char *emission, const char *source __UNUSED__)
222 {
223         DBG("signal: %s", emission);
224
225         EINA_SAFETY_ON_FALSE_RETURN(eina_str_has_prefix(emission, "clicked,"));
226         emission += strlen("clicked,");
227
228         if (strcmp(emission, "keypad") == 0)
229                 _gui_show(keypad);
230         else if (strcmp(emission, "contacts") == 0)
231                 _gui_show(contacts);
232         else if (strcmp(emission, "history") == 0)
233                 _gui_show(history);
234         else if (strcmp(emission, "voicemail") == 0)
235                 _gui_voicemail();
236         else if (strcmp(emission, "quit") == 0)
237                 _gui_quit();
238 }
239
240 static void _ofono_changed(void *data __UNUSED__)
241 {
242         const char *number;
243         Eina_Bool waiting;
244         unsigned char count;
245         char buf[32];
246
247         if ((ofono_modem_api_get() & OFONO_API_MSG_WAITING) == 0) {
248                 elm_object_signal_emit(main_layout, "disable,voicemail", "gui");
249                 elm_object_signal_emit(main_layout,
250                                         "toggle,off,voicemail", "gui");
251                 elm_object_part_text_set(main_layout, "elm.text.voicemail", "");
252                 return;
253         }
254
255         number = ofono_voicemail_number_get();
256         waiting = ofono_voicemail_waiting_get();
257         count = ofono_voicemail_count_get();
258
259         if (number)
260                 elm_object_signal_emit(main_layout, "enable,voicemail", "gui");
261         else
262                 elm_object_signal_emit(main_layout, "disable,voicemail", "gui");
263
264         if (waiting) {
265                 if (count == 0)
266                         snprintf(buf, sizeof(buf), "*");
267                 else if (count < 255)
268                         snprintf(buf, sizeof(buf), "%d", count);
269                 else
270                         snprintf(buf, sizeof(buf), "255+");
271
272                 elm_object_signal_emit(main_layout,
273                                         "toggle,on,voicemail", "gui");
274         } else {
275                 buf[0] = '\0';
276                 elm_object_signal_emit(main_layout,
277                                         "toggle,off,voicemail", "gui");
278         }
279
280         elm_object_part_text_set(main_layout, "elm.text.voicemail", buf);
281 }
282
283 static void _amb_properties_changed(void *data __UNUSED__)
284 {
285         Eina_Bool night_mode_changed = amb_night_mode_get();
286         if (night_mode != night_mode_changed) {
287                 DBG("Night mode changed to %d", night_mode_changed);
288                 night_mode = night_mode_changed;
289                 util_set_night_mode(night_mode);
290
291                 if (current_view)
292                         _gui_show(current_view);
293         }
294 }
295
296 static void _locale_properties_changed(void *data __UNUSED__)
297 {
298         const char *new_lang = locale_lang_get();
299         if (new_lang) {
300                 if (strncmp(new_lang, "LANG=", 5) == 0)
301                         new_lang += 5;
302
303                 DBG("Switching UI language to %s", new_lang);
304                 setenv ("LANG", new_lang, 1);
305                 setlocale (LC_ALL, new_lang);
306                 _gui_set_text();
307         }
308 }
309
310 static void _ofono_ussd_notify(void *data __UNUSED__, Eina_Bool needs_reply,
311                                 const char *message)
312 {
313         DBG("needs_reply=%d, message=%s", needs_reply, message);
314         ussd_start(message);
315 }
316
317 static void _on_contacts_selected(void *data __UNUSED__,
318                                         Evas_Object *obj __UNUSED__,
319                                         void *event_info)
320 {
321         const char *number = event_info;
322         DBG("Contact selected: %s", number);
323         gui_dial(number);
324 }
325
326 static void _load_last_user_view() {
327         Last_User_Mode *last;
328
329         last = util_get_last_user_mode();
330         if (!last) {
331                 DBG("Last user config file not found - create default view");
332                 last = calloc(1, sizeof(Last_User_Mode));
333                 last->last_view = DIALER_LAST_VIEW_KEYPAD;
334                 last->last_history_view = DIALER_LAST_HISTORY_VIEW_ALL;
335                 last->last_number = eina_stringshare_add("");
336                 util_set_last_user_mode(last);
337         }
338
339         if(last->last_number) {
340                 keypad_number_set(keypad, last->last_number, EINA_FALSE);
341         }
342         if (last->last_view == DIALER_LAST_VIEW_KEYPAD) {
343                 _gui_show(keypad);
344         } else if (last->last_view == DIALER_LAST_VIEW_CONTACTS) {
345                 _gui_show(contacts);
346         } else if (last->last_view == DIALER_LAST_VIEW_HISTORY) {
347                 _gui_show(history);
348                 if (last->last_history_view != DIALER_LAST_HISTORY_VIEW_ALL) {
349                         elm_object_signal_emit(history, "show,missed", "gui");
350                 }
351         }
352         eina_stringshare_del(last->last_number);
353         free(last);
354 }
355
356 Eina_Bool gui_init(void)
357 {
358         Evas_Object *lay, *obj;
359         Evas_Coord w, h;
360         const char *lang;
361
362         /* dialer should never, ever quit */
363         elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
364
365         win = elm_win_util_standard_add("ofono-dialer", "oFono Dialer");
366         EINA_SAFETY_ON_NULL_RETURN_VAL(win, EINA_FALSE);
367         elm_win_autodel_set(win, EINA_TRUE);
368         evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _on_del, NULL);
369
370 #ifdef HAVE_TIZEN
371 #ifdef HAVE_UI_GADGET
372         UG_INIT_EFL(win, UG_OPT_INDICATOR_PORTRAIT_ONLY);
373 #endif
374 #endif
375
376         /*
377          * check LANG and LC_ALL environment variables,
378          * LC_ALL takes precedence
379          */
380         lang = getenv("LC_ALL");
381         if (!lang)
382                 lang = getenv("LANG");
383
384         setlocale(LC_ALL, lang);
385         bindtextdomain(PACKAGE, LOCALEDIR);
386         textdomain(PACKAGE);
387
388         flip = elm_flip_add(win);
389         evas_object_size_hint_weight_set(flip,
390                                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
391         evas_object_size_hint_align_set(flip, EVAS_HINT_FILL, EVAS_HINT_FILL);
392         elm_win_resize_object_add(win, flip);
393         evas_object_smart_callback_add(flip, "animate,done",
394                                         _gui_call_sync, NULL);
395         evas_object_show(flip);
396
397         main_layout = lay = layout_add(win, "dialer");
398         EINA_SAFETY_ON_NULL_RETURN_VAL(lay, EINA_FALSE);
399         evas_object_size_hint_weight_set(lay,
400                                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
401         evas_object_size_hint_align_set(lay, EVAS_HINT_FILL, EVAS_HINT_FILL);
402         elm_object_part_content_set(flip, "front", lay);
403         evas_object_show(lay);
404
405         elm_object_signal_callback_add(lay, "clicked,*", "gui",
406                                         _on_clicked, NULL);
407
408         keypad = obj = keypad_add(win);
409         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
410         elm_object_part_content_set(lay, "elm.swallow.keypad", obj);
411
412         contacts = obj = contacts_add(win);
413         evas_object_smart_callback_add(contacts, "selected",
414                                         _on_contacts_selected, NULL);
415         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
416         elm_object_part_content_set(lay, "elm.swallow.contacts", obj);
417
418         history = obj = history_add(win);
419         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
420         elm_object_part_content_set(lay, "elm.swallow.history", obj);
421
422         cs = obj = callscreen_add(win);
423         EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
424         evas_object_size_hint_weight_set(obj,
425                                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
426         evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
427         elm_object_part_content_set(flip, "back", obj);
428         evas_object_show(obj);
429
430         _gui_set_text();
431         _load_last_user_view();
432
433         callback_node_modem_changed =
434                 ofono_modem_changed_cb_add(_ofono_changed, NULL);
435         callback_node_ussd_notify =
436                 ofono_ussd_notify_cb_add(_ofono_ussd_notify, NULL);
437         callback_node_amb_properties_changed =
438                 amb_properties_changed_cb_add(_amb_properties_changed, NULL);
439         callback_node_locale_properties_changed =
440                 locale_properties_changed_cb_add(_locale_properties_changed, NULL);
441
442         /* TODO: make it match better with Tizen: icon and other properties */
443         obj = elm_layout_edje_get(lay);
444         edje_object_size_min_get(obj, &w, &h);
445         if ((w == 0) || (h == 0))
446                 edje_object_size_min_restricted_calc(obj, &w, &h, w, h);
447         if ((w == 0) || (h == 0))
448                 edje_object_parts_extends_calc(obj, NULL, NULL, &w, &h);
449         evas_object_resize(win, w, h);
450
451         /* do not show it yet, RC will check if it should be visible or not */
452         return EINA_TRUE;
453 }
454
455 void gui_shutdown(void)
456 {
457 }