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