1 /*
2 * Copyright (C) 2015-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9 #include "PVRSettings.h"
10
11 #include "ServiceBroker.h"
12 #include "guilib/LocalizeStrings.h"
13 #include "pvr/PVRManager.h"
14 #include "pvr/addons/PVRClients.h"
15 #include "pvr/guilib/PVRGUIActions.h"
16 #include "settings/Settings.h"
17 #include "settings/SettingsComponent.h"
18 #include "settings/lib/SettingsManager.h"
19 #include "utils/StringUtils.h"
20 #include "utils/log.h"
21
22 #include <memory>
23 #include <set>
24 #include <string>
25 #include <utility>
26
27 using namespace PVR;
28
29 unsigned int CPVRSettings::m_iInstances = 0;
30
CPVRSettings(const std::set<std::string> & settingNames)31 CPVRSettings::CPVRSettings(const std::set<std::string>& settingNames)
32 {
33 Init(settingNames);
34
35 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
36 settings->GetSettingsManager()->RegisterSettingsHandler(this);
37 settings->RegisterCallback(this, settingNames);
38
39 if (m_iInstances == 0)
40 {
41 // statics must only be registered once, not per instance
42 settings->GetSettingsManager()->RegisterSettingOptionsFiller("pvrrecordmargins", MarginTimeFiller);
43 settings->GetSettingsManager()->AddDynamicCondition("pvrsettingvisible", IsSettingVisible);
44 settings->GetSettingsManager()->AddDynamicCondition("checkpvrparentalpin", CheckParentalPin);
45 }
46 m_iInstances++;
47 }
48
~CPVRSettings()49 CPVRSettings::~CPVRSettings()
50 {
51 const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
52
53 m_iInstances--;
54 if (m_iInstances == 0)
55 {
56 settings->GetSettingsManager()->RemoveDynamicCondition("checkpvrparentalpin");
57 settings->GetSettingsManager()->RemoveDynamicCondition("pvrsettingvisible");
58 settings->GetSettingsManager()->UnregisterSettingOptionsFiller("pvrrecordmargins");
59 }
60
61 settings->UnregisterCallback(this);
62 settings->GetSettingsManager()->UnregisterSettingsHandler(this);
63 }
64
Init(const std::set<std::string> & settingNames)65 void CPVRSettings::Init(const std::set<std::string>& settingNames)
66 {
67 for (auto settingName : settingNames)
68 {
69 SettingPtr setting = CServiceBroker::GetSettingsComponent()->GetSettings()->GetSetting(settingName);
70 if (!setting)
71 {
72 CLog::LogF(LOGERROR, "Unknown PVR setting '{}'", settingName);
73 continue;
74 }
75
76 CSingleLock lock(m_critSection);
77 m_settings.insert(std::make_pair(settingName, setting->Clone(settingName)));
78 }
79 }
80
OnSettingsLoaded()81 void CPVRSettings::OnSettingsLoaded()
82 {
83 std::set<std::string> settingNames;
84
85 {
86 CSingleLock lock(m_critSection);
87 for (const auto& settingName : m_settings)
88 settingNames.insert(settingName.first);
89
90 m_settings.clear();
91 }
92
93 Init(settingNames);
94 }
95
OnSettingChanged(const std::shared_ptr<const CSetting> & setting)96 void CPVRSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& setting)
97 {
98 if (setting == nullptr)
99 return;
100
101 CSingleLock lock(m_critSection);
102 m_settings[setting->GetId()] = setting->Clone(setting->GetId());
103 }
104
GetBoolValue(const std::string & settingName) const105 bool CPVRSettings::GetBoolValue(const std::string& settingName) const
106 {
107 CSingleLock lock(m_critSection);
108 auto settingIt = m_settings.find(settingName);
109 if (settingIt != m_settings.end() && (*settingIt).second->GetType() == SettingType::Boolean)
110 {
111 std::shared_ptr<const CSettingBool> setting = std::dynamic_pointer_cast<const CSettingBool>((*settingIt).second);
112 if (setting)
113 return setting->GetValue();
114 }
115
116 CLog::LogF(LOGERROR, "PVR setting '{}' not found or wrong type given", settingName);
117 return false;
118 }
119
GetIntValue(const std::string & settingName) const120 int CPVRSettings::GetIntValue(const std::string& settingName) const
121 {
122 CSingleLock lock(m_critSection);
123 auto settingIt = m_settings.find(settingName);
124 if (settingIt != m_settings.end() && (*settingIt).second->GetType() == SettingType::Integer)
125 {
126 std::shared_ptr<const CSettingInt> setting = std::dynamic_pointer_cast<const CSettingInt>((*settingIt).second);
127 if (setting)
128 return setting->GetValue();
129 }
130
131 CLog::LogF(LOGERROR, "PVR setting '{}' not found or wrong type given", settingName);
132 return -1;
133 }
134
GetStringValue(const std::string & settingName) const135 std::string CPVRSettings::GetStringValue(const std::string& settingName) const
136 {
137 CSingleLock lock(m_critSection);
138 auto settingIt = m_settings.find(settingName);
139 if (settingIt != m_settings.end() && (*settingIt).second->GetType() == SettingType::String)
140 {
141 std::shared_ptr<const CSettingString> setting = std::dynamic_pointer_cast<const CSettingString>((*settingIt).second);
142 if (setting)
143 return setting->GetValue();
144 }
145
146 CLog::LogF(LOGERROR, "PVR setting '{}' not found or wrong type given", settingName);
147 return "";
148 }
149
MarginTimeFiller(const SettingConstPtr &,std::vector<IntegerSettingOption> & list,int & current,void *)150 void CPVRSettings::MarginTimeFiller(const SettingConstPtr& /*setting*/,
151 std::vector<IntegerSettingOption>& list,
152 int& current,
153 void* /*data*/)
154 {
155 list.clear();
156
157 static const int marginTimeValues[] =
158 {
159 0, 1, 3, 5, 10, 15, 20, 30, 60, 90, 120, 180 // minutes
160 };
161
162 for (int iValue : marginTimeValues)
163 {
164 list.emplace_back(StringUtils::Format(g_localizeStrings.Get(14044).c_str(), iValue) /* %i min */, iValue);
165 }
166 }
167
IsSettingVisible(const std::string & condition,const std::string & value,const std::shared_ptr<const CSetting> & setting,void * data)168 bool CPVRSettings::IsSettingVisible(const std::string& condition,
169 const std::string& value,
170 const std::shared_ptr<const CSetting>& setting,
171 void* data)
172 {
173 if (setting == nullptr)
174 return false;
175
176 const std::string& settingId = setting->GetId();
177
178 if (settingId == CSettings::SETTING_PVRMANAGER_USEBACKENDCHANNELNUMBERS)
179 {
180 // Setting is only visible if exactly one PVR client is enabled or
181 // the expert setting to always use backend numbers is enabled
182 const auto& settings = CServiceBroker::GetSettingsComponent()->GetSettings();
183 int enabledClientAmount = CServiceBroker::GetPVRManager().Clients()->EnabledClientAmount();
184
185 return enabledClientAmount == 1 ||
186 (settings->GetBool(CSettings::SETTING_PVRMANAGER_USEBACKENDCHANNELNUMBERSALWAYS) &&
187 enabledClientAmount > 1);
188 }
189 else if (settingId == CSettings::SETTING_PVRMANAGER_USEBACKENDCHANNELNUMBERSALWAYS)
190 {
191 // Setting is only visible if more than one PVR client is enabled.
192 return CServiceBroker::GetPVRManager().Clients()->EnabledClientAmount() > 1;
193 }
194 else if (settingId == CSettings::SETTING_PVRMANAGER_CLIENTPRIORITIES)
195 {
196 // Setting is only visible if more than one PVR client is enabeld.
197 return CServiceBroker::GetPVRManager().Clients()->EnabledClientAmount() > 1;
198 }
199 else
200 {
201 // Show all other settings unconditionally.
202 return true;
203 }
204 }
205
CheckParentalPin(const std::string & condition,const std::string & value,const std::shared_ptr<const CSetting> & setting,void * data)206 bool CPVRSettings::CheckParentalPin(const std::string& condition,
207 const std::string& value,
208 const std::shared_ptr<const CSetting>& setting,
209 void* data)
210 {
211 return CServiceBroker::GetPVRManager().GUIActions()->CheckParentalPIN() == ParentalCheckResult::SUCCESS;
212 }
213