fix merge duplication
[platform/core/uifw/stt.git] / client / stt.c
1 /*
2 *  Copyright (c) 2011-2016 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 #include <aul.h>
15 #include <cynara-client.h>
16 #include <cynara-error.h>
17 #include <cynara-session.h>
18 #include <dirent.h>
19 #include <Ecore.h>
20 #include <fcntl.h>
21 #include <pthread.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <system_info.h>
26 #include <unistd.h>
27 #include <buxton2.h>
28 #include <stdatomic.h>
29 #include <sound_manager.h>
30 #include <sound_manager_internal.h>
31
32 #include "stt.h"
33 #include "stt_client.h"
34 #include "stt_dbus.h"
35 #include "stt_config_mgr.h"
36 #include "stt_internal.h"
37 #include "stt_main.h"
38 #include "stt_dlog.h"
39
40
41 static void __stt_notify_state_changed(void *data);
42 static void __stt_notify_error(void *data);
43
44 static Ecore_Timer* g_connect_timer = NULL;
45 static float g_volume_db = 0;
46
47 static pthread_mutex_t g_cynara_mutex = PTHREAD_MUTEX_INITIALIZER;
48
49 static cynara *p_cynara = NULL;
50
51 static bool g_err_callback_status = false;
52
53 /* for changing volume on each sound stream */
54 static sound_stream_ducking_h g_media_stream_ducking;
55 static sound_stream_ducking_h g_system_stream_ducking;
56 static sound_stream_ducking_h g_notification_stream_ducking;
57 static sound_stream_ducking_h g_alarm_stream_ducking;
58
59 #define STT_BG_VOLUME_RATIO_FARFIELD    0.0
60 #define STT_BG_VOLUME_RATIO_NEARFIELD   0.7
61 #define SND_MGR_DUCKING_DURATION 500
62
63
64 static bool is_stt_feature_enabled()
65 {
66         static atomic_int stt_feature_enabled = -1;
67
68         if (0 == stt_feature_enabled) {
69                 //LCOV_EXCL_START
70                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] STT NOT supported");
71                 return false;
72                 //LCOV_EXCL_STOP
73         } else if (-1 == stt_feature_enabled) {
74                 bool stt_supported = false;
75
76                 if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(STT_FEATURE_PATH, &stt_supported)) {
77                         //LCOV_EXCL_START
78                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get feature value");
79                         return false;
80                         //LCOV_EXCL_STOP
81                 }
82
83                 if (false == stt_supported) {
84                         //LCOV_EXCL_START
85                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] STT NOT supported");
86                         stt_feature_enabled = 0;
87                         return false;
88                         //LCOV_EXCL_STOP
89                 }
90
91                 stt_feature_enabled = 1;
92         }
93
94         return true;
95 }
96
97 static bool is_mic_feature_enabled()
98 {
99         static atomic_int mic_feature_enabled = -1;
100
101         if (0 == mic_feature_enabled) {
102                 //LCOV_EXCL_START
103                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] STT NOT supported");
104                 return false;
105                 //LCOV_EXCL_STOP
106         } else if (-1 == mic_feature_enabled) {
107                 bool mic_supported = false;
108
109                 if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool(STT_MIC_FEATURE_PATH, &mic_supported)) {
110                         //LCOV_EXCL_START
111                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get feature value");
112                         return false;
113                         //LCOV_EXCL_STOP
114                 }
115
116                 if (false == mic_supported) {
117                         //LCOV_EXCL_START
118                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] STT NOT supported");
119                         mic_feature_enabled = 0;
120                         return false;
121                         //LCOV_EXCL_STOP
122                 }
123
124                 mic_feature_enabled = 1;
125         }
126
127         return true;
128 }
129
130 static int __stt_get_feature_enabled()
131 {
132         if (false == is_stt_feature_enabled() || false == is_mic_feature_enabled()) {
133                 //LCOV_EXCL_START
134                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] STT NOT supported");
135                 return STT_ERROR_NOT_SUPPORTED;
136                 //LCOV_EXCL_STOP
137         }
138
139         return STT_ERROR_NONE;
140 }
141
142 static int __check_privilege_initialize()
143 {
144         int ret = cynara_initialize(&p_cynara, NULL);
145         if (CYNARA_API_SUCCESS != ret)
146                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] fail to initialize"); //LCOV_EXCL_LINE
147
148         return ret == CYNARA_API_SUCCESS;
149 }
150
151 static bool __check_privilege(const char* uid, const char * privilege)
152 {
153         FILE *fp = NULL;
154         char label_path[1024] = "/proc/self/attr/current";
155         char smack_label[1024] = {'\0',};
156
157         if (!p_cynara) {
158                 return false;
159         }
160
161         fp = fopen(label_path, "r");
162         if (fp != NULL) {
163                 if (0 >= fread(smack_label, 1, sizeof(smack_label), fp))
164                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] fail to fread"); //LCOV_EXCL_LINE
165
166                 fclose(fp);
167         }
168
169         pid_t pid = getpid();
170         char *session = cynara_session_from_pid(pid);
171         int ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
172         free(session);
173         session = NULL;
174
175         if (ret != CYNARA_API_ACCESS_ALLOWED) {
176                 SLOG(LOG_DEBUG, TAG_STTC, "[Client]cynara_check returned %d(Denied)", ret);
177                 return false;
178         }
179         return true;
180 }
181
182 static void __check_privilege_deinitialize()
183 {
184         if (p_cynara)
185                 cynara_finish(p_cynara);
186         p_cynara = NULL;
187 }
188
189 static int __stt_check_privilege()
190 {
191         pthread_mutex_lock(&g_cynara_mutex);
192
193         bool ret = true;
194         ret = __check_privilege_initialize();
195         if (false == ret) {
196                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] privilege initialize is failed"); //LCOV_EXCL_LINE
197                 pthread_mutex_unlock(&g_cynara_mutex);
198                 return STT_ERROR_PERMISSION_DENIED;
199         }
200
201         char uid[16];
202         snprintf(uid, 16, "%d", getuid());
203         ret = true;
204         ret = __check_privilege(uid, STT_PRIVILEGE_RECORDER);
205         __check_privilege_deinitialize();
206         if (false == ret) {
207                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Permission is denied"); //LCOV_EXCL_LINE
208                 pthread_mutex_unlock(&g_cynara_mutex);
209                 return STT_ERROR_PERMISSION_DENIED;
210         }
211
212         pthread_mutex_unlock(&g_cynara_mutex);
213         return STT_ERROR_NONE;
214 }
215
216 static int __stt_check_privilege_for_applaunch()
217 {
218         pthread_mutex_lock(&g_cynara_mutex);
219
220         bool ret = true;
221         ret = __check_privilege_initialize();
222         if (false == ret) {
223                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] privilege initialize is failed (applaunch)"); //LCOV_EXCL_LINE
224                 pthread_mutex_unlock(&g_cynara_mutex);
225                 return STT_ERROR_PERMISSION_DENIED;
226         }
227
228         char uid[16];
229         snprintf(uid, 16, "%d", getuid());
230         ret = true;
231         ret = __check_privilege(uid, STT_PRIVILEGE_APPLAUNCH);
232         __check_privilege_deinitialize();
233         if (false == ret) {
234                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Permission is denied : appmanager.launch"); //LCOV_EXCL_LINE
235                 pthread_mutex_unlock(&g_cynara_mutex);
236                 return STT_ERROR_PERMISSION_DENIED;
237         }
238
239         pthread_mutex_unlock(&g_cynara_mutex);
240         return STT_ERROR_NONE;
241 }
242
243 //LCOV_EXCL_START
244 static const char* __stt_get_error_code(stt_error_e err)
245 {
246         switch (err) {
247         case STT_ERROR_NONE:                    return "STT_ERROR_NONE";
248         case STT_ERROR_OUT_OF_MEMORY:           return "STT_ERROR_OUT_OF_MEMORY";
249         case STT_ERROR_IO_ERROR:                return "STT_ERROR_IO_ERROR";
250         case STT_ERROR_INVALID_PARAMETER:       return "STT_ERROR_INVALID_PARAMETER";
251         case STT_ERROR_TIMED_OUT:               return "STT_ERROR_TIMED_OUT";
252         case STT_ERROR_RECORDER_BUSY:           return "STT_ERROR_RECORDER_BUSY";
253         case STT_ERROR_OUT_OF_NETWORK:          return "STT_ERROR_OUT_OF_NETWORK";
254         case STT_ERROR_PERMISSION_DENIED:       return "STT_ERROR_PERMISSION_DENIED";
255         case STT_ERROR_NOT_SUPPORTED:           return "STT_ERROR_NOT_SUPPORTED";
256         case STT_ERROR_INVALID_STATE:           return "STT_ERROR_INVALID_STATE";
257         case STT_ERROR_INVALID_LANGUAGE:        return "STT_ERROR_INVALID_LANGUAGE";
258         case STT_ERROR_ENGINE_NOT_FOUND:        return "STT_ERROR_ENGINE_NOT_FOUND";
259         case STT_ERROR_OPERATION_FAILED:        return "STT_ERROR_OPERATION_FAILED";
260         case STT_ERROR_NOT_SUPPORTED_FEATURE:   return "STT_ERROR_NOT_SUPPORTED_FEATURE";
261         case STT_ERROR_SERVICE_RESET:           return "STT_ERROR_SERVICE_RESET";
262         default:
263                 return "Invalid error code";
264         }
265 }
266
267 static int __stt_convert_config_error_code(stt_config_error_e code)
268 {
269         if (code == STT_CONFIG_ERROR_NONE)                      return STT_ERROR_NONE;
270         if (code == STT_CONFIG_ERROR_OUT_OF_MEMORY)             return STT_ERROR_OUT_OF_MEMORY;
271         if (code == STT_CONFIG_ERROR_IO_ERROR)                  return STT_ERROR_IO_ERROR;
272         if (code == STT_CONFIG_ERROR_INVALID_PARAMETER)         return STT_ERROR_INVALID_PARAMETER;
273         if (code == STT_CONFIG_ERROR_PERMISSION_DENIED)         return STT_ERROR_PERMISSION_DENIED;
274         if (code == STT_CONFIG_ERROR_NOT_SUPPORTED)             return STT_ERROR_NOT_SUPPORTED;
275         if (code == STT_CONFIG_ERROR_INVALID_STATE)             return STT_ERROR_INVALID_STATE;
276         if (code == STT_CONFIG_ERROR_INVALID_LANGUAGE)          return STT_ERROR_INVALID_LANGUAGE;
277         if (code == STT_CONFIG_ERROR_ENGINE_NOT_FOUND)          return STT_ERROR_ENGINE_NOT_FOUND;
278         if (code == STT_CONFIG_ERROR_OPERATION_FAILED)          return STT_ERROR_OPERATION_FAILED;
279
280         return code;
281 }
282
283 void __stt_config_lang_changed_cb(const char* before_language, const char* current_language, void* user_data)
284 {
285         SLOG(LOG_DEBUG, TAG_STTC, "Language changed : Before lang(%s) Current lang(%s)",
286                 before_language, current_language);
287
288         if (0 == strcmp(before_language, current_language)) {
289                 return;
290         }
291
292         GList* client_list = NULL;
293         client_list = stt_client_get_client_list();
294
295         GList *iter = NULL;
296         stt_client_s *data = NULL;
297
298         if (g_list_length(client_list) > 0) {
299                 /* Get a first item */
300                 iter = g_list_first(client_list);
301
302                 while (NULL != iter) {
303                         data = iter->data;
304                         if (NULL != data->default_lang_changed_cb) {
305                                 SLOG(LOG_DEBUG, TAG_STTC, "Call default language changed callback : uid(%u)", data->uid);
306                                 data->default_lang_changed_cb(data->stt, before_language, current_language,
307                                         data->default_lang_changed_user_data);
308                         }
309
310                         /* Next item */
311                         iter = g_list_next(iter);
312                 }
313         }
314
315         return;
316 }
317
318 static Eina_Bool __reconnect_by_engine_changed(void *data)
319 {
320         stt_h stt = (stt_h)data;
321
322         stt_client_s* client = stt_client_get(stt);
323         if (NULL == client) {
324                 SLOG(LOG_ERROR, TAG_STTC, "[WARNING] A handle is not valid");
325                 return EINA_FALSE;
326         }
327
328         if (STT_STATE_READY != client->current_state) {
329                 usleep(10000);
330                 return EINA_TRUE;
331         }
332
333         int ret = stt_unprepare(stt);
334         if (0 != ret) {
335                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to prepare for setting a new engine... (%d)", ret);
336         }
337         ret = stt_prepare(stt);
338         if (0 != ret) {
339                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to prepare for setting a new engine... (%d)", ret);
340         }
341
342         return EINA_FALSE;
343 }
344
345 void __stt_config_engine_changed_cb(const char* engine_id, const char* setting, const char* language, bool support_silence, bool need_credential, void* user_data)
346 {
347         stt_h stt = (stt_h)user_data;
348
349         stt_client_s* client = stt_client_get(stt);
350         if (NULL == client) {
351                 SLOG(LOG_ERROR, TAG_STTC, "[WARNING] A handle is not valid");
352                 return;
353         }
354
355         if (NULL != engine_id)  SLOG(LOG_DEBUG, TAG_STTC, "Engine id(%s)", engine_id);
356         if (NULL != setting)    SLOG(LOG_DEBUG, TAG_STTC, "Engine setting(%s)", setting);
357         if (NULL != language)   SLOG(LOG_DEBUG, TAG_STTC, "Language(%s)", language);
358         SLOG(LOG_DEBUG, TAG_STTC, "Silence(%s), Credential(%s)", support_silence ? "on" : "off", need_credential ? "need" : "no need");
359
360         /* When the default engine is changed, please unload the old engine and load the new one. */
361         int ret = -1;
362
363         if (NULL == client->current_engine_id) {
364                 if (STT_STATE_RECORDING == client->current_state || STT_STATE_PROCESSING == client->current_state) {
365                         SLOG(LOG_INFO, TAG_STTC, "[INFO] stt cancel is invoked by engine_changed_cb, state(%d)", client->current_state);
366                         ret = stt_cancel(stt);
367                         if (0 != ret) {
368                                 SLOG(LOG_DEBUG, TAG_STTC, "[DEBUG] STT client cancelling...");
369                         }
370
371                         ecore_idler_add(__reconnect_by_engine_changed, (void*)stt);
372                 } else if (STT_STATE_READY == client->current_state) {
373                         ret = stt_unprepare(stt);
374                         if (0 != ret) {
375                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to prepare for setting a new engine... (%d)", ret);
376                         }
377                         ret = stt_prepare(stt);
378                         if (0 != ret) {
379                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to prepare for setting a new engine... (%d)", ret);
380                         }
381                 }
382         }
383
384         /* call callback function */
385         if (NULL != client->engine_changed_cb) {
386                 client->engine_changed_cb(stt, engine_id, language, support_silence, need_credential, client->engine_changed_user_data);
387         } else {
388                 SLOG(LOG_WARN, TAG_STTC, "No registered callback function for engine change");
389         }
390         return;
391 }
392
393 static const char* __stt_get_state_string(stt_state_e state)
394 {
395         switch (state) {
396         case STT_STATE_CREATED:                 return "STT_STATE_CREATED";
397         case STT_STATE_READY:           return "STT_STATE_READY";
398         case STT_STATE_RECORDING:               return "STT_STATE_RECORDING";
399         case STT_STATE_PROCESSING:      return "STT_STATE_PROCESSING";
400         default:
401                 return "Invalid State";
402         }
403 }
404 //LCOV_EXCL_STOP
405
406 static int __stt_check_handle(stt_h stt, stt_client_s** client)
407 {
408         RETVM_IF(NULL == stt, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input handle is null");
409
410         stt_client_s* temp = NULL;
411         temp = stt_client_get(stt);
412
413         /* check handle */
414         RETVM_IF(NULL == temp, STT_ERROR_INVALID_PARAMETER, "[ERROR] A handle is not available");
415         *client = temp;
416
417         return STT_ERROR_NONE;
418 }
419
420 static int __stt_check_precondition(stt_h stt, stt_client_s** client)
421 {
422         RETV_IF(0 != __stt_get_feature_enabled(), STT_ERROR_NOT_SUPPORTED);
423         RETV_IF(0 != __stt_check_privilege(), STT_ERROR_PERMISSION_DENIED);
424         RETV_IF(0 != __stt_check_handle(stt, client), STT_ERROR_INVALID_PARAMETER);
425         return STT_ERROR_NONE;
426 }
427
428 static int __stt_check_precondition_with_state(stt_h stt, stt_client_s** client, stt_state_e state)
429 {
430         int ret = __stt_check_precondition(stt, client);
431         if (STT_ERROR_NONE != ret)
432                 return ret;
433         const char* state_string = __stt_get_state_string(state);
434         RETVM_IF(state != (*client)->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not %s", (*client)->current_state, state_string);
435         return STT_ERROR_NONE;
436 }
437
438 int stt_create(stt_h* stt)
439 {
440         RETV_IF(0 != __stt_get_feature_enabled(), STT_ERROR_NOT_SUPPORTED);
441         RETV_IF(0 != __stt_check_privilege(), STT_ERROR_PERMISSION_DENIED);
442
443         SLOG(LOG_INFO, TAG_STTC, "===== Create STT");
444         RETVM_IF(NULL == stt, STT_ERROR_INVALID_PARAMETER, "[ERROR] A handle is null");
445
446         if (0 == stt_client_get_size()) {
447                 if (0 != stt_dbus_open_connection()) {
448                         //LCOV_EXCL_START
449                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to open connection");
450                         return STT_ERROR_OPERATION_FAILED;
451                         //LCOV_EXCL_STOP
452                 }
453         }
454
455         stt_h new_stt = NULL;
456         if (STT_ERROR_NONE != stt_client_new(&new_stt)) {
457                 //LCOV_EXCL_START
458                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to create client!");
459                 return STT_ERROR_OUT_OF_MEMORY;
460                 //LCOV_EXCL_STOP
461         }
462
463         stt_client_s* client = stt_client_get(new_stt);
464         if (NULL == client) {
465                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to create client"); //LCOV_EXCL_LINE
466                 stt_client_destroy(new_stt);
467                 return STT_ERROR_OPERATION_FAILED;
468         }
469
470         int ret = stt_config_mgr_initialize(client->uid);
471         ret = __stt_convert_config_error_code(ret);
472         if (0 != ret) {
473                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to init config manager : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
474                 stt_client_destroy(new_stt);
475                 return ret;
476         }
477
478         ret = stt_config_mgr_set_callback(client->uid, __stt_config_engine_changed_cb, __stt_config_lang_changed_cb, NULL, client->stt);
479         ret = __stt_convert_config_error_code(ret);
480         if (0 != ret) {
481                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to set config changed : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
482                 stt_client_destroy(new_stt);
483                 return ret;
484         }
485
486         *stt = new_stt;
487         SLOG(LOG_INFO, TAG_STTC, "[Success] uid(%u)", client->uid);
488         SLOG(LOG_DEBUG, TAG_STTC, "=====");
489         return STT_ERROR_NONE;
490 }
491
492 int stt_destroy(stt_h stt)
493 {
494         stt_client_s* client = NULL;
495         int temp = __stt_check_precondition(stt, &client);
496         if (STT_ERROR_NONE != temp)
497                 return temp;
498         SLOG(LOG_INFO, TAG_STTC, "===== Destroy STT");
499
500         /* check used callback */
501         if (0 != stt_client_get_use_callback(client)) {
502                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Cannot destroy in Callback function");
503                 return STT_ERROR_OPERATION_FAILED;
504         }
505
506         stt_config_mgr_finalize(client->uid);
507
508         int ret = -1;
509
510         /* check state */
511         switch (client->current_state) {
512         case STT_STATE_PROCESSING:
513         case STT_STATE_RECORDING:
514         case STT_STATE_READY:
515                 ret = stt_dbus_request_finalize(client->uid);
516                 if (0 != ret) {
517                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to request finalize : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
518                 }
519         case STT_STATE_CREATED:
520                 if (NULL != g_connect_timer) {
521                         SLOG(LOG_DEBUG, TAG_STTC, "Connect Timer is deleted");
522                         ecore_timer_del(g_connect_timer);
523                         g_connect_timer = NULL;
524                 }
525
526                 /* Free resources */
527                 stt_client_destroy(stt);
528                 break;
529         default:
530                 break;
531         }
532
533         if (0 == stt_client_get_size()) {
534                 if (0 != stt_dbus_close_connection()) {
535                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to close connection"); //LCOV_EXCL_LINE
536                 }
537         }
538
539         stt = NULL;
540
541         SLOG(LOG_INFO, TAG_STTC, "=====");
542         SLOG(LOG_DEBUG, TAG_STTC, " ");
543
544         return STT_ERROR_NONE;
545 }
546
547 static bool __stt_config_supported_engine_cb(const char* engine_id, const char* engine_name,
548                                              const char* setting, bool support_silence, void* user_data)
549 {
550         stt_h stt = (stt_h)user_data;
551
552         stt_client_s* client = stt_client_get(stt);
553         if (NULL == client) {
554                 //LCOV_EXCL_START
555                 SLOG(LOG_ERROR, TAG_STTC, "[WARNING] A handle is not valid");
556                 return false;
557                 //LCOV_EXCL_STOP
558         }
559
560         /* call callback function */
561         if (NULL != client->supported_engine_cb) {
562                 return client->supported_engine_cb(stt, engine_id, engine_name, client->supported_engine_user_data);
563         } else {
564                 SLOG(LOG_WARN, TAG_STTC, "No registered callback function of supported engine"); //LCOV_EXCL_LINE
565         }
566
567         return false;
568 }
569
570 int stt_foreach_supported_engines(stt_h stt, stt_supported_engine_cb callback, void* user_data)
571 {
572         stt_client_s* client = NULL;
573         int temp = __stt_check_precondition(stt, &client);
574         if (STT_ERROR_NONE != temp)
575                 return temp;
576         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
577         RETVM_IF(client->current_state != STT_STATE_CREATED, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not CREATED", client->current_state);
578
579         SLOG(LOG_INFO, TAG_STTC, "===== Foreach Supported engine");
580
581         client->supported_engine_cb = callback;
582         client->supported_engine_user_data = user_data;
583
584         int ret = 0;
585         ret = stt_config_mgr_get_engine_list(__stt_config_supported_engine_cb, client->stt);
586         ret = __stt_convert_config_error_code(ret);
587         if (0 != ret) {
588                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get engines : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
589         }
590
591         client->supported_engine_cb = NULL;
592         client->supported_engine_user_data = NULL;
593
594         SLOG(LOG_INFO, TAG_STTC, "=====");
595         SLOG(LOG_DEBUG, TAG_STTC, " ");
596
597         return ret;
598 }
599
600 int stt_get_engine(stt_h stt, char** engine_id)
601 {
602         stt_client_s* client = NULL;
603         int temp = __stt_check_precondition(stt, &client);
604         if (STT_ERROR_NONE != temp)
605                 return temp;
606
607         RETVM_IF(NULL == engine_id, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
608         RETVM_IF(client->current_state != STT_STATE_CREATED, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not CREATED", client->current_state);
609
610         SLOG(LOG_INFO, TAG_STTC, "===== Get current engine");
611
612         int ret = 0;
613
614         if (NULL != client->current_engine_id) {
615                 *engine_id = strdup(client->current_engine_id);
616                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS] Current engine uuid = %s", *engine_id);
617         } else {
618
619                 ret = stt_config_mgr_get_engine(engine_id);
620                 ret = __stt_convert_config_error_code(ret);
621                 if (0 != ret) {
622                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to request get current engine : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
623                 } else {
624                         SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS] Current engine uuid = %s", *engine_id);
625                 }
626         }
627
628         SLOG(LOG_INFO, TAG_STTC, "=====");
629         SLOG(LOG_DEBUG, TAG_STTC, " ");
630
631         return ret;
632 }
633
634 int __stt_set_buxtonkey(const char* engine_id)
635 {
636         /* Set vconfkey */
637         struct buxton_client * bux_cli;
638         struct buxton_layer * bux_layer;
639         struct buxton_value * bux_val;
640
641         int ret = buxton_open(&bux_cli, NULL, NULL);
642         if (0 != ret) {
643                 SLOG(LOG_ERROR, TAG_STTC, "[DBUS-BUXTON2] Fail to open buxton client"); //LCOV_EXCL_LINE
644                 return STT_ERROR_OPERATION_FAILED;
645         }
646         SLOG(LOG_DEBUG, TAG_STTC, "[DBUS-BUXTON2] buxton_open: %d", ret);
647         bux_layer = buxton_create_layer("system");
648         if (NULL == bux_layer) {
649                 //LCOV_EXCL_START
650                 SLOG(LOG_ERROR, TAG_STTC, "[DBUS-BUXTON2] buxton_create_layer FAIL");
651                 buxton_close(bux_cli);
652                 bux_cli = NULL;
653                 return STT_ERROR_OPERATION_FAILED;
654                 //LCOV_EXCL_STOP
655         }
656         bux_val = buxton_value_create_string(engine_id);
657         if (NULL == bux_val) {
658                 //LCOV_EXCL_START
659                 SLOG(LOG_ERROR, TAG_STTC, "[DBUS-BUXTON2] buxton_value_create_string FAIL");
660                 buxton_free_layer(bux_layer);
661                 buxton_close(bux_cli);
662                 bux_layer = NULL;
663                 bux_cli = NULL;
664                 return STT_ERROR_OPERATION_FAILED;
665                 //LCOV_EXCL_STOP
666         }
667
668         ret = buxton_set_value_sync(bux_cli, bux_layer, STT_ENGINE_DB_CUSTOM, bux_val);
669         if (0 != ret) {
670                 //LCOV_EXCL_START
671                 SLOG(LOG_ERROR, TAG_STTC, "[DBUS-BUXTON2] Fail to set value sync");
672                 buxton_value_free(bux_val);
673                 buxton_free_layer(bux_layer);
674                 buxton_close(bux_cli);
675
676                 bux_cli = NULL;
677                 bux_layer = NULL;
678                 bux_val = NULL;
679                 return STT_ERROR_OPERATION_FAILED;
680                 //LCOV_EXCL_STOP
681         }
682         SLOG(LOG_DEBUG, TAG_STTC, "[DBUS-BUXTON2] buxton_set_value_sync: %d, %s", ret, STT_ENGINE_DB_CUSTOM);
683
684         buxton_value_free(bux_val);
685         buxton_free_layer(bux_layer);
686         buxton_close(bux_cli);
687
688         bux_cli = NULL;
689         bux_layer = NULL;
690         bux_val = NULL;
691
692         return STT_ERROR_NONE;
693 }
694
695 int stt_set_engine(stt_h stt, const char* engine_id)
696 {
697         stt_client_s* client = NULL;
698         if (0 != __stt_get_feature_enabled()) {
699                 return STT_ERROR_NOT_SUPPORTED;
700         }
701         if (0 != __stt_check_privilege()) {
702                 return STT_ERROR_PERMISSION_DENIED;
703         }
704         if (0 != __stt_check_privilege_for_applaunch()) {
705                 return STT_ERROR_PERMISSION_DENIED;
706         }
707         if (0 != __stt_check_handle(stt, &client)) {
708                 return STT_ERROR_INVALID_PARAMETER;
709         }
710
711         SLOG(LOG_INFO, TAG_STTC, "===== Set current engine");
712
713         RETVM_IF(NULL == engine_id, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
714         RETVM_IF(client->current_state != STT_STATE_CREATED, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not CREATED", client->current_state);
715
716         SLOG(LOG_INFO, TAG_STTC, "===== engined_id(%s)", engine_id);
717
718         free(client->current_engine_id);
719         client->current_engine_id = strdup(engine_id);
720
721         /* Set vconfkey */
722         int ret = __stt_set_buxtonkey(engine_id);
723         if (0 != ret) {
724                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] set buxtonkey Failed!!!"); //LCOV_EXCL_LINE
725                 return ret;
726         }
727
728         SLOG(LOG_INFO, TAG_STTC, "=====");
729         SLOG(LOG_DEBUG, TAG_STTC, " ");
730
731         return 0;
732 }
733
734 int stt_set_credential(stt_h stt, const char* credential)
735 {
736         stt_client_s* client = NULL;
737         int temp = __stt_check_precondition(stt, &client);
738         if (STT_ERROR_NONE != temp)
739                 return temp;
740
741         SLOG(LOG_INFO, TAG_STTC, "===== Set credential");
742
743         RETVM_IF(NULL == credential, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
744         RETVM_IF(client->current_state != STT_STATE_CREATED && client->current_state != STT_STATE_READY, STT_ERROR_INVALID_STATE,
745                         "[ERROR] Invalid State: Current state(%d) is not CREATED or READY", client->current_state);
746
747         free(client->credential);
748         client->credential = strdup(credential);
749
750         SLOG(LOG_INFO, TAG_STTC, "=====");
751         SLOG(LOG_DEBUG, TAG_STTC, " ");
752
753         return STT_ERROR_NONE;
754 }
755
756 //LCOV_EXCL_START
757 static bool __stt_is_necessary_to_retry_dbus_request(int count, int return_value)
758 {
759         bool ret = true;
760         if (STT_ERROR_TIMED_OUT != return_value) {
761                 ret = false;
762         } else {
763                 SLOG(LOG_WARN, TAG_STTC, "[WARNING][%d] retry : %s", count, __stt_get_error_code(ret));
764                 usleep(10000);
765                 if (STT_RETRY_COUNT == count) {
766                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to request");
767                         ret = false;
768                 }
769         }
770         return ret;
771 }
772 //LCOV_EXCL_STOP
773
774 int stt_set_private_data(stt_h stt, const char* key, const char* data)
775 {
776         stt_client_s* client = NULL;
777         int temp = __stt_check_precondition(stt, &client);
778         if (STT_ERROR_NONE != temp)
779                 return temp;
780
781         RETVM_IF(NULL == key || NULL == data, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter");
782         RETVM_IF(STT_STATE_READY != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
783
784         SLOG(LOG_INFO, TAG_STTC, "===== Set private data");
785
786         if (true != client->internal && (0 == strcmp(key, "server") || 0 == strcmp(key, "rampcode") || 0 == strcmp(key, "epd"))) {
787                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] This is not an internal app");
788                 return STT_ERROR_INVALID_PARAMETER;
789         }
790
791         int ret = -1;
792         int count = 0;
793         while (0 != ret) {
794                 ret = stt_dbus_request_set_private_data(client->uid, key, data);
795                 if (0 != ret) {
796                         //LCOV_EXCL_START
797                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
798                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to set private data : %s", __stt_get_error_code(ret));
799                                 return ret;
800                         }
801                         count++;
802                         //LCOV_EXCL_STOP
803                 }
804         }
805
806         SLOG(LOG_INFO, TAG_STTC, "=====");
807         SLOG(LOG_DEBUG, TAG_STTC, "");
808
809         return STT_ERROR_NONE;
810 }
811
812 int stt_get_private_data(stt_h stt, const char* key, char** data)
813 {
814         stt_client_s* client = NULL;
815         int temp = __stt_check_precondition(stt, &client);
816         if (STT_ERROR_NONE != temp)
817                 return temp;
818
819         RETVM_IF(NULL == key || NULL == data, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter");
820         RETVM_IF(STT_STATE_READY != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
821
822         SLOG(LOG_INFO, TAG_STTC, "===== Get private data");
823
824         int ret = -1;
825         int count = 0;
826         while (0 != ret) {
827                 ret = stt_dbus_request_get_private_data(client->uid, key, data);
828                 if (0 != ret) {
829                         //LCOV_EXCL_START
830                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
831                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get private data : %s", __stt_get_error_code(ret));
832                                 return ret;
833                         }
834                         count++;
835                         //LCOV_EXCL_STOP
836                 }
837         }
838
839         if (0 == strncmp(*data, "NULL", strlen(*data))) {
840                 free(*data);
841                 *data = NULL;
842         }
843
844         SLOG(LOG_INFO, TAG_STTC, "=====");
845         SLOG(LOG_DEBUG, TAG_STTC, "");
846
847         return STT_ERROR_NONE;
848 }
849
850 int stt_set_server_stt(stt_h stt, const char* key, char* user_data)
851 {
852         int ret = -1;
853         stt_client_s* client = NULL;
854
855         int temp = __stt_check_precondition(stt, &client);
856         if (STT_ERROR_NONE != temp)
857                 return temp;
858
859         SLOG(LOG_INFO, TAG_STTC, "===== Set STT server");
860
861         RETVM_IF(NULL == key || NULL == user_data, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter");
862
863         if (STT_STATE_READY != client->current_state) {
864                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] The current state is invalid (%d).", client->current_state);
865                 return STT_ERROR_INVALID_STATE;
866         }
867
868         client->internal = true;
869         ret = stt_set_private_data(stt, key, user_data);
870         if (0 != ret) {
871                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to set private data, ret(%d), key(%s)", ret, key);
872                 return ret;
873         }
874
875         SLOG(LOG_INFO, TAG_STTC, "======");
876         SLOG(LOG_DEBUG, TAG_STTC, " ");
877
878         return ret;
879 }
880
881 static Eina_Bool __stt_connect_daemon(void *data)
882 {
883         stt_client_s* client = (stt_client_s*)data;
884         int ret = -1;
885
886         if (NULL == client) {
887                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
888                 g_connect_timer = NULL;
889                 return EINA_FALSE;
890         }
891
892         if (0 == stt_client_get_size() || NULL == stt_client_get_by_uid(client->uid)) {
893                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Client has been already destroyed"); //LCOV_EXCL_LINE
894                 return EINA_FALSE;
895         }
896
897         /* Check and Set vconfkey of custom engine before sending hello */
898         if (NULL != client->current_engine_id && 0 == __stt_check_privilege_for_applaunch()) {
899                 /* Set vconfkey */
900                 ret = __stt_set_buxtonkey(client->current_engine_id);
901                 //LCOV_EXCL_START
902                 if (0 != ret) {
903                         SLOG(LOG_DEBUG, TAG_STTC, "[DEBUG] set buxtonkey Failed!!! (inside __stt_connect_daemon)");
904                         return EINA_TRUE;
905                 }
906                 //LCOV_EXCL_STOP
907         }
908
909         /* Send hello */
910         ret = stt_dbus_request_hello(client->uid);
911         if (0 != ret) {
912                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to send hello, ret(0x%x)", ret);
913                 return EINA_TRUE;
914         }
915
916         g_connect_timer = NULL;
917         SLOG(LOG_INFO, TAG_STTC, "===== Connect stt-service");
918
919         /* request initialization */
920         bool silence_supported = false;
921         bool credential_needed = false;
922
923         ret = stt_dbus_request_initialize(client->uid, &silence_supported, &credential_needed);
924
925         if (STT_ERROR_ENGINE_NOT_FOUND == ret) {
926                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to initialize : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
927
928                 client->reason = STT_ERROR_ENGINE_NOT_FOUND; //LCOV_EXCL_LINE
929                 ecore_main_loop_thread_safe_call_async(__stt_notify_error, (void*)client); //LCOV_EXCL_LINE
930
931                 return EINA_FALSE; //LCOV_EXCL_LINE
932         } else if (STT_ERROR_NONE != ret) {
933                 SLOG(LOG_ERROR, TAG_STTC, "[WARNING] Fail to connection. Retry to connect"); //LCOV_EXCL_LINE
934                 return EINA_TRUE;
935         } else {
936                 /* success to connect stt-service */
937                 client->silence_supported = silence_supported;
938                 client->credential_needed = credential_needed;
939                 SLOG(LOG_DEBUG, TAG_STTC, "Supported options : silence(%s), credential(%s)", silence_supported ? "support" : "no support", credential_needed ? "need" : "no need");
940         }
941
942         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] uid(%u)", client->uid);
943
944         client->before_state = client->current_state;
945         client->current_state = STT_STATE_READY;
946
947         if (NULL != client->state_changed_cb) {
948                 stt_client_use_callback(client);
949                 client->state_changed_cb(client->stt, client->before_state,
950                         client->current_state, client->state_changed_user_data);
951                 stt_client_not_use_callback(client);
952                 SLOG(LOG_DEBUG, TAG_STTC, "State changed callback is called");
953         } else {
954                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null");
955         }
956
957         SLOG(LOG_INFO, TAG_STTC, "=====");
958         SLOG(LOG_DEBUG, TAG_STTC, "  ");
959
960         return EINA_FALSE;
961 }
962
963 int stt_prepare(stt_h stt)
964 {
965         stt_client_s* client = NULL;
966         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
967         if (STT_ERROR_NONE != temp)
968                 return temp;
969
970         SLOG(LOG_INFO, TAG_STTC, "===== Prepare STT");
971
972         ecore_thread_main_loop_begin();
973         g_connect_timer = ecore_timer_add(0.02, __stt_connect_daemon, (void*)client);
974         ecore_thread_main_loop_end();
975
976         SLOG(LOG_INFO, TAG_STTC, "=====");
977         SLOG(LOG_DEBUG, TAG_STTC, " ");
978
979         return STT_ERROR_NONE;
980 }
981
982 int stt_unprepare(stt_h stt)
983 {
984         stt_client_s* client = NULL;
985         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_READY);
986         if (STT_ERROR_NONE != temp)
987                 return temp;
988
989         SLOG(LOG_INFO, TAG_STTC, "===== Unprepare STT");
990
991         int ret = -1;
992         int count = 0;
993         while (0 != ret) {
994                 ret = stt_dbus_request_finalize(client->uid);
995                 if (0 != ret) {
996                         //LCOV_EXCL_START
997                         if (STT_ERROR_TIMED_OUT != ret) {
998                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to request finalize : %s", __stt_get_error_code(ret));
999                                 break;
1000                         } else {
1001                                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] retry");
1002                                 usleep(10000);
1003                                 count++;
1004                                 if (STT_RETRY_COUNT == count) {
1005                                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to request");
1006                                         break;
1007                                 }
1008                         }
1009                         //LCOV_EXCL_STOP
1010                 }
1011         }
1012
1013         client->internal_state = STT_INTERNAL_STATE_NONE;
1014
1015         client->before_state = client->current_state;
1016         client->current_state = STT_STATE_CREATED;
1017
1018         if (NULL != client->state_changed_cb) {
1019                 stt_client_use_callback(client);
1020                 client->state_changed_cb(client->stt, client->before_state,
1021                         client->current_state, client->state_changed_user_data);
1022                 stt_client_not_use_callback(client);
1023         } else {
1024                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null");
1025         }
1026
1027         if (g_connect_timer) {
1028                 ecore_timer_del(g_connect_timer);
1029                 g_connect_timer = NULL;
1030         }
1031
1032         SLOG(LOG_INFO, TAG_STTC, "=====");
1033         SLOG(LOG_DEBUG, TAG_STTC, " ");
1034
1035         return STT_ERROR_NONE;
1036 }
1037
1038 static bool __stt_config_supported_language_cb(const char* engine_id, const char* language, void* user_data)
1039 {
1040         stt_h stt = (stt_h)user_data;
1041
1042         stt_client_s* client = stt_client_get(stt);
1043         if (NULL == client) {
1044                 SLOG(LOG_ERROR, TAG_STTC, "[WARNING] A handle is not valid"); //LCOV_EXCL_LINE
1045                 return false;
1046         }
1047
1048         SLOG(LOG_INFO, TAG_STTC, "===== supported language callback");
1049
1050         /* call callback function */
1051         if (NULL != client->supported_lang_cb) {
1052                 return client->supported_lang_cb(stt, language, client->supported_lang_user_data);
1053         } else {
1054                 SLOG(LOG_WARN, TAG_STTC, "No registered callback function of supported languages"); //LCOV_EXCL_LINE
1055         }
1056
1057         return false;
1058 }
1059
1060 int stt_foreach_supported_languages(stt_h stt, stt_supported_language_cb callback, void* user_data)
1061 {
1062         stt_client_s* client = NULL;
1063         int temp = __stt_check_precondition(stt, &client);
1064         if (STT_ERROR_NONE != temp)
1065                 return temp;
1066
1067         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1068         SLOG(LOG_INFO, TAG_STTC, "===== Foreach Supported Language");
1069
1070         int ret;
1071         char* current_engine_id = NULL;
1072
1073         if (NULL == client->current_engine_id) {
1074                 ret = stt_config_mgr_get_engine(&current_engine_id);
1075                 if (NULL == current_engine_id) {
1076                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to allocate memory or Engine id is NULL");
1077                         return STT_ERROR_OPERATION_FAILED;
1078                 }
1079                 ret = __stt_convert_config_error_code(ret);
1080                 if (0 != ret) {
1081                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get default engine id : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1082                         free(current_engine_id);
1083                         current_engine_id = NULL;
1084                         return ret;
1085                 }
1086         } else {
1087                 current_engine_id = strdup(client->current_engine_id);
1088                 //LCOV_EXCL_START
1089                 if (NULL == current_engine_id) {
1090                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to allocate memory");
1091                         return STT_ERROR_OUT_OF_MEMORY;
1092                 }
1093                 //LCOV_EXCL_STOP
1094         }
1095
1096         client->supported_lang_cb = callback;
1097         client->supported_lang_user_data = user_data;
1098
1099         ret = stt_config_mgr_get_language_list(current_engine_id, __stt_config_supported_language_cb, client->stt);
1100         ret = __stt_convert_config_error_code(ret);
1101         if (0 != ret) {
1102                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get languages : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1103         }
1104
1105         free(current_engine_id);
1106         current_engine_id = NULL;
1107
1108         client->supported_lang_cb = NULL;
1109         client->supported_lang_user_data = NULL;
1110
1111         SLOG(LOG_INFO, TAG_STTC, "=====");
1112         SLOG(LOG_DEBUG, TAG_STTC, " ");
1113
1114         return ret;
1115 }
1116
1117 int stt_get_default_language(stt_h stt, char** language)
1118 {
1119         stt_client_s* client = NULL;
1120         int temp = __stt_check_precondition(stt, &client);
1121         if (STT_ERROR_NONE != temp)
1122                 return temp;
1123
1124         RETVM_IF(NULL == language, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1125         SLOG(LOG_INFO, TAG_STTC, "===== Get Default Language");
1126
1127         int ret = 0;
1128         ret = stt_config_mgr_get_default_language(language);
1129         ret = __stt_convert_config_error_code(ret);
1130         if (0 != ret) {
1131                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get default language : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1132         } else {
1133                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS] Current language = %s", *language);
1134         }
1135
1136         SLOG(LOG_INFO, TAG_STTC, "=====");
1137         SLOG(LOG_DEBUG, TAG_STTC, " ");
1138
1139         return ret;
1140 }
1141
1142 int stt_get_state(stt_h stt, stt_state_e* state)
1143 {
1144         stt_client_s* client = NULL;
1145         int temp = __stt_check_precondition(stt, &client);
1146         if (STT_ERROR_NONE != temp)
1147                 return temp;
1148
1149         RETVM_IF(NULL == state, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1150
1151         *state = client->current_state;
1152
1153         SLOG(LOG_INFO, TAG_STTC, "===== Get state(%d)", *state);
1154
1155         switch (*state) {
1156         case STT_STATE_CREATED:         SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'CREATED'");        break;
1157         case STT_STATE_READY:           SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'Ready'");          break;
1158         case STT_STATE_RECORDING:       SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'Recording'");      break;
1159         case STT_STATE_PROCESSING:      SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'Processing'");     break;
1160         default:                        SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid value");             break; //LCOV_EXCL_LINE
1161         }
1162
1163         return STT_ERROR_NONE;
1164 }
1165
1166 int stt_get_error_message(stt_h stt, char** err_msg)
1167 {
1168         stt_client_s* client = NULL;
1169         int temp = __stt_check_precondition(stt, &client);
1170         if (STT_ERROR_NONE != temp)
1171                 return temp;
1172
1173         RETVM_IF(NULL == err_msg, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1174         RETVM_IF(false == g_err_callback_status, STT_ERROR_OPERATION_FAILED, "[ERROR] This callback should be called during an err_callback");
1175
1176         if (NULL != client->err_msg) {
1177                 *err_msg = strdup(client->err_msg);
1178                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Error msg (%s)", *err_msg);
1179         } else {
1180                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Error msg (NULL)"); //LCOV_EXCL_LINE
1181         }
1182
1183         SLOG(LOG_INFO, TAG_STTC, "=====");
1184         SLOG(LOG_DEBUG, TAG_STTC, " ");
1185
1186         return STT_ERROR_NONE;
1187 }
1188
1189 int stt_is_recognition_type_supported(stt_h stt, const char* type, bool* support)
1190 {
1191         stt_client_s* client = NULL;
1192         int temp = __stt_check_precondition(stt, &client);
1193         if (STT_ERROR_NONE != temp)
1194                 return temp;
1195
1196         RETVM_IF(NULL == type || NULL == support, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1197         RETVM_IF(client->current_state != STT_STATE_READY, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
1198
1199         int ret = -1;
1200         int count = 0;
1201         while (0 != ret) {
1202                 ret = stt_dbus_request_is_recognition_type_supported(client->uid, type, support);
1203                 if (0 != ret) {
1204                         //LCOV_EXCL_START
1205                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
1206                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get recognition type supported : %s", __stt_get_error_code(ret));
1207                                 return ret;
1208                         }
1209                         count++;
1210                         //LCOV_EXCL_STOP
1211                 } else {
1212                         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] recognition type is %s", *support ? "true " : "false");
1213                         break;
1214                 }
1215         }
1216
1217         return STT_ERROR_NONE;
1218 }
1219
1220 int stt_get_audio_format(stt_h stt, stt_audio_type_e* type, int* rate, int* num_of_channels)
1221 {
1222         stt_client_s* client = NULL;
1223         RETV_IF(false == is_stt_feature_enabled(), STT_ERROR_NOT_SUPPORTED);
1224         RETV_IF(STT_ERROR_NONE != __stt_check_handle(stt, &client), STT_ERROR_INVALID_PARAMETER);
1225         RETVM_IF(NULL == type || NULL == rate || NULL == num_of_channels, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1226         RETVM_IF(client->current_state != STT_STATE_READY, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
1227
1228         int ret = STT_ERROR_OPERATION_FAILED;
1229         int count = 0;
1230         while (STT_ERROR_NONE != ret) {
1231                 ret = stt_dbus_request_get_audio_format(client->uid, type, rate, num_of_channels);
1232                 if (STT_ERROR_NONE != ret) {
1233                         //LCOV_EXCL_START
1234                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
1235                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get audio format : %d/%s", ret, get_error_message(ret));
1236                                 return ret;
1237                         }
1238                         count++;
1239                         //LCOV_EXCL_STOP
1240                 } else {
1241                         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Audio format: type(%d), rate(%d), number of channels(%d)",
1242                                  *type, *rate, *num_of_channels);
1243                         break;
1244                 }
1245         }
1246
1247         return STT_ERROR_NONE;
1248 }
1249
1250 int stt_set_silence_detection(stt_h stt, stt_option_silence_detection_e type)
1251 {
1252         stt_client_s* client = NULL;
1253         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_READY);
1254         if (STT_ERROR_NONE != temp)
1255                 return temp;
1256
1257         SLOG(LOG_INFO, TAG_STTC, "===== Set silence detection, supported(%d), type(%d)", client->silence_supported, type);
1258
1259         if (true == client->silence_supported) {
1260                 if (type >= STT_OPTION_SILENCE_DETECTION_FALSE && type <= STT_OPTION_SILENCE_DETECTION_AUTO) {
1261                         client->silence = type;
1262                 } else {
1263                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Type is invalid");
1264                         return STT_ERROR_INVALID_PARAMETER;
1265                 }
1266         } else {
1267                 return STT_ERROR_NOT_SUPPORTED_FEATURE;
1268         }
1269
1270         return STT_ERROR_NONE;
1271 }
1272
1273 int stt_set_start_sound(stt_h stt, const char* filename)
1274 {
1275
1276         stt_client_s* client = NULL;
1277         int temp = __stt_check_precondition(stt, &client);
1278         if (STT_ERROR_NONE != temp)
1279                 return temp;
1280
1281         RETVM_IF(NULL == filename, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1282         RETVM_IF(0 != access(filename, F_OK), STT_ERROR_INVALID_PARAMETER, "[ERROR] File does not exist");
1283         RETVM_IF(STT_STATE_READY != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
1284
1285         SLOG(LOG_INFO, TAG_STTC, "===== STT SET START SOUND");
1286
1287         int ret = -1;
1288         int count = 0;
1289         while (0 != ret) {
1290                 ret = stt_dbus_request_set_start_sound(client->uid, filename);
1291                 if (0 != ret) {
1292                         //LCOV_EXCL_START
1293                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
1294                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to set start sound : %s", __stt_get_error_code(ret));
1295                                 return ret;
1296                         }
1297                         count++;
1298                         //LCOV_EXCL_STOP
1299                 } else {
1300                         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Set start sound : %s", filename);
1301                         break;
1302                 }
1303         }
1304
1305         return STT_ERROR_NONE;
1306 }
1307
1308 int stt_unset_start_sound(stt_h stt)
1309 {
1310         stt_client_s* client = NULL;
1311         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_READY);
1312         if (STT_ERROR_NONE != temp)
1313                 return temp;
1314
1315         SLOG(LOG_INFO, TAG_STTC, "===== STT UNSET START SOUND");
1316
1317         int ret = -1;
1318         int count = 0;
1319         while (0 != ret) {
1320                 ret = stt_dbus_request_unset_start_sound(client->uid);
1321                 if (0 != ret) {
1322                         //LCOV_EXCL_START
1323                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
1324                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to unset start sound : %s", __stt_get_error_code(ret));
1325                                 return ret;
1326                         }
1327                         count++;
1328                         //LCOV_EXCL_STOP
1329                 } else {
1330                         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Unset start sound");
1331                         break;
1332                 }
1333         }
1334
1335         return STT_ERROR_NONE;
1336 }
1337
1338 int stt_set_stop_sound(stt_h stt, const char* filename)
1339 {
1340
1341         stt_client_s* client = NULL;
1342         int temp = __stt_check_precondition(stt, &client);
1343         if (STT_ERROR_NONE != temp)
1344                 return temp;
1345
1346         RETVM_IF(NULL == filename, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1347         RETVM_IF(0 != access(filename, F_OK), STT_ERROR_INVALID_PARAMETER, "[ERROR] File does not exist");
1348         RETVM_IF(STT_STATE_READY != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
1349
1350         SLOG(LOG_INFO, TAG_STTC, "===== STT SET STOP SOUND");
1351
1352         int ret = -1;
1353         int count = 0;
1354         while (0 != ret) {
1355                 ret = stt_dbus_request_set_stop_sound(client->uid, filename);
1356                 if (0 != ret) {
1357                         //LCOV_EXCL_START
1358                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
1359                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to set stop sound : %s", __stt_get_error_code(ret));
1360                                 return ret;
1361                         }
1362                         count++;
1363                         //LCOV_EXCL_STOP
1364                 } else {
1365                         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Set stop sound : %s", filename);
1366                         break;
1367                 }
1368         }
1369
1370         return STT_ERROR_NONE;
1371 }
1372
1373 int stt_unset_stop_sound(stt_h stt)
1374 {
1375         stt_client_s* client = NULL;
1376         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_READY);
1377         if (STT_ERROR_NONE != temp)
1378                 return temp;
1379
1380         SLOG(LOG_INFO, TAG_STTC, "===== STT UNSET STOP SOUND");
1381
1382         int ret = -1;
1383         int count = 0;
1384         while (0 != ret) {
1385                 ret = stt_dbus_request_unset_stop_sound(client->uid);
1386                 if (0 != ret) {
1387                         //LCOV_EXCL_START
1388                         if (false == __stt_is_necessary_to_retry_dbus_request(count, ret)) {
1389                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to unset stop sound : %s", __stt_get_error_code(ret));
1390                                 return ret;
1391                         }
1392                         count++;
1393                         //LCOV_EXCL_STOP
1394                 } else {
1395                         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Unset stop sound");
1396                         break;
1397                 }
1398         }
1399
1400         return STT_ERROR_NONE;
1401 }
1402
1403 int stt_start(stt_h stt, const char* language, const char* type)
1404 {
1405         stt_client_s* client = NULL;
1406         int tmp = __stt_check_precondition_with_state(stt, &client, STT_STATE_READY);
1407         if (STT_ERROR_NONE != tmp)
1408                 return tmp;
1409
1410         RETVM_IF(STT_INTERNAL_STATE_NONE != client->internal_state, STT_ERROR_IN_PROGRESS_TO_RECORDING, "[ERROR] Invalid State : Internal state is NOT none : %d", client->current_state);
1411         SLOG(LOG_INFO, TAG_STTC, "===== STT START");
1412
1413         int ret = -1;
1414         char appid[1024] = {0, };
1415         ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid) - 1);
1416
1417         if ((AUL_R_OK != ret) || (0 == strlen(appid))) {
1418                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get application ID"); //LCOV_EXCL_LINE
1419         } else {
1420                 SLOG(LOG_DEBUG, TAG_STTC, "[DEBUG] Current app id is %s", appid);
1421         }
1422
1423         const char* temp = NULL;
1424         if (NULL == language) {
1425                 temp = "default";
1426         } else {
1427                 temp = language;
1428         }
1429
1430         RETVM_IF(NULL == temp, STT_ERROR_OUT_OF_MEMORY, "[ERROR] Fail to allocate memory");
1431
1432         if (true == client->credential_needed && NULL == client->credential) {
1433                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Do not have app credential for this engine(%s)", client->current_engine_id); //LCOV_EXCL_LINE
1434                 return STT_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
1435         }
1436
1437         client->internal_state = STT_INTERNAL_STATE_STARTING;
1438         ret = stt_dbus_request_start(client->uid, temp, type, client->silence, appid, client->credential, client->audio_id);
1439         if (0 != ret) {
1440                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to start : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1441                 client->internal_state = STT_INTERNAL_STATE_NONE;
1442         } else {
1443                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Start is successful but not done");
1444                 client->is_streaming = false;
1445         }
1446
1447         SLOG(LOG_INFO, TAG_STTC, "=====");
1448         SLOG(LOG_DEBUG, TAG_STTC, " ");
1449
1450         return ret;
1451 }
1452
1453 int stt_stop(stt_h stt)
1454 {
1455         stt_client_s* client = NULL;
1456         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_RECORDING);
1457         if (STT_ERROR_NONE != temp)
1458                 return temp;
1459
1460         SLOG(LOG_INFO, TAG_STTC, "===== STT STOP");
1461
1462         if (STT_INTERNAL_STATE_CANCELING == client->internal_state) {
1463                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is CANCELING : %d", client->internal_state);
1464                 return STT_ERROR_IN_PROGRESS_TO_READY;
1465         } else if (STT_INTERNAL_STATE_STOPPING == client->internal_state) {
1466                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is STOPPING : %d", client->internal_state);
1467                 return STT_ERROR_IN_PROGRESS_TO_PROCESSING;
1468         }
1469
1470         if (client->is_streaming) {
1471                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Audio streaming is activated.");
1472                 return STT_ERROR_OPERATION_FAILED;
1473         }
1474
1475         client->internal_state = STT_INTERNAL_STATE_STOPPING;
1476         int ret = stt_dbus_request_stop(client->uid);
1477         if (0 != ret) {
1478                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to stop : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1479                 client->internal_state = STT_INTERNAL_STATE_NONE;
1480         } else {
1481                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Stop is successful but not done");
1482         }
1483
1484         SLOG(LOG_DEBUG, TAG_STTC, "=====");
1485         SLOG(LOG_DEBUG, TAG_STTC, " ");
1486
1487         return ret;
1488 }
1489
1490 int stt_start_audio_streaming(stt_h stt, const char* language, const char* type)
1491 {
1492         stt_client_s* client = NULL;
1493         RETV_IF(false == is_stt_feature_enabled(), STT_ERROR_NOT_SUPPORTED);
1494         RETV_IF(STT_ERROR_NONE != __stt_check_handle(stt, &client), STT_ERROR_INVALID_PARAMETER);
1495         RETVM_IF(NULL == type, STT_ERROR_INVALID_PARAMETER, "[ERROR] type is NULL");
1496
1497         RETVM_IF(STT_STATE_READY != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not READY", client->current_state);
1498
1499         RETVM_IF(STT_INTERNAL_STATE_NONE != client->internal_state, STT_ERROR_IN_PROGRESS_TO_RECORDING, "[ERROR] Invalid State : Internal state is NOT none : %d", client->current_state);
1500         SLOG(LOG_INFO, TAG_STTC, "===== STT START AUDIO STREAMING");
1501
1502         int ret = STT_ERROR_NONE;
1503         char appid[1024] = {0, };
1504         ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid) - 1);
1505
1506         if ((AUL_R_OK != ret) || (0 == strlen(appid))) {
1507                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get application ID"); //LCOV_EXCL_LINE
1508         } else {
1509                 SLOG(LOG_DEBUG, TAG_STTC, "[DEBUG] Current app id is %s", appid);
1510         }
1511
1512         const char* language_param = NULL == language ? "default" : language;
1513         if (true == client->credential_needed && NULL == client->credential) {
1514                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Do not have app credential for this engine(%s)", client->current_engine_id); //LCOV_EXCL_LINE
1515                 return STT_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
1516         }
1517
1518         client->internal_state = STT_INTERNAL_STATE_STARTING;
1519         ret = stt_dbus_request_start_audio_streaming(client->uid, language_param, type, client->silence, appid, client->credential, client->audio_id);
1520         if (0 != ret) {
1521                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to start : ret(%d/%s)", ret, get_error_message(ret)); //LCOV_EXCL_LINE
1522                 client->internal_state = STT_INTERNAL_STATE_NONE;
1523                 return ret;
1524         }
1525
1526         client->is_streaming = true;
1527         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Start audio streaming is successful but not done");
1528         SLOG(LOG_INFO, TAG_STTC, "=====");
1529         return STT_ERROR_NONE;
1530 }
1531
1532 int stt_send_audio_streaming(stt_h stt, const char* data, size_t data_size)
1533 {
1534         stt_client_s* client = NULL;
1535         RETV_IF(false == is_stt_feature_enabled(), STT_ERROR_NOT_SUPPORTED);
1536         RETV_IF(STT_ERROR_NONE != __stt_check_handle(stt, &client), STT_ERROR_INVALID_PARAMETER);
1537         RETVM_IF(NULL == data, STT_ERROR_INVALID_PARAMETER, "[ERROR] data is NULL");
1538         RETVM_IF(0 == data_size, STT_ERROR_INVALID_PARAMETER, "[ERROR] data size is 0");
1539
1540         RETVM_IF(STT_STATE_RECORDING != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not RECORDING", client->current_state);
1541
1542         SLOG(LOG_INFO, TAG_STTC, "===== STT SEND AUDIO STREAMING");
1543
1544         if (STT_INTERNAL_STATE_CANCELING == client->internal_state) {
1545                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is CANCELING : %d", client->internal_state);
1546                 return STT_ERROR_IN_PROGRESS_TO_READY;
1547         } else if (STT_INTERNAL_STATE_STOPPING == client->internal_state) {
1548                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is STOPPING : %d", client->internal_state);
1549                 return STT_ERROR_IN_PROGRESS_TO_PROCESSING;
1550         }
1551
1552         if (false == client->is_streaming) {
1553                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Audio streaming is not activated.");
1554                 return STT_ERROR_OPERATION_FAILED;
1555         }
1556
1557         int ret = stt_dbus_request_send_audio_streaming(client->uid, data, data_size);
1558         if (STT_ERROR_NONE != ret) {
1559                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to start : ret(%d/%s)", ret, get_error_message(ret)); //LCOV_EXCL_LINE
1560                 return ret;
1561         }
1562
1563         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Send audio streaming is successful");
1564         SLOG(LOG_INFO, TAG_STTC, "=====");
1565         return STT_ERROR_NONE;
1566 }
1567
1568 int stt_stop_audio_streaming(stt_h stt)
1569 {
1570         stt_client_s* client = NULL;
1571         RETV_IF(false == is_stt_feature_enabled(), STT_ERROR_NOT_SUPPORTED);
1572         RETV_IF(STT_ERROR_NONE != __stt_check_handle(stt, &client), STT_ERROR_INVALID_PARAMETER);
1573         RETVM_IF(STT_STATE_RECORDING != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not RECORDING", client->current_state);
1574
1575         SLOG(LOG_INFO, TAG_STTC, "===== STT STOP AUDIO STREAMING");
1576
1577         if (STT_INTERNAL_STATE_CANCELING == client->internal_state) {
1578                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is CANCELING : %d", client->internal_state);
1579                 return STT_ERROR_IN_PROGRESS_TO_READY;
1580         } else if (STT_INTERNAL_STATE_STOPPING == client->internal_state) {
1581                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is STOPPING : %d", client->internal_state);
1582                 return STT_ERROR_IN_PROGRESS_TO_PROCESSING;
1583         }
1584
1585         if (false == client->is_streaming) {
1586                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Audio streaming is not activated.");
1587                 return STT_ERROR_OPERATION_FAILED;
1588         }
1589
1590         client->internal_state = STT_INTERNAL_STATE_STOPPING;
1591         int ret = stt_dbus_request_stop_audio_streaming(client->uid);
1592         if (0 != ret) {
1593                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to stop : ret(%d/%s)", ret, get_error_message(ret)); //LCOV_EXCL_LINE
1594                 client->internal_state = STT_INTERNAL_STATE_NONE;
1595                 return ret;
1596         }
1597
1598         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Stop is successful but not done");
1599         SLOG(LOG_DEBUG, TAG_STTC, "=====");
1600         return STT_ERROR_NONE;
1601 }
1602
1603 int stt_cancel(stt_h stt)
1604 {
1605         stt_client_s* client = NULL;
1606         int temp = __stt_check_precondition(stt, &client);
1607         if (STT_ERROR_NONE != temp)
1608                 return temp;
1609
1610         SLOG(LOG_INFO, TAG_STTC, "===== STT CANCEL");
1611
1612         /* check state */
1613         if (STT_STATE_RECORDING != client->current_state && STT_STATE_PROCESSING != client->current_state) {
1614                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid state : Current state(%d) is 'Ready'", client->current_state); //LCOV_EXCL_LINE
1615                 return STT_ERROR_INVALID_STATE;
1616         }
1617
1618         if (STT_INTERNAL_STATE_STOPPING == client->internal_state) {
1619                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is STOPPING : %d", client->internal_state);
1620                 return STT_ERROR_IN_PROGRESS_TO_PROCESSING;
1621         } else if (STT_INTERNAL_STATE_CANCELING == client->internal_state) {
1622                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is CANCELING : %d", client->internal_state);
1623                 return STT_ERROR_IN_PROGRESS_TO_READY;
1624         }
1625
1626         client->internal_state = STT_INTERNAL_STATE_CANCELING;
1627         int ret = stt_dbus_request_cancel(client->uid);
1628         if (0 != ret) {
1629                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to cancel : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1630                 client->internal_state = STT_INTERNAL_STATE_NONE;
1631         } else {
1632                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Cancel is successful but not done");
1633         }
1634
1635         SLOG(LOG_DEBUG, TAG_STTC, "=====");
1636         SLOG(LOG_DEBUG, TAG_STTC, " ");
1637
1638         return ret;
1639 }
1640
1641 //LCOV_EXCL_START
1642 int __stt_cb_set_volume(unsigned int uid, float volume)
1643 {
1644         stt_client_s* client = NULL;
1645
1646         client = stt_client_get_by_uid(uid);
1647         if (NULL == client) {
1648                 SLOG(LOG_ERROR, TAG_STTC, "Handle is NOT valid");
1649                 return STT_ERROR_INVALID_PARAMETER;
1650         }
1651
1652         if (STT_STATE_RECORDING != client->current_state) {
1653                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Invalid state : NO 'Recording' state, cur(%d)", client->current_state);
1654                 return STT_ERROR_INVALID_STATE;
1655         }
1656
1657         g_volume_db = volume;
1658         SLOG(LOG_INFO, TAG_STTC, "Set volume (%f)", g_volume_db);
1659
1660         return 0;
1661 }
1662 //LCOV_EXCL_STOP
1663
1664 int stt_get_recording_volume(stt_h stt, float* volume)
1665 {
1666         stt_client_s* client = NULL;
1667         int temp = __stt_check_precondition(stt, &client);
1668         if (STT_ERROR_NONE != temp)
1669                 return temp;
1670
1671         RETVM_IF(NULL == volume, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1672         RETVM_IF(STT_STATE_RECORDING != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Invalid state : NO 'Recording' state, cur(%d)", client->current_state);
1673
1674         *volume = g_volume_db;
1675
1676         SLOG(LOG_INFO, TAG_STTC, "Get recording volume (%f)", *volume);
1677
1678         return STT_ERROR_NONE;
1679 }
1680
1681 //LCOV_EXCL_START
1682 bool __stt_result_time_cb(int index, int event, const char* text, long start_time, long end_time, void* user_data)
1683 {
1684         stt_client_s* client = (stt_client_s*)user_data;
1685
1686         /* check handle */
1687         if (NULL == client) {
1688                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
1689                 return EINA_FALSE;
1690         }
1691
1692         if (NULL != client->result_time_cb) {
1693                 SLOG(LOG_INFO, TAG_STTC, "(%d) event(%d) text(%s) start(%ld) end(%ld)",
1694                         index, event, text, start_time, end_time);
1695                 client->result_time_cb(client->stt, index, (stt_result_time_event_e)event,
1696                         text, start_time, end_time, client->result_time_user_data);
1697         } else {
1698                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Callback is NULL");
1699                 return false;
1700         }
1701
1702         return true;
1703 }
1704 //LCOV_EXCL_STOP
1705
1706 int stt_foreach_detailed_result(stt_h stt, stt_result_time_cb callback, void* user_data)
1707 {
1708         stt_client_s* client = NULL;
1709         int temp = __stt_check_precondition(stt, &client);
1710         if (STT_ERROR_NONE != temp)
1711                 return temp;
1712
1713         SLOG(LOG_INFO, TAG_STTC, "===== STT FOREACH DETAILED RESULT");
1714         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1715
1716         client->result_time_cb = callback;
1717         client->result_time_user_data = user_data;
1718
1719         int ret = -1;
1720         ret = stt_config_mgr_foreach_time_info(__stt_result_time_cb, client);
1721         ret = __stt_convert_config_error_code(ret);
1722         if (0 != ret) {
1723                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to foreach time info : %s", __stt_get_error_code(ret)); //LCOV_EXCL_LINE
1724         }
1725
1726         client->result_time_cb = NULL;
1727         client->result_time_user_data = NULL;
1728
1729         SLOG(LOG_INFO, TAG_STTC, "=====");
1730         SLOG(LOG_DEBUG, TAG_STTC, " ");
1731
1732         return ret;
1733 }
1734
1735 static void __stt_notify_error(void *data)
1736 {
1737         stt_client_s* client = (stt_client_s*)data;
1738
1739         SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error from sttd");
1740         RETM_IF(NULL == client, "[ERROR] Fail to notify error : A handle is not valid");
1741
1742         if (NULL == stt_client_get_by_uid(client->uid))
1743                 return;
1744
1745         if (NULL != client->error_cb) {
1746                 stt_client_use_callback(client);
1747                 g_err_callback_status = true;
1748                 client->error_cb(client->stt, client->reason, client->error_user_data);
1749                 g_err_callback_status = false;
1750                 stt_client_not_use_callback(client);
1751                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is called : reason [%d]", client->reason);
1752         } else {
1753                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null"); //LCOV_EXCL_LINE
1754         }
1755 }
1756
1757 int __stt_cb_error(unsigned int uid, int reason, char* err_msg)
1758 {
1759         if (-1 == uid) {
1760                 GList* client_list = NULL;
1761                 client_list = stt_client_get_client_list();
1762
1763                 GList *iter = NULL;
1764                 stt_client_s *data = NULL;
1765
1766                 if (g_list_length(client_list) > 0) {
1767                         /* Get a first item */
1768                         iter = g_list_first(client_list);
1769
1770                         while (NULL != iter) {
1771                                 data = iter->data;
1772
1773                                 data->reason = reason;
1774                                 data->internal_state = STT_INTERNAL_STATE_NONE;
1775
1776                                 free(data->err_msg);
1777                                 data->err_msg = NULL;
1778
1779                                 if (NULL != err_msg)
1780                                         data->err_msg = strdup(err_msg);
1781
1782                                 SLOG(LOG_INFO, TAG_STTC, "internal state is initialized to 0");
1783
1784                                 if (NULL != data->error_cb) {
1785                                         ecore_main_loop_thread_safe_call_async(__stt_notify_error, data);
1786                                 } else {
1787                                         SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null");
1788                                 }
1789
1790                                 if (STT_ERROR_SERVICE_RESET == reason) {
1791                                         SLOG(LOG_WARN, TAG_STTC, "[WARNING] Service reset");
1792
1793                                         data->current_state = STT_STATE_CREATED;
1794                                         if (0 != stt_prepare(data->stt)) {
1795                                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to prepare");
1796                                         }
1797                                 }
1798
1799                                 /* Next item */
1800                                 iter = g_list_next(iter);
1801                         }
1802                 }
1803         } else {
1804                 //LCOV_EXCL_START
1805                 stt_client_s* client = stt_client_get_by_uid(uid);
1806                 if (NULL == client) {
1807                         SLOG(LOG_ERROR, TAG_STTC, "Handle not found"); //LCOV_EXCL_LINE
1808                         return -1;
1809                 }
1810
1811                 client->reason = reason;
1812                 client->internal_state = STT_INTERNAL_STATE_NONE;
1813
1814                 free(client->err_msg);
1815                 client->err_msg = NULL;
1816
1817                 if (NULL != err_msg)
1818                         client->err_msg = strdup(err_msg);
1819
1820                 SLOG(LOG_INFO, TAG_STTC, "internal state is initialized to 0");
1821
1822                 if (NULL != client->error_cb) {
1823                         ecore_main_loop_thread_safe_call_async(__stt_notify_error, client);
1824                 } else {
1825                         SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null");
1826                 }
1827
1828                 if (STT_ERROR_SERVICE_RESET == reason) {
1829                         SLOG(LOG_WARN, TAG_STTC, "[WARNING] Service reset"); //LCOV_EXCL_LINE
1830
1831                         client->current_state = STT_STATE_CREATED;
1832                         if (0 != stt_prepare(client->stt)) {
1833                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to prepare"); //LCOV_EXCL_LINE
1834                         }
1835                 }
1836                 //LCOV_EXCL_STOP
1837         }
1838
1839         return 0;
1840 }
1841
1842 static void __stt_notify_state_changed(void *data)
1843 {
1844         stt_client_s* client = (stt_client_s*)data;
1845
1846         /* check handle */
1847         RETM_IF(NULL == client, "[ERROR] Fail to notify error : A handle is not valid");
1848         RET_IF(NULL == stt_client_get_by_uid(client->uid));
1849
1850         if (STT_INTERNAL_STATE_STARTING == client->internal_state && STT_STATE_RECORDING == client->current_state) {
1851                 client->internal_state = STT_INTERNAL_STATE_NONE;
1852                 SLOG(LOG_INFO, TAG_STTC, "Internal state change to NONE");
1853         } else if (STT_INTERNAL_STATE_STOPPING == client->internal_state && STT_STATE_PROCESSING == client->current_state) {
1854                 client->internal_state = STT_INTERNAL_STATE_NONE;
1855                 SLOG(LOG_INFO, TAG_STTC, "Internal state change to NONE");
1856         } else if (STT_INTERNAL_STATE_CANCELING == client->internal_state && STT_STATE_READY == client->current_state) {
1857                 client->internal_state = STT_INTERNAL_STATE_NONE;
1858                 SLOG(LOG_INFO, TAG_STTC, "Internal state change to NONE");
1859         }
1860
1861         if (NULL != client->state_changed_cb) {
1862                 stt_client_use_callback(client);
1863                 client->state_changed_cb(client->stt, client->before_state,
1864                         client->current_state, client->state_changed_user_data);
1865                 stt_client_not_use_callback(client);
1866                 SLOG(LOG_INFO, TAG_STTC, "State changed callback is called, State(%d)", client->current_state);
1867         } else {
1868                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null, State(%d)", client->current_state); //LCOV_EXCL_LINE
1869         }
1870
1871         return;
1872 }
1873
1874 int __stt_cb_result(unsigned int uid, int event, char** data, int data_count, const char* msg)
1875 {
1876         stt_client_s* client = stt_client_get_by_uid(uid);
1877         RETVM_IF(NULL == client, STT_ERROR_INVALID_PARAMETER, "Handle is NOT valid. uid(%u)", uid);
1878
1879         if (NULL != msg)
1880                 SECURE_SLOG(LOG_INFO, TAG_STTC, "Recognition Result Message = %s", msg);
1881
1882         for (int i = 0; i < data_count; i++) {
1883                 if (NULL != data[i])
1884                         SECURE_SLOG(LOG_INFO, TAG_STTC, "Recognition Result[%d] = %s", i, data[i]);
1885         }
1886
1887         if (NULL != client->recognition_result_cb) {
1888                 stt_client_use_callback(client);
1889                 client->recognition_result_cb(client->stt, event, (const char**)data, data_count,
1890                         msg, client->recognition_result_user_data);
1891                 stt_client_not_use_callback(client);
1892                 SLOG(LOG_INFO, TAG_STTC, "client recognition result callback called");
1893         } else {
1894                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] User recognition result callback is NULL");
1895         }
1896
1897         stt_config_mgr_remove_time_info_file();
1898
1899         if (STT_RESULT_EVENT_FINAL_RESULT == event || STT_RESULT_EVENT_ERROR == event) {
1900                 client->before_state = client->current_state;
1901                 client->current_state = STT_STATE_READY;
1902
1903                 if (NULL != client->state_changed_cb) {
1904                         ecore_main_loop_thread_safe_call_async(__stt_notify_state_changed, client);
1905                 } else {
1906                         SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null"); //LCOV_EXCL_LINE
1907                 }
1908         }
1909
1910         return STT_ERROR_NONE;
1911 }
1912
1913 int __stt_cb_set_state(unsigned int uid, int state)
1914 {
1915         stt_client_s* client = stt_client_get_by_uid(uid);
1916         if (NULL == client) {
1917                 SLOG(LOG_ERROR, TAG_STTC, "Handle not found"); //LCOV_EXCL_LINE
1918                 return -1;
1919         }
1920
1921         stt_state_e state_from_daemon = (stt_state_e)state;
1922
1923         if (client->current_state == state_from_daemon) {
1924                 SLOG(LOG_DEBUG, TAG_STTC, "Current state has already been %d", client->current_state);
1925                 return 0;
1926         }
1927
1928         client->before_state = client->current_state;
1929         client->current_state = state_from_daemon;
1930
1931         ecore_main_loop_thread_safe_call_async(__stt_notify_state_changed, client);
1932         return 0;
1933 }
1934
1935 //LCOV_EXCL_START
1936 static void __stt_notify_speech_status(void *data)
1937 {
1938         stt_client_s* client = (stt_client_s*)data;
1939
1940         /* check handle */
1941         RETM_IF(NULL == client, "[ERROR] Fail to notify speech status : A handle is not valid");
1942         RET_IF(NULL == stt_client_get_by_uid(client->uid));
1943
1944         if (NULL != client->speech_status_cb) {
1945                 stt_client_use_callback(client);
1946                 client->speech_status_cb(client->stt, client->speech_status, client->speech_status_user_data);
1947                 stt_client_not_use_callback(client);
1948                 SLOG(LOG_INFO, TAG_STTC, "Speech status callback is called"); //LCOV_EXCL_LINE
1949         } else {
1950                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Speech status callback is null"); //LCOV_EXCL_LINE
1951         }
1952
1953         return;
1954 }
1955
1956 int __stt_cb_speech_status(unsigned int uid, int status)
1957 {
1958         stt_client_s* client = stt_client_get_by_uid(uid);
1959         if (NULL == client) {
1960                 SLOG(LOG_ERROR, TAG_STTC, "Handle not found"); //LCOV_EXCL_LINE
1961                 return -1;
1962         }
1963
1964         client->speech_status = status;
1965
1966         ecore_main_loop_thread_safe_call_async(__stt_notify_speech_status, client);
1967         return 0;
1968 }
1969 //LCOV_EXCL_STOP
1970
1971 int stt_set_recognition_result_cb(stt_h stt, stt_recognition_result_cb callback, void* user_data)
1972 {
1973         stt_client_s* client = NULL;
1974         int temp = __stt_check_precondition(stt, &client);
1975         if (STT_ERROR_NONE != temp)
1976                 return temp;
1977
1978         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
1979         RETVM_IF(STT_STATE_CREATED != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created'", client->current_state);
1980
1981         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set recognition result cb");
1982
1983         client->recognition_result_cb = callback;
1984         client->recognition_result_user_data = user_data;
1985
1986         return 0;
1987 }
1988
1989 int stt_unset_recognition_result_cb(stt_h stt)
1990 {
1991         stt_client_s* client = NULL;
1992         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
1993         if (STT_ERROR_NONE != temp)
1994                 return temp;
1995
1996         SLOG(LOG_INFO, TAG_STTC, "[INFO] Unset recognition result cb");
1997
1998         client->recognition_result_cb = NULL;
1999         client->recognition_result_user_data = NULL;
2000
2001         return 0;
2002 }
2003
2004 int stt_set_state_changed_cb(stt_h stt, stt_state_changed_cb callback, void* user_data)
2005 {
2006         stt_client_s* client = NULL;
2007         int temp = __stt_check_precondition(stt, &client);
2008         if (STT_ERROR_NONE != temp)
2009                 return temp;
2010
2011         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2012         RETVM_IF(STT_STATE_CREATED != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created'", client->current_state);
2013
2014         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set state changed cb");
2015
2016         client->state_changed_cb = callback;
2017         client->state_changed_user_data = user_data;
2018
2019         return 0;
2020 }
2021
2022 int stt_unset_state_changed_cb(stt_h stt)
2023 {
2024         stt_client_s* client = NULL;
2025         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
2026         if (STT_ERROR_NONE != temp)
2027                 return temp;
2028
2029         SLOG(LOG_INFO, TAG_STTC, "[INFO] Unset state changed cb");
2030
2031         client->state_changed_cb = NULL;
2032         client->state_changed_user_data = NULL;
2033
2034         return 0;
2035 }
2036
2037 int stt_set_error_cb(stt_h stt, stt_error_cb callback, void* user_data)
2038 {
2039         stt_client_s* client = NULL;
2040         int temp = __stt_check_precondition(stt, &client);
2041         if (STT_ERROR_NONE != temp)
2042                 return temp;
2043
2044         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2045         RETVM_IF(STT_STATE_CREATED != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created'", client->current_state);
2046
2047         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set error cb");
2048
2049         client->error_cb = callback;
2050         client->error_user_data = user_data;
2051
2052         return 0;
2053 }
2054
2055 int stt_unset_error_cb(stt_h stt)
2056 {
2057         stt_client_s* client = NULL;
2058         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
2059         if (STT_ERROR_NONE != temp)
2060                 return temp;
2061
2062         SLOG(LOG_INFO, TAG_STTC, "[INFO] Unset error cb");
2063
2064         client->error_cb = NULL;
2065         client->error_user_data = NULL;
2066
2067         return 0;
2068 }
2069
2070 int stt_set_default_language_changed_cb(stt_h stt, stt_default_language_changed_cb callback, void* user_data)
2071 {
2072         stt_client_s* client = NULL;
2073         int temp = __stt_check_precondition(stt, &client);
2074         if (STT_ERROR_NONE != temp)
2075                 return temp;
2076
2077         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2078         RETVM_IF(STT_STATE_CREATED != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created'", client->current_state);
2079
2080         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set default language changed cb");
2081
2082         client->default_lang_changed_cb = callback;
2083         client->default_lang_changed_user_data = user_data;
2084
2085         return 0;
2086 }
2087
2088 int stt_unset_default_language_changed_cb(stt_h stt)
2089 {
2090         stt_client_s* client = NULL;
2091         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
2092         if (STT_ERROR_NONE != temp)
2093                 return temp;
2094
2095         SLOG(LOG_INFO, TAG_STTC, "[INFO] Unset default language changed cb");
2096
2097         client->default_lang_changed_cb = NULL;
2098         client->default_lang_changed_user_data = NULL;
2099
2100         return 0;
2101 }
2102
2103 int stt_set_engine_changed_cb(stt_h stt, stt_engine_changed_cb callback, void* user_data)
2104 {
2105         stt_client_s* client = NULL;
2106         int temp = __stt_check_precondition(stt, &client);
2107         if (STT_ERROR_NONE != temp)
2108                 return temp;
2109
2110         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2111         RETVM_IF(STT_STATE_CREATED != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created'", client->current_state);
2112
2113         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set engine changed cb");
2114
2115         client->engine_changed_cb = callback;
2116         client->engine_changed_user_data = user_data;
2117
2118         return 0;
2119 }
2120
2121 int stt_unset_engine_changed_cb(stt_h stt)
2122 {
2123         stt_client_s* client = NULL;
2124         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
2125         if (STT_ERROR_NONE != temp)
2126                 return temp;
2127
2128         SLOG(LOG_INFO, TAG_STTC, "[INFO] Unset engine changed cb");
2129
2130         client->engine_changed_cb = NULL;
2131         client->engine_changed_user_data = NULL;
2132
2133         return 0;
2134 }
2135
2136 int stt_set_speech_status_cb(stt_h stt, stt_speech_status_cb callback, void* user_data)
2137 {
2138         stt_client_s* client = NULL;
2139         int temp = __stt_check_precondition(stt, &client);
2140         if (STT_ERROR_NONE != temp)
2141                 return temp;
2142
2143         RETVM_IF(NULL == callback, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2144         RETVM_IF(STT_STATE_CREATED != client->current_state, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created'", client->current_state);
2145
2146         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set speech status cb");
2147
2148         client->speech_status_cb = callback;
2149         client->speech_status_user_data = user_data;
2150
2151         return 0;
2152 }
2153
2154 int stt_unset_speech_status_cb(stt_h stt)
2155 {
2156         stt_client_s* client = NULL;
2157         int temp = __stt_check_precondition_with_state(stt, &client, STT_STATE_CREATED);
2158         if (STT_ERROR_NONE != temp)
2159                 return temp;
2160
2161         SLOG(LOG_INFO, TAG_STTC, "[INFO] Unset speech status cb");
2162
2163         client->speech_status_cb = NULL;
2164         client->speech_status_user_data = NULL;
2165
2166         return 0;
2167 }
2168
2169 //LCOV_EXCL_START
2170 int stt_start_file(stt_h stt, const char* language, const char* type, const char* filepath)
2171 {
2172         stt_client_s* client = NULL;
2173         int tmp = __stt_check_precondition(stt, &client);
2174         if (STT_ERROR_NONE != tmp)
2175                 return tmp;
2176
2177         RETVM_IF(NULL == filepath, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2178         RETVM_IF(client->current_state != STT_STATE_READY, STT_ERROR_INVALID_STATE, "[ERROR] Invalid State: Current state(%d) is not READY", client->current_state);
2179
2180         SLOG(LOG_INFO, TAG_STTC, "===== STT START FILE");
2181
2182         if (STT_INTERNAL_STATE_NONE != client->internal_state) {
2183                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is NOT none : %d", client->internal_state);
2184                 return STT_ERROR_IN_PROGRESS_TO_RECORDING;
2185         }
2186
2187         int ret = -1;
2188         char appid[1024] = {0, };
2189         ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid) - 1);
2190
2191         if ((AUL_R_OK != ret) || (0 == strlen(appid))) {
2192                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get application ID");
2193         } else {
2194                 SLOG(LOG_INFO, TAG_STTC, "[DEBUG] Current app id is %s", appid);
2195         }
2196
2197         char* temp = NULL;
2198         if (NULL == language) {
2199                 temp = strdup("default");
2200         } else {
2201                 temp = strdup(language);
2202         }
2203
2204         RETVM_IF(NULL == temp, STT_ERROR_OUT_OF_MEMORY, "[ERROR] Fail to allocate memory");
2205
2206         if (true == client->credential_needed && NULL == client->credential) {
2207                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Do not have app credential for this engine(%s)", client->current_engine_id);
2208                 free(temp);
2209                 temp = NULL;
2210                 return STT_ERROR_PERMISSION_DENIED;
2211         }
2212
2213         client->internal_state = STT_INTERNAL_STATE_STARTING;
2214         ret = stt_dbus_request_start_file(client->uid, temp, type, client->silence, appid, client->credential, filepath);
2215         if (0 != ret) {
2216                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to start file : %s", __stt_get_error_code(ret));
2217                 client->internal_state = STT_INTERNAL_STATE_NONE;
2218         } else {
2219                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Start is successful but not done");
2220         }
2221
2222         free(temp);
2223         temp = NULL;
2224
2225         SLOG(LOG_DEBUG, TAG_STTC, "=====");
2226         SLOG(LOG_DEBUG, TAG_STTC, " ");
2227
2228         return ret;
2229 }
2230
2231 int stt_cancel_file(stt_h stt)
2232 {
2233         stt_client_s* client = NULL;
2234         int temp = __stt_check_precondition(stt, &client);
2235         if (STT_ERROR_NONE != temp)
2236                 return temp;
2237
2238         SLOG(LOG_INFO, TAG_STTC, "===== STT CANCEL FILE");
2239
2240         /* check state */
2241         if (STT_STATE_RECORDING != client->current_state && STT_STATE_PROCESSING != client->current_state) {
2242                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid state : Current state(%d) is 'Ready'", client->current_state);
2243                 return STT_ERROR_INVALID_STATE;
2244         }
2245
2246         if (STT_INTERNAL_STATE_STARTING == client->internal_state) {
2247                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is STARTING : %d", client->internal_state);
2248                 return STT_ERROR_IN_PROGRESS_TO_RECORDING;
2249         } else if (STT_INTERNAL_STATE_STOPPING == client->internal_state) {
2250                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is STOPPING : %d", client->internal_state);
2251                 return STT_ERROR_IN_PROGRESS_TO_PROCESSING;
2252         } else if (STT_INTERNAL_STATE_CANCELING == client->internal_state) {
2253                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Internal state is CANCELING : %d", client->internal_state);
2254                 return STT_ERROR_IN_PROGRESS_TO_READY;
2255         }
2256
2257         client->internal_state = STT_INTERNAL_STATE_CANCELING;
2258         int ret = stt_dbus_request_cancel_file(client->uid);
2259         if (0 != ret) {
2260                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to cancel file : %s", __stt_get_error_code(ret));
2261                 client->internal_state = STT_INTERNAL_STATE_NONE;
2262         } else {
2263                 SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Cancel file is successful but not done");
2264         }
2265
2266         SLOG(LOG_DEBUG, TAG_STTC, "=====");
2267         SLOG(LOG_DEBUG, TAG_STTC, " ");
2268
2269         return ret;
2270 }
2271 //LCOV_EXCL_STOP
2272
2273 void __sound_stream_ducking_state_changed_cb(sound_stream_ducking_h stream_ducking, bool is_ducked, void *user_data)
2274 {
2275         SLOG(LOG_DEBUG, TAG_STTC, "@@@ ducking state changed cb");
2276         SLOG(LOG_DEBUG, TAG_STTC, "[Volume] is ducked : %d", is_ducked);
2277         // ducking_flag = true;
2278         return;
2279 }
2280
2281 static char* __get_ducking_stream(sound_stream_type_e stream_type)
2282 {
2283         if (SOUND_STREAM_TYPE_MEDIA == stream_type)
2284                 return "Media stream";
2285         else if (SOUND_STREAM_TYPE_SYSTEM == stream_type)
2286                 return "System stream";
2287         else if (SOUND_STREAM_TYPE_NOTIFICATION == stream_type)
2288                 return "Notification stream";
2289         else if (SOUND_STREAM_TYPE_ALARM == stream_type)
2290                 return "Alarm stream";
2291
2292         return "Non matched stream";
2293 }
2294
2295 static int __activate_ducking_sound_stream(sound_stream_type_e stream_type, sound_stream_ducking_h stream_ducking_h, double bg_volume_ratio)
2296 {
2297         bool is_ducked = false;
2298         int ret = sound_manager_is_ducked(stream_ducking_h, &is_ducked);
2299         if (is_ducked) {
2300                 SLOG(LOG_DEBUG, TAG_STTC, "[Volume] The %s is already ducked", __get_ducking_stream(stream_type));
2301         } else {
2302                 ret = sound_manager_activate_ducking(stream_ducking_h, SND_MGR_DUCKING_DURATION, bg_volume_ratio);
2303                 if (SOUND_MANAGER_ERROR_NONE != ret) {
2304                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to activate ducking for %s", __get_ducking_stream(stream_type));
2305                 } else {
2306                         SLOG(LOG_INFO, TAG_STTC, "[Volume SUCCESS] Activate ducking for %s", __get_ducking_stream(stream_type));
2307                 }
2308         }
2309         return ret;
2310 }
2311
2312 static void __change_background_volume(stt_system_volume_event_e volume_event)
2313 {
2314         double bg_volume_ratio = 0.0;
2315
2316         if (STT_SYSTEM_VOLUME_EVENT_CHANGE_FOR_FARFIELD == volume_event) {
2317                 bg_volume_ratio = STT_BG_VOLUME_RATIO_FARFIELD;
2318         } else if (STT_SYSTEM_VOLUME_EVENT_CHANGE_FOR_NEARFIELD == volume_event) {
2319                 bg_volume_ratio = STT_BG_VOLUME_RATIO_NEARFIELD;
2320         }
2321
2322         SLOG(LOG_INFO, TAG_STTC, "[Volume] volume ratio(%lf)", bg_volume_ratio);
2323
2324         if (1.0 > bg_volume_ratio) {
2325                 __activate_ducking_sound_stream(SOUND_STREAM_TYPE_MEDIA, g_media_stream_ducking, bg_volume_ratio);
2326                 __activate_ducking_sound_stream(SOUND_STREAM_TYPE_SYSTEM, g_system_stream_ducking, bg_volume_ratio);
2327                 __activate_ducking_sound_stream(SOUND_STREAM_TYPE_NOTIFICATION, g_notification_stream_ducking, bg_volume_ratio);
2328                 __activate_ducking_sound_stream(SOUND_STREAM_TYPE_ALARM, g_alarm_stream_ducking, bg_volume_ratio);
2329         }
2330 }
2331
2332 static int __deactivate_ducking_sound_stream(sound_stream_type_e stream_type, sound_stream_ducking_h stream_ducking_h)
2333 {
2334         bool is_ducked = false;
2335         int ret = sound_manager_is_ducked(stream_ducking_h, &is_ducked);
2336         if (!is_ducked) {
2337                 SLOG(LOG_DEBUG, TAG_STTC, "[Volume] The %s is already recovered from ducking", __get_ducking_stream(stream_type));
2338         } else {
2339                 ret = sound_manager_deactivate_ducking(stream_ducking_h);
2340                 if (SOUND_MANAGER_ERROR_NONE != ret) {
2341                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to deactivate ducking for %s", __get_ducking_stream(stream_type));
2342                 } else {
2343                         SLOG(LOG_INFO, TAG_STTC, "[Volume SUCCESS] Deactivate ducking for %s", __get_ducking_stream(stream_type));
2344                 }
2345         }
2346         return ret;
2347 }
2348
2349 static void __recover_background_volume()
2350 {
2351         SLOG(LOG_INFO, TAG_STTC, "[Volume] background volume recover");
2352
2353         __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_MEDIA, g_media_stream_ducking);
2354         __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_SYSTEM, g_system_stream_ducking);
2355         __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_NOTIFICATION, g_notification_stream_ducking);
2356         __deactivate_ducking_sound_stream(SOUND_STREAM_TYPE_ALARM, g_alarm_stream_ducking);
2357 }
2358
2359 int __create_ducking_handle(void)
2360 {
2361         int ret = -1;
2362         if (NULL == g_media_stream_ducking) {
2363                 ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_MEDIA, __sound_stream_ducking_state_changed_cb, NULL, &g_media_stream_ducking);
2364                 if (SOUND_MANAGER_ERROR_NONE != ret)
2365                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to create stream ducking for type media, ret(%d)", ret);
2366         } else {
2367                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for media stream is already created");
2368         }
2369
2370         if (NULL == g_system_stream_ducking) {
2371                 ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_SYSTEM, __sound_stream_ducking_state_changed_cb, NULL, &g_system_stream_ducking);
2372                 if (SOUND_MANAGER_ERROR_NONE != ret)
2373                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to create stream ducking for system type, ret(%d)", ret);
2374         } else {
2375                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for system stream is already created");
2376         }
2377
2378         if (NULL == g_notification_stream_ducking) {
2379                 ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_NOTIFICATION, __sound_stream_ducking_state_changed_cb, NULL, &g_notification_stream_ducking);
2380                 if (SOUND_MANAGER_ERROR_NONE != ret)
2381                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to create stream ducking for notification type, ret(%d)", ret);
2382         } else {
2383                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for notification stream is already created");
2384         }
2385
2386         if (NULL == g_alarm_stream_ducking) {
2387                 ret = sound_manager_create_stream_ducking(SOUND_STREAM_TYPE_ALARM, __sound_stream_ducking_state_changed_cb, NULL, &g_alarm_stream_ducking);
2388                 if (SOUND_MANAGER_ERROR_NONE != ret)
2389                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to create stream ducking for alarm type, ret(%d)", ret);
2390         } else {
2391                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for alarm stream is already created");
2392         }
2393
2394         return ret;
2395 }
2396
2397 int stt_change_system_volume(stt_h stt, stt_system_volume_event_e volume_event)
2398 {
2399         SLOG(LOG_DEBUG, TAG_STTC, "[STT] Change system volume, volume_event(%d)", volume_event);
2400
2401         stt_client_s* client = NULL;
2402         int temp = __stt_check_precondition(stt, &client);
2403         if (STT_ERROR_NONE != temp)
2404                 return temp;
2405
2406         RETVM_IF((STT_SYSTEM_VOLUME_EVENT_CHANGE_FOR_NEARFIELD > volume_event || STT_SYSTEM_VOLUME_EVENT_CHANGE_FOR_FARFIELD < volume_event),
2407                          STT_ERROR_INVALID_PARAMETER,
2408                          "[ERROR] Invalid volume event (%d)",
2409                          volume_event);
2410
2411         /* check state */
2412         if (client->current_state != STT_STATE_READY && client->current_state != STT_STATE_CREATED) {
2413                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state(%d) is not READY nor CREATED", client->current_state);
2414                 return STT_ERROR_INVALID_STATE;
2415         }
2416
2417         /* change system volume */
2418         int ret = __create_ducking_handle();
2419         if (0 != ret) {
2420                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to create volume handle");
2421         } else {
2422                 SLOG(LOG_INFO, TAG_STTC, "[DEBUG] Success to create volume handle");
2423         }
2424
2425         __change_background_volume(volume_event);
2426         return STT_ERROR_NONE;
2427 }
2428
2429 int __destroy_ducking_handle(void)
2430 {
2431         int ret = -1;
2432         if (g_media_stream_ducking) {
2433                 ret = sound_manager_destroy_stream_ducking(g_media_stream_ducking);
2434                 if (SOUND_MANAGER_ERROR_NONE != ret)
2435                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to destroy media stream ducking, ret(%d)", ret);
2436                 g_media_stream_ducking = NULL;
2437         } else {
2438                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for media stream is already created");
2439         }
2440
2441         if (g_system_stream_ducking) {
2442                 ret = sound_manager_destroy_stream_ducking(g_system_stream_ducking);
2443                 if (SOUND_MANAGER_ERROR_NONE != ret)
2444                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to destroy system stream ducking, ret(%d)", ret);
2445                 g_system_stream_ducking = NULL;
2446         } else {
2447                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for system stream is already created");
2448         }
2449
2450         if (g_notification_stream_ducking) {
2451                 ret = sound_manager_destroy_stream_ducking(g_notification_stream_ducking);
2452                 if (SOUND_MANAGER_ERROR_NONE != ret)
2453                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to destroy notification stream ducking, ret(%d)", ret);
2454                 g_notification_stream_ducking = NULL;
2455         } else {
2456                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for notification stream is already created");
2457         }
2458
2459         if (g_alarm_stream_ducking) {
2460                 ret = sound_manager_destroy_stream_ducking(g_alarm_stream_ducking);
2461                 if (SOUND_MANAGER_ERROR_NONE != ret)
2462                         SLOG(LOG_WARN, TAG_STTC, "[Volume WARNING] Fail to destroy alarm stream ducking, ret(%d)", ret);
2463                 g_alarm_stream_ducking = NULL;
2464         } else {
2465                 SLOG(LOG_INFO, TAG_STTC, "[Volume INFO] Ducking handle for alarm stream is already created");
2466         }
2467         return ret;
2468 }
2469
2470 int stt_recover_system_volume(stt_h stt)
2471 {
2472         SLOG(LOG_DEBUG, TAG_STTC, "[STT] recover system volume");
2473
2474         stt_client_s* client = NULL;
2475         int temp = __stt_check_precondition(stt, &client);
2476         if (STT_ERROR_NONE != temp)
2477                 return temp;
2478
2479         /* check state */
2480         if (client->current_state != STT_STATE_READY && client->current_state != STT_STATE_CREATED) {
2481                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state(%d) is not READY nor CREATED", client->current_state);
2482                 return STT_ERROR_INVALID_STATE;
2483         }
2484
2485         /* recover volume */
2486         __recover_background_volume();
2487         int ret = __destroy_ducking_handle();
2488         if (0 != ret) {
2489                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to destroy volume handle");
2490         } else {
2491                 SLOG(LOG_INFO, TAG_STTC, "[DEBUG] Success to destroy volume handle");
2492         }
2493
2494         return STT_ERROR_NONE;
2495 }
2496
2497 int stt_set_audio_id(stt_h stt, const char *audio_id)
2498 {
2499         stt_client_s* client = NULL;
2500         int temp = __stt_check_precondition(stt, &client);
2501         if (STT_ERROR_NONE != temp)
2502                 return temp;
2503
2504         RETVM_IF(NULL == audio_id, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2505         RETVM_IF(STT_STATE_CREATED != client->current_state && client->current_state != STT_STATE_READY, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created' or 'Ready'", client->current_state);
2506
2507         SLOG(LOG_INFO, TAG_STTC, "[INFO] Set audio ID(%s)", audio_id);
2508
2509         free(client->audio_id);
2510         client->audio_id = strdup(audio_id);
2511
2512         RETVM_IF(NULL == client->audio_id, STT_ERROR_OUT_OF_MEMORY, "[ERROR] Fail to allocate memory for saving audio id");
2513
2514         return STT_ERROR_NONE;
2515 }
2516
2517 int stt_get_audio_id(stt_h stt, char **audio_id)
2518 {
2519         stt_client_s* client = NULL;
2520         int temp = __stt_check_precondition(stt, &client);
2521         if (STT_ERROR_NONE != temp)
2522                 return temp;
2523
2524         RETVM_IF(NULL == audio_id, STT_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is NULL");
2525         RETVM_IF(STT_STATE_CREATED != client->current_state && client->current_state != STT_STATE_READY, STT_ERROR_INVALID_STATE, "[ERROR] Current state(%d) is not 'Created' or 'Ready'", client->current_state);
2526
2527         *audio_id = strdup(client->audio_id);
2528         RETVM_IF(NULL == *audio_id, STT_ERROR_OUT_OF_MEMORY, "[ERROR] Fail to allocate memory for output audio id");
2529
2530         SLOG(LOG_INFO, TAG_STTC, "[SUCCESS] Get audio ID(%s)", *audio_id);
2531
2532         return STT_ERROR_NONE;
2533 }
2534
2535 /* FIXME: This is temporal restoration. It's gonna be removed after build issue resovled. */
2536 //LCOV_EXCL_START
2537 int stt_set_audio_type(stt_h stt, const char *audio_id)
2538 {
2539         return stt_set_audio_id(stt, audio_id);
2540 }
2541
2542 int stt_get_audio_type(stt_h stt, char **audio_id)
2543 {
2544         return stt_get_audio_id(stt, audio_id);
2545 }
2546 //LCOV_EXCL_STOP