Add to set playing mode to decide where the synthesized pcm data will be played
[platform/core/uifw/tts.git] / client / tts_tidl.c
1 /* *  Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
2 *  Licensed under the Apache License, Version 2.0 (the "License");
3 *  you may not use this file except in compliance with the License.
4 *  You may obtain a copy of the License at
5 *  http://www.apache.org/licenses/LICENSE-2.0
6 *  Unless required by applicable law or agreed to in writing, software
7 *  distributed under the License is distributed on an "AS IS" BASIS,
8 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 *  See the License for the specific language governing permissions and
10 *  limitations under the License.
11 */
12
13
14 #include "tts_main.h"
15 #include "tts_tidl.h"
16 #include "tts_proxy.h"
17 #include "tts_client.h"
18 #include "tts_core.h"
19 #include "tts_dlog.h"
20
21 #define MAXSLEEP 128
22 #define MAX_CONNECT_CHECK 100
23
24 typedef struct {
25         unsigned int uid;
26         bool connected;
27         bool connection_requesting;
28         bool register_callback_invoked;
29         rpc_port_proxy_tts_h rpc_h;
30         rpc_port_proxy_tts_notify_cb_h notify_cb_h;
31         char* engine_app_id;
32 } tts_tidl_info_s;
33
34 static GList* g_tidl_infos = NULL;
35 static GSList *g_destruction_scheduled_handles = NULL;
36
37 static Ecore_Idler *g_destroy_handles_idler = NULL;
38
39
40 static tts_tidl_info_s* __get_tidl_info_s(unsigned int uid)
41 {
42         GList* iter = NULL;
43         tts_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->uid == uid) {
53                                 return info;
54                         }
55
56                         /* Next item */
57                         iter = g_list_next(iter);
58                 }
59         }
60
61         return NULL;
62 }
63
64 static void __notify_cb(void *user_data, int pid, int uid, bundle *msg)
65 {
66         char *method = NULL;
67         char *val = NULL;
68         tts_client_s* client = tts_client_get_by_uid(uid);
69         RETM_IF(NULL == client, "[ERROR] Fail to get client");
70
71         unsigned int u_uid = (unsigned int)uid;
72         if (NULL != g_slist_find(g_destruction_scheduled_handles, user_data)) {
73                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] This message is for destroyed handle.");
74                 return;
75         }
76
77         SLOG(LOG_DEBUG, TAG_TTSC, "__notify_cb is invoked pid(%d) uid(%u)", pid, u_uid);
78
79         bundle_get_str(msg, TTS_BUNDLE_METHOD, &method);
80
81         if (0 == strncmp(TTSD_METHOD_HELLO, method, strlen(TTSD_METHOD_HELLO))) {
82                 char* credential_needed = NULL;
83                 char* service_state = NULL;
84                 char* ret = NULL;
85
86                 bundle_get_str(msg, TTS_BUNDLE_CREDENTIAL_NEEDED, &credential_needed);
87                 bundle_get_str(msg, TTS_BUNDLE_CURRENT_STATE, &service_state);
88                 bundle_get_str(msg, TTS_BUNDLE_REASON, &ret);
89
90                 if (NULL != credential_needed && NULL != ret) {
91                         tts_client_set_start_listening(u_uid, true);
92                         tts_core_receive_hello(u_uid, atoi(ret), (tts_service_state_e)atoi(service_state), atoi(credential_needed));
93
94                         tts_tidl_info_s* info = __get_tidl_info_s(u_uid);
95                         RETM_IF(NULL == info, "[ERROR] Fail to get tidl info");
96                         info->register_callback_invoked = false;
97                 } else {
98                         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get message(TTSD_METHOD_HELLO). pid(%d) uid(%u)", pid, u_uid);
99                 }
100         } else if (0 == strncmp(TTSD_METHOD_UTTERANCE_STARTED, method, strlen(TTSD_METHOD_UTTERANCE_STARTED))) {
101                 bundle_get_str(msg, TTS_BUNDLE_MESSAGE, &val);
102                 if (val) {
103                         tts_core_notify_utt_started(client, atoi(val));
104                 }
105         } else if (0 == strncmp(TTSD_METHOD_UTTERANCE_COMPLETED, method, strlen(TTSD_METHOD_UTTERANCE_COMPLETED))) {
106                 bundle_get_str(msg, TTS_BUNDLE_MESSAGE, &val);
107                 if (val) {
108                         tts_core_notify_utt_completeted(client, atoi(val));
109                 }
110         } else if (0 == strncmp(TTSD_METHOD_SET_STATE, method, strlen(TTSD_METHOD_SET_STATE))) {
111                 bundle_get_str(msg, TTS_BUNDLE_MESSAGE, &val);
112                 if (val) {
113                         tts_core_notify_state_changed(client, (tts_state_e)atoi(val));
114                 }
115         } else if (0 == strncmp(TTSD_METHOD_SET_SERVICE_STATE, method, strlen(TTSD_METHOD_SET_SERVICE_STATE))) {
116                 char* before_state = NULL;
117                 char* current_state = NULL;
118                 bundle_get_str(msg, TTS_BUNDLE_BEFORE_STATE, &before_state);
119                 bundle_get_str(msg, TTS_BUNDLE_CURRENT_STATE, &current_state);
120
121                 if (before_state && current_state) {
122                         tts_core_notify_service_state_changed(client, (tts_service_state_e)atoi(before_state), (tts_service_state_e)atoi(current_state));
123                 }
124         } else if (0 == strncmp(TTSD_METHOD_ERROR, method, strlen(TTSD_METHOD_ERROR))) {
125                 char *uttid = NULL;
126                 char *reason = NULL;
127                 char *err_msg = NULL;
128
129                 bundle_get_str(msg, TTS_BUNDLE_REASON, &reason);
130                 bundle_get_str(msg, TTS_BUNDLE_UTTID, &uttid);
131                 bundle_get_str(msg, TTS_BUNDLE_ERR_MSG, &err_msg);
132                 if (reason && uttid) {
133                         tts_core_notify_error_async(client, atoi(reason), atoi(uttid), err_msg);
134                 }
135         } else {
136                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid msg");
137         }
138 }
139
140 static void __on_connected(rpc_port_proxy_tts_h h, void *user_data)
141 {
142         unsigned int uid = (uintptr_t)user_data;
143
144         tts_client_s* client = tts_client_get_by_uid(uid);
145         RETM_IF(NULL == client, "[ERROR] Fail to get client");
146
147         tts_tidl_info_s* info = __get_tidl_info_s(uid);
148         RETM_IF(NULL == info, "[ERROR] Fail to get tidl info");
149
150         info->connected = true;
151         info->connection_requesting = false;
152
153         SLOG(LOG_DEBUG, TAG_TTSC, "Connected to server");
154 }
155
156 static void __on_disconnected(rpc_port_proxy_tts_h h, void *user_data)
157 {
158         unsigned int uid = (uintptr_t)user_data;
159
160         tts_client_s* client = tts_client_get_by_uid(uid);
161         RETM_IF(NULL == client, "[ERROR] Fail to get client");
162
163         tts_tidl_info_s* info = __get_tidl_info_s(uid);
164         RETM_IF(NULL == info, "[ERROR] Fail to get tidl info");
165
166         info->connected = false;
167         info->connection_requesting = false;
168         info->register_callback_invoked = false;
169
170         SLOG(LOG_DEBUG, TAG_TTSC, "Disconnected from server");
171         if (tts_client_is_listening_started(uid)) {
172                 SLOG(LOG_DEBUG, TAG_TTSC, "Try to reconnect to server");
173                 tts_core_handle_service_reset();
174         }
175 }
176
177 //LCOV_EXCL_START
178 static void __on_rejected(rpc_port_proxy_tts_h h, void *user_data)
179 {
180         unsigned int uid = (uintptr_t)user_data;
181         tts_client_s *client = tts_client_get_by_uid(uid);
182         RETM_IF(NULL == client, "[ERROR] Fail to get client");
183
184         tts_tidl_info_s* info = __get_tidl_info_s(uid);
185         RETM_IF(NULL == info, "[ERROR] Fail to get tidl info");
186         info->connection_requesting = false;
187         info->register_callback_invoked = false;
188
189         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Rejected from server(%d)", uid);
190 }
191 //LCOV_EXCL_STOP
192
193 static void __get_engine_app_id(int size, char* app_id)
194 {
195         RETM_IF(NULL == app_id, "app_id is NULL");
196
197         char* engine_name = vconf_get_str(TTS_ENGINE_DB_DEFAULT);
198         if (NULL == engine_name) {
199                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine name");
200                 engine_name = strdup(TTS_SERVER_ENGINE_DEFAULT);
201         }
202
203         snprintf(app_id, size, "%s", engine_name);
204         free(engine_name);
205
206         SLOG(LOG_INFO, TAG_TTSC, "engine app id : %s", app_id);
207 }
208
209 int tts_tidl_open_connection(unsigned int uid)
210 {
211         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_open_connection");
212
213         tts_client_s* client = tts_client_get_by_uid(uid);
214         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
215
216         tts_tidl_info_s* info = (tts_tidl_info_s*)calloc(1, sizeof(tts_tidl_info_s));
217         if (NULL == info) {
218                 SLOG(LOG_ERROR, TAG_TTSC, "[TIDL ERROR] Fail to create tidl_info_s");
219                 return TTS_ERROR_OUT_OF_MEMORY;
220         }
221
222         info->uid = uid;
223         g_tidl_infos = g_list_append(g_tidl_infos, info);
224
225         SLOG(LOG_ERROR, TAG_TTSC, "[TIDL] uid(%u)", uid);
226         return TTS_ERROR_NONE;
227 }
228
229 static void destroy_scheduled_handle(gpointer data)
230 {
231         rpc_port_proxy_tts_h rpc_h = (rpc_port_proxy_tts_h)data;
232         int ret = rpc_port_proxy_tts_destroy(rpc_h);
233         if (RPC_PORT_ERROR_NONE != ret) {
234                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy handle. ret(%d/%s)", ret, get_error_message(ret));
235         }
236 }
237
238 static Eina_Bool destroy_scheduled_handles_by_ecore_idler(void *user_data)
239 {
240         SLOG(LOG_INFO, TAG_TTSC, "[INFO] Destroy RPC handles those are scheduled to be destroyed.");
241         g_slist_free_full(g_destruction_scheduled_handles, destroy_scheduled_handle);
242         g_destruction_scheduled_handles = NULL;
243         g_destroy_handles_idler = NULL;
244
245         return EINA_FALSE;
246 }
247
248 static inline void destroy_rpc_port(tts_tidl_info_s* info)
249 {
250         RETM_IF(NULL == info->rpc_h, "[TIDL] Handle is already destroyed");
251
252         g_destruction_scheduled_handles = g_slist_append(g_destruction_scheduled_handles, info->rpc_h);
253         if (NULL == g_destroy_handles_idler) {
254                 g_destroy_handles_idler = ecore_idler_add(destroy_scheduled_handles_by_ecore_idler, NULL);
255         }
256
257         info->rpc_h = NULL;
258         info->notify_cb_h = NULL;
259
260         free(info->engine_app_id);
261         info->engine_app_id = NULL;
262
263         info->register_callback_invoked = false;
264         info->connection_requesting = false;
265         info->connected = false;
266 }
267
268 int tts_tidl_close_connection(unsigned int uid)
269 {
270         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_close_connection");
271
272         tts_client_s* client = tts_client_get_by_uid(uid);
273         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
274
275         tts_tidl_info_s* info = __get_tidl_info_s(uid);
276         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
277
278         destroy_rpc_port(info);
279         if (g_destroy_handles_idler) {
280                 ecore_idler_del(g_destroy_handles_idler);
281                 g_destroy_handles_idler = NULL;
282         }
283
284         g_slist_free_full(g_destruction_scheduled_handles, destroy_scheduled_handle);
285         g_destruction_scheduled_handles = NULL;
286
287         free(info->engine_app_id);
288         info->engine_app_id = NULL;
289
290         g_tidl_infos = g_list_remove(g_tidl_infos, info);
291         free(info);
292
293         return TTS_ERROR_NONE;
294 }
295
296 int tts_tidl_stop_listening(unsigned int uid)
297 {
298         RETVM_IF(false == tts_client_is_valid_uid(uid), TTS_ERROR_INVALID_PARAMETER, "[ERROR] uid is not valid");
299
300         tts_client_set_start_listening(uid, false);
301
302         return TTS_ERROR_NONE;
303 }
304
305 static void __request_tidl_connect(tts_tidl_info_s* info)
306 {
307         if (info->connection_requesting) {
308                 return;
309         }
310
311         int ret = rpc_port_proxy_tts_connect(info->rpc_h);
312         if (RPC_PORT_ERROR_NONE != ret) {
313                 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Fail to request connection to stub. ret(%d)", ret);
314                 return;
315         }
316
317         SLOG(LOG_INFO, TAG_TTSC, "[INFO] Request connection to stub. ret(%d)", ret);
318
319         info->connection_requesting = true;
320 }
321
322 static int __create_notify_callback_handle(tts_tidl_info_s* info)
323 {
324         if (NULL != info->notify_cb_h) {
325                 rpc_port_proxy_tts_notify_cb_dispose(info->rpc_h, info->notify_cb_h);
326                 info->notify_cb_h = NULL;
327         }
328
329         if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_notify_cb_create(&info->notify_cb_h)) {
330                 return TTS_ERROR_OUT_OF_MEMORY;
331         }
332
333         rpc_port_proxy_tts_notify_cb_set_callback(info->notify_cb_h, __notify_cb, (void *)info->rpc_h);
334         rpc_port_proxy_tts_notify_cb_set_once(info->notify_cb_h, false);
335
336         return TTS_ERROR_NONE;
337 }
338
339 static int __invoke_register_callback(int pid, tts_mode_e mode, tts_playing_mode_e playing_mode, int registered_event_mask, tts_tidl_info_s* info)
340 {
341         if (info->register_callback_invoked) {
342                 SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Already register callback is invoked");
343                 return TTS_ERROR_NONE;
344         }
345
346         int ret = __create_notify_callback_handle(info);
347         if (TTS_ERROR_NONE != ret) {
348                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create callback handle. ret(%d)", ret);
349                 return ret;
350         }
351
352         SLOG(LOG_ERROR, TAG_TTSC, ">>>>> Request register cb. uid(%d)", info->uid);
353         rpc_port_proxy_tts_invoke_register_cb(info->rpc_h, pid, info->uid, (int)mode, (int)playing_mode, registered_event_mask, info->notify_cb_h);
354         info->register_callback_invoked = true;
355         return TTS_ERROR_NONE;
356 }
357
358 static inline bool __is_rpc_port_valid(tts_tidl_info_s* info, const char* engine_id)
359 {
360         if (NULL == info->rpc_h || NULL == info->engine_app_id) {
361                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is empty");
362                 return false;
363         }
364
365         if (NULL == engine_id) {
366                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine ID is null");
367                 return false;
368         }
369
370         if (0 != strncmp(info->engine_app_id, engine_id, TTS_ENGINE_APPID_LEN)) {
371                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine id is not current engine");
372                 return false;
373         }
374
375         return true;
376 }
377
378 static inline int __create_rpc_port(tts_tidl_info_s* info, const char* engine_id)
379 {
380         RETVM_IF(NULL != info->rpc_h, TTS_ERROR_NONE, "[TIDL] Handle is already created");
381
382         rpc_port_proxy_tts_callback_s rpc_callback = {
383                 .connected = __on_connected,
384                 .disconnected = __on_disconnected,
385                 .rejected = __on_rejected
386         };
387
388         rpc_port_proxy_tts_h handle = NULL;
389         uintptr_t ptr_uid = info->uid;
390         if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_create(engine_id, &rpc_callback, (void*)ptr_uid, &handle) || NULL == handle) {
391                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create proxy");
392                 return TTS_ERROR_OPERATION_FAILED;
393         }
394
395         info->rpc_h = handle;
396         info->engine_app_id = strdup(engine_id);
397
398         return TTS_ERROR_NONE;
399 }
400
401 static int __reset_rpc_port(tts_tidl_info_s* info, const char* engine_id)
402 {
403         destroy_rpc_port(info);
404
405         if (TTS_ERROR_NONE != __create_rpc_port(info, engine_id)) {
406                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create new rpc port");
407                 return TTS_ERROR_OPERATION_FAILED;
408         }
409
410         SLOG(LOG_INFO, TAG_TTSC, "[TIDL] Reset rpc port. uid(%u). engine ID(%s)", info->uid, engine_id);
411         return TTS_ERROR_NONE;
412 }
413
414 static int __check_and_prepare_rpc_port(tts_tidl_info_s* info)
415 {
416         char engine_id[TTS_ENGINE_APPID_LEN] = {0, };
417         __get_engine_app_id(TTS_ENGINE_APPID_LEN, engine_id);
418
419         if (__is_rpc_port_valid(info, engine_id)) {
420                 SLOG(LOG_INFO, TAG_TTSC, "[TIDL] Current rpc port is valid");
421                 return TTS_ERROR_NONE;
422         }
423
424         return __reset_rpc_port(info, engine_id);
425 }
426
427 int tts_tidl_request_hello(unsigned int uid, tts_mode_e mode, tts_playing_mode_e playing_mode, int registered_event_mask)
428 {
429         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_hello");
430
431         tts_client_s* client = tts_client_get_by_uid(uid);
432         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
433
434         tts_tidl_info_s* info = __get_tidl_info_s(uid);
435         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
436
437         if (TTS_ERROR_NONE != __check_and_prepare_rpc_port(info)) {
438                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare rpc port");
439                 return TTS_ERROR_OPERATION_FAILED;
440         }
441
442         if (!info->connected) {
443                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Not Connected");
444                 __request_tidl_connect(info);
445                 return TTS_ERROR_OPERATION_FAILED;
446         }
447
448         SLOG(LOG_DEBUG, TAG_TTSC, ">>>>> TTS Hello");
449         if (TTS_ERROR_NONE != __invoke_register_callback(client->pid, mode, playing_mode, registered_event_mask, info)) {
450                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to invoke register callback");
451                 return TTS_ERROR_OPERATION_FAILED;
452         }
453
454         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
455         return TTS_ERROR_NONE;
456 }
457
458 static int __request_tidl_connect_sync(tts_tidl_info_s* info)
459 {
460         int ret = rpc_port_proxy_tts_connect_sync(info->rpc_h);
461         SLOG(LOG_INFO, TAG_TTSC, "[INFO] Request connection to stub. ret(%d)", ret);
462         if (RPC_PORT_ERROR_NONE == ret) {
463                 return TTS_ERROR_NONE;
464         }
465
466         return TTS_ERROR_OPERATION_FAILED;
467 }
468
469 static int __convert_and_handle_tidl_error(int ret, tts_tidl_info_s* info)
470 {
471         switch (ret) {
472         case RPC_PORT_ERROR_IO_ERROR:
473                 SLOG(LOG_INFO, TAG_TTSC, "[INFO] IO error occurs. Destroy old rpc port");
474                 destroy_rpc_port(info);
475                 return TTS_ERROR_IO_ERROR;
476
477         case RPC_PORT_ERROR_OUT_OF_MEMORY:
478                 return TTS_ERROR_OUT_OF_MEMORY;
479
480         default:
481                 break;
482         }
483
484         return ret;
485 }
486
487 static int __invoke_register_callback_sync(int pid, tts_tidl_info_s* info)
488 {
489         int ret = TTS_ERROR_NONE;
490
491         ret = __create_notify_callback_handle(info);
492         if (TTS_ERROR_NONE != ret) {
493                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create callback handle. ret(%d/%s)", ret, get_error_message(ret));
494                 return ret;
495         }
496
497         info->register_callback_invoked = true;
498         SLOG(LOG_ERROR, TAG_TTSC, ">>>>> Request register cb sync. uid(%d)", info->uid);
499         ret = rpc_port_proxy_tts_invoke_register_cb_sync(info->rpc_h, pid, info->uid, info->notify_cb_h);
500         int exception = get_last_result();
501         if (RPC_PORT_ERROR_NONE != exception) {
502                 ret = __convert_and_handle_tidl_error(exception, info);
503         }
504         info->register_callback_invoked = false;
505
506         if (TTS_ERROR_NONE != ret) {
507                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to register callback. ret(%d/%s)", ret, get_error_message(ret));
508                 return ret;
509         }
510
511         return TTS_ERROR_NONE;
512 }
513
514 int tts_tidl_request_hello_sync(unsigned int uid)
515 {
516         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_hello");
517
518         tts_client_s* client = tts_client_get_by_uid(uid);
519         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
520
521         tts_tidl_info_s* info = __get_tidl_info_s(uid);
522         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
523
524         if (TTS_ERROR_NONE != __check_and_prepare_rpc_port(info)) {
525                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare rpc port");
526                 return TTS_ERROR_OPERATION_FAILED;
527         }
528
529         if (!info->connected) {
530                 SLOG(LOG_WARN, TAG_TTSC, "[WARNNING] Stub is not Connected. Try to connect..");
531                 int ret = __request_tidl_connect_sync(info);
532                 if (TTS_ERROR_NONE != ret) {
533                         SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to connect. ret(%d)", ret);
534                         return TTS_ERROR_OPERATION_FAILED;
535                 }
536
537                 SLOG(LOG_INFO, TAG_TTSC, "[TIDL] Stub is Connected");
538         }
539
540         SLOG(LOG_DEBUG, TAG_TTSC, ">>>>> TTS Hello");
541         if (TTS_ERROR_NONE != __invoke_register_callback_sync(client->pid, info)) {
542                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to invoke register callback");
543                 return TTS_ERROR_OPERATION_FAILED;
544         }
545
546         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
547         return TTS_ERROR_NONE;
548 }
549
550 int tts_tidl_request_initialize(unsigned int uid, tts_mode_e mode, tts_playing_mode_e playing_mode, int registered_event_mask, tts_service_state_e* service_state, bool* credential_needed)
551 {
552         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_initialize : uid(%u), mode(%d), playing_mode(%d)", uid, (int)mode, (int)playing_mode);
553
554         tts_client_s* client = tts_client_get_by_uid(uid);
555         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
556
557         tts_tidl_info_s* info = __get_tidl_info_s(uid);
558         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
559
560         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
561
562         bool tmp_credential_needed = false;
563         int tmp_service_state = -1;
564         int ret = rpc_port_proxy_tts_invoke_initialize(info->rpc_h, client->pid, uid, (int)mode, (int)playing_mode, registered_event_mask, &tmp_service_state, &tmp_credential_needed);
565         int exception = get_last_result();
566         if (RPC_PORT_ERROR_NONE != exception) {
567                 ret = __convert_and_handle_tidl_error(exception, info);
568         }
569
570         SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts initialize : ret(%d/%s)", ret, get_error_message(ret));
571         if (TTS_ERROR_NONE != ret) {
572                 return ret;
573         }
574
575         *credential_needed = tmp_credential_needed;
576         *service_state = (tts_service_state_e)tmp_service_state;
577
578         SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts initialize : service_state(%d), credential_needed(%d)", tmp_service_state, tmp_credential_needed);
579
580         return TTS_ERROR_NONE;
581 }
582
583 int tts_tidl_request_finalize(unsigned int uid)
584 {
585         SLOG(LOG_INFO, TAG_TTSC, "[TIDL] tts_tidl_request_finalize");
586
587         tts_client_s* client = tts_client_get_by_uid(uid);
588         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
589
590         tts_tidl_info_s* info = __get_tidl_info_s(uid);
591         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
592
593         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
594
595         int ret = rpc_port_proxy_tts_invoke_finalize(info->rpc_h, uid);
596         int exception = get_last_result();
597         if (RPC_PORT_ERROR_NONE != exception) {
598                 ret = __convert_and_handle_tidl_error(exception, info);
599         }
600
601         if (TTS_ERROR_NONE != ret) {
602                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to tts finalize. ret(%d/%s)", ret, get_error_message(ret));
603                 return ret;
604         }
605
606         tts_client_set_start_listening(uid, false);
607         destroy_rpc_port(info);
608         SLOG(LOG_ERROR, TAG_TTSC, ">>>> Success tts finalize. uid(%u)", uid);
609
610         return TTS_ERROR_NONE;
611 }
612
613 int tts_tidl_request_add_text(unsigned int uid, const char* text, const char* lang, int vctype, int speed, int uttid, const char* credential)
614 {
615         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_add_text");
616
617         tts_client_s* client = tts_client_get_by_uid(uid);
618         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
619
620         tts_tidl_info_s* info = __get_tidl_info_s(uid);
621         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
622
623         RETVM_IF(NULL == text || NULL == lang, TTS_ERROR_INVALID_PARAMETER, "Input parameter is NULL");
624
625         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
626
627         const char *not_null_credential = NULL == credential ? "NULL" : credential;
628         int ret = rpc_port_proxy_tts_invoke_add_text(info->rpc_h, uid, text, lang, vctype, speed, uttid, not_null_credential);
629         int exception = get_last_result();
630         if (RPC_PORT_ERROR_NONE != exception) {
631                 ret = __convert_and_handle_tidl_error(exception, info);
632         }
633
634         if (TTS_ERROR_NONE != ret) {
635                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request add text : Fail to invoke message");
636                 return ret;
637         }
638
639         return TTS_ERROR_NONE;
640 }
641
642 int tts_tidl_request_set_private_data(unsigned int uid, const char* key, const char* data)
643 {
644         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_set_private_data");
645
646         tts_client_s* client = tts_client_get_by_uid(uid);
647         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
648
649         tts_tidl_info_s* info = __get_tidl_info_s(uid);
650         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
651
652         RETVM_IF(NULL == key || NULL == data, TTS_ERROR_INVALID_PARAMETER, "Input parameter is NULL");
653
654         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
655
656         int ret = rpc_port_proxy_tts_invoke_set_private(info->rpc_h, uid, key, data);
657         int exception = get_last_result();
658         if (RPC_PORT_ERROR_NONE != exception) {
659                 ret = __convert_and_handle_tidl_error(exception, info);
660         }
661
662         if (TTS_ERROR_NONE != ret) {
663                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request set private data : Fail to invoke message");
664                 return ret;
665         }
666
667         return TTS_ERROR_NONE;
668 }
669
670 int tts_tidl_request_get_private_data(unsigned int uid, const char* key, char** data)
671 {
672         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_get_private_data");
673
674         tts_client_s* client = tts_client_get_by_uid(uid);
675         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
676
677         tts_tidl_info_s* info = __get_tidl_info_s(uid);
678         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
679
680         RETVM_IF(NULL == key || NULL == data, TTS_ERROR_INVALID_PARAMETER, "Input parameter is NULL");
681
682         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
683
684         char *tmp = NULL;
685         int ret = rpc_port_proxy_tts_invoke_get_private(info->rpc_h, uid, key, &tmp);
686         int exception = get_last_result();
687         if (RPC_PORT_ERROR_NONE != exception) {
688                 ret = __convert_and_handle_tidl_error(exception, info);
689         }
690
691         if (TTS_ERROR_NONE != ret) {
692                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request get private data : Fail to invoke message");
693                 free(tmp);
694                 return ret;
695         }
696
697         *data = tmp;
698         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
699
700         return TTS_ERROR_NONE;
701 }
702
703 int tts_tidl_request_play(unsigned int uid, const char* credential)
704 {
705         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_play");
706
707         tts_client_s* client = tts_client_get_by_uid(uid);
708         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
709
710         tts_tidl_info_s* info = __get_tidl_info_s(uid);
711         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
712
713         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
714
715         const char *not_null_credential = NULL == credential ? "NULL" : credential;
716         int ret = rpc_port_proxy_tts_invoke_play(info->rpc_h, uid, not_null_credential);
717         int exception = get_last_result();
718         if (RPC_PORT_ERROR_NONE != exception) {
719                 ret = __convert_and_handle_tidl_error(exception, info);
720         }
721
722         if (TTS_ERROR_NONE != ret) {
723                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request play : Fail to invoke message");
724                 return ret;
725         }
726
727         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
728
729         return TTS_ERROR_NONE;
730 }
731
732 int tts_tidl_request_stop(unsigned int uid)
733 {
734         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_stop");
735
736         tts_client_s* client = tts_client_get_by_uid(uid);
737         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
738
739         tts_tidl_info_s* info = __get_tidl_info_s(uid);
740         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
741
742         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
743
744         int ret = rpc_port_proxy_tts_invoke_stop(info->rpc_h, uid);
745         int exception = get_last_result();
746         if (RPC_PORT_ERROR_NONE != exception) {
747                 ret = __convert_and_handle_tidl_error(exception, info);
748         }
749
750         if (TTS_ERROR_NONE != ret) {
751                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request stop : Fail to invoke message");
752                 return ret;
753         }
754         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
755
756         return TTS_ERROR_NONE;
757 }
758
759 int tts_tidl_request_pause(unsigned int uid)
760 {
761         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_pause");
762
763         tts_client_s* client = tts_client_get_by_uid(uid);
764         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
765
766         tts_tidl_info_s* info = __get_tidl_info_s(uid);
767         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
768
769         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
770
771         int ret = rpc_port_proxy_tts_invoke_pause(info->rpc_h, uid);
772         int exception = get_last_result();
773         if (RPC_PORT_ERROR_NONE != exception) {
774                 ret = __convert_and_handle_tidl_error(exception, info);
775         }
776
777         if (TTS_ERROR_NONE != ret) {
778                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request pause : Fail to invoke message(%d)", ret);
779                 return ret;
780         }
781
782         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
783
784         return TTS_ERROR_NONE;
785 }
786
787 int tts_tidl_request_play_pcm(unsigned int uid)
788 {
789         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_play_pcm");
790
791         tts_client_s* client = tts_client_get_by_uid(uid);
792         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
793
794         tts_tidl_info_s* info = __get_tidl_info_s(uid);
795         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
796
797         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
798
799         int ret = rpc_port_proxy_tts_invoke_play_pcm(info->rpc_h, uid);
800         int exception = get_last_result();
801         if (RPC_PORT_ERROR_NONE != exception) {
802                 ret = __convert_and_handle_tidl_error(exception, info);
803         }
804
805         if (TTS_ERROR_NONE != ret) {
806                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request play pcm : Fail to invoke message(%d)", ret);
807                 return ret;
808         }
809
810         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
811
812         return TTS_ERROR_NONE;
813 }
814
815 int tts_tidl_request_stop_pcm(unsigned int uid)
816 {
817         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_stop_pcm");
818
819         tts_client_s* client = tts_client_get_by_uid(uid);
820         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
821
822         tts_tidl_info_s* info = __get_tidl_info_s(uid);
823         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
824
825         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
826
827         int ret = rpc_port_proxy_tts_invoke_stop_pcm(info->rpc_h, uid);
828         int exception = get_last_result();
829         if (RPC_PORT_ERROR_NONE != exception) {
830                 ret = __convert_and_handle_tidl_error(exception, info);
831         }
832
833         if (TTS_ERROR_NONE != ret) {
834                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request pause pcm : Fail to invoke message(%d)", ret);
835                 return ret;
836         }
837
838         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
839
840         return TTS_ERROR_NONE;
841 }
842
843 int tts_tidl_request_add_pcm(unsigned int uid, int event, const char* data, int data_size, int audio_type, int rate)
844 {
845         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_add_pcm");
846
847         tts_client_s* client = tts_client_get_by_uid(uid);
848         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
849
850         tts_tidl_info_s* info = __get_tidl_info_s(uid);
851         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
852
853         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
854
855         rpc_port_proxy_array_char_h pcm_data = NULL;
856         rpc_port_proxy_array_char_create(&pcm_data);
857         if (NULL == pcm_data) {
858                 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create data handle");
859                 return TTS_ERROR_OUT_OF_MEMORY;
860         }
861
862         if (NULL != data && 0 < data_size) {
863                 rpc_port_proxy_array_char_set(pcm_data, (char*)data, data_size);
864         } else {
865                 SLOG(LOG_INFO, TAG_TTSC, "[TIDL] data is empty");
866         }
867
868         int ret = rpc_port_proxy_tts_invoke_add_pcm(info->rpc_h, uid, event, pcm_data, data_size, audio_type, rate);
869         rpc_port_proxy_array_char_destroy(pcm_data);
870         int exception = get_last_result();
871         if (RPC_PORT_ERROR_NONE != exception) {
872                 ret = __convert_and_handle_tidl_error(exception, info);
873         }
874
875         if (TTS_ERROR_NONE != ret) {
876                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request pause pcm : Fail to invoke message(%d)", ret);
877                 return ret;
878         }
879
880         SLOG(LOG_DEBUG, TAG_TTSC, "<<<<");
881
882         return TTS_ERROR_NONE;
883 }
884
885 int tts_tidl_request_get_service_state(unsigned int uid, tts_service_state_e* service_state)
886 {
887         SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_get_service_state");
888
889         tts_client_s* client = tts_client_get_by_uid(uid);
890         RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client");
891
892         tts_tidl_info_s* info = __get_tidl_info_s(uid);
893         RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info");
894
895         RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected");
896
897         int state = (int)TTS_SERVICE_STATE_READY;
898         int ret = rpc_port_proxy_tts_invoke_get_service_state(info->rpc_h, uid, &state);
899         int exception = get_last_result();
900         if (RPC_PORT_ERROR_NONE != exception) {
901                 ret = __convert_and_handle_tidl_error(exception, info);
902         }
903
904         if (TTS_ERROR_NONE != ret) {
905                 SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request get service state : Fail to invoke message");
906                 return ret;
907         }
908
909         *service_state = (tts_service_state_e)state;
910
911         SLOG(LOG_DEBUG, TAG_TTSC, "<<<< get service state : service state(%d)", state);
912
913         return TTS_ERROR_NONE;
914 }