/* * Copyright (c) 2021-2022 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/common/dom/dom_video.h" #include "frameworks/bridge/common/utils/utils.h" namespace OHOS::Ace::Framework { namespace { constexpr uint32_t METHOD_VIDEO_TO_ARGS_SIZE = 1; } DOMVideo::DOMVideo(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName) { videoChild_ = AceType::MakeRefPtr(); videoChild_->SetFullscreenEvent([weak = AceType::WeakClaim(this)](bool fullscreen, const WeakPtr& player, const WeakPtr& texture) { auto client = weak.Upgrade(); RefPtr result; if (client) { result = client->FireFullscreen(fullscreen, player, texture); } return result; }); if (IsRightToLeft()) { videoChild_->SetTextDirection(TextDirection::RTL); } } bool DOMVideo::SetSpecializedAttr(const std::pair& attr) { // Operator map for attr static const std::unordered_map&, const std::string&)> attrOperators = { { DOM_VIDEO_MUTED, [](const RefPtr& video, const std::string& val) { video->SetMute(StringToBool(val)); } }, { DOM_VIDEO_SRC, [](const RefPtr& video, const std::string& val) { video->SetSrc(val); } }, { DOM_VIDEO_AUTOPLAY, [](const RefPtr& video, const std::string& val) { video->SetAutoPlay(StringToBool(val)); } }, { DOM_VIDEO_POSTER, [](const RefPtr& video, const std::string& val) { video->SetPoster(val); } }, { DOM_VIDEO_CONTROLS, [](const RefPtr& video, const std::string& val) { video->SetNeedControls(StringToBool(val)); } }, { DOM_VIDEO_LOOP, [](const RefPtr& video, const std::string& val) { video->SetLoop(StringToBool(val)); } }, { DOM_VIDEO_START_TIME, [](const RefPtr& video, const std::string& val) { video->SetStartTime(StringToInt(val)); } }, { DOM_VIDEO_SPEED, [](const RefPtr& video, const std::string& val) { video->SetSpeed(StringUtils::StringToDouble(val)); } }, { DOM_VIDEO_DIRECTION, [](const RefPtr& video, const std::string& val) { video->SetDirection(val); } }, }; auto operatorIter = attrOperators.find(attr.first); if (operatorIter != attrOperators.end()) { operatorIter->second(videoChild_, attr.second); return true; } return false; } bool DOMVideo::SetSpecializedStyle(const std::pair& style) { // Operator map for styles static const std::unordered_map&, const std::string&)> styleOperators = { // Set video-fit { DOM_VIDEO_FIT, [](const RefPtr& video, const std::string& val) { video->SetFit(ConvertStrToFit(val)); } }, // Set video-position { DOM_VIDEO_POSITION, [](const RefPtr& video, const std::string& val) { video->SetImagePosition(ConvertStrToPosition(val)); } }, }; auto operatorIter = styleOperators.find(style.first); if (operatorIter != styleOperators.end()) { operatorIter->second(videoChild_, style.second); return true; } return false; } bool DOMVideo::AddSpecializedEvent(int32_t pageId, const std::string& event) { // Operator map for event static const std::unordered_map&, const EventMarker&)> eventOperators = { { DOM_VIDEO_EVENT_PREPARED, [](const RefPtr& video, const EventMarker& event) { video->SetPreparedEventId(event); } }, { DOM_VIDEO_EVENT_START, [](const RefPtr& video, const EventMarker& event) { video->SetStartEventId(event); } }, { DOM_VIDEO_EVENT_PAUSE, [](const RefPtr& video, const EventMarker& event) { video->SetPauseEventId(event); } }, { DOM_VIDEO_EVENT_STOP, [](const RefPtr& video, const EventMarker& event) { video->SetStopEventId(event); } }, { DOM_VIDEO_EVENT_FINISH, [](const RefPtr& video, const EventMarker& event) { video->SetFinishEventId(event); } }, { DOM_VIDEO_EVENT_ERROR, [](const RefPtr& video, const EventMarker& event) { video->SetErrorEventId(event); } }, { DOM_VIDEO_EVENT_SEEKING, [](const RefPtr& video, const EventMarker& event) { video->SetSeekingEventId(event); } }, { DOM_VIDEO_EVENT_SEEKED, [](const RefPtr& video, const EventMarker& event) { video->SetSeekedEventId(event); } }, { DOM_VIDEO_EVENT_TIMEUPDATE, [](const RefPtr& video, const EventMarker& event) { video->SetTimeUpdateEventId(event); } }, { DOM_VIDEO_EVENT_FULLSCREENCHANGE, [](const RefPtr& video, const EventMarker& event) { video->SetFullscreenChangeEventId(event); } }, }; auto operatorIter = eventOperators.find(event); if (operatorIter != eventOperators.end()) { operatorIter->second(videoChild_, EventMarker(GetNodeIdForEvent(), event, pageId)); return true; } return false; } void DOMVideo::CallSpecializedMethod(const std::string& method, const std::string& args) { // Operator map for method static const std::unordered_map&, const std::string&)> methedOperators = { { DOM_VIDEO_METHOD_START, [](const RefPtr& video, const std::string& args) { auto controller = video->GetVideoController(); ACE_DCHECK(controller); controller->Start(); } }, { DOM_VIDEO_METHOD_PAUSE, [](const RefPtr& video, const std::string& args) { auto controller = video->GetVideoController(); ACE_DCHECK(controller); controller->Pause(); } }, { DOM_VIDEO_METHOD_STOP, [](const RefPtr& video, const std::string& args) { auto controller = video->GetVideoController(); ACE_DCHECK(controller); controller->Stop(); } }, { DOM_VIDEO_METHOD_SEEK_TO, [](const RefPtr& video, const std::string& args) { auto controller = video->GetVideoController(); ACE_DCHECK(controller); auto value = GetParamFromJson(args, "currenttime"); if (value) { int32_t pos = value->GetInt(); controller->SeekTo(pos); } } }, { DOM_VIDEO_METHOD_REQUEST_FULLSCREEN, [](const RefPtr& video, const std::string& args) { auto controller = video->GetVideoController(); ACE_DCHECK(controller); auto value = GetParamFromJson(args, "screenOrientation "); if (value) { controller->RequestFullscreen(!(value->GetString() == "landscape")); } } }, { DOM_VIDEO_METHOD_EXIT_FULLSCREEN, [](const RefPtr& video, const std::string& args) { auto controller = video->GetVideoController(); ACE_DCHECK(controller); controller->ExitFullscreen(false); } }, }; auto operatorIter = methedOperators.find(method); if (operatorIter != methedOperators.end()) { operatorIter->second(videoChild_, args); } } std::unique_ptr DOMVideo::GetParamFromJson(const std::string& json, const std::string& key) { std::unique_ptr argsValue = JsonUtil::ParseJsonString(json); if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != METHOD_VIDEO_TO_ARGS_SIZE) { LOGW("Video parse args error"); return nullptr; } std::unique_ptr Value = argsValue->GetArrayItem(0)->GetValue(key); if (!Value) { return nullptr; } return Value; } RefPtr DOMVideo::FireFullscreen( bool isFullScreen, const WeakPtr& player, const WeakPtr& texture) { const auto& composed = GetRootComponent(); ACE_DCHECK(composed); if (isFullScreen) { if (isFullscreen_) { return nullptr; } originComponent_ = composed->GetChild(); videoChild_->SetFullscreen(true); videoChild_->SetPlayer(player); videoChild_->SetTexture(texture); composed->SetChild(GetEventComponents(videoChild_)); isFullscreen_ = true; } else { if (!isFullscreen_) { return nullptr; } if (!originComponent_) { return nullptr; } videoChild_->SetFullscreen(false); videoChild_->SetPlayer(nullptr); videoChild_->SetTexture(nullptr); composed->SetChild(originComponent_); isFullscreen_ = false; auto controller = videoChild_->GetVideoController(); ACE_DCHECK(controller); controller->ExitFullscreen(true); return nullptr; } return GetRootComponent(); } RefPtr DOMVideo::GetEventComponents(const RefPtr& videoChild) { std::vector> components; RefPtr focusableEventComponent = GetFocusableComponent(); if (focusableEventComponent) { components.emplace_back(focusableEventComponent); } RefPtr touchEventComponent = GetTouchListenerComponent(); if (touchEventComponent) { components.emplace_back(touchEventComponent); } RefPtr gestureEventComponent = GetGestureListenerComponent(); if (gestureEventComponent) { components.emplace_back(gestureEventComponent); } RefPtr mouseEventComponent = GetMouseListenerComponent(); if (mouseEventComponent) { components.emplace_back(mouseEventComponent); } for (int32_t idx = static_cast(components.size()) - 1; idx >= 1; --idx) { components[idx - 1]->SetChild(components[idx]); } auto box = AceType::MakeRefPtr(); Component::MergeRSNode(box); RefPtr oldBox = GetBoxComponent(); if (oldBox) { box->SetOnClick(oldBox->GetOnClick()); } box->SetChild(videoChild); if (!components.empty()) { const auto& lastEventComponent = components.back(); if (lastEventComponent) { lastEventComponent->SetChild(box); return components.front(); } } return box; } ImageFit DOMVideo::ConvertStrToFit(const std::string& fit) { static const std::unordered_map IMAGE_FIT_TABLE = { { "fill", ImageFit::FILL }, { "contain", ImageFit::CONTAIN }, { "cover", ImageFit::COVER }, { "scaledown", ImageFit::SCALE_DOWN }, { "none", ImageFit::NONE }, }; auto imageFitIter = IMAGE_FIT_TABLE.find(fit); return imageFitIter != IMAGE_FIT_TABLE.end() ? imageFitIter->second : ImageFit::CONTAIN; } ImageObjectPosition DOMVideo::ConvertStrToPosition(const std::string& position) { ImageObjectPosition objectPosition; ParseBackgroundImagePosition(position, objectPosition); return objectPosition; } } // namespace OHOS::Ace::Framework