2 * Copyright (C) 2022 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 "VideoUtils.h"
12 #include "FileItemList.h"
13 #include "ServiceBroker.h"
15 #include "filesystem/Directory.h"
16 #include "filesystem/VideoDatabaseDirectory/QueryParams.h"
17 #include "playlists/PlayListFileItemClassify.h"
18 #include "settings/SettingUtils.h"
19 #include "settings/Settings.h"
20 #include "settings/SettingsComponent.h"
21 #include "settings/lib/Setting.h"
22 #include "utils/FileUtils.h"
23 #include "utils/URIUtils.h"
24 #include "utils/log.h"
25 #include "video/VideoDatabase.h"
26 #include "video/VideoFileItemClassify.h"
27 #include "video/VideoInfoTag.h"
38 KODI::VIDEO::UTILS::ResumeInformation
GetFolderItemResumeInformation(const CFileItem
& item
)
40 if (!item
.m_bIsFolder
)
43 CFileItem
folderItem(item
);
44 if ((!folderItem
.HasProperty("inprogressepisodes") || // season/show
45 (folderItem
.GetProperty("inprogressepisodes").asInteger() == 0)) &&
46 (!folderItem
.HasProperty("inprogress") || // movie set
47 (folderItem
.GetProperty("inprogress").asInteger() == 0)))
52 if (!folderItem
.HasProperty("inprogressepisodes") && !folderItem
.HasProperty("inprogress"))
54 XFILE::VIDEODATABASEDIRECTORY::CQueryParams params
;
55 XFILE::VIDEODATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(item
.GetPath(), params
);
57 if (params
.GetTvShowId() >= 0)
59 if (params
.GetSeason() >= 0)
61 const int idSeason
= db
.GetSeasonId(static_cast<int>(params
.GetTvShowId()),
62 static_cast<int>(params
.GetSeason()));
65 CVideoInfoTag details
;
66 db
.GetSeasonInfo(idSeason
, details
, &folderItem
);
71 CVideoInfoTag details
;
72 db
.GetTvShowInfo(item
.GetPath(), details
, static_cast<int>(params
.GetTvShowId()),
76 else if (params
.GetSetId() >= 0)
78 CVideoInfoTag details
;
79 db
.GetSetInfo(static_cast<int>(params
.GetSetId()), details
, &folderItem
);
86 if (folderItem
.IsResumable())
88 KODI::VIDEO::UTILS::ResumeInformation resumeInfo
;
89 resumeInfo
.isResumable
= true;
96 KODI::VIDEO::UTILS::ResumeInformation
GetNonFolderItemResumeInformation(const CFileItem
& item
)
98 // do not resume nfo files
102 // do not resume playlists, except strm files
103 if (!item
.IsType(".strm") && PLAYLIST::IsPlayList(item
))
106 // do not resume Live TV and 'deleted' items (e.g. trashed pvr recordings)
107 if (item
.IsLiveTV() || item
.IsDeleted())
110 KODI::VIDEO::UTILS::ResumeInformation resumeInfo
;
112 if (item
.GetCurrentResumeTimeAndPartNumber(resumeInfo
.startOffset
, resumeInfo
.partNumber
))
114 if (resumeInfo
.startOffset
> 0)
116 resumeInfo
.startOffset
= CUtil::ConvertSecsToMilliSecs(resumeInfo
.startOffset
);
117 resumeInfo
.isResumable
= true;
122 // Obtain the resume bookmark from video db...
127 CLog::LogF(LOGERROR
, "Cannot open VideoDatabase");
131 std::string path
= item
.GetPath();
132 if (VIDEO::IsVideoDb(item
) || item
.IsDVD())
134 if (item
.HasVideoInfoTag())
136 path
= item
.GetVideoInfoTag()->m_strFileNameAndPath
;
138 else if (VIDEO::IsVideoDb(item
))
140 // Obtain path+filename from video db
141 XFILE::VIDEODATABASEDIRECTORY::CQueryParams params
;
142 XFILE::VIDEODATABASEDIRECTORY::CDirectoryNode::GetDatabaseInfo(item
.GetPath(), params
);
145 VideoDbContentType content_type
;
146 if ((id
= params
.GetMovieId()) >= 0)
147 content_type
= VideoDbContentType::MOVIES
;
148 else if ((id
= params
.GetEpisodeId()) >= 0)
149 content_type
= VideoDbContentType::EPISODES
;
150 else if ((id
= params
.GetMVideoId()) >= 0)
151 content_type
= VideoDbContentType::MUSICVIDEOS
;
154 CLog::LogF(LOGERROR
, "Cannot obtain video content type");
159 db
.GetFilePathById(static_cast<int>(id
), path
, content_type
);
164 CLog::LogF(LOGERROR
, "Cannot obtain bookmark for DVD");
171 db
.GetResumeBookMark(path
, bookmark
);
174 if (bookmark
.IsSet())
176 resumeInfo
.isResumable
= bookmark
.IsPartWay();
177 resumeInfo
.startOffset
= CUtil::ConvertSecsToMilliSecs(bookmark
.timeInSeconds
);
178 resumeInfo
.partNumber
= static_cast<int>(bookmark
.partNumber
);
184 } // unnamed namespace
186 namespace KODI::VIDEO::UTILS
188 std::string
GetOpticalMediaPath(const CFileItem
& item
)
190 auto exists
= [&item
](const std::string
& file
)
192 const std::string path
= URIUtils::AddFileToFolder(item
.GetPath(), file
);
193 return CFileUtils::Exists(path
);
196 using namespace std::string_literals
;
197 const auto files
= std::array
{
198 "VIDEO_TS.IFO"s
, "VIDEO_TS/VIDEO_TS.IFO"s
,
199 #ifdef HAVE_LIBBLURAY
200 "index.bdmv"s
, "INDEX.BDM"s
,
201 "BDMV/index.bdmv"s
, "BDMV/INDEX.BDM"s
,
205 const auto it
= std::find_if(files
.begin(), files
.end(), exists
);
206 return it
!= files
.end() ? URIUtils::AddFileToFolder(item
.GetPath(), *it
) : std::string
{};
209 bool IsAutoPlayNextItem(const CFileItem
& item
)
211 if (!item
.HasVideoInfoTag())
214 return IsAutoPlayNextItem(item
.GetVideoInfoTag()->m_type
);
217 bool IsAutoPlayNextItem(const std::string
& content
)
219 int settingValue
= CSettings::SETTING_AUTOPLAYNEXT_UNCATEGORIZED
;
220 if (content
== MediaTypeMovie
|| content
== MediaTypeMovies
||
221 content
== MediaTypeVideoCollections
)
222 settingValue
= CSettings::SETTING_AUTOPLAYNEXT_MOVIES
;
223 else if (content
== MediaTypeEpisode
|| content
== MediaTypeSeasons
||
224 content
== MediaTypeEpisodes
)
225 settingValue
= CSettings::SETTING_AUTOPLAYNEXT_EPISODES
;
226 else if (content
== MediaTypeMusicVideo
|| content
== MediaTypeMusicVideos
)
227 settingValue
= CSettings::SETTING_AUTOPLAYNEXT_MUSICVIDEOS
;
228 else if (content
== MediaTypeTvShow
|| content
== MediaTypeTvShows
)
229 settingValue
= CSettings::SETTING_AUTOPLAYNEXT_TVSHOWS
;
231 const auto setting
= std::dynamic_pointer_cast
<CSettingList
>(
232 CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(
233 CSettings::SETTING_VIDEOPLAYER_AUTOPLAYNEXTITEM
));
235 return setting
&& CSettingUtils::FindIntInList(setting
, settingValue
);
238 ResumeInformation
GetItemResumeInformation(const CFileItem
& item
)
240 ResumeInformation info
= GetNonFolderItemResumeInformation(item
);
241 if (info
.isResumable
)
244 return GetFolderItemResumeInformation(item
);
247 ResumeInformation
GetStackPartResumeInformation(const CFileItem
& item
, unsigned int partNumber
)
249 ResumeInformation resumeInfo
;
253 const std::string
& path
= item
.GetDynPath();
254 if (URIUtils::IsDiscImageStack(path
))
258 XFILE::CDirectory::GetDirectory(path
, parts
, "", XFILE::DIR_FLAG_DEFAULTS
);
260 resumeInfo
= GetItemResumeInformation(*parts
[partNumber
- 1]);
261 resumeInfo
.partNumber
= partNumber
;
269 CLog::LogF(LOGERROR
, "Cannot open VideoDatabase");
273 std::vector
<uint64_t> times
;
274 if (db
.GetStackTimes(path
, times
))
276 resumeInfo
.startOffset
= times
[partNumber
- 1];
277 resumeInfo
.isResumable
= (resumeInfo
.startOffset
> 0);
279 resumeInfo
.partNumber
= partNumber
;
285 } // namespace KODI::VIDEO::UTILS