[WRTjs][VD] Introduce in-process VideoSplashScreen 44/308844/5 submit/tizen/20240409.160014
authorDongHyun Song <dh81.song@samsung.com>
Fri, 10 Nov 2023 00:28:31 +0000 (09:28 +0900)
committerBot Blink <blinkbot@samsung.com>
Tue, 9 Apr 2024 08:18:59 +0000 (08:18 +0000)
From Tizen 5.5 VideoSplashScreen has been introduced, which is
running on amd process as amd-extension.

Recently, amd process had some performance issues due to video
playing, so we had decided to move VSS feature to WRT side.

This patch MUST be released with AppFW team's changes, wich disable
VSS feature on their side.

Change-Id: I0d564941628c883d644d1a89e0a46a0d06eb45e2
Signed-off-by: DongHyun Song <dh81.song@samsung.com>
29 files changed:
packaging/chromium-efl.spec
tizen_src/build/BUILD.gn
wrt/BUILD.gn
wrt/filenames.gni
wrt/src/browser/basic_splash_screen.cc
wrt/src/browser/basic_splash_screen.h
wrt/src/browser/basic_splash_screen_off_screen.cc
wrt/src/browser/basic_splash_screen_off_screen.h
wrt/src/browser/basic_splash_screen_on_screen.cc
wrt/src/browser/basic_splash_screen_on_screen.h
wrt/src/browser/splash_screen.cc
wrt/src/browser/splash_screen.h
wrt/src/browser/tv/native_web_runtime_delegate_tv.cc
wrt/src/browser/tv/native_web_runtime_delegate_tv.h
wrt/src/browser/tv/splash_screen_delegate_tv.cc
wrt/src/browser/tv/splash_screen_delegate_tv.h
wrt/src/browser/tv/video_splash_amd_player.cc [new file with mode: 0644]
wrt/src/browser/tv/video_splash_amd_player.h [new file with mode: 0644]
wrt/src/browser/tv/video_splash_player.cc [new file with mode: 0644]
wrt/src/browser/tv/video_splash_player.h [new file with mode: 0644]
wrt/src/browser/tv/video_splash_screen.cc
wrt/src/browser/tv/video_splash_screen.h
wrt/src/browser/tv/wrt_native_window_tv.cc
wrt/src/browser/wrt_native_window.cc
wrt/src/common/application_data_wrapper.h
wrt/src/common/splash_screen_delegate.cc [new file with mode: 0644]
wrt/src/common/splash_screen_delegate.h
wrt/src/common/tv/wrt_lib_wrapper.cc
wrt/src/common/tv/wrt_lib_wrapper.h

index f6624ae..f2dc9b0 100644 (file)
@@ -198,7 +198,6 @@ BuildRequires: pkgconfig(xtst)
 %endif
 
 %if "%{?tizen_profile_name}" == "tv"
-BuildRequires: pkgconfig(aul-extension)
 BuildRequires: pkgconfig(capi-media-sound-manager)
 BuildRequires: pkgconfig(capi-stt-wrapper-tv)
 BuildRequires: pkgconfig(capi-system-display-rotator)
