[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / video / VideoUtils.cpp
blobeb6ab9674d3f37665323cc5ee7d4021eb8dff495
1 /*
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.
7 */
9 #include "VideoUtils.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "ServiceBroker.h"
14 #include "Util.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"
29 #include <algorithm>
30 #include <array>
31 #include <cstdint>
32 #include <vector>
34 using namespace KODI;
36 namespace
38 KODI::VIDEO::UTILS::ResumeInformation GetFolderItemResumeInformation(const CFileItem& item)
40 if (!item.m_bIsFolder)
41 return {};
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)))
49 CVideoDatabase db;
50 if (db.Open())
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()));
63 if (idSeason >= 0)
65 CVideoInfoTag details;
66 db.GetSeasonInfo(idSeason, details, &folderItem);
69 else
71 CVideoInfoTag details;
72 db.GetTvShowInfo(item.GetPath(), details, static_cast<int>(params.GetTvShowId()),
73 &folderItem);
76 else if (params.GetSetId() >= 0)
78 CVideoInfoTag details;
79 db.GetSetInfo(static_cast<int>(params.GetSetId()), details, &folderItem);
82 db.Close();
86 if (folderItem.IsResumable())
88 KODI::VIDEO::UTILS::ResumeInformation resumeInfo;
89 resumeInfo.isResumable = true;
90 return resumeInfo;
93 return {};
96 KODI::VIDEO::UTILS::ResumeInformation GetNonFolderItemResumeInformation(const CFileItem& item)
98 // do not resume nfo files
99 if (item.IsNFO())
100 return {};
102 // do not resume playlists, except strm files
103 if (!item.IsType(".strm") && PLAYLIST::IsPlayList(item))
104 return {};
106 // do not resume Live TV and 'deleted' items (e.g. trashed pvr recordings)
107 if (item.IsLiveTV() || item.IsDeleted())
108 return {};
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;
120 else
122 // Obtain the resume bookmark from video db...
124 CVideoDatabase db;
125 if (!db.Open())
127 CLog::LogF(LOGERROR, "Cannot open VideoDatabase");
128 return {};
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);
144 long id = -1;
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;
152 else
154 CLog::LogF(LOGERROR, "Cannot obtain video content type");
155 db.Close();
156 return {};
159 db.GetFilePathById(static_cast<int>(id), path, content_type);
161 else
163 // DVD
164 CLog::LogF(LOGERROR, "Cannot obtain bookmark for DVD");
165 db.Close();
166 return {};
170 CBookmark bookmark;
171 db.GetResumeBookMark(path, bookmark);
172 db.Close();
174 if (bookmark.IsSet())
176 resumeInfo.isResumable = bookmark.IsPartWay();
177 resumeInfo.startOffset = CUtil::ConvertSecsToMilliSecs(bookmark.timeInSeconds);
178 resumeInfo.partNumber = static_cast<int>(bookmark.partNumber);
181 return resumeInfo;
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,
202 #endif
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())
212 return false;
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)
242 return info;
244 return GetFolderItemResumeInformation(item);
247 ResumeInformation GetStackPartResumeInformation(const CFileItem& item, unsigned int partNumber)
249 ResumeInformation resumeInfo;
251 if (item.IsStack())
253 const std::string& path = item.GetDynPath();
254 if (URIUtils::IsDiscImageStack(path))
256 // disc image stack
257 CFileItemList parts;
258 XFILE::CDirectory::GetDirectory(path, parts, "", XFILE::DIR_FLAG_DEFAULTS);
260 resumeInfo = GetItemResumeInformation(*parts[partNumber - 1]);
261 resumeInfo.partNumber = partNumber;
263 else
265 // video file stack
266 CVideoDatabase db;
267 if (!db.Open())
269 CLog::LogF(LOGERROR, "Cannot open VideoDatabase");
270 return {};
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;
282 return resumeInfo;
285 } // namespace KODI::VIDEO::UTILS