Fix build error on gcc-13 Build
[platform/core/uifw/voice-control.git] / client / vc_setting_tidl.c
1 /*
2 * Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "vc_command.h"
18 #include "vc_setting_tidl.h"
19 #include "vc_setting_proxy.h"
20 #include "vc_main.h"
21
22 #include <vconf.h>
23
24 typedef struct {
25         int pid;
26         bool connected;
27         bool connection_requesting;
28         bool register_notify_callback_invoked;
29
30         rpc_port_proxy_vc_setting_proxy_vc_setting_h rpc_h;
31         rpc_port_proxy_vc_setting_proxy_vc_setting_notify_cb_h notify_cb_h;
32
33         char* engine_appid;
34 } vc_setting_tidl_info_s;
35
36 static GList* g_tidl_infos = NULL;
37
38
39 static vc_setting_tidl_info_s* __get_tidl_info_s(int pid)
40 {
41         // TODO: Hmm.... is this necessary...??
42         GList* iter = NULL;
43         vc_setting_tidl_info_s* info = NULL;
44
45         if (g_list_length(g_tidl_infos) > 0) {
46                 /* Get a first item */
47                 iter = g_list_first(g_tidl_infos);
48
49                 while (NULL != iter) {
50                         info = iter->data;
51
52                         if (info->pid == pid) {
53                                 return info;
54                         }
55
56                         /* Next item */
57                         iter = g_list_next(iter);
58                 }
59         }
60
61         return NULL;
62 }
63
64 static char* __get_engine_appid(void)
65 {
66         char* engine_name = vconf_get_str(VC_ENGINE_DB_DEFAULT);
67         if (NULL == engine_name) {
68                 SLOG(LOG_WARN, TAG_VCC, "[WARNING] Fail to get engine name. Please use default engine name.");
69                 engine_name = strdup("org.tizen.vc-engine-default");
70         }
71
72         char* appid = strdup(engine_name);
73
74         SLOG(LOG_INFO, TAG_VCC, "[INFO] VC engine appid(%s)", appid);
75
76         free(engine_name);
77
78         return appid;
79 }
80
81 static void __on_connected(rpc_port_proxy_vc_setting_proxy_vc_setting_h h, void* user_data)
82 {
83         unsigned int pid = (intptr_t)user_data;
84
85         vc_setting_tidl_info_s* info = __get_tidl_info_s(pid);
86         RETM_IF(NULL == info, TAG_VCC, "[ERROR] Fail to get tidl info");
87
88         info->connected = true;
89         info->connection_requesting = false;
90         info->register_notify_callback_invoked = false;
91
92         SLOG(LOG_INFO, TAG_VCC, "[INFO] Connected to server");
93 }
94
95 static void __on_disconnected(rpc_port_proxy_vc_setting_proxy_vc_setting_h h, void* user_data)
96 {
97         unsigned int pid = (intptr_t)user_data;
98
99         vc_setting_tidl_info_s* info = __get_tidl_info_s(pid);
100         RETM_IF(NULL == info, TAG_VCC, "[ERROR] Fail to get tidl info");
101
102         info->connected = false;
103         info->connection_requesting = false;
104         info->register_notify_callback_invoked = false;
105
106         /* retry to connect */
107         SLOG(LOG_INFO, TAG_VCC, "[INFO] Disconnected to server");
108 }
109
110 static void __on_rejected(rpc_port_proxy_vc_setting_proxy_vc_setting_h h, void* user_data)
111 {
112         unsigned int pid = (intptr_t)user_data;
113
114         vc_setting_tidl_info_s* info = __get_tidl_info_s(pid);
115         RETM_IF(NULL == info, TAG_VCC, "[ERROR] Fail to get tidl info");
116
117         info->connection_requesting = false;
118         info->register_notify_callback_invoked = false;
119
120         SLOG(LOG_INFO, TAG_VCC, "[INFO] Rejected from server(%d)", pid);
121 }
122
123
124 static rpc_port_proxy_vc_setting_proxy_vc_setting_h __create_rpc_port(int pid, const char* engine_app_id)
125 {
126         SLOG(LOG_INFO, TAG_VCC, "[INFO] vc setting __create_rpc_port");
127
128         rpc_port_proxy_vc_setting_proxy_vc_setting_callback_s rpc_callback = {
129                 .connected = __on_connected,
130                 .disconnected = __on_disconnected,
131                 .rejected = __on_rejected
132         };
133
134         rpc_port_proxy_vc_setting_proxy_vc_setting_h handle = NULL;
135         intptr_t ptr_pid = pid;
136         if (0 != rpc_port_proxy_vc_setting_proxy_vc_setting_create(engine_app_id, &rpc_callback, (void*)ptr_pid, &handle)) {
137                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail rpc_port_proxy_vc_setting_proxy_vc_setting_create");
138                 return NULL;
139         }
140         SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] Succeed rpc_port_proxy_vc_setting_proxy_vc_setting_create");
141
142         return handle;
143 }
144
145 static void __request_tidl_connect(vc_setting_tidl_info_s* info)
146 {
147         if (info->connection_requesting) {
148                 SLOG(LOG_INFO, TAG_VCC, "[TIDL] Already connection is requested. Skip to call rpc_port_proxy_vc_setting_proxy_vc_setting_connect().");
149                 return;
150         }
151
152         int ret = rpc_port_proxy_vc_setting_proxy_vc_setting_connect_sync(info->rpc_h);
153         if (0 != ret) {
154                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request connection to stub. ret(%d)", ret);
155                 return;
156         }
157
158         SLOG(LOG_INFO, TAG_VCC, "[INFO] Request connection to stub. ret(%d)", ret);
159         info->connection_requesting = true;
160 }
161
162 static void __notify_cb(void* user_data, int pid, bundle* msg)
163 {
164         // corresponding to listener_event_callback
165         char* method = NULL;
166
167         SLOG(LOG_DEBUG, TAG_VCC, "__notify_cb is invoked pid(%d)", pid);
168
169         bundle_get_str(msg, VC_BUNDLE_METHOD, &method);
170
171         if (0 == strncmp(VCD_METHOD_HELLO, method, strlen(VCD_METHOD_HELLO))) {
172                 SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] HELLO received");
173         } /* VCD_METHOD_HELLO */
174         else {
175                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid msg");
176         }
177 }
178
179 static int __create_notify_callback_handle(vc_setting_tidl_info_s* info)
180 {
181         if (NULL != info->notify_cb_h) {
182                 rpc_port_proxy_vc_setting_proxy_vc_setting_notify_cb_dispose(info->rpc_h, info->notify_cb_h);
183                 info->notify_cb_h = NULL;
184         }
185
186         if (RPC_PORT_ERROR_NONE != rpc_port_proxy_vc_setting_proxy_vc_setting_notify_cb_create(&info->notify_cb_h)) {
187                 return VC_ERROR_OUT_OF_MEMORY;
188         }
189
190         rpc_port_proxy_vc_setting_proxy_vc_setting_notify_cb_set_callback(info->notify_cb_h, __notify_cb, NULL);
191         rpc_port_proxy_vc_setting_proxy_vc_setting_notify_cb_set_once(info->notify_cb_h, false);
192
193         return VC_ERROR_NONE;
194 }
195
196 static int __invoke_register_notify_callback(int pid, vc_setting_tidl_info_s* info)
197 {
198         if (info->register_notify_callback_invoked) {
199                 SLOG(LOG_ERROR, TAG_VCC, "[INFO] Already register callback is invoked");
200                 return VC_ERROR_NONE;
201         }
202
203         int ret = __create_notify_callback_handle(info);
204         if (VC_ERROR_NONE != ret) {
205                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to create callback handle. ret(%d)", ret);
206                 return VC_ERROR_OPERATION_FAILED;
207         }
208
209         rpc_port_proxy_vc_setting_proxy_vc_setting_invoke_register_notify_cb(info->rpc_h, pid, info->notify_cb_h);
210         info->register_notify_callback_invoked = true;
211         return VC_ERROR_NONE;
212 }
213
214 int vc_setting_tidl_open_connection()
215 {
216         SLOG(LOG_INFO, TAG_VCC, "[TIDL] vc_setting_tidl_open_connection");
217
218         vc_setting_tidl_info_s* info = (vc_setting_tidl_info_s*)calloc(1, sizeof(vc_setting_tidl_info_s));
219         if (NULL == info) {
220                 SLOG(LOG_ERROR, TAG_VCC, "[TIDL ERROR] Fail to create tidl_info_s");
221                 return VC_ERROR_OUT_OF_MEMORY;
222         }
223
224         int pid = getpid();
225         char* engine_appid = __get_engine_appid();
226
227         info->rpc_h = __create_rpc_port(pid, engine_appid);
228         if (NULL == info->rpc_h) {
229                 SLOG(LOG_ERROR, TAG_VCC, "[TIDL ERROR] Fail to create proxy");
230                 free(info);
231                 free(engine_appid);
232                 return VC_ERROR_OPERATION_FAILED;
233         }
234
235         info->pid = pid;
236         g_tidl_infos = g_list_append(g_tidl_infos, info);
237
238         SLOG(LOG_ERROR, TAG_VCC, "[TIDL] pid(%d) rpc_h(%p), engine_appid(%s)", pid, info->rpc_h, info->engine_appid);
239         free(engine_appid);
240
241         return VC_ERROR_NONE;
242
243 }
244
245 int vc_setting_tidl_close_connection()
246 {
247         SLOG(LOG_INFO, TAG_VCC, "[TIDL] vc_setting_tidl_close_connection");
248
249         int pid = getpid();
250         vc_setting_tidl_info_s* info = __get_tidl_info_s(pid);
251         RETVM_IF(NULL == info, VC_ERROR_INVALID_PARAMETER, TAG_VCC, "[ERROR] Fail to get tidl info");
252
253         if (0 != rpc_port_proxy_vc_setting_proxy_vc_setting_destroy(info->rpc_h)) {
254                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to disconnect");
255                 return VC_ERROR_OPERATION_FAILED;
256         }
257
258         info->rpc_h = NULL;
259         info->notify_cb_h = NULL;
260
261         g_tidl_infos = g_list_remove(g_tidl_infos, info);
262         free(info);
263
264         return VC_ERROR_NONE;
265 }
266
267 int vc_setting_tidl_request_hello()
268 {
269         SLOG(LOG_INFO, TAG_VCC, "[TIDL] vc_tidl_request_hello");
270
271         int pid = getpid();
272         vc_setting_tidl_info_s* info = __get_tidl_info_s(pid);
273         RETVM_IF(NULL == info, VC_ERROR_INVALID_PARAMETER, TAG_VCC, "[ERROR] Fail to get tidl info");
274
275         __request_tidl_connect(info);
276
277         if (!info->connected) {
278                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Not Connected.");
279                 return VC_ERROR_OPERATION_FAILED;
280         }
281
282         SLOG(LOG_DEBUG, TAG_VCC, ">>>>> VCC Hello");
283         if (VC_ERROR_NONE != __invoke_register_notify_callback(pid, info)) {
284                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to invoke register callback");
285                 return VC_ERROR_OPERATION_FAILED;
286         }
287
288         SLOG(LOG_DEBUG, TAG_VCC, "<<<<");
289         return VC_ERROR_NONE;
290
291 }
292
293 static int __convert_unhandled_error(int ret)
294 {
295         if (RPC_PORT_ERROR_IO_ERROR == ret || RPC_PORT_ERROR_OUT_OF_MEMORY == ret) {
296                 return VC_ERROR_OPERATION_FAILED;
297         }
298
299         return ret;
300 }
301
302 int vc_setting_tidl_request_set_language(int pid, const char* language)
303 {
304         SLOG(LOG_INFO, TAG_VCC, "[TIDL] vc_setting_tidl_request_set_language");
305
306         vc_setting_tidl_info_s* info = __get_tidl_info_s(pid);
307         RETVM_IF(NULL == info, VC_ERROR_INVALID_PARAMETER, TAG_VCC, "[ERROR] Fail to get tidl info");
308         RETVM_IF(false == info->connected, VC_ERROR_OPERATION_FAILED, TAG_VCC, "[ERROR] Not Connected");
309
310         int ret = rpc_port_proxy_vc_setting_proxy_vc_setting_invoke_set_language(info->rpc_h, pid, language);
311         int exception = get_last_result();
312         if (RPC_PORT_ERROR_NONE != exception) {
313                 ret = __convert_unhandled_error(exception);
314         }
315
316         if (VC_ERROR_NONE != ret) {
317                 SLOG(LOG_ERROR, TAG_VCC, ">>>> Request vc setting set language : Fail to invoke message (%d)", ret);
318                 return ret;
319         }
320
321         SLOG(LOG_DEBUG, TAG_VCC, "@@ vc setting set language : pid(%d), language(%s)", pid, language);
322
323         return VC_ERROR_NONE;
324 }
325