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 "frameworks/bridge/declarative_frontend/jsview/js_video.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "bridge/declarative_frontend/jsview/js_video_controller.h"
20 #include "bridge/declarative_frontend/jsview/models/video_model_impl.h"
21 #include "core/components_ng/pattern/video/video_model_ng.h"
22
23 namespace OHOS::Ace {
24
25 std::unique_ptr<VideoModel> VideoModel::instance_ = nullptr;
26
GetInstance()27 VideoModel* VideoModel::GetInstance()
28 {
29 if (!instance_) {
30 #ifdef NG_BUILD
31 instance_.reset(new NG::VideoModelNG());
32 #else
33 if (Container::IsCurrentUseNewPipeline()) {
34 instance_.reset(new NG::VideoModelNG());
35 } else {
36 instance_.reset(new Framework::VideoModelImpl());
37 }
38 #endif
39 }
40 return instance_.get();
41 }
42
43 } // namespace OHOS::Ace
44
45 namespace OHOS::Ace::Framework {
46
Create(const JSCallbackInfo & info)47 void JSVideo::Create(const JSCallbackInfo& info)
48 {
49 if (info.Length() <= 0 || !info[0]->IsObject()) {
50 LOGE("JSVideo: info is invalid.");
51 return;
52 }
53 JSRef<JSObject> videoObj = JSRef<JSObject>::Cast(info[0]);
54 JSRef<JSVal> srcValue = videoObj->GetProperty("src");
55 JSRef<JSVal> previewUriValue = videoObj->GetProperty("previewUri");
56 JSRef<JSVal> currentProgressRateValue = videoObj->GetProperty("currentProgressRate");
57
58 auto controllerObj = videoObj->GetProperty("controller");
59 RefPtr<VideoControllerV2> videoController = nullptr;
60 if (controllerObj->IsObject()) {
61 auto* jsVideoController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSVideoController>();
62 if (jsVideoController) {
63 videoController = jsVideoController->GetController();
64 }
65 }
66 VideoModel::GetInstance()->Create(videoController);
67
68 // Parse the src, if it is invalid, use the empty string.
69 std::string videoSrc;
70 if (!ParseJsMedia(srcValue, videoSrc)) {
71 LOGW("Video parse src failed.");
72 }
73 VideoModel::GetInstance()->SetSrc(videoSrc);
74
75 // Parse the rate, if it is invalid, set it as 1.0.
76 double currentProgressRate = 1.0;
77 if (ParseJsDouble(currentProgressRateValue, currentProgressRate)) {
78 LOGW("Video parse currentProgressRate failed.");
79 }
80 VideoModel::GetInstance()->SetProgressRate(currentProgressRate);
81
82 std::string previewUri;
83 if (previewUriValue->IsUndefined() || previewUriValue->IsNull()) {
84 // When it is undefined, just set the empty image.
85 LOGW("Video parse previewUri failed, it is null.");
86 VideoModel::GetInstance()->SetPosterSourceInfo(previewUri);
87 return;
88 }
89 auto noPixMap = ParseJsMedia(previewUriValue, previewUri);
90 if (noPixMap) {
91 // Src is a string or resource
92 VideoModel::GetInstance()->SetPosterSourceInfo(previewUri);
93 } else {
94 // Src is a pixelmap.
95 LOGE("can not support pixel map");
96 }
97 }
98
JsMuted(const JSCallbackInfo & info)99 void JSVideo::JsMuted(const JSCallbackInfo& info)
100 {
101 bool muted = false;
102 if (info[0]->IsBoolean()) {
103 muted = info[0]->ToBoolean();
104 }
105 VideoModel::GetInstance()->SetMuted(muted);
106 }
107
JsAutoPlay(const JSCallbackInfo & info)108 void JSVideo::JsAutoPlay(const JSCallbackInfo& info)
109 {
110 bool autoPlay = false;
111 if (info[0]->IsBoolean()) {
112 autoPlay = info[0]->ToBoolean();
113 }
114 VideoModel::GetInstance()->SetAutoPlay(autoPlay);
115 }
116
JsControls(const JSCallbackInfo & info)117 void JSVideo::JsControls(const JSCallbackInfo& info)
118 {
119 bool controls = true;
120 if (info[0]->IsBoolean()) {
121 controls = info[0]->ToBoolean();
122 }
123 VideoModel::GetInstance()->SetControls(controls);
124 }
125
JsLoop(const JSCallbackInfo & info)126 void JSVideo::JsLoop(const JSCallbackInfo& info)
127 {
128 bool loop = false;
129 if (info[0]->IsBoolean()) {
130 loop = info[0]->ToBoolean();
131 }
132 VideoModel::GetInstance()->SetLoop(loop);
133 }
134
JsObjectFit(const JSCallbackInfo & info)135 void JSVideo::JsObjectFit(const JSCallbackInfo& info)
136 {
137 ImageFit imageFit = ImageFit::COVER;
138 // The default value of Imagefit is FILL, but in the video the default value is COVER.
139 // So the default value need to be converted.
140 if (info[0]->IsUndefined()) {
141 LOGW("JSVideo: objectfit is undefined.");
142 VideoModel::GetInstance()->SetObjectFit(imageFit);
143 return;
144 }
145 if (info[0]->IsNumber()) {
146 imageFit = static_cast<ImageFit>(info[0]->ToNumber<int>());
147 }
148 VideoModel::GetInstance()->SetObjectFit(imageFit);
149 }
150
JsOnStart(const JSCallbackInfo & args)151 void JSVideo::JsOnStart(const JSCallbackInfo& args)
152 {
153 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
154 auto onStart = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
155 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
156 ACE_SCORING_EVENT("Video.onStart");
157 std::vector<std::string> keys = { "start" };
158 func->Execute(keys, param);
159 };
160 VideoModel::GetInstance()->SetOnStart(std::move(onStart));
161 }
162
JsOnPause(const JSCallbackInfo & args)163 void JSVideo::JsOnPause(const JSCallbackInfo& args)
164 {
165 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
166 auto onPause = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
167 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
168 ACE_SCORING_EVENT("Video.onPause");
169 std::vector<std::string> keys = { "pause" };
170 func->Execute(keys, param);
171 };
172 VideoModel::GetInstance()->SetOnPause(std::move(onPause));
173 }
174
JsOnFinish(const JSCallbackInfo & args)175 void JSVideo::JsOnFinish(const JSCallbackInfo& args)
176 {
177 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
178 auto onFinish = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
179 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
180 ACE_SCORING_EVENT("Video.onFinish");
181 std::vector<std::string> keys = { "finish" };
182 func->Execute(keys, param);
183 };
184 VideoModel::GetInstance()->SetOnFinish(std::move(onFinish));
185 }
186
JsOnFullscreenChange(const JSCallbackInfo & args)187 void JSVideo::JsOnFullscreenChange(const JSCallbackInfo& args)
188 {
189 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
190 auto OnFullScreenChange = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](
191 const std::string& param) {
192 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
193 ACE_SCORING_EVENT("Video.OnFullScreenChange");
194 std::vector<std::string> keys = { "fullscreen" };
195 func->Execute(keys, param);
196 };
197 VideoModel::GetInstance()->SetOnFullScreenChange(std::move(OnFullScreenChange));
198 }
199
JsOnPrepared(const JSCallbackInfo & args)200 void JSVideo::JsOnPrepared(const JSCallbackInfo& args)
201 {
202 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
203 auto onPrepared = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
204 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
205 ACE_SCORING_EVENT("Video.onPrepared");
206 std::vector<std::string> keys = { "duration" };
207 func->Execute(keys, param);
208 };
209 VideoModel::GetInstance()->SetOnPrepared(std::move(onPrepared));
210 }
211
JsOnSeeking(const JSCallbackInfo & args)212 void JSVideo::JsOnSeeking(const JSCallbackInfo& args)
213 {
214 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
215 auto onSeeking = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
216 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
217 ACE_SCORING_EVENT("Video.onSeeking");
218 std::vector<std::string> keys = { "time" };
219 func->Execute(keys, param);
220 };
221 VideoModel::GetInstance()->SetOnSeeking(std::move(onSeeking));
222 }
223
JsOnSeeked(const JSCallbackInfo & args)224 void JSVideo::JsOnSeeked(const JSCallbackInfo& args)
225 {
226 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
227 auto onSeeked = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
228 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
229 ACE_SCORING_EVENT("Video.onSeeked");
230 std::vector<std::string> keys = { "time" };
231 func->Execute(keys, param);
232 };
233 VideoModel::GetInstance()->SetOnSeeked(std::move(onSeeked));
234 }
235
JsOnUpdate(const JSCallbackInfo & args)236 void JSVideo::JsOnUpdate(const JSCallbackInfo& args)
237 {
238 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
239 auto onUpdate = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
240 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
241 ACE_SCORING_EVENT("Video.onUpdate");
242 std::vector<std::string> keys = { "time" };
243 func->Execute(keys, param);
244 };
245 VideoModel::GetInstance()->SetOnUpdate(std::move(onUpdate));
246 }
247
JsOnError(const JSCallbackInfo & args)248 void JSVideo::JsOnError(const JSCallbackInfo& args)
249 {
250 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
251 auto onError = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
252 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
253 ACE_SCORING_EVENT("Video.onError");
254 std::vector<std::string> keys = { "error" };
255 func->Execute(keys, param);
256 };
257 VideoModel::GetInstance()->SetOnError(std::move(onError));
258 }
259
GetEventMarker(const JSCallbackInfo & info,const std::vector<std::string> & keys)260 EventMarker JSVideo::GetEventMarker(const JSCallbackInfo& info, const std::vector<std::string>& keys)
261 {
262 if (!info[0]->IsFunction()) {
263 LOGE("info[0] is not a function.");
264 return EventMarker();
265 }
266
267 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
268 auto eventMarker =
269 EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys](const std::string& param) {
270 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
271 func->Execute(keys, param);
272 });
273 return eventMarker;
274 }
275
JSBind(BindingTarget globalObj)276 void JSVideo::JSBind(BindingTarget globalObj)
277 {
278 JSClass<JSVideo>::Declare("Video");
279 MethodOptions opt = MethodOptions::NONE;
280 JSClass<JSVideo>::StaticMethod("create", &JSVideo::Create, opt);
281 JSClass<JSVideo>::StaticMethod("muted", &JSVideo::JsMuted, opt);
282 JSClass<JSVideo>::StaticMethod("autoPlay", &JSVideo::JsAutoPlay, opt);
283 JSClass<JSVideo>::StaticMethod("controls", &JSVideo::JsControls, opt);
284 JSClass<JSVideo>::StaticMethod("loop", &JSVideo::JsLoop, opt);
285 JSClass<JSVideo>::StaticMethod("objectFit", &JSVideo::JsObjectFit, opt);
286
287 JSClass<JSVideo>::StaticMethod("onStart", &JSVideo::JsOnStart);
288 JSClass<JSVideo>::StaticMethod("onPause", &JSVideo::JsOnPause);
289 JSClass<JSVideo>::StaticMethod("onFinish", &JSVideo::JsOnFinish);
290 JSClass<JSVideo>::StaticMethod("onFullscreenChange", &JSVideo::JsOnFullscreenChange);
291 JSClass<JSVideo>::StaticMethod("onPrepared", &JSVideo::JsOnPrepared);
292 JSClass<JSVideo>::StaticMethod("onSeeking", &JSVideo::JsOnSeeking);
293 JSClass<JSVideo>::StaticMethod("onSeeked", &JSVideo::JsOnSeeked);
294 JSClass<JSVideo>::StaticMethod("onUpdate", &JSVideo::JsOnUpdate);
295 JSClass<JSVideo>::StaticMethod("onError", &JSVideo::JsOnError);
296
297 JSClass<JSVideo>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
298 JSClass<JSVideo>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
299 JSClass<JSVideo>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
300 JSClass<JSVideo>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
301 JSClass<JSVideo>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
302 JSClass<JSVideo>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
303 JSClass<JSVideo>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
304 JSClass<JSVideo>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
305
306 JSClass<JSVideo>::Inherit<JSViewAbstract>();
307 // override method
308 JSClass<JSVideo>::StaticMethod("opacity", &JSViewAbstract::JsOpacityPassThrough);
309 JSClass<JSVideo>::StaticMethod("transition", &JSViewAbstract::JsTransitionPassThrough);
310 JSClass<JSVideo>::Bind<>(globalObj);
311 }
312
313 } // namespace OHOS::Ace::Framework
314