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