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.
9 #include "VideoVersionHelper.h"
12 #include "ServiceBroker.h"
14 #include "dialogs/GUIDialogSelect.h"
15 #include "guilib/GUIComponent.h"
16 #include "guilib/GUIWindowManager.h"
17 #include "guilib/LocalizeStrings.h"
18 #include "settings/Settings.h"
19 #include "settings/SettingsComponent.h"
20 #include "settings/lib/Setting.h"
21 #include "utils/StringUtils.h"
22 #include "utils/log.h"
23 #include "video/VideoDatabase.h"
24 #include "video/VideoManagerTypes.h"
25 #include "video/VideoThumbLoader.h"
27 using namespace VIDEO::GUILIB
;
34 explicit CVideoChooser(const std::shared_ptr
<const CFileItem
>& item
) : m_item(item
) {}
35 virtual ~CVideoChooser() = default;
37 void EnableTypeSwitch(bool enable
) { m_enableTypeSwitch
= enable
; }
38 void SetInitialAssetType(VideoAssetType type
) { m_initialAssetType
= type
; }
40 std::shared_ptr
<const CFileItem
> ChooseVideo();
43 CVideoChooser() = delete;
44 std::shared_ptr
<const CFileItem
> ChooseVideoVersion();
45 std::shared_ptr
<const CFileItem
> ChooseVideoExtra();
46 std::shared_ptr
<const CFileItem
> ChooseVideo(CGUIDialogSelect
& dialog
,
49 CFileItemList
& itemsToDisplay
,
50 const CFileItemList
& itemsToSwitchTo
);
52 const std::shared_ptr
<const CFileItem
> m_item
;
53 bool m_enableTypeSwitch
{false};
54 VideoAssetType m_initialAssetType
{VideoAssetType::UNKNOWN
};
55 bool m_switchType
{false};
56 CFileItemList m_videoVersions
;
57 CFileItemList m_videoExtras
;
60 std::shared_ptr
<const CFileItem
> CVideoChooser::ChooseVideo()
63 m_videoVersions
.Clear();
64 m_videoExtras
.Clear();
66 std::shared_ptr
<const CFileItem
> result
;
67 if (m_enableTypeSwitch
&& !m_item
->HasVideoVersions() && !m_item
->HasVideoExtras())
70 if (!m_enableTypeSwitch
&& m_initialAssetType
== VideoAssetType::VERSION
&&
71 !m_item
->HasVideoVersions())
74 if (!m_enableTypeSwitch
&& m_initialAssetType
== VideoAssetType::EXTRA
&&
75 !m_item
->HasVideoExtras())
81 CLog::LogF(LOGERROR
, "Unable to open video database!");
85 if (m_initialAssetType
== VideoAssetType::VERSION
|| m_enableTypeSwitch
)
87 db
.GetAssetsForVideo(m_item
->GetVideoContentType(), m_item
->GetVideoInfoTag()->m_iDbId
,
88 VideoAssetType::VERSION
, m_videoVersions
);
90 // find default version item in list and select it
91 for (const auto& item
: m_videoVersions
)
93 item
->Select(item
->GetVideoInfoTag()->IsDefaultVideoVersion());
97 if (m_initialAssetType
== VideoAssetType::EXTRA
|| m_enableTypeSwitch
)
98 db
.GetAssetsForVideo(m_item
->GetVideoContentType(), m_item
->GetVideoInfoTag()->m_iDbId
,
99 VideoAssetType::EXTRA
, m_videoExtras
);
101 VideoAssetType itemType
{m_initialAssetType
};
104 if (itemType
== VideoAssetType::VERSION
)
106 result
= ChooseVideoVersion();
107 itemType
= VideoAssetType::EXTRA
;
111 result
= ChooseVideoExtra();
112 itemType
= VideoAssetType::VERSION
;
118 // switch type button pressed. Re-open, this time with the "other" type to select.
123 std::shared_ptr
<const CFileItem
> CVideoChooser::ChooseVideoVersion()
125 CGUIDialogSelect
* dialog
{CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogSelect
>(
126 WINDOW_DIALOG_SELECT_VIDEO_VERSION
)};
129 CLog::LogF(LOGERROR
, "Unable to get WINDOW_DIALOG_SELECT_VIDEO_VERSION dialog instance!");
133 return ChooseVideo(*dialog
, 40208 /* Choose version */, 40211 /* Extras */, m_videoVersions
,
137 std::shared_ptr
<const CFileItem
> CVideoChooser::ChooseVideoExtra()
139 CGUIDialogSelect
* dialog
{CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogSelect
>(
140 WINDOW_DIALOG_SELECT_VIDEO_EXTRA
)};
143 CLog::LogF(LOGERROR
, "Unable to get WINDOW_DIALOG_SELECT_VIDEO_EXTRA dialog instance!");
147 return ChooseVideo(*dialog
, 40214 /* Choose extra */, 40210 /* Versions */, m_videoExtras
,
151 std::shared_ptr
<const CFileItem
> CVideoChooser::ChooseVideo(CGUIDialogSelect
& dialog
,
154 CFileItemList
& itemsToDisplay
,
155 const CFileItemList
& itemsToSwitchTo
)
157 CVideoThumbLoader thumbLoader
;
158 thumbLoader
.Load(itemsToDisplay
);
159 for (auto& item
: itemsToDisplay
)
160 item
->SetLabel2(item
->GetVideoInfoTag()->m_strFileNameAndPath
);
164 const std::string heading
{
165 StringUtils::Format(g_localizeStrings
.Get(headingId
), m_item
->GetVideoInfoTag()->GetTitle())};
166 dialog
.SetHeading(heading
);
168 dialog
.EnableButton(m_enableTypeSwitch
&& !itemsToSwitchTo
.IsEmpty(), buttonId
);
169 dialog
.SetUseDetails(true);
170 dialog
.SetMultiSelection(false);
171 dialog
.SetItems(itemsToDisplay
);
175 if (thumbLoader
.IsLoading())
176 thumbLoader
.StopThread();
178 m_switchType
= dialog
.IsButtonPressed();
179 if (dialog
.IsConfirmed())
180 return dialog
.GetSelectedFileItem();
184 } // unnamed namespace
186 std::shared_ptr
<CFileItem
> CVideoVersionHelper::ChooseVideoFromAssets(
187 const std::shared_ptr
<CFileItem
>& item
)
189 std::shared_ptr
<const CFileItem
> video
;
191 VideoAssetType assetType
{static_cast<int>(
192 item
->GetProperty("video_asset_type").asInteger(static_cast<int>(VideoAssetType::UNKNOWN
)))};
193 bool allAssetTypes
{false};
194 bool hasMultipleChoices
{false};
198 case VideoAssetType::UNKNOWN
:
199 // asset type not provided means all types are allowed and the user can switch between types
200 allAssetTypes
= true;
201 if (item
->HasVideoVersions() || item
->HasVideoExtras())
202 hasMultipleChoices
= true;
205 case VideoAssetType::VERSION
:
206 if (item
->HasVideoVersions())
207 hasMultipleChoices
= true;
210 case VideoAssetType::EXTRA
:
211 if (item
->HasVideoExtras())
212 hasMultipleChoices
= true;
216 CLog::LogF(LOGERROR
, "unknown asset type ({})", static_cast<int>(assetType
));
220 if (hasMultipleChoices
)
222 if (!item
->GetProperty("needs_resolved_video_asset").asBoolean(false))
224 // auto select the default video version
225 const auto settings
{CServiceBroker::GetSettingsComponent()->GetSettings()};
226 if (settings
->GetBool(CSettings::SETTING_MYVIDEOS_SELECTDEFAULTVERSION
))
228 if (item
->GetVideoInfoTag()->IsDefaultVideoVersion())
230 video
= std::make_shared
<const CFileItem
>(*item
);
237 CLog::LogF(LOGERROR
, "Unable to open video database!");
241 CFileItem defaultVersion
;
242 if (!db
.GetDefaultVersionForVideo(item
->GetVideoContentType(),
243 item
->GetVideoInfoTag()->m_iDbId
, defaultVersion
))
244 CLog::LogF(LOGERROR
, "Unable to get default version from video database!");
246 video
= std::make_shared
<const CFileItem
>(defaultVersion
);
252 if (!video
&& (item
->GetProperty("needs_resolved_video_asset").asBoolean(false) ||
253 !item
->GetProperty("has_resolved_video_asset").asBoolean(false)))
255 CVideoChooser chooser
{item
};
259 chooser
.EnableTypeSwitch(true);
260 chooser
.SetInitialAssetType(VideoAssetType::VERSION
);
264 chooser
.EnableTypeSwitch(false);
265 chooser
.SetInitialAssetType(assetType
);
268 const auto result
{chooser
.ChooseVideo()};
277 return std::make_shared
<CFileItem
>(*video
);
282 bool VIDEO::IsVideoAssetFile(const CFileItem
& item
)
284 if (item
.m_bIsFolder
|| !item
.IsVideoDb())
287 // @todo maybe in the future look for prefix videodb://movies/videoversions in path instead
288 // @todo better encoding of video assets as path, they won't always be tied with movies.
289 const CURL itemUrl
{item
.GetPath()};
290 if (itemUrl
.HasOption("videoversionid"))