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 LOGW("Video parse args error");
209 return nullptr;
210 }
211
212 std::unique_ptr<JsonValue> Value = argsValue->GetArrayItem(0)->GetValue(key);
213 if (!Value) {
214 return nullptr;
215 }
216 return Value;
217 }
218
FireFullscreen(bool isFullScreen,const WeakPtr<Player> & player,const WeakPtr<Texture> & texture)219 RefPtr<Component> DOMVideo::FireFullscreen(
220 bool isFullScreen, const WeakPtr<Player>& player, const WeakPtr<Texture>& texture)
221 {
222 const auto& composed = GetRootComponent();
223 ACE_DCHECK(composed);
224 if (isFullScreen) {
225 if (isFullscreen_) {
226 return nullptr;
227 }
228 originComponent_ = composed->GetChild();
229 videoChild_->SetFullscreen(true);
230 videoChild_->SetPlayer(player);
231 videoChild_->SetTexture(texture);
232 composed->SetChild(GetEventComponents(videoChild_));
233 isFullscreen_ = true;
234 } else {
235 if (!isFullscreen_) {
236 return nullptr;
237 }
238 if (!originComponent_) {
239 return nullptr;
240 }
241 videoChild_->SetFullscreen(false);
242 videoChild_->SetPlayer(nullptr);
243 videoChild_->SetTexture(nullptr);
244 composed->SetChild(originComponent_);
245 isFullscreen_ = false;
246
247 auto controller = videoChild_->GetVideoController();
248 ACE_DCHECK(controller);
249 controller->ExitFullscreen(true);
250 return nullptr;
251 }
252
253 return GetRootComponent();
254 }
255
GetEventComponents(const RefPtr<Component> & videoChild)256 RefPtr<Component> DOMVideo::GetEventComponents(const RefPtr<Component>& videoChild)
257 {
258 std::vector<RefPtr<SoleChildComponent>> components;
259 RefPtr<FocusableComponent> focusableEventComponent = GetFocusableComponent();
260 if (focusableEventComponent) {
261 components.emplace_back(focusableEventComponent);
262 }
263 RefPtr<TouchListenerComponent> touchEventComponent = GetTouchListenerComponent();
264 if (touchEventComponent) {
265 components.emplace_back(touchEventComponent);
266 }
267 RefPtr<GestureListenerComponent> gestureEventComponent = GetGestureListenerComponent();
268 if (gestureEventComponent) {
269 components.emplace_back(gestureEventComponent);
270 }
271 RefPtr<MouseListenerComponent> mouseEventComponent = GetMouseListenerComponent();
272 if (mouseEventComponent) {
273 components.emplace_back(mouseEventComponent);
274 }
275 for (int32_t idx = static_cast<int32_t>(components.size()) - 1; idx >= 1; --idx) {
276 components[idx - 1]->SetChild(components[idx]);
277 }
278
279 auto box = AceType::MakeRefPtr<BoxComponent>();
280 Component::MergeRSNode(box);
281 RefPtr<BoxComponent> oldBox = GetBoxComponent();
282 if (oldBox) {
283 box->SetOnClick(oldBox->GetOnClick());
284 }
285 box->SetChild(videoChild);
286
287 if (!components.empty()) {
288 const auto& lastEventComponent = components.back();
289 if (lastEventComponent) {
290 lastEventComponent->SetChild(box);
291 return components.front();
292 }
293 }
294 return box;
295 }
296
ConvertStrToFit(const std::string & fit)297 ImageFit DOMVideo::ConvertStrToFit(const std::string& fit)
298 {
299 static const std::unordered_map<std::string, ImageFit> IMAGE_FIT_TABLE = {
300 { "fill", ImageFit::FILL },
301 { "contain", ImageFit::CONTAIN },
302 { "cover", ImageFit::COVER },
303 { "scaledown", ImageFit::SCALE_DOWN },
304 { "none", ImageFit::NONE },
305 };
306 auto imageFitIter = IMAGE_FIT_TABLE.find(fit);
307 return imageFitIter != IMAGE_FIT_TABLE.end() ? imageFitIter->second : ImageFit::CONTAIN;
308 }
309
ConvertStrToPosition(const std::string & position)310 ImageObjectPosition DOMVideo::ConvertStrToPosition(const std::string& position)
311 {
312 ImageObjectPosition objectPosition;
313 ParseBackgroundImagePosition(position, objectPosition);
314 return objectPosition;
315 }
316
317 } // namespace OHOS::Ace::Framework
318