1 /*
2 * Copyright (c) 2021-2022 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 "frameworks/bridge/common/dom/dom_video.h"
17
18 #include "frameworks/bridge/common/dom/dom_type.h"
19 #include "frameworks/bridge/common/utils/utils.h"
20
21 namespace OHOS::Ace::Framework {
22 namespace {
23
24 constexpr uint32_t METHOD_VIDEO_TO_ARGS_SIZE = 1;
25
26 }
27
DOMVideo(NodeId nodeId,const std::string & nodeName)28 DOMVideo::DOMVideo(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
29 {
30 videoChild_ = AceType::MakeRefPtr<VideoComponent>();
31 videoChild_->SetFullscreenEvent([weak = AceType::WeakClaim(this)](bool fullscreen, const WeakPtr<Player>& player,
32 const WeakPtr<Texture>& texture) {
33 auto client = weak.Upgrade();
34 RefPtr<OHOS::Ace::Component> result;
35 if (client) {
36 result = client->FireFullscreen(fullscreen, player, texture);
37 }
38 return result;
39 });
40 if (IsRightToLeft()) {
41 videoChild_->SetTextDirection(TextDirection::RTL);
42 }
43 }
44
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)45 bool DOMVideo::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
46 {
47 // Operator map for attr
48 static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const std::string&)>
49 attrOperators = {
50 { DOM_VIDEO_MUTED,
51 [](const RefPtr<VideoComponent>& video, const std::string& val) {
52 video->SetMute(StringToBool(val));
53 } },
54 { DOM_VIDEO_SRC,
55 [](const RefPtr<VideoComponent>& video, const std::string& val) {
56 video->SetSrc(val);
57 } },
58 { DOM_VIDEO_AUTOPLAY,
59 [](const RefPtr<VideoComponent>& video, const std::string& val) {
60 video->SetAutoPlay(StringToBool(val));
61 } },
62 { DOM_VIDEO_POSTER,
63 [](const RefPtr<VideoComponent>& video, const std::string& val) {
64 video->SetPoster(val);
65 } },
66 { DOM_VIDEO_CONTROLS,
67 [](const RefPtr<VideoComponent>& video, const std::string& val) {
68 video->SetNeedControls(StringToBool(val));
69 } },
70 { DOM_VIDEO_LOOP,
71 [](const RefPtr<VideoComponent>& video, const std::string& val) {
72 video->SetLoop(StringToBool(val));
73 } },
74 { DOM_VIDEO_START_TIME,
75 [](const RefPtr<VideoComponent>& video, const std::string& val) {
76 video->SetStartTime(StringToInt(val));
77 } },
78 { DOM_VIDEO_SPEED, [](const RefPtr<VideoComponent>& video, const std::string& val) {
79 video->SetSpeed(StringUtils::StringToDouble(val));
80 } },
81 { DOM_VIDEO_DIRECTION, [](const RefPtr<VideoComponent>& video, const std::string& val) {
82 video->SetDirection(val);
83 } },
84 };
85 auto operatorIter = attrOperators.find(attr.first);
86 if (operatorIter != attrOperators.end()) {
87 operatorIter->second(videoChild_, attr.second);
88 return true;
89 }
90 return false;
91 }
92
SetSpecializedStyle(const std::pair<std::string,std::string> & style)93 bool DOMVideo::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
94 {
95 // Operator map for styles
96 static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const std::string&)>
97 styleOperators = {
98 // Set video-fit
99 { DOM_VIDEO_FIT, [](const RefPtr<VideoComponent>& video,
100 const std::string& val) { video->SetFit(ConvertStrToFit(val)); } },
101 // Set video-position
102 { DOM_VIDEO_POSITION, [](const RefPtr<VideoComponent>& video,
103 const std::string& val) { video->SetImagePosition(ConvertStrToPosition(val)); } },
104 };
105 auto operatorIter = styleOperators.find(style.first);
106 if (operatorIter != styleOperators.end()) {
107 operatorIter->second(videoChild_, style.second);
108 return true;
109 }
110 return false;
111 }
112
AddSpecializedEvent(int32_t pageId,const std::string & event)113 bool DOMVideo::AddSpecializedEvent(int32_t pageId, const std::string& event)
114 {
115 // Operator map for event
116 static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const EventMarker&)>
117 eventOperators = {
118 { DOM_VIDEO_EVENT_PREPARED, [](const RefPtr<VideoComponent>& video,
119 const EventMarker& event) { video->SetPreparedEventId(event); } },
120 { DOM_VIDEO_EVENT_START,
121 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetStartEventId(event); } },
122 { DOM_VIDEO_EVENT_PAUSE,
123 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetPauseEventId(event); } },
124 { DOM_VIDEO_EVENT_STOP,
125 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetStopEventId(event); } },
126 { DOM_VIDEO_EVENT_FINISH,
127 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetFinishEventId(event); } },
128 { DOM_VIDEO_EVENT_ERROR,
129 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetErrorEventId(event); } },
130 { DOM_VIDEO_EVENT_SEEKING, [](const RefPtr<VideoComponent>& video,
131 const EventMarker& event) { video->SetSeekingEventId(event); } },
132 { DOM_VIDEO_EVENT_SEEKED,
133 [](const RefPtr<VideoComponent>& video, const EventMarker& event) { video->SetSeekedEventId(event); } },
134 { DOM_VIDEO_EVENT_TIMEUPDATE, [](const RefPtr<VideoComponent>& video,
135 const EventMarker& event) { video->SetTimeUpdateEventId(event); } },
136 { DOM_VIDEO_EVENT_FULLSCREENCHANGE,
137 [](const RefPtr<VideoComponent>& video, const EventMarker& event) {
138 video->SetFullscreenChangeEventId(event);
139 } },
140 };
141 auto operatorIter = eventOperators.find(event);
142 if (operatorIter != eventOperators.end()) {
143 operatorIter->second(videoChild_, EventMarker(GetNodeIdForEvent(), event, pageId));
144 return true;
145 }
146 return false;
147 }
148
CallSpecializedMethod(const std::string & method,const std::string & args)149 void DOMVideo::CallSpecializedMethod(const std::string& method, const std::string& args)
150 {
151 // Operator map for method
152 static const std::unordered_map<std::string, void (*)(const RefPtr<VideoComponent>&, const std::string&)>
153 methedOperators = {
154 { DOM_VIDEO_METHOD_START,
155 [](const RefPtr<VideoComponent>& video, const std::string& args) {
156 auto controller = video->GetVideoController();
157 ACE_DCHECK(controller);
158 controller->Start();
159 } },
160 { DOM_VIDEO_METHOD_PAUSE,
161 [](const RefPtr<VideoComponent>& video, const std::string& args) {
162 auto controller = video->GetVideoController();
163 ACE_DCHECK(controller);
164 controller->Pause();
165 } },
166 { DOM_VIDEO_METHOD_STOP,
167 [](const RefPtr<VideoComponent>& video, const std::string& args) {
168 auto controller = video->GetVideoController();
169 ACE_DCHECK(controller);
170 controller->Stop();
171 } },
172 { DOM_VIDEO_METHOD_SEEK_TO,
173 [](const RefPtr<VideoComponent>& video, const std::string& args) {
174 auto controller = video->GetVideoController();
175 ACE_DCHECK(controller);
176 auto value = GetParamFromJson(args, "currenttime");
177 if (value) {
178 int32_t pos = value->GetInt();
179 controller->SeekTo(pos);
180 }
181 } },
182 { DOM_VIDEO_METHOD_REQUEST_FULLSCREEN,
183 [](const RefPtr<VideoComponent>& video, const std::string& args) {
184 auto controller = video->GetVideoController();
185 ACE_DCHECK(controller);
186 auto value = GetParamFromJson(args, "screenOrientation ");
187 if (value) {
188 controller->RequestFullscreen(!(value->GetString() == "landscape"));
189 }
190 } },
191 { DOM_VIDEO_METHOD_EXIT_FULLSCREEN,
192 [](const RefPtr<VideoComponent>& video, const std::string& args) {
193 auto controller = video->GetVideoController();
194 ACE_DCHECK(controller);
195 controller->ExitFullscreen(false);
196 } },
197 };
198 auto operatorIter = methedOperators.find(method);
199 if (operatorIter != methedOperators.end()) {
200 operatorIter->second(videoChild_, args);
201 }
202 }
203
GetParamFromJson(const std::string & json,const std::string & key)204 std::unique_ptr<JsonValue> DOMVideo::GetParamFromJson(const std::string& json, const std::string& key)
205 {
206 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(json);
207 if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != METHOD_VIDEO_TO_ARGS_SIZE) {
208 LOGE("parse args error");
209 return nullptr;
210 }
211
212 std::unique_ptr<JsonValue> Value = argsValue->GetArrayItem(0)->GetValue(key);
213 if (!Value) {
214 LOGE("get index failed");
215 return nullptr;
216 }
217 return Value;
218 }
219
FireFullscreen(bool isFullScreen,const WeakPtr<Player> & player,const WeakPtr<Texture> & texture)220 RefPtr<Component> DOMVideo::FireFullscreen(
221 bool isFullScreen, const WeakPtr<Player>& player, const WeakPtr<Texture>& texture)
222 {
223 const auto& composed = GetRootComponent();
224 ACE_DCHECK(composed);
225 if (isFullScreen) {
226 if (isFullscreen_) {
227 return nullptr;
228 }
229 originComponent_ = composed->GetChild();
230 videoChild_->SetFullscreen(true);
231 videoChild_->SetPlayer(player);
232 videoChild_->SetTexture(texture);
233 composed->SetChild(GetEventComponents(videoChild_));
234 isFullscreen_ = true;
235 } else {
236 if (!isFullscreen_) {
237 return nullptr;
238 }
239 if (!originComponent_) {
240 LOGE("the origin component is null");
241 return nullptr;
242 }
243 videoChild_->SetFullscreen(false);
244 videoChild_->SetPlayer(nullptr);
245 videoChild_->SetTexture(nullptr);
246 composed->SetChild(originComponent_);
247 isFullscreen_ = false;
248
249 auto controller = videoChild_->GetVideoController();
250 ACE_DCHECK(controller);
251 controller->ExitFullscreen(true);
252 return nullptr;
253 }
254
255 return GetRootComponent();
256 }
257
GetEventComponents(const RefPtr<Component> & videoChild)258 RefPtr<Component> DOMVideo::GetEventComponents(const RefPtr<Component>& videoChild)
259 {
260 std::vector<RefPtr<SoleChildComponent>> components;
261 RefPtr<FocusableComponent> focusableEventComponent = GetFocusableComponent();
262 if (focusableEventComponent) {
263 components.emplace_back(focusableEventComponent);
264 }
265 RefPtr<TouchListenerComponent> touchEventComponent = GetTouchListenerComponent();
266 if (touchEventComponent) {
267 components.emplace_back(touchEventComponent);
268 }
269 RefPtr<GestureListenerComponent> gestureEventComponent = GetGestureListenerComponent();
270 if (gestureEventComponent) {
271 components.emplace_back(gestureEventComponent);
272 }
273 RefPtr<MouseListenerComponent> mouseEventComponent = GetMouseListenerComponent();
274 if (mouseEventComponent) {
275 components.emplace_back(mouseEventComponent);
276 }
277 for (int32_t idx = static_cast<int32_t>(components.size()) - 1; idx >= 1; --idx) {
278 components[idx - 1]->SetChild(components[idx]);
279 }
280
281 auto box = AceType::MakeRefPtr<BoxComponent>();
282 Component::MergeRSNode(box);
283 RefPtr<BoxComponent> oldBox = GetBoxComponent();
284 if (oldBox) {
285 box->SetOnClick(oldBox->GetOnClick());
286 }
287 box->SetChild(videoChild);
288
289 if (!components.empty()) {
290 const auto& lastEventComponent = components.back();
291 if (lastEventComponent) {
292 lastEventComponent->SetChild(box);
293 return components.front();
294 }
295 }
296 return box;
297 }
298
ConvertStrToFit(const std::string & fit)299 ImageFit DOMVideo::ConvertStrToFit(const std::string& fit)
300 {
301 static const std::unordered_map<std::string, ImageFit> IMAGE_FIT_TABLE = {
302 { "fill", ImageFit::FILL },
303 { "contain", ImageFit::CONTAIN },
304 { "cover", ImageFit::COVER },
305 { "scaledown", ImageFit::SCALE_DOWN },
306 { "none", ImageFit::NONE },
307 };
308 auto imageFitIter = IMAGE_FIT_TABLE.find(fit);
309 return imageFitIter != IMAGE_FIT_TABLE.end() ? imageFitIter->second : ImageFit::CONTAIN;
310 }
311
ConvertStrToPosition(const std::string & position)312 ImageObjectPosition DOMVideo::ConvertStrToPosition(const std::string& position)
313 {
314 ImageObjectPosition objectPosition;
315 if (!ParseBackgroundImagePosition(position, objectPosition)) {
316 LOGE("ConvertStrToPosition failed");
317 }
318 return objectPosition;
319 }
320
321 } // namespace OHOS::Ace::Framework
322