Add initial code for inputdelegator
[platform/core/uifw/inputdelegator.git] / src / SttManager.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <assert.h>
18 #include <vconf.h>
19 #include <vconf-keys.h>
20
21 #include "Debug.h"
22 #include "SttManager.h"
23
24 using namespace is::stt;
25
26 enum {
27         READY = 0x0001,
28         RECORDING = 0x0010,
29         PROCESSING = 0x0100,
30         CREATE = 0x1000
31 };
32
33 static inline const char *stt_state_str(stt_state_e cur) {
34
35         if(cur == STT_STATE_CREATED)
36                 return (const char *) "STT_STATE_CREATED";
37
38         else if(cur == STT_STATE_READY)
39                 return (const char *) "STT_STATE_READY";
40
41         else if(cur == STT_STATE_RECORDING)
42                 return (const char *) "STT_STATE_RECORDING";
43
44         else if(cur == STT_STATE_PROCESSING)
45                 return (const char *) "STT_STATE_PROCESSING";
46
47         else
48                 return (const char *) "ABNORMAL CASE";
49 }
50
51
52 SttManager::SttManager(ISttFeedback& feedback)
53 : ifeedback(feedback),
54   iscancelled(false)
55 {
56
57    try {
58                 /**
59                 * Create stt handle.
60                 *
61                 */
62                 int ret = stt_create(&handle);
63
64                 if(ret != STT_ERROR_NONE)
65                         throw SttException(ret, ErrorString((stt_error_e)ret));
66
67                 /**
68                 * Set default properties
69                 *
70                 */
71                 EnableFeedback();
72         }
73         catch(SttException &e) {
74                 PRINTFUNC(DLOG_ERROR, "reason : %s", e.what());
75                 assert(0);
76         }
77 }
78
79
80
81 SttManager::~SttManager() {
82
83         try {
84                 EnableFeedback(false);
85
86                 Cancel();
87                 UnPrepare();
88         }
89         catch(SttException &e) {
90                 PRINTFUNC(DLOG_ERROR, "reason : %s", e.what());
91                 stt_destroy(handle);
92         }
93 }
94
95 void SttManager::Prepare() {
96
97         /**
98         * Prepare stt service.
99         *
100         */
101         int ret = stt_prepare(handle);
102
103         if(ret != STT_ERROR_NONE)
104                 throw SttException(ret, ErrorString((stt_error_e)ret));
105 }
106
107
108
109 void SttManager::UnPrepare() {
110
111    /**
112     * UnPrepare stt service.
113     *
114     */
115    int ret = stt_unprepare(handle);
116
117    if(ret != STT_ERROR_NONE)
118            throw SttException(ret, ErrorString((stt_error_e)ret));
119 }
120
121
122
123 void SttManager::Start() {
124
125         if(!Validate((int) READY)) {
126             throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_READY");
127         }
128
129         PRINTFUNC(DLOG_DEBUG, "HERE");
130
131         iscancelled = false;
132
133         /**
134         * Start stt service.
135         *
136         */
137         asrtype = STT_RECOGNITION_TYPE_FREE_PARTIAL;
138         int ret;
139
140         bool bval = false;
141
142 //      stt_is_samsung_asr(&bval);
143
144         if( bval == true && !language.compare("en_GB")) {
145                 PRINTFUNC(DLOG_DEBUG, "en_GB requested, change to en_US");
146         ret = stt_start(handle, "en_US", asrtype.c_str());
147         } else {
148         ret = stt_start(handle, language.c_str(), asrtype.c_str());
149         }
150
151         if(ret != STT_ERROR_NONE)
152                 throw SttException(ret, ErrorString((stt_error_e)ret));
153 }
154
155
156
157 void SttManager::Stop() {
158
159         if(!Validate((int) RECORDING)) {
160                 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_RECORDING");
161         }
162
163         /**
164         * Stop stt service.
165         *
166         */
167         int ret = stt_stop(handle);
168
169         if(ret != STT_ERROR_NONE)
170                 throw SttException(ret, ErrorString((stt_error_e)ret));
171 }
172
173
174
175 void SttManager::Cancel() {
176
177         if(iscancelled) {
178                 PRINTFUNC(DLOG_WARN, "iscancelled (%d)", iscancelled);
179                 return;
180         }
181
182         if(!Validate((int) (RECORDING|PROCESSING))) {
183                 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !(STT_STATE_RECORDING or STT_STATE_PROCESSING)");
184         }
185
186         /**
187         * Cancel stt service (recording, processing)
188         *
189         */
190         int ret = stt_cancel(handle);
191
192         if(ret != STT_ERROR_NONE)
193                 throw SttException(ret, ErrorString((stt_error_e)ret));
194
195         iscancelled = true;
196         PRINTFUNC(DLOG_INFO, "iscancelled (%d)", iscancelled);
197
198         ifeedback.SttIdle();
199 }
200
201
202 bool SttManager::Validate(int state) {
203
204         stt_state_e cur;
205
206         int ret = stt_get_state(handle, &cur);
207         if(ret != STT_ERROR_NONE) {
208                 return false;
209         }
210
211         PRINTFUNC(DLOG_DEBUG, "validate state - %d", state);
212         PRINTFUNC(DLOG_DEBUG, "stt deamon state - %s",
213                 cur == STT_STATE_CREATED ? "STT_STATE_CREATED" :
214                 cur == STT_STATE_READY ? "STT_STATE_READY" :
215                 cur == STT_STATE_RECORDING ? "STT_STATE_RECORDING" :
216                 cur == STT_STATE_PROCESSING ? "STT_STATE_PROCESSING" : "ABNORMAL");
217
218         switch(cur) {
219                 case STT_STATE_CREATED :
220                         if(state & CREATE) return true;
221                         break;
222                 case STT_STATE_READY :
223                         if(state & READY) return true;
224                         break;
225                 case STT_STATE_RECORDING :
226                         if(state & RECORDING) return true;
227                         break;
228                 case STT_STATE_PROCESSING :
229                         if(state & PROCESSING) return true;
230                         break;
231                 default :
232                         break;
233         }
234
235         return false;
236 }
237
238
239
240 void SttManager::Initialize() {
241
242    /** Todo. add routine to intialize */
243 }
244
245 void SttManager::PrintResultState(stt_result_event_e result_type)
246 {
247         std::string result;
248
249         switch (result_type) {
250                 case STT_RESULT_EVENT_FINAL_RESULT :
251                         result = "STT_RESULT_EVENT_FINAL_RESULT";
252                         break;
253                 case STT_RESULT_EVENT_PARTIAL_RESULT :
254                         result = "STT_RESULT_EVENT_PARTIAL_RESULT";
255                         break;
256                 case STT_RESULT_EVENT_ERROR :
257                         result = "STT_RESULT_EVENT_ERROR";
258                         break;
259                 default :
260                         result = "UNKNOWN";
261                         break;
262         }
263
264         PRINTFUNC(DLOG_INFO, "result type : %s", result.c_str());
265
266 }
267
268 void SttManager::on_result(
269    stt_h handle,
270    stt_result_event_e event,
271    const char** data,
272    int size,
273    const char* msg,
274    void *user_data) {
275
276    PrintResultState(event);
277
278    if(!user_data) {
279                 PRINTFUNC(DLOG_ERROR, "user_data null");
280                 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
281    }
282
283    SttManager& manager = *((SttManager *) user_data);
284
285    std::vector<std::string> results;
286
287    PRINTFUNC(DLOG_INFO, "result size : %d, msg : %s", size, msg);
288
289    for(size_t i = 0; i < (size_t) size; i++) {
290         if(data[i]) {
291                 results.push_back(std::string(data[i]));
292         }
293
294         if(msg)
295            manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(msg));
296         else
297            manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(""));
298    }
299
300 }
301
302 void SttManager::PrintState(stt_state_e previous, stt_state_e current)
303 {
304         std::string prev;
305         std::string curr;
306
307         switch (previous) {
308                 case STT_STATE_READY :
309                         prev = "STT_STATE_READY";
310                         break;
311                 case STT_STATE_CREATED :
312                         prev = "STT_STATE_CREATED";
313                         break;
314                 case STT_STATE_RECORDING :
315                         prev = "STT_STATE_RECORDING";
316                         break;
317                 case STT_STATE_PROCESSING :
318                         prev = "STT_STATE_PROCESSING";
319                         break;
320                 default :
321                         prev = "UNKNOWN";
322                         break;
323         }
324
325         switch (current) {
326                 case STT_STATE_READY :
327                         curr = "STT_STATE_READY";
328                         break;
329                 case STT_STATE_CREATED :
330                         curr = "STT_STATE_CREATED";
331                         break;
332                 case STT_STATE_RECORDING :
333                         curr = "STT_STATE_RECORDING";
334                         break;
335                 case STT_STATE_PROCESSING :
336                         curr = "STT_STATE_PROCESSING";
337                         break;
338                 default :
339                         curr = "UNKNOWN";
340                         break;
341         }
342
343         PRINTFUNC(DLOG_INFO, "previous: %s(%d), current: %s(%d)", prev.c_str(), previous, curr.c_str(), current);
344
345 }
346
347 void SttManager::on_state_changed(
348         stt_h handle,
349         stt_state_e previous,
350         stt_state_e current,
351         void *user_data) {
352
353         PrintState(previous, current);
354
355         if(!user_data)
356                 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
357
358         SttManager& manager = *((SttManager *) user_data);
359
360         if(current== STT_STATE_READY) {
361                 if(previous == STT_STATE_CREATED) {
362                         manager.EnableSilenceDetection();
363                         manager.ifeedback.AutoStart();
364                 }
365                 else if(previous == STT_STATE_RECORDING) {
366                         std::string msg;
367                         std::vector<std::string> results;
368                         manager.ifeedback.OnResult(manager.asrtype, STT_RESULT_EVENT_ERROR, results, msg);
369                 }
370                 else {
371                         manager.ifeedback.SttIdle();
372                 }
373         }
374         else if(current == STT_STATE_RECORDING) {
375                         manager.ifeedback.SttRecording();
376         }
377         else if(current == STT_STATE_PROCESSING) {
378                 if(!manager.iscancelled) {
379                         PRINTFUNC(DLOG_INFO, "iscancelled (%d)", manager.iscancelled);
380                         manager.ifeedback.SttProcessing();
381                 }
382                 else {
383                         manager.iscancelled = false;
384                         PRINTFUNC(DLOG_INFO, "iscancelled (%d)", manager.iscancelled);
385                 }
386         }
387 }
388
389 void SttManager::PrintErrorState(stt_error_e reason)
390 {
391         std::string res;
392
393         switch (reason) {
394                 case STT_ERROR_OUT_OF_MEMORY :
395                         res = "STT_ERROR_OUT_OF_MEMORY";
396                         break;
397                 case STT_ERROR_IO_ERROR :
398                         res = "STT_ERROR_IO_ERROR";
399                         break;
400                 case STT_ERROR_INVALID_PARAMETER :
401                         res = "STT_ERROR_INVALID_PARAMETER";
402                         break;
403                 case STT_ERROR_TIMED_OUT :
404                         res = "STT_ERROR_TIMED_OUT";
405                         break;
406                 case STT_ERROR_RECORDER_BUSY :
407                         res = "STT_ERROR_RECORDER_BUSY";
408                         break;
409                 case STT_ERROR_OUT_OF_NETWORK :
410                         res = "STT_ERROR_OUT_OF_NETWORK";
411                         break;
412                 case STT_ERROR_PERMISSION_DENIED :
413                         res = "STT_ERROR_PERMISSION_DENIED";
414                         break;
415                 case STT_ERROR_NOT_SUPPORTED :
416                         res = "STT_ERROR_NOT_SUPPORTED";
417                         break;
418                 case STT_ERROR_INVALID_STATE :
419                         res = "STT_ERROR_INVALID_STATE";
420                         break;
421                 case STT_ERROR_INVALID_LANGUAGE :
422                         res = "STT_ERROR_INVALID_LANGUAGE";
423                         break;
424                 case STT_ERROR_ENGINE_NOT_FOUND :
425                         res = "STT_ERROR_ENGINE_NOT_FOUND";
426                         break;
427                 case STT_ERROR_OPERATION_FAILED :
428                         res = "STT_ERROR_OPERATION_FAILED";
429                         break;
430                 case STT_ERROR_NOT_SUPPORTED_FEATURE :
431                         res = "STT_ERROR_NOT_SUPPORTED_FEATURE";
432                         break;
433                 default :
434                         res = "UNKNOWN ERROR REASON";
435                         break;
436         }
437
438         PRINTFUNC(DLOG_INFO, "Error reason %s(%d)", res.c_str(), reason);
439
440 }
441
442
443 void SttManager::on_error(
444    stt_h handle,
445    stt_error_e reason,
446    void *user_data) {
447
448    PRINTFUNC(DLOG_INFO, "stt-daemon error (%d)", reason);
449
450    if(!user_data)
451                 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
452
453    SttManager& manager = *((SttManager *) user_data);
454    manager.ifeedback.OnError(reason);
455 }
456
457
458
459 void SttManager::SetLanguage(std::string language) {
460
461    this->language = language;
462 }
463
464
465
466 void SttManager::EnableFeedback(bool enabled) {
467
468    int ret = STT_ERROR_NONE;
469
470    void *udata = static_cast<void *>(this);
471
472    if(enabled) {
473       ret = stt_set_recognition_result_cb(handle, on_result, udata);
474       if(STT_ERROR_NONE != ret)
475                 throw SttException(ret, ErrorString((stt_error_e)ret));
476
477       ret = stt_set_error_cb(handle, on_error, udata);
478       if(STT_ERROR_NONE != ret)
479                 throw SttException(ret, ErrorString((stt_error_e)ret));
480
481       ret = stt_set_state_changed_cb(handle, on_state_changed, udata);
482       if(STT_ERROR_NONE != ret)
483                 throw SttException(ret, ErrorString((stt_error_e)ret));
484    }
485    else {
486       ret = stt_unset_error_cb(handle);
487       if(STT_ERROR_NONE != ret)
488                 throw SttException(ret, ErrorString((stt_error_e)ret));
489
490       ret = stt_unset_state_changed_cb(handle);
491       if(STT_ERROR_NONE != ret)
492                 throw SttException(ret, ErrorString((stt_error_e)ret));
493
494       ret = stt_unset_recognition_result_cb(handle);
495       if(STT_ERROR_NONE != ret)
496                 throw SttException(ret, ErrorString((stt_error_e)ret));
497    }
498 }
499
500
501
502 const char* SttManager::ErrorString(int ecode) {
503
504    const char *str = NULL;
505
506    switch (ecode) {
507       case STT_ERROR_OUT_OF_MEMORY:
508          str = (const char *) "STT_ERROR_OUT_OF_MEMORY";
509          break;
510       case STT_ERROR_IO_ERROR:
511          str = (const char *) "STT_ERROR_IO_ERROR";
512          break;
513       case STT_ERROR_INVALID_PARAMETER:
514          str = (const char *) "STT_ERROR_INVALID_PARAMETER";
515          break;
516       case STT_ERROR_TIMED_OUT:
517          str = (const char *) "STT_ERROR_TIMED_OUT";
518          break;
519       case STT_ERROR_RECORDER_BUSY:
520          str = (const char *) "STT_ERROR_RECORDER_BUSY";
521          break;
522       case STT_ERROR_OUT_OF_NETWORK:
523          str = (const char *) "STT_ERROR_OUT_OF_NETWORK";
524          break;
525       case STT_ERROR_INVALID_STATE:
526          str = (const char *) " STT_ERROR_INVALID_STATE";
527          break;
528       case STT_ERROR_INVALID_LANGUAGE:
529          str = (const char *) "STT_ERROR_INVALID_LANGUAGE";
530          break;
531       case STT_ERROR_ENGINE_NOT_FOUND:
532          str = (const char *) "STT_ERROR_ENGINE_NOT_FOUND";
533          break;
534       case STT_ERROR_OPERATION_FAILED:
535          str = (const char *) "STT_ERROR_OPERATION_FAILED";
536          break;
537       case STT_ERROR_NOT_SUPPORTED_FEATURE:
538          str = (const char *) "STT_ERROR_NOT_SUPPORTED_FEATURE";
539          break;
540    }
541
542    return str;
543 }
544
545
546
547 void SttManager::SoundFeedback() {
548
549    int is_sound = 0;
550    int is_sound_vibe = 0;
551
552    if(vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &is_sound)) {
553       PRINTFUNC(DLOG_ERROR, "get sound status failed.");
554    }
555
556    if(vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &is_sound_vibe)) {
557       PRINTFUNC(DLOG_ERROR, "get vibe status failed.");
558    }
559
560    if(is_sound || is_sound_vibe) {
561       stt_set_start_sound(handle, "/usr/share/ise-voice-input/audio/voice_start.wav");
562       stt_set_stop_sound(handle, "/usr/share/ise-voice-input/audio/voice_stop.wav");
563    }
564    else {
565       stt_unset_start_sound(handle);
566       stt_unset_stop_sound(handle);
567    }
568 }
569
570
571
572 void SttManager::EnableSilenceDetection(bool enabled) {
573
574         stt_option_silence_detection_e s_option;
575
576         if(enabled)
577                 s_option = STT_OPTION_SILENCE_DETECTION_TRUE;
578         else
579                 s_option = STT_OPTION_SILENCE_DETECTION_FALSE;
580
581         int ret = stt_set_silence_detection(handle, s_option);
582         if (STT_ERROR_NONE != ret) {
583                 PRINTFUNC(
584                         DLOG_ERROR,
585                         "error(%d) = %s",
586                         ret,
587                         ErrorString((stt_error_e) ret)
588                 );
589         }
590         else {
591                 PRINTFUNC(NO_PRINT, "stt_set_silence_detection Successful");
592         }
593 }
594