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