1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/event/multimodal/multimodal_scene.h"
17 
18 #include "base/log/dump_log.h"
19 
20 namespace OHOS::Ace {
21 
GetAvailableSubscriptId()22 std::string MultiModalScene::GetAvailableSubscriptId()
23 {
24     if (cachedIds_.empty()) {
25         auto newId = currentAvailableId_++;
26         return std::to_string(newId);
27     }
28     auto cachedId = *(cachedIds_.begin());
29     cachedIds_.erase(cachedIds_.begin());
30     return cachedId;
31 }
32 
RemoveSubscriptId(const std::string & subscriptId)33 void MultiModalScene::RemoveSubscriptId(const std::string& subscriptId)
34 {
35     cachedIds_.emplace(subscriptId);
36 }
37 
GetCurrentMaxSubscriptId()38 std::string MultiModalScene::GetCurrentMaxSubscriptId()
39 {
40     return std::to_string(currentAvailableId_ - 1);
41 }
42 
SubscribeVoiceEvent(const VoiceEvent & voiceEvent,const MultimodalEventCallback & callback)43 bool MultiModalScene::SubscribeVoiceEvent(const VoiceEvent& voiceEvent, const MultimodalEventCallback& callback)
44 {
45     if (!callback) {
46         LOGW("fail to subscribe voice event due to callback is null");
47         return false;
48     }
49     auto result = voiceEventCallbacks_.try_emplace(voiceEvent.GetVoiceContent(), callback);
50     if (!result.second) {
51         LOGW("subscribe duplicate voice event, voice label %{private}s", voiceEvent.GetVoiceContent().c_str());
52         return false;
53     }
54     voiceEvents_.emplace_back(voiceEvent);
55     if (!subscriber_) {
56         LOGE("fail to subscribe voice event due to subscriber is null");
57         return false;
58     }
59     if (!subscriber_->SubscribeVoiceEvents({ voiceEvent })) {
60         LOGE("fail to subscribe voice event due to subscribe fail");
61         return false;
62     }
63     return true;
64 }
65 
UnSubscribeVoiceEvent(const VoiceEvent & voiceEvent)66 void MultiModalScene::UnSubscribeVoiceEvent(const VoiceEvent& voiceEvent)
67 {
68     voiceEventCallbacks_.erase(voiceEvent.GetVoiceContent());
69     auto iter = std::remove(voiceEvents_.begin(), voiceEvents_.end(), voiceEvent);
70     if (iter != voiceEvents_.end()) {
71         voiceEvents_.erase(iter);
72         if (subscriber_) {
73             subscriber_->UnSubscribeVoiceEvents({ voiceEvent });
74         }
75     }
76 }
77 
SubscribeSubscriptSwitchEvent(const EventCallback<void (bool)> & callback)78 void MultiModalScene::SubscribeSubscriptSwitchEvent(const EventCallback<void(bool)>& callback)
79 {
80     subscriptSwitchListeners_.emplace_back(callback);
81 }
82 
UnSubscribeSubscriptSwitchEvent(const EventCallback<void (bool)> & callback)83 void MultiModalScene::UnSubscribeSubscriptSwitchEvent(const EventCallback<void(bool)>& callback)
84 {
85     auto iter = std::remove(subscriptSwitchListeners_.begin(), subscriptSwitchListeners_.end(), callback);
86     if (iter != subscriptSwitchListeners_.end()) {
87         subscriptSwitchListeners_.erase(iter);
88     }
89 }
90 
OnNotifyMultimodalEvent(const AceMultimodalEvent & event)91 void MultiModalScene::OnNotifyMultimodalEvent(const AceMultimodalEvent& event)
92 {
93     static const int32_t SHOW_BADGE = 6;
94     static const int32_t HIDE_BADGE = 7;
95     if (event.GetVoice().action == SHOW_BADGE || event.GetVoice().action == HIDE_BADGE) {
96         badgeFlag_ = event.GetVoice().action == SHOW_BADGE;
97         for (const auto& callback : subscriptSwitchListeners_) {
98             if (callback) {
99                 callback(event.GetVoice().action == SHOW_BADGE);
100             }
101         }
102     }
103     auto voiceIter = voiceEventCallbacks_.find(event.GetVoice().hotWord);
104     if (voiceIter != voiceEventCallbacks_.end()) {
105         (voiceIter->second)(event);
106         return;
107     }
108     auto badgeIter = voiceEventCallbacks_.find(event.GetVoice().badge);
109     if (badgeIter != voiceEventCallbacks_.end()) {
110         (badgeIter->second)(event);
111     }
112 }
113 
UnSubscribeAllEvents()114 void MultiModalScene::UnSubscribeAllEvents()
115 {
116     if (subscriber_ && !voiceEvents_.empty()) {
117         subscriber_->UnSubscribeVoiceEvents(voiceEvents_);
118     }
119     voiceEvents_.clear();
120     voiceEventCallbacks_.clear();
121     subscriptSwitchListeners_.clear();
122 }
123 
Hide()124 void MultiModalScene::Hide()
125 {
126     if (subscriber_ && !voiceEvents_.empty()) {
127         subscriber_->UnSubscribeVoiceEvents(voiceEvents_);
128     }
129 }
130 
Resume()131 void MultiModalScene::Resume()
132 {
133     if (subscriber_ && !voiceEvents_.empty()) {
134         subscriber_->SubscribeVoiceEvents(voiceEvents_);
135     }
136 }
137 
~MultiModalScene()138 MultiModalScene::~MultiModalScene()
139 {
140     UnSubscribeAllEvents();
141 }
142 
Dump() const143 void MultiModalScene::Dump() const
144 {
145     if (DumpLog::GetInstance().GetDumpFile()) {
146         for (const auto& event : voiceEvents_) {
147             DumpLog::GetInstance().AddDesc("voice event: ", event.GetVoiceContent());
148             DumpLog::GetInstance().AddDesc("badge event: ", event.IsBadge());
149         }
150         DumpLog::GetInstance().AddDesc("current badge id: ", currentAvailableId_);
151         DumpLog::GetInstance().AddDesc("badge flag: ", badgeFlag_);
152         DumpLog::GetInstance().Print(0, GetTypeName(), voiceEvents_.size());
153     }
154 }
155 
156 } // namespace OHOS::Ace