diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/pvr/windows/GUIWindowPVRRecordings.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/pvr/windows/GUIWindowPVRRecordings.cpp')
-rw-r--r-- | xbmc/pvr/windows/GUIWindowPVRRecordings.cpp | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp new file mode 100644 index 0000000..d127217 --- /dev/null +++ b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2012-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 "GUIWindowPVRRecordings.h" + +#include "GUIInfoManager.h" +#include "ServiceBroker.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIMessage.h" +#include "guilib/GUIRadioButtonControl.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "input/actions/Action.h" +#include "input/actions/ActionIDs.h" +#include "pvr/PVRManager.h" +#include "pvr/guilib/PVRGUIActionsPlayback.h" +#include "pvr/guilib/PVRGUIActionsRecordings.h" +#include "pvr/recordings/PVRRecording.h" +#include "pvr/recordings/PVRRecordings.h" +#include "pvr/recordings/PVRRecordingsPath.h" +#include "settings/MediaSettings.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/URIUtils.h" +#include "video/VideoLibraryQueue.h" +#include "video/VideoUtils.h" +#include "video/windows/GUIWindowVideoBase.h" +#include "video/windows/GUIWindowVideoNav.h" + +#include <memory> +#include <mutex> +#include <string> + +using namespace PVR; + +CGUIWindowPVRRecordingsBase::CGUIWindowPVRRecordingsBase(bool bRadio, + int id, + const std::string& xmlFile) + : CGUIWindowPVRBase(bRadio, id, xmlFile), + m_settings( + {CSettings::SETTING_PVRRECORD_GROUPRECORDINGS, CSettings::SETTING_MYVIDEOS_SELECTACTION}) +{ +} + +CGUIWindowPVRRecordingsBase::~CGUIWindowPVRRecordingsBase() = default; + +void CGUIWindowPVRRecordingsBase::OnWindowLoaded() +{ + CONTROL_SELECT(CONTROL_BTNGROUPITEMS); +} + +std::string CGUIWindowPVRRecordingsBase::GetDirectoryPath() +{ + const std::string basePath = CPVRRecordingsPath(m_bShowDeletedRecordings, m_bRadio); + return URIUtils::PathHasParent(m_vecItems->GetPath(), basePath) ? m_vecItems->GetPath() + : basePath; +} + +void CGUIWindowPVRRecordingsBase::GetContextButtons(int itemNumber, CContextButtons& buttons) +{ + if (itemNumber < 0 || itemNumber >= m_vecItems->Size()) + return; + CFileItemPtr pItem = m_vecItems->Get(itemNumber); + + if (pItem->IsParentFolder()) + { + // No context menu for ".." items + return; + } + + bool isDeletedRecording = false; + + std::shared_ptr<CPVRRecording> recording(pItem->GetPVRRecordingInfoTag()); + if (recording) + { + isDeletedRecording = recording->IsDeleted(); + + if (isDeletedRecording) + { + if (m_vecItems->GetObjectCount() > 1) + buttons.Add(CONTEXT_BUTTON_DELETE_ALL, 19292); /* Delete all permanently */ + } + } + + if (!isDeletedRecording) + CGUIWindowPVRBase::GetContextButtons(itemNumber, buttons); +} + +bool CGUIWindowPVRRecordingsBase::OnAction(const CAction& action) +{ + if (action.GetID() == ACTION_PARENT_DIR || action.GetID() == ACTION_NAV_BACK) + { + CPVRRecordingsPath path(m_vecItems->GetPath()); + if (path.IsValid() && !path.IsRecordingsRoot()) + { + GoParentFolder(); + return true; + } + } + else if (action.GetID() == ACTION_TOGGLE_WATCHED) + { + const std::shared_ptr<CFileItem> pItem = m_vecItems->Get(m_viewControl.GetSelectedItem()); + if (!pItem || pItem->IsParentFolder()) + return false; + + bool bUnWatched = false; + if (pItem->HasPVRRecordingInfoTag()) + bUnWatched = pItem->GetPVRRecordingInfoTag()->GetPlayCount() == 0; + else if (pItem->m_bIsFolder) + bUnWatched = pItem->GetProperty("unwatchedepisodes").asInteger() > 0; + else + return false; + + CVideoLibraryQueue::GetInstance().MarkAsWatched(pItem, bUnWatched); + return true; + } + + return CGUIWindowPVRBase::OnAction(action); +} + +bool CGUIWindowPVRRecordingsBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button) +{ + if (itemNumber < 0 || itemNumber >= m_vecItems->Size()) + return false; + CFileItemPtr pItem = m_vecItems->Get(itemNumber); + + return OnContextButtonDeleteAll(pItem.get(), button) || + CGUIMediaWindow::OnContextButton(itemNumber, button); +} + +bool CGUIWindowPVRRecordingsBase::Update(const std::string& strDirectory, + bool updateFilterPath /* = true */) +{ + m_thumbLoader.StopThread(); + + int iOldCount = m_vecItems->GetObjectCount(); + const std::string oldPath = m_vecItems->GetPath(); + + bool bReturn = CGUIWindowPVRBase::Update(strDirectory); + + if (bReturn) + { + // TODO: does it make sense to show the non-deleted recordings, although user wants + // to see the deleted recordings? Or is this just another hack to avoid misbehavior + // of CGUIMediaWindow if it has no content? + + std::unique_lock<CCriticalSection> lock(m_critSection); + + /* empty list for deleted recordings */ + if (m_vecItems->GetObjectCount() == 0 && m_bShowDeletedRecordings) + { + /* show the normal recordings instead */ + m_bShowDeletedRecordings = false; + lock.unlock(); + Update(GetDirectoryPath()); + return bReturn; + } + } + + if (bReturn && iOldCount > 0 && m_vecItems->GetObjectCount() == 0 && + oldPath == m_vecItems->GetPath()) + { + /* go to the parent folder if we're in a subdirectory and for instance just deleted the last item */ + const CPVRRecordingsPath path(m_vecItems->GetPath()); + if (path.IsValid() && !path.IsRecordingsRoot()) + GoParentFolder(); + } + return bReturn; +} + +void CGUIWindowPVRRecordingsBase::UpdateButtons() +{ + int iWatchMode = CMediaSettings::GetInstance().GetWatchedMode("recordings"); + int iStringId = 257; // "Error" + + if (iWatchMode == WatchedModeAll) + iStringId = 22015; // "All recordings" + else if (iWatchMode == WatchedModeUnwatched) + iStringId = 16101; // "Unwatched" + else if (iWatchMode == WatchedModeWatched) + iStringId = 16102; // "Watched" + + SET_CONTROL_LABEL(CONTROL_BTNSHOWMODE, g_localizeStrings.Get(iStringId)); + + bool bGroupRecordings = m_settings.GetBoolValue(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS); + SET_CONTROL_SELECTED(GetID(), CONTROL_BTNGROUPITEMS, bGroupRecordings); + + CGUIRadioButtonControl* btnShowDeleted = + static_cast<CGUIRadioButtonControl*>(GetControl(CONTROL_BTNSHOWDELETED)); + if (btnShowDeleted) + { + btnShowDeleted->SetVisible( + m_bRadio ? CServiceBroker::GetPVRManager().Recordings()->HasDeletedRadioRecordings() + : CServiceBroker::GetPVRManager().Recordings()->HasDeletedTVRecordings()); + btnShowDeleted->SetSelected(m_bShowDeletedRecordings); + } + + CGUIWindowPVRBase::UpdateButtons(); + SET_CONTROL_LABEL(CONTROL_LABEL_HEADER1, m_bShowDeletedRecordings + ? g_localizeStrings.Get(19179) + : ""); /* Deleted recordings trash */ + + const CPVRRecordingsPath path(m_vecItems->GetPath()); + SET_CONTROL_LABEL(CONTROL_LABEL_HEADER2, + bGroupRecordings && path.IsValid() ? path.GetUnescapedDirectoryPath() : ""); +} + +bool CGUIWindowPVRRecordingsBase::OnMessage(CGUIMessage& message) +{ + bool bReturn = false; + switch (message.GetMessage()) + { + case GUI_MSG_CLICKED: + if (message.GetSenderId() == m_viewControl.GetCurrentControl()) + { + int iItem = m_viewControl.GetSelectedItem(); + if (iItem >= 0 && iItem < m_vecItems->Size()) + { + const CFileItemPtr item(m_vecItems->Get(iItem)); + switch (message.GetParam1()) + { + case ACTION_SELECT_ITEM: + case ACTION_MOUSE_LEFT_CLICK: + case ACTION_PLAYER_PLAY: + { + const CPVRRecordingsPath path(m_vecItems->GetPath()); + if (path.IsValid() && path.IsRecordingsRoot() && item->IsParentFolder()) + { + // handle special 'go home' item. + CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_HOME); + bReturn = true; + break; + } + + if (!item->IsParentFolder() && message.GetParam1() == ACTION_PLAYER_PLAY) + { + if (item->m_bIsFolder) + { + if (CGUIWindowVideoNav::ShowResumeMenu(*item)) + VIDEO_UTILS::PlayItem(item); + } + else + CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().PlayRecording( + *item, true /* check resume */); + + bReturn = true; + } + else if (item->m_bIsFolder) + { + // recording folders and ".." folders in subfolders are handled by base class. + bReturn = false; + } + else + { + switch (m_settings.GetIntValue(CSettings::SETTING_MYVIDEOS_SELECTACTION)) + { + case SELECT_ACTION_CHOOSE: + OnPopupMenu(iItem); + bReturn = true; + break; + case SELECT_ACTION_PLAY_OR_RESUME: + CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().PlayRecording( + *item, true /* check resume */); + bReturn = true; + break; + case SELECT_ACTION_RESUME: + CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().ResumePlayRecording( + *item, true /* fall back to play if no resume possible */); + bReturn = true; + break; + case SELECT_ACTION_INFO: + CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().ShowRecordingInfo( + *item); + bReturn = true; + break; + default: + bReturn = false; + break; + } + } + break; + } + case ACTION_CONTEXT_MENU: + case ACTION_MOUSE_RIGHT_CLICK: + OnPopupMenu(iItem); + bReturn = true; + break; + case ACTION_SHOW_INFO: + CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().ShowRecordingInfo(*item); + bReturn = true; + break; + case ACTION_DELETE_ITEM: + CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().DeleteRecording(*item); + bReturn = true; + break; + default: + bReturn = false; + break; + } + } + } + else if (message.GetSenderId() == CONTROL_BTNGROUPITEMS) + { + const std::shared_ptr<CSettings> settings = + CServiceBroker::GetSettingsComponent()->GetSettings(); + settings->ToggleBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS); + settings->Save(); + Refresh(true); + } + else if (message.GetSenderId() == CONTROL_BTNSHOWDELETED) + { + CGUIRadioButtonControl* radioButton = + static_cast<CGUIRadioButtonControl*>(GetControl(CONTROL_BTNSHOWDELETED)); + if (radioButton) + { + m_bShowDeletedRecordings = radioButton->IsSelected(); + Update(GetDirectoryPath()); + } + bReturn = true; + } + else if (message.GetSenderId() == CONTROL_BTNSHOWMODE) + { + CMediaSettings::GetInstance().CycleWatchedMode("recordings"); + CServiceBroker::GetSettingsComponent()->GetSettings()->Save(); + OnFilterItems(GetProperty("filter").asString()); + UpdateButtons(); + return true; + } + break; + case GUI_MSG_REFRESH_LIST: + { + switch (static_cast<PVREvent>(message.GetParam1())) + { + case PVREvent::CurrentItem: + case PVREvent::Epg: + case PVREvent::EpgActiveItem: + case PVREvent::EpgContainer: + case PVREvent::Timers: + SetInvalid(); + break; + + case PVREvent::RecordingsInvalidated: + case PVREvent::TimersInvalidated: + Refresh(true); + break; + + default: + break; + } + break; + } + } + + return bReturn || CGUIWindowPVRBase::OnMessage(message); +} + +bool CGUIWindowPVRRecordingsBase::OnContextButtonDeleteAll(CFileItem* item, CONTEXT_BUTTON button) +{ + if (button == CONTEXT_BUTTON_DELETE_ALL) + { + CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().DeleteAllRecordingsFromTrash(); + return true; + } + + return false; +} + +void CGUIWindowPVRRecordingsBase::OnPrepareFileItems(CFileItemList& items) +{ + if (items.IsEmpty()) + return; + + CFileItemList files; + for (const auto& item : items) + { + if (!item->m_bIsFolder) + files.Add(item); + } + + if (!files.IsEmpty()) + { + if (m_database.Open()) + { + CGUIWindowVideoBase::LoadVideoInfo(files, m_database, false); + m_database.Close(); + } + m_thumbLoader.Load(files); + } + + CGUIWindowPVRBase::OnPrepareFileItems(items); +} + +bool CGUIWindowPVRRecordingsBase::GetFilteredItems(const std::string& filter, CFileItemList& items) +{ + bool listchanged = CGUIWindowPVRBase::GetFilteredItems(filter, items); + + int watchMode = CMediaSettings::GetInstance().GetWatchedMode("recordings"); + + CFileItemPtr item; + for (int i = 0; i < items.Size(); i++) + { + item = items.Get(i); + + if (item->IsParentFolder()) // Don't delete the go to parent folder + continue; + + if (!item->HasPVRRecordingInfoTag()) + continue; + + int iPlayCount = item->GetPVRRecordingInfoTag()->GetPlayCount(); + if ((watchMode == WatchedModeWatched && iPlayCount == 0) || + (watchMode == WatchedModeUnwatched && iPlayCount > 0)) + { + items.Remove(i); + i--; + listchanged = true; + } + } + + // Remove the parent folder item, if it's the only item in the folder. + if (items.GetObjectCount() == 0 && items.GetFileCount() > 0 && items.Get(0)->IsParentFolder()) + items.Remove(0); + + return listchanged; +} + +std::string CGUIWindowPVRTVRecordings::GetRootPath() const +{ + return CPVRRecordingsPath(m_bShowDeletedRecordings, false); +} + +std::string CGUIWindowPVRRadioRecordings::GetRootPath() const +{ + return CPVRRecordingsPath(m_bShowDeletedRecordings, true); +} |