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.
18 #include <vconf-keys.h>
19 #include <sound_manager.h>
21 #include "SttManager.h"
22 #include "ise-stt-mode.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)
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";
47 return (const char *) "ABNORMAL CASE";
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)
55 SttManager::SttManager(ISttFeedback& feedback)
56 : ifeedback(feedback),
64 int ret = static_cast<int>(stt_create(&handle));
66 if (ret != STT_ERROR_NONE)
67 throw SttException(ret, ErrorString((stt_error_e)ret));
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);
75 * Set default properties
80 catch(SttException &e) {
81 LOGW("reason : %s", e.what());
85 SttManager::~SttManager() {
87 EnableFeedback(false);
92 catch(SttException &e) {
93 LOGW("reason : %s", e.what());
99 sound_manager_destroy_stream_information(g_stream_info_h);
102 void SttManager::Prepare() {
104 * Prepare stt service.
107 int ret = stt_prepare(handle);
109 if (ret != STT_ERROR_NONE)
110 throw SttException(ret, ErrorString((stt_error_e)ret));
113 void SttManager::UnPrepare() {
115 * UnPrepare stt service.
118 int ret = stt_unprepare(handle);
120 if (ret != STT_ERROR_NONE)
121 throw SttException(ret, ErrorString((stt_error_e)ret));
124 void SttManager::Start() {
125 if (!Validate((int) READY)) {
126 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_READY");
137 asrtype = STT_RECOGNITION_TYPE_FREE_PARTIAL;
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);
145 ret = stt_start(handle, language.c_str(), asrtype.c_str());
147 if (ret != STT_ERROR_NONE)
148 throw SttException(ret, ErrorString((stt_error_e)ret));
151 void SttManager::Stop() {
152 if (!Validate((int) RECORDING)) {
153 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_RECORDING");
160 int ret = stt_stop(handle);
162 if (ret != STT_ERROR_NONE)
163 throw SttException(ret, ErrorString((stt_error_e)ret));
166 void SttManager::Cancel() {
168 LOGD("iscancelled (%d)", iscancelled);
172 if (!Validate((int) (RECORDING|PROCESSING))) {
173 throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !(STT_STATE_RECORDING or STT_STATE_PROCESSING)");
177 * Cancel stt service (recording, processing)
180 int ret = stt_cancel(handle);
182 if (ret != STT_ERROR_NONE)
183 throw SttException(ret, ErrorString((stt_error_e)ret));
186 LOGD("iscancelled (%d)", iscancelled);
191 bool SttManager::Validate(int state) {
194 int ret = stt_get_state(handle, &cur);
195 if (ret != STT_ERROR_NONE) {
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");
207 case STT_STATE_CREATED:
208 if (state & CREATE) return true;
210 case STT_STATE_READY:
211 if (state & READY) return true;
213 case STT_STATE_RECORDING:
214 if (state & RECORDING) return true;
216 case STT_STATE_PROCESSING:
217 if (state & PROCESSING) return true;
226 void SttManager::Initialize() {
227 /** Todo. add routine to intialize */
230 void SttManager::PrintResultState(stt_result_event_e result_type)
234 switch (result_type) {
235 case STT_RESULT_EVENT_FINAL_RESULT:
236 result = "STT_RESULT_EVENT_FINAL_RESULT";
238 case STT_RESULT_EVENT_PARTIAL_RESULT:
239 result = "STT_RESULT_EVENT_PARTIAL_RESULT";
241 case STT_RESULT_EVENT_ERROR:
242 result = "STT_RESULT_EVENT_ERROR";
248 SECURE_LOGD("result type : %s", result.c_str());
251 void SttManager::on_result(
253 stt_result_event_e event,
258 PrintResultState(event);
261 LOGD("user_data null");
262 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
265 SttManager& manager = *((SttManager *) user_data);
267 std::vector<std::string> results;
269 LOGD("result size : %d, msg : %s", size, msg);
271 for (size_t i = 0; i < (size_t) size; i++) {
273 results.push_back(std::string(data[i]));
277 manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(msg));
279 manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(""));
283 void SttManager::PrintState(stt_state_e previous, stt_state_e current)
289 case STT_STATE_READY:
290 prev = "STT_STATE_READY";
292 case STT_STATE_CREATED:
293 prev = "STT_STATE_CREATED";
295 case STT_STATE_RECORDING:
296 prev = "STT_STATE_RECORDING";
298 case STT_STATE_PROCESSING:
299 prev = "STT_STATE_PROCESSING";
307 case STT_STATE_READY:
308 curr = "STT_STATE_READY";
310 case STT_STATE_CREATED:
311 curr = "STT_STATE_CREATED";
313 case STT_STATE_RECORDING:
314 curr = "STT_STATE_RECORDING";
316 case STT_STATE_PROCESSING:
317 curr = "STT_STATE_PROCESSING";
323 LOGD("previous: %s(%d), current: %s(%d)", prev.c_str(), previous, curr.c_str(), current);
326 void SttManager::on_state_changed(
328 stt_state_e previous,
331 PrintState(previous, current);
332 LOGD("SttManager::on_state_changed");
335 throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
337 SttManager& manager = *((SttManager *) user_data);
339 if (current== STT_STATE_READY) {
340 if (previous == STT_STATE_RECORDING ||
341 previous == STT_STATE_PROCESSING) {
345 if (previous == STT_STATE_CREATED) {
346 manager.EnableSilenceDetection();
347 manager.ifeedback.AutoStart();
348 } else if (previous == STT_STATE_RECORDING) {
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();
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 LOGD("iscancelled (%d)", manager.iscancelled);
363 manager.ifeedback.SttProcessing();
365 manager.iscancelled = false;
366 LOGD("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 LOGD("Error reason %s(%d)", res.c_str(), reason);
422 void SttManager::on_error(
426 LOGW("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 LOGD("SttManager::EnableFeedback");
441 int ret = STT_ERROR_NONE;
443 void *udata = static_cast<void *>(this);
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));
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));
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));
458 ret = stt_unset_error_cb(handle);
459 if (STT_ERROR_NONE != ret)
460 throw SttException(ret, ErrorString((stt_error_e)ret));
462 ret = stt_unset_state_changed_cb(handle);
463 if (STT_ERROR_NONE != ret)
464 throw SttException(ret, ErrorString((stt_error_e)ret));
466 ret = stt_unset_recognition_result_cb(handle);
467 if (STT_ERROR_NONE != ret)
468 throw SttException(ret, ErrorString((stt_error_e)ret));
472 const char* SttManager::ErrorString(int ecode) {
473 const char *str = NULL;
476 case STT_ERROR_OUT_OF_MEMORY:
477 str = (const char *) "STT_ERROR_OUT_OF_MEMORY";
479 case STT_ERROR_IO_ERROR:
480 str = (const char *) "STT_ERROR_IO_ERROR";
482 case STT_ERROR_INVALID_PARAMETER:
483 str = (const char *) "STT_ERROR_INVALID_PARAMETER";
485 case STT_ERROR_TIMED_OUT:
486 str = (const char *) "STT_ERROR_TIMED_OUT";
488 case STT_ERROR_RECORDER_BUSY:
489 str = (const char *) "STT_ERROR_RECORDER_BUSY";
491 case STT_ERROR_OUT_OF_NETWORK:
492 str = (const char *) "STT_ERROR_OUT_OF_NETWORK";
494 case STT_ERROR_INVALID_STATE:
495 str = (const char *) " STT_ERROR_INVALID_STATE";
497 case STT_ERROR_INVALID_LANGUAGE:
498 str = (const char *) "STT_ERROR_INVALID_LANGUAGE";
500 case STT_ERROR_ENGINE_NOT_FOUND:
501 str = (const char *) "STT_ERROR_ENGINE_NOT_FOUND";
503 case STT_ERROR_OPERATION_FAILED:
504 str = (const char *) "STT_ERROR_OPERATION_FAILED";
506 case STT_ERROR_NOT_SUPPORTED_FEATURE:
507 str = (const char *) "STT_ERROR_NOT_SUPPORTED_FEATURE";
513 void SttManager::SoundFeedback() {
516 void SttManager::EnableSilenceDetection(bool enabled) {
517 stt_option_silence_detection_e s_option;
520 s_option = STT_OPTION_SILENCE_DETECTION_TRUE;
522 s_option = STT_OPTION_SILENCE_DETECTION_FALSE;
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));
528 LOGD("stt_set_silence_detection Successful");
532 void SttManager::ReleaseSoundFocus()
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);