diff options
Diffstat (limited to 'xbmc/video/ContextMenus.cpp')
-rw-r--r-- | xbmc/video/ContextMenus.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/xbmc/video/ContextMenus.cpp b/xbmc/video/ContextMenus.cpp new file mode 100644 index 0000000..c1f4c43 --- /dev/null +++ b/xbmc/video/ContextMenus.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2016-2018 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 "ContextMenus.h" + +#include "Autorun.h" +#include "GUIUserMessages.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "application/Application.h" +#include "application/ApplicationComponents.h" +#include "application/ApplicationPlayer.h" +#include "filesystem/Directory.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "playlists/PlayList.h" +#include "settings/MediaSettings.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "video/VideoUtils.h" +#include "video/dialogs/GUIDialogVideoInfo.h" +#include "video/windows/GUIWindowVideoBase.h" +#include "view/GUIViewState.h" + +#include <utility> + +namespace CONTEXTMENU +{ + +CVideoInfo::CVideoInfo(MediaType mediaType) + : CStaticContextMenuAction(19033), m_mediaType(std::move(mediaType)) +{ +} + +bool CVideoInfo::IsVisible(const CFileItem& item) const +{ + if (!item.HasVideoInfoTag()) + return false; + + if (item.IsPVRRecording()) + return false; // pvr recordings have its own implementation for this + + return item.GetVideoInfoTag()->m_type == m_mediaType; +} + +bool CVideoInfo::Execute(const std::shared_ptr<CFileItem>& item) const +{ + CGUIDialogVideoInfo::ShowFor(*item); + return true; +} + +bool CVideoRemoveResumePoint::IsVisible(const CFileItem& itemIn) const +{ + CFileItem item(itemIn.GetItemToPlay()); + if (item.IsDeleted()) // e.g. trashed pvr recording + return false; + + // Folders don't have a resume point + return !item.m_bIsFolder && VIDEO_UTILS::GetItemResumeInformation(item).isResumable; +} + +bool CVideoRemoveResumePoint::Execute(const std::shared_ptr<CFileItem>& item) const +{ + CVideoLibraryQueue::GetInstance().ResetResumePoint(item); + return true; +} + +bool CVideoMarkWatched::IsVisible(const CFileItem& item) const +{ + if (item.IsDeleted()) // e.g. trashed pvr recording + return false; + + if (item.m_bIsFolder && item.IsPlugin()) // we cannot manage plugin folder's watched state + return false; + + if (item.m_bIsFolder) // Only allow video db content, video and recording folders to be updated recursively + { + if (item.HasVideoInfoTag()) + return item.IsVideoDb(); + else if (item.GetProperty("IsVideoFolder").asBoolean()) + return true; + else + return !item.IsParentFolder() && URIUtils::IsPVRRecordingFileOrFolder(item.GetPath()); + } + else if (!item.HasVideoInfoTag()) + return false; + + return item.GetVideoInfoTag()->GetPlayCount() == 0; +} + +bool CVideoMarkWatched::Execute(const std::shared_ptr<CFileItem>& item) const +{ + CVideoLibraryQueue::GetInstance().MarkAsWatched(item, true); + return true; +} + +bool CVideoMarkUnWatched::IsVisible(const CFileItem& item) const +{ + if (item.IsDeleted()) // e.g. trashed pvr recording + return false; + + if (item.m_bIsFolder && item.IsPlugin()) // we cannot manage plugin folder's watched state + return false; + + if (item.m_bIsFolder) // Only allow video db content, video and recording folders to be updated recursively + { + if (item.HasVideoInfoTag()) + return item.IsVideoDb(); + else if (item.GetProperty("IsVideoFolder").asBoolean()) + return true; + else + return !item.IsParentFolder() && URIUtils::IsPVRRecordingFileOrFolder(item.GetPath()); + } + else if (!item.HasVideoInfoTag()) + return false; + + return item.GetVideoInfoTag()->GetPlayCount() > 0; +} + +bool CVideoMarkUnWatched::Execute(const std::shared_ptr<CFileItem>& item) const +{ + CVideoLibraryQueue::GetInstance().MarkAsWatched(item, false); + return true; +} + +bool CVideoBrowse::IsVisible(const CFileItem& item) const +{ + if (item.IsFileFolder(EFILEFOLDER_MASK_ONBROWSE)) + return false; // handled by CMediaWindow + + return item.m_bIsFolder && VIDEO_UTILS::IsItemPlayable(item); +} + +bool CVideoBrowse::Execute(const std::shared_ptr<CFileItem>& item) const +{ + int target = WINDOW_INVALID; + if (URIUtils::IsPVRRadioRecordingFileOrFolder(item->GetPath())) + target = WINDOW_RADIO_RECORDINGS; + else if (URIUtils::IsPVRTVRecordingFileOrFolder(item->GetPath())) + target = WINDOW_TV_RECORDINGS; + else + target = WINDOW_VIDEO_NAV; + + auto& windowMgr = CServiceBroker::GetGUI()->GetWindowManager(); + + if (target == windowMgr.GetActiveWindow()) + { + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, target, 0, GUI_MSG_UPDATE); + msg.SetStringParam(item->GetPath()); + windowMgr.SendMessage(msg); + } + else + { + windowMgr.ActivateWindow(target, {item->GetPath(), "return"}); + } + return true; +} + +std::string CVideoResume::GetLabel(const CFileItem& item) const +{ + return CGUIWindowVideoBase::GetResumeString(item.GetItemToPlay()); +} + +bool CVideoResume::IsVisible(const CFileItem& itemIn) const +{ + CFileItem item(itemIn.GetItemToPlay()); + if (item.IsDeleted()) // e.g. trashed pvr recording + return false; + + return VIDEO_UTILS::GetItemResumeInformation(item).isResumable; +} + +namespace +{ + +void AddRecordingsToPlayList(const std::shared_ptr<CFileItem>& item, CFileItemList& queuedItems) +{ + if (item->m_bIsFolder) + { + CFileItemList items; + XFILE::CDirectory::GetDirectory(item->GetPath(), items, "", XFILE::DIR_FLAG_DEFAULTS); + + const int watchedMode = CMediaSettings::GetInstance().GetWatchedMode("recordings"); + const bool unwatchedOnly = watchedMode == WatchedModeUnwatched; + const bool watchedOnly = watchedMode == WatchedModeWatched; + for (const auto& currItem : items) + { + if (currItem->HasVideoInfoTag() && + ((unwatchedOnly && currItem->GetVideoInfoTag()->GetPlayCount() > 0) || + (watchedOnly && currItem->GetVideoInfoTag()->GetPlayCount() <= 0))) + continue; + + AddRecordingsToPlayList(currItem, queuedItems); + } + } + else + { + queuedItems.Add(item); + } +} + +void AddRecordingsToPlayListAndSort(const std::shared_ptr<CFileItem>& item, + CFileItemList& queuedItems) +{ + queuedItems.SetPath(item->GetPath()); + AddRecordingsToPlayList(item, queuedItems); + + if (!queuedItems.IsEmpty()) + { + const int windowId = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(); + if (windowId == WINDOW_TV_RECORDINGS || windowId == WINDOW_RADIO_RECORDINGS) + { + std::unique_ptr<CGUIViewState> viewState(CGUIViewState::GetViewState(windowId, queuedItems)); + if (viewState) + queuedItems.Sort(viewState->GetSortMethod()); + } + } +} + +void PlayAndQueueRecordings(const std::shared_ptr<CFileItem>& item, int windowId) +{ + const std::shared_ptr<CFileItem> parentFolderItem = + std::make_shared<CFileItem>(URIUtils::GetParentPath(item->GetPath()), true); + + // add all items of given item's directory to a temporary playlist, start playback of given item + CFileItemList queuedItems; + AddRecordingsToPlayListAndSort(parentFolderItem, queuedItems); + + PLAYLIST::CPlayListPlayer& player = CServiceBroker::GetPlaylistPlayer(); + + player.ClearPlaylist(PLAYLIST::TYPE_VIDEO); + player.Reset(); + player.Add(PLAYLIST::TYPE_VIDEO, queuedItems); + + // figure out where to start playback + PLAYLIST::CPlayList& playList = player.GetPlaylist(PLAYLIST::TYPE_VIDEO); + int itemToPlay = 0; + + for (int i = 0; i < queuedItems.Size(); ++i) + { + if (item->IsSamePath(queuedItems.Get(i).get())) + { + itemToPlay = i; + break; + } + } + + if (player.IsShuffled(PLAYLIST::TYPE_VIDEO)) + { + playList.Swap(0, playList.FindOrder(itemToPlay)); + itemToPlay = 0; + } + + player.SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO); + player.Play(itemToPlay, ""); +} + +void SetPathAndPlay(CFileItem& item) +{ + if (!item.m_bIsFolder && item.IsVideoDb()) + { + 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? + { + g_application.PlayMedia(item, "", PLAYLIST::TYPE_VIDEO); + } + else + { + item.SetProperty("playlist_type_hint", PLAYLIST::TYPE_VIDEO); + VIDEO_UTILS::PlayItem(std::make_shared<CFileItem>(item)); + } +} + +} // unnamed namespace + +bool CVideoResume::Execute(const std::shared_ptr<CFileItem>& itemIn) const +{ + CFileItem item(itemIn->GetItemToPlay()); +#ifdef HAS_DVD_DRIVE + if (item.IsDVD() || item.IsCDDA()) + return MEDIA_DETECT::CAutorun::PlayDisc(item.GetPath(), true, false); +#endif + + item.SetStartOffset(STARTOFFSET_RESUME); + SetPathAndPlay(item); + return true; +}; + +std::string CVideoPlay::GetLabel(const CFileItem& itemIn) const +{ + CFileItem item(itemIn.GetItemToPlay()); + if (item.IsLiveTV()) + return g_localizeStrings.Get(19000); // Switch to channel + if (VIDEO_UTILS::GetItemResumeInformation(item).isResumable) + return g_localizeStrings.Get(12021); // Play from beginning + return g_localizeStrings.Get(208); // Play +} + +bool CVideoPlay::IsVisible(const CFileItem& item) const +{ + return VIDEO_UTILS::IsItemPlayable(item); +} + +bool CVideoPlay::Execute(const std::shared_ptr<CFileItem>& itemIn) const +{ + CFileItem item(itemIn->GetItemToPlay()); +#ifdef HAS_DVD_DRIVE + if (item.IsDVD() || item.IsCDDA()) + return MEDIA_DETECT::CAutorun::PlayDisc(item.GetPath(), true, true); +#endif + SetPathAndPlay(item); + return true; +}; + +namespace +{ +void SelectNextItem(int windowID) +{ + auto& windowMgr = CServiceBroker::GetGUI()->GetWindowManager(); + CGUIWindow* window = windowMgr.GetWindow(windowID); + if (window) + { + const int viewContainerID = window->GetViewContainerID(); + if (viewContainerID > 0) + { + CGUIMessage msg1(GUI_MSG_ITEM_SELECTED, windowID, viewContainerID); + windowMgr.SendMessage(msg1, windowID); + + CGUIMessage msg2(GUI_MSG_ITEM_SELECT, windowID, viewContainerID, msg1.GetParam1() + 1); + windowMgr.SendMessage(msg2, windowID); + } + } +} +} // unnamed namespace + +bool CVideoQueue::IsVisible(const CFileItem& item) const +{ + if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST) + return false; // Already queued + + if (!item.CanQueue()) + return false; + + return VIDEO_UTILS::IsItemPlayable(item); +} + +bool CVideoQueue::Execute(const std::shared_ptr<CFileItem>& item) const +{ + const int windowID = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(); + if (windowID == WINDOW_VIDEO_PLAYLIST) + return false; // Already queued + + VIDEO_UTILS::QueueItem(item, VIDEO_UTILS::QueuePosition::POSITION_END); + + // Set selection to next item in active window's view. + SelectNextItem(windowID); + + return true; +}; + +bool CVideoPlayNext::IsVisible(const CFileItem& item) const +{ + if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST) + return false; // Already queued + + if (!item.CanQueue()) + return false; + + return VIDEO_UTILS::IsItemPlayable(item); +} + +bool CVideoPlayNext::Execute(const std::shared_ptr<CFileItem>& item) const +{ + if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST) + return false; // Already queued + + VIDEO_UTILS::QueueItem(item, VIDEO_UTILS::QueuePosition::POSITION_BEGIN); + return true; +}; + +bool CVideoPlayAndQueue::IsVisible(const CFileItem& item) const +{ + const int windowId = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(); + if (windowId == WINDOW_VIDEO_PLAYLIST) + return false; // Already queued + + if ((windowId == WINDOW_TV_RECORDINGS || windowId == WINDOW_RADIO_RECORDINGS) && + item.IsUsablePVRRecording()) + return true; + + return false; //! @todo implement +} + +bool CVideoPlayAndQueue::Execute(const std::shared_ptr<CFileItem>& item) const +{ + const int windowId = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(); + if (windowId == WINDOW_VIDEO_PLAYLIST) + return false; // Already queued + + if ((windowId == WINDOW_TV_RECORDINGS || windowId == WINDOW_RADIO_RECORDINGS) && + item->IsUsablePVRRecording()) + { + // recursively add items located in the same folder as item to play list, starting with item + PlayAndQueueRecordings(item, windowId); + return true; + } + + return true; //! @todo implement +}; + +} |