Adding logic to handle disconnected modems
[profile/ivi/lemolo.git] / tizen / dialer_daemon.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <Elementary.h>
5 #include <appcore-efl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <Evas.h>
9 #include <E_DBus.h>
10 #include <aul.h>
11 #include <appsvc.h>
12 #include <Eina.h>
13
14 #define APP_NAME "org.tizen.call"
15 #define BUS_NAME "org.tizen.dialer"
16 #define PATH "/"
17 #define IFACE "org.tizen.dialer.Control"
18
19 static E_DBus_Connection *bus_conn = NULL;
20
21
22 typedef struct _Daemon {
23         Eina_Bool online;
24         Eina_List *pending;
25 } Daemon;
26
27 static void _dial_return_cb(void *data __UNUSED__, DBusMessage *msg __UNUSED__,
28                                 DBusError *error)
29 {
30         if (dbus_error_is_set(error)) {
31                 fprintf(stderr, "Error: %s %s", error->name, error->message);
32                 return;
33         }
34         elm_exit();
35 }
36
37 static void _pending_call_send(Daemon *d)
38 {
39         DBusMessage *p_msg;
40         EINA_LIST_FREE(d->pending, p_msg) {
41                 e_dbus_message_send(bus_conn, p_msg, _dial_return_cb, -1, NULL);
42                 dbus_message_unref(p_msg);
43         }
44 }
45
46 static void _has_owner_cb(void *data, DBusMessage *msg, DBusError *error)
47 {
48         dbus_bool_t online;
49         DBusError err;
50         Daemon *d = data;
51
52         if (dbus_error_is_set(error)) {
53                 fprintf(stderr, "Error: %s %s", error->name, error->message);
54                 return;
55         }
56         dbus_error_init(&err);
57         dbus_message_get_args(msg, &err, DBUS_TYPE_BOOLEAN, &online,
58                                 DBUS_TYPE_INVALID);
59
60         if (!online)
61                 e_dbus_start_service_by_name(bus_conn, BUS_NAME, 0, NULL, NULL);
62         else {
63                 d->online = EINA_TRUE;
64                 _pending_call_send(d);
65         }
66 }
67
68 static void _name_owner_changed(void *data, DBusMessage *msg)
69 {
70         DBusError err;
71         const char *name, *from, *to;
72         Daemon *d = data;
73
74         dbus_error_init(&err);
75         if (!dbus_message_get_args(msg, &err,
76                                         DBUS_TYPE_STRING, &name,
77                                         DBUS_TYPE_STRING, &from,
78                                         DBUS_TYPE_STRING, &to,
79                                         DBUS_TYPE_INVALID)) {
80                 fprintf(stderr,
81                         "Could not get NameOwnerChanged arguments: %s: %s",
82                         err.name, err.message);
83                 dbus_error_free(&err);
84                 return;
85         }
86
87         if (strcmp(name, BUS_NAME) != 0)
88                 return;
89
90         d->online = EINA_TRUE;
91         _pending_call_send(d);
92 }
93
94 static Eina_Bool _dbus_init(Daemon *dialer_daemon)
95 {
96         DBusMessage *msg;
97         char *bus_name = BUS_NAME;
98
99         bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
100         if (!bus_conn) {
101                 fprintf(stderr, "Could not fetch the DBus session");
102                 return EINA_FALSE;
103         }
104
105         e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
106                                         E_DBUS_FDO_INTERFACE,
107                                         "NameOwnerChanged",
108                                         _name_owner_changed, dialer_daemon);
109
110         msg = dbus_message_new_method_call(E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
111                                                 E_DBUS_FDO_INTERFACE,
112                                                 "NameHasOwner");
113
114         EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
115
116         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &bus_name,
117                                         DBUS_TYPE_INVALID))
118                 goto err_msg;
119
120         e_dbus_message_send(bus_conn, msg, _has_owner_cb, -1, dialer_daemon);
121         dbus_message_unref(msg);
122
123         return EINA_TRUE;
124 err_msg:
125         dbus_message_unref(msg);
126         return EINA_FALSE;
127 }
128
129 static int _dial(const char *number, Daemon *d)
130 {
131         dbus_bool_t do_auto = TRUE;
132         DBusMessage *msg;
133
134         msg = dbus_message_new_method_call(BUS_NAME, PATH, IFACE, "Dial");
135
136         EINA_SAFETY_ON_NULL_RETURN_VAL(msg, -1);
137
138         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
139                                         DBUS_TYPE_BOOLEAN, &do_auto,
140                                         DBUS_TYPE_INVALID))
141                 goto err_msg;
142
143         if (d->online) {
144                 e_dbus_message_send(bus_conn, msg, _dial_return_cb, -1, NULL);
145                 dbus_message_unref(msg);
146         } else
147                 d->pending = eina_list_append(d->pending, msg);
148
149         return 0;
150 err_msg:
151         dbus_message_unref(msg);
152         return -1;
153 }
154
155 static int _create(void *data __UNUSED__)
156 {
157         return 0;
158 }
159
160 static int _reset(bundle *b, void *data)
161 {
162         const char *number, *mime_type, *tmp;
163         Daemon *d = data;
164
165         EINA_SAFETY_ON_NULL_RETURN_VAL(b, -1);
166         number = bundle_get_val(b, "number");
167         if (!number) {
168                 mime_type = bundle_get_val(b, AUL_K_MIME_TYPE);
169                 if (mime_type){
170                         if (strncmp(mime_type, "phonenum.uri", 12) == 0 ||
171                                 strncmp(mime_type, "tel.uri", 7) == 0) {
172                                 tmp = bundle_get_val(b, AUL_K_MIME_CONTENT);
173                                 EINA_SAFETY_ON_NULL_RETURN_VAL(tmp, -1);
174                                 if (strncmp(tmp, "tel:", 4) == 0)
175                                         number = (char *)tmp + 4;
176                                 else {
177                                         fprintf(stderr, "Phone not present");
178                                         return -1;
179                                 }
180                         } else {
181                                 fprintf(stderr, "Unexpected mime type.");
182                                 return -1;
183                         }
184                 } else {
185                         tmp = (const char *)appsvc_get_uri(b);
186                         EINA_SAFETY_ON_NULL_RETURN_VAL(tmp, -1);
187                         number = (char *)tmp + 4;
188                 }
189         }
190         EINA_SAFETY_ON_NULL_RETURN_VAL(number, -1);
191         return _dial(number, d);
192 }
193
194 static int _resume(void *data __UNUSED__)
195 {
196         return 0;
197 }
198
199 static int _pause(void *data __UNUSED__)
200 {
201         return 0;
202 }
203
204 static int _terminate(void *data __UNUSED__)
205 {
206         return 0;
207 }
208
209 int main(int argc __UNUSED__, char **argv __UNUSED__)
210 {
211         int r;
212         Daemon dialer_daemon;
213         dialer_daemon.pending = NULL;
214         dialer_daemon.online = EINA_FALSE;
215         struct appcore_ops ops = {
216                 .create = _create,
217                 .resume = _resume,
218                 .reset = _reset,
219                 .pause = _pause,
220                 .terminate = _terminate,
221         };
222         ops.data = &dialer_daemon;
223
224         e_dbus_init();
225         EINA_SAFETY_ON_FALSE_RETURN_VAL(_dbus_init(&dialer_daemon), -1);
226         r = appcore_efl_main(APP_NAME, &argc, &argv, &ops);
227         e_dbus_connection_close(bus_conn);
228
229         e_dbus_shutdown();
230         return r;
231 }