2 * Copyright (C) 2016-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.
9 #include "PVRGUIActionsRecordings.h"
12 #include "FileItemList.h"
13 #include "ServiceBroker.h"
15 #include "dialogs/GUIDialogBusy.h"
16 #include "dialogs/GUIDialogYesNo.h"
17 #include "filesystem/IDirectory.h"
18 #include "guilib/GUIComponent.h"
19 #include "guilib/GUIWindowManager.h"
20 #include "guilib/WindowIDs.h"
21 #include "messaging/helpers/DialogOKHelper.h"
22 #include "pvr/PVRItem.h"
23 #include "pvr/PVRManager.h"
24 #include "pvr/addons/PVRClient.h"
25 #include "pvr/addons/PVRClients.h"
26 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
27 #include "pvr/dialogs/GUIDialogPVRRecordingSettings.h"
28 #include "pvr/recordings/PVRRecording.h"
29 #include "settings/Settings.h"
30 #include "threads/IRunnable.h"
31 #include "utils/Variant.h"
32 #include "utils/log.h"
39 using namespace KODI::MESSAGING
;
43 class AsyncRecordingAction
: private IRunnable
46 bool Execute(const CFileItem
& item
);
49 AsyncRecordingAction() = default;
52 // IRunnable implementation
55 // the worker function
56 virtual bool DoRun(const std::shared_ptr
<CFileItem
>& item
) = 0;
58 std::shared_ptr
<CFileItem
> m_item
;
59 bool m_bSuccess
= false;
62 bool AsyncRecordingAction::Execute(const CFileItem
& item
)
64 m_item
= std::make_shared
<CFileItem
>(item
);
65 CGUIDialogBusy::Wait(this, 100, false);
69 void AsyncRecordingAction::Run()
71 m_bSuccess
= DoRun(m_item
);
74 CServiceBroker::GetPVRManager().TriggerRecordingsUpdate();
77 class AsyncRenameRecording
: public AsyncRecordingAction
80 explicit AsyncRenameRecording(const std::string
& strNewName
) : m_strNewName(strNewName
) {}
83 bool DoRun(const std::shared_ptr
<CFileItem
>& item
) override
85 if (item
->IsUsablePVRRecording())
87 return item
->GetPVRRecordingInfoTag()->Rename(m_strNewName
);
91 CLog::LogF(LOGERROR
, "Cannot rename item '{}': no valid recording tag", item
->GetPath());
95 std::string m_strNewName
;
98 class AsyncDeleteRecording
: public AsyncRecordingAction
101 explicit AsyncDeleteRecording(bool bWatchedOnly
= false) : m_bWatchedOnly(bWatchedOnly
) {}
104 bool DoRun(const std::shared_ptr
<CFileItem
>& item
) override
107 if (item
->m_bIsFolder
)
109 CUtil::GetRecursiveListing(item
->GetPath(), items
, "", XFILE::DIR_FLAG_NO_FILE_INFO
);
116 return std::accumulate(
117 items
.cbegin(), items
.cend(), true, [this](bool success
, const auto& itemToDelete
) {
118 return (itemToDelete
->IsPVRRecording() &&
119 (!m_bWatchedOnly
|| itemToDelete
->GetPVRRecordingInfoTag()->GetPlayCount() > 0) &&
120 !itemToDelete
->GetPVRRecordingInfoTag()->Delete())
125 bool m_bWatchedOnly
= false;
128 class AsyncEmptyRecordingsTrash
: public AsyncRecordingAction
131 bool DoRun(const std::shared_ptr
<CFileItem
>& item
) override
133 return CServiceBroker::GetPVRManager().Clients()->DeleteAllRecordingsFromTrash() ==
138 class AsyncUndeleteRecording
: public AsyncRecordingAction
141 bool DoRun(const std::shared_ptr
<CFileItem
>& item
) override
143 if (item
->IsDeletedPVRRecording())
145 return item
->GetPVRRecordingInfoTag()->Undelete();
149 CLog::LogF(LOGERROR
, "Cannot undelete item '{}': no valid recording tag", item
->GetPath());
155 class AsyncSetRecordingPlayCount
: public AsyncRecordingAction
158 bool DoRun(const std::shared_ptr
<CFileItem
>& item
) override
160 const std::shared_ptr
<CPVRClient
> client
= CServiceBroker::GetPVRManager().GetClient(*item
);
163 const std::shared_ptr
<const CPVRRecording
> recording
= item
->GetPVRRecordingInfoTag();
164 return client
->SetRecordingPlayCount(*recording
, recording
->GetLocalPlayCount()) ==
171 class AsyncSetRecordingLifetime
: public AsyncRecordingAction
174 bool DoRun(const std::shared_ptr
<CFileItem
>& item
) override
176 const std::shared_ptr
<CPVRClient
> client
= CServiceBroker::GetPVRManager().GetClient(*item
);
178 return client
->SetRecordingLifetime(*item
->GetPVRRecordingInfoTag()) == PVR_ERROR_NO_ERROR
;
183 } // unnamed namespace
185 bool CPVRGUIActionsRecordings::ShowRecordingInfo(const CFileItem
& item
) const
187 if (!item
.IsPVRRecording())
189 CLog::LogF(LOGERROR
, "No recording!");
193 CGUIDialogPVRRecordingInfo
* pDlgInfo
=
194 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogPVRRecordingInfo
>(
195 WINDOW_DIALOG_PVR_RECORDING_INFO
);
198 CLog::LogF(LOGERROR
, "Unable to get WINDOW_DIALOG_PVR_RECORDING_INFO!");
202 pDlgInfo
->SetRecording(item
);
207 bool CPVRGUIActionsRecordings::EditRecording(const CFileItem
& item
) const
209 const std::shared_ptr
<CPVRRecording
> recording
= CPVRItem(item
).GetRecording();
212 CLog::LogF(LOGERROR
, "No recording!");
216 std::shared_ptr
<CPVRRecording
> origRecording(new CPVRRecording
);
217 origRecording
->Update(*recording
,
218 *CServiceBroker::GetPVRManager().GetClient(recording
->ClientID()));
220 if (!ShowRecordingSettings(recording
))
223 if (origRecording
->m_strTitle
!= recording
->m_strTitle
)
225 if (!AsyncRenameRecording(recording
->m_strTitle
).Execute(item
))
226 CLog::LogF(LOGERROR
, "Renaming recording failed!");
229 if (origRecording
->GetLocalPlayCount() != recording
->GetLocalPlayCount())
231 if (!AsyncSetRecordingPlayCount().Execute(item
))
232 CLog::LogF(LOGERROR
, "Setting recording playcount failed!");
235 if (origRecording
->LifeTime() != recording
->LifeTime())
237 if (!AsyncSetRecordingLifetime().Execute(item
))
238 CLog::LogF(LOGERROR
, "Setting recording lifetime failed!");
244 bool CPVRGUIActionsRecordings::CanEditRecording(const CFileItem
& item
) const
246 return CGUIDialogPVRRecordingSettings::CanEditRecording(item
);
249 bool CPVRGUIActionsRecordings::DeleteRecording(const CFileItem
& item
) const
251 if ((!item
.IsPVRRecording() && !item
.m_bIsFolder
) || item
.IsParentFolder())
254 if (!ConfirmDeleteRecording(item
))
257 if (!AsyncDeleteRecording().Execute(item
))
259 HELPERS::ShowOKDialogText(
262 19111}); // "Error", "PVR backend error. Check the log for more information about this message."
269 bool CPVRGUIActionsRecordings::ConfirmDeleteRecording(const CFileItem
& item
) const
271 return CGUIDialogYesNo::ShowAndGetInput(
272 CVariant
{122}, // "Confirm delete"
274 ? CVariant
{19113} // "Delete all recordings in this folder?"
275 : item
.GetPVRRecordingInfoTag()->IsDeleted()
277 // "Remove this deleted recording from trash? This operation cannot be reverted."
278 : CVariant
{19112}, // "Delete this recording?"
279 CVariant
{""}, CVariant
{item
.GetLabel()});
282 bool CPVRGUIActionsRecordings::DeleteWatchedRecordings(const CFileItem
& item
) const
284 if (!item
.m_bIsFolder
|| item
.IsParentFolder())
287 if (!ConfirmDeleteWatchedRecordings(item
))
290 if (!AsyncDeleteRecording(true).Execute(item
))
292 HELPERS::ShowOKDialogText(
295 19111}); // "Error", "PVR backend error. Check the log for more information about this message."
302 bool CPVRGUIActionsRecordings::ConfirmDeleteWatchedRecordings(const CFileItem
& item
) const
304 return CGUIDialogYesNo::ShowAndGetInput(
305 CVariant
{122}, // "Confirm delete"
306 CVariant
{19328}, // "Delete all watched recordings in this folder?"
307 CVariant
{""}, CVariant
{item
.GetLabel()});
310 bool CPVRGUIActionsRecordings::DeleteAllRecordingsFromTrash() const
312 if (!ConfirmDeleteAllRecordingsFromTrash())
315 if (!AsyncEmptyRecordingsTrash().Execute({}))
321 bool CPVRGUIActionsRecordings::ConfirmDeleteAllRecordingsFromTrash() const
323 return CGUIDialogYesNo::ShowAndGetInput(
324 CVariant
{19292}, // "Delete all permanently"
326 19293}); // "Remove all deleted recordings from trash? This operation cannot be reverted."
329 bool CPVRGUIActionsRecordings::UndeleteRecording(const CFileItem
& item
) const
331 if (!item
.IsDeletedPVRRecording())
334 if (!AsyncUndeleteRecording().Execute(item
))
336 HELPERS::ShowOKDialogText(
339 19111}); // "Error", "PVR backend error. Check the log for more information about this message."
346 bool CPVRGUIActionsRecordings::ShowRecordingSettings(
347 const std::shared_ptr
<CPVRRecording
>& recording
) const
349 CGUIDialogPVRRecordingSettings
* pDlgInfo
=
350 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogPVRRecordingSettings
>(
351 WINDOW_DIALOG_PVR_RECORDING_SETTING
);
354 CLog::LogF(LOGERROR
, "Unable to get WINDOW_DIALOG_PVR_RECORDING_SETTING!");
358 pDlgInfo
->SetRecording(recording
);
361 return pDlgInfo
->IsConfirmed();