Merge with Tizen 2.3
[platform/core/uifw/stt.git] / server / sttd_dbus.c
1 /*
2 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved 
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14
15 #include <dbus/dbus.h>
16 #include <Ecore.h>
17
18 #include "sttd_main.h"
19 #include "sttd_dbus.h"
20 #include "sttd_client_data.h"
21 #include "sttd_dbus_server.h"
22 #include "stt_defs.h"
23
24 static DBusConnection* g_conn;
25 static int g_waiting_time = 3000;
26
27 int sttdc_send_hello(int uid)
28 {
29         int pid = sttd_client_get_pid(uid);
30
31         if (0 > pid) {
32                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid");
33                 return -1;
34         }
35
36         char service_name[64];
37         memset(service_name, 0, 64);
38         snprintf(service_name, 64, "%s%d", STT_CLIENT_SERVICE_NAME, pid);
39
40         char target_if_name[128];
41         snprintf(target_if_name, sizeof(target_if_name), "%s%d", STT_CLIENT_SERVICE_INTERFACE, pid);
42
43         DBusMessage* msg;
44
45         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Send hello message : uid(%d)", uid);
46
47         msg = dbus_message_new_method_call(
48                 service_name, 
49                 STT_CLIENT_SERVICE_OBJECT_PATH, 
50                 target_if_name, 
51                 STTD_METHOD_HELLO);
52
53         if (NULL == msg) { 
54                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message"); 
55                 return -1;
56         }
57
58         dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID);
59
60         DBusError err;
61         dbus_error_init(&err);
62
63         DBusMessage* result_msg;
64         int result = -1;
65
66         result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err);
67         dbus_message_unref(msg);
68         if (dbus_error_is_set(&err)) {
69                 SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Send error (%s)", err.message);
70                 dbus_error_free(&err);
71         }
72
73         if (NULL != result_msg) {
74                 dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
75
76                 if (dbus_error_is_set(&err)) { 
77                         SLOG(LOG_ERROR, TAG_STTD, "[Dbus] Get arguments error (%s)\n", err.message);
78                         dbus_error_free(&err); 
79                         result = -1;
80                 }
81
82                 dbus_message_unref(result_msg);
83         } else {
84                 SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Result message is NULL. Client is not available");
85                 result = 0;
86         }
87
88         return result;
89 }
90
91 int sttdc_send_get_state(int uid, int* state)
92 {
93         int pid = sttd_client_get_pid(uid);
94
95         if (0 > pid) {
96                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid");
97                 return -1;
98         }
99
100         char service_name[64];
101         memset(service_name, 0, 64);
102         snprintf(service_name, 64, "%s%d", STT_CLIENT_SERVICE_NAME, pid);
103
104         char target_if_name[128];
105         snprintf(target_if_name, sizeof(target_if_name), "%s%d", STT_CLIENT_SERVICE_INTERFACE, pid);
106
107         DBusMessage* msg;
108
109         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Send get state message : uid(%d)", uid);
110
111         msg = dbus_message_new_method_call(
112                 service_name, 
113                 STT_CLIENT_SERVICE_OBJECT_PATH, 
114                 target_if_name, 
115                 STTD_METHOD_GET_STATE);
116
117         if (NULL == msg) { 
118                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message"); 
119                 return -1;
120         }
121
122         dbus_message_append_args(msg, DBUS_TYPE_INT32, &uid, DBUS_TYPE_INVALID);
123
124         DBusError err;
125         dbus_error_init(&err);
126
127         DBusMessage* result_msg;
128         int tmp = -1;
129         int result = 0;
130
131         result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err);
132         dbus_message_unref(msg);
133         if (dbus_error_is_set(&err)) {
134                 SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Send error (%s)", err.message);
135                 dbus_error_free(&err);
136         }
137
138         if (NULL != result_msg) {
139                 dbus_message_get_args(result_msg, &err, DBUS_TYPE_INT32, &tmp, DBUS_TYPE_INVALID);
140
141                 if (dbus_error_is_set(&err)) { 
142                         SLOG(LOG_ERROR, TAG_STTD, "[Dbus] Get arguments error (%s)\n", err.message);
143                         dbus_error_free(&err); 
144                         result = -1;
145                 } else {
146                         *state = tmp;
147                         result = 0;
148                 }
149
150                 dbus_message_unref(result_msg);
151         } else {
152                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus] Result message is NULL. Client is not available");
153                 result = -1;
154         }
155         
156         return result;
157 }
158
159 int sttdc_send_result(int uid, int event, const char** data, int data_count, const char* result_msg)
160 {
161         int pid = sttd_client_get_pid(uid);
162
163         if (0 > pid) {
164                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid" );
165                 return -1;
166         }
167
168         char service_name[64];
169         memset(service_name, 0, 64);
170         snprintf(service_name, 64, "%s%d", STT_CLIENT_SERVICE_NAME, pid);
171
172         char target_if_name[128];
173         snprintf(target_if_name, sizeof(target_if_name), "%s%d", STT_CLIENT_SERVICE_INTERFACE, pid);
174
175         DBusMessage* msg;
176
177         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] send result signal : uid(%d), event(%d), result count(%d)", uid, event, data_count);
178
179         msg = dbus_message_new_method_call(
180                 service_name, 
181                 STT_CLIENT_SERVICE_OBJECT_PATH, 
182                 target_if_name, 
183                 STTD_METHOD_RESULT);
184
185         if (NULL == msg) { 
186                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message"); 
187                 return -1;
188         }
189
190         DBusMessageIter args;
191         dbus_message_iter_init_append(msg, &args);
192
193         /* Append uid & type */
194         dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &uid);
195
196         char* msg_temp;
197         dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &event);
198
199         /* Append result msg */
200         if (NULL == result_msg) {
201                 msg_temp = strdup("None");
202                 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &msg_temp);
203                 SLOG(LOG_WARN, TAG_STTD, "[Dbus] result message is NULL"); 
204                 free(msg_temp);
205         } else {
206                 SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] result message(%s)", result_msg ); 
207                 dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &(result_msg));
208         }
209         
210         /* Append result size */
211         if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(data_count))) {
212                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus] response message : Fail to append result size"); 
213                 return -1;
214         }
215
216         int i;
217         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] result size (%d)", data_count); 
218         for (i = 0;i < data_count;i++) {
219                 if (NULL != data[i]) {
220                         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] result (%d, %s)", i, data[i] ); 
221
222                         if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &data[i])) {
223                                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus] response message : Fail to append result data");
224                                 return -1;
225                         }
226                 } else {
227                         int reason = (int)STTD_ERROR_OPERATION_FAILED;
228
229                         if (0 != sttdc_send_error_signal(uid, reason, "Fail to get recognition result from engine")) {
230                                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to send error info. Remove client data"); 
231
232                                 /* clean client data */
233                                 sttd_client_delete(uid);
234                         }
235
236                         SECURE_SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Result from engine is NULL(%d)", i); 
237                         return -1;
238                 }
239         }
240         
241         if (!dbus_connection_send(g_conn, msg, NULL)) {
242                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to send message : Out Of Memory !"); 
243                 return -1;
244         }
245
246         dbus_connection_flush(g_conn);
247         dbus_message_unref(msg);
248
249         return 0;
250 }
251
252 int sttdc_send_error_signal(int uid, int reason, const char *err_msg)
253 {
254         if (NULL == err_msg) {
255                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Input parameter is NULL"); 
256                 return STTD_ERROR_INVALID_PARAMETER;
257         }
258
259         int pid = sttd_client_get_pid(uid);
260
261         if (0 > pid) {
262                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid" );
263                 return -1;
264         }
265
266         char service_name[64];
267         memset(service_name, 0, 64);
268         snprintf(service_name, 64, "%s%d", STT_CLIENT_SERVICE_NAME, pid);
269
270         char target_if_name[128];
271         snprintf(target_if_name, sizeof(target_if_name), "%s%d", STT_CLIENT_SERVICE_INTERFACE, pid);
272
273         DBusMessage* msg;
274         SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] send error signal : reason(%d), Error Msg(%s)", reason, err_msg);
275
276         msg = dbus_message_new_method_call(
277                 service_name, 
278                 STT_CLIENT_SERVICE_OBJECT_PATH, 
279                 target_if_name, 
280                 STTD_METHOD_ERROR);
281
282         if (NULL == msg) { 
283                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message"); 
284                 return -1;
285         }
286
287         dbus_message_append_args(msg, 
288                 DBUS_TYPE_INT32, &uid, 
289                 DBUS_TYPE_INT32, &reason, 
290                 DBUS_TYPE_STRING, &err_msg,
291                 DBUS_TYPE_INVALID);
292         
293         DBusError err;
294         dbus_error_init(&err);
295
296         DBusMessage* result_msg;
297
298         result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err);
299         dbus_message_unref(msg);
300         if (dbus_error_is_set(&err)) {
301                 SLOG(LOG_ERROR, TAG_STTD, "[ERROR] Send error (%s)", err.message);
302                 dbus_error_free(&err);
303         }
304
305         if (NULL != result_msg) {
306                 dbus_message_unref(result_msg);
307         } else {
308                 SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Result message is NULL.");
309         }
310
311         return 0;
312 }
313
314 int sttdc_send_set_state(int uid, int state)
315 {
316         int pid = sttd_client_get_pid(uid);
317
318         if (0 > pid) {
319                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] pid is NOT valid");
320                 return -1;
321         }
322
323         char service_name[64];
324         memset(service_name, 0, 64);
325         snprintf(service_name, 64, "%s%d", STT_CLIENT_SERVICE_NAME, pid);
326
327         char target_if_name[128];
328         snprintf(target_if_name, sizeof(target_if_name), "%s%d", STT_CLIENT_SERVICE_INTERFACE, pid);
329
330         DBusMessage* msg;
331
332         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Dbus] Send change state message : uid(%d), state(%d)", uid, state);
333
334         msg = dbus_message_new_method_call(
335                 service_name, 
336                 STT_CLIENT_SERVICE_OBJECT_PATH, 
337                 target_if_name, 
338                 STTD_METHOD_SET_STATE);
339
340         if (NULL == msg) { 
341                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to create message"); 
342                 return -1;
343         }
344
345         dbus_message_append_args(msg, 
346                 DBUS_TYPE_INT32, &uid, 
347                 DBUS_TYPE_INT32, &state, 
348                 DBUS_TYPE_INVALID);
349
350         if (!dbus_connection_send(g_conn, msg, NULL)) {
351                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to send message : Out Of Memory !"); 
352                 return -1;
353         }
354
355         dbus_connection_flush(g_conn);
356         dbus_message_unref(msg);
357
358         return 0;
359 }
360
361 static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
362 {
363         DBusConnection* conn = (DBusConnection*)data;
364         DBusMessage* msg = NULL;
365
366         if (NULL == conn)
367                 return ECORE_CALLBACK_RENEW;
368
369         dbus_connection_read_write_dispatch(conn, 50);
370         
371         msg = dbus_connection_pop_message(conn);
372
373         if (true != dbus_connection_get_is_connected(conn)) {
374                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Conn is disconnected");
375                 return ECORE_CALLBACK_RENEW;
376         }
377
378         /* loop again if we haven't read a message */
379         if (NULL == msg) { 
380                 return ECORE_CALLBACK_RENEW;
381         }
382
383         /* client event */
384         if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_HELLO))
385                 sttd_dbus_server_hello(conn, msg);
386
387         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_INITIALIZE))
388                 sttd_dbus_server_initialize(conn, msg);
389         
390         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_FINALIZE))
391                 sttd_dbus_server_finalize(conn, msg);
392
393         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_SET_CURRENT_ENGINE))
394                 sttd_dbus_server_set_current_engine(conn, msg);
395
396         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_CHECK_APP_AGREED))
397                 sttd_dbus_server_check_app_agreed(conn, msg);
398
399         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_GET_SUPPORT_LANGS))
400                 sttd_dbus_server_get_support_lang(conn, msg);
401
402         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_GET_CURRENT_LANG))
403                 sttd_dbus_server_get_default_lang(conn, msg);
404
405         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_IS_TYPE_SUPPORTED))
406                 sttd_dbus_server_is_recognition_type_supported(conn, msg);
407
408
409         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_SET_START_SOUND))
410                 sttd_dbus_server_set_start_sound(conn, msg);
411
412         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_UNSET_START_SOUND))
413                 sttd_dbus_server_unset_start_sound(conn, msg);
414
415         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_SET_STOP_SOUND))
416                 sttd_dbus_server_set_stop_sound(conn, msg);
417
418         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_UNSET_STOP_SOUND))
419                 sttd_dbus_server_unset_stop_sound(conn, msg);
420
421
422         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_START)) 
423                 sttd_dbus_server_start(conn, msg);
424         
425         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_STOP)) 
426                 sttd_dbus_server_stop(conn, msg);
427
428         else if (dbus_message_is_method_call(msg, STT_SERVER_SERVICE_INTERFACE, STT_METHOD_CANCEL)) 
429                 sttd_dbus_server_cancel(conn, msg);
430
431
432         /* free the message */
433         dbus_message_unref(msg);
434
435         return ECORE_CALLBACK_RENEW;
436 }
437
438 int sttd_dbus_open_connection()
439 {
440         DBusError err;
441         dbus_error_init(&err);
442
443         int ret;
444
445         /* connect to the bus and check for errors */
446         g_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
447
448         if (dbus_error_is_set(&err)) { 
449                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail dbus_bus_get : %s", err.message);
450                 dbus_error_free(&err); 
451         }
452
453         if (NULL == g_conn) { 
454                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to get dbus connection" );
455                 return -1;
456         }
457
458         /* request our name on the bus and check for errors */
459         ret = dbus_bus_request_name(g_conn, STT_SERVER_SERVICE_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
460
461         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
462                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to be primary owner");
463                 return -1;
464         }
465
466         if (dbus_error_is_set(&err)) { 
467                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] dbus_bus_request_name() : %s", err.message);
468                 dbus_error_free(&err); 
469                 return -1;
470         }
471
472         /* add a rule for getting signal */
473         char rule[128];
474         snprintf(rule, 128, "type='signal',interface='%s'", STT_SERVER_SERVICE_INTERFACE);
475
476         /* add a rule for which messages we want to see */
477         dbus_bus_add_match(g_conn, rule, &err); /* see signals from the given interface */
478         dbus_connection_flush(g_conn);
479
480         if (dbus_error_is_set(&err)) { 
481                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] dbus_bus_add_match() : %s", err.message);
482                 return -1; 
483         }
484
485         int fd = 0;
486         dbus_connection_get_unix_fd(g_conn, &fd);
487
488         if (!ecore_init()) {
489                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] ecore_init()");
490                 return -1;
491         }
492
493         Ecore_Fd_Handler* fd_handler;
494         fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ , (Ecore_Fd_Cb)listener_event_callback, g_conn, NULL, NULL);
495
496         if (NULL == fd_handler) {
497                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] Fail to get fd handler");
498                 return -1;
499         }
500
501         return 0;
502 }
503
504 int sttd_dbus_close_connection()
505 {
506         DBusError err;
507         dbus_error_init(&err);
508
509         dbus_bus_release_name (g_conn, STT_SERVER_SERVICE_NAME, &err);
510
511         if (dbus_error_is_set(&err)) {
512                 SLOG(LOG_ERROR, TAG_STTD, "[Dbus ERROR] dbus_bus_release_name() : %s", err.message); 
513                 dbus_error_free(&err); 
514                 return -1;
515         }
516
517         return 0;
518 }