Release version 0.1.41
[platform/core/uifw/stt.git] / client / stt.c
1 /*
2 *  Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd All Rights Reserved 
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14
15 #include <sys/wait.h>
16 #include <sys/types.h> 
17 #include <unistd.h>
18 #include <Ecore.h>
19 #include <sys/stat.h>
20 #include <dirent.h>
21
22 #include "stt.h"
23 #include "stt_main.h"
24 #include "stt_client.h"
25 #include "stt_dbus.h"
26
27 #define CONNECTION_RETRY_COUNT 3
28
29 static bool g_is_daemon_started = false;
30
31 static Ecore_Timer* g_connect_timer = NULL;
32
33 static int __check_stt_daemon();
34 static Eina_Bool __stt_notify_state_changed(void *data);
35 static Eina_Bool __stt_notify_error(void *data);
36
37 int stt_create(stt_h* stt)
38 {
39         SLOG(LOG_DEBUG, TAG_STTC, "===== Create STT");
40
41         if (NULL == stt) {
42                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is null");
43                 return STT_ERROR_INVALID_PARAMETER;
44         }
45
46         if (0 == stt_client_get_size()) {
47                 if (0 != stt_dbus_open_connection()) {
48                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to open connection");
49                         return STT_ERROR_OPERATION_FAILED;
50                 }
51         }
52
53         if (0 != stt_client_new(stt)) {
54                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to create client!");
55                 return STT_ERROR_OUT_OF_MEMORY;
56         }
57
58         SLOG(LOG_DEBUG, TAG_STTC, "[Success] uid(%d)", (*stt)->handle);
59
60         SLOG(LOG_DEBUG, TAG_STTC, "=====");
61         SLOG(LOG_DEBUG, TAG_STTC, " ");
62
63         return STT_ERROR_NONE;
64 }
65
66 int stt_destroy(stt_h stt)
67 {
68         SLOG(LOG_DEBUG, TAG_STTC, "===== Destroy STT");
69
70         if (NULL == stt) {
71                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input handle is null");
72                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
73                 SLOG(LOG_DEBUG, TAG_STTC, " ");
74                 return STT_ERROR_INVALID_PARAMETER;
75         }
76         
77         stt_client_s* client = stt_client_get(stt);
78
79         /* check handle */
80         if (NULL == client) {
81                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
82                 return STT_ERROR_INVALID_PARAMETER;
83         }
84
85         /* check used callback */
86         if (0 != stt_client_get_use_callback(client)) {
87                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Cannot destroy in Callback function");
88                 return STT_ERROR_OPERATION_FAILED;
89         }
90
91         int ret = -1;
92
93         /* check state */
94         switch (client->current_state) {
95         case STT_STATE_PROCESSING:
96         case STT_STATE_RECORDING:
97         case STT_STATE_READY:
98                 ret = stt_dbus_request_finalize(client->uid);
99                 if (0 != ret) {
100                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to request finalize");
101                 }
102                 g_is_daemon_started = false;
103         case STT_STATE_CREATED:
104                 if (NULL != g_connect_timer) {
105                         SLOG(LOG_DEBUG, TAG_STTC, "Connect Timer is deleted");
106                         ecore_timer_del(g_connect_timer);
107                 }
108                 /* Free resources */
109                 stt_client_destroy(stt);
110                 break;
111         }
112
113         SLOG(LOG_DEBUG, TAG_STTC, "Success: destroy");
114
115         if (0 == stt_client_get_size()) {
116                 if (0 != stt_dbus_close_connection()) {
117                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to close connection");
118                 }
119         }
120
121         SLOG(LOG_DEBUG, TAG_STTC, "=====");
122         SLOG(LOG_DEBUG, TAG_STTC, " ");
123
124         return STT_ERROR_NONE;
125 }
126
127 static Eina_Bool __stt_connect_daemon(void *data)
128 {
129         stt_h stt = (stt_h)data;
130
131         stt_client_s* client = stt_client_get(stt);
132
133         if (NULL == client) {
134                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
135                 return STT_ERROR_INVALID_PARAMETER;
136         }
137
138         /* Send hello */
139         if (0 != stt_dbus_request_hello()) {
140                 if (false == g_is_daemon_started) {
141                         g_is_daemon_started = true;
142                         __check_stt_daemon();
143                 }
144                 return EINA_TRUE;
145         }
146
147         SLOG(LOG_DEBUG, TAG_STTC, "===== Connect daemon");
148
149         /* request initialization */
150         int ret = -1;
151         int i = 1;
152         bool silence_supported = false;
153         bool profanity_supported = false;
154         bool punctuation_supported = false;
155
156         while (1) {
157                 ret = stt_dbus_request_initialize(client->uid, &silence_supported, &profanity_supported, &punctuation_supported);
158
159                 if (STT_ERROR_ENGINE_NOT_FOUND == ret) {
160                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to initialize : STT Engine Not found");
161                         
162                         client->reason = STT_ERROR_ENGINE_NOT_FOUND;
163
164                         ecore_timer_add(0, __stt_notify_error, (void*)stt);
165
166                         return EINA_FALSE;
167
168                 } else if(0 != ret) {
169                         usleep(1);
170                         if(CONNECTION_RETRY_COUNT == i) {
171                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to initialize : TIMED OUT");
172
173                                 client->reason = STT_ERROR_TIMED_OUT;
174
175                                 ecore_timer_add(0, __stt_notify_error, (void*)stt);
176
177                                 return EINA_FALSE;
178                         }    
179                         i++;
180                 } else {
181                         /* success to connect stt-daemon */
182                         stt_client_set_option_supported(client->stt, silence_supported, profanity_supported, punctuation_supported);
183                         SLOG(LOG_DEBUG, TAG_STTC, "Supported options : silence(%s), profanity(%s), punctuation(%s)", 
184                                 silence_supported ? "true" : "false", profanity_supported ? "true" : "false", punctuation_supported ? "true" : "false");
185                         break;
186                 }
187         }
188
189         client->before_state = client->current_state;
190         client->current_state = STT_STATE_READY;
191
192         ecore_timer_add(0, __stt_notify_state_changed, (void*)stt);
193
194         g_connect_timer = NULL;
195
196         SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS] uid(%d)", client->uid);
197
198         SLOG(LOG_DEBUG, TAG_STTC, "=====");
199         SLOG(LOG_DEBUG, TAG_STTC, "  ");
200
201         return EINA_FALSE;
202 }
203
204
205 int stt_prepare(stt_h stt)
206 {
207         SLOG(LOG_DEBUG, TAG_STTC, "===== Prepare STT");
208
209         stt_client_s* client = stt_client_get(stt);
210
211         /* check handle */
212         if (NULL == client) {
213                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
214                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
215                 SLOG(LOG_DEBUG, TAG_STTC, " ");
216                 return STT_ERROR_INVALID_PARAMETER;
217         }
218
219         /* check state */
220         if (client->current_state != STT_STATE_CREATED) {
221                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not 'CREATED'"); 
222                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
223                 SLOG(LOG_DEBUG, TAG_STTC, " ");
224                 return STT_ERROR_INVALID_STATE;
225         }
226
227         g_connect_timer = ecore_timer_add(0, __stt_connect_daemon, (void*)stt);
228
229         SLOG(LOG_DEBUG, TAG_STTC, "=====");
230         SLOG(LOG_DEBUG, TAG_STTC, " ");
231
232         return STT_ERROR_NONE;
233 }
234
235 int stt_unprepare(stt_h stt)
236 {
237         SLOG(LOG_DEBUG, TAG_STTC, "===== Unprepare STT");
238
239         stt_client_s* client = stt_client_get(stt);
240
241         /* check handle */
242         if (NULL == client) {
243                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
244                 return STT_ERROR_INVALID_PARAMETER;
245         }
246
247         /* check state */
248         if (client->current_state != STT_STATE_READY) {
249                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not 'READY'"); 
250                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
251                 SLOG(LOG_DEBUG, TAG_STTC, " ");
252                 return STT_ERROR_INVALID_STATE;
253         }
254
255         int ret = stt_dbus_request_finalize(client->uid);
256         if (0 != ret) {
257                 SLOG(LOG_WARN, TAG_STTC, "[ERROR] Fail to request finalize");
258         }
259         g_is_daemon_started = false;
260
261         client->before_state = client->current_state;
262         client->current_state = STT_STATE_CREATED;
263
264         ecore_timer_add(0, __stt_notify_state_changed, (void*)stt);
265
266         SLOG(LOG_DEBUG, TAG_STTC, "=====");
267         SLOG(LOG_DEBUG, TAG_STTC, " ");
268
269         return STT_ERROR_NONE;
270 }
271
272 int stt_foreach_supported_languages(stt_h stt, stt_supported_language_cb callback, void* user_data)
273 {
274         SLOG(LOG_DEBUG, TAG_STTC, "===== Foreach Supported Language");
275
276         if (NULL == stt || NULL == callback) {
277                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
278                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
279                 SLOG(LOG_DEBUG, TAG_STTC, " ");
280                 return STT_ERROR_INVALID_PARAMETER;
281         }
282
283         stt_client_s* client = stt_client_get(stt);
284
285         /* check handle */
286         if (NULL == client) {
287                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
288                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
289                 SLOG(LOG_DEBUG, TAG_STTC, " ");
290                 return STT_ERROR_INVALID_PARAMETER;
291         }
292
293         /* check state */
294         if (client->current_state != STT_STATE_READY) {
295                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
296                 return STT_ERROR_INVALID_STATE;
297         }
298
299         int ret = 0;
300         ret = stt_dbus_request_get_support_langs(client->uid, client->stt, callback, user_data);
301         if (0 != ret) {
302                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get languages");
303         } else {
304                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS]");
305         }
306
307         SLOG(LOG_DEBUG, TAG_STTC, "=====");
308         SLOG(LOG_DEBUG, TAG_STTC, " ");
309
310         return STT_ERROR_NONE;
311 }
312
313
314 int stt_get_default_language(stt_h stt, char** language)
315 {
316         SLOG(LOG_DEBUG, TAG_STTC, "===== Get Default Language");
317
318         if (NULL == stt || NULL == language) {
319                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
320                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
321                 SLOG(LOG_DEBUG, TAG_STTC, " ");
322                 return STT_ERROR_INVALID_PARAMETER;
323         }
324
325         stt_client_s* client = stt_client_get(stt);
326
327         /* check handle */
328         if (NULL == client) {
329                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
330                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
331                 SLOG(LOG_DEBUG, TAG_STTC, " ");
332                 return STT_ERROR_INVALID_PARAMETER;
333         }
334
335         /* check state */
336         if (client->current_state != STT_STATE_READY) {
337                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
338                 return STT_ERROR_INVALID_STATE;
339         }
340
341         int ret = 0;
342         ret = stt_dbus_request_get_default_lang(client->uid, language);
343
344         if (0 != ret) {
345                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail : request get default language");
346         } else {
347                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS] Current language = %s", *language);
348         }
349
350         SLOG(LOG_DEBUG, TAG_STTC, "=====");
351         SLOG(LOG_DEBUG, TAG_STTC, " ");
352
353         return ret;
354 }
355
356 int stt_get_state(stt_h stt, stt_state_e* state)
357 {
358         if (NULL == stt || NULL == state) {
359                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
360                 return STT_ERROR_INVALID_PARAMETER;
361         }
362
363         stt_client_s* client = stt_client_get(stt);
364
365         if (NULL == client) {
366                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Get state : A handle is not valid");
367                 return STT_ERROR_INVALID_PARAMETER;
368         }
369
370         *state = client->current_state;
371
372         switch(*state) {
373                 case STT_STATE_CREATED:         SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'CREATED'");        break;
374                 case STT_STATE_READY:           SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'Ready'");          break;
375                 case STT_STATE_RECORDING:       SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'Recording'");      break;
376                 case STT_STATE_PROCESSING:      SLOG(LOG_DEBUG, TAG_STTC, "Current state is 'Processing'");     break;
377         }
378
379         return STT_ERROR_NONE;
380 }
381
382 int stt_is_partial_result_supported(stt_h stt, bool* partial_result)
383 {
384         if (NULL == stt || NULL == partial_result) {
385                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
386                 return STT_ERROR_INVALID_PARAMETER;
387         }
388
389         stt_client_s* client = stt_client_get(stt);
390
391         if (NULL == client) {
392                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not valid");
393                 return STT_ERROR_INVALID_PARAMETER;
394         }
395
396         /* check state */
397         if (client->current_state != STT_STATE_READY) {
398                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
399                 return STT_ERROR_INVALID_STATE;
400         }
401
402         int ret = 0;
403         ret = stt_dbus_request_is_partial_result_supported(client->uid, partial_result);
404
405         if (0 != ret) {
406                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get partial result supported");
407         } else {
408                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS] Partial result supporting is %s", *partial_result ? "true " : "false");
409         }
410
411         return STT_ERROR_NONE;
412 }
413
414 int stt_set_profanity_filter(stt_h stt, stt_option_profanity_e type)
415 {
416         if (NULL == stt) {
417                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
418                 return STT_ERROR_INVALID_PARAMETER;
419         }
420
421         stt_client_s* client = stt_client_get(stt);
422
423         if (NULL == client) {
424                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Get state : A handle is not valid");
425                 return STT_ERROR_INVALID_PARAMETER;
426         }
427
428         /* check state */
429         if (client->current_state != STT_STATE_READY) {
430                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
431                 return STT_ERROR_INVALID_STATE;
432         }
433
434         if (true == client->profanity_supported) {
435                 if (type >= STT_OPTION_PROFANITY_FALSE && type <= STT_OPTION_PROFANITY_AUTO)
436                         client->profanity = type;       
437                 else {
438                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Type is invalid");
439                         return STT_ERROR_INVALID_PARAMETER;
440                 }
441         } else {
442                 return STT_ERROR_NOT_SUPPORTED_FEATURE; 
443         }
444
445         return STT_ERROR_NONE;
446 }
447
448 int stt_set_punctuation_override(stt_h stt, stt_option_punctuation_e type)
449 {
450         if (NULL == stt) {
451                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
452                 return STT_ERROR_INVALID_PARAMETER;
453         }
454
455         stt_client_s* client = stt_client_get(stt);
456
457         if (NULL == client) {
458                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Get state : A handle is not valid");
459                 return STT_ERROR_INVALID_PARAMETER;
460         }
461         
462         /* check state */
463         if (client->current_state != STT_STATE_READY) {
464                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
465                 return STT_ERROR_INVALID_STATE;
466         }
467
468         if (true == client->punctuation_supported) {
469                 if (type >= STT_OPTION_PUNCTUATION_FALSE && type <= STT_OPTION_PUNCTUATION_AUTO)
470                         client->punctuation = type;     
471                 else {
472                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Type is invalid");
473                         return STT_ERROR_INVALID_PARAMETER;
474                 }
475         } else {
476                 return STT_ERROR_NOT_SUPPORTED_FEATURE; 
477         }
478
479         return STT_ERROR_NONE;
480 }
481
482 int stt_set_silence_detection(stt_h stt, stt_option_silence_detection_e type)
483 {
484         if (NULL == stt) {
485                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
486                 return STT_ERROR_INVALID_PARAMETER;
487         }
488
489         stt_client_s* client = stt_client_get(stt);
490
491         if (NULL == client) {
492                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Get state : A handle is not valid");
493                 return STT_ERROR_INVALID_PARAMETER;
494         }
495
496         /* check state */
497         if (client->current_state != STT_STATE_READY) {
498                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
499                 return STT_ERROR_INVALID_STATE;
500         }
501
502         if (true == client->silence_supported) {
503                 if (type >= STT_OPTION_SILENCE_DETECTION_FALSE && type <= STT_OPTION_SILENCE_DETECTION_AUTO)
504                         client->silence = type; 
505                 else {
506                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Type is invalid");
507                         return STT_ERROR_INVALID_PARAMETER;
508                 }
509         } else {
510                 return STT_ERROR_NOT_SUPPORTED_FEATURE; 
511         }
512
513         return STT_ERROR_NONE;
514 }
515
516 int stt_start(stt_h stt, const char* language, const char* type)
517 {
518         SLOG(LOG_DEBUG, TAG_STTC, "===== STT START");
519
520         if (NULL == stt) {
521                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
522                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
523                 SLOG(LOG_DEBUG, TAG_STTC, " ");
524                 return STT_ERROR_INVALID_PARAMETER;
525         }
526
527         stt_client_s* client = stt_client_get(stt);
528
529         /* check handle */
530         if (NULL == client) {
531                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
532                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
533                 SLOG(LOG_DEBUG, TAG_STTC, " ");
534                 return STT_ERROR_INVALID_PARAMETER;
535         }
536
537         /* check state */
538         if (client->current_state != STT_STATE_READY) {
539                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State: Current state is not READY"); 
540                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
541                 SLOG(LOG_DEBUG, TAG_STTC, " ");
542                 return STT_ERROR_INVALID_STATE;
543         }
544
545         char* temp;
546         if (NULL == language) {
547                 temp = strdup("default");
548         } else {
549                 temp = strdup(language);
550         }
551
552         int ret; 
553         /* do request */
554         ret = stt_dbus_request_start(client->uid, temp, type, client->profanity, client->punctuation, client->silence);
555
556         if (ret) {
557                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to start");
558         } else {
559                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS]");
560
561                 client->before_state = client->current_state;
562                 client->current_state = STT_STATE_RECORDING;
563
564                 ecore_timer_add(0, __stt_notify_state_changed, (void*)stt);
565         }
566
567         free(temp);
568
569         SLOG(LOG_DEBUG, TAG_STTC, "=====");
570         SLOG(LOG_DEBUG, TAG_STTC, " ");
571
572         return ret;
573 }
574
575 int stt_stop(stt_h stt)
576 {
577         SLOG(LOG_DEBUG, TAG_STTC, "===== STT STOP");
578
579         if (NULL == stt) {
580                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] [ERROR] Input parameter is NULL");
581                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
582                 SLOG(LOG_DEBUG, TAG_STTC, " ");
583                 return STT_ERROR_INVALID_PARAMETER;
584         }
585
586         stt_client_s* client = stt_client_get(stt);
587
588         /* check handle */
589         if (NULL == client) {
590                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
591                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
592                 SLOG(LOG_DEBUG, TAG_STTC, " ");
593                 return STT_ERROR_INVALID_PARAMETER;
594         }   
595         
596         /* check state */
597         if (client->current_state != STT_STATE_RECORDING) {
598                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Invalid State : Current state is NOT RECORDING"); 
599                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
600                 SLOG(LOG_DEBUG, TAG_STTC, " ");
601                 return STT_ERROR_INVALID_STATE;
602         }
603
604         int ret = 0; 
605         /* do request */
606         ret = stt_dbus_request_stop(client->uid);
607         if (0 != ret) {
608                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Fail to stop");
609         } else {
610                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS]");
611
612                 client->before_state = client->current_state;
613                 client->current_state = STT_STATE_PROCESSING;
614
615                 ecore_timer_add(0, __stt_notify_state_changed, (void*)stt);
616         }
617
618         SLOG(LOG_DEBUG, TAG_STTC, "=====");
619         SLOG(LOG_DEBUG, TAG_STTC, " ");
620
621         return ret;
622 }
623
624
625 int stt_cancel(stt_h stt)
626 {
627         SLOG(LOG_DEBUG, TAG_STTC, "===== STT CANCEL");
628
629         if (NULL == stt) {
630                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input handle is null");
631                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
632                 SLOG(LOG_DEBUG, TAG_STTC, " ");
633                 return STT_ERROR_INVALID_PARAMETER;
634         }
635
636         stt_client_s* client = stt_client_get(stt);
637
638         /* check handle */
639         if (NULL == client) {
640                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
641                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
642                 SLOG(LOG_DEBUG, TAG_STTC, " ");
643                 return STT_ERROR_INVALID_PARAMETER;
644         }       
645
646         /* check state */
647         if (STT_STATE_RECORDING != client->current_state && STT_STATE_PROCESSING != client->current_state) {
648                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Invalid state : Current state is 'Ready'");
649                 SLOG(LOG_DEBUG, TAG_STTC, "=====");
650                 SLOG(LOG_DEBUG, TAG_STTC, " ");
651                 return STT_ERROR_INVALID_STATE;
652         }
653
654         int ret; 
655         /* do request */
656         ret = stt_dbus_request_cancel(client->uid);
657         if (0 != ret) {
658                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Fail to cancel");
659         } else {
660                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS]");
661
662                 client->before_state = client->current_state;
663                 client->current_state = STT_STATE_READY;
664
665                 ecore_timer_add(0, __stt_notify_state_changed, (void*)stt);
666         }
667
668         SLOG(LOG_DEBUG, TAG_STTC, "=====");
669         SLOG(LOG_DEBUG, TAG_STTC, " ");
670
671         return ret;
672 }
673
674 static int __stt_get_audio_volume(float* volume)
675 {
676         FILE* fp = fopen(STT_AUDIO_VOLUME_PATH, "rb");
677         if (!fp) {
678                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to open Volume File");
679                 return STT_ERROR_OPERATION_FAILED;
680         }
681
682         int readlen = fread((void*)volume, sizeof(*volume), 1, fp);
683         fclose(fp);
684
685         if (0 == readlen)
686                 *volume = 0.0f;
687
688         return 0;
689 }
690
691 int stt_get_recording_volume(stt_h stt, float* volume)
692 {
693         if (NULL == stt || NULL == volume) {
694                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
695                 return STT_ERROR_INVALID_PARAMETER;
696         }
697
698         stt_client_s* client = stt_client_get(stt);
699
700         /* check handle */
701         if (NULL == client) {
702                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
703                 return STT_ERROR_INVALID_PARAMETER;
704         } 
705         
706         if (STT_STATE_RECORDING != client->current_state) {
707                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Invalid state : NO 'Recording' state");
708                 return STT_ERROR_INVALID_STATE;
709         }    
710         
711         int ret = 0;
712         ret = __stt_get_audio_volume(volume);
713         if (0 != ret) {
714                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get audio volume");
715                 return STT_ERROR_OPERATION_FAILED;
716         }
717
718         return STT_ERROR_NONE;
719 }
720
721 int stt_start_file_recognition(stt_h stt, const char* filepath, const char* language, const char* type)
722 {
723         if (NULL == stt || NULL == type || NULL == filepath) {
724                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
725                 return STT_ERROR_INVALID_PARAMETER;
726         }
727
728         stt_client_s* client = stt_client_get(stt);
729
730         /* check handle */
731         if (NULL == client) {
732                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
733                 return STT_ERROR_INVALID_PARAMETER;
734         } 
735
736         if (STT_STATE_READY != client->current_state) {
737                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Invalid state : NO 'Ready' state");
738                 return STT_ERROR_INVALID_STATE;
739         }
740
741         char* temp;
742         if (NULL == language) {
743                 temp = strdup("default");
744         } else {
745                 temp = strdup(language);
746         }
747
748         int ret; 
749         ret = stt_dbus_request_start_file_recognition(client->uid, filepath, temp, type, client->profanity, client->punctuation);
750
751         if (ret) {
752                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to start");
753         } else {
754                 SLOG(LOG_DEBUG, TAG_STTC, "[SUCCESS]");
755
756                 client->before_state = client->current_state;
757                 client->current_state = STT_STATE_PROCESSING;
758
759                 ecore_timer_add(0, __stt_notify_state_changed, (void*)stt);
760         }
761
762         free(temp);
763
764         return STT_ERROR_NONE;
765 }
766
767 static Eina_Bool __stt_notify_error(void *data)
768 {
769         stt_h stt = (stt_h)data;
770
771         stt_client_s* client = stt_client_get(stt);
772
773         /* check handle */
774         if (NULL == client) {
775                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
776                 return EINA_FALSE;
777         }
778
779         if (NULL != client->error_cb) {
780                 stt_client_use_callback(client);
781                 client->error_cb(client->stt, client->reason, client->error_user_data); 
782                 stt_client_not_use_callback(client);
783                 SLOG(LOG_DEBUG, TAG_STTC, "Error callback is called");
784         } else {
785                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null");
786         }
787
788         return EINA_FALSE;
789 }
790
791 int __stt_cb_error(int uid, int reason)
792 {
793         stt_client_s* client = stt_client_get_by_uid(uid);
794         if( NULL == client ) {
795                 SLOG(LOG_ERROR, TAG_STTC, "Handle not found\n");
796                 return -1;
797         }
798
799         client->reason = reason;
800
801         if (NULL != client->error_cb) {
802                 ecore_timer_add(0, __stt_notify_error, client->stt);
803         } else {
804                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null");
805         }    
806
807         return 0;
808 }
809
810 static Eina_Bool __stt_notify_result(void *data)
811 {
812         stt_h stt = (stt_h)data;
813
814         stt_client_s* client = stt_client_get(stt);
815
816         /* check handle */
817         if (NULL == client) {
818                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
819                 return EINA_FALSE;
820         }
821
822         if (NULL != client->result_cb) {
823                 stt_client_use_callback(client);
824                 client->result_cb(client->stt, client->type, (const char**)client->data_list, client->data_count, client->msg, client->result_user_data);
825                 stt_client_not_use_callback(client);
826                 SLOG(LOG_DEBUG, TAG_STTC, "client result callback called");
827         } else {
828                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] User result callback is null");
829         } 
830
831         /* Free result */
832         if (NULL != client->type)
833                 free(client->type);
834
835         if (NULL != client->data_list) {
836                 char **temp = NULL;
837                 temp = client->data_list;
838
839                 int i = 0;
840                 for (i = 0;i < client->data_count;i++) {
841                         if(NULL != temp[i])
842                                 free(temp[i]);
843                         else 
844                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Result data is error");
845                 }
846                 free(client->data_list);
847         }
848         
849         if (NULL != client->msg) 
850                 free(client->msg);
851
852         client->data_count = 0;
853
854         return EINA_FALSE;
855 }
856
857 static Eina_Bool __stt_notify_state_changed(void *data)
858 {
859         stt_h stt = (stt_h)data;
860
861         stt_client_s* client = stt_client_get(stt);
862
863         /* check handle */
864         if (NULL == client) {
865                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
866                 return EINA_FALSE;
867         }
868
869         if (NULL != client->state_changed_cb) {
870                 stt_client_use_callback(client);
871                 client->state_changed_cb(client->stt, client->before_state, client->current_state, client->state_changed_user_data); 
872                 stt_client_not_use_callback(client);
873                 SLOG(LOG_DEBUG, TAG_STTC, "State changed callback is called");
874         } else {
875                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null");
876         }
877
878         return EINA_FALSE;
879 }
880
881 int __stt_cb_result(int uid, const char* type, const char** data, int data_count, const char* msg)
882 {
883         stt_client_s* client = NULL;
884         
885         client = stt_client_get_by_uid(uid);
886         if (NULL == client) {
887                 SLOG(LOG_ERROR, TAG_STTC, "Handle is NOT valid");
888                 return -1;
889         }
890
891         SLOG(LOG_DEBUG, TAG_STTC, "Recognition Result Message = %s", msg);
892
893         int i=0;
894         for (i = 0;i < data_count;i++) {
895                 if(NULL != data[i])
896                         SLOG(LOG_DEBUG, TAG_STTC, "Recognition Result[%d] = %s", i, data[i]);
897         }       
898
899         if (NULL != client->result_cb) {
900                 client->type = strdup(type);
901                 client->msg = strdup(msg);
902                 client->data_count = data_count;
903
904                 if (data_count > 0) {
905                         char **temp = NULL;
906                         temp = malloc( sizeof(char*) * data_count);
907
908                         for (i = 0;i < data_count;i++) {
909                                 if(NULL != data[i])
910                                         temp[i] = strdup(data[i]);
911                                 else 
912                                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Result data is error");
913                         }
914
915                         client->data_list = temp;
916                 }
917
918                 ecore_timer_add(0, __stt_notify_result, client->stt);
919         } else {
920                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] User result callback is null");
921         }   
922
923         client->before_state = client->current_state;
924         client->current_state = STT_STATE_READY;
925
926         if (NULL != client->state_changed_cb) {
927                 ecore_timer_add(0, __stt_notify_state_changed, client->stt);
928         } else {
929                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null");
930         }
931
932         return 0;
933 }
934
935 static Eina_Bool __stt_notify_partial_result(void *data)
936 {
937         stt_h stt = (stt_h)data;
938
939         stt_client_s* client = stt_client_get(stt);
940
941         /* check handle */
942         if (NULL == client) {
943                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
944                 return EINA_FALSE;
945         }
946
947         if (client->partial_result_cb) {
948                 stt_client_use_callback(client);
949                 client->partial_result_cb(client->stt, client->partial_result, client->partial_result_user_data);
950                 stt_client_not_use_callback(client);
951                 SLOG(LOG_DEBUG, TAG_STTC, "Partial result callback is called");
952         } else {
953                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Partial result callback is null");
954         }   
955
956         if (NULL != client->partial_result)
957                 free(client->partial_result);
958
959         return EINA_FALSE;
960 }
961
962 int __stt_cb_partial_result(int uid, const char* data)
963 {
964         stt_client_s* client = NULL;
965
966         client = stt_client_get_by_uid(uid);
967         if (NULL == client) {
968                 SLOG(LOG_ERROR, TAG_STTC, "Handle is NOT valid");
969                 return -1;
970         }
971
972         if (client->current_state == STT_STATE_READY) {
973                 SLOG(LOG_ERROR, TAG_STTC, "Current state has already been 'Ready' state");      
974                 return 0;
975         }
976
977         if (client->partial_result_cb) {
978                 client->partial_result = strdup(data);
979                 ecore_timer_add(0, __stt_notify_partial_result, client->stt);
980         } else {
981                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Partial result callback is null");
982         }  
983
984         return 0;
985 }
986
987 int __stt_cb_set_state(int uid, int state)
988 {
989         stt_client_s* client = stt_client_get_by_uid(uid);
990         if( NULL == client ) {
991                 SLOG(LOG_ERROR, TAG_STTC, "Handle not found");
992                 return -1;
993         }
994
995         stt_state_e state_from_daemon = (stt_state_e)state;
996
997         if (client->current_state == state_from_daemon) {
998                 SLOG(LOG_DEBUG, TAG_STTC, "Current state has already been %d", client->current_state);
999                 return 0;
1000         }
1001
1002         client->before_state = client->current_state;
1003         client->current_state = state_from_daemon;
1004
1005         ecore_timer_add(0, __stt_notify_state_changed, client->stt);
1006         return 0;
1007 }
1008
1009 int stt_set_result_cb(stt_h stt, stt_result_cb callback, void* user_data)
1010 {
1011         if (stt == NULL || callback == NULL)
1012                 return STT_ERROR_INVALID_PARAMETER;
1013
1014         stt_client_s* client = stt_client_get(stt);
1015
1016         /* check handle */
1017         if (NULL == client) {
1018                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1019                 return STT_ERROR_INVALID_PARAMETER;
1020         }
1021
1022         if (STT_STATE_CREATED != client->current_state) {
1023                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1024                 return STT_ERROR_INVALID_STATE;
1025         }
1026
1027         client->result_cb = callback;
1028         client->result_user_data = user_data;
1029
1030         return 0;
1031 }
1032
1033 int stt_unset_result_cb(stt_h stt)
1034 {
1035         if (NULL == stt)
1036                 return STT_ERROR_INVALID_PARAMETER;
1037
1038         stt_client_s* client = stt_client_get(stt);
1039
1040         /* check handle */
1041         if (NULL == client) {
1042                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1043                 return STT_ERROR_INVALID_PARAMETER;
1044         }
1045
1046         if (STT_STATE_CREATED != client->current_state) {
1047                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1048                 return STT_ERROR_INVALID_STATE;
1049         }
1050
1051         client->result_cb = NULL;
1052         client->result_user_data = NULL;
1053
1054         return 0;
1055 }
1056
1057 int stt_set_partial_result_cb(stt_h stt, stt_partial_result_cb callback, void* user_data)
1058 {
1059         if (NULL == stt || NULL == callback)
1060                 return STT_ERROR_INVALID_PARAMETER;
1061
1062         stt_client_s* client = stt_client_get(stt);
1063
1064         /* check handle */
1065         if (NULL == client) {
1066                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1067                 return STT_ERROR_INVALID_PARAMETER;
1068         }
1069
1070         if (STT_STATE_CREATED != client->current_state) {
1071                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1072                 return STT_ERROR_INVALID_STATE;
1073         }
1074
1075         client->partial_result_cb = callback;
1076         client->partial_result_user_data = user_data;
1077
1078         return 0;
1079 }
1080
1081 int stt_unset_partial_result_cb(stt_h stt)
1082 {
1083         if (NULL == stt)
1084                 return STT_ERROR_INVALID_PARAMETER;
1085
1086         stt_client_s* client = stt_client_get(stt);
1087
1088         /* check handle */
1089         if (NULL == client) {
1090                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1091                 return STT_ERROR_INVALID_PARAMETER;
1092         }
1093
1094         if (STT_STATE_CREATED != client->current_state) {
1095                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1096                 return STT_ERROR_INVALID_STATE;
1097         }
1098
1099         client->partial_result_cb = NULL;
1100         client->partial_result_user_data = NULL;
1101
1102         return 0;
1103 }
1104
1105 int stt_set_state_changed_cb(stt_h stt, stt_state_changed_cb callback, void* user_data)
1106 {
1107         if (NULL == stt || NULL == callback)
1108                 return STT_ERROR_INVALID_PARAMETER;
1109
1110         stt_client_s* client = stt_client_get(stt);
1111
1112         /* check handle */
1113         if (NULL == client) {
1114                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1115                 return STT_ERROR_INVALID_PARAMETER;
1116         }
1117
1118         if (STT_STATE_CREATED != client->current_state) {
1119                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1120                 return STT_ERROR_INVALID_STATE;
1121         }
1122
1123         client->state_changed_cb = callback;
1124         client->state_changed_user_data = user_data;
1125
1126         return 0;
1127 }
1128
1129 int stt_unset_state_changed_cb(stt_h stt)
1130 {
1131         if (NULL == stt)
1132                 return STT_ERROR_INVALID_PARAMETER;
1133
1134         stt_client_s* client = stt_client_get(stt);
1135
1136         /* check handle */
1137         if (NULL == client) {
1138                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1139                 return STT_ERROR_INVALID_PARAMETER;
1140         }
1141
1142         if (STT_STATE_CREATED != client->current_state) {
1143                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1144                 return STT_ERROR_INVALID_STATE;
1145         }
1146
1147         client->state_changed_cb = NULL;
1148         client->state_changed_user_data = NULL;
1149
1150         return 0;
1151 }
1152
1153
1154 int stt_set_error_cb(stt_h stt, stt_error_cb callback, void* user_data)
1155 {
1156         if (NULL == stt || NULL == callback)
1157                 return STT_ERROR_INVALID_PARAMETER;
1158
1159         stt_client_s* client = stt_client_get(stt);
1160
1161         /* check handle */
1162         if (NULL == client) {
1163                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1164                 return STT_ERROR_INVALID_PARAMETER;
1165         }
1166
1167         if (STT_STATE_CREATED != client->current_state) {
1168                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1169                 return STT_ERROR_INVALID_STATE;
1170         }
1171
1172         client->error_cb = callback;
1173         client->error_user_data = user_data;
1174
1175         return 0;
1176 }
1177
1178 int stt_unset_error_cb(stt_h stt)
1179 {
1180         if (NULL == stt)
1181                 return STT_ERROR_INVALID_PARAMETER;
1182
1183         stt_client_s* client = stt_client_get(stt);
1184
1185         /* check handle */
1186         if (NULL == client) {
1187                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1188                 return STT_ERROR_INVALID_PARAMETER;
1189         }
1190
1191         if (STT_STATE_CREATED != client->current_state) {
1192                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1193                 return STT_ERROR_INVALID_STATE;
1194         }
1195
1196         client->error_cb = NULL;
1197         client->error_user_data = NULL;
1198
1199         return 0;
1200 }
1201
1202 int __get_cmd_line(char *file, char *buf) 
1203 {
1204         FILE *fp = NULL;
1205
1206         fp = fopen(file, "r");
1207         if (fp == NULL) {
1208                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Get command line");
1209                 return -1;
1210         }
1211
1212         memset(buf, 0, 256);
1213         if (NULL == fgets(buf, 256, fp)) {
1214                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to fget command line");
1215                 fclose(fp);
1216                 return -1;
1217         }
1218         fclose(fp);
1219
1220         return 0;
1221 }
1222
1223 static bool __stt_is_alive()
1224 {
1225         DIR *dir;
1226         struct dirent *entry;
1227         struct stat filestat;
1228         
1229         int pid;
1230         char cmdLine[256];
1231         char tempPath[256];
1232
1233         dir  = opendir("/proc");
1234         if (NULL == dir) {
1235                 SLOG(LOG_ERROR, TAG_STTC, "process checking is FAILED");
1236                 return FALSE;
1237         }
1238
1239         while ((entry = readdir(dir)) != NULL) {
1240                 if (0 != lstat(entry->d_name, &filestat))
1241                         continue;
1242
1243                 if (!S_ISDIR(filestat.st_mode))
1244                         continue;
1245
1246                 pid = atoi(entry->d_name);
1247                 if (pid <= 0) continue;
1248
1249                 sprintf(tempPath, "/proc/%d/cmdline", pid);
1250                 if (0 != __get_cmd_line(tempPath, cmdLine)) {
1251                         continue;
1252                 }
1253                 if ( 0 == strncmp(cmdLine, "[stt-daemon]", strlen("[stt-daemon]")) ||
1254                         0 == strncmp(cmdLine, "stt-daemon", strlen("stt-daemon")) ||
1255                         0 == strncmp(cmdLine, "/usr/bin/stt-daemon", strlen("/usr/bin/stt-daemon"))) {
1256                                 SLOG(LOG_DEBUG, TAG_STTC, "stt-daemon is ALIVE !! \n");
1257                                 closedir(dir);
1258                                 return TRUE;
1259                 }
1260         }
1261         SLOG(LOG_DEBUG, TAG_STTC, "THERE IS NO stt-daemon !! \n");
1262
1263         closedir(dir);
1264         return FALSE;
1265
1266 }
1267
1268 static int __check_stt_daemon()
1269 {
1270         if( TRUE == __stt_is_alive() )
1271                 return 0;
1272         
1273         /* fork-exec stt-daemon */
1274         int pid, i;
1275
1276         pid = fork();
1277
1278         switch(pid) {
1279         case -1:
1280                 SLOG(LOG_DEBUG, TAG_STTC, "[STT ERROR] fail to create STT-DAEMON \n");
1281                 break;
1282
1283         case 0:
1284                 setsid();
1285                 for (i = 0;i < _NSIG;i++)
1286                         signal(i, SIG_DFL);
1287
1288                 execl("/usr/bin/stt-daemon", "/usr/bin/stt-daemon", NULL);
1289                 break;
1290
1291         default:
1292                 break;
1293         }
1294
1295         return 0;
1296 }
1297
1298
1299
1300