merge with master
[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 -1;
680         }
681
682         fread((void*)volume, sizeof(*volume), 1, fp);
683         fclose(fp);
684
685         return 0;
686 }
687
688 int stt_get_recording_volume(stt_h stt, float* volume)
689 {
690         if (NULL == stt || NULL == volume) {
691                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Input parameter is NULL");
692                 return STT_ERROR_INVALID_PARAMETER;
693         }
694
695         stt_client_s* client = stt_client_get(stt);
696
697         /* check handle */
698         if (NULL == client) {
699                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
700                 return STT_ERROR_INVALID_PARAMETER;
701         } 
702         
703         if (STT_STATE_RECORDING != client->current_state) {
704                 SLOG(LOG_DEBUG, TAG_STTC, "[ERROR] Invalid state : NO 'Recording' state");
705                 return STT_ERROR_INVALID_STATE;
706         }    
707         
708         int ret = 0;
709         ret = __stt_get_audio_volume(volume);
710         if (0 != ret) {
711                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to get audio volume");
712                 return STT_ERROR_OPERATION_FAILED;
713         }
714
715         return STT_ERROR_NONE;
716 }
717
718 static Eina_Bool __stt_notify_error(void *data)
719 {
720         stt_h stt = (stt_h)data;
721
722         stt_client_s* client = stt_client_get(stt);
723
724         /* check handle */
725         if (NULL == client) {
726                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
727                 return EINA_FALSE;
728         }
729
730         if (NULL != client->error_cb) {
731                 stt_client_use_callback(client);
732                 client->error_cb(client->stt, client->reason, client->error_user_data); 
733                 stt_client_not_use_callback(client);
734                 SLOG(LOG_DEBUG, TAG_STTC, "Error callback is called");
735         } else {
736                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null");
737         }
738
739         return EINA_FALSE;
740 }
741
742 int __stt_cb_error(int uid, int reason)
743 {
744         stt_client_s* client = stt_client_get_by_uid(uid);
745         if( NULL == client ) {
746                 SLOG(LOG_ERROR, TAG_STTC, "Handle not found\n");
747                 return -1;
748         }
749
750         client->reason = reason;
751
752         if (NULL != client->error_cb) {
753                 ecore_timer_add(0, __stt_notify_error, client->stt);
754         } else {
755                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Error callback is null");
756         }    
757
758         return 0;
759 }
760
761 static Eina_Bool __stt_notify_result(void *data)
762 {
763         stt_h stt = (stt_h)data;
764
765         stt_client_s* client = stt_client_get(stt);
766
767         /* check handle */
768         if (NULL == client) {
769                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
770                 return EINA_FALSE;
771         }
772
773         if (NULL != client->result_cb) {
774                 stt_client_use_callback(client);
775                 client->result_cb(client->stt, client->type, (const char**)client->data_list, client->data_count, client->msg, client->result_user_data);
776                 stt_client_not_use_callback(client);
777                 SLOG(LOG_DEBUG, TAG_STTC, "client result callback called");
778         } else {
779                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] User result callback is null");
780         } 
781
782         /* Free result */
783         if (NULL != client->type)
784                 free(client->type);
785
786         if (NULL != client->data_list) {
787                 char **temp = NULL;
788                 temp = client->data_list;
789
790                 int i = 0;
791                 for (i = 0;i < client->data_count;i++) {
792                         if(NULL != temp[i])
793                                 free(temp[i]);
794                         else 
795                                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Result data is error");
796                 }
797                 free(client->data_list);
798         }
799         
800         if (NULL != client->msg) 
801                 free(client->msg);
802
803         client->data_count = 0;
804
805         return EINA_FALSE;
806 }
807
808 static Eina_Bool __stt_notify_state_changed(void *data)
809 {
810         stt_h stt = (stt_h)data;
811
812         stt_client_s* client = stt_client_get(stt);
813
814         /* check handle */
815         if (NULL == client) {
816                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
817                 return EINA_FALSE;
818         }
819
820         if (NULL != client->state_changed_cb) {
821                 stt_client_use_callback(client);
822                 client->state_changed_cb(client->stt, client->before_state, client->current_state, client->state_changed_user_data); 
823                 stt_client_not_use_callback(client);
824                 SLOG(LOG_DEBUG, TAG_STTC, "State changed callback is called");
825         } else {
826                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null");
827         }
828
829         return EINA_FALSE;
830 }
831
832 int __stt_cb_result(int uid, const char* type, const char** data, int data_count, const char* msg)
833 {
834         stt_client_s* client = NULL;
835         
836         client = stt_client_get_by_uid(uid);
837         if (NULL == client) {
838                 SLOG(LOG_ERROR, TAG_STTC, "Handle is NOT valid");
839                 return -1;
840         }
841
842         SLOG(LOG_DEBUG, TAG_STTC, "Recognition Result Message = %s", msg);
843
844         int i=0;
845         for (i = 0;i < data_count;i++) {
846                 if(NULL != data[i])
847                         SLOG(LOG_DEBUG, TAG_STTC, "Recognition Result[%d] = %s", i, data[i]);
848         }       
849
850         if (NULL != client->result_cb) {
851                 client->type = strdup(type);
852                 client->msg = strdup(msg);
853                 client->data_count = data_count;
854
855                 if (data_count > 0) {
856                         char **temp = NULL;
857                         temp = malloc( sizeof(char*) * data_count);
858
859                         for (i = 0;i < data_count;i++) {
860                                 if(NULL != data[i])
861                                         temp[i] = strdup(data[i]);
862                                 else 
863                                         SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Result data is error");
864                         }
865
866                         client->data_list = temp;
867                 }
868
869                 ecore_timer_add(0, __stt_notify_result, client->stt);
870         } else {
871                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] User result callback is null");
872         }   
873
874         client->before_state = client->current_state;
875         client->current_state = STT_STATE_READY;
876
877         if (NULL != client->state_changed_cb) {
878                 ecore_timer_add(0, __stt_notify_state_changed, client->stt);
879         } else {
880                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] State changed callback is null");
881         }
882
883         return 0;
884 }
885
886 static Eina_Bool __stt_notify_partial_result(void *data)
887 {
888         stt_h stt = (stt_h)data;
889
890         stt_client_s* client = stt_client_get(stt);
891
892         /* check handle */
893         if (NULL == client) {
894                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to notify error : A handle is not valid");
895                 return EINA_FALSE;
896         }
897
898         if (client->partial_result_cb) {
899                 stt_client_use_callback(client);
900                 client->partial_result_cb(client->stt, client->partial_result, client->partial_result_user_data);
901                 stt_client_not_use_callback(client);
902                 SLOG(LOG_DEBUG, TAG_STTC, "Partial result callback is called");
903         } else {
904                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Partial result callback is null");
905         }   
906
907         if (NULL != client->partial_result)
908                 free(client->partial_result);
909
910         return EINA_FALSE;
911 }
912
913 int __stt_cb_partial_result(int uid, const char* data)
914 {
915         stt_client_s* client = NULL;
916
917         client = stt_client_get_by_uid(uid);
918         if (NULL == client) {
919                 SLOG(LOG_ERROR, TAG_STTC, "Handle is NOT valid");
920                 return -1;
921         }
922
923         if (client->current_state == STT_STATE_READY) {
924                 SLOG(LOG_ERROR, TAG_STTC, "Current state has already been 'Ready' state");      
925                 return 0;
926         }
927
928         if (client->partial_result_cb) {
929                 client->partial_result = strdup(data);
930                 ecore_timer_add(0, __stt_notify_partial_result, client->stt);
931         } else {
932                 SLOG(LOG_WARN, TAG_STTC, "[WARNING] Partial result callback is null");
933         }  
934
935         return 0;
936 }
937
938 int __stt_cb_set_state(int uid, int state)
939 {
940         stt_client_s* client = stt_client_get_by_uid(uid);
941         if( NULL == client ) {
942                 SLOG(LOG_ERROR, TAG_STTC, "Handle not found");
943                 return -1;
944         }
945
946         stt_state_e state_from_daemon = (stt_state_e)state;
947
948         if (client->current_state == state_from_daemon) {
949                 SLOG(LOG_DEBUG, TAG_STTC, "Current state has already been %d", client->current_state);
950                 return 0;
951         }
952
953         client->before_state = client->current_state;
954         client->current_state = state_from_daemon;
955
956         ecore_timer_add(0, __stt_notify_state_changed, client->stt);
957         return 0;
958 }
959
960 int stt_set_result_cb(stt_h stt, stt_result_cb callback, void* user_data)
961 {
962         if (stt == NULL || callback == NULL)
963                 return STT_ERROR_INVALID_PARAMETER;
964
965         stt_client_s* client = stt_client_get(stt);
966
967         /* check handle */
968         if (NULL == client) {
969                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
970                 return STT_ERROR_INVALID_PARAMETER;
971         }
972
973         if (STT_STATE_CREATED != client->current_state) {
974                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
975                 return STT_ERROR_INVALID_STATE;
976         }
977
978         client->result_cb = callback;
979         client->result_user_data = user_data;
980
981         return 0;
982 }
983
984 int stt_unset_result_cb(stt_h stt)
985 {
986         if (NULL == stt)
987                 return STT_ERROR_INVALID_PARAMETER;
988
989         stt_client_s* client = stt_client_get(stt);
990
991         /* check handle */
992         if (NULL == client) {
993                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
994                 return STT_ERROR_INVALID_PARAMETER;
995         }
996
997         if (STT_STATE_CREATED != client->current_state) {
998                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
999                 return STT_ERROR_INVALID_STATE;
1000         }
1001
1002         client->result_cb = NULL;
1003         client->result_user_data = NULL;
1004
1005         return 0;
1006 }
1007
1008 int stt_set_partial_result_cb(stt_h stt, stt_partial_result_cb callback, void* user_data)
1009 {
1010         if (NULL == stt || NULL == callback)
1011                 return STT_ERROR_INVALID_PARAMETER;
1012
1013         stt_client_s* client = stt_client_get(stt);
1014
1015         /* check handle */
1016         if (NULL == client) {
1017                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1018                 return STT_ERROR_INVALID_PARAMETER;
1019         }
1020
1021         if (STT_STATE_CREATED != client->current_state) {
1022                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1023                 return STT_ERROR_INVALID_STATE;
1024         }
1025
1026         client->partial_result_cb = callback;
1027         client->partial_result_user_data = user_data;
1028
1029         return 0;
1030 }
1031
1032 int stt_unset_partial_result_cb(stt_h stt)
1033 {
1034         if (NULL == stt)
1035                 return STT_ERROR_INVALID_PARAMETER;
1036
1037         stt_client_s* client = stt_client_get(stt);
1038
1039         /* check handle */
1040         if (NULL == client) {
1041                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1042                 return STT_ERROR_INVALID_PARAMETER;
1043         }
1044
1045         if (STT_STATE_CREATED != client->current_state) {
1046                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1047                 return STT_ERROR_INVALID_STATE;
1048         }
1049
1050         client->partial_result_cb = NULL;
1051         client->partial_result_user_data = NULL;
1052
1053         return 0;
1054 }
1055
1056 int stt_set_state_changed_cb(stt_h stt, stt_state_changed_cb callback, void* user_data)
1057 {
1058         if (NULL == stt || NULL == callback)
1059                 return STT_ERROR_INVALID_PARAMETER;
1060
1061         stt_client_s* client = stt_client_get(stt);
1062
1063         /* check handle */
1064         if (NULL == client) {
1065                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1066                 return STT_ERROR_INVALID_PARAMETER;
1067         }
1068
1069         if (STT_STATE_CREATED != client->current_state) {
1070                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1071                 return STT_ERROR_INVALID_STATE;
1072         }
1073
1074         client->state_changed_cb = callback;
1075         client->state_changed_user_data = user_data;
1076
1077         return 0;
1078 }
1079
1080 int stt_unset_state_changed_cb(stt_h stt)
1081 {
1082         if (NULL == stt)
1083                 return STT_ERROR_INVALID_PARAMETER;
1084
1085         stt_client_s* client = stt_client_get(stt);
1086
1087         /* check handle */
1088         if (NULL == client) {
1089                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] A handle is not available");
1090                 return STT_ERROR_INVALID_PARAMETER;
1091         }
1092
1093         if (STT_STATE_CREATED != client->current_state) {
1094                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Current state is not 'ready'."); 
1095                 return STT_ERROR_INVALID_STATE;
1096         }
1097
1098         client->state_changed_cb = NULL;
1099         client->state_changed_user_data = NULL;
1100
1101         return 0;
1102 }
1103
1104
1105 int stt_set_error_cb(stt_h stt, stt_error_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->error_cb = callback;
1124         client->error_user_data = user_data;
1125
1126         return 0;
1127 }
1128
1129 int stt_unset_error_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->error_cb = NULL;
1148         client->error_user_data = NULL;
1149
1150         return 0;
1151 }
1152
1153 int __get_cmd_line(char *file, char *buf) 
1154 {
1155         FILE *fp = NULL;
1156
1157         fp = fopen(file, "r");
1158         if (fp == NULL) {
1159                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Get command line");
1160                 return -1;
1161         }
1162
1163         memset(buf, 0, 256);
1164         if (NULL == fgets(buf, 256, fp)) {
1165                 SLOG(LOG_ERROR, TAG_STTC, "[ERROR] Fail to fget command line");
1166                 fclose(fp);
1167                 return -1;
1168         }
1169         fclose(fp);
1170
1171         return 0;
1172 }
1173
1174 static bool __stt_is_alive()
1175 {
1176         DIR *dir;
1177         struct dirent *entry;
1178         struct stat filestat;
1179         
1180         int pid;
1181         char cmdLine[256];
1182         char tempPath[256];
1183
1184         dir  = opendir("/proc");
1185         if (NULL == dir) {
1186                 SLOG(LOG_ERROR, TAG_STTC, "process checking is FAILED");
1187                 return FALSE;
1188         }
1189
1190         while ((entry = readdir(dir)) != NULL) {
1191                 if (0 != lstat(entry->d_name, &filestat))
1192                         continue;
1193
1194                 if (!S_ISDIR(filestat.st_mode))
1195                         continue;
1196
1197                 pid = atoi(entry->d_name);
1198                 if (pid <= 0) continue;
1199
1200                 sprintf(tempPath, "/proc/%d/cmdline", pid);
1201                 if (0 != __get_cmd_line(tempPath, cmdLine)) {
1202                         continue;
1203                 }
1204                 if ( 0 == strncmp(cmdLine, "[stt-daemon]", strlen("[stt-daemon]")) ||
1205                         0 == strncmp(cmdLine, "stt-daemon", strlen("stt-daemon")) ||
1206                         0 == strncmp(cmdLine, "/usr/bin/stt-daemon", strlen("/usr/bin/stt-daemon"))) {
1207                                 SLOG(LOG_DEBUG, TAG_STTC, "stt-daemon is ALIVE !! \n");
1208                                 closedir(dir);
1209                                 return TRUE;
1210                 }
1211         }
1212         SLOG(LOG_DEBUG, TAG_STTC, "THERE IS NO stt-daemon !! \n");
1213
1214         closedir(dir);
1215         return FALSE;
1216
1217 }
1218
1219 static int __check_stt_daemon()
1220 {
1221         if( TRUE == __stt_is_alive() )
1222                 return 0;
1223         
1224         /* fork-exec stt-daemon */
1225         int pid, i;
1226
1227         pid = fork();
1228
1229         switch(pid) {
1230         case -1:
1231                 SLOG(LOG_DEBUG, TAG_STTC, "[STT ERROR] fail to create STT-DAEMON \n");
1232                 break;
1233
1234         case 0:
1235                 setsid();
1236                 for (i = 0;i < _NSIG;i++)
1237                         signal(i, SIG_DFL);
1238
1239                 execl("/usr/bin/stt-daemon", "/usr/bin/stt-daemon", NULL);
1240                 break;
1241
1242         default:
1243                 break;
1244         }
1245
1246         return 0;
1247 }
1248
1249
1250
1251