index 4721b99..ff72301 100644 (file)
@@ -931,9 +931,6 @@ if (enable_wrt_js) {
   }
 
   if (tizen_product_tv) {
-    tizen_pkg_config("aul-extension") {
-      packages = [ "aul-extension" ]
-    }
     tizen_pkg_config("autoinput") {
       packages = [ "autoinput" ]
     }
index b6ba21d..8fb2b68 100644 (file)
@@ -275,7 +275,6 @@ config("wrt_config") {
   }
   if (tizen_product_tv) {
     configs += [
-      "//tizen_src/build:aul-extension",
       "//tizen_src/build:autoinput",
       "//tizen_src/build:libcapi-media-camera",
       "//tizen_src/build:capi-screensaver",
index 4fbf198..d04f234 100644 (file)
@@ -133,6 +133,7 @@ wrt_lib_sources = [
   "src/common/privilege.h",
   "src/common/resource_manager.cc",
   "src/common/resource_manager.h",
+  "src/common/splash_screen_delegate.cc",
   "src/common/splash_screen_delegate.h",
   "src/common/wrt_application_info.cc",
   "src/common/wrt_content_client.cc",
@@ -204,6 +205,10 @@ wrt_lib_sources_tv = [
   "src/browser/tv/splash_screen_delegate_tv.h",
   "src/browser/tv/tv_window_manager.cc",
   "src/browser/tv/tv_window_manager.h",
+  "src/browser/tv/video_splash_amd_player.cc",
+  "src/browser/tv/video_splash_amd_player.h",
+  "src/browser/tv/video_splash_player.cc",
+  "src/browser/tv/video_splash_player.h",
   "src/browser/tv/video_splash_screen.cc",
   "src/browser/tv/video_splash_screen.h",
   "src/browser/tv/widget_state.cc",
index 26f5fcb..82f7900 100644 (file)
 namespace wrt {
 
 // static
-SplashScreen* BasicSplashScreen::Create(
-    std::unique_ptr<SplashScreenDelegate> delegate) {
+SplashScreen* BasicSplashScreen::Create() {
   if (WRTNativeWindow::UseOnscreenRendering())
-    return new BasicSplashScreenOnScreen(std::move(delegate));
+    return new BasicSplashScreenOnScreen();
   else
-    return new BasicSplashScreenOffScreen(std::move(delegate));
+    return new BasicSplashScreenOffScreen();
 }
 
-BasicSplashScreen::BasicSplashScreen(
-    std::unique_ptr<SplashScreenDelegate> delegate)
-    : delegate_(std::move(delegate)) {}
-
 wgt::parse::ReadyWhen BasicSplashScreen::GetReadyWhen() {
   auto& app_data = ApplicationData::GetInstance();
   return app_data.launch_screen_info().ready_when();
index 0b2e733..b1e36a1 100644 (file)
@@ -25,14 +25,13 @@ namespace wrt {
 
 class BasicSplashScreen : public SplashScreen {
  public:
-  static SplashScreen* Create(std::unique_ptr<SplashScreenDelegate> delegate);
+  static SplashScreen* Create();
 
   ~BasicSplashScreen() override = default;
 
  protected:
-  BasicSplashScreen(std::unique_ptr<SplashScreenDelegate> delegate);
+  BasicSplashScreen() = default;
 
-  void BeforeHide() override {}
   wgt::parse::ReadyWhen GetReadyWhen() override;
 
   using SplashScreenData = const wgt::parse::LaunchScreenData;
@@ -42,8 +41,6 @@ class BasicSplashScreen : public SplashScreen {
   gfx::Insets ParseImageBorder(const std::vector<std::string>& borders,
                                std::vector<BorderOption>* border_options);
   std::string GetImagePath(SplashScreenData* splash_screen_data);
-
-  std::unique_ptr<SplashScreenDelegate> delegate_;
 };
 
 }  // namespace wrt
index be0fa4b..7d5d903 100644 (file)
@@ -32,10 +32,6 @@ gfx::Size GetWindowSize(Evas_Object* window) {
 
 }  // namespace
 
-BasicSplashScreenOffScreen::BasicSplashScreenOffScreen(
-    std::unique_ptr<SplashScreenDelegate> delegate)
-    : BasicSplashScreen(std::move(delegate)) {}
-
 void BasicSplashScreenOffScreen::Init() {
   auto* window = WRTNativeWindow::GetTopWindow();
   auto size = GetWindowSize(window);
index a8118ab..6d465f2 100644 (file)
@@ -26,7 +26,7 @@ namespace wrt {
 
 class BasicSplashScreenOffScreen : public BasicSplashScreen {
  public:
-  BasicSplashScreenOffScreen(std::unique_ptr<SplashScreenDelegate> delegate);
+  BasicSplashScreenOffScreen() = default;
   ~BasicSplashScreenOffScreen() override = default;
 
  protected:
index 8aac890..4c35fc7 100644 (file)
 
 namespace wrt {
 
-BasicSplashScreenOnScreen::BasicSplashScreenOnScreen(
-    std::unique_ptr<SplashScreenDelegate> delegate)
-    : BasicSplashScreen(std::move(delegate)),
-      widget_delegate_(new SplashScreenWidgetDelegate) {}
+BasicSplashScreenOnScreen::BasicSplashScreenOnScreen()
+    : widget_delegate_(new SplashScreenWidgetDelegate) {}
 
 void BasicSplashScreenOnScreen::Init() {
   auto* host = widget_delegate_->host();
index 969758d..9d8c783 100644 (file)
@@ -25,7 +25,7 @@ class SplashScreenWidgetDelegate;
 
 class BasicSplashScreenOnScreen : public BasicSplashScreen {
  public:
-  BasicSplashScreenOnScreen(std::unique_ptr<SplashScreenDelegate> delegate);
+  BasicSplashScreenOnScreen();
   ~BasicSplashScreenOnScreen() override = default;
 
  protected:
index 15c5cef..e382439 100644 (file)
@@ -19,7 +19,6 @@
 #include "base/logging.h"
 #include "base/task/single_thread_task_runner.h"
 #include "wrt/src/browser/basic_splash_screen.h"
-#include "wrt/src/browser/wrt_native_window.h"
 
 #if BUILDFLAG(IS_TIZEN_TV)
 #include "wrt/src/browser/tv/splash_screen_delegate_tv.h"
@@ -46,17 +45,15 @@ bool SplashScreen::ShowSplashScreen() {
   delegate = std::make_unique<SplashScreenDelegateTV>();
 #elif BUILDFLAG(IS_TIZEN_DA)
   delegate = std::make_unique<SplashScreenDelegateDA>();
+#else
+  delegate = std::make_unique<SplashScreenDelegate>();
 #endif
 
-  auto& app_data = ApplicationData::GetInstance();
-  if (delegate && delegate->IsVideoPlaying())
-    splash_screen.reset(delegate->CreateVideoSplashScreen());
-  else if (app_data.launch_screen_info().HasLaunchScreenData())
-    splash_screen.reset(BasicSplashScreen::Create(std::move(delegate)));
-
+  splash_screen.reset(delegate->CreateSplashScreen());
   if (!splash_screen)
     return false;
 
+  splash_screen->SetDelegate(std::move(delegate));
   splash_screen->Init();
   return true;
 }
@@ -84,7 +81,6 @@ bool SplashScreen::HideSplashScreen(HideReason reason) {
   }
   hidden_reason = reason;
 
-  splash_screen->BeforeHide();
   LOG(INFO) << "Will HideSplashScreen reason by " << reason;
   return true;
 }
@@ -99,10 +95,17 @@ bool SplashScreen::IsShowing() {
   return !!splash_screen && hidden_reason == HideReason::UNDECIDED;
 }
 
+// static
+void SplashScreen::AddObserver(WRTNativeWindow* native_window) {
+  // Because SplashScreen can be created before NativeWindow created,
+  //  - i.e., VideoSplashScreen
+  // AddObserver should be called on NativeWindow created time.
+  if (splash_screen)
+    native_window->AddObserver(splash_screen.get());
+}
+
 SplashScreen::SplashScreen() {
-  auto main_native_window = WRTNativeWindow::GetMainNativeWindow();
-  if (main_native_window)
-    main_native_window->AddObserver(this);
+  LOG(INFO) << "SplashScreen is created";
 }
 
 SplashScreen::~SplashScreen() {
index ff453e7..c58da29 100644 (file)
 #define BROWSER_SPLASH_SCREEN_H_
 
 #include "electron/shell/browser/native_window_observer.h"
+#include "wrt/src/browser/wrt_native_window.h"
 #include "wrt/src/common/application_data.h"
+#include "wrt/src/common/splash_screen_delegate.h"
 
 namespace wrt {
 
-enum HideReason {
-  RENDERED,
-  LOADFINISHED,
-  CUSTOM,
-  VIDEOFINISHED,
-  UNDECIDED,
-};
+enum HideReason { RENDERED, LOADFINISHED, CUSTOM, VIDEOFINISHED, UNDECIDED };
 
 class SplashScreen : public electron::NativeWindowObserver {
  public:
+  static void AddObserver(WRTNativeWindow* native_window);
   static bool ShowSplashScreen();
   static bool HideSplashScreen(HideReason reason);
   static bool IsShowing();
@@ -43,12 +40,17 @@ class SplashScreen : public electron::NativeWindowObserver {
   SplashScreen();
 
   virtual void Init() = 0;
-  virtual void BeforeHide() = 0;
   virtual void Hide() = 0;
   virtual wgt::parse::ReadyWhen GetReadyWhen() = 0;
 
+  void SetDelegate(std::unique_ptr<SplashScreenDelegate> delegate) {
+    delegate_ = std::move(delegate);
+  }
+
   // electron::NativeWindowObserver
   void OnWindowShow() override;
+
+  std::unique_ptr<SplashScreenDelegate> delegate_;
 };
 
 }  // namespace wrt
index 675bb13..9ca79eb 100644 (file)
@@ -278,14 +278,20 @@ void NativeWebRuntimeDelegateTV::Initialize(void* data) {
   auto extension_manager = XWalkExtensionManager::GetInstance();
   extension_manager->RegisterUpgradableExtensions();
 
+  EarlyPlayVideoSplashScreen();
   SetAllowedPath();
   SetFileRequestIntercepter(base::BindRepeating(
       &NativeWebRuntimeDelegateTV::IsAllowedPath, base::Unretained(this)));
   SetEncryptedFileUrlCallbacks();
-
   initialized_ = true;
 }
 
+void NativeWebRuntimeDelegateTV::EarlyPlayVideoSplashScreen() {
+  auto& app_data = ApplicationDataTV::GetInstance();
+  if (app_data.video_splash_screen_info().HasVideoSplashScreenData())
+    SplashScreen::ShowSplashScreen();
+}
+
 void NativeWebRuntimeDelegateTV::EarlyLoadUrlIfHostedApp() {
   auto& app_data = ApplicationData::GetInstance();
   if (!app_data.IsHostedApp() || has_payload_data_)
@@ -299,7 +305,6 @@ void NativeWebRuntimeDelegateTV::EarlyLoadUrlIfHostedApp() {
 }
 
 void NativeWebRuntimeDelegateTV::DidInitialized() {
-  VideoSplashScreen::InitializeVSS();
   EarlyLoadUrlIfHostedApp();
   SetD2dServiceMessageListener();
   SubscribePowerState();
@@ -643,7 +648,13 @@ void NativeWebRuntimeDelegateTV::PepperUpdatePluginService() {
 // static
 void NativeWebRuntimeDelegateTV::PreSetupOnWorker() {
   LOG(INFO) << "PreSetupOnWorker";
-  if (!ApplicationData::GetInstance().IsHostedApp())
+  auto& app_data = ApplicationDataTV::GetInstance();
+  auto is_local_app = !app_data.IsHostedApp();
+  auto has_splash_screen =
+      app_data.launch_screen_info().HasLaunchScreenData() ||
+      app_data.video_splash_screen_info().HasVideoSplashScreenData();
+
+  if (is_local_app || has_splash_screen)
     GetInstance().TryMount();
   GetInstance().PepperUpdatePluginService();
 }
index a6a658d..d35e30a 100644 (file)
@@ -78,6 +78,7 @@ class NativeWebRuntimeDelegateTV : public WRTProfileDelegate {
   void ApplyHalfWindow(std::string half_window_option);
   void ClearTmpFolder();
   void EarlyLoadUrlIfHostedApp();
+  void EarlyPlayVideoSplashScreen();
   bool IsAllowedPath(const base::FilePath& path);
   void SetAllowedPath();
   void SetD2dServiceMessageListener();
index b2b459a..4c3bae9 100755 (executable)
@@ -7,6 +7,7 @@
 #include <display-rotator-api.h>
 
 #include "tizen_src/chromium_impl/tizen/vconf_handle.h"
+#include "wrt/src/browser/tv/native_web_runtime_delegate_tv.h"
 #include "wrt/src/browser/tv/video_splash_screen.h"
 #include "wrt/src/common/tv/application_data_tv.h"
 
@@ -19,6 +20,10 @@ const char* kVconfRotationState = "db/sysman/rotation_state";
 
 } // namespace
 
+SplashScreenDelegateTV::SplashScreenDelegateTV() {
+  NativeWebRuntimeDelegateTV::GetInstance().TryMount();
+}
+
 wgt::parse::ScreenOrientation SplashScreenDelegateTV::GetScreenOrientation() {
   int rotation_state = VconfHandle(kVconfRotationState).Int();
   if (rotation_state == DISPLAY_ROTATOR_ORIENTATION_PORTRAIT ||
@@ -38,14 +43,12 @@ std::string SplashScreenDelegateTV::ConvertAliasPath(std::string& image_path) {
   }
 }
 
-bool SplashScreenDelegateTV::IsVideoPlaying() {
+SplashScreen* SplashScreenDelegateTV::CreateSplashScreen() {
   auto& app_data = ApplicationDataTV::GetInstance();
-  return app_data.video_splash_screen_info().HasVideoSplashScreenData() &&
-         VideoSplashScreen::IsVSSPlaying();
-}
-
-SplashScreen* SplashScreenDelegateTV::CreateVideoSplashScreen() {
-  return new VideoSplashScreen;
+  if (app_data.video_splash_screen_info().HasVideoSplashScreenData())
+    return VideoSplashScreen::Create();
+  else
+    return SplashScreenDelegate::CreateSplashScreen();
 }
 
 }  // namespace wrt
index 2f2e5d5..b3770ea 100644 (file)
@@ -11,14 +11,13 @@ namespace wrt {
 
 class SplashScreenDelegateTV : public SplashScreenDelegate {
  public:
-  SplashScreenDelegateTV() {}
+  SplashScreenDelegateTV();
   ~SplashScreenDelegateTV() override {}
 
  private:
-  bool IsVideoPlaying() override;
   std::string ConvertAliasPath(std::string& image_path) override;
-  SplashScreen* CreateVideoSplashScreen() override;
   wgt::parse::ScreenOrientation GetScreenOrientation() override;
+  SplashScreen* CreateSplashScreen() override;
 };
 
 }  // namespace wrt
diff --git a/wrt/src/browser/tv/video_splash_amd_player.cc b/wrt/src/browser/tv/video_splash_amd_player.cc
new file mode 100644 (file)
index 0000000..5303072
--- /dev/null
@@ -0,0 +1,143 @@
+// Copyright 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "wrt/src/browser/tv/video_splash_amd_player.h"
+
+#include "wrt/src/browser/native_web_runtime.h"
+#include "wrt/src/browser/splash_screen.h"
+#include "wrt/src/browser/tv/widget_state.h"
+#include "wrt/src/common/tv/application_data_tv.h"
+#include "wrt/src/common/tv/wrt_lib_wrapper.h"
+
+namespace wrt {
+
+namespace {
+
+const char* kSplashScreenAulAppCom = "crosswalk.splashscreen.player.";
+aul_app_com_connection_h aul_app_com_connection_ = nullptr;
+
+const char* HideReasonToString(HideReason reason) {
+  switch (reason) {
+    case HideReason::UNDECIDED:
+      return "UNDECIDED";
+    case HideReason::CUSTOM:
+      return "CUSTOM";
+    case HideReason::RENDERED:
+      return "FIRST_PAINT";
+    case HideReason::LOADFINISHED:
+      return "COMPLETE";
+    case HideReason::VIDEOFINISHED:
+      return "VIDEO_FINISHED";
+  }
+  return "UNKNOWN";
+}
+
+void HideVSSPlayer(std::string hide_reason) {
+  if (hide_reason != "VIDEOFINISHED") {
+    int error_code = aul_extension_splash_screen_tv_event(hide_reason.c_str());
+    LOG(INFO) << "Hide AUL SplashScreen msg send with " << error_code << " ["
+              << hide_reason << "]";
+  } else {
+    LOG(INFO) << "Hide AUL SplashScreen msg send with --- [" << hide_reason
+              << "]";
+  }
+}
+
+bool ReleaseVSSCom() {
+  auto& app_data = ApplicationDataTV::GetInstance();
+  return (app_data.video_splash_screen_info().HasVideoSplashScreenData() &&
+          !!aul_app_com_connection_ &&
+          !aul_extension_splash_screen_tv_event("ISVIDEO"));
+}
+
+int OnSplashScreenMessage(const char* endpoint,
+                          aul_app_com_result_e e,
+                          bundle* envelope,
+                          void* user_data) {
+  char* tmp = nullptr;
+  bundle_get_str(envelope, "EVENT", &tmp);
+  if (!tmp)
+    return -1;
+  std::string msg(tmp);
+  LOG(INFO) << "Get msg from splash screen: " << msg;
+  if ("VIDEOFINISHED" == msg || "PLAYERERROR" == msg) {
+    HideVSSPlayer("VIDEOFINISHED");
+    std::vector<std::string> params = {"video-finished"};
+    NativeWebRuntime::GetInstance().NotifyMessage("hideSplashScreen", params);
+  } else if ("TERMINATE" == msg) {
+    NativeWebRuntime::GetInstance().RequestQuit();
+  } else if ("INTERRUPT" == msg) {
+    VideoSplashAmdPlayer::Finalize();
+    NativeWebRuntime::GetInstance().NotifySuspend();
+    WidgetStateProvider::OnStatusChanged("pause");
+  } else {
+    return -1;
+  }
+  return 0;
+}
+
+}  // namespace
+
+VideoSplashAmdPlayer::VideoSplashAmdPlayer() {
+  if (aul_app_com_connection_)
+    return;
+
+  if (!aul_extension_splash_screen_tv_event("ISVIDEO")) {
+    LOG(ERROR) << "Failed to send ISVIDEO to VSS";
+    return;
+  }
+
+  auto& app_data = ApplicationDataTV::GetInstance();
+  std::string com_endpoint = kSplashScreenAulAppCom + app_data.app_id();
+  if (aul_app_com_create(com_endpoint.c_str(), nullptr, OnSplashScreenMessage,
+                         nullptr, &aul_app_com_connection_)) {
+    LOG(ERROR) << "Failed to initialize AUL APP COM";
+  } else {
+    LOG(ERROR) << "Initialized AUL APP COM with " << com_endpoint;
+  }
+}
+
+VideoSplashAmdPlayer::~VideoSplashAmdPlayer() {}
+
+// static
+void VideoSplashAmdPlayer::Finalize() {
+  if (!ReleaseVSSCom())
+    return;
+
+  LOG(INFO) << "Finalize AUL APP COM and VSS";
+  aul_app_com_leave(aul_app_com_connection_);
+  aul_app_com_connection_ = nullptr;
+  aul_extension_splash_screen_tv_reset();
+}
+
+void VideoSplashAmdPlayer::Hide() {
+  if (was_hidden_)
+    return;
+
+  if (IsPlayerPlaying()) {
+    auto hidden_reason = SplashScreen::GetHiddenReason();
+    const char* hide_reason = HideReasonToString(hidden_reason);
+    HideVSSPlayer(hide_reason);
+    was_hidden_ = true;
+  }
+  Finalize();
+}
+
+bool VideoSplashAmdPlayer::Initialize() {
+  return true;
+}
+
+bool VideoSplashAmdPlayer::PreparePlayer() {
+  return true;
+}
+
+bool VideoSplashAmdPlayer::PlayerStart(const std::string& video_src) {
+  return true;
+}
+
+bool VideoSplashAmdPlayer::IsPlayerPlaying() {
+  return !!aul_app_com_connection_;
+}
+
+}  // namespace wrt
diff --git a/wrt/src/browser/tv/video_splash_amd_player.h b/wrt/src/browser/tv/video_splash_amd_player.h
new file mode 100644 (file)
index 0000000..1dc642e
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BROWSER_VIDEO_SPLASH_AMD_PLAYER_H_
+#define BROWSER_VIDEO_SPLASH_AMD_PLAYER_H_
+
+#include "wrt/src/browser/tv/video_splash_player.h"
+#include "wrt/src/common/application_data.h"
+
+namespace wrt {
+
+class VideoSplashAmdPlayer : public VideoSplashPlayer {
+ public:
+  static void Finalize();
+
+  VideoSplashAmdPlayer();
+  ~VideoSplashAmdPlayer() override;
+
+ private:
+  void Hide() override;
+  bool Initialize() override;
+  bool PreparePlayer() override;
+  bool PlayerStart(const std::string& video_src) override;
+  bool IsPlayerPlaying() override;
+
+  bool was_hidden_ = false;
+};
+
+}  // namespace wrt
+
+#endif  // BROWSER_VIDEO_SPLASH_AMD_PLAYER_H_
\ No newline at end of file
diff --git a/wrt/src/browser/tv/video_splash_player.cc b/wrt/src/browser/tv/video_splash_player.cc
new file mode 100644 (file)
index 0000000..dc96a75
--- /dev/null
@@ -0,0 +1,375 @@
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "wrt/src/browser/tv/video_splash_player.h"
+
+#include <vector>
+
+#include <Ecore_Wl2.h>
+
+#include "base/logging.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/ozone/platform/efl/efl_window.h"
+#include "wrt/src/browser/native_web_runtime.h"
+#include "wrt/src/browser/tv/widget_state.h"
+#include "wrt/src/browser/tv/wrt_native_window_tv.h"
+#include "wrt/src/common/application_data.h"
+
+namespace wrt {
+
+namespace {
+
+#define ADD_CASE(type) \
+  case type:           \
+    return #type
+
+#define CAPI_CHECK(test, msg)                              \
+  do {                                                     \
+    auto const result = static_cast<player_error_e>(test); \
+    if (result != PLAYER_ERROR_NONE) {                     \
+      LOG(ERROR) << "CAPI " << msg << " failed with "      \
+                 << GetPlayerErrorString(result);          \
+      return result;                                       \
+    }                                                      \
+  } while (0)
+
+const char* kKeyBack = "XF86Back";
+const char* kKeyExit = "XF86Exit";
+const char* kElmWindowName = "VSSPlayer";
+
+inline bool IsKeySameAs(const char* key, const char* event_key) {
+  return strcmp(key, event_key) == 0;
+}
+
+const char* GetPlayerErrorString(player_error_e type) {
+  switch (type) {
+    ADD_CASE(PLAYER_ERROR_NONE);
+    ADD_CASE(PLAYER_ERROR_OUT_OF_MEMORY);
+    ADD_CASE(PLAYER_ERROR_INVALID_PARAMETER);
+    ADD_CASE(PLAYER_ERROR_NO_SUCH_FILE);
+    ADD_CASE(PLAYER_ERROR_INVALID_OPERATION);
+    ADD_CASE(PLAYER_ERROR_FILE_NO_SPACE_ON_DEVICE);
+    ADD_CASE(PLAYER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE);
+    ADD_CASE(PLAYER_ERROR_SEEK_FAILED);
+    ADD_CASE(PLAYER_ERROR_INVALID_STATE);
+    ADD_CASE(PLAYER_ERROR_NOT_SUPPORTED_FILE);
+    ADD_CASE(PLAYER_ERROR_INVALID_URI);
+    ADD_CASE(PLAYER_ERROR_SOUND_POLICY);
+    ADD_CASE(PLAYER_ERROR_CONNECTION_FAILED);
+    ADD_CASE(PLAYER_ERROR_VIDEO_CAPTURE_FAILED);
+    ADD_CASE(PLAYER_ERROR_DRM_EXPIRED);
+    ADD_CASE(PLAYER_ERROR_DRM_NO_LICENSE);
+    ADD_CASE(PLAYER_ERROR_DRM_FUTURE_USE);
+    ADD_CASE(PLAYER_ERROR_DRM_NOT_PERMITTED);
+    ADD_CASE(PLAYER_ERROR_RESOURCE_LIMIT);
+    ADD_CASE(PLAYER_ERROR_PERMISSION_DENIED);
+    ADD_CASE(PLAYER_ERROR_SERVICE_DISCONNECTED);
+    ADD_CASE(PLAYER_ERROR_BUFFER_SPACE);
+    ADD_CASE(PLAYER_ERROR_NOT_SUPPORTED_AUDIO_CODEC);
+    ADD_CASE(PLAYER_ERROR_NOT_SUPPORTED_VIDEO_CODEC);
+    ADD_CASE(PLAYER_ERROR_NOT_SUPPORTED_SUBTITLE);
+    ADD_CASE(PLAYER_ERROR_AUDIO_CODEC_NOT_SUPPORTED);
+    ADD_CASE(PLAYER_ERROR_VIDEO_CODEC_NOT_SUPPORTED);
+    ADD_CASE(PLAYER_ERROR_NO_AUTH);
+    ADD_CASE(PLAYER_ERROR_GENEREIC);
+    ADD_CASE(PLAYER_ERROR_DRM_INFO);
+    ADD_CASE(PLAYER_ERROR_SYNC_PLAY_NETWORK_EXCEPTION);
+    ADD_CASE(PLAYER_ERROR_SYNC_PLAY_SERVER_DOWN);
+    ADD_CASE(PLAYER_ERROR_NOT_SUPPORTED_FORMAT);
+    ADD_CASE(PLAYER_ERROR_STREAMING_PLAYER);
+    ADD_CASE(PLAYER_ERROR_DTCP_FSK);
+    ADD_CASE(PLAYER_ERROR_PRE_LOADING_TIME_OUT);
+    ADD_CASE(PLAYER_ERROR_NETWORK_ERROR);
+    ADD_CASE(PLAYER_ERROR_CHANNEL_SURFING_FAILED);
+    default:
+      return "UNKNOWN ERROR";
+  }
+}
+
+std::string ConvertMessage(VideoSplashPlayer::SplashScreenMsgType msg) {
+  switch (msg) {
+    case VideoSplashPlayer::SplashScreenMsgType::VIDEOFINISHED:
+      return "VIDEOFINISHED";
+    case VideoSplashPlayer::SplashScreenMsgType::TERMINATE:
+      return "TERMINATE";
+    case VideoSplashPlayer::SplashScreenMsgType::PLAYERERROR:
+      return "PLAYERERROR";
+    case VideoSplashPlayer::SplashScreenMsgType::NOVIDEO:
+      return "NOVIDEO";
+    default:
+      return "NONE";
+  }
+}
+
+}  // namespace
+
+void VideoSplashPlayer::CapiPlayer::Show() {
+  LOG(INFO) << "will show VSSPlayer window";
+  if (vss_window_) {
+    evas_object_show(vss_window_);
+    elm_win_raise(vss_window_);
+  }
+}
+
+void VideoSplashPlayer::CapiPlayer::Hide() {
+  DestroyPlayer();
+
+  if (vss_window_) {
+    LOG(INFO) << "will hide VSSPlayer window";
+
+    evas_object_smart_callback_del(vss_window_, "visibility,changed",
+                                   VisibilityChangeEvent);
+    elm_win_lower(vss_window_);
+    evas_object_hide(vss_window_);
+    evas_object_del(vss_window_);
+    vss_window_ = nullptr;
+  }
+}
+
+bool VideoSplashPlayer::CapiPlayer::CreateElmWindow() {
+  vss_window_ = elm_win_add(nullptr, "player", ELM_WIN_BASIC);
+  if (!vss_window_) {
+    LOG(ERROR) << "elm_win_add failed";
+    return false;
+  }
+
+  elm_win_title_set(vss_window_, kElmWindowName);
+  elm_win_borderless_set(vss_window_, EINA_TRUE);
+  elm_win_indicator_mode_set(vss_window_, ELM_WIN_INDICATOR_HIDE);
+
+  int window_width, window_height;
+  elm_win_screen_size_get(vss_window_, nullptr, nullptr, &window_width,
+                          &window_height);
+  evas_object_resize(vss_window_, window_width, window_height);
+  LOG(INFO) << "Screen size : " << window_width << "x" << window_height;
+
+  return true;
+}
+
+VideoSplashPlayer::CapiPlayer::CapiPlayer() {
+  LOG(INFO) << "New CapiPlayer is created";
+}
+
+VideoSplashPlayer::CapiPlayer::~CapiPlayer() {
+  LOG(INFO) << "CapiPlayer is destroying";
+  DestroyPlayer();
+  Hide();
+}
+
+player_state_e VideoSplashPlayer::CapiPlayer::GetPlayerState() {
+  player_state_e state = PLAYER_STATE_NONE;
+  if (!player_ || PLAYER_ERROR_NONE != player_get_state(player_, &state))
+    LOG(ERROR) << "player_get_state failed";
+  return state;
+}
+
+bool VideoSplashPlayer::CapiPlayer::Initialize() {
+  if (key_handler_) {
+    ecore_event_handler_del(key_handler_);
+    key_handler_ = nullptr;
+  }
+
+  if (!CreateElmWindow())
+    return false;
+
+  evas_object_smart_callback_add(vss_window_, "visibility,changed",
+                                 VisibilityChangeEvent, this);
+
+  return true;
+}
+
+int VideoSplashPlayer::CapiPlayer::PreparePlayerGreedy() {
+  CAPI_CHECK(player_create(&(player_)), "player_create");
+  CAPI_CHECK(player_set_error_cb(player_, &OnCapiPlayerError, this),
+             "player_set_error_cb");
+  CAPI_CHECK(player_set_completed_cb(player_, &OnCapiPlayerCompleted, this),
+             "player_set_completed_cb");
+  CAPI_CHECK(
+      player_set_display(player_, PLAYER_DISPLAY_TYPE_OVERLAY, vss_window_),
+      "player_set_display");
+
+  LOG(INFO) << "PreparePlayerGreedy for player finished : " << player_;
+  return PLAYER_ERROR_NONE;
+}
+
+int VideoSplashPlayer::CapiPlayer::ReportError(int error, const char* func) {
+  SendMessage(SplashScreenMsgType::PLAYERERROR);
+  auto error_string = GetPlayerErrorString((player_error_e)error);
+  LOG(ERROR) << func << " failed : " << error_string;
+  return error;
+}
+
+int VideoSplashPlayer::CapiPlayer::PreparePlayerLazy(const char* url) {
+  int error = PLAYER_ERROR_NONE;
+
+  error = player_set_video_still(player_, PLAYER_STILL_MODE_ON);
+  if (error != PLAYER_ERROR_NONE) {
+    return ReportError(error, "player_set_video_still");
+  }
+  if ((error = player_set_uri(player_, url)) != PLAYER_ERROR_NONE) {
+    return ReportError(error, "player_set_uri");
+  }
+  if ((error = player_prepare(player_)) != PLAYER_ERROR_NONE) {
+    return ReportError(error, "player_prepare");
+  }
+
+  Show();
+  if ((error = player_start(player_)) != PLAYER_ERROR_NONE) {
+    return ReportError(error, "player_start");
+  }
+  key_handler_ =
+      ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, OnKeyPressCb, this);
+
+  LOG(INFO) << "PreparePlayerLazy for player finished : " << player_;
+  return error;
+}
+
+bool VideoSplashPlayer::CapiPlayer::RelaunchPlayer() {
+  if (DestroyPlayer() != PLAYER_ERROR_NONE)
+    return false;
+  PreparePlayerGreedy();
+  return true;
+}
+
+bool VideoSplashPlayer::CapiPlayer::IsPlayerPlaying() {
+  return (player_ && GetPlayerState() == PLAYER_STATE_PLAYING);
+}
+
+void VideoSplashPlayer::CapiPlayer::SendMessage(SplashScreenMsgType msg) {
+  auto callback = [](SplashScreenMsgType msg) {
+    LOG(INFO) << "Handle SendMessage - " << ConvertMessage(msg);
+    if (msg == SplashScreenMsgType::PLAYERERROR ||
+        msg == SplashScreenMsgType::NOVIDEO ||
+        msg == SplashScreenMsgType::VIDEOFINISHED) {
+      std::vector<std::string> params = {"video-finished"};
+      NativeWebRuntime::GetInstance().NotifyMessage("hideSplashScreen", params);
+    } else if (msg == SplashScreenMsgType::TERMINATE) {
+      NativeWebRuntime::GetInstance().RequestQuit();
+    }
+  };
+  content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
+                                               base::BindOnce(callback, msg));
+}
+
+void VideoSplashPlayer::CapiPlayer::VisibilityChangeEvent(void* data,
+                                                          Evas_Object* obj,
+                                                          void* event) {
+  CapiPlayer* cp = static_cast<CapiPlayer*>(data);
+  if (!cp)
+    return;
+
+  uintptr_t visibility = reinterpret_cast<uintptr_t>(event);
+  if (!visibility) {
+    LOG(INFO) << "VSS is hidden by another window, will terminate the app";
+    cp->Hide();
+    cp->SendMessage(SplashScreenMsgType::TERMINATE);
+  }
+}
+
+int VideoSplashPlayer::CapiPlayer::DestroyPlayer() {
+  if (player_) {
+    player_set_error_cb(player_, nullptr, nullptr);
+    player_set_completed_cb(player_, nullptr, nullptr);
+
+    if (GetPlayerState() > PLAYER_STATE_READY) {
+      CAPI_CHECK(player_stop(player_), "player_stop");
+      CAPI_CHECK(player_unprepare(player_), "player_unprepare");
+    }
+
+    // Log was moved before the actual player_destroy, as using
+    // "player_" after the player_destroy is going to be flagged
+    // as use-after-free by the SVACE
+    LOG(INFO) << "DestroyPlayer for player finish : " << player_;
+    CAPI_CHECK(player_destroy(player_), "player_destroy");
+    player_ = nullptr;
+  }
+  return PLAYER_ERROR_NONE;
+}
+
+void VideoSplashPlayer::CapiPlayer::OnCapiPlayerCompleted(void* user_data) {
+  auto cp = static_cast<CapiPlayer*>(user_data);
+  if (!cp) {
+    LOG(ERROR) << "No CapiPlayer";
+    return;
+  }
+  LOG(INFO) << "CAPI PLAYER COMPLETED";
+  cp->SendMessage(SplashScreenMsgType::VIDEOFINISHED);
+}
+
+void VideoSplashPlayer::CapiPlayer::OnCapiPlayerError(int error_code,
+                                                      void* user_data) {
+  auto cp = static_cast<CapiPlayer*>(user_data);
+  if (!cp) {
+    LOG(ERROR) << "No CapiPlayer";
+    return;
+  }
+  cp->SendMessage(SplashScreenMsgType::PLAYERERROR);
+}
+
+Eina_Bool VideoSplashPlayer::CapiPlayer::OnKeyPressCb(void* data,
+                                                      int type,
+                                                      void* event) {
+  Ecore_Event_Key* ev = static_cast<Ecore_Event_Key*>(event);
+  CapiPlayer* cp = static_cast<CapiPlayer*>(data);
+  if (!ev || !cp)
+    return ECORE_CALLBACK_CANCEL;
+
+  LOG(INFO) << "Received key press : " << ev->key;
+
+  if (IsKeySameAs(kKeyBack, ev->key) || IsKeySameAs(kKeyExit, ev->key)) {
+    cp->SendMessage(SplashScreenMsgType::TERMINATE);
+  }
+
+  return ECORE_CALLBACK_PASS_ON;
+}
+
+VideoSplashPlayer::VideoSplashPlayer() {
+  capi_player_ = std::make_unique<CapiPlayer>();
+}
+
+VideoSplashPlayer::~VideoSplashPlayer() {
+  LOG(INFO) << "VideoSplashPlayer is destroying";
+}
+
+bool VideoSplashPlayer::PreparePlayer() {
+  if (!capi_player_) {
+    LOG(ERROR) << "There is no capi_player_ yet";
+    return false;
+  }
+  return (capi_player_->PreparePlayerGreedy()) == PLAYER_ERROR_NONE;
+}
+
+bool VideoSplashPlayer::PlayerStart(const std::string& video_src) {
+  if (!capi_player_) {
+    LOG(ERROR) << "There is no capi_player_ yet";
+    return false;
+  }
+
+  if (capi_player_->IsPlayerPlaying())
+    capi_player_->RelaunchPlayer();
+
+  LOG(INFO) << "video_src : " << video_src;
+  if (video_src.empty()) {
+    capi_player_->SendMessage(SplashScreenMsgType::NOVIDEO);
+    return false;
+  }
+
+  auto play_prepared = capi_player_->PreparePlayerLazy(video_src.c_str());
+  return play_prepared == PLAYER_ERROR_NONE;
+}
+
+bool VideoSplashPlayer::IsPlayerPlaying() {
+  return capi_player_->IsPlayerPlaying();
+}
+
+void VideoSplashPlayer::Hide() {
+  capi_player_->Hide();
+}
+
+bool VideoSplashPlayer::Initialize() {
+  return capi_player_->Initialize();
+}
+
+}  // namespace wrt
diff --git a/wrt/src/browser/tv/video_splash_player.h b/wrt/src/browser/tv/video_splash_player.h
new file mode 100644 (file)
index 0000000..8714991
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BROWSER_VIDEO_SPLASH_PLAYER_H_
+#define BROWSER_VIDEO_SPLASH_PLAYER_H_
+
+#include <string>
+
+#include <Elementary.h>
+#include <player_product.h>
+
+#include "wrt/src/browser/tv/video_splash_screen.h"
+
+namespace wrt {
+
+class VideoSplashPlayer {
+ public:
+  enum class SplashScreenMsgType {
+    VIDEOFINISHED,
+    TERMINATE,
+    PLAYERERROR,
+    NOVIDEO
+  };
+
+  VideoSplashPlayer();
+  virtual ~VideoSplashPlayer();
+
+  virtual void Hide();
+  virtual bool Initialize();
+  virtual bool PreparePlayer();
+  virtual bool PlayerStart(const std::string& video_src);
+  virtual bool IsPlayerPlaying();
+
+  class CapiPlayer {
+   public:
+    CapiPlayer();
+    ~CapiPlayer();
+
+    void Show();
+    void Hide();
+    bool Initialize();
+    int PreparePlayerGreedy();
+    int PreparePlayerLazy(const char* url);
+
+    bool RelaunchPlayer();
+    bool IsPlayerPlaying();
+    void SendMessage(SplashScreenMsgType msg);
+
+   private:
+    static void OnCapiPlayerCompleted(void* user_data);
+    static void OnCapiPlayerError(int error_code, void* user_data);
+    static Eina_Bool OnKeyPressCb(void* data, int type, void* event);
+    static void VisibilityChangeEvent(void* data,
+                                      Evas_Object* obj,
+                                      void* event);
+
+    player_state_e GetPlayerState();
+    bool CreateElmWindow();
+    int DestroyPlayer();
+    int ReportError(int error, const char* func);
+
+    Evas_Object* vss_window_ = nullptr;
+    Ecore_Event_Handler* key_handler_ = nullptr;
+
+    player_h player_ = nullptr;
+  };
+
+ private:
+  std::unique_ptr<CapiPlayer> capi_player_;
+};
+
+}  // namespace wrt
+
+#endif  // BROWSER_VIDEO_SPLASH_PLAYER_H_
index 63849eb..8ce4089 100644 (file)
 
 #include "wrt/src/browser/tv/video_splash_screen.h"
 
-#include <aul-extension.h>
-#include <aul_app_com.h>
-
-#include "wrt/src/browser/native_web_runtime.h"
-#include "wrt/src/browser/tv/widget_state.h"
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "chromium_impl/build/tizen_version.h"
+#include "wrt/src/browser/tv/native_web_runtime_delegate_tv.h"
 #include "wrt/src/browser/tv/wrt_native_window_tv.h"
+#include "wrt/src/browser/wrt_native_widget.h"
 #include "wrt/src/common/tv/application_data_tv.h"
 
+#if TIZEN_VERSION_AT_LEAST(9, 0, 0)
+#include "wrt/src/browser/tv/video_splash_player.h"
+#else
+#include "wrt/src/browser/tv/video_splash_amd_player.h"
+#endif
+
 namespace wrt {
 
 namespace {
 
-const char* kSplashScreenAulAppCom = "crosswalk.splashscreen.player.";
-aul_app_com_connection_h aul_app_com_connection_ = nullptr;
-
-const char* HideReasonToString(HideReason reason) {
-  switch (reason) {
-    case HideReason::UNDECIDED:
-      return "UNDECIDED";
-    case HideReason::CUSTOM:
-      return "CUSTOM";
-    case HideReason::RENDERED:
-      return "FIRST_PAINT";
-    case HideReason::LOADFINISHED:
-      return "COMPLETE";
-    case HideReason::VIDEOFINISHED:
-      return "VIDEO_FINISHED";
-  }
-  return "UNKNOWN";
-}
-
-void HideVSSPlayer(std::string hide_reason) {
-  if (hide_reason != "VIDEOFINISHED") {
-    int error_code = aul_extension_splash_screen_tv_event(hide_reason.c_str());
-    LOG(INFO) << "Hide AUL SplashScreen msg send with " << error_code << " ["
-              << hide_reason << "]";
-  } else {
-    LOG(INFO) << "Hide AUL SplashScreen msg send with --- [" << hide_reason
-              << "]";
-  }
-}
-
-int OnSplashScreenMessage(const char* endpoint,
-                          aul_app_com_result_e e,
-                          bundle* envelope,
-                          void* user_data) {
-  char* tmp = nullptr;
-  bundle_get_str(envelope, "EVENT", &tmp);
-  if (!tmp)
-    return -1;
-  std::string msg(tmp);
-  LOG(INFO) << "Get msg from splash screen: " << msg;
-  if ("VIDEOFINISHED" == msg || "PLAYERERROR" == msg) {
-    HideVSSPlayer("VIDEOFINISHED");
-    std::vector<std::string> params = {"video-finished"};
-    NativeWebRuntime::GetInstance().NotifyMessage("hideSplashScreen", params);
-  } else if ("TERMINATE" == msg) {
-    NativeWebRuntime::GetInstance().RequestQuit();
-  } else if ("INTERRUPT" == msg) {
-    VideoSplashScreen::FinalizeVSS();
-    NativeWebRuntime::GetInstance().NotifySuspend();
-    WidgetStateProvider::OnStatusChanged("pause");
-  } else {
-    return -1;
-  }
-  return 0;
-}
-
-bool ReleaseVSSCom() {
-  auto& app_data = ApplicationDataTV::GetInstance();
-
-  return (app_data.video_splash_screen_info().HasVideoSplashScreenData() &&
-          !!aul_app_com_connection_ &&
-          !aul_extension_splash_screen_tv_event("ISVIDEO"));
-}
+std::unique_ptr<VideoSplashPlayer> video_player;
 
 }  // namespace
 
-VideoSplashScreen::~VideoSplashScreen() {
-  FinalizeVSS();
-}
-
 // static
-bool VideoSplashScreen::IsVSSPlaying() {
-  return !!aul_app_com_connection_;
+SplashScreen* VideoSplashScreen::Create() {
+  return new VideoSplashScreen();
 }
 
 // static
-void VideoSplashScreen::FinalizeVSS() {
-  if (!ReleaseVSSCom())
-    return;
+bool VideoSplashScreen::IsPlayerPlaying() {
+  auto& app_data = ApplicationDataTV::GetInstance();
+  return app_data.video_splash_screen_info().HasVideoSplashScreenData() &&
+         video_player && video_player->IsPlayerPlaying();
+}
 
-  LOG(INFO) << "Finalize AUL APP COM and VSS";
-  aul_app_com_leave(aul_app_com_connection_);
-  aul_app_com_connection_ = nullptr;
-  aul_extension_splash_screen_tv_reset();
+VideoSplashScreen::VideoSplashScreen() {
+#if TIZEN_VERSION_AT_LEAST(9, 0, 0)
+  video_player = std::make_unique<VideoSplashPlayer>();
+#else
+  video_player = std::make_unique<VideoSplashAmdPlayer>();
+#endif
 }
 
-// static
-void VideoSplashScreen::InitializeVSS() {
-  auto& app_data = ApplicationDataTV::GetInstance();
-  if (!app_data.video_splash_screen_info().HasVideoSplashScreenData())
-    return;
+VideoSplashScreen::~VideoSplashScreen() {
+  video_player.reset();
+}
 
-  if (aul_app_com_connection_)
+void VideoSplashScreen::Init() {
+  if (!video_player->Initialize())
     return;
-
-  if (!aul_extension_splash_screen_tv_event("ISVIDEO")) {
-    LOG(ERROR) << "Failed to send ISVIDEO to VSS";
+  if (!video_player->PreparePlayer())
     return;
-  }
 
-  std::string com_endpoint = kSplashScreenAulAppCom + app_data.app_id();
-  if (aul_app_com_create(com_endpoint.c_str(), nullptr, OnSplashScreenMessage,
-                         nullptr, &aul_app_com_connection_)) {
-    LOG(ERROR) << "Failed to initialize AUL APP COM";
-  } else {
-    LOG(ERROR) << "Initialized AUL APP COM with " << com_endpoint;
-  }
-}
-
-void VideoSplashScreen::BeforeHide() {
-  Hide();
+  auto video_src = GetVideoSrc();
+  if (!video_player->PlayerStart(video_src))
+    LOG(ERROR) << "VSS playing is failed";
+  else
+    LOG(INFO) << "VSS is now playing";
 }
 
 void VideoSplashScreen::Hide() {
-  if (was_hidden_)
-    return;
-
-  if (VideoSplashScreen::IsVSSPlaying()) {
-    auto hidden_reason = SplashScreen::GetHiddenReason();
-    const char* hide_reason = HideReasonToString(hidden_reason);
-    HideVSSPlayer(hide_reason);
-    was_hidden_ = true;
-  }
+  video_player->Hide();
 }
 
 wgt::parse::ReadyWhen VideoSplashScreen::GetReadyWhen() {
@@ -146,4 +73,36 @@ wgt::parse::ReadyWhen VideoSplashScreen::GetReadyWhen() {
   return app_data.video_splash_screen_info().ready_when();
 }
 
+std::string VideoSplashScreen::GetVideoSrc() {
+  auto default_orientation = wgt::parse::ScreenOrientation::AUTO;
+  auto orientation =
+      delegate_ ? delegate_->GetScreenOrientation() : default_orientation;
+
+  auto& app_data = ApplicationDataTV::GetInstance();
+  auto& vss_info = app_data.video_splash_screen_info();
+  auto video_src = vss_info.GetVideoSrc(orientation);
+  if (video_src.empty())
+    video_src = vss_info.GetVideoSrc(default_orientation);
+
+  if (video_src.empty())
+    return {};
+
+  auto backup_path =
+      base::FilePath("/opt/share/webappservice/videoSplashScreen/")
+          .Append(app_data.GetPackageID())
+          .Append(video_src);
+  if (base::PathExists(backup_path)) {
+    LOG(INFO) << "backup_path src : " << backup_path;
+    return backup_path.value();
+  }
+
+  auto video_absolute_path =
+      base::FilePath(app_data.application_path()).Append(video_src);
+  if (base::PathExists(video_absolute_path)) {
+    return video_absolute_path.value();
+  }
+
+  return {};
+}
+
 }  // namespace wrt
index 661419f..f74e9bf 100644 (file)
@@ -9,25 +9,25 @@
 
 #include "wrt/src/browser/splash_screen.h"
 #include "wrt/src/common/application_data.h"
+#include "wrt/src/common/splash_screen_delegate.h"
 
 namespace wrt {
 
 class VideoSplashScreen : public SplashScreen {
  public:
-  VideoSplashScreen() = default;
-  ~VideoSplashScreen();
+  static SplashScreen* Create();
+  static bool IsPlayerPlaying();
 
-  static void InitializeVSS();
-  static bool IsVSSPlaying();
-  static void FinalizeVSS();
+  VideoSplashScreen();
+  ~VideoSplashScreen() override;
 
  private:
-  void Init() override {}
-  void BeforeHide() override;
+  // SplashScreen
+  void Init() override;
   void Hide() override;
   wgt::parse::ReadyWhen GetReadyWhen() override;
 
-  bool was_hidden_ = false;
+  std::string GetVideoSrc();
 };
 
 }  // namespace wrt
index 5684d27..e6107c2 100644 (file)
@@ -4,7 +4,6 @@
 
 #include "wrt/src/browser/tv/wrt_native_window_tv.h"
 
-#include <aul-extension.h>
 #include <cursor_module.h>
 #include <display-rotator-api.h>
 #include <json/json.h>
@@ -1154,12 +1153,11 @@ void WRTNativeWindowTV::VisibilityChangedAsBackground() {
 
   SuspendMedia(true);
   DisableVisibilitySetting();
-  if (visibility_state_.empty() && !VideoSplashScreen::IsVSSPlaying())
+  if (visibility_state_.empty() && !VideoSplashScreen::IsPlayerPlaying())
     WidgetStateProvider::OnStatusChanged("behind");
 
   visibility_state_ = "hidden";
   OnVisibilityChange(false);
-  VideoSplashScreen::FinalizeVSS();
 }
 
 void WRTNativeWindowTV::VisibilityChangedAsForeground() {
index dd83f27..b8bdeb8 100644 (file)
@@ -506,6 +506,7 @@ WRTNativeWindow::WRTNativeWindow(const gin_helper::Dictionary& options,
   if (is_main_native_window_) {
     EnsurePlatformWindow();
     InitializePlatformEventListeners();
+    SplashScreen::AddObserver(this);
     // TODO: Find a way to avoid using elementary
     elm_app_name_set(ApplicationData::GetInstance().app_id().c_str());
   }
index c98f864..ccdfb28 100755 (executable)
@@ -214,12 +214,19 @@ class AddonInfo : public Wrapper<wgt::parse::AddonInfo> {
 class VideoSplashScreenInfo
     : public Wrapper<wgt::parse::VideoSplashScreenInfo> {
  public:
+  const std::string GetVideoSrc(
+      wgt::parse::ScreenOrientation orientation) const {
+    if (!impl_)
+      return nullptr;
+
+    auto& screen_data = impl_->launch_screen_data();
+    auto iter = screen_data.find(orientation);
+    if (iter != screen_data.end())
+      return iter->second.video;
+    return {};
+  }
   bool HasVideoSplashScreenData() const {
-#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
     if (!impl_ || impl_->launch_screen_data().empty())
-#else
-    if (!impl_ || impl_->screen_data().empty())
-#endif
       return false;
     return true;
   }
diff --git a/wrt/src/common/splash_screen_delegate.cc b/wrt/src/common/splash_screen_delegate.cc
new file mode 100644 (file)
index 0000000..629e970
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "wrt/src/common/splash_screen_delegate.h"
+
+#include "wrt/src/browser/basic_splash_screen.h"
+
+namespace wrt {
+
+SplashScreen* SplashScreenDelegate::CreateSplashScreen() {
+  auto& app_data = ApplicationData::GetInstance();
+  if (app_data.launch_screen_info().HasLaunchScreenData())
+    return BasicSplashScreen::Create();
+  else
+    return nullptr;
+}
+
+}  // namespace wrt
index 3accac3..b0f0405 100644 (file)
@@ -26,9 +26,8 @@ class SplashScreenDelegate {
     return wgt::parse::ScreenOrientation::AUTO;
   }
   virtual void SetSplashImage(Evas_Object* image, Evas_Object* background) {}
-  virtual bool IsVideoPlaying() { return false; }
   virtual std::string ConvertAliasPath(std::string& image_path) { return {}; }
-  virtual SplashScreen* CreateVideoSplashScreen() { return nullptr; }
+  virtual SplashScreen* CreateSplashScreen();
 };
 
 class SplashScreenWidgetDelegate : public views::WidgetDelegate {
index 45d4c55..0e576da 100644 (file)
@@ -26,6 +26,7 @@ const char* kLibCapiUiEflUtil = LIB_PATH "/libcapi-ui-efl-util.so.0";
 const char* kLibEflAssist = LIB_PATH "/libefl-assist.so.0";
 const char* kLibTvControl = LIB_PATH "/libtv-control.so.0";
 const char* kLibDeviced = LIB_PATH "/libdeviced.so.1";
+const char* kLibAulExtension = LIB_PATH "/libaul-extension.so.0";
 
 base::Lock worker_thread_lock;
 
@@ -208,4 +209,45 @@ ambient_mode_e device_power_get_ambient_mode(void) {
     return AMBIENT_MODE_OFF;
 }
 
+int aul_extension_splash_screen_tv_event(const char* event) {
+  typedef int (*func_sig)(const char*);
+  auto* func = (func_sig)GetFunction(kLibAulExtension, __FUNCTION__);
+  if (func)
+    return func(event);
+  else
+    return -1;
+}
+
+int aul_extension_splash_screen_tv_reset() {
+  typedef int (*func_sig)();
+  auto* func = (func_sig)GetFunction(kLibAulExtension, __FUNCTION__);
+  if (func)
+    return func();
+  else
+    return -1;
+}
+
+int aul_app_com_create(const char* endpoint,
+                       aul_app_com_permission_h permission,
+                       app_com_cb callback,
+                       void* user_data,
+                       aul_app_com_connection_h* connection) {
+  typedef int (*func_sig)(const char*, aul_app_com_permission_h, app_com_cb,
+                          void*, aul_app_com_connection_h*);
+  auto* func = (func_sig)GetFunction(kLibAulExtension, __FUNCTION__);
+  if (func)
+    return func(endpoint, permission, callback, user_data, connection);
+  else
+    return -1;
+}
+
+int aul_app_com_leave(aul_app_com_connection_h connection) {
+  typedef int (*func_sig)(aul_app_com_connection_h);
+  auto* func = (func_sig)GetFunction(kLibAulExtension, __FUNCTION__);
+  if (func)
+    return func(connection);
+  else
+    return -1;
+}
+
 }  // namespace wrt
index ef919e6..dc79b5a 100644 (file)
@@ -6,6 +6,7 @@
 #define COMMON_TV_WRT_LIB_WRAPPER_H_
 
 #include <Elementary.h>
+#include <bundle.h>
 
 namespace wrt {
 
@@ -85,6 +86,27 @@ int device_power_subscribe_state_changed_event(device_state_changed_cb cb,
 int device_power_unsubscribe_state_changed_event(device_state_changed_cb cb);
 ambient_mode_e device_power_get_ambient_mode(void);
 
+// aul-extension
+
+typedef void* aul_app_com_result_e;
+
+typedef int (*app_com_cb)(const char* endpoint,
+                          aul_app_com_result_e result,
+                          bundle* envelope,
+                          void* user_data);
+
+typedef void* aul_app_com_connection_h;
+typedef void* aul_app_com_permission_h;
+
+int aul_extension_splash_screen_tv_event(const char* event);
+int aul_extension_splash_screen_tv_reset();
+int aul_app_com_create(const char* endpoint,
+                       aul_app_com_permission_h permission,
+                       app_com_cb callback,
+                       void* user_data,
+                       aul_app_com_connection_h* connection);
+int aul_app_com_leave(aul_app_com_connection_h connection);
+
 }  // namespace wrt
 
 #endif  // COMMON_TV_WRT_LIB_WRAPPER_H_