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 "ContextMenus.h"
12 #include "GUIUserMessages.h"
13 #include "PlayListPlayer.h"
14 #include "ServiceBroker.h"
15 #include "application/Application.h"
16 #include "application/ApplicationComponents.h"
17 #include "application/ApplicationPlayer.h"
18 #include "filesystem/Directory.h"
19 #include "guilib/GUIComponent.h"
20 #include "guilib/GUIWindowManager.h"
21 #include "guilib/LocalizeStrings.h"
22 #include "playlists/PlayList.h"
23 #include "settings/MediaSettings.h"
24 #include "utils/StringUtils.h"
25 #include "utils/URIUtils.h"
26 #include "video/VideoUtils.h"
27 #include "video/dialogs/GUIDialogVideoInfo.h"
28 #include "video/windows/GUIWindowVideoBase.h"
29 #include "view/GUIViewState.h"
36 CVideoInfo::CVideoInfo(MediaType mediaType
)
37 : CStaticContextMenuAction(19033), m_mediaType(std::move(mediaType
))
41 bool CVideoInfo::IsVisible(const CFileItem
& item
) const
43 if (!item
.HasVideoInfoTag())
46 if (item
.IsPVRRecording())
47 return false; // pvr recordings have its own implementation for this
49 return item
.GetVideoInfoTag()->m_type
== m_mediaType
;
52 bool CVideoInfo::Execute(const std::shared_ptr
<CFileItem
>& item
) const
54 CGUIDialogVideoInfo::ShowFor(*item
);
58 bool CVideoRemoveResumePoint::IsVisible(const CFileItem
& itemIn
) const
60 CFileItem
item(itemIn
.GetItemToPlay());
61 if (item
.IsDeleted()) // e.g. trashed pvr recording
64 // Folders don't have a resume point
65 return !item
.m_bIsFolder
&& VIDEO_UTILS::GetItemResumeInformation(item
).isResumable
;
68 bool CVideoRemoveResumePoint::Execute(const std::shared_ptr
<CFileItem
>& item
) const
70 CVideoLibraryQueue::GetInstance().ResetResumePoint(item
);
74 bool CVideoMarkWatched::IsVisible(const CFileItem
& item
) const
76 if (item
.IsDeleted()) // e.g. trashed pvr recording
79 if (item
.m_bIsFolder
&& item
.IsPlugin()) // we cannot manage plugin folder's watched state
82 if (item
.m_bIsFolder
) // Only allow video db content, video and recording folders to be updated recursively
84 if (item
.HasVideoInfoTag())
85 return item
.IsVideoDb();
86 else if (item
.GetProperty("IsVideoFolder").asBoolean())
89 return !item
.IsParentFolder() && URIUtils::IsPVRRecordingFileOrFolder(item
.GetPath());
91 else if (!item
.HasVideoInfoTag())
94 return item
.GetVideoInfoTag()->GetPlayCount() == 0;
97 bool CVideoMarkWatched::Execute(const std::shared_ptr
<CFileItem
>& item
) const
99 CVideoLibraryQueue::GetInstance().MarkAsWatched(item
, true);
103 bool CVideoMarkUnWatched::IsVisible(const CFileItem
& item
) const
105 if (item
.IsDeleted()) // e.g. trashed pvr recording
108 if (item
.m_bIsFolder
&& item
.IsPlugin()) // we cannot manage plugin folder's watched state
111 if (item
.m_bIsFolder
) // Only allow video db content, video and recording folders to be updated recursively
113 if (item
.HasVideoInfoTag())
114 return item
.IsVideoDb();
115 else if (item
.GetProperty("IsVideoFolder").asBoolean())
118 return !item
.IsParentFolder() && URIUtils::IsPVRRecordingFileOrFolder(item
.GetPath());
120 else if (!item
.HasVideoInfoTag())
123 return item
.GetVideoInfoTag()->GetPlayCount() > 0;
126 bool CVideoMarkUnWatched::Execute(const std::shared_ptr
<CFileItem
>& item
) const
128 CVideoLibraryQueue::GetInstance().MarkAsWatched(item
, false);
132 bool CVideoBrowse::IsVisible(const CFileItem
& item
) const
134 if (item
.IsFileFolder(EFILEFOLDER_MASK_ONBROWSE
))
135 return false; // handled by CMediaWindow
137 return item
.m_bIsFolder
&& VIDEO_UTILS::IsItemPlayable(item
);
140 bool CVideoBrowse::Execute(const std::shared_ptr
<CFileItem
>& item
) const
142 int target
= WINDOW_INVALID
;
143 if (URIUtils::IsPVRRadioRecordingFileOrFolder(item
->GetPath()))
144 target
= WINDOW_RADIO_RECORDINGS
;
145 else if (URIUtils::IsPVRTVRecordingFileOrFolder(item
->GetPath()))
146 target
= WINDOW_TV_RECORDINGS
;
148 target
= WINDOW_VIDEO_NAV
;
150 auto& windowMgr
= CServiceBroker::GetGUI()->GetWindowManager();
152 if (target
== windowMgr
.GetActiveWindow())
154 CGUIMessage
msg(GUI_MSG_NOTIFY_ALL
, target
, 0, GUI_MSG_UPDATE
);
155 msg
.SetStringParam(item
->GetPath());
156 windowMgr
.SendMessage(msg
);
160 windowMgr
.ActivateWindow(target
, {item
->GetPath(), "return"});
165 std::string
CVideoResume::GetLabel(const CFileItem
& item
) const
167 return CGUIWindowVideoBase::GetResumeString(item
.GetItemToPlay());
170 bool CVideoResume::IsVisible(const CFileItem
& itemIn
) const
172 CFileItem
item(itemIn
.GetItemToPlay());
173 if (item
.IsDeleted()) // e.g. trashed pvr recording
176 return VIDEO_UTILS::GetItemResumeInformation(item
).isResumable
;
182 void AddRecordingsToPlayList(const std::shared_ptr
<CFileItem
>& item
, CFileItemList
& queuedItems
)
184 if (item
->m_bIsFolder
)
187 XFILE::CDirectory::GetDirectory(item
->GetPath(), items
, "", XFILE::DIR_FLAG_DEFAULTS
);
189 const int watchedMode
= CMediaSettings::GetInstance().GetWatchedMode("recordings");
190 const bool unwatchedOnly
= watchedMode
== WatchedModeUnwatched
;
191 const bool watchedOnly
= watchedMode
== WatchedModeWatched
;
192 for (const auto& currItem
: items
)
194 if (currItem
->HasVideoInfoTag() &&
195 ((unwatchedOnly
&& currItem
->GetVideoInfoTag()->GetPlayCount() > 0) ||
196 (watchedOnly
&& currItem
->GetVideoInfoTag()->GetPlayCount() <= 0)))
199 AddRecordingsToPlayList(currItem
, queuedItems
);
204 queuedItems
.Add(item
);
208 void AddRecordingsToPlayListAndSort(const std::shared_ptr
<CFileItem
>& item
,
209 CFileItemList
& queuedItems
)
211 queuedItems
.SetPath(item
->GetPath());
212 AddRecordingsToPlayList(item
, queuedItems
);
214 if (!queuedItems
.IsEmpty())
216 const int windowId
= CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
217 if (windowId
== WINDOW_TV_RECORDINGS
|| windowId
== WINDOW_RADIO_RECORDINGS
)
219 std::unique_ptr
<CGUIViewState
> viewState(CGUIViewState::GetViewState(windowId
, queuedItems
));
221 queuedItems
.Sort(viewState
->GetSortMethod());
226 void PlayAndQueueRecordings(const std::shared_ptr
<CFileItem
>& item
, int windowId
)
228 const std::shared_ptr
<CFileItem
> parentFolderItem
=
229 std::make_shared
<CFileItem
>(URIUtils::GetParentPath(item
->GetPath()), true);
231 // add all items of given item's directory to a temporary playlist, start playback of given item
232 CFileItemList queuedItems
;
233 AddRecordingsToPlayListAndSort(parentFolderItem
, queuedItems
);
235 PLAYLIST::CPlayListPlayer
& player
= CServiceBroker::GetPlaylistPlayer();
237 player
.ClearPlaylist(PLAYLIST::TYPE_VIDEO
);
239 player
.Add(PLAYLIST::TYPE_VIDEO
, queuedItems
);
241 // figure out where to start playback
242 PLAYLIST::CPlayList
& playList
= player
.GetPlaylist(PLAYLIST::TYPE_VIDEO
);
245 for (int i
= 0; i
< queuedItems
.Size(); ++i
)
247 if (item
->IsSamePath(queuedItems
.Get(i
).get()))
254 if (player
.IsShuffled(PLAYLIST::TYPE_VIDEO
))
256 playList
.Swap(0, playList
.FindOrder(itemToPlay
));
260 player
.SetCurrentPlaylist(PLAYLIST::TYPE_VIDEO
);
261 player
.Play(itemToPlay
, "");
264 void SetPathAndPlay(CFileItem
& item
)
266 if (!item
.m_bIsFolder
&& item
.IsVideoDb())
268 item
.SetProperty("original_listitem_url", item
.GetPath());
269 item
.SetPath(item
.GetVideoInfoTag()->m_strFileNameAndPath
);
271 item
.SetProperty("check_resume", false);
273 if (item
.IsLiveTV()) // pvr tv or pvr radio?
275 g_application
.PlayMedia(item
, "", PLAYLIST::TYPE_VIDEO
);
279 item
.SetProperty("playlist_type_hint", PLAYLIST::TYPE_VIDEO
);
280 VIDEO_UTILS::PlayItem(std::make_shared
<CFileItem
>(item
));
284 } // unnamed namespace
286 bool CVideoResume::Execute(const std::shared_ptr
<CFileItem
>& itemIn
) const
288 CFileItem
item(itemIn
->GetItemToPlay());
290 if (item
.IsDVD() || item
.IsCDDA())
291 return MEDIA_DETECT::CAutorun::PlayDisc(item
.GetPath(), true, false);
294 item
.SetStartOffset(STARTOFFSET_RESUME
);
295 SetPathAndPlay(item
);
299 std::string
CVideoPlay::GetLabel(const CFileItem
& itemIn
) const
301 CFileItem
item(itemIn
.GetItemToPlay());
303 return g_localizeStrings
.Get(19000); // Switch to channel
304 if (VIDEO_UTILS::GetItemResumeInformation(item
).isResumable
)
305 return g_localizeStrings
.Get(12021); // Play from beginning
306 return g_localizeStrings
.Get(208); // Play
309 bool CVideoPlay::IsVisible(const CFileItem
& item
) const
311 return VIDEO_UTILS::IsItemPlayable(item
);
314 bool CVideoPlay::Execute(const std::shared_ptr
<CFileItem
>& itemIn
) const
316 CFileItem
item(itemIn
->GetItemToPlay());
318 if (item
.IsDVD() || item
.IsCDDA())
319 return MEDIA_DETECT::CAutorun::PlayDisc(item
.GetPath(), true, true);
321 SetPathAndPlay(item
);
325 bool CVideoQueue::IsVisible(const CFileItem
& item
) const
327 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST
)
328 return false; // Already queued
330 if (!item
.CanQueue())
333 return VIDEO_UTILS::IsItemPlayable(item
);
336 bool CVideoQueue::Execute(const std::shared_ptr
<CFileItem
>& item
) const
338 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST
)
339 return false; // Already queued
341 VIDEO_UTILS::QueueItem(item
, VIDEO_UTILS::QueuePosition::POSITION_END
);
345 bool CVideoPlayNext::IsVisible(const CFileItem
& item
) const
347 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST
)
348 return false; // Already queued
350 if (!item
.CanQueue())
353 return VIDEO_UTILS::IsItemPlayable(item
);
356 bool CVideoPlayNext::Execute(const std::shared_ptr
<CFileItem
>& item
) const
358 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VIDEO_PLAYLIST
)
359 return false; // Already queued
361 VIDEO_UTILS::QueueItem(item
, VIDEO_UTILS::QueuePosition::POSITION_BEGIN
);
365 bool CVideoPlayAndQueue::IsVisible(const CFileItem
& item
) const
367 const int windowId
= CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
368 if (windowId
== WINDOW_VIDEO_PLAYLIST
)
369 return false; // Already queued
371 if ((windowId
== WINDOW_TV_RECORDINGS
|| windowId
== WINDOW_RADIO_RECORDINGS
) &&
372 item
.IsUsablePVRRecording())
375 return false; //! @todo implement
378 bool CVideoPlayAndQueue::Execute(const std::shared_ptr
<CFileItem
>& item
) const
380 const int windowId
= CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
381 if (windowId
== WINDOW_VIDEO_PLAYLIST
)
382 return false; // Already queued
384 if ((windowId
== WINDOW_TV_RECORDINGS
|| windowId
== WINDOW_RADIO_RECORDINGS
) &&
385 item
->IsUsablePVRRecording())
387 // recursively add items located in the same folder as item to play list, starting with item
388 PlayAndQueueRecordings(item
, windowId
);
392 return true; //! @todo implement