/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "frameworks/bridge/declarative_frontend/jsview/js_video.h" #include "base/log/ace_scoring_log.h" #include "bridge/declarative_frontend/jsview/js_video_controller.h" #include "bridge/declarative_frontend/jsview/models/video_model_impl.h" #include "core/components_ng/pattern/video/video_model_ng.h" namespace OHOS::Ace { std::unique_ptr VideoModel::instance_ = nullptr; VideoModel* VideoModel::GetInstance() { if (!instance_) { #ifdef NG_BUILD instance_.reset(new NG::VideoModelNG()); #else if (Container::IsCurrentUseNewPipeline()) { instance_.reset(new NG::VideoModelNG()); } else { instance_.reset(new Framework::VideoModelImpl()); } #endif } return instance_.get(); } } // namespace OHOS::Ace namespace OHOS::Ace::Framework { void JSVideo::Create(const JSCallbackInfo& info) { if (info.Length() <= 0 || !info[0]->IsObject()) { LOGE("JSVideo: info is invalid."); return; } JSRef videoObj = JSRef::Cast(info[0]); JSRef srcValue = videoObj->GetProperty("src"); JSRef previewUriValue = videoObj->GetProperty("previewUri"); JSRef currentProgressRateValue = videoObj->GetProperty("currentProgressRate"); auto controllerObj = videoObj->GetProperty("controller"); RefPtr videoController = nullptr; if (controllerObj->IsObject()) { auto* jsVideoController = JSRef::Cast(controllerObj)->Unwrap(); if (jsVideoController) { videoController = jsVideoController->GetController(); } } VideoModel::GetInstance()->Create(videoController); // Parse the src, if it is invalid, use the empty string. std::string videoSrc; if (!ParseJsMedia(srcValue, videoSrc)) { LOGW("Video parse src failed."); } VideoModel::GetInstance()->SetSrc(videoSrc); // Parse the rate, if it is invalid, set it as 1.0. double currentProgressRate = 1.0; if (ParseJsDouble(currentProgressRateValue, currentProgressRate)) { LOGW("Video parse currentProgressRate failed."); } VideoModel::GetInstance()->SetProgressRate(currentProgressRate); std::string previewUri; if (previewUriValue->IsUndefined() || previewUriValue->IsNull()) { // When it is undefined, just set the empty image. LOGW("Video parse previewUri failed, it is null."); VideoModel::GetInstance()->SetPosterSourceInfo(previewUri); return; } auto noPixMap = ParseJsMedia(previewUriValue, previewUri); if (noPixMap) { // Src is a string or resource VideoModel::GetInstance()->SetPosterSourceInfo(previewUri); } else { // Src is a pixelmap. LOGE("can not support pixel map"); } } void JSVideo::JsMuted(const JSCallbackInfo& info) { bool muted = false; if (info[0]->IsBoolean()) { muted = info[0]->ToBoolean(); } VideoModel::GetInstance()->SetMuted(muted); } void JSVideo::JsAutoPlay(const JSCallbackInfo& info) { bool autoPlay = false; if (info[0]->IsBoolean()) { autoPlay = info[0]->ToBoolean(); } VideoModel::GetInstance()->SetAutoPlay(autoPlay); } void JSVideo::JsControls(const JSCallbackInfo& info) { bool controls = true; if (info[0]->IsBoolean()) { controls = info[0]->ToBoolean(); } VideoModel::GetInstance()->SetControls(controls); } void JSVideo::JsLoop(const JSCallbackInfo& info) { bool loop = false; if (info[0]->IsBoolean()) { loop = info[0]->ToBoolean(); } VideoModel::GetInstance()->SetLoop(loop); } void JSVideo::JsObjectFit(const JSCallbackInfo& info) { ImageFit imageFit = ImageFit::COVER; // The default value of Imagefit is FILL, but in the video the default value is COVER. // So the default value need to be converted. if (info[0]->IsUndefined()) { LOGW("JSVideo: objectfit is undefined."); VideoModel::GetInstance()->SetObjectFit(imageFit); return; } if (info[0]->IsNumber()) { imageFit = static_cast(info[0]->ToNumber()); } VideoModel::GetInstance()->SetObjectFit(imageFit); } void JSVideo::JsOnStart(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onStart = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onStart"); std::vector keys = { "start" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnStart(std::move(onStart)); } void JSVideo::JsOnPause(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onPause = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onPause"); std::vector keys = { "pause" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnPause(std::move(onPause)); } void JSVideo::JsOnFinish(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onFinish = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onFinish"); std::vector keys = { "finish" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnFinish(std::move(onFinish)); } void JSVideo::JsOnFullscreenChange(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto OnFullScreenChange = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)]( const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.OnFullScreenChange"); std::vector keys = { "fullscreen" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnFullScreenChange(std::move(OnFullScreenChange)); } void JSVideo::JsOnPrepared(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onPrepared = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onPrepared"); std::vector keys = { "duration" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnPrepared(std::move(onPrepared)); } void JSVideo::JsOnSeeking(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onSeeking = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onSeeking"); std::vector keys = { "time" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnSeeking(std::move(onSeeking)); } void JSVideo::JsOnSeeked(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onSeeked = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onSeeked"); std::vector keys = { "time" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnSeeked(std::move(onSeeked)); } void JSVideo::JsOnUpdate(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onUpdate = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onUpdate"); std::vector keys = { "time" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnUpdate(std::move(onUpdate)); } void JSVideo::JsOnError(const JSCallbackInfo& args) { auto jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(args[0])); auto onError = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); ACE_SCORING_EVENT("Video.onError"); std::vector keys = { "error" }; func->Execute(keys, param); }; VideoModel::GetInstance()->SetOnError(std::move(onError)); } EventMarker JSVideo::GetEventMarker(const JSCallbackInfo& info, const std::vector& keys) { if (!info[0]->IsFunction()) { LOGE("info[0] is not a function."); return EventMarker(); } RefPtr jsFunc = AceType::MakeRefPtr(JSRef(), JSRef::Cast(info[0])); auto eventMarker = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys](const std::string& param) { JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx); func->Execute(keys, param); }); return eventMarker; } void JSVideo::JSBind(BindingTarget globalObj) { JSClass::Declare("Video"); MethodOptions opt = MethodOptions::NONE; JSClass::StaticMethod("create", &JSVideo::Create, opt); JSClass::StaticMethod("muted", &JSVideo::JsMuted, opt); JSClass::StaticMethod("autoPlay", &JSVideo::JsAutoPlay, opt); JSClass::StaticMethod("controls", &JSVideo::JsControls, opt); JSClass::StaticMethod("loop", &JSVideo::JsLoop, opt); JSClass::StaticMethod("objectFit", &JSVideo::JsObjectFit, opt); JSClass::StaticMethod("onStart", &JSVideo::JsOnStart); JSClass::StaticMethod("onPause", &JSVideo::JsOnPause); JSClass::StaticMethod("onFinish", &JSVideo::JsOnFinish); JSClass::StaticMethod("onFullscreenChange", &JSVideo::JsOnFullscreenChange); JSClass::StaticMethod("onPrepared", &JSVideo::JsOnPrepared); JSClass::StaticMethod("onSeeking", &JSVideo::JsOnSeeking); JSClass::StaticMethod("onSeeked", &JSVideo::JsOnSeeked); JSClass::StaticMethod("onUpdate", &JSVideo::JsOnUpdate); JSClass::StaticMethod("onError", &JSVideo::JsOnError); JSClass::StaticMethod("onTouch", &JSInteractableView::JsOnTouch); JSClass::StaticMethod("onHover", &JSInteractableView::JsOnHover); JSClass::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey); JSClass::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete); JSClass::StaticMethod("onClick", &JSInteractableView::JsOnClick); JSClass::StaticMethod("onAppear", &JSInteractableView::JsOnAppear); JSClass::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear); JSClass::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage); JSClass::Inherit(); // override method JSClass::StaticMethod("opacity", &JSViewAbstract::JsOpacityPassThrough); JSClass::StaticMethod("transition", &JSViewAbstract::JsTransitionPassThrough); JSClass::Bind<>(globalObj); } } // namespace OHOS::Ace::Framework