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