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