summaryrefslogtreecommitdiffstats
path: root/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp')
-rw-r--r--xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp2017
1 files changed, 2017 insertions, 0 deletions
diff --git a/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp b/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp
new file mode 100644
index 0000000..9cffb9a
--- /dev/null
+++ b/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp
@@ -0,0 +1,2017 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "PVRGUIInfo.h"
+
+#include "FileItem.h"
+#include "GUIInfoManager.h"
+#include "ServiceBroker.h"
+#include "application/Application.h"
+#include "application/ApplicationComponents.h"
+#include "application/ApplicationPlayer.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "guilib/guiinfo/GUIInfo.h"
+#include "guilib/guiinfo/GUIInfoLabels.h"
+#include "pvr/PVRItem.h"
+#include "pvr/PVRManager.h"
+#include "pvr/PVRPlaybackState.h"
+#include "pvr/addons/PVRClient.h"
+#include "pvr/addons/PVRClients.h"
+#include "pvr/channels/PVRChannel.h"
+#include "pvr/channels/PVRChannelGroup.h"
+#include "pvr/channels/PVRChannelGroupMember.h"
+#include "pvr/channels/PVRChannelGroupsContainer.h"
+#include "pvr/channels/PVRRadioRDSInfoTag.h"
+#include "pvr/epg/EpgInfoTag.h"
+#include "pvr/epg/EpgSearchFilter.h"
+#include "pvr/guilib/PVRGUIActionsChannels.h"
+#include "pvr/providers/PVRProvider.h"
+#include "pvr/providers/PVRProviders.h"
+#include "pvr/recordings/PVRRecording.h"
+#include "pvr/recordings/PVRRecordings.h"
+#include "pvr/timers/PVRTimerInfoTag.h"
+#include "pvr/timers/PVRTimers.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "threads/SingleLock.h"
+#include "threads/SystemClock.h"
+#include "utils/StringUtils.h"
+
+#include <cmath>
+#include <ctime>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+using namespace PVR;
+using namespace KODI::GUILIB::GUIINFO;
+using namespace std::chrono_literals;
+
+CPVRGUIInfo::CPVRGUIInfo() : CThread("PVRGUIInfo")
+{
+ ResetProperties();
+}
+
+void CPVRGUIInfo::ResetProperties()
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ m_anyTimersInfo.ResetProperties();
+ m_tvTimersInfo.ResetProperties();
+ m_radioTimersInfo.ResetProperties();
+ m_timesInfo.Reset();
+ m_bHasTVRecordings = false;
+ m_bHasRadioRecordings = false;
+ m_iCurrentActiveClient = 0;
+ m_strPlayingClientName.clear();
+ m_strBackendName.clear();
+ m_strBackendVersion.clear();
+ m_strBackendHost.clear();
+ m_strBackendTimers.clear();
+ m_strBackendRecordings.clear();
+ m_strBackendDeletedRecordings.clear();
+ m_strBackendProviders.clear();
+ m_strBackendChannelGroups.clear();
+ m_strBackendChannels.clear();
+ m_iBackendDiskTotal = 0;
+ m_iBackendDiskUsed = 0;
+ m_bIsPlayingTV = false;
+ m_bIsPlayingRadio = false;
+ m_bIsPlayingRecording = false;
+ m_bIsPlayingEpgTag = false;
+ m_bIsPlayingEncryptedStream = false;
+ m_bIsRecordingPlayingChannel = false;
+ m_bCanRecordPlayingChannel = false;
+ m_bIsPlayingActiveRecording = false;
+ m_bHasTVChannels = false;
+ m_bHasRadioChannels = false;
+
+ ClearQualityInfo(m_qualityInfo);
+ ClearDescrambleInfo(m_descrambleInfo);
+
+ m_updateBackendCacheRequested = false;
+ m_bRegistered = false;
+}
+
+void CPVRGUIInfo::ClearQualityInfo(PVR_SIGNAL_STATUS& qualityInfo)
+{
+ memset(&qualityInfo, 0, sizeof(qualityInfo));
+ strncpy(qualityInfo.strAdapterName, g_localizeStrings.Get(13106).c_str(),
+ PVR_ADDON_NAME_STRING_LENGTH - 1);
+ strncpy(qualityInfo.strAdapterStatus, g_localizeStrings.Get(13106).c_str(),
+ PVR_ADDON_NAME_STRING_LENGTH - 1);
+}
+
+void CPVRGUIInfo::ClearDescrambleInfo(PVR_DESCRAMBLE_INFO& descrambleInfo)
+{
+ descrambleInfo = {};
+}
+
+void CPVRGUIInfo::Start()
+{
+ ResetProperties();
+ Create();
+ SetPriority(ThreadPriority::BELOW_NORMAL);
+}
+
+void CPVRGUIInfo::Stop()
+{
+ StopThread();
+
+ auto& mgr = CServiceBroker::GetPVRManager();
+ auto& channels = mgr.Get<PVR::GUI::Channels>();
+ channels.GetChannelNavigator().Unsubscribe(this);
+ channels.Events().Unsubscribe(this);
+ mgr.Events().Unsubscribe(this);
+
+ CGUIComponent* gui = CServiceBroker::GetGUI();
+ if (gui)
+ {
+ gui->GetInfoManager().UnregisterInfoProvider(this);
+ m_bRegistered = false;
+ }
+}
+
+void CPVRGUIInfo::Notify(const PVREvent& event)
+{
+ if (event == PVREvent::Timers || event == PVREvent::TimersInvalidated)
+ UpdateTimersCache();
+}
+
+void CPVRGUIInfo::Notify(const PVRChannelNumberInputChangedEvent& event)
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ m_channelNumberInput = event.m_input;
+}
+
+void CPVRGUIInfo::Notify(const PVRPreviewAndPlayerShowInfoChangedEvent& event)
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ m_previewAndPlayerShowInfo = event.m_previewAndPlayerShowInfo;
+}
+
+void CPVRGUIInfo::Process()
+{
+ auto toggleIntervalMs = std::chrono::milliseconds(
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_iPVRInfoToggleInterval);
+ XbmcThreads::EndTime<> cacheTimer(toggleIntervalMs);
+
+ auto& mgr = CServiceBroker::GetPVRManager();
+ mgr.Events().Subscribe(this, &CPVRGUIInfo::Notify);
+
+ auto& channels = mgr.Get<PVR::GUI::Channels>();
+ channels.Events().Subscribe(this, &CPVRGUIInfo::Notify);
+ channels.GetChannelNavigator().Subscribe(this, &CPVRGUIInfo::Notify);
+
+ /* updated on request */
+ UpdateTimersCache();
+
+ /* update the backend cache once initially */
+ m_updateBackendCacheRequested = true;
+
+ while (!g_application.m_bStop && !m_bStop)
+ {
+ if (!m_bRegistered)
+ {
+ CGUIComponent* gui = CServiceBroker::GetGUI();
+ if (gui)
+ {
+ gui->GetInfoManager().RegisterInfoProvider(this);
+ m_bRegistered = true;
+ }
+ }
+
+ if (!m_bStop)
+ UpdateQualityData();
+ std::this_thread::yield();
+
+ if (!m_bStop)
+ UpdateDescrambleData();
+ std::this_thread::yield();
+
+ if (!m_bStop)
+ UpdateMisc();
+ std::this_thread::yield();
+
+ if (!m_bStop)
+ UpdateTimeshiftData();
+ std::this_thread::yield();
+
+ if (!m_bStop)
+ UpdateTimersToggle();
+ std::this_thread::yield();
+
+ if (!m_bStop)
+ UpdateNextTimer();
+ std::this_thread::yield();
+
+ // Update the backend cache every toggleInterval seconds
+ if (!m_bStop && cacheTimer.IsTimePast())
+ {
+ UpdateBackendCache();
+ cacheTimer.Set(toggleIntervalMs);
+ }
+
+ if (!m_bStop)
+ CThread::Sleep(500ms);
+ }
+}
+
+void CPVRGUIInfo::UpdateQualityData()
+{
+ if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
+ CSettings::SETTING_PVRPLAYBACK_SIGNALQUALITY))
+ return;
+
+ const std::shared_ptr<CPVRPlaybackState> playbackState =
+ CServiceBroker::GetPVRManager().PlaybackState();
+ if (!playbackState)
+ return;
+
+ PVR_SIGNAL_STATUS qualityInfo;
+ ClearQualityInfo(qualityInfo);
+
+ const int channelUid = playbackState->GetPlayingChannelUniqueID();
+ if (channelUid > 0)
+ {
+ const std::shared_ptr<CPVRClient> client =
+ CServiceBroker::GetPVRManager().Clients()->GetCreatedClient(
+ playbackState->GetPlayingClientID());
+ if (client)
+ client->SignalQuality(channelUid, qualityInfo);
+ }
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ m_qualityInfo = qualityInfo;
+}
+
+void CPVRGUIInfo::UpdateDescrambleData()
+{
+ const std::shared_ptr<CPVRPlaybackState> playbackState =
+ CServiceBroker::GetPVRManager().PlaybackState();
+ if (!playbackState)
+ return;
+
+ PVR_DESCRAMBLE_INFO descrambleInfo;
+ ClearDescrambleInfo(descrambleInfo);
+
+ const int channelUid = playbackState->GetPlayingChannelUniqueID();
+ if (channelUid > 0)
+ {
+ const std::shared_ptr<CPVRClient> client =
+ CServiceBroker::GetPVRManager().Clients()->GetCreatedClient(
+ playbackState->GetPlayingClientID());
+ if (client)
+ client->GetDescrambleInfo(channelUid, descrambleInfo);
+ }
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ m_descrambleInfo = descrambleInfo;
+}
+
+void CPVRGUIInfo::UpdateMisc()
+{
+ const CPVRManager& mgr = CServiceBroker::GetPVRManager();
+ bool bStarted = mgr.IsStarted();
+ const std::shared_ptr<CPVRPlaybackState> state = mgr.PlaybackState();
+
+ /* safe to fetch these unlocked, since they're updated from the same thread as this one */
+ const std::string strPlayingClientName = bStarted ? state->GetPlayingClientName() : "";
+ const bool bHasTVRecordings = bStarted && mgr.Recordings()->GetNumTVRecordings() > 0;
+ const bool bHasRadioRecordings = bStarted && mgr.Recordings()->GetNumRadioRecordings() > 0;
+ const bool bIsPlayingTV = bStarted && state->IsPlayingTV();
+ const bool bIsPlayingRadio = bStarted && state->IsPlayingRadio();
+ const bool bIsPlayingRecording = bStarted && state->IsPlayingRecording();
+ const bool bIsPlayingEpgTag = bStarted && state->IsPlayingEpgTag();
+ const bool bIsPlayingEncryptedStream = bStarted && state->IsPlayingEncryptedChannel();
+ const bool bHasTVChannels = bStarted && mgr.ChannelGroups()->GetGroupAllTV()->HasChannels();
+ const bool bHasRadioChannels = bStarted && mgr.ChannelGroups()->GetGroupAllRadio()->HasChannels();
+ const bool bCanRecordPlayingChannel = bStarted && state->CanRecordOnPlayingChannel();
+ const bool bIsRecordingPlayingChannel = bStarted && state->IsRecordingOnPlayingChannel();
+ const bool bIsPlayingActiveRecording = bStarted && state->IsPlayingActiveRecording();
+ const std::string strPlayingTVGroup =
+ (bStarted && bIsPlayingTV) ? state->GetActiveChannelGroup(false)->GroupName() : "";
+ const std::string strPlayingRadioGroup =
+ (bStarted && bIsPlayingRadio) ? state->GetActiveChannelGroup(true)->GroupName() : "";
+
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ m_strPlayingClientName = strPlayingClientName;
+ m_bHasTVRecordings = bHasTVRecordings;
+ m_bHasRadioRecordings = bHasRadioRecordings;
+ m_bIsPlayingTV = bIsPlayingTV;
+ m_bIsPlayingRadio = bIsPlayingRadio;
+ m_bIsPlayingRecording = bIsPlayingRecording;
+ m_bIsPlayingEpgTag = bIsPlayingEpgTag;
+ m_bIsPlayingEncryptedStream = bIsPlayingEncryptedStream;
+ m_bHasTVChannels = bHasTVChannels;
+ m_bHasRadioChannels = bHasRadioChannels;
+ m_strPlayingTVGroup = strPlayingTVGroup;
+ m_strPlayingRadioGroup = strPlayingRadioGroup;
+ m_bCanRecordPlayingChannel = bCanRecordPlayingChannel;
+ m_bIsRecordingPlayingChannel = bIsRecordingPlayingChannel;
+ m_bIsPlayingActiveRecording = bIsPlayingActiveRecording;
+}
+
+void CPVRGUIInfo::UpdateTimeshiftData()
+{
+ m_timesInfo.Update();
+}
+
+bool CPVRGUIInfo::InitCurrentItem(CFileItem* item)
+{
+ CServiceBroker::GetPVRManager().PublishEvent(PVREvent::CurrentItem);
+ return false;
+}
+
+bool CPVRGUIInfo::GetLabel(std::string& value,
+ const CFileItem* item,
+ int contextWindow,
+ const CGUIInfo& info,
+ std::string* fallback) const
+{
+ return GetListItemAndPlayerLabel(item, info, value) || GetPVRLabel(item, info, value) ||
+ GetRadioRDSLabel(item, info, value);
+}
+
+namespace
+{
+std::string GetAsLocalizedDateString(const CDateTime& datetime, bool bLongDate)
+{
+ return datetime.IsValid() ? datetime.GetAsLocalizedDate(bLongDate) : "";
+}
+
+std::string GetAsLocalizedTimeString(const CDateTime& datetime)
+{
+ return datetime.IsValid() ? datetime.GetAsLocalizedTime("", false) : "";
+}
+
+std::string GetAsLocalizedDateTimeString(const CDateTime& datetime)
+{
+ return datetime.IsValid() ? datetime.GetAsLocalizedDateTime(false, false) : "";
+}
+
+std::string GetEpgTagTitle(const std::shared_ptr<CPVREpgInfoTag>& epgTag)
+{
+ if (epgTag)
+ {
+ if (CServiceBroker::GetPVRManager().IsParentalLocked(epgTag))
+ return g_localizeStrings.Get(19266); // Parental locked
+ else if (!epgTag->Title().empty())
+ return epgTag->Title();
+ }
+
+ if (!CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
+ CSettings::SETTING_EPG_HIDENOINFOAVAILABLE))
+ return g_localizeStrings.Get(19055); // no information available
+
+ return {};
+}
+
+} // unnamed namespace
+
+bool CPVRGUIInfo::GetListItemAndPlayerLabel(const CFileItem* item,
+ const CGUIInfo& info,
+ std::string& strValue) const
+{
+ const std::shared_ptr<CPVRTimerInfoTag> timer = item->GetPVRTimerInfoTag();
+ if (timer)
+ {
+ switch (info.m_info)
+ {
+ case LISTITEM_DATE:
+ strValue = timer->Summary();
+ return true;
+ case LISTITEM_STARTDATE:
+ strValue = GetAsLocalizedDateString(timer->StartAsLocalTime(), true);
+ return true;
+ case LISTITEM_STARTTIME:
+ strValue = GetAsLocalizedTimeString(timer->StartAsLocalTime());
+ return true;
+ case LISTITEM_ENDDATE:
+ strValue = GetAsLocalizedDateString(timer->EndAsLocalTime(), true);
+ return true;
+ case LISTITEM_ENDTIME:
+ strValue = GetAsLocalizedTimeString(timer->EndAsLocalTime());
+ return true;
+ case LISTITEM_DURATION:
+ if (timer->GetDuration() > 0)
+ {
+ strValue = StringUtils::SecondsToTimeString(timer->GetDuration(),
+ static_cast<TIME_FORMAT>(info.GetData4()));
+ return true;
+ }
+ return false;
+ case LISTITEM_TITLE:
+ strValue = timer->Title();
+ return true;
+ case LISTITEM_COMMENT:
+ strValue =
+ timer->GetStatus(CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() ==
+ WINDOW_RADIO_TIMER_RULES);
+ return true;
+ case LISTITEM_TIMERTYPE:
+ strValue = timer->GetTypeAsString();
+ return true;
+ case LISTITEM_CHANNEL_NAME:
+ strValue = timer->ChannelName();
+ return true;
+ case LISTITEM_EPG_EVENT_TITLE:
+ case LISTITEM_EPG_EVENT_ICON:
+ case LISTITEM_GENRE:
+ case LISTITEM_PLOT:
+ case LISTITEM_PLOT_OUTLINE:
+ case LISTITEM_ORIGINALTITLE:
+ case LISTITEM_YEAR:
+ case LISTITEM_SEASON:
+ case LISTITEM_EPISODE:
+ case LISTITEM_EPISODENAME:
+ case LISTITEM_DIRECTOR:
+ case LISTITEM_CHANNEL_NUMBER:
+ case LISTITEM_PREMIERED:
+ break; // obtain value from channel/epg
+ default:
+ return false;
+ }
+ }
+
+ const std::shared_ptr<CPVRRecording> recording(item->GetPVRRecordingInfoTag());
+ if (recording)
+ {
+ // Note: CPVRRecoding is derived from CVideoInfoTag. All base class properties will be handled
+ // by CVideoGUIInfoProvider. Only properties introduced by CPVRRecording need to be handled here.
+ switch (info.m_info)
+ {
+ case LISTITEM_DATE:
+ strValue = GetAsLocalizedDateTimeString(recording->RecordingTimeAsLocalTime());
+ return true;
+ case LISTITEM_STARTDATE:
+ strValue = GetAsLocalizedDateString(recording->RecordingTimeAsLocalTime(), true);
+ return true;
+ case VIDEOPLAYER_STARTTIME:
+ case LISTITEM_STARTTIME:
+ strValue = GetAsLocalizedTimeString(recording->RecordingTimeAsLocalTime());
+ return true;
+ case LISTITEM_ENDDATE:
+ strValue = GetAsLocalizedDateString(recording->EndTimeAsLocalTime(), true);
+ return true;
+ case VIDEOPLAYER_ENDTIME:
+ case LISTITEM_ENDTIME:
+ strValue = GetAsLocalizedTimeString(recording->EndTimeAsLocalTime());
+ return true;
+ case LISTITEM_EXPIRATION_DATE:
+ if (recording->HasExpirationTime())
+ {
+ strValue = GetAsLocalizedDateString(recording->ExpirationTimeAsLocalTime(), false);
+ return true;
+ }
+ break;
+ case LISTITEM_EXPIRATION_TIME:
+ if (recording->HasExpirationTime())
+ {
+ strValue = GetAsLocalizedTimeString(recording->ExpirationTimeAsLocalTime());
+ ;
+ return true;
+ }
+ break;
+ case VIDEOPLAYER_EPISODENAME:
+ case LISTITEM_EPISODENAME:
+ strValue = recording->EpisodeName();
+ // fixup multiline episode name strings (which do not fit in any way in our GUI)
+ StringUtils::Replace(strValue, "\n", ", ");
+ return true;
+ case VIDEOPLAYER_CHANNEL_NAME:
+ case LISTITEM_CHANNEL_NAME:
+ strValue = recording->ChannelName();
+ if (strValue.empty())
+ {
+ if (recording->ProviderName().empty())
+ {
+ const auto& provider = recording->GetProvider();
+ strValue = provider->GetName();
+ }
+ else
+ {
+ strValue = recording->ProviderName();
+ }
+ }
+ return true;
+ case VIDEOPLAYER_CHANNEL_NUMBER:
+ case LISTITEM_CHANNEL_NUMBER:
+ {
+ const std::shared_ptr<CPVRChannelGroupMember> groupMember =
+ CServiceBroker::GetPVRManager().Get<PVR::GUI::Channels>().GetChannelGroupMember(*item);
+ if (groupMember)
+ {
+ strValue = groupMember->ChannelNumber().FormattedChannelNumber();
+ return true;
+ }
+ break;
+ }
+ case LISTITEM_ICON:
+ if (recording->ClientIconPath().empty() && recording->ClientThumbnailPath().empty() &&
+ // Only use a fallback if there is more than a single provider available
+ // Note: an add-on itself is a provider, hence we don't use > 0
+ CServiceBroker::GetPVRManager().Providers()->GetNumProviders() > 1 &&
+ !recording->Channel())
+ {
+ auto provider = recording->GetProvider();
+ if (!provider->GetIconPath().empty())
+ {
+ strValue = provider->GetIconPath();
+ return true;
+ }
+ }
+ return false;
+ case VIDEOPLAYER_CHANNEL_GROUP:
+ {
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ strValue = recording->IsRadio() ? m_strPlayingRadioGroup : m_strPlayingTVGroup;
+ return true;
+ }
+ case VIDEOPLAYER_PREMIERED:
+ case LISTITEM_PREMIERED:
+ if (recording->FirstAired().IsValid())
+ {
+ strValue = recording->FirstAired().GetAsLocalizedDate();
+ return true;
+ }
+ else if (recording->HasYear())
+ {
+ strValue = std::to_string(recording->GetYear());
+ return true;
+ }
+ return false;
+ case LISTITEM_SIZE:
+ if (recording->GetSizeInBytes() > 0)
+ {
+ strValue = StringUtils::SizeToString(recording->GetSizeInBytes());
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ const std::shared_ptr<CPVREpgSearchFilter> filter = item->GetEPGSearchFilter();
+ if (filter)
+ {
+ switch (info.m_info)
+ {
+ case LISTITEM_DATE:
+ {
+ CDateTime lastExecLocal;
+ lastExecLocal.SetFromUTCDateTime(filter->GetLastExecutedDateTime());
+ strValue = GetAsLocalizedDateTimeString(lastExecLocal);
+ if (strValue.empty())
+ strValue = g_localizeStrings.Get(10006); // "N/A"
+ return true;
+ }
+ }
+ return false;
+ }
+
+ std::shared_ptr<CPVREpgInfoTag> epgTag;
+ std::shared_ptr<CPVRChannel> channel;
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ CPVRItem pvrItem(item);
+ channel = pvrItem.GetChannel();
+
+ switch (info.m_info)
+ {
+ case VIDEOPLAYER_NEXT_TITLE:
+ case VIDEOPLAYER_NEXT_GENRE:
+ case VIDEOPLAYER_NEXT_PLOT:
+ case VIDEOPLAYER_NEXT_PLOT_OUTLINE:
+ case VIDEOPLAYER_NEXT_STARTTIME:
+ case VIDEOPLAYER_NEXT_ENDTIME:
+ case VIDEOPLAYER_NEXT_DURATION:
+ case LISTITEM_NEXT_TITLE:
+ case LISTITEM_NEXT_GENRE:
+ case LISTITEM_NEXT_PLOT:
+ case LISTITEM_NEXT_PLOT_OUTLINE:
+ case LISTITEM_NEXT_STARTDATE:
+ case LISTITEM_NEXT_STARTTIME:
+ case LISTITEM_NEXT_ENDDATE:
+ case LISTITEM_NEXT_ENDTIME:
+ case LISTITEM_NEXT_DURATION:
+ // next playing event
+ epgTag = pvrItem.GetNextEpgInfoTag();
+ break;
+ default:
+ // now playing event
+ epgTag = pvrItem.GetEpgInfoTag();
+ break;
+ }
+
+ switch (info.m_info)
+ {
+ // special handling for channels without epg or with radio rds data
+ case PLAYER_TITLE:
+ case LISTITEM_TITLE:
+ case VIDEOPLAYER_NEXT_TITLE:
+ case LISTITEM_NEXT_TITLE:
+ case LISTITEM_EPG_EVENT_TITLE:
+ // Note: in difference to LISTITEM_TITLE, LISTITEM_EPG_EVENT_TITLE returns the title
+ // associated with the epg event of a timer, if any, and not the title of the timer.
+ strValue = GetEpgTagTitle(epgTag);
+ return true;
+ }
+ }
+
+ if (epgTag)
+ {
+ switch (info.m_info)
+ {
+ case VIDEOPLAYER_GENRE:
+ case LISTITEM_GENRE:
+ case VIDEOPLAYER_NEXT_GENRE:
+ case LISTITEM_NEXT_GENRE:
+ strValue = epgTag->GetGenresLabel();
+ return true;
+ case VIDEOPLAYER_PLOT:
+ case LISTITEM_PLOT:
+ case VIDEOPLAYER_NEXT_PLOT:
+ case LISTITEM_NEXT_PLOT:
+ if (!CServiceBroker::GetPVRManager().IsParentalLocked(epgTag))
+ strValue = epgTag->Plot();
+ return true;
+ case VIDEOPLAYER_PLOT_OUTLINE:
+ case LISTITEM_PLOT_OUTLINE:
+ case VIDEOPLAYER_NEXT_PLOT_OUTLINE:
+ case LISTITEM_NEXT_PLOT_OUTLINE:
+ if (!CServiceBroker::GetPVRManager().IsParentalLocked(epgTag))
+ strValue = epgTag->PlotOutline();
+ return true;
+ case LISTITEM_DATE:
+ strValue = GetAsLocalizedDateTimeString(epgTag->StartAsLocalTime());
+ return true;
+ case LISTITEM_STARTDATE:
+ case LISTITEM_NEXT_STARTDATE:
+ strValue = GetAsLocalizedDateString(epgTag->StartAsLocalTime(), true);
+ return true;
+ case VIDEOPLAYER_STARTTIME:
+ case VIDEOPLAYER_NEXT_STARTTIME:
+ case LISTITEM_STARTTIME:
+ case LISTITEM_NEXT_STARTTIME:
+ strValue = GetAsLocalizedTimeString(epgTag->StartAsLocalTime());
+ return true;
+ case LISTITEM_ENDDATE:
+ case LISTITEM_NEXT_ENDDATE:
+ strValue = GetAsLocalizedDateString(epgTag->EndAsLocalTime(), true);
+ return true;
+ case VIDEOPLAYER_ENDTIME:
+ case VIDEOPLAYER_NEXT_ENDTIME:
+ case LISTITEM_ENDTIME:
+ case LISTITEM_NEXT_ENDTIME:
+ strValue = GetAsLocalizedTimeString(epgTag->EndAsLocalTime());
+ return true;
+ // note: for some reason, there is no VIDEOPLAYER_DURATION
+ case LISTITEM_DURATION:
+ case VIDEOPLAYER_NEXT_DURATION:
+ case LISTITEM_NEXT_DURATION:
+ if (epgTag->GetDuration() > 0)
+ {
+ strValue = StringUtils::SecondsToTimeString(epgTag->GetDuration(),
+ static_cast<TIME_FORMAT>(info.GetData4()));
+ return true;
+ }
+ return false;
+ case VIDEOPLAYER_IMDBNUMBER:
+ case LISTITEM_IMDBNUMBER:
+ strValue = epgTag->IMDBNumber();
+ return true;
+ case VIDEOPLAYER_ORIGINALTITLE:
+ case LISTITEM_ORIGINALTITLE:
+ if (!CServiceBroker::GetPVRManager().IsParentalLocked(epgTag))
+ strValue = epgTag->OriginalTitle();
+ return true;
+ case VIDEOPLAYER_YEAR:
+ case LISTITEM_YEAR:
+ if (epgTag->Year() > 0)
+ {
+ strValue = std::to_string(epgTag->Year());
+ return true;
+ }
+ return false;
+ case VIDEOPLAYER_SEASON:
+ case LISTITEM_SEASON:
+ if (epgTag->SeriesNumber() >= 0)
+ {
+ strValue = std::to_string(epgTag->SeriesNumber());
+ return true;
+ }
+ return false;
+ case VIDEOPLAYER_EPISODE:
+ case LISTITEM_EPISODE:
+ if (epgTag->EpisodeNumber() >= 0)
+ {
+ strValue = std::to_string(epgTag->EpisodeNumber());
+ return true;
+ }
+ return false;
+ case VIDEOPLAYER_EPISODENAME:
+ case LISTITEM_EPISODENAME:
+ if (!CServiceBroker::GetPVRManager().IsParentalLocked(epgTag))
+ {
+ strValue = epgTag->EpisodeName();
+ // fixup multiline episode name strings (which do not fit in any way in our GUI)
+ StringUtils::Replace(strValue, "\n", ", ");
+ }
+ return true;
+ case VIDEOPLAYER_CAST:
+ case LISTITEM_CAST:
+ strValue = epgTag->GetCastLabel();
+ return true;
+ case VIDEOPLAYER_DIRECTOR:
+ case LISTITEM_DIRECTOR:
+ strValue = epgTag->GetDirectorsLabel();
+ return true;
+ case VIDEOPLAYER_WRITER:
+ case LISTITEM_WRITER:
+ strValue = epgTag->GetWritersLabel();
+ return true;
+ case LISTITEM_EPG_EVENT_ICON:
+ strValue = epgTag->IconPath();
+ return true;
+ case VIDEOPLAYER_PARENTAL_RATING:
+ case LISTITEM_PARENTAL_RATING:
+ if (epgTag->ParentalRating() > 0)
+ {
+ strValue = std::to_string(epgTag->ParentalRating());
+ return true;
+ }
+ return false;
+ case VIDEOPLAYER_PREMIERED:
+ case LISTITEM_PREMIERED:
+ if (epgTag->FirstAired().IsValid())
+ {
+ strValue = epgTag->FirstAired().GetAsLocalizedDate();
+ return true;
+ }
+ else if (epgTag->Year() > 0)
+ {
+ strValue = std::to_string(epgTag->Year());
+ return true;
+ }
+ return false;
+ case VIDEOPLAYER_RATING:
+ case LISTITEM_RATING:
+ {
+ int iStarRating = epgTag->StarRating();
+ if (iStarRating > 0)
+ {
+ strValue = StringUtils::FormatNumber(iStarRating);
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+
+ if (channel)
+ {
+ switch (info.m_info)
+ {
+ case MUSICPLAYER_CHANNEL_NAME:
+ {
+ const std::shared_ptr<CPVRRadioRDSInfoTag> rdsTag = channel->GetRadioRDSInfoTag();
+ if (rdsTag)
+ {
+ strValue = rdsTag->GetProgStation();
+ if (!strValue.empty())
+ return true;
+ }
+ // fall-thru is intended
+ [[fallthrough]];
+ }
+ case VIDEOPLAYER_CHANNEL_NAME:
+ case LISTITEM_CHANNEL_NAME:
+ strValue = channel->ChannelName();
+ return true;
+ case MUSICPLAYER_CHANNEL_NUMBER:
+ case VIDEOPLAYER_CHANNEL_NUMBER:
+ case LISTITEM_CHANNEL_NUMBER:
+ {
+ auto groupMember = item->GetPVRChannelGroupMemberInfoTag();
+ if (!groupMember)
+ groupMember =
+ CServiceBroker::GetPVRManager().Get<PVR::GUI::Channels>().GetChannelGroupMember(
+ *item);
+ if (groupMember)
+ {
+ strValue = groupMember->ChannelNumber().FormattedChannelNumber();
+ return true;
+ }
+ break;
+ }
+ case MUSICPLAYER_CHANNEL_GROUP:
+ case VIDEOPLAYER_CHANNEL_GROUP:
+ {
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+ strValue = channel->IsRadio() ? m_strPlayingRadioGroup : m_strPlayingTVGroup;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CPVRGUIInfo::GetPVRLabel(const CFileItem* item,
+ const CGUIInfo& info,
+ std::string& strValue) const
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ switch (info.m_info)
+ {
+ case PVR_EPG_EVENT_ICON:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ if (epgTag)
+ {
+ strValue = epgTag->IconPath();
+ }
+ return true;
+ }
+ case PVR_EPG_EVENT_DURATION:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue = m_timesInfo.GetEpgEventDuration(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ }
+ case PVR_EPG_EVENT_ELAPSED_TIME:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue =
+ m_timesInfo.GetEpgEventElapsedTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ }
+ case PVR_EPG_EVENT_REMAINING_TIME:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue =
+ m_timesInfo.GetEpgEventRemainingTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ }
+ case PVR_EPG_EVENT_FINISH_TIME:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ strValue =
+ m_timesInfo.GetEpgEventFinishTime(epgTag, static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ }
+ case PVR_TIMESHIFT_START_TIME:
+ strValue = m_timesInfo.GetTimeshiftStartTime(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_END_TIME:
+ strValue = m_timesInfo.GetTimeshiftEndTime(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PLAY_TIME:
+ strValue = m_timesInfo.GetTimeshiftPlayTime(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_OFFSET:
+ strValue = m_timesInfo.GetTimeshiftOffset(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_DURATION:
+ strValue =
+ m_timesInfo.GetTimeshiftProgressDuration(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_START_TIME:
+ strValue =
+ m_timesInfo.GetTimeshiftProgressStartTime(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_END_TIME:
+ strValue = m_timesInfo.GetTimeshiftProgressEndTime(static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ case PVR_EPG_EVENT_SEEK_TIME:
+ {
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ strValue = m_timesInfo.GetEpgEventSeekTime(appPlayer->GetSeekHandler().GetSeekSize(),
+ static_cast<TIME_FORMAT>(info.GetData1()));
+ return true;
+ }
+ case PVR_NOW_RECORDING_TITLE:
+ strValue = m_anyTimersInfo.GetActiveTimerTitle();
+ return true;
+ case PVR_NOW_RECORDING_CHANNEL:
+ strValue = m_anyTimersInfo.GetActiveTimerChannelName();
+ return true;
+ case PVR_NOW_RECORDING_CHAN_ICO:
+ strValue = m_anyTimersInfo.GetActiveTimerChannelIcon();
+ return true;
+ case PVR_NOW_RECORDING_DATETIME:
+ strValue = m_anyTimersInfo.GetActiveTimerDateTime();
+ return true;
+ case PVR_NEXT_RECORDING_TITLE:
+ strValue = m_anyTimersInfo.GetNextTimerTitle();
+ return true;
+ case PVR_NEXT_RECORDING_CHANNEL:
+ strValue = m_anyTimersInfo.GetNextTimerChannelName();
+ return true;
+ case PVR_NEXT_RECORDING_CHAN_ICO:
+ strValue = m_anyTimersInfo.GetNextTimerChannelIcon();
+ return true;
+ case PVR_NEXT_RECORDING_DATETIME:
+ strValue = m_anyTimersInfo.GetNextTimerDateTime();
+ return true;
+ case PVR_TV_NOW_RECORDING_TITLE:
+ strValue = m_tvTimersInfo.GetActiveTimerTitle();
+ return true;
+ case PVR_TV_NOW_RECORDING_CHANNEL:
+ strValue = m_tvTimersInfo.GetActiveTimerChannelName();
+ return true;
+ case PVR_TV_NOW_RECORDING_CHAN_ICO:
+ strValue = m_tvTimersInfo.GetActiveTimerChannelIcon();
+ return true;
+ case PVR_TV_NOW_RECORDING_DATETIME:
+ strValue = m_tvTimersInfo.GetActiveTimerDateTime();
+ return true;
+ case PVR_TV_NEXT_RECORDING_TITLE:
+ strValue = m_tvTimersInfo.GetNextTimerTitle();
+ return true;
+ case PVR_TV_NEXT_RECORDING_CHANNEL:
+ strValue = m_tvTimersInfo.GetNextTimerChannelName();
+ return true;
+ case PVR_TV_NEXT_RECORDING_CHAN_ICO:
+ strValue = m_tvTimersInfo.GetNextTimerChannelIcon();
+ return true;
+ case PVR_TV_NEXT_RECORDING_DATETIME:
+ strValue = m_tvTimersInfo.GetNextTimerDateTime();
+ return true;
+ case PVR_RADIO_NOW_RECORDING_TITLE:
+ strValue = m_radioTimersInfo.GetActiveTimerTitle();
+ return true;
+ case PVR_RADIO_NOW_RECORDING_CHANNEL:
+ strValue = m_radioTimersInfo.GetActiveTimerChannelName();
+ return true;
+ case PVR_RADIO_NOW_RECORDING_CHAN_ICO:
+ strValue = m_radioTimersInfo.GetActiveTimerChannelIcon();
+ return true;
+ case PVR_RADIO_NOW_RECORDING_DATETIME:
+ strValue = m_radioTimersInfo.GetActiveTimerDateTime();
+ return true;
+ case PVR_RADIO_NEXT_RECORDING_TITLE:
+ strValue = m_radioTimersInfo.GetNextTimerTitle();
+ return true;
+ case PVR_RADIO_NEXT_RECORDING_CHANNEL:
+ strValue = m_radioTimersInfo.GetNextTimerChannelName();
+ return true;
+ case PVR_RADIO_NEXT_RECORDING_CHAN_ICO:
+ strValue = m_radioTimersInfo.GetNextTimerChannelIcon();
+ return true;
+ case PVR_RADIO_NEXT_RECORDING_DATETIME:
+ strValue = m_radioTimersInfo.GetNextTimerDateTime();
+ return true;
+ case PVR_NEXT_TIMER:
+ strValue = m_anyTimersInfo.GetNextTimer();
+ return true;
+ case PVR_ACTUAL_STREAM_SIG:
+ CharInfoSignal(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_SNR:
+ CharInfoSNR(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_BER:
+ CharInfoBER(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_UNC:
+ CharInfoUNC(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_CLIENT:
+ CharInfoPlayingClientName(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_DEVICE:
+ CharInfoFrontendName(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_STATUS:
+ CharInfoFrontendStatus(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_CRYPTION:
+ CharInfoEncryption(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_SERVICE:
+ CharInfoService(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_MUX:
+ CharInfoMux(strValue);
+ return true;
+ case PVR_ACTUAL_STREAM_PROVIDER:
+ CharInfoProvider(strValue);
+ return true;
+ case PVR_BACKEND_NAME:
+ CharInfoBackendName(strValue);
+ return true;
+ case PVR_BACKEND_VERSION:
+ CharInfoBackendVersion(strValue);
+ return true;
+ case PVR_BACKEND_HOST:
+ CharInfoBackendHost(strValue);
+ return true;
+ case PVR_BACKEND_DISKSPACE:
+ CharInfoBackendDiskspace(strValue);
+ return true;
+ case PVR_BACKEND_PROVIDERS:
+ CharInfoBackendProviders(strValue);
+ return true;
+ case PVR_BACKEND_CHANNEL_GROUPS:
+ CharInfoBackendChannelGroups(strValue);
+ return true;
+ case PVR_BACKEND_CHANNELS:
+ CharInfoBackendChannels(strValue);
+ return true;
+ case PVR_BACKEND_TIMERS:
+ CharInfoBackendTimers(strValue);
+ return true;
+ case PVR_BACKEND_RECORDINGS:
+ CharInfoBackendRecordings(strValue);
+ return true;
+ case PVR_BACKEND_DELETED_RECORDINGS:
+ CharInfoBackendDeletedRecordings(strValue);
+ return true;
+ case PVR_BACKEND_NUMBER:
+ CharInfoBackendNumber(strValue);
+ return true;
+ case PVR_TOTAL_DISKSPACE:
+ CharInfoTotalDiskSpace(strValue);
+ return true;
+ case PVR_CHANNEL_NUMBER_INPUT:
+ strValue = m_channelNumberInput;
+ return true;
+ }
+
+ return false;
+}
+
+bool CPVRGUIInfo::GetRadioRDSLabel(const CFileItem* item,
+ const CGUIInfo& info,
+ std::string& strValue) const
+{
+ if (!item->HasPVRChannelInfoTag())
+ return false;
+
+ const std::shared_ptr<CPVRRadioRDSInfoTag> tag =
+ item->GetPVRChannelInfoTag()->GetRadioRDSInfoTag();
+ if (tag)
+ {
+ switch (info.m_info)
+ {
+ case RDS_CHANNEL_COUNTRY:
+ strValue = tag->GetCountry();
+ return true;
+ case RDS_TITLE:
+ strValue = tag->GetTitle();
+ return true;
+ case RDS_ARTIST:
+ strValue = tag->GetArtist();
+ return true;
+ case RDS_BAND:
+ strValue = tag->GetBand();
+ return true;
+ case RDS_COMPOSER:
+ strValue = tag->GetComposer();
+ return true;
+ case RDS_CONDUCTOR:
+ strValue = tag->GetConductor();
+ return true;
+ case RDS_ALBUM:
+ strValue = tag->GetAlbum();
+ return true;
+ case RDS_ALBUM_TRACKNUMBER:
+ if (tag->GetAlbumTrackNumber() > 0)
+ {
+ strValue = std::to_string(tag->GetAlbumTrackNumber());
+ return true;
+ }
+ break;
+ case RDS_GET_RADIO_STYLE:
+ strValue = tag->GetRadioStyle();
+ return true;
+ case RDS_COMMENT:
+ strValue = tag->GetComment();
+ return true;
+ case RDS_INFO_NEWS:
+ strValue = tag->GetInfoNews();
+ return true;
+ case RDS_INFO_NEWS_LOCAL:
+ strValue = tag->GetInfoNewsLocal();
+ return true;
+ case RDS_INFO_STOCK:
+ strValue = tag->GetInfoStock();
+ return true;
+ case RDS_INFO_STOCK_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoStock().size()));
+ return true;
+ case RDS_INFO_SPORT:
+ strValue = tag->GetInfoSport();
+ return true;
+ case RDS_INFO_SPORT_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoSport().size()));
+ return true;
+ case RDS_INFO_LOTTERY:
+ strValue = tag->GetInfoLottery();
+ return true;
+ case RDS_INFO_LOTTERY_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoLottery().size()));
+ return true;
+ case RDS_INFO_WEATHER:
+ strValue = tag->GetInfoWeather();
+ return true;
+ case RDS_INFO_WEATHER_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoWeather().size()));
+ return true;
+ case RDS_INFO_HOROSCOPE:
+ strValue = tag->GetInfoHoroscope();
+ return true;
+ case RDS_INFO_HOROSCOPE_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoHoroscope().size()));
+ return true;
+ case RDS_INFO_CINEMA:
+ strValue = tag->GetInfoCinema();
+ return true;
+ case RDS_INFO_CINEMA_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoCinema().size()));
+ return true;
+ case RDS_INFO_OTHER:
+ strValue = tag->GetInfoOther();
+ return true;
+ case RDS_INFO_OTHER_SIZE:
+ strValue = std::to_string(static_cast<int>(tag->GetInfoOther().size()));
+ return true;
+ case RDS_PROG_HOST:
+ strValue = tag->GetProgHost();
+ return true;
+ case RDS_PROG_EDIT_STAFF:
+ strValue = tag->GetEditorialStaff();
+ return true;
+ case RDS_PROG_HOMEPAGE:
+ strValue = tag->GetProgWebsite();
+ return true;
+ case RDS_PROG_STYLE:
+ strValue = tag->GetProgStyle();
+ return true;
+ case RDS_PHONE_HOTLINE:
+ strValue = tag->GetPhoneHotline();
+ return true;
+ case RDS_PHONE_STUDIO:
+ strValue = tag->GetPhoneStudio();
+ return true;
+ case RDS_SMS_STUDIO:
+ strValue = tag->GetSMSStudio();
+ return true;
+ case RDS_EMAIL_HOTLINE:
+ strValue = tag->GetEMailHotline();
+ return true;
+ case RDS_EMAIL_STUDIO:
+ strValue = tag->GetEMailStudio();
+ return true;
+ case RDS_PROG_STATION:
+ strValue = tag->GetProgStation();
+ return true;
+ case RDS_PROG_NOW:
+ strValue = tag->GetProgNow();
+ return true;
+ case RDS_PROG_NEXT:
+ strValue = tag->GetProgNext();
+ return true;
+ case RDS_AUDIO_LANG:
+ strValue = tag->GetLanguage();
+ return true;
+ case RDS_GET_RADIOTEXT_LINE:
+ strValue = tag->GetRadioText(info.GetData1());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CPVRGUIInfo::GetFallbackLabel(std::string& value,
+ const CFileItem* item,
+ int contextWindow,
+ const CGUIInfo& info,
+ std::string* fallback)
+{
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ switch (info.m_info)
+ {
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ // VIDEOPLAYER_*, MUSICPLAYER_*
+ /////////////////////////////////////////////////////////////////////////////////////////////
+ case VIDEOPLAYER_TITLE:
+ case MUSICPLAYER_TITLE:
+ value = GetEpgTagTitle(CPVRItem(item).GetEpgInfoTag());
+ return !value.empty();
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool CPVRGUIInfo::GetInt(int& value,
+ const CGUIListItem* item,
+ int contextWindow,
+ const CGUIInfo& info) const
+{
+ if (!item->IsFileItem())
+ return false;
+
+ const CFileItem* fitem = static_cast<const CFileItem*>(item);
+ return GetListItemAndPlayerInt(fitem, info, value) || GetPVRInt(fitem, info, value);
+}
+
+bool CPVRGUIInfo::GetListItemAndPlayerInt(const CFileItem* item,
+ const CGUIInfo& info,
+ int& iValue) const
+{
+ switch (info.m_info)
+ {
+ case LISTITEM_PROGRESS:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag = CPVRItem(item).GetEpgInfoTag();
+ if (epgTag)
+ iValue = static_cast<int>(epgTag->ProgressPercentage());
+ }
+ return true;
+ }
+ return false;
+}
+
+bool CPVRGUIInfo::GetPVRInt(const CFileItem* item, const CGUIInfo& info, int& iValue) const
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ switch (info.m_info)
+ {
+ case PVR_EPG_EVENT_DURATION:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ iValue = m_timesInfo.GetEpgEventDuration(epgTag);
+ return true;
+ }
+ case PVR_EPG_EVENT_PROGRESS:
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ (item->IsPVRChannel() || item->IsEPG()) ? CPVRItem(item).GetEpgInfoTag() : nullptr;
+ iValue = m_timesInfo.GetEpgEventProgress(epgTag);
+ return true;
+ }
+ case PVR_TIMESHIFT_PROGRESS:
+ iValue = m_timesInfo.GetTimeshiftProgress();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_DURATION:
+ iValue = m_timesInfo.GetTimeshiftProgressDuration();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_PLAY_POS:
+ iValue = m_timesInfo.GetTimeshiftProgressPlayPosition();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_EPG_START:
+ iValue = m_timesInfo.GetTimeshiftProgressEpgStart();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_EPG_END:
+ iValue = m_timesInfo.GetTimeshiftProgressEpgEnd();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_BUFFER_START:
+ iValue = m_timesInfo.GetTimeshiftProgressBufferStart();
+ return true;
+ case PVR_TIMESHIFT_PROGRESS_BUFFER_END:
+ iValue = m_timesInfo.GetTimeshiftProgressBufferEnd();
+ return true;
+ case PVR_TIMESHIFT_SEEKBAR:
+ iValue = GetTimeShiftSeekPercent();
+ return true;
+ case PVR_ACTUAL_STREAM_SIG_PROGR:
+ iValue = std::lrintf(static_cast<float>(m_qualityInfo.iSignal) / 0xFFFF * 100);
+ return true;
+ case PVR_ACTUAL_STREAM_SNR_PROGR:
+ iValue = std::lrintf(static_cast<float>(m_qualityInfo.iSNR) / 0xFFFF * 100);
+ return true;
+ case PVR_BACKEND_DISKSPACE_PROGR:
+ if (m_iBackendDiskTotal > 0)
+ iValue = std::lrintf(static_cast<float>(m_iBackendDiskUsed) / m_iBackendDiskTotal * 100);
+ else
+ iValue = 0xFF;
+ return true;
+ }
+ return false;
+}
+
+bool CPVRGUIInfo::GetBool(bool& value,
+ const CGUIListItem* item,
+ int contextWindow,
+ const CGUIInfo& info) const
+{
+ if (!item->IsFileItem())
+ return false;
+
+ const CFileItem* fitem = static_cast<const CFileItem*>(item);
+ return GetListItemAndPlayerBool(fitem, info, value) || GetPVRBool(fitem, info, value) ||
+ GetRadioRDSBool(fitem, info, value);
+}
+
+bool CPVRGUIInfo::GetListItemAndPlayerBool(const CFileItem* item,
+ const CGUIInfo& info,
+ bool& bValue) const
+{
+ switch (info.m_info)
+ {
+ case LISTITEM_HASARCHIVE:
+ if (item->IsPVRChannel())
+ {
+ bValue = item->GetPVRChannelInfoTag()->HasArchive();
+ return true;
+ }
+ break;
+ case LISTITEM_ISPLAYABLE:
+ if (item->IsEPG())
+ {
+ bValue = item->GetEPGInfoTag()->IsPlayable();
+ return true;
+ }
+ break;
+ case LISTITEM_ISRECORDING:
+ if (item->IsPVRChannel())
+ {
+ bValue = CServiceBroker::GetPVRManager().Timers()->IsRecordingOnChannel(
+ *item->GetPVRChannelInfoTag());
+ return true;
+ }
+ else if (item->IsEPG() || item->IsPVRTimer())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = timer->IsRecording();
+ return true;
+ }
+ else if (item->IsPVRRecording())
+ {
+ bValue = item->GetPVRRecordingInfoTag()->IsInProgress();
+ return true;
+ }
+ break;
+ case LISTITEM_INPROGRESS:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag = CPVRItem(item).GetEpgInfoTag();
+ if (epgTag)
+ bValue = epgTag->IsActive();
+ return true;
+ }
+ break;
+ case LISTITEM_HASTIMER:
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = true;
+ return true;
+ }
+ break;
+ case LISTITEM_HASTIMERSCHEDULE:
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = timer->HasParent();
+ return true;
+ }
+ break;
+ case LISTITEM_HASREMINDER:
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = timer->IsReminder();
+ return true;
+ }
+ break;
+ case LISTITEM_HASREMINDERRULE:
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = timer->IsReminder() && timer->HasParent();
+ return true;
+ }
+ break;
+ case LISTITEM_TIMERISACTIVE:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = timer->IsActive();
+ break;
+ }
+ break;
+ case LISTITEM_TIMERHASCONFLICT:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = timer->HasConflict();
+ return true;
+ }
+ break;
+ case LISTITEM_TIMERHASERROR:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVRTimerInfoTag> timer = CPVRItem(item).GetTimerInfoTag();
+ if (timer)
+ bValue = (timer->IsBroken() && !timer->HasConflict());
+ return true;
+ }
+ break;
+ case LISTITEM_HASRECORDING:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag = CPVRItem(item).GetEpgInfoTag();
+ if (epgTag)
+ bValue = !!CServiceBroker::GetPVRManager().Recordings()->GetRecordingForEpgTag(epgTag);
+ return true;
+ }
+ break;
+ case LISTITEM_HAS_EPG:
+ if (item->IsPVRChannel() || item->IsEPG() || item->IsPVRTimer())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgTag = CPVRItem(item).GetEpgInfoTag();
+ bValue = (epgTag != nullptr);
+ return true;
+ }
+ break;
+ case LISTITEM_ISENCRYPTED:
+ if (item->IsPVRChannel() || item->IsEPG())
+ {
+ const std::shared_ptr<CPVRChannel> channel = CPVRItem(item).GetChannel();
+ if (channel)
+ bValue = channel->IsEncrypted();
+ return true;
+ }
+ break;
+ case LISTITEM_IS_NEW:
+ if (item->IsEPG())
+ {
+ if (item->GetEPGInfoTag())
+ {
+ bValue = item->GetEPGInfoTag()->IsNew();
+ return true;
+ }
+ }
+ else if (item->IsPVRRecording())
+ {
+ bValue = item->GetPVRRecordingInfoTag()->IsNew();
+ return true;
+ }
+ else if (item->IsPVRTimer() && item->GetPVRTimerInfoTag()->GetEpgInfoTag())
+ {
+ bValue = item->GetPVRTimerInfoTag()->GetEpgInfoTag()->IsNew();
+ return true;
+ }
+ else if (item->IsPVRChannel())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgNow = item->GetPVRChannelInfoTag()->GetEPGNow();
+ bValue = epgNow ? epgNow->IsNew() : false;
+ return true;
+ }
+ break;
+ case LISTITEM_IS_PREMIERE:
+ if (item->IsEPG())
+ {
+ bValue = item->GetEPGInfoTag()->IsPremiere();
+ return true;
+ }
+ else if (item->IsPVRRecording())
+ {
+ bValue = item->GetPVRRecordingInfoTag()->IsPremiere();
+ return true;
+ }
+ else if (item->IsPVRTimer() && item->GetPVRTimerInfoTag()->GetEpgInfoTag())
+ {
+ bValue = item->GetPVRTimerInfoTag()->GetEpgInfoTag()->IsPremiere();
+ return true;
+ }
+ else if (item->IsPVRChannel())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgNow = item->GetPVRChannelInfoTag()->GetEPGNow();
+ bValue = epgNow ? epgNow->IsPremiere() : false;
+ return true;
+ }
+ break;
+ case LISTITEM_IS_FINALE:
+ if (item->IsEPG())
+ {
+ bValue = item->GetEPGInfoTag()->IsFinale();
+ return true;
+ }
+ else if (item->IsPVRRecording())
+ {
+ bValue = item->GetPVRRecordingInfoTag()->IsFinale();
+ return true;
+ }
+ else if (item->IsPVRTimer() && item->GetPVRTimerInfoTag()->GetEpgInfoTag())
+ {
+ bValue = item->GetPVRTimerInfoTag()->GetEpgInfoTag()->IsFinale();
+ return true;
+ }
+ else if (item->IsPVRChannel())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgNow = item->GetPVRChannelInfoTag()->GetEPGNow();
+ bValue = epgNow ? epgNow->IsFinale() : false;
+ return true;
+ }
+ break;
+ case LISTITEM_IS_LIVE:
+ if (item->IsEPG())
+ {
+ bValue = item->GetEPGInfoTag()->IsLive();
+ return true;
+ }
+ else if (item->IsPVRRecording())
+ {
+ bValue = item->GetPVRRecordingInfoTag()->IsLive();
+ return true;
+ }
+ else if (item->IsPVRTimer() && item->GetPVRTimerInfoTag()->GetEpgInfoTag())
+ {
+ bValue = item->GetPVRTimerInfoTag()->GetEpgInfoTag()->IsLive();
+ return true;
+ }
+ else if (item->IsPVRChannel())
+ {
+ const std::shared_ptr<CPVREpgInfoTag> epgNow = item->GetPVRChannelInfoTag()->GetEPGNow();
+ bValue = epgNow ? epgNow->IsLive() : false;
+ return true;
+ }
+ break;
+ case MUSICPLAYER_CONTENT:
+ case VIDEOPLAYER_CONTENT:
+ if (item->IsPVRChannel())
+ {
+ bValue = StringUtils::EqualsNoCase(info.GetData3(), "livetv");
+ return bValue; // if no match for this provider, other providers shall be asked.
+ }
+ break;
+ case VIDEOPLAYER_HAS_INFO:
+ if (item->IsPVRChannel())
+ {
+ bValue = !item->GetPVRChannelInfoTag()->ChannelName().empty();
+ return true;
+ }
+ break;
+ case VIDEOPLAYER_HAS_EPG:
+ if (item->IsPVRChannel())
+ {
+ bValue = (item->GetPVRChannelInfoTag()->GetEPGNow() != nullptr);
+ return true;
+ }
+ break;
+ case VIDEOPLAYER_CAN_RESUME_LIVE_TV:
+ if (item->IsPVRRecording())
+ {
+ const std::shared_ptr<CPVRRecording> recording = item->GetPVRRecordingInfoTag();
+ const std::shared_ptr<CPVREpg> epg =
+ recording->Channel() ? recording->Channel()->GetEPG() : nullptr;
+ const std::shared_ptr<CPVREpgInfoTag> epgTag =
+ CServiceBroker::GetPVRManager().EpgContainer().GetTagById(epg,
+ recording->BroadcastUid());
+ bValue = (epgTag && epgTag->IsActive());
+ return true;
+ }
+ break;
+ case PLAYER_IS_CHANNEL_PREVIEW_ACTIVE:
+ if (item->IsPVRChannel())
+ {
+ if (m_previewAndPlayerShowInfo)
+ {
+ bValue = true;
+ }
+ else
+ {
+ bValue = !m_videoInfo.valid;
+ if (bValue && item->GetPVRChannelInfoTag()->IsRadio())
+ bValue = !m_audioInfo.valid;
+ }
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+bool CPVRGUIInfo::GetPVRBool(const CFileItem* item, const CGUIInfo& info, bool& bValue) const
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ switch (info.m_info)
+ {
+ case PVR_IS_RECORDING:
+ bValue = m_anyTimersInfo.HasRecordingTimers();
+ return true;
+ case PVR_IS_RECORDING_TV:
+ bValue = m_tvTimersInfo.HasRecordingTimers();
+ return true;
+ case PVR_IS_RECORDING_RADIO:
+ bValue = m_radioTimersInfo.HasRecordingTimers();
+ return true;
+ case PVR_HAS_TIMER:
+ bValue = m_anyTimersInfo.HasTimers();
+ return true;
+ case PVR_HAS_TV_TIMER:
+ bValue = m_tvTimersInfo.HasTimers();
+ return true;
+ case PVR_HAS_RADIO_TIMER:
+ bValue = m_radioTimersInfo.HasTimers();
+ return true;
+ case PVR_HAS_TV_CHANNELS:
+ bValue = m_bHasTVChannels;
+ return true;
+ case PVR_HAS_RADIO_CHANNELS:
+ bValue = m_bHasRadioChannels;
+ return true;
+ case PVR_HAS_NONRECORDING_TIMER:
+ bValue = m_anyTimersInfo.HasNonRecordingTimers();
+ return true;
+ case PVR_HAS_NONRECORDING_TV_TIMER:
+ bValue = m_tvTimersInfo.HasNonRecordingTimers();
+ return true;
+ case PVR_HAS_NONRECORDING_RADIO_TIMER:
+ bValue = m_radioTimersInfo.HasNonRecordingTimers();
+ return true;
+ case PVR_IS_PLAYING_TV:
+ bValue = m_bIsPlayingTV;
+ return true;
+ case PVR_IS_PLAYING_RADIO:
+ bValue = m_bIsPlayingRadio;
+ return true;
+ case PVR_IS_PLAYING_RECORDING:
+ bValue = m_bIsPlayingRecording;
+ return true;
+ case PVR_IS_PLAYING_EPGTAG:
+ bValue = m_bIsPlayingEpgTag;
+ return true;
+ case PVR_ACTUAL_STREAM_ENCRYPTED:
+ bValue = m_bIsPlayingEncryptedStream;
+ return true;
+ case PVR_IS_TIMESHIFTING:
+ bValue = m_timesInfo.IsTimeshifting();
+ return true;
+ case PVR_CAN_RECORD_PLAYING_CHANNEL:
+ bValue = m_bCanRecordPlayingChannel;
+ return true;
+ case PVR_IS_RECORDING_PLAYING_CHANNEL:
+ bValue = m_bIsRecordingPlayingChannel;
+ return true;
+ case PVR_IS_PLAYING_ACTIVE_RECORDING:
+ bValue = m_bIsPlayingActiveRecording;
+ return true;
+ }
+ return false;
+}
+
+bool CPVRGUIInfo::GetRadioRDSBool(const CFileItem* item, const CGUIInfo& info, bool& bValue) const
+{
+ if (!item->HasPVRChannelInfoTag())
+ return false;
+
+ const std::shared_ptr<CPVRRadioRDSInfoTag> tag =
+ item->GetPVRChannelInfoTag()->GetRadioRDSInfoTag();
+ if (tag)
+ {
+ switch (info.m_info)
+ {
+ case RDS_HAS_RADIOTEXT:
+ bValue = tag->IsPlayingRadioText();
+ return true;
+ case RDS_HAS_RADIOTEXT_PLUS:
+ bValue = tag->IsPlayingRadioTextPlus();
+ return true;
+ case RDS_HAS_HOTLINE_DATA:
+ bValue = (!tag->GetEMailHotline().empty() || !tag->GetPhoneHotline().empty());
+ return true;
+ case RDS_HAS_STUDIO_DATA:
+ bValue = (!tag->GetEMailStudio().empty() || !tag->GetSMSStudio().empty() ||
+ !tag->GetPhoneStudio().empty());
+ return true;
+ }
+ }
+
+ switch (info.m_info)
+ {
+ case RDS_HAS_RDS:
+ {
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ bValue = appPlayer->IsPlayingRDS();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CPVRGUIInfo::CharInfoBackendNumber(std::string& strValue) const
+{
+ size_t numBackends = m_backendProperties.size();
+
+ if (numBackends > 0)
+ strValue = StringUtils::Format("{0} {1} {2}", m_iCurrentActiveClient + 1,
+ g_localizeStrings.Get(20163), numBackends);
+ else
+ strValue = g_localizeStrings.Get(14023);
+}
+
+void CPVRGUIInfo::CharInfoTotalDiskSpace(std::string& strValue) const
+{
+ strValue = StringUtils::SizeToString(m_iBackendDiskTotal).c_str();
+}
+
+void CPVRGUIInfo::CharInfoSignal(std::string& strValue) const
+{
+ strValue = StringUtils::Format("{} %", m_qualityInfo.iSignal / 655);
+}
+
+void CPVRGUIInfo::CharInfoSNR(std::string& strValue) const
+{
+ strValue = StringUtils::Format("{} %", m_qualityInfo.iSNR / 655);
+}
+
+void CPVRGUIInfo::CharInfoBER(std::string& strValue) const
+{
+ strValue = StringUtils::Format("{:08X}", m_qualityInfo.iBER);
+}
+
+void CPVRGUIInfo::CharInfoUNC(std::string& strValue) const
+{
+ strValue = StringUtils::Format("{:08X}", m_qualityInfo.iUNC);
+}
+
+void CPVRGUIInfo::CharInfoFrontendName(std::string& strValue) const
+{
+ if (!strlen(m_qualityInfo.strAdapterName))
+ strValue = g_localizeStrings.Get(13205);
+ else
+ strValue = m_qualityInfo.strAdapterName;
+}
+
+void CPVRGUIInfo::CharInfoFrontendStatus(std::string& strValue) const
+{
+ if (!strlen(m_qualityInfo.strAdapterStatus))
+ strValue = g_localizeStrings.Get(13205);
+ else
+ strValue = m_qualityInfo.strAdapterStatus;
+}
+
+void CPVRGUIInfo::CharInfoBackendName(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendName;
+}
+
+void CPVRGUIInfo::CharInfoBackendVersion(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendVersion;
+}
+
+void CPVRGUIInfo::CharInfoBackendHost(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendHost;
+}
+
+void CPVRGUIInfo::CharInfoBackendDiskspace(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+
+ auto diskTotal = m_iBackendDiskTotal;
+ auto diskUsed = m_iBackendDiskUsed;
+
+ if (diskTotal > 0)
+ {
+ strValue = StringUtils::Format(g_localizeStrings.Get(802),
+ StringUtils::SizeToString(diskTotal - diskUsed),
+ StringUtils::SizeToString(diskTotal));
+ }
+ else
+ strValue = g_localizeStrings.Get(13205);
+}
+
+void CPVRGUIInfo::CharInfoBackendProviders(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendProviders;
+}
+
+void CPVRGUIInfo::CharInfoBackendChannelGroups(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendChannelGroups;
+}
+
+void CPVRGUIInfo::CharInfoBackendChannels(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendChannels;
+}
+
+void CPVRGUIInfo::CharInfoBackendTimers(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendTimers;
+}
+
+void CPVRGUIInfo::CharInfoBackendRecordings(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendRecordings;
+}
+
+void CPVRGUIInfo::CharInfoBackendDeletedRecordings(std::string& strValue) const
+{
+ m_updateBackendCacheRequested = true;
+ strValue = m_strBackendDeletedRecordings;
+}
+
+void CPVRGUIInfo::CharInfoPlayingClientName(std::string& strValue) const
+{
+ if (m_strPlayingClientName.empty())
+ strValue = g_localizeStrings.Get(13205);
+ else
+ strValue = m_strPlayingClientName;
+}
+
+void CPVRGUIInfo::CharInfoEncryption(std::string& strValue) const
+{
+ if (m_descrambleInfo.iCaid != PVR_DESCRAMBLE_INFO_NOT_AVAILABLE)
+ {
+ // prefer dynamically updated info, if available
+ strValue = CPVRChannel::GetEncryptionName(m_descrambleInfo.iCaid);
+ return;
+ }
+ else
+ {
+ const std::shared_ptr<CPVRChannel> channel =
+ CServiceBroker::GetPVRManager().PlaybackState()->GetPlayingChannel();
+ if (channel)
+ {
+ strValue = channel->EncryptionName();
+ return;
+ }
+ }
+
+ strValue.clear();
+}
+
+void CPVRGUIInfo::CharInfoService(std::string& strValue) const
+{
+ if (!strlen(m_qualityInfo.strServiceName))
+ strValue = g_localizeStrings.Get(13205);
+ else
+ strValue = m_qualityInfo.strServiceName;
+}
+
+void CPVRGUIInfo::CharInfoMux(std::string& strValue) const
+{
+ if (!strlen(m_qualityInfo.strMuxName))
+ strValue = g_localizeStrings.Get(13205);
+ else
+ strValue = m_qualityInfo.strMuxName;
+}
+
+void CPVRGUIInfo::CharInfoProvider(std::string& strValue) const
+{
+ if (!strlen(m_qualityInfo.strProviderName))
+ strValue = g_localizeStrings.Get(13205);
+ else
+ strValue = m_qualityInfo.strProviderName;
+}
+
+void CPVRGUIInfo::UpdateBackendCache()
+{
+ std::unique_lock<CCriticalSection> lock(m_critSection);
+
+ // Update the backend information for all backends if
+ // an update has been requested
+ if (m_iCurrentActiveClient == 0 && m_updateBackendCacheRequested)
+ {
+ std::vector<SBackend> backendProperties;
+ {
+ CSingleExit exit(m_critSection);
+ backendProperties = CServiceBroker::GetPVRManager().Clients()->GetBackendProperties();
+ }
+
+ m_backendProperties = backendProperties;
+ m_updateBackendCacheRequested = false;
+ }
+
+ // Store some defaults
+ m_strBackendName = g_localizeStrings.Get(13205);
+ m_strBackendVersion = g_localizeStrings.Get(13205);
+ m_strBackendHost = g_localizeStrings.Get(13205);
+ m_strBackendProviders = g_localizeStrings.Get(13205);
+ m_strBackendChannelGroups = g_localizeStrings.Get(13205);
+ m_strBackendChannels = g_localizeStrings.Get(13205);
+ m_strBackendTimers = g_localizeStrings.Get(13205);
+ m_strBackendRecordings = g_localizeStrings.Get(13205);
+ m_strBackendDeletedRecordings = g_localizeStrings.Get(13205);
+ m_iBackendDiskTotal = 0;
+ m_iBackendDiskUsed = 0;
+
+ // Update with values from the current client when we have at least one
+ if (!m_backendProperties.empty())
+ {
+ const auto& backend = m_backendProperties[m_iCurrentActiveClient];
+
+ m_strBackendName = backend.name;
+ m_strBackendVersion = backend.version;
+ m_strBackendHost = backend.host;
+
+ // We always display one extra as the add-on itself counts as a provider
+ if (backend.numProviders >= 0)
+ m_strBackendProviders = std::to_string(backend.numProviders + 1);
+
+ if (backend.numChannelGroups >= 0)
+ m_strBackendChannelGroups = std::to_string(backend.numChannelGroups);
+
+ if (backend.numChannels >= 0)
+ m_strBackendChannels = std::to_string(backend.numChannels);
+
+ if (backend.numTimers >= 0)
+ m_strBackendTimers = std::to_string(backend.numTimers);
+
+ if (backend.numRecordings >= 0)
+ m_strBackendRecordings = std::to_string(backend.numRecordings);
+
+ if (backend.numDeletedRecordings >= 0)
+ m_strBackendDeletedRecordings = std::to_string(backend.numDeletedRecordings);
+
+ m_iBackendDiskTotal = backend.diskTotal;
+ m_iBackendDiskUsed = backend.diskUsed;
+ }
+
+ // Update the current active client, eventually wrapping around
+ if (++m_iCurrentActiveClient >= m_backendProperties.size())
+ m_iCurrentActiveClient = 0;
+}
+
+void CPVRGUIInfo::UpdateTimersCache()
+{
+ m_anyTimersInfo.UpdateTimersCache();
+ m_tvTimersInfo.UpdateTimersCache();
+ m_radioTimersInfo.UpdateTimersCache();
+}
+
+void CPVRGUIInfo::UpdateTimersToggle()
+{
+ m_anyTimersInfo.UpdateTimersToggle();
+ m_tvTimersInfo.UpdateTimersToggle();
+ m_radioTimersInfo.UpdateTimersToggle();
+}
+
+void CPVRGUIInfo::UpdateNextTimer()
+{
+ m_anyTimersInfo.UpdateNextTimer();
+ m_tvTimersInfo.UpdateNextTimer();
+ m_radioTimersInfo.UpdateNextTimer();
+}
+
+int CPVRGUIInfo::GetTimeShiftSeekPercent() const
+{
+ int progress = m_timesInfo.GetTimeshiftProgressPlayPosition();
+
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ int seekSize = appPlayer->GetSeekHandler().GetSeekSize();
+ if (seekSize != 0)
+ {
+ int total = m_timesInfo.GetTimeshiftProgressDuration();
+
+ float totalTime = static_cast<float>(total);
+ if (totalTime == 0.0f)
+ return 0;
+
+ float percentPerSecond = 100.0f / totalTime;
+ float percent = progress + percentPerSecond * seekSize;
+ percent = std::max(0.0f, std::min(percent, 100.0f));
+ return std::lrintf(percent);
+ }
+ return progress;
+}