diff options
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>(); |