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