Coding rule check
[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         if (cur == STT_STATE_CREATED)
35                 return (const char *) "STT_STATE_CREATED";
36
37         else if (cur == STT_STATE_READY)
38                 return (const char *) "STT_STATE_READY";
39
40         else if (cur == STT_STATE_RECORDING)
41                 return (const char *) "STT_STATE_RECORDING";
42
43         else if (cur == STT_STATE_PROCESSING)
44                 return (const char *) "STT_STATE_PROCESSING";
45
46         else
47                 return (const char *) "ABNORMAL CASE";
48 }
49
50 SttManager::SttManager(ISttFeedback& feedback)
51 : ifeedback(feedback),
52   iscancelled(false)
53 {
54         try {
55                 /**
56                 * Create stt handle.
57                 *
58                 */
59                 int ret = stt_create(&handle);
60
61                 if(ret != STT_ERROR_NONE)
62                         throw SttException(ret, ErrorString((stt_error_e)ret));
63
64                 /**
65                 * Set default properties
66                 *
67                 */
68                 EnableFeedback();
69         }
70         catch(SttException &e) {
71                 PRINTFUNC(DLOG_ERROR, "reason : %s", e.what());
72                 assert(0);
73         }
74 }
75
76 SttManager::~SttManager() {
77         try {
78                 EnableFeedback(false);
79
80                 Cancel();
81                 UnPrepare();
82         }
83         catch(SttException &e) {
84                 PRINTFUNC(DLOG_ERROR, "reason : %s", e.what());
85                 stt_destroy(handle);
86         }
87 }
88
89 void SttManager::Prepare() {
90         /**
91         * Prepare stt service.
92         *
93         */
94         int ret = stt_prepare(handle);
95
96         if(ret != STT_ERROR_NONE)
97                 throw SttException(ret, ErrorString((stt_error_e)ret));
98 }
99
100 void SttManager::UnPrepare() {
101    /**
102     * UnPrepare stt service.
103     *
104     */
105    int ret = stt_unprepare(handle);
106
107    if (ret != STT_ERROR_NONE)
108            throw SttException(ret, ErrorString((stt_error_e)ret));
109 }
110
111 void SttManager::Start() {
112         if(!Validate((int) READY)) {
113             throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_READY");
114         }
115
116         PRINTFUNC(DLOG_DEBUG, "HERE");
117
118         iscancelled = false;
119
120         /**
121         * Start stt service.
122         *
123         */
124         asrtype = STT_RECOGNITION_TYPE_FREE_PARTIAL;
125         int ret;
126
127         bool bval = false;
128
129 //      stt_is_samsung_asr(&bval);
130
131         if( bval == true && !language.compare("en_GB")) {
132                 PRINTFUNC(DLOG_DEBUG, "en_GB requested, change to en_US");
133         ret = stt_start(handle, "en_US", asrtype.c_str());
134         } else {
135         ret = stt_start(handle, language.c_str(), asrtype.c_str());
136         }
137
138         if(ret != STT_ERROR_NONE)
139                 throw SttException(ret, ErrorString((stt_error_e)ret));
140 }
141
142 void SttManager::Stop() {
143         if(!Validate((int) RECORDING)) {
144                 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_RECORDING");
145         }
146
147         /**
148         * Stop stt service.
149         *
150         */
151         int ret = stt_stop(handle);
152
153         if(ret != STT_ERROR_NONE)
154                 throw SttException(ret, ErrorString((stt_error_e)ret));
155 }
156
157 void SttManager::Cancel() {
158         if(iscancelled) {
159                 PRINTFUNC(DLOG_WARN, "iscancelled (%d)", iscancelled);
160                 return;
161         }
162
163         if(!Validate((int) (RECORDING|PROCESSING))) {
164                 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !(STT_STATE_RECORDING or STT_STATE_PROCESSING)");
165         }
166
167         /**
168         * Cancel stt service (recording, processing)
169         *
170         */
171         int ret = stt_cancel(handle);
172
173         if(ret != STT_ERROR_NONE)
174                 throw SttException(ret, ErrorString((stt_error_e)ret));
175
176         iscancelled = true;
177         PRINTFUNC(DLOG_INFO, "iscancelled (%d)", iscancelled);
178
179         ifeedback.SttIdle();
180 }
181
182
183 bool SttManager::Validate(int state) {
184         stt_state_e cur;
185
186         int ret = stt_get_state(handle, &cur);
187         if (ret != STT_ERROR_NONE) {
188                 return false;
189         }
190
191         PRINTFUNC(DLOG_DEBUG, "validate state - %d", state);
192         PRINTFUNC(DLOG_DEBUG, "stt deamon state - %s",
193                 cur == STT_STATE_CREATED ? "STT_STATE_CREATED" :
194                 cur == STT_STATE_READY ? "STT_STATE_READY" :
195                 cur == STT_STATE_RECORDING ? "STT_STATE_RECORDING" :
196                 cur == STT_STATE_PROCESSING ? "STT_STATE_PROCESSING" : "ABNORMAL");
197
198         switch(cur) {
199                 case STT_STATE_CREATED :
200                         if (state & CREATE) return true;
201                         break;
202                 case STT_STATE_READY :
203                         if (state & READY) return true;
204                         break;
205                 case STT_STATE_RECORDING :
206                         if (state & RECORDING) return true;
207                         break;
208                 case STT_STATE_PROCESSING :
209                         if (state & PROCESSING) return true;
210                         break;
211                 default :
212                         break;
213         }
214
215         return false;
216 }
217
218 void SttManager::Initialize() {
219    /** Todo. add routine to intialize */
220 }
221
222 void SttManager::PrintResultState(stt_result_event_e result_type)
223 {
224         std::string result;
225
226         switch (result_type) {
227                 case STT_RESULT_EVENT_FINAL_RESULT :
228                         result = "STT_RESULT_EVENT_FINAL_RESULT";
229                         break;
230                 case STT_RESULT_EVENT_PARTIAL_RESULT :
231                         result = "STT_RESULT_EVENT_PARTIAL_RESULT";
232                         break;
233                 case STT_RESULT_EVENT_ERROR :
234                         result = "STT_RESULT_EVENT_ERROR";
235                         break;
236                 default :
237                         result = "UNKNOWN";
238                         break;
239         }
240         PRINTFUNC(DLOG_INFO, "result type : %s", result.c_str());
241 }
242
243 void SttManager::on_result(
244    stt_h handle,
245    stt_result_event_e event,
246    const char** data,
247    int size,
248    const char* msg,
249    void *user_data) {
250    PrintResultState(event);
251
252    if (!user_data) {
253                 PRINTFUNC(DLOG_ERROR, "user_data null");
254                 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
255    }
256
257    SttManager& manager = *((SttManager *) user_data);
258
259    std::vector<std::string> results;
260
261    PRINTFUNC(DLOG_INFO, "result size : %d, msg : %s", size, msg);
262
263    for (size_t i = 0; i < (size_t) size; i++) {
264         if (data[i]) {
265                 results.push_back(std::string(data[i]));
266         }
267
268         if (msg)
269            manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(msg));
270         else
271            manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(""));
272    }
273 }
274
275 void SttManager::PrintState(stt_state_e previous, stt_state_e current)
276 {
277         std::string prev;
278         std::string curr;
279
280         switch (previous) {
281                 case STT_STATE_READY :
282                         prev = "STT_STATE_READY";
283                         break;
284                 case STT_STATE_CREATED :
285                         prev = "STT_STATE_CREATED";
286                         break;
287                 case STT_STATE_RECORDING :
288                         prev = "STT_STATE_RECORDING";
289                         break;
290                 case STT_STATE_PROCESSING :
291                         prev = "STT_STATE_PROCESSING";
292                         break;
293                 default :
294                         prev = "UNKNOWN";
295                         break;
296         }
297
298         switch (current) {
299                 case STT_STATE_READY :
300                         curr = "STT_STATE_READY";
301                         break;
302                 case STT_STATE_CREATED :
303                         curr = "STT_STATE_CREATED";
304                         break;
305                 case STT_STATE_RECORDING :
306                         curr = "STT_STATE_RECORDING";
307                         break;
308                 case STT_STATE_PROCESSING :
309                         curr = "STT_STATE_PROCESSING";
310                         break;
311                 default :
312                         curr = "UNKNOWN";
313                         break;
314         }
315         PRINTFUNC(DLOG_INFO, "previous: %s(%d), current: %s(%d)", prev.c_str(), previous, curr.c_str(), current);
316 }
317
318 void SttManager::on_state_changed(
319         stt_h handle,
320         stt_state_e previous,
321         stt_state_e current,
322         void *user_data) {
323         PrintState(previous, current);
324
325         if (!user_data)
326                 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
327
328         SttManager& manager = *((SttManager *) user_data);
329
330         if (current== STT_STATE_READY) {
331                 if (previous == STT_STATE_CREATED) {
332                         manager.EnableSilenceDetection();
333                         manager.ifeedback.AutoStart();
334                 } else if (previous == STT_STATE_RECORDING) {
335                         std::string msg;
336                         std::vector<std::string> results;
337                         manager.ifeedback.OnResult(manager.asrtype, STT_RESULT_EVENT_ERROR, results, msg);
338                 } else {
339                         manager.ifeedback.SttIdle();
340                 }
341         } else if (current == STT_STATE_RECORDING) {
342                         manager.ifeedback.SttRecording();
343         } else if (current == STT_STATE_PROCESSING) {
344                 if (!manager.iscancelled) {
345                         PRINTFUNC(DLOG_INFO, "iscancelled (%d)", manager.iscancelled);
346                         manager.ifeedback.SttProcessing();
347                 } else {
348                         manager.iscancelled = false;
349                         PRINTFUNC(DLOG_INFO, "iscancelled (%d)", manager.iscancelled);
350                 }
351         }
352 }
353
354 void SttManager::PrintErrorState(stt_error_e reason)
355 {
356         std::string res;
357
358         switch (reason) {
359                 case STT_ERROR_OUT_OF_MEMORY :
360                         res = "STT_ERROR_OUT_OF_MEMORY";
361                         break;
362                 case STT_ERROR_IO_ERROR :
363                         res = "STT_ERROR_IO_ERROR";
364                         break;
365                 case STT_ERROR_INVALID_PARAMETER :
366                         res = "STT_ERROR_INVALID_PARAMETER";
367                         break;
368                 case STT_ERROR_TIMED_OUT :
369                         res = "STT_ERROR_TIMED_OUT";
370                         break;
371                 case STT_ERROR_RECORDER_BUSY :
372                         res = "STT_ERROR_RECORDER_BUSY";
373                         break;
374                 case STT_ERROR_OUT_OF_NETWORK :
375                         res = "STT_ERROR_OUT_OF_NETWORK";
376                         break;
377                 case STT_ERROR_PERMISSION_DENIED :
378                         res = "STT_ERROR_PERMISSION_DENIED";
379                         break;
380                 case STT_ERROR_NOT_SUPPORTED :
381                         res = "STT_ERROR_NOT_SUPPORTED";
382                         break;
383                 case STT_ERROR_INVALID_STATE :
384                         res = "STT_ERROR_INVALID_STATE";
385                         break;
386                 case STT_ERROR_INVALID_LANGUAGE :
387                         res = "STT_ERROR_INVALID_LANGUAGE";
388                         break;
389                 case STT_ERROR_ENGINE_NOT_FOUND :
390                         res = "STT_ERROR_ENGINE_NOT_FOUND";
391                         break;
392                 case STT_ERROR_OPERATION_FAILED :
393                         res = "STT_ERROR_OPERATION_FAILED";
394                         break;
395                 case STT_ERROR_NOT_SUPPORTED_FEATURE :
396                         res = "STT_ERROR_NOT_SUPPORTED_FEATURE";
397                         break;
398                 default :
399                         res = "UNKNOWN ERROR REASON";
400                         break;
401         }
402         PRINTFUNC(DLOG_INFO, "Error reason %s(%d)", res.c_str(), reason);
403 }
404
405 void SttManager::on_error(
406    stt_h handle,
407    stt_error_e reason,
408    void *user_data) {
409    PRINTFUNC(DLOG_INFO, "stt-daemon error (%d)", reason);
410
411    if (!user_data)
412                 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
413
414    SttManager& manager = *((SttManager *) user_data);
415    manager.ifeedback.OnError(reason);
416 }
417
418 void SttManager::SetLanguage(std::string language) {
419    this->language = language;
420 }
421
422 void SttManager::EnableFeedback(bool enabled) {
423    int ret = STT_ERROR_NONE;
424
425    void *udata = static_cast<void *>(this);
426
427    if (enabled) {
428       ret = stt_set_recognition_result_cb(handle, on_result, udata);
429       if (STT_ERROR_NONE != ret)
430                 throw SttException(ret, ErrorString((stt_error_e)ret));
431
432       ret = stt_set_error_cb(handle, on_error, udata);
433       if (STT_ERROR_NONE != ret)
434                 throw SttException(ret, ErrorString((stt_error_e)ret));
435
436       ret = stt_set_state_changed_cb(handle, on_state_changed, udata);
437       if (STT_ERROR_NONE != ret)
438                 throw SttException(ret, ErrorString((stt_error_e)ret));
439    } else {
440       ret = stt_unset_error_cb(handle);
441       if (STT_ERROR_NONE != ret)
442                 throw SttException(ret, ErrorString((stt_error_e)ret));
443
444       ret = stt_unset_state_changed_cb(handle);
445       if (STT_ERROR_NONE != ret)
446                 throw SttException(ret, ErrorString((stt_error_e)ret));
447
448       ret = stt_unset_recognition_result_cb(handle);
449       if (STT_ERROR_NONE != ret)
450                 throw SttException(ret, ErrorString((stt_error_e)ret));
451    }
452 }
453
454 const char* SttManager::ErrorString(int ecode) {
455    const char *str = NULL;
456
457    switch (ecode) {
458       case STT_ERROR_OUT_OF_MEMORY:
459          str = (const char *) "STT_ERROR_OUT_OF_MEMORY";
460          break;
461       case STT_ERROR_IO_ERROR:
462          str = (const char *) "STT_ERROR_IO_ERROR";
463          break;
464       case STT_ERROR_INVALID_PARAMETER:
465          str = (const char *) "STT_ERROR_INVALID_PARAMETER";
466          break;
467       case STT_ERROR_TIMED_OUT:
468          str = (const char *) "STT_ERROR_TIMED_OUT";
469          break;
470       case STT_ERROR_RECORDER_BUSY:
471          str = (const char *) "STT_ERROR_RECORDER_BUSY";
472          break;
473       case STT_ERROR_OUT_OF_NETWORK:
474          str = (const char *) "STT_ERROR_OUT_OF_NETWORK";
475          break;
476       case STT_ERROR_INVALID_STATE:
477          str = (const char *) " STT_ERROR_INVALID_STATE";
478          break;
479       case STT_ERROR_INVALID_LANGUAGE:
480          str = (const char *) "STT_ERROR_INVALID_LANGUAGE";
481          break;
482       case STT_ERROR_ENGINE_NOT_FOUND:
483          str = (const char *) "STT_ERROR_ENGINE_NOT_FOUND";
484          break;
485       case STT_ERROR_OPERATION_FAILED:
486          str = (const char *) "STT_ERROR_OPERATION_FAILED";
487          break;
488       case STT_ERROR_NOT_SUPPORTED_FEATURE:
489          str = (const char *) "STT_ERROR_NOT_SUPPORTED_FEATURE";
490          break;
491    }
492    return str;
493 }
494
495 void SttManager::SoundFeedback() {
496    int is_sound = 0;
497    int is_sound_vibe = 0;
498
499    if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &is_sound)) {
500       PRINTFUNC(DLOG_ERROR, "get sound status failed.");
501    }
502
503    if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &is_sound_vibe)) {
504       PRINTFUNC(DLOG_ERROR, "get vibe status failed.");
505    }
506
507    if (is_sound || is_sound_vibe) {
508       stt_set_start_sound(handle, "/usr/share/ise-voice-input/audio/voice_start.wav");
509       stt_set_stop_sound(handle, "/usr/share/ise-voice-input/audio/voice_stop.wav");
510    } else {
511       stt_unset_start_sound(handle);
512       stt_unset_stop_sound(handle);
513    }
514 }
515
516
517
518 void SttManager::EnableSilenceDetection(bool enabled) {
519         stt_option_silence_detection_e s_option;
520
521         if (enabled)
522                 s_option = STT_OPTION_SILENCE_DETECTION_TRUE;
523         else
524                 s_option = STT_OPTION_SILENCE_DETECTION_FALSE;
525
526         int ret = stt_set_silence_detection(handle, s_option);
527         if (STT_ERROR_NONE != ret) {
528                 PRINTFUNC(
529                         DLOG_ERROR,
530                         "error(%d) = %s",
531                         ret,
532                         ErrorString((stt_error_e) ret));
533         } else {
534                 PRINTFUNC(NO_PRINT, "stt_set_silence_detection Successful");
535         }
536 }
537