4 #include <Elementary.h>
11 typedef struct _Callscreen
14 Evas_Object *gui_activecall; /* for gui.h */
26 OFono_Call_State last_state;
27 Ecore_Timer *elapsed_updater;
30 OFono_Pending *pending;
39 static void _on_active_call_clicked(void *data __UNUSED__,
40 Evas_Object *o __UNUSED__,
41 const char *emission __UNUSED__,
42 const char *source __UNUSED__)
47 static OFono_Callback_List_Modem_Node *callback_node_modem_changed = NULL;
49 static OFono_Callback_List_Call_Node *callback_node_call_added = NULL;
50 static OFono_Callback_List_Call_Node *callback_node_call_removed = NULL;
51 static OFono_Callback_List_Call_Node *callback_node_call_changed = NULL;
53 static OFono_Callback_List_Call_Disconnected_Node
54 *callback_node_call_disconnected = NULL;
56 static char *_call_name_or_id(const OFono_Call *call);
57 static char *_call_type_get(const OFono_Call *call);
59 static void _on_mp_hangup(void *data, Evas_Object *o __UNUSED__,
60 const char *emission __UNUSED__,
61 const char *source __UNUSED__)
63 OFono_Call *call = data;
64 DBG("User ask hangup of multiparty call=%p", call);
65 ofono_call_hangup(call, NULL, NULL);
68 static void _on_mp_pvt_reply(void *data, OFono_Error err)
70 Callscreen *ctx = data;
72 DBG("PrivateChat: err=%d", err);
74 if (err == OFONO_ERROR_NONE)
75 elm_object_signal_emit(ctx->self, "multiparty,private", "call");
78 static void _on_mp_pvt(void *data, Evas_Object *o,
79 const char *emission __UNUSED__,
80 const char *source __UNUSED__)
82 Callscreen *ctx = evas_object_data_get(o, "callscreen.ctx");
83 OFono_Call *call = data;
84 DBG("User ask private chat of multiparty call=%p", call);
85 ofono_private_chat(call, _on_mp_pvt_reply, ctx);
88 static void _on_raise(void *data __UNUSED__, Evas_Object *o,
89 const char *emission __UNUSED__,
90 const char *source __UNUSED__)
95 static void _multiparty_update(Callscreen *ctx)
97 Eina_List *new = NULL, *old = NULL;
98 const Eina_List *n1, *n2;
102 EINA_LIST_FOREACH(ctx->calls.list, n1, c) {
103 if (ofono_call_multiparty_get(c))
104 new = eina_list_append(new, c);
107 old = ctx->multiparty.calls;
108 if (eina_list_count(new) != eina_list_count(old))
111 for (n1 = new, n2 = old; n1 && n2; n1 = n1->next, n2 = n2->next) {
112 if (n1->data != n2->data)
123 eina_list_free(ctx->multiparty.calls);
124 ctx->multiparty.calls = new;
126 elm_box_clear(ctx->multiparty.bx);
129 elm_object_signal_emit(ctx->self, "hide,multiparty-details",
134 EINA_LIST_FOREACH(new, n1, c) {
135 char *name, *number, *type;
137 name = _call_name_or_id(c);
138 type = _call_type_get(c);
139 number = phone_format(ofono_call_line_id_get(c));
141 it = gui_layout_add(ctx->multiparty.bx, "multiparty-details");
142 evas_object_size_hint_align_set(it,
143 EVAS_HINT_FILL, EVAS_HINT_FILL);
144 evas_object_show(it);
146 elm_object_part_text_set(it, "elm.text.name", name);
147 elm_object_part_text_set(it, "elm.text.number", number);
148 elm_object_part_text_set(it, "elm.text.type", type);
150 if (strcmp(name, number) == 0)
151 elm_object_signal_emit(it, "hide,name", "call");
153 elm_object_signal_emit(it, "show,name", "call");
155 elm_object_signal_callback_add(it, "clicked,hangup", "call",
157 elm_object_signal_callback_add(it, "clicked,private", "call",
159 elm_object_signal_callback_add(it, "raise", "call",
162 evas_object_data_set(it, "callscreen.ctx", ctx);
163 elm_box_pack_end(ctx->multiparty.bx, it);
169 elm_object_signal_emit(ctx->self, "show,multiparty-details", "call");
172 static void _multiparty_private_available_update(Callscreen *ctx)
174 Eina_List *lst = elm_box_children_get(ctx->multiparty.bx);
175 const char *sig = ctx->calls.held ? "hide,private" : "show,private";
178 EINA_LIST_FREE(lst, it)
179 elm_object_signal_emit(it, sig, "call");
182 static void _calls_update(Callscreen *ctx)
185 OFono_Call *c, *found = NULL, *waiting = NULL, *held = NULL;
186 OFono_Call_State found_state = OFONO_CALL_STATE_DISCONNECTED;
187 static const int state_priority[] = {
188 [OFONO_CALL_STATE_DISCONNECTED] = 0,
189 [OFONO_CALL_STATE_ACTIVE] = 6,
190 [OFONO_CALL_STATE_HELD] = 3,
191 [OFONO_CALL_STATE_DIALING] = 5,
192 [OFONO_CALL_STATE_ALERTING] = 4,
193 [OFONO_CALL_STATE_INCOMING] = 2,
194 [OFONO_CALL_STATE_WAITING] = 1
197 if (ctx->calls.active) {
198 OFono_Call_State s = ofono_call_state_get(ctx->calls.active);
199 if (s != OFONO_CALL_STATE_ACTIVE) {
200 ctx->calls.active = NULL;
204 if (ctx->calls.waiting) {
205 OFono_Call_State s = ofono_call_state_get(ctx->calls.waiting);
206 if (s != OFONO_CALL_STATE_WAITING)
207 ctx->calls.waiting = NULL;
209 if (ctx->calls.held) {
210 OFono_Call_State s = ofono_call_state_get(ctx->calls.held);
211 if (s != OFONO_CALL_STATE_HELD)
212 ctx->calls.held = NULL;
215 _multiparty_update(ctx);
217 if (ctx->calls.active && ctx->calls.waiting && ctx->calls.held)
220 EINA_LIST_FOREACH(ctx->calls.list, n, c) {
221 OFono_Call_State state = ofono_call_state_get(c);
223 DBG("compare %p (%d) to %p (%d)", found, found_state,
225 if (state_priority[state] > state_priority[found_state]) {
229 if ((!waiting) && (state == OFONO_CALL_STATE_WAITING))
231 if ((!held) && (state == OFONO_CALL_STATE_HELD))
235 DBG("found=%p, state=%d, waiting=%p, held=%p",
236 found, found_state, waiting, held);
240 if (!ctx->calls.active) {
241 ctx->calls.active = found;
244 if (!ctx->calls.waiting)
245 ctx->calls.waiting = waiting;
246 if (!ctx->calls.held)
247 ctx->calls.held = held;
252 static void _call_disconnected_done(Callscreen *ctx, const char *reason)
256 if (!ctx->calls.list) {
257 if (ctx->gui_activecall) {
258 gui_activecall_set(NULL);
259 evas_object_del(ctx->gui_activecall);
260 ctx->gui_activecall = NULL;
264 if (strcmp(reason, "local") == 0) {
265 /* Bug #11 says this shouldn't be done.
267 * TODO: talk to ofono devs and see what to do,
268 * maybe introuce ReleaseAndSwap()
271 /* If there is a held call and active is
272 * hangup we're left with held but no active,
275 * Just make the held active by calling
278 if (ctx->calls.active == ctx->disconnected.call &&
279 ctx->calls.held != ctx->disconnected.call) {
280 INF("User disconnected and left held call. "
281 "Automatically activate it.");
283 /* TODO: sound to notify user */
284 ofono_swap_calls(NULL, NULL);
289 ctx->disconnected.call = NULL;
292 static void _popup_close(void *data, Evas_Object *o __UNUSED__, void *event __UNUSED__)
294 Callscreen *ctx = data;
296 evas_object_del(ctx->disconnected.popup);
297 ctx->disconnected.popup = NULL;
299 eina_stringshare_replace(&ctx->disconnected.number, NULL);
301 _call_disconnected_done(ctx, "network");
304 static void _popup_redial(void *data, Evas_Object *o __UNUSED__, void *event __UNUSED__)
306 Callscreen *ctx = data;
308 ofono_dial(ctx->disconnected.number, NULL, NULL, NULL);
309 _popup_close(ctx, NULL, NULL);
312 static void _call_disconnected_show(Callscreen *ctx, OFono_Call *c,
316 const char *number, *title;
319 DBG("ctx=%p, active=%p, held=%p, waiting=%p, previous=%s, "
320 "disconnected=%p (%s)",
321 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting,
322 ctx->disconnected.number, c, reason);
324 if (ctx->calls.waiting == c) {
325 ctx->calls.waiting = NULL;
326 elm_object_part_text_set(ctx->self, "elm.text.waiting", "");
327 elm_object_signal_emit(ctx->self, "hide,waiting", "call");
330 if (ctx->calls.held == c) {
331 ctx->calls.held = NULL;
332 if (ofono_call_multiparty_get(c))
334 elm_object_part_text_set(ctx->self, "elm.text.held", "");
335 elm_object_signal_emit(ctx->self, "hide,held", "call");
336 _multiparty_private_available_update(ctx);
340 if ((ctx->calls.active) && (ctx->calls.active != c))
342 ctx->calls.active = NULL;
344 ctx->disconnected.call = c;
346 elm_object_signal_emit(ctx->self, "active,disconnected", "call");
348 if ((strcmp(reason, "local") == 0) || (strcmp(reason, "remote") == 0))
351 number = ofono_call_line_id_get(c);
352 if ((!number) || (number[0] == '\0'))
355 if (ctx->disconnected.number)
358 if (strcmp(reason, "network") == 0)
359 title = "Network Disconnected!";
361 title = "Disconnected!";
363 snprintf(msg, sizeof(msg), "Try to redial %s", number);
365 eina_stringshare_replace(&ctx->disconnected.number, number);
367 ctx->disconnected.popup = p = elm_popup_add(ctx->self);
368 evas_object_size_hint_weight_set(p, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
369 elm_object_part_text_set(p, "title,text", title);
370 elm_object_text_set(p, msg);
372 bt = elm_button_add(p);
373 elm_object_text_set(bt, "Close");
374 elm_object_part_content_set(p, "button1", bt);
375 evas_object_smart_callback_add(bt, "clicked", _popup_close, ctx);
377 bt = elm_button_add(p);
378 elm_object_text_set(bt, "Redial");
379 elm_object_part_content_set(p, "button2", bt);
380 evas_object_smart_callback_add(bt, "clicked", _popup_redial, ctx);
382 /* TODO: sound to notify user */
388 _call_disconnected_done(ctx, reason);
391 static void _tones_send_reply(void *data, OFono_Error err)
393 Callscreen *ctx = data;
396 ERR("Failed to send tones: %d", err);
398 ctx->tones.pending = NULL;
399 if (eina_strbuf_length_get(ctx->tones.todo) > 0) {
400 const char *tones = eina_strbuf_string_get(ctx->tones.todo);
402 DBG("Send pending tones: %s", tones);
403 ctx->tones.pending = ofono_tones_send(
404 tones, _tones_send_reply, ctx);
405 eina_strbuf_reset(ctx->tones.todo);
409 static void _on_pressed(void *data, Evas_Object *obj __UNUSED__,
410 const char *emission, const char *source __UNUSED__)
412 Callscreen *ctx = data;
413 DBG("ctx=%p, active=%p, held=%p, waiting=%p, signal: %s",
414 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting,
417 EINA_SAFETY_ON_FALSE_RETURN(eina_str_has_prefix(emission, "pressed,"));
418 emission += strlen("pressed,");
422 static void _on_released(void *data, Evas_Object *obj __UNUSED__,
423 const char *emission,
424 const char *source __UNUSED__)
426 Callscreen *ctx = data;
427 DBG("ctx=%p, active=%p, held=%p, waiting=%p, signal: %s",
428 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting,
431 EINA_SAFETY_ON_FALSE_RETURN(eina_str_has_prefix(emission, "released,"));
432 emission += strlen("released,");
436 static void _on_clicked(void *data, Evas_Object *obj __UNUSED__,
437 const char *emission, const char *source __UNUSED__)
439 Callscreen *ctx = data;
440 const char *dtmf = NULL;
441 DBG("ctx=%p, active=%p, held=%p, waiting=%p, signal: %s",
442 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting,
445 EINA_SAFETY_ON_FALSE_RETURN(eina_str_has_prefix(emission, "clicked,"));
446 emission += strlen("clicked,");
448 if ((emission[0] >= '0') && (emission[0] <= '9'))
450 else if (strcmp(emission, "star") == 0)
452 else if (strcmp(emission, "hash") == 0)
456 if (!ctx->tones.pending)
457 ctx->tones.pending = ofono_tones_send(
458 dtmf, _tones_send_reply, ctx);
460 eina_strbuf_append_char(ctx->tones.todo, dtmf[0]);
464 if (strcmp(emission, "hangup") == 0) {
465 if (ctx->calls.active) {
466 OFono_Call *c = ctx->calls.active;
467 if (ofono_call_multiparty_get(c))
468 ofono_multiparty_hangup(NULL, NULL);
470 ofono_call_hangup(c, NULL, NULL);
472 } else if (strcmp(emission, "answer") == 0) {
473 if (ctx->calls.active)
474 ofono_call_answer(ctx->calls.active, NULL, NULL);
475 } else if (strcmp(emission, "mute") == 0) {
476 Eina_Bool val = !ofono_mute_get();
477 ofono_mute_set(val, NULL, NULL);
478 } else if (strcmp(emission, "speaker") == 0) {
479 ERR("TODO - implement platform loudspeaker code");
480 } else if (strcmp(emission, "contacts") == 0) {
481 ERR("TODO - implement access to contacts");
482 } else if (strcmp(emission, "add-call") == 0) {
484 } else if (strcmp(emission, "merge") == 0) {
486 ofono_multiparty_create(NULL, NULL);
487 } else if (strcmp(emission, "swap") == 0) {
489 ofono_swap_calls(NULL, NULL);
490 } else if (strcmp(emission, "waiting-hangup") == 0) {
491 if (ctx->calls.waiting)
492 ofono_call_hangup(ctx->calls.waiting, NULL, NULL);
493 } else if (strcmp(emission, "hangup-answer") == 0) {
494 if (ctx->calls.waiting)
495 ofono_release_and_answer(NULL, NULL);
496 } else if (strcmp(emission, "hold-answer") == 0) {
497 if (ctx->calls.waiting)
498 ofono_hold_and_answer(NULL, NULL);
502 static void _on_key_down(void *data, Evas *e __UNUSED__,
503 Evas_Object *o __UNUSED__,
506 Callscreen *ctx = data;
507 Evas_Event_Key_Down *ev = event_info;
508 DBG("ctx=%p, key=%s (%s, %s)", ctx, ev->keyname, ev->key, ev->string);
510 if ((strcmp(ev->key, "minus") == 0) ||
511 (strcmp(ev->key, "KP_Subtract") == 0) ||
512 (strcmp(ev->key, "XF86AudioLowerVolume") == 0)) {
513 unsigned char last, cur;
515 last = cur = ofono_volume_speaker_get();
522 ofono_volume_speaker_set(cur, NULL, NULL);
523 } else if ((strcmp(ev->key, "plus") == 0) ||
524 (strcmp(ev->key, "KP_Add") == 0) ||
525 (strcmp(ev->key, "XF86AudioRaiseVolume") == 0)) {
526 unsigned char last, cur;
528 last = cur = ofono_volume_speaker_get();
535 ofono_volume_speaker_set(cur, NULL, NULL);
539 static void _ofono_changed(void *data)
541 Callscreen *ctx = data;
542 Edje_Message_Float msgf;
546 if (!ctx->calls.list)
549 sig = ofono_mute_get() ? "toggle,on,mute" : "toggle,off,mute";
550 elm_object_signal_emit(ctx->self, sig, "call");
552 ed = elm_layout_edje_get(ctx->self);
554 msgf.val = (ofono_volume_speaker_get() / 100.0);
555 edje_object_message_send(ed, EDJE_MESSAGE_FLOAT, 1, &msgf);
557 msgf.val = (ofono_volume_microphone_get() / 100.0);
558 edje_object_message_send(ed, EDJE_MESSAGE_FLOAT, 2, &msgf);
562 static void _call_added(void *data, OFono_Call *c)
564 Callscreen *ctx = data;
565 DBG("ctx=%p, active=%p, held=%p, waiting=%p, added=%p",
566 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting, c);
568 ctx->calls.list = eina_list_append(ctx->calls.list, c);
569 if (!ctx->calls.active) {
575 static void _call_removed(void *data, OFono_Call *c)
577 Callscreen *ctx = data;
578 DBG("ctx=%p, active=%p, held=%p, waiting=%p, removed=%p",
579 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting, c);
580 ctx->calls.list = eina_list_remove(ctx->calls.list, c);
581 _call_disconnected_show(ctx, c, "local");
584 static Eina_Bool _on_elapsed_updater(void *data)
586 Callscreen *ctx = data;
587 double next, elapsed, start;
588 Edje_Message_Float msgf;
589 Evas_Object *ed, *activecall = ctx->gui_activecall;
592 if (!ctx->calls.active)
595 start = ofono_call_start_time_get(ctx->calls.active);
597 ERR("Unknown start time for call");
601 elapsed = ecore_loop_time_get() - start;
603 ERR("Time rewinded? %f - %f = %f", ecore_loop_time_get(), start,
608 ed = elm_layout_edje_get(ctx->self);
610 edje_object_message_send(ed, EDJE_MESSAGE_FLOAT, 3, &msgf);
613 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
615 (int)elapsed % 3600 / 60,
618 snprintf(buf, sizeof(buf), "%02d:%02d",
621 elm_object_part_text_set(ctx->self, "elm.text.elapsed", buf);
623 elm_object_part_text_set(activecall, "elm.text.elapsed", buf);
625 next = 1.0 - (elapsed - (int)elapsed);
626 ctx->elapsed_updater = ecore_timer_add(next, _on_elapsed_updater, ctx);
631 elm_object_part_text_set(activecall, "elm.text.elapsed", "");
632 elm_object_signal_emit(activecall, "hide,elapsed", "call");
635 elm_object_part_text_set(ctx->self, "elm.text.elapsed", "");
636 elm_object_signal_emit(ctx->self, "hide,elapsed", "call");
637 ctx->elapsed_updater = NULL;
641 static char *_call_name_or_id(const OFono_Call *call)
643 const char *s = ofono_call_line_id_get(call);
644 Contact_Info *info = gui_contact_search(s, NULL);
647 return strdup(contact_info_name_get(info));
650 return phone_format(ofono_call_line_id_get(call));
653 static char *_call_name_get(const Callscreen *ctx __UNUSED__,
654 const OFono_Call *call)
656 if (!ofono_call_multiparty_get(call))
657 return _call_name_or_id(call);
659 return strdup("Conference");
662 static char *_call_type_get(const OFono_Call *call)
665 const char *s = ofono_call_line_id_get(call);
666 Contact_Info *info = gui_contact_search(s, &type);
675 static void _call_changed(void *data, OFono_Call *c)
677 Callscreen *ctx = data;
678 OFono_Call_State state;
679 Eina_Bool was_waiting, was_held, is_held;
680 const char *status, *sig = "hide,answer";
681 char *contact, *type;
683 DBG("ctx=%p, active=%p, held=%p, waiting=%p, changed=%p",
684 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting, c);
686 was_waiting = !!ctx->calls.waiting;
688 was_held = (ctx->calls.held) && (ctx->calls.held != ctx->calls.active);
692 if ((ctx->calls.waiting) && (!was_waiting)) {
694 contact = _call_name_get(ctx, ctx->calls.waiting);
695 snprintf(buf, sizeof(buf), "%s is waiting...", contact);
696 elm_object_part_text_set(ctx->self, "elm.text.waiting", buf);
697 elm_object_signal_emit(ctx->self, "show,waiting", "call");
699 } else if ((!ctx->calls.waiting) && (was_waiting)) {
700 elm_object_part_text_set(ctx->self, "elm.text.waiting", "");
701 elm_object_signal_emit(ctx->self, "hide,waiting", "call");
704 is_held = (ctx->calls.held) && (ctx->calls.held != ctx->calls.active);
706 if ((is_held) && (!was_held)) {
707 elm_object_signal_emit(ctx->self, "show,held", "call");
708 _multiparty_private_available_update(ctx);
709 } else if ((!is_held) && (was_held)) {
710 elm_object_part_text_set(ctx->self, "elm.text.held", "");
711 elm_object_signal_emit(ctx->self, "hide,held", "call");
712 _multiparty_private_available_update(ctx);
715 c = ctx->calls.active;
719 contact = _call_name_get(ctx, c);
720 type = _call_type_get(c);
722 state = ofono_call_state_get(c);
724 case OFONO_CALL_STATE_DISCONNECTED:
725 status = "Disconnected";
727 case OFONO_CALL_STATE_ACTIVE:
730 case OFONO_CALL_STATE_HELD:
733 case OFONO_CALL_STATE_DIALING:
734 status = "Dialing...";
736 case OFONO_CALL_STATE_ALERTING:
737 status = "Alerting...";
739 case OFONO_CALL_STATE_INCOMING:
740 status = "Incoming...";
743 case OFONO_CALL_STATE_WAITING:
744 status = "Waiting...";
750 if (!ctx->gui_activecall) {
751 ctx->gui_activecall = gui_layout_add(ctx->self, "activecall");
752 elm_object_signal_callback_add(ctx->gui_activecall,
754 _on_active_call_clicked, ctx);
755 gui_activecall_set(ctx->gui_activecall);
757 elm_object_part_text_set(ctx->gui_activecall, "elm.text.name", contact);
759 elm_object_part_text_set(ctx->gui_activecall,
760 "elm.text.phone.type", type);
761 elm_object_part_text_set(ctx->gui_activecall, "elm.text.status",
765 elm_object_part_text_set(ctx->self, "elm.text.name", contact);
766 elm_object_part_text_set(ctx->self, "elm.text.phone.type", type);
770 elm_object_part_text_set(ctx->self, "elm.text.status", status);
771 elm_object_signal_emit(ctx->self, sig, "call");
773 sig = ofono_call_multiparty_get(c) ? "show,multiparty" :
775 elm_object_signal_emit(ctx->self, sig, "call");
776 elm_object_signal_emit(ctx->gui_activecall, sig, "call");
778 if (ctx->last_state != state) {
779 Eina_Bool have_updater = !!ctx->elapsed_updater;
780 Eina_Bool want_updater = EINA_FALSE;
783 case OFONO_CALL_STATE_DISCONNECTED:
784 sig = "state,disconnected";
786 case OFONO_CALL_STATE_ACTIVE:
787 sig = "state,active";
788 want_updater = EINA_TRUE;
790 case OFONO_CALL_STATE_HELD:
793 case OFONO_CALL_STATE_DIALING:
794 sig = "state,dialing";
796 case OFONO_CALL_STATE_ALERTING:
797 sig = "state,alerting";
799 case OFONO_CALL_STATE_INCOMING:
800 sig = "state,incoming";
802 case OFONO_CALL_STATE_WAITING:
803 sig = "state,waiting";
809 elm_object_signal_emit(ctx->self, sig, "call");
810 elm_object_signal_emit(ctx->gui_activecall,
813 ctx->last_state = state;
816 if (have_updater && !want_updater) {
817 ecore_timer_del(ctx->elapsed_updater);
818 ctx->elapsed_updater = NULL;
819 sig = "hide,elapsed";
820 elm_object_part_text_set(ctx->self, "elm.text.elapsed",
822 } else if (want_updater) {
824 sig = "show,elapsed";
826 ecore_timer_del(ctx->elapsed_updater);
827 ctx->elapsed_updater = NULL;
829 _on_elapsed_updater(ctx);
832 elm_object_signal_emit(ctx->self, sig, "call");
833 elm_object_signal_emit(ctx->gui_activecall,
839 contact = _call_name_get(ctx, ctx->calls.held);
840 elm_object_part_text_set(ctx->self, "elm.text.held", contact);
843 if (ofono_call_multiparty_get(ctx->calls.held))
844 sig = "show,held,multiparty";
846 sig = "hide,held,multiparty";
847 elm_object_signal_emit(ctx->self, sig, "call");
850 sig = is_held ? "enable,merge" : "disable,merge";
851 elm_object_signal_emit(ctx->self, sig, "call");
853 sig = ctx->calls.held ? "enable,swap" : "disable,swap";
854 elm_object_signal_emit(ctx->self, sig, "call");
856 if (state == OFONO_CALL_STATE_DISCONNECTED)
857 _call_disconnected_show(ctx, c, "local");
862 static void _call_disconnected(void *data, OFono_Call *c, const char *reason)
864 Callscreen *ctx = data;
865 DBG("ctx=%p, active=%p, held=%p, waiting=%p, disconnected=%p (%s)",
866 ctx, ctx->calls.active, ctx->calls.held, ctx->calls.waiting,
869 EINA_SAFETY_ON_NULL_RETURN(reason);
870 _call_disconnected_show(ctx, c, reason);
873 static void _on_del(void *data, Evas *e __UNUSED__,
874 Evas_Object *obj __UNUSED__, void *event __UNUSED__)
876 Callscreen *ctx = data;
878 ofono_call_added_cb_del(callback_node_call_added);
879 ofono_call_removed_cb_del(callback_node_call_removed);
880 ofono_call_changed_cb_del(callback_node_call_changed);
881 ofono_call_disconnected_cb_del(callback_node_call_disconnected);
882 ofono_modem_changed_cb_del(callback_node_modem_changed);
884 eina_strbuf_free(ctx->tones.todo);
885 if (ctx->tones.pending)
886 ofono_pending_cancel(ctx->tones.pending);
888 if (ctx->elapsed_updater)
889 ecore_timer_del(ctx->elapsed_updater);
891 eina_stringshare_del(ctx->disconnected.number);
893 eina_list_free(ctx->multiparty.calls);
895 eina_list_free(ctx->calls.list);
899 Evas_Object *callscreen_add(Evas_Object *parent)
902 Evas_Object *obj = gui_layout_add(parent, "call");
903 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
905 ctx = calloc(1, sizeof(Callscreen));
907 ctx->tones.todo = eina_strbuf_new();
909 evas_object_data_set(obj, "callscreen.ctx", ctx);
911 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
913 elm_object_signal_callback_add(obj, "pressed,*", "call",
915 elm_object_signal_callback_add(obj, "released,*", "call",
917 elm_object_signal_callback_add(obj, "clicked,*", "call",
920 elm_object_focus_allow_set(obj, EINA_TRUE);
921 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
924 elm_object_part_text_set(obj, "elm.text.name", "");
925 elm_object_part_text_set(obj, "elm.text.status", "");
926 elm_object_part_text_set(obj, "elm.text.elapsed", "");
928 ctx->multiparty.sc = elm_scroller_add(obj);
929 elm_scroller_policy_set(ctx->multiparty.sc, ELM_SCROLLER_POLICY_AUTO,
930 ELM_SCROLLER_POLICY_OFF);
931 elm_scroller_bounce_set(ctx->multiparty.sc, EINA_FALSE, EINA_TRUE);
932 elm_object_style_set(ctx->multiparty.sc, "multiparty-details");
934 ctx->multiparty.bx = elm_box_add(obj);
935 evas_object_size_hint_weight_set(ctx->multiparty.bx,
936 EVAS_HINT_EXPAND, 0.0);
937 evas_object_size_hint_align_set(ctx->multiparty.bx,
938 EVAS_HINT_FILL, 0.0);
939 evas_object_show(ctx->multiparty.bx);
940 elm_object_content_set(ctx->multiparty.sc, ctx->multiparty.bx);
942 elm_object_part_content_set(obj, "elm.swallow.multiparty-details",
945 callback_node_call_added = ofono_call_added_cb_add(_call_added, ctx);
947 callback_node_call_removed =
948 ofono_call_removed_cb_add(_call_removed, ctx);
950 callback_node_call_changed =
951 ofono_call_changed_cb_add(_call_changed, ctx);
953 callback_node_call_disconnected =
954 ofono_call_disconnected_cb_add(_call_disconnected, ctx);
956 callback_node_modem_changed =
957 ofono_modem_changed_cb_add(_ofono_changed, ctx);