Merge pull request #25977 from sarbes/estuary_optimization
[xbmc.git] / xbmc / video / guilib / VideoVersionHelper.cpp
blobfbe9bdb202ad7813a792345c5f5ef178a8a9b302
1 /*
2 * Copyright (C) 2023 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 "VideoVersionHelper.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "ServiceBroker.h"
14 #include "URL.h"
15 #include "dialogs/GUIDialogSelect.h"
16 #include "guilib/GUIComponent.h"
17 #include "guilib/GUIWindowManager.h"
18 #include "guilib/LocalizeStrings.h"
19 #include "settings/Settings.h"
20 #include "settings/SettingsComponent.h"
21 #include "settings/lib/Setting.h"
22 #include "utils/StringUtils.h"
23 #include "utils/log.h"
24 #include "video/VideoDatabase.h"
25 #include "video/VideoFileItemClassify.h"
26 #include "video/VideoManagerTypes.h"
27 #include "video/VideoThumbLoader.h"
29 namespace KODI::VIDEO::GUILIB
32 namespace
34 class CVideoChooser
36 public:
37 explicit CVideoChooser(const std::shared_ptr<const CFileItem>& item) : m_item(item) {}
38 virtual ~CVideoChooser() = default;
40 void EnableTypeSwitch(bool enable) { m_enableTypeSwitch = enable; }
41 void SetInitialAssetType(VideoAssetType type) { m_initialAssetType = type; }
43 std::shared_ptr<const CFileItem> ChooseVideo();
45 private:
46 CVideoChooser() = delete;
47 std::shared_ptr<const CFileItem> ChooseVideoVersion();
48 std::shared_ptr<const CFileItem> ChooseVideoExtra();
49 std::shared_ptr<const CFileItem> ChooseVideo(CGUIDialogSelect& dialog,
50 int headingId,
51 int buttonId,
52 CFileItemList& itemsToDisplay,
53 const CFileItemList& itemsToSwitchTo);
55 const std::shared_ptr<const CFileItem> m_item;
56 bool m_enableTypeSwitch{false};
57 VideoAssetType m_initialAssetType{VideoAssetType::UNKNOWN};
58 bool m_switchType{false};
59 CFileItemList m_videoVersions;
60 CFileItemList m_videoExtras;
63 std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideo()
65 m_switchType = false;
66 m_videoVersions.Clear();
67 m_videoExtras.Clear();
69 std::shared_ptr<const CFileItem> result;
70 if (m_enableTypeSwitch && !m_item->HasVideoVersions() && !m_item->HasVideoExtras())
71 return result;
73 if (!m_enableTypeSwitch && m_initialAssetType == VideoAssetType::VERSION &&
74 !m_item->HasVideoVersions())
75 return result;
77 if (!m_enableTypeSwitch && m_initialAssetType == VideoAssetType::EXTRA &&
78 !m_item->HasVideoExtras())
79 return result;
81 CVideoDatabase db;
82 if (!db.Open())
84 CLog::LogF(LOGERROR, "Unable to open video database!");
85 return result;
88 if (m_initialAssetType == VideoAssetType::VERSION || m_enableTypeSwitch)
90 db.GetAssetsForVideo(m_item->GetVideoContentType(), m_item->GetVideoInfoTag()->m_iDbId,
91 VideoAssetType::VERSION, m_videoVersions);
93 // find default version item in list and select it
94 for (const auto& item : m_videoVersions)
96 item->Select(item->GetVideoInfoTag()->IsDefaultVideoVersion());
100 if (m_initialAssetType == VideoAssetType::EXTRA || m_enableTypeSwitch)
101 db.GetAssetsForVideo(m_item->GetVideoContentType(), m_item->GetVideoInfoTag()->m_iDbId,
102 VideoAssetType::EXTRA, m_videoExtras);
104 VideoAssetType itemType{m_initialAssetType};
105 while (true)
107 if (itemType == VideoAssetType::VERSION)
109 result = ChooseVideoVersion();
110 itemType = VideoAssetType::EXTRA;
112 else
114 result = ChooseVideoExtra();
115 itemType = VideoAssetType::VERSION;
118 if (!m_switchType)
119 break;
121 // switch type button pressed. Re-open, this time with the "other" type to select.
123 return result;
126 std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideoVersion()
128 CGUIDialogSelect* dialog{CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(
129 WINDOW_DIALOG_SELECT_VIDEO_VERSION)};
130 if (!dialog)
132 CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_SELECT_VIDEO_VERSION dialog instance!");
133 return {};
136 return ChooseVideo(*dialog, 40208 /* Choose version */, 40211 /* Extras */, m_videoVersions,
137 m_videoExtras);
140 std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideoExtra()
142 CGUIDialogSelect* dialog{CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(
143 WINDOW_DIALOG_SELECT_VIDEO_EXTRA)};
144 if (!dialog)
146 CLog::LogF(LOGERROR, "Unable to get WINDOW_DIALOG_SELECT_VIDEO_EXTRA dialog instance!");
147 return {};
150 return ChooseVideo(*dialog, 40214 /* Choose extra */, 40210 /* Versions */, m_videoExtras,
151 m_videoVersions);
154 std::shared_ptr<const CFileItem> CVideoChooser::ChooseVideo(CGUIDialogSelect& dialog,
155 int headingId,
156 int buttonId,
157 CFileItemList& itemsToDisplay,
158 const CFileItemList& itemsToSwitchTo)
160 CVideoThumbLoader thumbLoader;
161 thumbLoader.Load(itemsToDisplay);
162 for (auto& item : itemsToDisplay)
163 item->SetLabel2(item->GetVideoInfoTag()->m_strFileNameAndPath);
165 dialog.Reset();
167 const std::string heading{
168 StringUtils::Format(g_localizeStrings.Get(headingId), m_item->GetVideoInfoTag()->GetTitle())};
169 dialog.SetHeading(heading);
171 dialog.EnableButton(m_enableTypeSwitch && !itemsToSwitchTo.IsEmpty(), buttonId);
172 dialog.SetUseDetails(true);
173 dialog.SetMultiSelection(false);
174 dialog.SetItems(itemsToDisplay);
176 dialog.Open();
178 if (thumbLoader.IsLoading())
179 thumbLoader.StopThread();
181 m_switchType = dialog.IsButtonPressed();
182 if (dialog.IsConfirmed())
183 return dialog.GetSelectedFileItem();
185 return {};
187 } // unnamed namespace
189 std::shared_ptr<CFileItem> CVideoVersionHelper::ChooseVideoFromAssets(
190 const std::shared_ptr<CFileItem>& item)
192 std::shared_ptr<const CFileItem> video;
194 VideoAssetType assetType{static_cast<int>(
195 item->GetProperty("video_asset_type").asInteger(static_cast<int>(VideoAssetType::UNKNOWN)))};
196 bool allAssetTypes{false};
197 bool hasMultipleChoices{false};
199 switch (assetType)
201 case VideoAssetType::UNKNOWN:
202 // asset type not provided means all types are allowed and the user can switch between types
203 allAssetTypes = true;
204 if (item->HasVideoVersions() || item->HasVideoExtras())
205 hasMultipleChoices = true;
206 break;
208 case VideoAssetType::VERSION:
209 if (item->HasVideoVersions())
210 hasMultipleChoices = true;
211 break;
213 case VideoAssetType::EXTRA:
214 if (item->HasVideoExtras())
215 hasMultipleChoices = true;
216 break;
218 default:
219 CLog::LogF(LOGERROR, "unknown asset type ({})", static_cast<int>(assetType));
220 return {};
223 if (hasMultipleChoices)
225 if (!item->GetProperty("needs_resolved_video_asset").asBoolean(false))
227 // auto select the default video version
228 const auto settings{CServiceBroker::GetSettingsComponent()->GetSettings()};
229 if (settings->GetBool(CSettings::SETTING_MYVIDEOS_SELECTDEFAULTVERSION))
231 if (item->GetVideoInfoTag()->IsDefaultVideoVersion())
233 video = std::make_shared<const CFileItem>(*item);
235 else
237 CVideoDatabase db;
238 if (!db.Open())
240 CLog::LogF(LOGERROR, "Unable to open video database!");
242 else
244 CFileItem defaultVersion;
245 if (!db.GetDefaultVersionForVideo(item->GetVideoContentType(),
246 item->GetVideoInfoTag()->m_iDbId, defaultVersion))
247 CLog::LogF(LOGERROR, "Unable to get default version from video database!");
248 else
249 video = std::make_shared<const CFileItem>(defaultVersion);
255 if (!video && (item->GetProperty("needs_resolved_video_asset").asBoolean(false) ||
256 !item->GetProperty("has_resolved_video_asset").asBoolean(false)))
258 CVideoChooser chooser{item};
260 if (allAssetTypes)
262 chooser.EnableTypeSwitch(true);
263 chooser.SetInitialAssetType(VideoAssetType::VERSION);
265 else
267 chooser.EnableTypeSwitch(false);
268 chooser.SetInitialAssetType(assetType);
271 const auto result{chooser.ChooseVideo()};
272 if (result)
273 video = result;
274 else
275 return {};
279 if (video)
280 return std::make_shared<CFileItem>(*video);
282 return item;
285 } // namespace KODI::VIDEO::GUILIB