[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / pvr / epg / EpgInfoTag.cpp
bloba21894b64c7f432c4191efe22eff0cf7bdedff8d
1 /*
2 * Copyright (C) 2012-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.
7 */
9 #include "EpgInfoTag.h"
11 #include "ServiceBroker.h"
12 #include "pvr/PVRManager.h"
13 #include "pvr/PVRPlaybackState.h"
14 #include "pvr/addons/PVRClient.h"
15 #include "pvr/epg/Epg.h"
16 #include "pvr/epg/EpgChannelData.h"
17 #include "pvr/epg/EpgDatabase.h"
18 #include "settings/AdvancedSettings.h"
19 #include "settings/SettingsComponent.h"
20 #include "utils/StringUtils.h"
21 #include "utils/Variant.h"
22 #include "utils/log.h"
24 #include <memory>
25 #include <mutex>
26 #include <string>
27 #include <vector>
29 using namespace PVR;
31 const std::string CPVREpgInfoTag::IMAGE_OWNER_PATTERN = "epgtag_{}";
33 CPVREpgInfoTag::CPVREpgInfoTag(int iEpgID, const std::string& iconPath)
34 : m_iUniqueBroadcastID(EPG_TAG_INVALID_UID),
35 m_iconPath(iconPath, StringUtils::Format(IMAGE_OWNER_PATTERN, iEpgID)),
36 m_iFlags(EPG_TAG_FLAG_UNDEFINED),
37 m_channelData(new CPVREpgChannelData),
38 m_iEpgID(iEpgID)
42 CPVREpgInfoTag::CPVREpgInfoTag(const std::shared_ptr<CPVREpgChannelData>& channelData,
43 int iEpgID,
44 const CDateTime& start,
45 const CDateTime& end,
46 bool bIsGapTag)
47 : m_iUniqueBroadcastID(EPG_TAG_INVALID_UID),
48 m_iconPath(StringUtils::Format(IMAGE_OWNER_PATTERN, iEpgID)),
49 m_iFlags(EPG_TAG_FLAG_UNDEFINED),
50 m_bIsGapTag(bIsGapTag),
51 m_iEpgID(iEpgID)
53 if (channelData)
54 m_channelData = channelData;
55 else
56 m_channelData = std::make_shared<CPVREpgChannelData>();
58 const CDateTimeSpan correction(
59 0, 0, 0, CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iPVRTimeCorrection);
60 m_startTime = start + correction;
61 m_endTime = end + correction;
64 CPVREpgInfoTag::CPVREpgInfoTag(const EPG_TAG& data,
65 int iClientId,
66 const std::shared_ptr<CPVREpgChannelData>& channelData,
67 int iEpgID)
68 : m_iGenreType(data.iGenreType),
69 m_iGenreSubType(data.iGenreSubType),
70 m_iParentalRating(data.iParentalRating),
71 m_iStarRating(data.iStarRating),
72 m_iSeriesNumber(data.iSeriesNumber),
73 m_iEpisodeNumber(data.iEpisodeNumber),
74 m_iEpisodePart(data.iEpisodePartNumber),
75 m_iUniqueBroadcastID(data.iUniqueBroadcastId),
76 m_iYear(data.iYear),
77 m_iconPath(data.strIconPath ? data.strIconPath : "",
78 StringUtils::Format(IMAGE_OWNER_PATTERN, iEpgID)),
79 m_startTime(
80 data.startTime +
81 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iPVRTimeCorrection),
82 m_endTime(data.endTime +
83 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iPVRTimeCorrection),
84 m_iFlags(data.iFlags),
85 m_iEpgID(iEpgID)
87 // strFirstAired is optional, so check if supported before assigning it
88 if (data.strFirstAired && strlen(data.strFirstAired) > 0)
89 m_firstAired.SetFromW3CDate(data.strFirstAired);
91 if (channelData)
93 m_channelData = channelData;
95 if (m_channelData->ClientId() != iClientId)
96 CLog::LogF(LOGERROR, "Client id mismatch (channel: {}, epg: {})!", m_channelData->ClientId(),
97 iClientId);
98 if (m_channelData->UniqueClientChannelId() != static_cast<int>(data.iUniqueChannelId))
99 CLog::LogF(LOGERROR, "Channel uid mismatch (channel: {}, epg: {})!",
100 m_channelData->UniqueClientChannelId(), data.iUniqueChannelId);
102 else
104 // provide minimalistic channel data until we get fully initialized later
105 m_channelData = std::make_shared<CPVREpgChannelData>(iClientId, data.iUniqueChannelId);
108 // explicit NULL check, because there is no implicit NULL constructor for std::string
109 if (data.strTitle)
110 m_strTitle = data.strTitle;
111 if (data.strGenreDescription)
112 m_strGenreDescription = data.strGenreDescription;
113 if (data.strPlotOutline)
114 m_strPlotOutline = data.strPlotOutline;
115 if (data.strPlot)
116 m_strPlot = data.strPlot;
117 if (data.strOriginalTitle)
118 m_strOriginalTitle = data.strOriginalTitle;
119 if (data.strCast)
120 m_cast = Tokenize(data.strCast);
121 if (data.strDirector)
122 m_directors = Tokenize(data.strDirector);
123 if (data.strWriter)
124 m_writers = Tokenize(data.strWriter);
125 if (data.strIMDBNumber)
126 m_strIMDBNumber = data.strIMDBNumber;
127 if (data.strEpisodeName)
128 m_strEpisodeName = data.strEpisodeName;
129 if (data.strSeriesLink)
130 m_strSeriesLink = data.strSeriesLink;
131 if (data.strParentalRatingCode)
132 m_strParentalRatingCode = data.strParentalRatingCode;
135 void CPVREpgInfoTag::SetChannelData(const std::shared_ptr<CPVREpgChannelData>& data)
137 std::unique_lock<CCriticalSection> lock(m_critSection);
138 if (data)
139 m_channelData = data;
140 else
141 m_channelData = std::make_shared<CPVREpgChannelData>();
144 bool CPVREpgInfoTag::operator==(const CPVREpgInfoTag& right) const
146 if (this == &right)
147 return true;
149 std::unique_lock<CCriticalSection> lock(m_critSection);
150 return (m_iUniqueBroadcastID == right.m_iUniqueBroadcastID && m_channelData &&
151 right.m_channelData &&
152 m_channelData->UniqueClientChannelId() == right.m_channelData->UniqueClientChannelId() &&
153 m_channelData->ClientId() == right.m_channelData->ClientId());
156 bool CPVREpgInfoTag::operator!=(const CPVREpgInfoTag& right) const
158 if (this == &right)
159 return false;
161 return !(*this == right);
164 void CPVREpgInfoTag::Serialize(CVariant& value) const
166 std::unique_lock<CCriticalSection> lock(m_critSection);
167 value["broadcastid"] = m_iDatabaseID; // Use DB id here as it is unique across PVR clients
168 value["channeluid"] = m_channelData->UniqueClientChannelId();
169 value["parentalrating"] = m_iParentalRating;
170 value["parentalratingcode"] = m_strParentalRatingCode;
171 value["rating"] = m_iStarRating;
172 value["title"] = m_strTitle;
173 value["plotoutline"] = m_strPlotOutline;
174 value["plot"] = m_strPlot;
175 value["originaltitle"] = m_strOriginalTitle;
176 value["thumbnail"] = ClientIconPath();
177 value["cast"] = DeTokenize(m_cast);
178 value["director"] = DeTokenize(m_directors);
179 value["writer"] = DeTokenize(m_writers);
180 value["year"] = m_iYear;
181 value["imdbnumber"] = m_strIMDBNumber;
182 value["genre"] = Genre();
183 value["filenameandpath"] = Path();
184 value["starttime"] = m_startTime.IsValid() ? m_startTime.GetAsDBDateTime() : StringUtils::Empty;
185 value["endtime"] = m_endTime.IsValid() ? m_endTime.GetAsDBDateTime() : StringUtils::Empty;
186 value["runtime"] = GetDuration() / 60;
187 value["firstaired"] = m_firstAired.IsValid() ? m_firstAired.GetAsDBDate() : StringUtils::Empty;
188 value["progress"] = Progress();
189 value["progresspercentage"] = ProgressPercentage();
190 value["episodename"] = m_strEpisodeName;
191 value["episodenum"] = m_iEpisodeNumber;
192 value["episodepart"] = m_iEpisodePart;
193 value["seasonnum"] = m_iSeriesNumber;
194 value["isactive"] = IsActive();
195 value["wasactive"] = WasActive();
196 value["isseries"] = IsSeries();
197 value["serieslink"] = m_strSeriesLink;
198 value["clientid"] = m_channelData->ClientId();
201 int CPVREpgInfoTag::ClientID() const
203 std::unique_lock<CCriticalSection> lock(m_critSection);
204 return m_channelData->ClientId();
207 CDateTime CPVREpgInfoTag::GetCurrentPlayingTime() const
209 return CServiceBroker::GetPVRManager().PlaybackState()->GetChannelPlaybackTime(ClientID(),
210 UniqueChannelID());
213 bool CPVREpgInfoTag::IsActive() const
215 CDateTime now = GetCurrentPlayingTime();
216 return (m_startTime <= now && m_endTime > now);
219 bool CPVREpgInfoTag::WasActive() const
221 CDateTime now = GetCurrentPlayingTime();
222 return (m_endTime < now);
225 bool CPVREpgInfoTag::IsUpcoming() const
227 CDateTime now = GetCurrentPlayingTime();
228 return (m_startTime > now);
231 float CPVREpgInfoTag::ProgressPercentage() const
233 float fReturn = 0.0f;
235 time_t currentTime, startTime, endTime;
236 CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(currentTime);
237 m_startTime.GetAsTime(startTime);
238 m_endTime.GetAsTime(endTime);
239 int iDuration = endTime - startTime > 0 ? endTime - startTime : 3600;
241 if (currentTime >= startTime && currentTime <= endTime)
242 fReturn = static_cast<float>(currentTime - startTime) * 100.0f / iDuration;
243 else if (currentTime > endTime)
244 fReturn = 100.0f;
246 return fReturn;
249 int CPVREpgInfoTag::Progress() const
251 time_t currentTime, startTime;
252 CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(currentTime);
253 m_startTime.GetAsTime(startTime);
254 int iDuration = currentTime - startTime;
256 if (iDuration <= 0)
257 return 0;
259 return iDuration;
262 void CPVREpgInfoTag::SetUniqueBroadcastID(unsigned int iUniqueBroadcastID)
264 m_iUniqueBroadcastID = iUniqueBroadcastID;
267 unsigned int CPVREpgInfoTag::UniqueBroadcastID() const
269 return m_iUniqueBroadcastID;
272 int CPVREpgInfoTag::DatabaseID() const
274 return m_iDatabaseID;
277 int CPVREpgInfoTag::UniqueChannelID() const
279 std::unique_lock<CCriticalSection> lock(m_critSection);
280 return m_channelData->UniqueClientChannelId();
283 std::string CPVREpgInfoTag::ChannelIconPath() const
285 std::unique_lock<CCriticalSection> lock(m_critSection);
286 return m_channelData->ChannelIconPath();
289 CDateTime CPVREpgInfoTag::StartAsUTC() const
291 return m_startTime;
294 CDateTime CPVREpgInfoTag::StartAsLocalTime() const
296 CDateTime retVal;
297 retVal.SetFromUTCDateTime(m_startTime);
298 return retVal;
301 CDateTime CPVREpgInfoTag::EndAsUTC() const
303 return m_endTime;
306 CDateTime CPVREpgInfoTag::EndAsLocalTime() const
308 CDateTime retVal;
309 retVal.SetFromUTCDateTime(m_endTime);
310 return retVal;
313 void CPVREpgInfoTag::SetEndFromUTC(const CDateTime& end)
315 m_endTime = end;
318 int CPVREpgInfoTag::GetDuration() const
320 time_t start, end;
321 m_startTime.GetAsTime(start);
322 m_endTime.GetAsTime(end);
323 return end - start > 0 ? end - start : 3600;
326 std::string CPVREpgInfoTag::Title() const
328 return m_strTitle;
331 std::string CPVREpgInfoTag::PlotOutline() const
333 return m_strPlotOutline;
336 std::string CPVREpgInfoTag::Plot() const
338 return m_strPlot;
341 std::string CPVREpgInfoTag::OriginalTitle() const
343 return m_strOriginalTitle;
346 const std::vector<std::string> CPVREpgInfoTag::Cast() const
348 return m_cast;
351 const std::vector<std::string> CPVREpgInfoTag::Directors() const
353 return m_directors;
356 const std::vector<std::string> CPVREpgInfoTag::Writers() const
358 return m_writers;
361 const std::string CPVREpgInfoTag::GetCastLabel() const
363 // Note: see CVideoInfoTag::GetCast for reference implementation.
364 std::string strLabel;
365 for (const auto& castEntry : m_cast)
366 strLabel += StringUtils::Format("{}\n", castEntry);
368 return StringUtils::TrimRight(strLabel, "\n");
371 const std::string CPVREpgInfoTag::GetDirectorsLabel() const
373 return StringUtils::Join(
374 m_directors,
375 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
378 const std::string CPVREpgInfoTag::GetWritersLabel() const
380 return StringUtils::Join(
381 m_writers,
382 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
385 const std::string CPVREpgInfoTag::GetGenresLabel() const
387 return StringUtils::Join(
388 Genre(), CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoItemSeparator);
391 int CPVREpgInfoTag::Year() const
393 return m_iYear;
396 std::string CPVREpgInfoTag::IMDBNumber() const
398 return m_strIMDBNumber;
401 int CPVREpgInfoTag::GenreType() const
403 return m_iGenreType;
406 int CPVREpgInfoTag::GenreSubType() const
408 return m_iGenreSubType;
411 std::string CPVREpgInfoTag::GenreDescription() const
413 return m_strGenreDescription;
416 const std::vector<std::string> CPVREpgInfoTag::Genre() const
418 if (m_genre.empty())
420 if ((m_iGenreType == EPG_GENRE_USE_STRING || m_iGenreSubType == EPG_GENRE_USE_STRING) &&
421 !m_strGenreDescription.empty())
423 // Type and sub type are both not given. No EPG color coding possible unless sub type is
424 // used to specify EPG_GENRE_USE_STRING leaving type available for genre category, use the
425 // provided genre description for the text.
426 m_genre = Tokenize(m_strGenreDescription);
429 if (m_genre.empty())
431 // Determine the genre from the type and subtype IDs.
432 m_genre = Tokenize(CPVREpg::ConvertGenreIdToString(m_iGenreType, m_iGenreSubType));
435 return m_genre;
438 CDateTime CPVREpgInfoTag::FirstAired() const
440 return m_firstAired;
443 int CPVREpgInfoTag::ParentalRating() const
445 return m_iParentalRating;
448 std::string CPVREpgInfoTag::ParentalRatingCode() const
450 return m_strParentalRatingCode;
453 int CPVREpgInfoTag::StarRating() const
455 return m_iStarRating;
458 int CPVREpgInfoTag::SeriesNumber() const
460 return m_iSeriesNumber;
463 std::string CPVREpgInfoTag::SeriesLink() const
465 return m_strSeriesLink;
468 int CPVREpgInfoTag::EpisodeNumber() const
470 return m_iEpisodeNumber;
473 int CPVREpgInfoTag::EpisodePart() const
475 return m_iEpisodePart;
478 std::string CPVREpgInfoTag::EpisodeName() const
480 return m_strEpisodeName;
483 std::string CPVREpgInfoTag::IconPath() const
485 return m_iconPath.GetLocalImage();
488 std::string CPVREpgInfoTag::ClientIconPath() const
490 return m_iconPath.GetClientImage();
493 std::string CPVREpgInfoTag::Path() const
495 return StringUtils::Format("pvr://guide/{:04}/{}.epg", EpgID(), m_startTime.GetAsDBDateTime());
498 bool CPVREpgInfoTag::Update(const CPVREpgInfoTag& tag, bool bUpdateBroadcastId /* = true */)
500 std::unique_lock<CCriticalSection> lock(m_critSection);
501 bool bChanged =
502 (m_strTitle != tag.m_strTitle || m_strPlotOutline != tag.m_strPlotOutline ||
503 m_strPlot != tag.m_strPlot || m_strOriginalTitle != tag.m_strOriginalTitle ||
504 m_cast != tag.m_cast || m_directors != tag.m_directors || m_writers != tag.m_writers ||
505 m_iYear != tag.m_iYear || m_strIMDBNumber != tag.m_strIMDBNumber ||
506 m_startTime != tag.m_startTime || m_endTime != tag.m_endTime ||
507 m_iGenreType != tag.m_iGenreType || m_iGenreSubType != tag.m_iGenreSubType ||
508 m_strGenreDescription != tag.m_strGenreDescription || m_firstAired != tag.m_firstAired ||
509 m_iParentalRating != tag.m_iParentalRating ||
510 m_strParentalRatingCode != tag.m_strParentalRatingCode ||
511 m_iStarRating != tag.m_iStarRating || m_iEpisodeNumber != tag.m_iEpisodeNumber ||
512 m_iEpisodePart != tag.m_iEpisodePart || m_iSeriesNumber != tag.m_iSeriesNumber ||
513 m_strEpisodeName != tag.m_strEpisodeName ||
514 m_iUniqueBroadcastID != tag.m_iUniqueBroadcastID || m_iEpgID != tag.m_iEpgID ||
515 m_genre != tag.m_genre || m_iconPath != tag.m_iconPath || m_iFlags != tag.m_iFlags ||
516 m_strSeriesLink != tag.m_strSeriesLink || m_channelData != tag.m_channelData);
518 if (bUpdateBroadcastId)
519 bChanged |= (m_iDatabaseID != tag.m_iDatabaseID);
521 if (bChanged)
523 if (bUpdateBroadcastId)
524 m_iDatabaseID = tag.m_iDatabaseID;
526 m_strTitle = tag.m_strTitle;
527 m_strPlotOutline = tag.m_strPlotOutline;
528 m_strPlot = tag.m_strPlot;
529 m_strOriginalTitle = tag.m_strOriginalTitle;
530 m_cast = tag.m_cast;
531 m_directors = tag.m_directors;
532 m_writers = tag.m_writers;
533 m_iYear = tag.m_iYear;
534 m_strIMDBNumber = tag.m_strIMDBNumber;
535 m_startTime = tag.m_startTime;
536 m_endTime = tag.m_endTime;
537 m_iGenreType = tag.m_iGenreType;
538 m_iGenreSubType = tag.m_iGenreSubType;
539 m_strGenreDescription = tag.m_strGenreDescription;
540 m_genre = tag.m_genre;
541 m_iEpgID = tag.m_iEpgID;
542 m_iFlags = tag.m_iFlags;
543 m_strSeriesLink = tag.m_strSeriesLink;
544 m_firstAired = tag.m_firstAired;
545 m_iParentalRating = tag.m_iParentalRating;
546 m_strParentalRatingCode = tag.m_strParentalRatingCode;
547 m_iStarRating = tag.m_iStarRating;
548 m_iEpisodeNumber = tag.m_iEpisodeNumber;
549 m_iEpisodePart = tag.m_iEpisodePart;
550 m_iSeriesNumber = tag.m_iSeriesNumber;
551 m_strEpisodeName = tag.m_strEpisodeName;
552 m_iUniqueBroadcastID = tag.m_iUniqueBroadcastID;
553 m_iconPath = tag.m_iconPath;
554 m_channelData = tag.m_channelData;
557 return bChanged;
560 bool CPVREpgInfoTag::QueuePersistQuery(const std::shared_ptr<CPVREpgDatabase>& database)
562 if (!database)
564 CLog::LogF(LOGERROR, "Could not open the EPG database");
565 return false;
568 return database->QueuePersistQuery(*this);
571 std::vector<PVR_EDL_ENTRY> CPVREpgInfoTag::GetEdl() const
573 std::vector<PVR_EDL_ENTRY> edls;
575 std::unique_lock<CCriticalSection> lock(m_critSection);
576 const std::shared_ptr<const CPVRClient> client =
577 CServiceBroker::GetPVRManager().GetClient(m_channelData->ClientId());
579 if (client && client->GetClientCapabilities().SupportsEpgTagEdl())
580 client->GetEpgTagEdl(shared_from_this(), edls);
582 return edls;
585 int CPVREpgInfoTag::EpgID() const
587 return m_iEpgID;
590 void CPVREpgInfoTag::SetEpgID(int iEpgID)
592 m_iEpgID = iEpgID;
593 m_iconPath.SetOwner(StringUtils::Format(IMAGE_OWNER_PATTERN, m_iEpgID));
596 bool CPVREpgInfoTag::IsRecordable() const
598 bool bIsRecordable = false;
600 std::unique_lock<CCriticalSection> lock(m_critSection);
601 const std::shared_ptr<const CPVRClient> client =
602 CServiceBroker::GetPVRManager().GetClient(m_channelData->ClientId());
603 if (!client || (client->IsRecordable(shared_from_this(), bIsRecordable) != PVR_ERROR_NO_ERROR))
605 // event end time based fallback
606 bIsRecordable = EndAsLocalTime() > CDateTime::GetCurrentDateTime();
608 return bIsRecordable;
611 bool CPVREpgInfoTag::IsPlayable() const
613 bool bIsPlayable = false;
615 std::unique_lock<CCriticalSection> lock(m_critSection);
616 const std::shared_ptr<const CPVRClient> client =
617 CServiceBroker::GetPVRManager().GetClient(m_channelData->ClientId());
618 if (!client || (client->IsPlayable(shared_from_this(), bIsPlayable) != PVR_ERROR_NO_ERROR))
620 // fallback
621 bIsPlayable = false;
623 return bIsPlayable;
626 bool CPVREpgInfoTag::IsSeries() const
628 if ((m_iFlags & EPG_TAG_FLAG_IS_SERIES) > 0 || SeriesNumber() >= 0 || EpisodeNumber() >= 0 ||
629 EpisodePart() >= 0)
630 return true;
631 else
632 return false;
635 bool CPVREpgInfoTag::IsRadio() const
637 std::unique_lock<CCriticalSection> lock(m_critSection);
638 return m_channelData->IsRadio();
641 bool CPVREpgInfoTag::IsParentalLocked() const
643 std::unique_lock<CCriticalSection> lock(m_critSection);
644 return m_channelData->IsLocked();
647 bool CPVREpgInfoTag::IsGapTag() const
649 std::unique_lock<CCriticalSection> lock(m_critSection);
650 return m_bIsGapTag;
653 bool CPVREpgInfoTag::IsNew() const
655 return (m_iFlags & EPG_TAG_FLAG_IS_NEW) > 0;
658 bool CPVREpgInfoTag::IsPremiere() const
660 return (m_iFlags & EPG_TAG_FLAG_IS_PREMIERE) > 0;
663 bool CPVREpgInfoTag::IsFinale() const
665 return (m_iFlags & EPG_TAG_FLAG_IS_FINALE) > 0;
668 bool CPVREpgInfoTag::IsLive() const
670 return (m_iFlags & EPG_TAG_FLAG_IS_LIVE) > 0;
673 const std::vector<std::string> CPVREpgInfoTag::Tokenize(const std::string& str)
675 return StringUtils::Split(str, EPG_STRING_TOKEN_SEPARATOR);
678 const std::string CPVREpgInfoTag::DeTokenize(const std::vector<std::string>& tokens)
680 return StringUtils::Join(tokens, EPG_STRING_TOKEN_SEPARATOR);