2 * Copyright 2018 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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.
17 #include "wakeup_manager.h"
18 #include "wakeup_manager_main.h"
19 #include "wakeup_policy_default.h"
20 #include "dependency_resolver.h"
23 namespace multiassistant
28 static bool check_language_valid(string language)
33 static bool initialize_wakeup_event_info(wakeup_event_info* info)
39 info->wakeup_appid = nullptr;
40 info->wakeup_word = nullptr;
41 info->wakeup_language = nullptr;
42 info->wakeup_voice_id = nullptr;
43 info->wakeup_engine = nullptr;
44 info->wakeup_confidence_score = 0.0f;
46 info->wakeup_start_time = 0;
47 info->wakeup_end_time = 0L;
48 info->wakeup_time_valid = false;
50 info->extra_data = nullptr;
51 info->extra_data_length = 0;
52 info->extra_data_description = nullptr;
57 CWakeupManager::CWakeupManager(IWakeupEventObserver *observer)
59 initialize_wakeup_event_info(&mLastWakeupEventInfo);
66 CWakeupManager::~CWakeupManager()
70 void CWakeupManager::initialize_wakeup_policy()
72 mWakeupPolicy.reset(new CWakeupPolicyDefault{&mPolicyEventObserver});
74 /* Default Policy specific initialization */
75 CWakeupPolicyDefault *policy =
76 dynamic_cast<CWakeupPolicyDefault*>(mWakeupPolicy.get());
80 policy->set_delay(mWakeupSettings.get_wakeup_policy_delay());
81 MWR_LOGD("Setting Delay : %f", mWakeupSettings.get_wakeup_policy_delay());
82 for (const auto& assistant : mWakeupSettings.get_wakeup_policy_priority()) {
83 policy->set_assistant_priority(assistant, ++priority);
84 MWR_LOGD("Setting Priority : %d %s", priority, assistant.c_str());
89 bool CWakeupManager::initialize()
93 mPolicyEventObserver.set_wakeup_manager(this);
94 mEngineEventObserver.set_wakeup_manager(this);
95 mAudioEventObserver.set_wakeup_manager(this);
96 mSettingsEventObserver.set_wakeup_manager(this);
98 mWakeupSettings.initialize();
100 mAudioEventObserver.set_wakeup_engine_manager(&mWakeupEngineManager);
101 mAudioManager.subscribe(&mAudioEventObserver);
102 mAudioManager.initialize();
104 initialize_wakeup_policy();
106 mWakeupEngineManager.subscribe(&mEngineEventObserver);
107 mWakeupEngineManager.initialize();
109 mas_proxy_interface interface;
110 interface.process_event = wakeup_manager_process_event;
111 interface.feed_audio_data = wakeup_manager_feed_audio_data;
113 dependency_resolver_initialize(interface);
115 mWakeupSettings.subscribe(&mSettingsEventObserver);
121 bool CWakeupManager::deinitialize()
125 dependency_resolver_deinitialize();
127 mWakeupEngineManager.unsubscribe(&mEngineEventObserver);
128 mWakeupEngineManager.deinitialize();
130 mAudioManager.unsubscribe(&mAudioEventObserver);
131 mAudioManager.deinitialize();
133 mWakeupSettings.deinitialize();
134 mAssistantLanguageInfo.clear();
140 void CWakeupManager::subscribe(IWakeupEventObserver *observer)
142 mObservers.push_back(observer);
145 void CWakeupManager::unsubscribe(IWakeupEventObserver *observer)
147 auto iter = find(mObservers.begin(), mObservers.end(), observer);
148 if (iter != mObservers.end()) {
149 mObservers.erase(iter);
153 bool CWakeupManager::activate(void)
157 if (WAKEUP_MANAGER_STATE_INACTIVE != mWakeupManagerState)
160 /* Activate assistants that supports current voice input language */
161 set_language(mWakeupSettings.get_current_language());
163 change_manager_state(WAKEUP_MANAGER_STATE_LISTENING);
164 if (mWakeupEngineManager.get_audio_data_required()) {
165 mAudioManager.start_recording();
172 bool CWakeupManager::deactivate(void)
176 if (WAKEUP_MANAGER_STATE_INACTIVE == mWakeupManagerState)
179 mAudioManager.stop_recording();
180 change_manager_state(WAKEUP_MANAGER_STATE_INACTIVE);
186 bool CWakeupManager::add_assistant_language(string appid, string language)
190 for (auto& info : mAssistantLanguageInfo) {
191 if(0 == info.appid.compare(appid)) {
192 info.languageList.push_back(language);
197 AssistantLanguageInfo info;
199 info.languageList.push_back(language);
200 mAssistantLanguageInfo.push_back(info);
206 bool CWakeupManager::add_assistant_wakeup_word(string appid, string wakeup_word, string language)
210 mWakeupEngineManager.engine_add_wakeup_word(appid, wakeup_word, language);
216 bool CWakeupManager::set_assistant_wakeup_engine(string appid, string engine)
220 mWakeupEngineManager.engine_add_target_assistant(engine, appid);
226 bool CWakeupManager::set_language(string language)
229 MWR_LOGD("[ENTER] : %s", language.c_str());
231 if (check_language_valid(language)) {
232 mCurrentLanguage = language;
235 for (auto& info : mAssistantLanguageInfo) {
237 for(auto it = info.languageList.begin(); it != info.languageList.end(); it++) {
238 if(language == *it) {
244 mAssistantActivated[info.appid] = false;
246 mAssistantActivated[info.appid] = true;
249 mWakeupEngineManager.set_assistant_activated(info.appid, found);
252 mWakeupEngineManager.set_language(language);
255 MWR_LOGE("[ERROR] Not supported language (%s)", language.c_str());
262 bool CWakeupManager::get_voice_key_pressed()
264 return mVoiceKeyPressed;
267 STREAMING_MODE CWakeupManager::get_streaming_mode()
269 return mStreamingMode;
272 bool CWakeupManager::set_streaming_mode(STREAMING_MODE mode)
274 mStreamingMode = mode;
278 bool CWakeupManager::change_manager_state(wakeup_manager_state_e state)
280 if (WAKEUP_MANAGER_STATE_UTTERANCE == mWakeupManagerState ||
281 WAKEUP_MANAGER_STATE_PROCESSING == mWakeupManagerState) {
282 if (WAKEUP_MANAGER_STATE_VOICE_FEEDBACK == state ||
283 WAKEUP_MANAGER_STATE_LISTENING == state) {
284 stop_streaming_utterance_data();
285 stop_streaming_previous_utterance_data();
286 stop_streaming_follow_up_data();
289 mWakeupManagerState = state;
290 mWakeupEngineManager.update_manager_state(state);
294 wakeup_manager_state_e CWakeupManager::get_manager_state()
296 return mWakeupManagerState;
299 bool CWakeupManager::update_voice_feedback_state(string appid, bool state)
304 if (WAKEUP_MANAGER_STATE_LISTENING == mWakeupManagerState ||
305 WAKEUP_MANAGER_STATE_PROCESSING == mWakeupManagerState) {
306 change_manager_state(WAKEUP_MANAGER_STATE_VOICE_FEEDBACK);
309 if (WAKEUP_MANAGER_STATE_VOICE_FEEDBACK == mWakeupManagerState) {
310 change_manager_state(WAKEUP_MANAGER_STATE_LISTENING);
318 bool CWakeupManager::send_assistant_specific_command(string appid, string command)
323 static const string voice_key_pressed{"voice_key_pressed"};
324 static const string voice_key_released{"voice_key_released"};
326 if (0 == command.compare(voice_key_pressed)) {
327 process_event(MA_PLUGIN_EVENT_VOICE_KEY_PRESSED, NULL, 0);
328 } else if (0 == command.compare(voice_key_released)) {
329 process_event(MA_PLUGIN_EVENT_VOICE_KEY_RELEASED, NULL, 0);
333 mWakeupEngineManager.engine_set_assistant_specific_command(appid, command);
339 bool CWakeupManager::change_system_volume(string appid, int event)
341 MWR_LOGD("[DEBUG] change system volume, system volume event(%d)", event);
344 if (MA_SYSTEM_VOLUME_EVENT_CHANGE == event) {
345 mAudioManager.change_system_volume();
346 } else if (MA_SYSTEM_VOLUME_EVENT_RECOVER == event) {
347 mAudioManager.recover_system_volume();
353 bool CWakeupManager::update_result_state(string appid, int state)
357 if (WAKEUP_MANAGER_STATE_PROCESSING == mWakeupManagerState ||
358 WAKEUP_MANAGER_STATE_UTTERANCE == mWakeupManagerState) {
359 change_manager_state(WAKEUP_MANAGER_STATE_LISTENING);
366 static long get_current_milliseconds_after_epoch()
368 auto now = chrono::system_clock::now();
369 auto now_ms = chrono::time_point_cast<chrono::milliseconds>(now);
370 /* number of milliseconds since the epoch of system_clock */
371 auto value = now_ms.time_since_epoch();
373 return value.count();
376 bool CWakeupManager::process_event(ma_plugin_event_e event, void* data, int len)
378 MWR_LOGD("[ENTER] : %d", event);
379 if (WAKEUP_MANAGER_STATE_INACTIVE == mWakeupManagerState)
383 if (MA_PLUGIN_EVENT_VOICE_KEY_PRESSED == event) {
384 if (mVoiceKeyPressed != true) {
385 stop_streaming_utterance_data();
386 stop_streaming_previous_utterance_data();
387 stop_streaming_follow_up_data();
389 mAudioManager.clear_audio_data();
390 change_manager_state(WAKEUP_MANAGER_STATE_UTTERANCE);
392 mVoiceKeyPressed = true;
394 /* (Re)Start recorder thread using appropriate recorder */
395 mAudioManager.start_recording();
397 /* Wakeup default assistant */
398 /* TODO: apply conversation timeout for selecting assistant here */
399 wakeup_event_info event_info;
400 initialize_wakeup_event_info(&event_info);
401 /* Make sure to use background data */
402 event_info.wakeup_time_valid = true;
403 event_info.wakeup_end_time = get_current_milliseconds_after_epoch();
404 event_info.wakeup_engine = WAKEUP_ENGINE_VOICE_KEY;
406 string appid = mWakeupSettings.get_default_assistant_appid();
407 event_info.wakeup_appid = appid.c_str();
408 MWR_LOGD("wakeup_appid : %s", event_info.wakeup_appid);
410 set_last_wakeup_event_info(event_info);
411 for (const auto& observer : mObservers) {
412 observer->on_wakeup(event_info);
415 } else if (MA_PLUGIN_EVENT_VOICE_KEY_RELEASED_AFTER_PUSH == event) {
416 if (mVoiceKeyPressed != false) {
417 mVoiceKeyPressed = false;
418 mAudioManager.finalize_audio_data();
420 if (mWakeupEngineManager.get_audio_data_required()) {
421 /* Restart recorder thread using standard mic */
422 mAudioManager.stop_recording();
423 mAudioManager.start_recording();
425 mAudioManager.stop_recording();
428 } else if (MA_PLUGIN_EVENT_VOICE_KEY_RELEASED_AFTER_TAP == event) {
429 if (mVoiceKeyPressed != false) {
430 mVoiceKeyPressed = false;
439 vector<IWakeupEventObserver*> CWakeupManager::get_observers()
444 void CWakeupManager::set_last_wakeup_event_info(wakeup_event_info info)
446 mLastWakeupEventInfo = info;
449 static Eina_Bool streaming_duration_expired(void *data)
452 CWakeupManager *wakeup_manager = static_cast<CWakeupManager*>(data);
453 if (nullptr == wakeup_manager) return ECORE_CALLBACK_CANCEL;
455 CAudioManager *audio_manager = wakeup_manager->get_audio_manager();
456 CWakeupEngineManager *engine_manager = wakeup_manager->get_engine_manager();
458 if (nullptr == audio_manager) return ECORE_CALLBACK_CANCEL;
459 if (nullptr == engine_manager) return ECORE_CALLBACK_CANCEL;
461 switch(wakeup_manager->get_streaming_mode()) {
462 case STREAMING_MODE::UTTERANCE:
463 audio_manager->stop_streaming_current_utterance_data();
464 engine_manager->stop_streaming_current_utterance_data();
466 case STREAMING_MODE::PREVIOUS_UTTERANCE:
467 audio_manager->stop_streaming_previous_utterance_data();
469 case STREAMING_MODE::FOLLOW_UP:
470 audio_manager->stop_streaming_follow_up_data();
474 unsigned char final_buffer[2] = {'\0', };
475 vector<IWakeupEventObserver*> observers = wakeup_manager->get_observers();
476 for (const auto& observer : observers) {
477 observer->on_streaming_audio_data(
478 WAKEUP_SPEECH_STREAMING_EVENT_FINISH, final_buffer, sizeof(final_buffer));
480 wakeup_manager->set_streaming_mode(STREAMING_MODE::NONE);
482 return ECORE_CALLBACK_CANCEL;
485 bool CWakeupManager::start_streaming_utterance_data()
489 mAudioManager.stop_streaming_current_utterance_data();
490 mWakeupEngineManager.stop_streaming_current_utterance_data();
492 mStreamingMode = STREAMING_MODE::UTTERANCE;
494 bool streaming_by_manager = true;
495 if (false == mLastWakeupEventInfo.wakeup_time_valid) {
496 mWakeupEngineManager.start_streaming_current_utterance_data();
497 streaming_by_manager = false;
499 mAudioManager.start_streaming_current_utterance_data(mLastWakeupEventInfo.wakeup_end_time);
502 ecore_thread_main_loop_begin();
503 if (mStreamingDurationTimer) {
504 ecore_timer_del(mStreamingDurationTimer);
505 mStreamingDurationTimer = nullptr;
507 if (streaming_by_manager) {
508 mStreamingDurationTimer = ecore_timer_add(
509 mWakeupSettings.get_streaming_duration_max(),
510 streaming_duration_expired, this);
512 ecore_thread_main_loop_end();
518 bool CWakeupManager::stop_streaming_utterance_data()
522 if (mStreamingDurationTimer) {
523 ecore_thread_main_loop_begin();
524 ecore_timer_del(mStreamingDurationTimer);
525 mStreamingDurationTimer = nullptr;
526 ecore_thread_main_loop_end();
528 if (WAKEUP_MANAGER_STATE_UTTERANCE == mWakeupManagerState) {
529 change_manager_state(WAKEUP_MANAGER_STATE_PROCESSING);
531 mAudioManager.stop_streaming_current_utterance_data();
532 mWakeupEngineManager.stop_streaming_current_utterance_data();
534 mStreamingMode = STREAMING_MODE::NONE;
540 bool CWakeupManager::start_streaming_follow_up_data()
544 mStreamingMode = STREAMING_MODE::FOLLOW_UP;
550 bool CWakeupManager::stop_streaming_follow_up_data()
554 mStreamingMode = STREAMING_MODE::NONE;
560 bool CWakeupManager::start_streaming_previous_utterance_data()
564 mStreamingMode = STREAMING_MODE::PREVIOUS_UTTERANCE;
570 bool CWakeupManager::stop_streaming_previous_utterance_data()
574 mStreamingMode = STREAMING_MODE::NONE;
580 bool CWakeupManager::get_audio_format(int* rate, int* channel, int* audio_type)
584 if (!audio_type || !rate || !channel) {
585 MWR_LOGE("[ERROR] Invalid parameter");
589 dependency_resolver_get_audio_format(rate, channel, audio_type);
591 MWR_LOGD("[END] rate(%d), channel(%d), audio_type(%d)", *rate, *channel, *audio_type);
595 bool CWakeupManager::get_audio_source_type(char** type)
600 MWR_LOGE("[ERROR] Invalid parameter");
604 dependency_resolver_get_audio_source_type(type);
606 MWR_LOGD("[END] type(%s)", *type);
610 CWakeupPolicy* CWakeupManager::get_wakeup_policy()
612 return mWakeupPolicy.get();
615 CWakeupEngineManager* CWakeupManager::get_engine_manager()
617 return &mWakeupEngineManager;
620 CAudioManager* CWakeupManager::get_audio_manager()
622 return &mAudioManager;
625 CWakeupSettings* CWakeupManager::get_wakeup_settings()
627 return &mWakeupSettings;
630 void CWakeupManager::feed_audio_data(wakeup_speech_streaming_event_e event, void* buffer, int len)
632 mAudioManager.feed_audio_data(event, buffer, len);
635 bool CWakeupManager::CEngineEventObserver::on_wakeup_event(string engine_name, wakeup_event_info info)
638 if (nullptr == mWakeupManager) return false;
640 CWakeupPolicy* policy = mWakeupManager->get_wakeup_policy();
642 policy->wakeup_candidate(info);
647 bool CWakeupManager::CEngineEventObserver::on_speech_status(string engine_name, wakeup_service_speech_status_e status)
650 if (nullptr == mWakeupManager) return false;
655 bool CWakeupManager::CEngineEventObserver::on_error(string engine_name, int error_code, string error_message)
658 if (nullptr == mWakeupManager) return false;
663 bool CWakeupManager::CEngineEventObserver::on_audio_data_require_status(string engine_name, bool require)
666 if (nullptr == mWakeupManager) return false;
667 if (WAKEUP_MANAGER_STATE_INACTIVE == mWakeupManager->get_manager_state()) return false;
669 CAudioManager *audio_manager = mWakeupManager->get_audio_manager();
670 CWakeupEngineManager *engine_manager = mWakeupManager->get_engine_manager();
672 if (audio_manager && engine_manager) {
673 if (engine_manager->get_audio_data_required()) {
674 if (mWakeupManager->get_voice_key_pressed() != true) {
675 audio_manager->start_recording();
678 if (mWakeupManager->get_voice_key_pressed() != true) {
679 audio_manager->stop_recording();
686 bool CWakeupManager::CEngineEventObserver::on_streaming_audio_data(
687 wakeup_speech_streaming_event_e event, void* buffer, unsigned int len)
689 if (nullptr == mWakeupManager) return false;
691 vector<IWakeupEventObserver*> observers = mWakeupManager->get_observers();
692 for (const auto& observer : observers) {
693 observer->on_streaming_audio_data(event, buffer, len);
695 if (WAKEUP_SPEECH_STREAMING_EVENT_FINISH == event) {
696 mWakeupManager->set_streaming_mode(STREAMING_MODE::NONE);
702 void CWakeupManager::CPolicyEventObserver::on_wakeup(wakeup_event_info info)
704 if (nullptr == mWakeupManager) return;
705 mWakeupManager->stop_streaming_utterance_data();
706 mWakeupManager->stop_streaming_previous_utterance_data();
707 mWakeupManager->stop_streaming_follow_up_data();
708 mWakeupManager->change_manager_state(WAKEUP_MANAGER_STATE_UTTERANCE);
710 CWakeupEngineManager *engine_manager = mWakeupManager->get_engine_manager();
711 if (nullptr == engine_manager) return;
713 mWakeupManager->set_last_wakeup_event_info(info);
714 engine_manager->set_selected_wakeup_info(info);
715 vector<IWakeupEventObserver*> observers = mWakeupManager->get_observers();
716 for (const auto& observer : observers) {
717 observer->on_wakeup(info);
721 bool CWakeupManager::CAudioEventObserver::on_recording_audio_data(long time, void* data, int len)
723 if (nullptr == mWakeupManager) return false;
725 CWakeupEngineManager *engine_manager = mWakeupManager->get_engine_manager();
726 if (nullptr == mEngineManager) return false;
728 if (false == engine_manager->get_audio_data_required()) return false;
730 if (mWakeupManager->get_voice_key_pressed() != true) {
731 engine_manager->engine_feed_audio_data(time, data, len);
737 bool CWakeupManager::CAudioEventObserver::on_streaming_audio_data(
738 wakeup_speech_streaming_event_e event, void* buffer, unsigned int len)
740 if (nullptr == mWakeupManager) return false;
742 vector<IWakeupEventObserver*> observers = mWakeupManager->get_observers();
743 for (const auto& observer : observers) {
744 observer->on_streaming_audio_data(event, buffer, len);
746 if (WAKEUP_SPEECH_STREAMING_EVENT_FINISH == event) {
747 mWakeupManager->set_streaming_mode(STREAMING_MODE::NONE);
753 bool CWakeupManager::CSettingsEventObserver::on_voice_input_language_changed(
754 const char* language)
756 if (nullptr == mWakeupManager || nullptr == language) return false;
757 mWakeupManager->set_language(std::string(language));