diff options
author | ksooo <3226626+ksooo@users.noreply.github.com> | 2023-11-29 08:58:33 +0100 |
---|---|---|
committer | ksooo <3226626+ksooo@users.noreply.github.com> | 2023-12-07 19:07:45 +0100 |
commit | 565fe8a525d26be43ea082221f7a4472dbcf862a (patch) | |
tree | f0f55e07f4d90dd34b28734576d36afafbe323bf | |
parent | fbda2709c5a84870e2be2805a433253805410099 (diff) |
[video] Move play/select action handling for video versions to CVideo(Play|Select)ActionProcessor implementation, to gain consistent functionality across Kodi and to get rid of special handling for video versions playback scattered across the code base.
19 files changed, 432 insertions, 177 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po index 05e898b52d..bb3f6157e7 100644 --- a/addons/resource.language.en_gb/resources/strings.po +++ b/addons/resource.language.en_gb/resources/strings.po @@ -23868,10 +23868,10 @@ msgctxt "#40022" msgid "Manage {0:s}" msgstr "" -#. Play video version dialog title +#. Choose video version dialog title #: xbmc/video/dialogs/GUIDialogVideoVersion.cpp msgctxt "#40023" -msgid "Play {0:s}" +msgid "Choose {0:s}" msgstr "" #. Play default video version setting diff --git a/addons/skin.estuary/xml/DialogVideoVersion.xml b/addons/skin.estuary/xml/DialogVideoVersion.xml index 2c50812913..9a109ca028 100644 --- a/addons/skin.estuary/xml/DialogVideoVersion.xml +++ b/addons/skin.estuary/xml/DialogVideoVersion.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <window> <defaultcontrol always="true">200</defaultcontrol> - <onload condition="Window.IsActive(videoversionplay)">Control.SetFocus(50)</onload> + <onload condition="Window.IsActive(videoversionselect)">Control.SetFocus(50)</onload> <include>Animation_DialogPopupOpenClose</include> <controls> <include condition="Window.IsActive(videoversion)">DialogVideoVersionLayout</include> - <include condition="Window.IsActive(videoversionplay)">DialogVideoVersionPlayLayout</include> + <include condition="Window.IsActive(videoversionselect)">DialogVideoVersionSelectLayout</include> </controls> </window> diff --git a/addons/skin.estuary/xml/Includes_DialogVideoVersion.xml b/addons/skin.estuary/xml/Includes_DialogVideoVersion.xml index d6180c8f1b..4f7163c048 100644 --- a/addons/skin.estuary/xml/Includes_DialogVideoVersion.xml +++ b/addons/skin.estuary/xml/Includes_DialogVideoVersion.xml @@ -57,7 +57,7 @@ </control> </control> </include> - <include name="DialogVideoVersionPlayLayout"> + <include name="DialogVideoVersionSelectLayout"> <control type="group"> <centertop>50%</centertop> <centerleft>50%</centerleft> @@ -85,13 +85,13 @@ <param name="id" value="201" /> <param name="label" value="$LOCALIZE[40000]" /> <param name="usealttexture" value="Control.IsVisible(50)" /> - <param name="visible">Window.IsActive(videoversion)| Window.IsActive(videoversionplay) + Integer.IsGreater(Container(50).NumItems,0)</param> + <param name="visible">Window.IsActive(videoversion)| Window.IsActive(videoversionselect) + Integer.IsGreater(Container(50).NumItems,0)</param> </include> <include content="DialogToggleButton"> <param name="id" value="202" /> <param name="label" value="$LOCALIZE[31615]" /> <param name="usealttexture" value="Control.IsVisible(51)" /> - <param name="visible">Window.IsActive(videoversion) | Window.IsActive(videoversionplay) + Integer.IsGreater(Container(51).NumItems,0)</param> + <param name="visible">Window.IsActive(videoversion) | Window.IsActive(videoversionselect) + Integer.IsGreater(Container(51).NumItems,0)</param> </include> </control> <control type="image"> diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp index 555857849d..3104ce1be8 100644 --- a/xbmc/guilib/GUIWindowManager.cpp +++ b/xbmc/guilib/GUIWindowManager.cpp @@ -293,7 +293,7 @@ void CGUIWindowManager::CreateWindows() Add(new CGUIDialogOK); Add(new CGUIDialogVideoInfo); Add(new CGUIDialogVideoVersion(WINDOW_DIALOG_VIDEO_VERSION)); - Add(new CGUIDialogVideoVersion(WINDOW_DIALOG_VIDEO_VERSION_PLAY)); + Add(new CGUIDialogVideoVersion(WINDOW_DIALOG_VIDEO_VERSION_SELECT)); Add(new CGUIDialogTextViewer); Add(new CGUIWindowFullScreen); Add(new CGUIWindowVisualisation); @@ -335,7 +335,7 @@ bool CGUIWindowManager::DestroyWindows() DestroyWindow(WINDOW_DIALOG_MUSIC_INFO); DestroyWindow(WINDOW_DIALOG_VIDEO_INFO); DestroyWindow(WINDOW_DIALOG_VIDEO_VERSION); - DestroyWindow(WINDOW_DIALOG_VIDEO_VERSION_PLAY); + DestroyWindow(WINDOW_DIALOG_VIDEO_VERSION_SELECT); DestroyWindow(WINDOW_VIDEO_PLAYLIST); DestroyWindow(WINDOW_VIDEO_NAV); DestroyWindow(WINDOW_FILES); diff --git a/xbmc/guilib/WindowIDs.h b/xbmc/guilib/WindowIDs.h index 8b54b358d7..3f70bd8fc3 100644 --- a/xbmc/guilib/WindowIDs.h +++ b/xbmc/guilib/WindowIDs.h @@ -169,7 +169,7 @@ #define WINDOW_VISUALISATION 12006 #define WINDOW_SLIDESHOW 12007 #define WINDOW_DIALOG_COLOR_PICKER 12008 -#define WINDOW_DIALOG_VIDEO_VERSION_PLAY 12009 +#define WINDOW_DIALOG_VIDEO_VERSION_SELECT 12009 #define WINDOW_WEATHER 12600 #define WINDOW_SCREENSAVER 12900 #define WINDOW_DIALOG_VIDEO_OSD 12901 diff --git a/xbmc/input/WindowTranslator.cpp b/xbmc/input/WindowTranslator.cpp index cfcba73003..c1bbd68da7 100644 --- a/xbmc/input/WindowTranslator.cpp +++ b/xbmc/input/WindowTranslator.cpp @@ -120,7 +120,7 @@ const CWindowTranslator::WindowMapByName CWindowTranslator::WindowMappingByName {"okdialog", WINDOW_DIALOG_OK}, {"movieinformation", WINDOW_DIALOG_VIDEO_INFO}, {"videoversion", WINDOW_DIALOG_VIDEO_VERSION}, - {"videoversionplay", WINDOW_DIALOG_VIDEO_VERSION_PLAY}, + {"videoversionselect", WINDOW_DIALOG_VIDEO_VERSION_SELECT}, {"textviewer", WINDOW_DIALOG_TEXT_VIEWER}, {"fullscreenvideo", WINDOW_FULLSCREEN_VIDEO}, {"dialogcolorpicker", WINDOW_DIALOG_COLOR_PICKER}, diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp index a7ba3592d2..f1f4228f5d 100644 --- a/xbmc/listproviders/DirectoryProvider.cpp +++ b/xbmc/listproviders/DirectoryProvider.cpp @@ -37,7 +37,6 @@ #include "video/VideoInfoTag.h" #include "video/VideoThumbLoader.h" #include "video/VideoUtils.h" -#include "video/dialogs/GUIDialogVideoVersion.h" #include "video/guilib/VideoPlayActionProcessor.h" #include "video/guilib/VideoSelectActionProcessor.h" @@ -496,18 +495,7 @@ protected: bool OnPlaySelected() override { - //! @todo get rid of special handling for movie versions - if (m_item->GetVideoInfoTag()->m_type == MediaTypeMovie) - { - CGUIDialogVideoVersion::PlayVideoVersion( - m_item, - [](const std::shared_ptr<CFileItem>& item) { - ExecuteAction({"PlayMedia", *item.get(), "noresume"}); - }); - } - else - ExecuteAction({"PlayMedia", *m_item, "noresume"}); - + ExecuteAction({"PlayMedia", *m_item, "noresume"}); return true; } @@ -550,18 +538,7 @@ protected: bool OnPlaySelected() override { - //! @todo get rid of special handling for movie versions - if (m_item->GetVideoInfoTag()->m_type == MediaTypeMovie) - { - CGUIDialogVideoVersion::PlayVideoVersion( - m_item, - [](const std::shared_ptr<CFileItem>& item) { - ExecuteAction({"PlayMedia", *item.get(), "noresume"}); - }); - } - else - ExecuteAction({"PlayMedia", *m_item, "noresume"}); - + ExecuteAction({"PlayMedia", *m_item, "noresume"}); return true; } }; diff --git a/xbmc/video/ContextMenus.cpp b/xbmc/video/ContextMenus.cpp index 9a179d5020..ec7a1bbd3f 100644 --- a/xbmc/video/ContextMenus.cpp +++ b/xbmc/video/ContextMenus.cpp @@ -21,7 +21,7 @@ #include "video/VideoInfoTag.h" #include "video/VideoUtils.h" #include "video/dialogs/GUIDialogVideoInfo.h" -#include "video/dialogs/GUIDialogVideoVersion.h" +#include "video/guilib/VideoPlayActionProcessor.h" #include <utility> @@ -175,38 +175,69 @@ bool CVideoResume::IsVisible(const CFileItem& itemIn) const namespace { -void SetPathAndPlay(CFileItem& item, const std::string& player) +class CVideoPlayActionProcessor : public VIDEO::GUILIB::CVideoPlayActionProcessorBase { - if (!item.m_bIsFolder && item.IsVideoDb()) +public: + explicit CVideoPlayActionProcessor(const std::shared_ptr<CFileItem>& item, + const std::string& player) + : CVideoPlayActionProcessorBase(item), m_player(player) { - item.SetProperty("original_listitem_url", item.GetPath()); - item.SetPath(item.GetVideoInfoTag()->m_strFileNameAndPath); } - item.SetProperty("check_resume", false); - if (item.IsLiveTV()) // pvr tv or pvr radio? +protected: + bool OnResumeSelected() override { - g_application.PlayMedia(item, "", PLAYLIST::TYPE_VIDEO); + m_item->SetStartOffset(STARTOFFSET_RESUME); + Play(); + return true; } - else + + bool OnPlaySelected() override { - item.SetProperty("playlist_type_hint", PLAYLIST::TYPE_VIDEO); + Play(); + return true; + } + +private: + void Play() + { + m_item->SetProperty("playlist_type_hint", PLAYLIST::TYPE_VIDEO); + const ContentUtils::PlayMode mode{m_item->GetProperty("CheckAutoPlayNextItem").asBoolean() + ? ContentUtils::PlayMode::CHECK_AUTO_PLAY_NEXT_ITEM + : ContentUtils::PlayMode::PLAY_ONLY_THIS}; + VIDEO_UTILS::PlayItem(m_item, m_player, mode); + } + + const std::string m_player; +}; - const ContentUtils::PlayMode mode = item.GetProperty("CheckAutoPlayNextItem").asBoolean() - ? ContentUtils::PlayMode::CHECK_AUTO_PLAY_NEXT_ITEM - : ContentUtils::PlayMode::PLAY_ONLY_THIS; +void SetPathAndPlay(const std::shared_ptr<CFileItem>& item, const std::string& player, bool resume) +{ + item->SetProperty("check_resume", false); - //! @todo get rid of special handling for movie versions - if (item.GetStartOffset() != STARTOFFSET_RESUME && - item.GetVideoInfoTag()->m_type == MediaTypeMovie) + if (item->IsLiveTV()) // pvr tv or pvr radio? + { + g_application.PlayMedia(*item, "", PLAYLIST::TYPE_VIDEO); + } + else + { + if (!item->m_bIsFolder && item->IsVideoDb()) { - auto videoItem = std::make_shared<CFileItem>(item); - CGUIDialogVideoVersion::PlayVideoVersion( - videoItem, [player, mode](const std::shared_ptr<CFileItem>& item) - { VIDEO_UTILS::PlayItem(item, player, mode); }); + item->SetProperty("original_listitem_url", item->GetPath()); + item->SetPath(item->GetVideoInfoTag()->m_strFileNameAndPath); } + + // play the given/default video version, if multiple versions are available + item->SetProperty("prohibit_choose_video_version", true); + + CVideoPlayActionProcessor proc{item, player}; + if (resume && (item->GetStartOffset() == STARTOFFSET_RESUME || + VIDEO_UTILS::GetItemResumeInformation(*item).isResumable)) + proc.Process(VIDEO::GUILIB::PLAY_ACTION_RESUME); else - VIDEO_UTILS::PlayItem(std::make_shared<CFileItem>(item), player, mode); + proc.Process(VIDEO::GUILIB::PLAY_ACTION_PLAY_FROM_BEGINNING); + + item->ClearProperty("prohibit_choose_video_version"); } } @@ -230,14 +261,14 @@ std::vector<std::string> GetPlayers(const CPlayerCoreFactory& playerCoreFactory, bool CVideoResume::Execute(const std::shared_ptr<CFileItem>& itemIn) const { - CFileItem item(itemIn->GetItemToPlay()); + const auto item{std::make_shared<CFileItem>(itemIn->GetItemToPlay())}; #ifdef HAS_OPTICAL_DRIVE - if (item.IsDVD() || item.IsCDDA()) - return MEDIA_DETECT::CAutorun::PlayDisc(item.GetPath(), true, false); + if (item->IsDVD() || item->IsCDDA()) + return MEDIA_DETECT::CAutorun::PlayDisc(item->GetPath(), true, false); #endif - item.SetStartOffset(STARTOFFSET_RESUME); - SetPathAndPlay(item, ""); + item->SetStartOffset(STARTOFFSET_RESUME); + SetPathAndPlay(item, "", true); return true; }; @@ -258,12 +289,12 @@ bool CVideoPlay::IsVisible(const CFileItem& item) const bool CVideoPlay::Execute(const std::shared_ptr<CFileItem>& itemIn) const { - CFileItem item(itemIn->GetItemToPlay()); + const auto item{std::make_shared<CFileItem>(itemIn->GetItemToPlay())}; #ifdef HAS_OPTICAL_DRIVE - if (item.IsDVD() || item.IsCDDA()) - return MEDIA_DETECT::CAutorun::PlayDisc(item.GetPath(), true, true); + if (item->IsDVD() || item->IsCDDA()) + return MEDIA_DETECT::CAutorun::PlayDisc(item->GetPath(), true, true); #endif - SetPathAndPlay(item, ""); + SetPathAndPlay(item, "", false); return true; }; @@ -275,14 +306,14 @@ bool CVideoPlayUsing::IsVisible(const CFileItem& item) const bool CVideoPlayUsing::Execute(const std::shared_ptr<CFileItem>& itemIn) const { - CFileItem item{itemIn->GetItemToPlay()}; + const auto item{std::make_shared<CFileItem>(itemIn->GetItemToPlay())}; const CPlayerCoreFactory& playerCoreFactory{CServiceBroker::GetPlayerCoreFactory()}; - const std::vector<std::string> players{GetPlayers(playerCoreFactory, item)}; + const std::vector<std::string> players{GetPlayers(playerCoreFactory, *item)}; const std::string player{playerCoreFactory.SelectPlayerDialog(players)}; if (!player.empty()) { - SetPathAndPlay(item, player); + SetPathAndPlay(item, player, false); return true; } return false; diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp index e1e781b9b7..08e7a1579f 100644 --- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp @@ -741,17 +741,7 @@ private: const ContentUtils::PlayMode mode{m_item->GetProperty("CheckAutoPlayNextItem").asBoolean() ? ContentUtils::PlayMode::CHECK_AUTO_PLAY_NEXT_ITEM : ContentUtils::PlayMode::PLAY_ONLY_THIS}; - - //! @todo get rid of special handling for movie versions - if (m_item->GetStartOffset() != STARTOFFSET_RESUME && - m_item->GetVideoInfoTag()->m_type == MediaTypeMovie) - { - CGUIDialogVideoVersion::PlayVideoVersion(m_item, - [mode](const std::shared_ptr<CFileItem>& item) - { VIDEO_UTILS::PlayItem(item, "", mode); }); - } - else - VIDEO_UTILS::PlayItem(m_item, "", mode); + VIDEO_UTILS::PlayItem(m_item, "", mode); } }; } // unnamed namespace diff --git a/xbmc/video/dialogs/GUIDialogVideoVersion.cpp b/xbmc/video/dialogs/GUIDialogVideoVersion.cpp index 94e1c45eeb..a8f380ab59 100644 --- a/xbmc/video/dialogs/GUIDialogVideoVersion.cpp +++ b/xbmc/video/dialogs/GUIDialogVideoVersion.cpp @@ -11,16 +11,13 @@ #include "FileItem.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" -#include "Util.h" -#include "application/Application.h" +#include "URL.h" #include "cores/VideoPlayer/DVDFileInfo.h" #include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogFileBrowser.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogSelect.h" #include "dialogs/GUIDialogYesNo.h" -#include "filesystem/Directory.h" -#include "filesystem/VideoDatabaseDirectory.h" #include "guilib/GUIComponent.h" #include "guilib/GUIImage.h" #include "guilib/GUIKeyboardFactory.h" @@ -28,29 +25,24 @@ #include "guilib/GUIWindowManager.h" #include "guilib/LocalizeStrings.h" #include "input/Key.h" -#include "profiles/ProfileManager.h" -#include "settings/AdvancedSettings.h" +#include "playlists/PlayListTypes.h" #include "settings/MediaSourceSettings.h" -#include "settings/SettingUtils.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "settings/lib/Setting.h" #include "storage/MediaManager.h" -#include "utils/ExecString.h" #include "utils/FileExtensionProvider.h" #include "utils/SortUtils.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "utils/Variant.h" #include "utils/log.h" -#include "video/VideoDbUrl.h" #include "video/VideoInfoTag.h" -#include "video/VideoItemArtworkHandler.h" #include "video/VideoThumbLoader.h" +#include "video/VideoUtils.h" #include "video/dialogs/GUIDialogVideoInfo.h" +#include "video/guilib/VideoPlayActionProcessor.h" #include <algorithm> -#include <iterator> #include <string> static constexpr unsigned int CONTROL_LABEL_MODE = 1; @@ -90,6 +82,12 @@ bool CGUIDialogVideoVersion::OnMessage(CGUIMessage& message) { switch (message.GetMessage()) { + case GUI_MSG_WINDOW_INIT: + { + m_cancelled = false; + break; + } + case GUI_MSG_WINDOW_DEINIT: { ClearVideoVersionList(); @@ -129,7 +127,7 @@ bool CGUIDialogVideoVersion::OnMessage(CGUIMessage& message) if (m_mode == Mode::MANAGE) SET_CONTROL_FOCUS(CONTROL_BUTTON_PLAY, 0); else - Play(); + CloseAll(); } } else if (control == CONTROL_LIST_EXTRAS_VERSION) @@ -154,7 +152,7 @@ bool CGUIDialogVideoVersion::OnMessage(CGUIMessage& message) if (m_mode == Mode::MANAGE) SET_CONTROL_FOCUS(CONTROL_BUTTON_PLAY, 0); else - Play(); + CloseAll(); } } else if (control == CONTROL_BUTTON_PLAY) @@ -193,10 +191,16 @@ bool CGUIDialogVideoVersion::OnMessage(CGUIMessage& message) return CGUIDialog::OnMessage(message); } +bool CGUIDialogVideoVersion::OnBack(int actionID) +{ + m_cancelled = true; + return CGUIDialog::OnBack(actionID); +} + void CGUIDialogVideoVersion::OnInitWindow() { // set working mode - SET_CONTROL_LABEL(CONTROL_LABEL_MODE, m_mode == Mode::MANAGE ? "manage" : "play"); + SET_CONTROL_LABEL(CONTROL_LABEL_MODE, m_mode == Mode::MANAGE ? "manage" : "choose"); // set window title std::string title = m_videoItem->GetVideoInfoTag()->GetTitle(); @@ -312,7 +316,7 @@ void CGUIDialogVideoVersion::SetVideoItem(const std::shared_ptr<CFileItem>& item loader.LoadItem(item.get()); } -void CGUIDialogVideoVersion::Play() +void CGUIDialogVideoVersion::CloseAll() { // close our dialog Close(true); @@ -323,15 +327,51 @@ void CGUIDialogVideoVersion::Play() WINDOW_DIALOG_VIDEO_INFO); if (dialog) dialog->Close(true); +} - // set the selected video version as default temporarily - SetDefaultVideoVersion(*m_selectedVideoVersion.get()); +namespace +{ +class CVideoPlayActionProcessor : public VIDEO::GUILIB::CVideoPlayActionProcessorBase +{ +public: + explicit CVideoPlayActionProcessor(const std::shared_ptr<CFileItem>& item, + const std::shared_ptr<CFileItem>& videoVersion) + : CVideoPlayActionProcessorBase(item, videoVersion) + { + } + +protected: + bool OnResumeSelected() override + { + m_item->SetStartOffset(STARTOFFSET_RESUME); + Play(); + return true; + } + + bool OnPlaySelected() override + { + Play(); + return true; + } + +private: + void Play() + { + m_item->SetProperty("playlist_type_hint", PLAYLIST::TYPE_VIDEO); + const ContentUtils::PlayMode mode{m_item->GetProperty("CheckAutoPlayNextItem").asBoolean() + ? ContentUtils::PlayMode::CHECK_AUTO_PLAY_NEXT_ITEM + : ContentUtils::PlayMode::PLAY_ONLY_THIS}; + VIDEO_UTILS::PlayItem(m_item, "", mode); + } +}; +} // unnamed namespace - // play the video item - m_playCallback(m_videoItem); +void CGUIDialogVideoVersion::Play() +{ + CloseAll(); - // restore the default video version - SetDefaultVideoVersion(*m_defaultVideoVersion.get()); + CVideoPlayActionProcessor proc{m_videoItem, m_selectedVideoVersion}; + proc.Process(); } void CGUIDialogVideoVersion::Remove() @@ -599,79 +639,53 @@ void CGUIDialogVideoVersion::SetSelectedVideoVersion(const std::shared_ptr<CFile m_selectedVideoVersion = std::make_unique<CFileItem>(*version); } -void CGUIDialogVideoVersion::SetPlayCallback(VideoVersionPlayCallback callback) -{ - m_playCallback = callback; -} - -void CGUIDialogVideoVersion::PlayVideoItem(const std::shared_ptr<CFileItem>& item) -{ - CGUIMessage msg(GUI_MSG_EXECUTE, 0, 0); - msg.SetStringParam(CExecString("PlayMedia", *item.get(), "noresume").GetExecString()); - CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); -} - void CGUIDialogVideoVersion::ManageVideoVersion(const std::shared_ptr<CFileItem>& item) { CGUIDialogVideoVersion* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogVideoVersion>( WINDOW_DIALOG_VIDEO_VERSION); if (!dialog) + { + CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_VIDEO_VERSION instance!"); return; + } dialog->SetVideoItem(item); dialog->SetMode(Mode::MANAGE); - dialog->SetPlayCallback(PlayVideoItem); dialog->Open(); } -void CGUIDialogVideoVersion::PlayVideoVersion(const std::shared_ptr<CFileItem>& item, - VideoVersionPlayCallback callback) +CGUIDialogVideoVersion::VersionSelectResult CGUIDialogVideoVersion::ChooseVideoVersion( + const std::shared_ptr<CFileItem>& item) { - // play the specified video version - if (item->GetVideoInfoTag()->m_idVideoVersion > 0) - { - callback(item); - return; - } - - // play the default video version - if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( - CSettings::SETTING_VIDEOPLAYER_PLAYDEFAULTVERSION)) + if (!item->HasVideoInfoTag()) { - auto temp = item; - - // play a temporary copy of the item if it is video version folder - if (item->GetVideoInfoTag()->m_idVideoVersion == VIDEO_VERSION_ID_ALL && - CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( - CSettings::SETTING_VIDEOLIBRARY_SHOWVIDEOVERSIONSASFOLDER)) - { - temp = std::make_shared<CFileItem>(*item); - temp->m_bIsFolder = false; - } - - callback(temp); - return; + CLog::LogF(LOGWARNING, "Item is not a video. path={}", item->GetPath()); + return {true, {}}; } - // play the video item directly - if (!item->GetVideoInfoTag()->m_hasVideoVersions) + if (!item->HasVideoVersions()) { - callback(item); - return; + CLog::LogF(LOGWARNING, "Item has no video versions. path={}", item->GetPath()); + return {true, {}}; } - // prompt to play selected video version - CGUIDialogVideoVersion* dialog = + // prompt to select a video version + CGUIDialogVideoVersion* dialog{ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogVideoVersion>( - WINDOW_DIALOG_VIDEO_VERSION_PLAY); + WINDOW_DIALOG_VIDEO_VERSION_SELECT)}; if (!dialog) - return; + { + CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_VIDEO_VERSION_SELECT instance!"); + return {true, {}}; + } dialog->SetVideoItem(item); - dialog->SetMode(Mode::PLAY); - dialog->SetPlayCallback(PlayVideoItem); + dialog->SetMode(Mode::CHOOSE); dialog->Open(); + + // get the selected video version from dialog if not cancelled + return {dialog->m_cancelled, dialog->m_selectedVideoVersion}; } int CGUIDialogVideoVersion::ManageVideoVersionContextMenu(const std::shared_ptr<CFileItem>& version) diff --git a/xbmc/video/dialogs/GUIDialogVideoVersion.h b/xbmc/video/dialogs/GUIDialogVideoVersion.h index ba547edd83..b408f3c782 100644 --- a/xbmc/video/dialogs/GUIDialogVideoVersion.h +++ b/xbmc/video/dialogs/GUIDialogVideoVersion.h @@ -25,11 +25,12 @@ public: CGUIDialogVideoVersion(int id); ~CGUIDialogVideoVersion(void) override; bool OnMessage(CGUIMessage& message) override; + bool OnBack(int actionID) override; enum class Mode { MANAGE, - PLAY, + CHOOSE, }; void SetMode(Mode mode) { m_mode = mode; } void SetVideoItem(const std::shared_ptr<CFileItem>& item); @@ -39,17 +40,18 @@ public: static bool ProcessVideoVersion(VideoDbContentType itemType, int dbId); static int SelectVideoVersion(const std::shared_ptr<CFileItem>& item); static void ManageVideoVersion(const std::shared_ptr<CFileItem>& item); - static void PlayVideoItem(const std::shared_ptr<CFileItem>& item); static std::string GenerateExtrasVideoVersion(const std::string& extrasRoot, const std::string& extrasPath); static std::string GenerateExtrasVideoVersion(const std::string& extrasPath); - - using VideoVersionPlayCallback = std::function<void(const std::shared_ptr<CFileItem>& item)>; - static void PlayVideoVersion(const std::shared_ptr<CFileItem>& item, - VideoVersionPlayCallback play); - static int ManageVideoVersionContextMenu(const std::shared_ptr<CFileItem>& version); + struct VersionSelectResult + { + bool cancelled{false}; + std::shared_ptr<CFileItem> selected; + }; + static VersionSelectResult ChooseVideoVersion(const std::shared_ptr<CFileItem>& item); + protected: void OnInitWindow() override; @@ -58,7 +60,6 @@ private: void SetSelectedVideoVersion(const std::shared_ptr<CFileItem>& version); void ClearVideoVersionList(); void RefreshVideoVersionList(); - void SetPlayCallback(VideoVersionPlayCallback callback); void AddVideoVersion(bool primary); void Play(); void AddVersion(); @@ -67,15 +68,14 @@ private: void SetDefault(); void Remove(); void ChooseArt(); - - VideoVersionPlayCallback m_playCallback; + void CloseAll(); std::shared_ptr<CFileItem> m_videoItem; Mode m_mode{Mode::MANAGE}; - + bool m_cancelled{false}; CVideoDatabase m_database; std::unique_ptr<CFileItemList> m_primaryVideoVersionList; std::unique_ptr<CFileItemList> m_extrasVideoVersionList; std::unique_ptr<CFileItem> m_defaultVideoVersion; - std::unique_ptr<CFileItem> m_selectedVideoVersion; + std::shared_ptr<CFileItem> m_selectedVideoVersion; }; diff --git a/xbmc/video/guilib/CMakeLists.txt b/xbmc/video/guilib/CMakeLists.txt index b0a93d5234..c5226897c4 100644 --- a/xbmc/video/guilib/CMakeLists.txt +++ b/xbmc/video/guilib/CMakeLists.txt @@ -1,9 +1,11 @@ set(SOURCES VideoPlayActionProcessor.cpp - VideoSelectActionProcessor.cpp) + VideoSelectActionProcessor.cpp + VideoActionProcessorHelper.cpp) set(HEADERS VideoPlayAction.h VideoPlayActionProcessor.h VideoSelectAction.h - VideoSelectActionProcessor.h) + VideoSelectActionProcessor.h + VideoActionProcessorHelper.h) core_add_library(video_guilib) diff --git a/xbmc/video/guilib/VideoActionProcessorHelper.cpp b/xbmc/video/guilib/VideoActionProcessorHelper.cpp new file mode 100644 index 0000000000..10f7d3f936 --- /dev/null +++ b/xbmc/video/guilib/VideoActionProcessorHelper.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "VideoActionProcessorHelper.h" + +#include "FileItem.h" +#include "GUIUserMessages.h" +#include "ServiceBroker.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "settings/lib/Setting.h" +#include "utils/log.h" +#include "video/VideoDatabase.h" +#include "video/dialogs/GUIDialogVideoVersion.h" + +using namespace VIDEO::GUILIB; + +CVideoActionProcessorHelper::~CVideoActionProcessorHelper() +{ + RestoreDefaultVideoVersion(); +} + +void CVideoActionProcessorHelper::SetDefaultVideoVersion() +{ + RestoreDefaultVideoVersion(); + + //! @todo this hack must go away! Playback currently only works if we persist the + //! movie version to play in the video database temporarily, until playback was started. + CVideoDatabase db; + if (!db.Open()) + { + CLog::LogF(LOGERROR, "Unable to open video database!"); + return; + } + + const VideoDbContentType itemType{m_item->GetVideoContentType()}; + const int dbId{m_item->GetVideoInfoTag()->m_iDbId}; + + CFileItem defaultVideoVersion; + db.GetDefaultVideoVersion(itemType, dbId, defaultVideoVersion); + m_defaultVideoVersionFileId = defaultVideoVersion.GetVideoInfoTag()->m_iDbId; + m_defaultVideoVersionDynPath = defaultVideoVersion.GetDynPath(); + + db.SetDefaultVideoVersion(itemType, dbId, m_videoVersion->GetVideoInfoTag()->m_iDbId); + + m_item->SetDynPath(m_videoVersion->GetDynPath()); + db.GetDetailsByTypeAndId(*m_item, itemType, dbId); + + // notify all windows to update the file item + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, GUI_MSG_FLAG_FORCE_UPDATE, m_item); + CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); +} + +void CVideoActionProcessorHelper::RestoreDefaultVideoVersion() +{ + //! @todo this hack must go away! + if (m_restoreFolderFlag) + { + m_restoreFolderFlag = false; + m_item->m_bIsFolder = true; + } + + if (m_defaultVideoVersionFileId == -1) + return; + + //! @todo this hack must go away! Playback currently only works if we persist the + //! movie version to play in the video database temporarily, until playback was started. + CVideoDatabase db; + if (!db.Open()) + { + CLog::LogF(LOGERROR, "Unable to open video database!"); + return; + } + + const VideoDbContentType itemType{m_item->GetVideoContentType()}; + const int dbId{m_item->GetVideoInfoTag()->m_iDbId}; + + db.SetDefaultVideoVersion(itemType, dbId, m_defaultVideoVersionFileId); + + m_item->SetDynPath(m_defaultVideoVersionDynPath); + db.GetDetailsByTypeAndId(*m_item, itemType, dbId); + + m_defaultVideoVersionFileId = -1; + m_defaultVideoVersionDynPath.clear(); + + // notify all windows to update the file item + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, GUI_MSG_FLAG_FORCE_UPDATE, m_item); + CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg); +} + +std::shared_ptr<CFileItem> CVideoActionProcessorHelper::ChooseVideoVersion() +{ + if (!m_videoVersion && m_item->HasVideoVersions()) + { + // select the specified video version + if (m_item->GetVideoInfoTag()->m_idVideoVersion > 0) + m_videoVersion = m_item; + + const auto settings{CServiceBroker::GetSettingsComponent()->GetSettings()}; + + if (!m_videoVersion) + { + //! @todo get rid of this hack to patch away item's folder flag if it is video version + //! folder + if (m_item->GetVideoInfoTag()->m_idVideoVersion == VIDEO_VERSION_ID_ALL && + settings->GetBool(CSettings::SETTING_VIDEOLIBRARY_SHOWVIDEOVERSIONSASFOLDER)) + { + m_item->m_bIsFolder = false; + m_restoreFolderFlag = true; + } + } + + if (!m_videoVersion) + { + // select the default video version + if (settings->GetBool(CSettings::SETTING_VIDEOPLAYER_PLAYDEFAULTVERSION)) + { + CVideoDatabase db; + if (!db.Open()) + { + CLog::LogF(LOGERROR, "Unable to open video database!"); + } + else + { + CFileItem defaultVersion; + db.GetDefaultVideoVersion(m_item->GetVideoContentType(), + m_item->GetVideoInfoTag()->m_iDbId, defaultVersion); + if (!defaultVersion.HasVideoInfoTag() || defaultVersion.GetVideoInfoTag()->IsEmpty()) + CLog::LogF(LOGERROR, "Unable to get default video version from video database!"); + else + m_videoVersion = std::make_shared<const CFileItem>(defaultVersion); + } + } + } + + if (!m_videoVersion && !m_item->GetProperty("prohibit_choose_video_version").asBoolean(false)) + { + const auto result{CGUIDialogVideoVersion::ChooseVideoVersion(m_item)}; + if (result.cancelled) + return {}; + else + m_videoVersion = result.selected; + } + } + + if (m_videoVersion) + SetDefaultVideoVersion(); + + return m_item; +} diff --git a/xbmc/video/guilib/VideoActionProcessorHelper.h b/xbmc/video/guilib/VideoActionProcessorHelper.h new file mode 100644 index 0000000000..0238d70953 --- /dev/null +++ b/xbmc/video/guilib/VideoActionProcessorHelper.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +class CFileItem; + +namespace VIDEO +{ +namespace GUILIB +{ +class CVideoActionProcessorHelper +{ +public: + CVideoActionProcessorHelper(const std::shared_ptr<CFileItem>& item, + const std::shared_ptr<const CFileItem>& videoVersion) + : m_item{item}, m_videoVersion{videoVersion} + { + } + virtual ~CVideoActionProcessorHelper(); + + std::shared_ptr<CFileItem> ChooseVideoVersion(); + +private: + CVideoActionProcessorHelper() = delete; + void SetDefaultVideoVersion(); + void RestoreDefaultVideoVersion(); + + std::shared_ptr<CFileItem> m_item; + std::shared_ptr<const CFileItem> m_videoVersion; + int m_defaultVideoVersionFileId{-1}; + std::string m_defaultVideoVersionDynPath; + bool m_restoreFolderFlag{false}; +}; +} // namespace GUILIB +} // namespace VIDEO diff --git a/xbmc/video/guilib/VideoPlayActionProcessor.cpp b/xbmc/video/guilib/VideoPlayActionProcessor.cpp index 0c01f2caa4..123bdb1985 100644 --- a/xbmc/video/guilib/VideoPlayActionProcessor.cpp +++ b/xbmc/video/guilib/VideoPlayActionProcessor.cpp @@ -8,12 +8,15 @@ #include "VideoPlayActionProcessor.h" +#include "FileItem.h" #include "ServiceBroker.h" #include "dialogs/GUIDialogContextMenu.h" #include "guilib/LocalizeStrings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" +#include "utils/Variant.h" #include "video/VideoUtils.h" +#include "video/guilib/VideoActionProcessorHelper.h" using namespace VIDEO::GUILIB; @@ -28,11 +31,27 @@ bool CVideoPlayActionProcessorBase::Process() return Process(GetDefaultPlayAction()); } -bool CVideoPlayActionProcessorBase::Process(PlayAction PlayAction) +bool CVideoPlayActionProcessorBase::Process(PlayAction playAction) { m_userCancelled = false; - switch (PlayAction) + CVideoActionProcessorHelper procHelper{m_item, m_videoVersion}; + + if (!m_versionChecked && + (playAction == PLAY_ACTION_PLAY_FROM_BEGINNING || playAction == PLAY_ACTION_PLAY_OR_RESUME)) + { + m_versionChecked = true; + const auto videoVersion{procHelper.ChooseVideoVersion()}; + if (videoVersion) + m_item = videoVersion; + else + { + m_userCancelled = true; + return true; // User cancelled the select menu. We're done. + } + } + + switch (playAction) { case PLAY_ACTION_PLAY_OR_RESUME: { diff --git a/xbmc/video/guilib/VideoPlayActionProcessor.h b/xbmc/video/guilib/VideoPlayActionProcessor.h index d3f447b98b..25753bc6d0 100644 --- a/xbmc/video/guilib/VideoPlayActionProcessor.h +++ b/xbmc/video/guilib/VideoPlayActionProcessor.h @@ -22,6 +22,11 @@ class CVideoPlayActionProcessorBase { public: explicit CVideoPlayActionProcessorBase(const std::shared_ptr<CFileItem>& item) : m_item(item) {} + CVideoPlayActionProcessorBase(const std::shared_ptr<CFileItem>& item, + const std::shared_ptr<const CFileItem>& videoVersion) + : m_item{item}, m_videoVersion{videoVersion} + { + } virtual ~CVideoPlayActionProcessorBase() = default; static PlayAction GetDefaultPlayAction(); @@ -41,6 +46,9 @@ protected: private: CVideoPlayActionProcessorBase() = delete; PlayAction ChoosePlayOrResume(); + + bool m_versionChecked{false}; + const std::shared_ptr<const CFileItem> m_videoVersion; }; } // namespace GUILIB } // namespace VIDEO diff --git a/xbmc/video/guilib/VideoSelectActionProcessor.cpp b/xbmc/video/guilib/VideoSelectActionProcessor.cpp index dfb6e2eabe..6ff489c580 100644 --- a/xbmc/video/guilib/VideoSelectActionProcessor.cpp +++ b/xbmc/video/guilib/VideoSelectActionProcessor.cpp @@ -19,8 +19,10 @@ #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "utils/StringUtils.h" +#include "utils/Variant.h" #include "video/VideoInfoTag.h" #include "video/VideoUtils.h" +#include "video/guilib/VideoActionProcessorHelper.h" using namespace VIDEO::GUILIB; @@ -37,6 +39,19 @@ bool CVideoSelectActionProcessorBase::Process() bool CVideoSelectActionProcessorBase::Process(SelectAction selectAction) { + CVideoActionProcessorHelper procHelper{m_item, m_videoVersion}; + + if (!m_versionChecked && + (selectAction == SELECT_ACTION_PLAY || selectAction == SELECT_ACTION_PLAY_OR_RESUME)) + { + m_versionChecked = true; + const auto videoVersion{procHelper.ChooseVideoVersion()}; + if (videoVersion) + m_item = videoVersion; + else + return true; // User cancelled the select menu. We're done. + } + switch (selectAction) { case SELECT_ACTION_CHOOSE: diff --git a/xbmc/video/guilib/VideoSelectActionProcessor.h b/xbmc/video/guilib/VideoSelectActionProcessor.h index 52d01b0846..a154921166 100644 --- a/xbmc/video/guilib/VideoSelectActionProcessor.h +++ b/xbmc/video/guilib/VideoSelectActionProcessor.h @@ -22,6 +22,11 @@ class CVideoSelectActionProcessorBase { public: explicit CVideoSelectActionProcessorBase(const std::shared_ptr<CFileItem>& item) : m_item(item) {} + CVideoSelectActionProcessorBase(const std::shared_ptr<CFileItem>& item, + const std::shared_ptr<const CFileItem>& videoVersion) + : m_item{item}, m_videoVersion{videoVersion} + { + } virtual ~CVideoSelectActionProcessorBase() = default; static SelectAction GetDefaultSelectAction(); @@ -45,6 +50,9 @@ private: CVideoSelectActionProcessorBase() = delete; SelectAction ChooseVideoItemSelectAction() const; unsigned int ChooseStackItemPartNumber() const; + + bool m_versionChecked{false}; + const std::shared_ptr<const CFileItem> m_videoVersion; }; } // namespace GUILIB } // namespace VIDEO diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index 3aef9de39f..7e7ee38705 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -57,7 +57,6 @@ #include "video/VideoLibraryQueue.h" #include "video/VideoUtils.h" #include "video/dialogs/GUIDialogVideoInfo.h" -#include "video/dialogs/GUIDialogVideoVersion.h" #include "video/guilib/VideoPlayActionProcessor.h" #include "video/guilib/VideoSelectActionProcessor.h" #include "view/GUIViewState.h" @@ -978,16 +977,7 @@ bool CGUIWindowVideoBase::OnPlayMedia(int iItem, const std::string &player) if (m_thumbLoader.IsLoading()) m_thumbLoader.StopAsync(); - //! @todo get rid of special handling for movie versions - if (itemCopy->GetVideoInfoTag()->m_type == MediaTypeMovie || - itemCopy->GetVideoInfoTag()->m_type == MediaTypeVideoVersion) - { - CGUIDialogVideoVersion::PlayVideoVersion( - itemCopy, [player](const std::shared_ptr<CFileItem>& item) - { CServiceBroker::GetPlaylistPlayer().Play(item, player); }); - } - else - CServiceBroker::GetPlaylistPlayer().Play(itemCopy, player); + CServiceBroker::GetPlaylistPlayer().Play(itemCopy, player); const auto& components = CServiceBroker::GetAppComponents(); const auto appPlayer = components.GetComponent<CApplicationPlayer>(); |