2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <vconf-keys.h>
20 #include <sound_manager.h>
23 #include "SttManager.h"
25 using namespace is::stt;
34 static sound_stream_info_h g_stream_info_h = NULL;
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";
40 else if (cur == STT_STATE_READY)
41 return (const char *) "STT_STATE_READY";
43 else if (cur == STT_STATE_RECORDING)
44 return (const char *) "STT_STATE_RECORDING";
46 else if (cur == STT_STATE_PROCESSING)
47 return (const char *) "STT_STATE_PROCESSING";
50 return (const char *) "ABNORMAL CASE";
53 static void player_focus_state_cb(sound_stream_info_h stream_info, sound_stream_focus_change_reason_e reason_for_change, const char *extra_info, void *user_data)
57 SttManager::SttManager(ISttFeedback& feedback)
58 : ifeedback(feedback),
66 int ret = stt_create(&handle);
68 if(ret != STT_ERROR_NONE)
69 throw SttException(ret, ErrorString((stt_error_e)ret));
71 ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_RECOGNITION, player_focus_state_cb, NULL, &g_stream_info_h);
72 if (SOUND_MANAGER_ERROR_NONE != ret) {
73 LOGW("Fail to create stream info. ret : %d", ret);
77 * Set default properties
82 catch(SttException &e) {
83 PRINTFUNC(DLOG_ERROR, "reason : %s", e.what());
88 SttManager::~SttManager() {
90 EnableFeedback(false);
95 catch(SttException &e) {
96 PRINTFUNC(DLOG_ERROR, "reason : %s", e.what());
102 sound_manager_destroy_stream_information(g_stream_info_h);
105 void SttManager::Prepare() {
107 * Prepare stt service.
110 int ret = stt_prepare(handle);
112 if(ret != STT_ERROR_NONE)
113 throw SttException(ret, ErrorString((stt_error_e)ret));
116 void SttManager::UnPrepare() {
118 * UnPrepare stt service.
121 int ret = stt_unprepare(handle);
123 if (ret != STT_ERROR_NONE)
124 throw SttException(ret, ErrorString((stt_error_e)ret));
127 void SttManager::Start() {
128 if(!Validate((int) READY)) {
129 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_READY");
132 PRINTFUNC(DLOG_DEBUG, "HERE");
140 asrtype = STT_RECOGNITION_TYPE_FREE_PARTIAL;
143 ret = sound_manager_acquire_focus(g_stream_info_h, (sound_stream_focus_mask_e)(SOUND_STREAM_FOCUS_FOR_PLAYBACK | SOUND_STREAM_FOCUS_FOR_RECORDING), NULL);
144 if (SOUND_MANAGER_ERROR_NONE != ret) {
145 LOGW("Fail to acquire playback or recording focus. ret : %d, stream handle : %p", ret, g_stream_info_h);
148 ret = stt_start(handle, language.c_str(), asrtype.c_str());
150 if(ret != STT_ERROR_NONE)
151 throw SttException(ret, ErrorString((stt_error_e)ret));
154 void SttManager::Stop() {
155 if(!Validate((int) RECORDING)) {
156 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_RECORDING");
163 int ret = stt_stop(handle);
165 if(ret != STT_ERROR_NONE)
166 throw SttException(ret, ErrorString((stt_error_e)ret));
169 void SttManager::Cancel() {
171 PRINTFUNC(DLOG_WARN, "iscancelled (%d)", iscancelled);
175 if(!Validate((int) (RECORDING|PROCESSING))) {
176 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !(STT_STATE_RECORDING or STT_STATE_PROCESSING)");
180 * Cancel stt service (recording, processing)
183 int ret = stt_cancel(handle);
185 if(ret != STT_ERROR_NONE)
186 throw SttException(ret, ErrorString((stt_error_e)ret));
189 PRINTFUNC(DLOG_INFO, "iscancelled (%d)", iscancelled);
195 bool SttManager::Validate(int state) {
198 int ret = stt_get_state(handle, &cur);
199 if (ret != STT_ERROR_NONE) {
203 PRINTFUNC(DLOG_DEBUG, "validate state - %d", state);
204 PRINTFUNC(DLOG_DEBUG, "stt deamon state - %s",
205 cur == STT_STATE_CREATED ? "STT_STATE_CREATED" :
206 cur == STT_STATE_READY ? "STT_STATE_READY" :
207 cur == STT_STATE_RECORDING ? "STT_STATE_RECORDING" :
208 cur == STT_STATE_PROCESSING ? "STT_STATE_PROCESSING" : "ABNORMAL");
211 case STT_STATE_CREATED :
212 if (state & CREATE) return true;
214 case STT_STATE_READY :
215 if (state & READY) return true;
217 case STT_STATE_RECORDING :
218 if (state & RECORDING) return true;
220 case STT_STATE_PROCESSING :
221 if (state & PROCESSING) return true;
230 void SttManager::Initialize() {
231 /** Todo. add routine to intialize */
234 void SttManager::PrintResultState(stt_result_event_e result_type)
238 switch (result_type) {
239 case STT_RESULT_EVENT_FINAL_RESULT :
240 result = "STT_RESULT_EVENT_FINAL_RESULT";
242 case STT_RESULT_EVENT_PARTIAL_RESULT :
243 result = "STT_RESULT_EVENT_PARTIAL_RESULT";
245 case STT_RESULT_EVENT_ERROR :
246 result = "STT_RESULT_EVENT_ERROR";
252 PRINTFUNC(DLOG_INFO, "result type : %s", result.c_str());
255 void SttManager::on_result(
257 stt_result_event_e event,
262 PrintResultState(event);
265 PRINTFUNC(DLOG_ERROR, "user_data null");
266 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
269 SttManager& manager = *((SttManager *) user_data);
271 std::vector<std::string> results;
273 PRINTFUNC(DLOG_INFO, "result size : %d, msg : %s", size, msg);
275 for (size_t i = 0; i < (size_t) size; i++) {
277 results.push_back(std::string(data[i]));
281 manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(msg));
283 manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(""));
287 void SttManager::PrintState(stt_state_e previous, stt_state_e current)
293 case STT_STATE_READY :
294 prev = "STT_STATE_READY";
296 case STT_STATE_CREATED :
297 prev = "STT_STATE_CREATED";
299 case STT_STATE_RECORDING :
300 prev = "STT_STATE_RECORDING";
302 case STT_STATE_PROCESSING :
303 prev = "STT_STATE_PROCESSING";
311 case STT_STATE_READY :
312 curr = "STT_STATE_READY";
314 case STT_STATE_CREATED :
315 curr = "STT_STATE_CREATED";
317 case STT_STATE_RECORDING :
318 curr = "STT_STATE_RECORDING";
320 case STT_STATE_PROCESSING :
321 curr = "STT_STATE_PROCESSING";
327 PRINTFUNC(DLOG_INFO, "previous: %s(%d), current: %s(%d)", prev.c_str(), previous, curr.c_str(), current);
330 void SttManager::on_state_changed(
332 stt_state_e previous,
335 PrintState(previous, current);
338 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
340 SttManager& manager = *((SttManager *) user_data);
342 if (current== STT_STATE_READY) {
343 if (previous == STT_STATE_RECORDING ||
344 previous == STT_STATE_PROCESSING) {
348 if (previous == STT_STATE_CREATED) {
349 manager.EnableSilenceDetection();
350 manager.ifeedback.AutoStart();
351 } else if (previous == STT_STATE_RECORDING) {
353 std::vector<std::string> results;
354 manager.ifeedback.OnResult(manager.asrtype, STT_RESULT_EVENT_ERROR, results, msg);
356 manager.ifeedback.SttIdle();
358 } else if (current == STT_STATE_RECORDING) {
359 manager.ifeedback.SttRecording();
360 } else if (current == STT_STATE_PROCESSING) {
361 if (!manager.iscancelled) {
362 PRINTFUNC(DLOG_INFO, "iscancelled (%d)", manager.iscancelled);
363 manager.ifeedback.SttProcessing();
365 manager.iscancelled = false;
366 PRINTFUNC(DLOG_INFO, "iscancelled (%d)", manager.iscancelled);
371 void SttManager::PrintErrorState(stt_error_e reason)
376 case STT_ERROR_OUT_OF_MEMORY :
377 res = "STT_ERROR_OUT_OF_MEMORY";
379 case STT_ERROR_IO_ERROR :
380 res = "STT_ERROR_IO_ERROR";
382 case STT_ERROR_INVALID_PARAMETER :
383 res = "STT_ERROR_INVALID_PARAMETER";
385 case STT_ERROR_TIMED_OUT :
386 res = "STT_ERROR_TIMED_OUT";
388 case STT_ERROR_RECORDER_BUSY :
389 res = "STT_ERROR_RECORDER_BUSY";
391 case STT_ERROR_OUT_OF_NETWORK :
392 res = "STT_ERROR_OUT_OF_NETWORK";
394 case STT_ERROR_PERMISSION_DENIED :
395 res = "STT_ERROR_PERMISSION_DENIED";
397 case STT_ERROR_NOT_SUPPORTED :
398 res = "STT_ERROR_NOT_SUPPORTED";
400 case STT_ERROR_INVALID_STATE :
401 res = "STT_ERROR_INVALID_STATE";
403 case STT_ERROR_INVALID_LANGUAGE :
404 res = "STT_ERROR_INVALID_LANGUAGE";
406 case STT_ERROR_ENGINE_NOT_FOUND :
407 res = "STT_ERROR_ENGINE_NOT_FOUND";
409 case STT_ERROR_OPERATION_FAILED :
410 res = "STT_ERROR_OPERATION_FAILED";
412 case STT_ERROR_NOT_SUPPORTED_FEATURE :
413 res = "STT_ERROR_NOT_SUPPORTED_FEATURE";
416 res = "UNKNOWN ERROR REASON";
419 PRINTFUNC(DLOG_INFO, "Error reason %s(%d)", res.c_str(), reason);
422 void SttManager::on_error(
426 PRINTFUNC(DLOG_INFO, "stt-daemon error (%d)", reason);
429 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
431 SttManager& manager = *((SttManager *) user_data);
432 manager.ifeedback.OnError(reason);
435 void SttManager::SetLanguage(std::string language) {
436 this->language = language;
439 void SttManager::EnableFeedback(bool enabled) {
440 int ret = STT_ERROR_NONE;
442 void *udata = static_cast<void *>(this);
445 ret = stt_set_recognition_result_cb(handle, on_result, udata);
446 if (STT_ERROR_NONE != ret)
447 throw SttException(ret, ErrorString((stt_error_e)ret));
449 ret = stt_set_error_cb(handle, on_error, udata);
450 if (STT_ERROR_NONE != ret)
451 throw SttException(ret, ErrorString((stt_error_e)ret));
453 ret = stt_set_state_changed_cb(handle, on_state_changed, udata);
454 if (STT_ERROR_NONE != ret)
455 throw SttException(ret, ErrorString((stt_error_e)ret));
457 ret = stt_unset_error_cb(handle);
458 if (STT_ERROR_NONE != ret)
459 throw SttException(ret, ErrorString((stt_error_e)ret));
461 ret = stt_unset_state_changed_cb(handle);
462 if (STT_ERROR_NONE != ret)
463 throw SttException(ret, ErrorString((stt_error_e)ret));
465 ret = stt_unset_recognition_result_cb(handle);
466 if (STT_ERROR_NONE != ret)
467 throw SttException(ret, ErrorString((stt_error_e)ret));
471 const char* SttManager::ErrorString(int ecode) {
472 const char *str = NULL;
475 case STT_ERROR_OUT_OF_MEMORY:
476 str = (const char *) "STT_ERROR_OUT_OF_MEMORY";
478 case STT_ERROR_IO_ERROR:
479 str = (const char *) "STT_ERROR_IO_ERROR";
481 case STT_ERROR_INVALID_PARAMETER:
482 str = (const char *) "STT_ERROR_INVALID_PARAMETER";
484 case STT_ERROR_TIMED_OUT:
485 str = (const char *) "STT_ERROR_TIMED_OUT";
487 case STT_ERROR_RECORDER_BUSY:
488 str = (const char *) "STT_ERROR_RECORDER_BUSY";
490 case STT_ERROR_OUT_OF_NETWORK:
491 str = (const char *) "STT_ERROR_OUT_OF_NETWORK";
493 case STT_ERROR_INVALID_STATE:
494 str = (const char *) " STT_ERROR_INVALID_STATE";
496 case STT_ERROR_INVALID_LANGUAGE:
497 str = (const char *) "STT_ERROR_INVALID_LANGUAGE";
499 case STT_ERROR_ENGINE_NOT_FOUND:
500 str = (const char *) "STT_ERROR_ENGINE_NOT_FOUND";
502 case STT_ERROR_OPERATION_FAILED:
503 str = (const char *) "STT_ERROR_OPERATION_FAILED";
505 case STT_ERROR_NOT_SUPPORTED_FEATURE:
506 str = (const char *) "STT_ERROR_NOT_SUPPORTED_FEATURE";
512 void SttManager::SoundFeedback() {
514 int is_sound_vibe = 0;
516 if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &is_sound)) {
517 PRINTFUNC(DLOG_ERROR, "get sound status failed.");
520 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &is_sound_vibe)) {
521 PRINTFUNC(DLOG_ERROR, "get vibe status failed.");
524 if (is_sound || is_sound_vibe) {
525 stt_set_start_sound(handle, "/usr/share/ise-voice-input/audio/voice_start.wav");
526 stt_set_stop_sound(handle, "/usr/share/ise-voice-input/audio/voice_stop.wav");
528 stt_unset_start_sound(handle);
529 stt_unset_stop_sound(handle);
535 void SttManager::EnableSilenceDetection(bool enabled) {
536 stt_option_silence_detection_e s_option;
539 s_option = STT_OPTION_SILENCE_DETECTION_TRUE;
541 s_option = STT_OPTION_SILENCE_DETECTION_FALSE;
543 int ret = stt_set_silence_detection(handle, s_option);
544 if (STT_ERROR_NONE != ret) {
549 ErrorString((stt_error_e) ret));
551 PRINTFUNC(NO_PRINT, "stt_set_silence_detection Successful");
555 void SttManager::ReleaseSoundFocus()
557 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), NULL);
558 if (SOUND_MANAGER_ERROR_NONE != ret) {
559 LOGW("Fail to release playback or recording focus. ret : %d", ret);