[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / pvr / windows / GUIWindowPVRRecordings.cpp
blob0e5886a52b170a0c9b518a1e77d137f0556bccc6
1 /*
2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUIWindowPVRRecordings.h"
11 #include "FileItemList.h"
12 #include "GUIInfoManager.h"
13 #include "ServiceBroker.h"
14 #include "guilib/GUIComponent.h"
15 #include "guilib/GUIMessage.h"
16 #include "guilib/GUIRadioButtonControl.h"
17 #include "guilib/GUIWindowManager.h"
18 #include "guilib/LocalizeStrings.h"
19 #include "input/actions/Action.h"
20 #include "input/actions/ActionIDs.h"
21 #include "pvr/PVRManager.h"
22 #include "pvr/guilib/PVRGUIActionsPlayback.h"
23 #include "pvr/guilib/PVRGUIActionsRecordings.h"
24 #include "pvr/recordings/PVRRecording.h"
25 #include "pvr/recordings/PVRRecordings.h"
26 #include "pvr/recordings/PVRRecordingsPath.h"
27 #include "settings/MediaSettings.h"
28 #include "settings/Settings.h"
29 #include "settings/SettingsComponent.h"
30 #include "utils/URIUtils.h"
31 #include "video/VideoLibraryQueue.h"
32 #include "video/guilib/VideoGUIUtils.h"
33 #include "video/guilib/VideoPlayActionProcessor.h"
34 #include "video/guilib/VideoSelectActionProcessor.h"
35 #include "video/windows/GUIWindowVideoBase.h"
37 #include <memory>
38 #include <mutex>
39 #include <string>
41 using namespace KODI;
42 using namespace PVR;
44 CGUIWindowPVRRecordingsBase::CGUIWindowPVRRecordingsBase(bool bRadio,
45 int id,
46 const std::string& xmlFile)
47 : CGUIWindowPVRBase(bRadio, id, xmlFile),
48 m_settings({CSettings::SETTING_PVRRECORD_GROUPRECORDINGS})
52 CGUIWindowPVRRecordingsBase::~CGUIWindowPVRRecordingsBase() = default;
54 void CGUIWindowPVRRecordingsBase::OnWindowLoaded()
56 CONTROL_SELECT(CONTROL_BTNGROUPITEMS);
59 std::string CGUIWindowPVRRecordingsBase::GetDirectoryPath()
61 const std::string basePath = CPVRRecordingsPath(m_bShowDeletedRecordings, m_bRadio);
62 return URIUtils::PathHasParent(m_vecItems->GetPath(), basePath) ? m_vecItems->GetPath()
63 : basePath;
66 void CGUIWindowPVRRecordingsBase::GetContextButtons(int itemNumber, CContextButtons& buttons)
68 if (itemNumber < 0 || itemNumber >= m_vecItems->Size())
69 return;
70 CFileItemPtr pItem = m_vecItems->Get(itemNumber);
72 if (pItem->IsParentFolder())
74 // No context menu for ".." items
75 return;
78 bool isDeletedRecording = false;
80 std::shared_ptr<CPVRRecording> recording(pItem->GetPVRRecordingInfoTag());
81 if (recording)
83 isDeletedRecording = recording->IsDeleted();
85 if (isDeletedRecording)
87 if (m_vecItems->GetObjectCount() > 1)
88 buttons.Add(CONTEXT_BUTTON_DELETE_ALL, 19292); /* Delete all permanently */
92 if (!isDeletedRecording)
93 CGUIWindowPVRBase::GetContextButtons(itemNumber, buttons);
96 bool CGUIWindowPVRRecordingsBase::OnAction(const CAction& action)
98 if (action.GetID() == ACTION_PARENT_DIR || action.GetID() == ACTION_NAV_BACK)
100 CPVRRecordingsPath path(m_vecItems->GetPath());
101 if (path.IsValid() && !path.IsRecordingsRoot())
103 GoParentFolder();
104 return true;
107 else if (action.GetID() == ACTION_TOGGLE_WATCHED)
109 const std::shared_ptr<CFileItem> pItem = m_vecItems->Get(m_viewControl.GetSelectedItem());
110 if (!pItem || pItem->IsParentFolder())
111 return false;
113 bool bUnWatched = false;
114 if (pItem->HasPVRRecordingInfoTag())
115 bUnWatched = pItem->GetPVRRecordingInfoTag()->GetPlayCount() == 0;
116 else if (pItem->m_bIsFolder)
117 bUnWatched = pItem->GetProperty("unwatchedepisodes").asInteger() > 0;
118 else
119 return false;
121 CVideoLibraryQueue::GetInstance().MarkAsWatched(pItem, bUnWatched);
122 return true;
125 return CGUIWindowPVRBase::OnAction(action);
128 bool CGUIWindowPVRRecordingsBase::OnPopupMenu(int iItem)
130 if (iItem >= 0 && iItem < m_vecItems->Size())
132 const auto item = m_vecItems->Get(iItem);
133 item->SetProperty("CheckAutoPlayNextItem", true);
136 return CGUIWindowPVRBase::OnPopupMenu(iItem);
139 bool CGUIWindowPVRRecordingsBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
141 if (itemNumber < 0 || itemNumber >= m_vecItems->Size())
142 return false;
143 CFileItemPtr pItem = m_vecItems->Get(itemNumber);
145 return OnContextButtonDeleteAll(pItem.get(), button) ||
146 CGUIMediaWindow::OnContextButton(itemNumber, button);
149 bool CGUIWindowPVRRecordingsBase::Update(const std::string& strDirectory,
150 bool updateFilterPath /* = true */)
152 m_thumbLoader.StopThread();
154 int iOldCount = m_vecItems->GetObjectCount();
155 const std::string oldPath = m_vecItems->GetPath();
157 bool bReturn = CGUIWindowPVRBase::Update(strDirectory);
159 if (bReturn)
161 // TODO: does it make sense to show the non-deleted recordings, although user wants
162 // to see the deleted recordings? Or is this just another hack to avoid misbehavior
163 // of CGUIMediaWindow if it has no content?
165 std::unique_lock<CCriticalSection> lock(m_critSection);
167 /* empty list for deleted recordings */
168 if (m_vecItems->GetObjectCount() == 0 && m_bShowDeletedRecordings)
170 /* show the normal recordings instead */
171 m_bShowDeletedRecordings = false;
172 lock.unlock();
173 Update(GetDirectoryPath());
174 return bReturn;
178 if (bReturn && iOldCount > 0 && m_vecItems->GetObjectCount() == 0 &&
179 oldPath == m_vecItems->GetPath())
181 /* go to the parent folder if we're in a subdirectory and for instance just deleted the last item */
182 const CPVRRecordingsPath path(m_vecItems->GetPath());
183 if (path.IsValid() && !path.IsRecordingsRoot())
184 GoParentFolder();
186 return bReturn;
189 void CGUIWindowPVRRecordingsBase::UpdateButtons()
191 int iWatchMode = CMediaSettings::GetInstance().GetWatchedMode("recordings");
192 int iStringId = 257; // "Error"
194 if (iWatchMode == WatchedModeAll)
195 iStringId = 22015; // "All recordings"
196 else if (iWatchMode == WatchedModeUnwatched)
197 iStringId = 16101; // "Unwatched"
198 else if (iWatchMode == WatchedModeWatched)
199 iStringId = 16102; // "Watched"
201 SET_CONTROL_LABEL(CONTROL_BTNSHOWMODE, g_localizeStrings.Get(iStringId));
203 bool bGroupRecordings = m_settings.GetBoolValue(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS);
204 SET_CONTROL_SELECTED(GetID(), CONTROL_BTNGROUPITEMS, bGroupRecordings);
206 CGUIRadioButtonControl* btnShowDeleted =
207 static_cast<CGUIRadioButtonControl*>(GetControl(CONTROL_BTNSHOWDELETED));
208 if (btnShowDeleted)
210 btnShowDeleted->SetVisible(
211 m_bRadio ? CServiceBroker::GetPVRManager().Recordings()->HasDeletedRadioRecordings()
212 : CServiceBroker::GetPVRManager().Recordings()->HasDeletedTVRecordings());
213 btnShowDeleted->SetSelected(m_bShowDeletedRecordings);
216 CGUIWindowPVRBase::UpdateButtons();
217 SET_CONTROL_LABEL(CONTROL_LABEL_HEADER1, m_bShowDeletedRecordings
218 ? g_localizeStrings.Get(19179)
219 : ""); /* Deleted recordings trash */
221 const CPVRRecordingsPath path(m_vecItems->GetPath());
222 SET_CONTROL_LABEL(CONTROL_LABEL_HEADER2,
223 bGroupRecordings && path.IsValid() ? path.GetUnescapedDirectoryPath() : "");
226 namespace
228 class CVideoSelectActionProcessor : public VIDEO::GUILIB::CVideoSelectActionProcessorBase
230 public:
231 CVideoSelectActionProcessor(CGUIWindowPVRRecordingsBase& window,
232 const std::shared_ptr<CFileItem>& item,
233 int itemIndex)
234 : CVideoSelectActionProcessorBase(item), m_window(window), m_itemIndex(itemIndex)
238 protected:
239 bool OnPlayPartSelected(unsigned int part) override
241 //! @todo pvr recordings do not support video stacking (yet).
242 return false;
245 bool OnResumeSelected() override
247 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().ResumePlayRecording(
248 *m_item, true /* fall back to play if no resume possible */);
249 return true;
252 bool OnPlaySelected() override
254 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().PlayRecording(
255 *m_item, false /* no resume check */);
256 return true;
259 bool OnQueueSelected() override
261 VIDEO::UTILS::QueueItem(m_item, VIDEO::UTILS::QueuePosition::POSITION_END);
262 return true;
265 bool OnInfoSelected() override
267 CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().ShowRecordingInfo(*m_item);
268 return true;
271 bool OnMoreSelected() override
273 m_window.OnPopupMenu(m_itemIndex);
274 return true;
277 private:
278 CGUIWindowPVRRecordingsBase& m_window;
279 const int m_itemIndex{-1};
282 class CVideoPlayActionProcessor : public VIDEO::GUILIB::CVideoPlayActionProcessorBase
284 public:
285 explicit CVideoPlayActionProcessor(const std::shared_ptr<CFileItem>& item)
286 : CVideoPlayActionProcessorBase(item)
290 protected:
291 bool OnResumeSelected() override
293 if (m_item->m_bIsFolder)
295 m_item->SetStartOffset(STARTOFFSET_RESUME);
296 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().PlayRecordingFolder(
297 *m_item, false /* no resume check */);
299 else
301 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().ResumePlayRecording(
302 *m_item, true /* fall back to play if no resume possible */);
304 return true;
307 bool OnPlaySelected() override
309 if (m_item->m_bIsFolder)
311 m_item->SetStartOffset(0);
312 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().PlayRecordingFolder(
313 *m_item, false /* no resume check */);
315 else
317 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().PlayRecording(
318 *m_item, false /* no resume check */);
320 return true;
323 } // namespace
325 bool CGUIWindowPVRRecordingsBase::OnMessage(CGUIMessage& message)
327 bool bReturn = false;
328 switch (message.GetMessage())
330 case GUI_MSG_CLICKED:
331 if (message.GetSenderId() == m_viewControl.GetCurrentControl())
333 int iItem = m_viewControl.GetSelectedItem();
334 if (iItem >= 0 && iItem < m_vecItems->Size())
336 const CFileItemPtr item(m_vecItems->Get(iItem));
337 switch (message.GetParam1())
339 case ACTION_SELECT_ITEM:
340 case ACTION_MOUSE_LEFT_CLICK:
341 case ACTION_PLAYER_PLAY:
343 const CPVRRecordingsPath path(m_vecItems->GetPath());
344 if (path.IsValid() && path.IsRecordingsRoot() && item->IsParentFolder())
346 // handle .. item, which is only visible if list of recordings is empty.
347 CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_HOME);
348 bReturn = true;
349 break;
352 if (!item->IsParentFolder() && message.GetParam1() == ACTION_PLAYER_PLAY)
354 CVideoPlayActionProcessor proc{item};
355 bReturn = proc.ProcessDefaultAction();
357 else if (item->m_bIsFolder)
359 // recording folders and ".." folders in subfolders are handled by base class.
360 bReturn = false;
362 else
364 CVideoSelectActionProcessor proc(*this, item, iItem);
365 bReturn = proc.ProcessDefaultAction();
367 break;
369 case ACTION_CONTEXT_MENU:
370 case ACTION_MOUSE_RIGHT_CLICK:
371 OnPopupMenu(iItem);
372 bReturn = true;
373 break;
374 case ACTION_SHOW_INFO:
375 CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().ShowRecordingInfo(*item);
376 bReturn = true;
377 break;
378 case ACTION_DELETE_ITEM:
379 CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().DeleteRecording(*item);
380 bReturn = true;
381 break;
382 default:
383 bReturn = false;
384 break;
388 else if (message.GetSenderId() == CONTROL_BTNGROUPITEMS)
390 const std::shared_ptr<CSettings> settings =
391 CServiceBroker::GetSettingsComponent()->GetSettings();
392 settings->ToggleBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS);
393 settings->Save();
394 Refresh(true);
396 else if (message.GetSenderId() == CONTROL_BTNSHOWDELETED)
398 CGUIRadioButtonControl* radioButton =
399 static_cast<CGUIRadioButtonControl*>(GetControl(CONTROL_BTNSHOWDELETED));
400 if (radioButton)
402 m_bShowDeletedRecordings = radioButton->IsSelected();
403 Update(GetDirectoryPath());
405 bReturn = true;
407 else if (message.GetSenderId() == CONTROL_BTNSHOWMODE)
409 CMediaSettings::GetInstance().CycleWatchedMode("recordings");
410 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
411 OnFilterItems(GetProperty("filter").asString());
412 UpdateButtons();
413 return true;
415 break;
416 case GUI_MSG_REFRESH_LIST:
418 switch (static_cast<PVREvent>(message.GetParam1()))
420 case PVREvent::CurrentItem:
421 case PVREvent::Epg:
422 case PVREvent::EpgActiveItem:
423 case PVREvent::EpgContainer:
424 case PVREvent::Timers:
425 SetInvalid();
426 break;
428 case PVREvent::RecordingsInvalidated:
429 case PVREvent::TimersInvalidated:
430 Refresh(true);
431 break;
433 default:
434 break;
436 break;
440 return bReturn || CGUIWindowPVRBase::OnMessage(message);
443 bool CGUIWindowPVRRecordingsBase::OnContextButtonDeleteAll(CFileItem* item, CONTEXT_BUTTON button)
445 if (button == CONTEXT_BUTTON_DELETE_ALL)
447 CServiceBroker::GetPVRManager().Get<PVR::GUI::Recordings>().DeleteAllRecordingsFromTrash();
448 return true;
451 return false;
454 void CGUIWindowPVRRecordingsBase::OnPrepareFileItems(CFileItemList& items)
456 if (items.IsEmpty())
457 return;
459 CFileItemList files;
460 for (const auto& item : items)
462 if (!item->m_bIsFolder)
463 files.Add(item);
466 if (!files.IsEmpty())
468 if (m_database.Open())
470 CGUIWindowVideoBase::LoadVideoInfo(files, m_database, false);
471 m_database.Close();
473 m_thumbLoader.Load(files);
476 CGUIWindowPVRBase::OnPrepareFileItems(items);
479 bool CGUIWindowPVRRecordingsBase::GetFilteredItems(const std::string& filter, CFileItemList& items)
481 bool listchanged = CGUIWindowPVRBase::GetFilteredItems(filter, items);
483 int watchMode = CMediaSettings::GetInstance().GetWatchedMode("recordings");
485 CFileItemPtr item;
486 for (int i = 0; i < items.Size(); i++)
488 item = items.Get(i);
490 if (item->IsParentFolder()) // Don't delete the go to parent folder
491 continue;
493 if (!item->HasPVRRecordingInfoTag())
494 continue;
496 int iPlayCount = item->GetPVRRecordingInfoTag()->GetPlayCount();
497 if ((watchMode == WatchedModeWatched && iPlayCount == 0) ||
498 (watchMode == WatchedModeUnwatched && iPlayCount > 0))
500 items.Remove(i);
501 i--;
502 listchanged = true;
506 // Remove the parent folder item, if it's the only item in the folder.
507 if (items.GetObjectCount() == 0 && items.GetFileCount() > 0 && items.Get(0)->IsParentFolder())
508 items.Remove(0);
510 return listchanged;
513 std::string CGUIWindowPVRTVRecordings::GetRootPath() const
515 return CPVRRecordingsPath(m_bShowDeletedRecordings, false);
518 std::string CGUIWindowPVRRadioRecordings::GetRootPath() const
520 return CPVRRecordingsPath(m_bShowDeletedRecordings, true);