1 /* 2 * Copyright (C) 2005-2021 Team Kodi (https://kodi.tv) 3 * 4 * SPDX-License-Identifier: GPL-2.0-or-later 5 * See LICENSE.md for more information. 6 */ 7 8 #pragma once 9 10 #include "data/Channel.h" 11 #include "utilities/Logger.h" 12 13 #include <string> 14 #include <type_traits> 15 16 #include <kodi/AddonBase.h> 17 18 namespace iptvsimple 19 { 20 static const std::string M3U_CACHE_FILENAME = "iptv.m3u.cache"; 21 static const std::string XMLTV_CACHE_FILENAME = "xmltv.xml.cache"; 22 static const std::string ADDON_DATA_BASE_DIR = "special://userdata/addon_data/pvr.iptvsimple"; 23 static const std::string DEFAULT_GENRE_TEXT_MAP_FILE = ADDON_DATA_BASE_DIR + "/genres/genreTextMappings/genres.xml"; 24 static const int DEFAULT_UDPXY_MULTICAST_RELAY_PORT = 4022; 25 26 static const int DEFAULT_NUM_GROUPS = 1; 27 static const std::string CHANNEL_GROUPS_DIR = "/channelGroups"; 28 static const std::string DEFAULT_CUSTOM_TV_GROUPS_FILE = ADDON_DATA_BASE_DIR + "/channelGroups/customTVGroups-example.xml"; 29 static const std::string DEFAULT_CUSTOM_RADIO_GROUPS_FILE = ADDON_DATA_BASE_DIR + "/channelGroups/customRadioGroups-example.xml"; 30 static const std::string CHANNEL_GROUPS_ADDON_DATA_BASE_DIR = ADDON_DATA_BASE_DIR + CHANNEL_GROUPS_DIR; 31 32 enum class PathType 33 : int // same type as addon settings 34 { 35 LOCAL_PATH = 0, 36 REMOTE_PATH 37 }; 38 39 enum class RefreshMode 40 : int // same type as addon settings 41 { 42 DISABLED = 0, 43 REPEATED_REFRESH, 44 ONCE_PER_DAY 45 }; 46 47 enum class ChannelGroupMode 48 : int // same type as addon settings 49 { 50 ALL_GROUPS = 0, 51 SOME_GROUPS, 52 CUSTOM_GROUPS 53 }; 54 55 enum class EpgLogosMode 56 : int // same type as addon settings 57 { 58 IGNORE_XMLTV = 0, 59 PREFER_M3U, 60 PREFER_XMLTV 61 }; 62 63 enum class CatchupOverrideMode 64 : int // same type as addon settings 65 { 66 WITHOUT_TAGS = 0, 67 WITH_TAGS, 68 ALL_CHANNELS 69 }; 70 71 class Settings 72 { 73 public: 74 /** 75 * Singleton getter for the instance 76 */ GetInstance()77 static Settings& GetInstance() 78 { 79 static Settings settings; 80 return settings; 81 } 82 83 void ReadFromAddon(const std::string& userPath, const std::string& clientPath); 84 void ReloadAddonSettings(); 85 ADDON_STATUS SetValue(const std::string& settingName, const kodi::CSettingValue& settingValue); 86 GetUserPath()87 const std::string& GetUserPath() const { return m_userPath; } GetClientPath()88 const std::string& GetClientPath() const { return m_clientPath; } 89 GetM3ULocation()90 const std::string& GetM3ULocation() const { return m_m3uPathType == PathType::REMOTE_PATH ? m_m3uUrl : m_m3uPath; } GetM3UPathType()91 const PathType& GetM3UPathType() const { return m_m3uPathType; } GetM3UPath()92 const std::string& GetM3UPath() const { return m_m3uPath; } GetM3UUrl()93 const std::string& GetM3UUrl() const { return m_m3uUrl; } UseM3UCache()94 bool UseM3UCache() const { return m_m3uPathType == PathType::REMOTE_PATH ? m_cacheM3U : false; } GetStartChannelNumber()95 int GetStartChannelNumber() const { return m_startChannelNumber; } NumberChannelsByM3uOrderOnly()96 bool NumberChannelsByM3uOrderOnly() const { return m_numberChannelsByM3uOrderOnly; } GetM3URefreshMode()97 const RefreshMode& GetM3URefreshMode() const { return m_m3uRefreshMode; } GetM3URefreshIntervalMins()98 int GetM3URefreshIntervalMins() const { return m_m3uRefreshIntervalMins; } GetM3URefreshHour()99 int GetM3URefreshHour() const { return m_m3uRefreshHour; } AllowTVChannelGroupsOnly()100 bool AllowTVChannelGroupsOnly() const { return m_allowTVChannelGroupsOnly; } GetTVChannelGroupMode()101 const ChannelGroupMode& GetTVChannelGroupMode() const { return m_tvChannelGroupMode; } GetCustomTVGroupsFile()102 const std::string& GetCustomTVGroupsFile() const { return m_customTVGroupsFile; } AllowRadioChannelGroupsOnly()103 bool AllowRadioChannelGroupsOnly() const { return m_allowRadioChannelGroupsOnly; } GetRadioChannelGroupMode()104 const ChannelGroupMode& GetRadioChannelGroupMode() const { return m_radioChannelGroupMode; } GetCustomRadioGroupsFile()105 const std::string& GetCustomRadioGroupsFile() const { return m_customRadioGroupsFile; } 106 GetEpgLocation()107 const std::string& GetEpgLocation() const 108 { 109 const std::string& epgLocation = m_epgPathType == PathType::REMOTE_PATH ? m_epgUrl : m_epgPath; 110 return epgLocation.empty() ? m_tvgUrl : epgLocation; 111 } GetEpgPathType()112 const PathType& GetEpgPathType() const { return m_epgPathType; } GetEpgPath()113 const std::string& GetEpgPath() const { return m_epgPath; } GetEpgUrl()114 const std::string& GetEpgUrl() const { return m_epgUrl; } UseEPGCache()115 bool UseEPGCache() const { return m_epgPathType == PathType::REMOTE_PATH ? m_cacheEPG : false; } GetEpgTimeshiftHours()116 float GetEpgTimeshiftHours() const { return m_epgTimeShiftHours; } GetEpgTimeshiftSecs()117 int GetEpgTimeshiftSecs() const { return static_cast<int>(m_epgTimeShiftHours * 60 * 60); } GetTsOverride()118 bool GetTsOverride() const { return m_tsOverride; } AlwaysLoadEPGData()119 bool AlwaysLoadEPGData() const { return m_epgLogosMode == EpgLogosMode::PREFER_XMLTV || IsCatchupEnabled(); } 120 GetGenresLocation()121 const std::string& GetGenresLocation() const { return m_genresPathType == PathType::REMOTE_PATH ? m_genresUrl : m_genresPath; } UseEpgGenreTextWhenMapping()122 bool UseEpgGenreTextWhenMapping() const { return m_useEpgGenreTextWhenMapping; } GetGenresPathType()123 const PathType& GetGenresPathType() const { return m_genresPathType; } GetGenresPath()124 const std::string& GetGenresPath() const { return m_genresPath; } GetGenresUrl()125 const std::string& GetGenresUrl() const { return m_genresUrl; } 126 GetLogoLocation()127 const std::string& GetLogoLocation() const { return m_logoPathType == PathType::REMOTE_PATH ? m_logoBaseUrl : m_logoPath; } GetLogoPathType()128 const PathType& GetLogoPathType() const { return m_logoPathType; } GetLogoPath()129 const std::string& GetLogoPath() const { return m_logoPath; } GetLogoBaseUrl()130 const std::string& GetLogoBaseUrl() const { return m_logoBaseUrl; } GetEpgLogosMode()131 const EpgLogosMode& GetEpgLogosMode() const { return m_epgLogosMode; } UseLocalLogosOnlyIgnoreM3U()132 bool UseLocalLogosOnlyIgnoreM3U() const { return m_useLocalLogosOnly; } 133 IsTimeshiftEnabled()134 bool IsTimeshiftEnabled() const { return m_timeshiftEnabled; } IsTimeshiftEnabledAll()135 bool IsTimeshiftEnabledAll() const { return m_timeshiftEnabledAll; } IsTimeshiftEnabledHttp()136 bool IsTimeshiftEnabledHttp() const { return m_timeshiftEnabledHttp; } IsTimeshiftEnabledUdp()137 bool IsTimeshiftEnabledUdp() const { return m_timeshiftEnabledUdp; } AlwaysEnableTimeshiftModeIfMissing()138 bool AlwaysEnableTimeshiftModeIfMissing() const { return m_timeshiftEnabledCustom; } 139 IsCatchupEnabled()140 bool IsCatchupEnabled() const { return m_catchupEnabled; } GetCatchupQueryFormat()141 const std::string& GetCatchupQueryFormat() const { return m_catchupQueryFormat; } GetCatchupDays()142 int GetCatchupDays() const { return m_catchupDays; } GetCatchupDaysInSeconds()143 time_t GetCatchupDaysInSeconds() const { return static_cast<time_t>(m_catchupDays) * 24 * 60 * 60; } GetAllChannelsCatchupMode()144 const CatchupMode& GetAllChannelsCatchupMode() const { return m_allChannelsCatchupMode; } GetCatchupOverrideMode()145 const CatchupOverrideMode& GetCatchupOverrideMode() const { return m_catchupOverrideMode; } GetCatchupCorrectionHours()146 float GetCatchupCorrectionHours() const { return m_catchupCorrectionHours; } GetCatchupCorrectionSecs()147 int GetCatchupCorrectionSecs() const { return static_cast<int>(m_catchupCorrectionHours * 60 * 60); } CatchupPlayEpgAsLive()148 bool CatchupPlayEpgAsLive() const { return m_catchupPlayEpgAsLive; } GetCatchupWatchEpgBeginBufferMins()149 int GetCatchupWatchEpgBeginBufferMins() const { return m_catchupWatchEpgBeginBufferMins; } GetCatchupWatchEpgBeginBufferSecs()150 time_t GetCatchupWatchEpgBeginBufferSecs() const { return static_cast<time_t>(m_catchupWatchEpgBeginBufferMins) * 60; } GetCatchupWatchEpgEndBufferMins()151 int GetCatchupWatchEpgEndBufferMins() const { return m_catchupWatchEpgEndBufferMins; } GetCatchupWatchEpgEndBufferSecs()152 time_t GetCatchupWatchEpgEndBufferSecs() const { return static_cast<time_t>(m_catchupWatchEpgEndBufferMins) * 60; } CatchupOnlyOnFinishedProgrammes()153 bool CatchupOnlyOnFinishedProgrammes() const { return m_catchupOnlyOnFinishedProgrammes; } 154 TransformMulticastStreamUrls()155 bool TransformMulticastStreamUrls() const { return m_transformMulticastStreamUrls; } GetUdpxyHost()156 const std::string& GetUdpxyHost() const { return m_udpxyHost; } GetUdpxyPort()157 int GetUdpxyPort() const { return m_udpxyPort; } UseFFmpegReconnect()158 bool UseFFmpegReconnect() const { return m_useFFmpegReconnect; } UseInputstreamAdaptiveforHls()159 bool UseInputstreamAdaptiveforHls() const { return m_useInputstreamAdaptiveforHls; } GetDefaultUserAgent()160 const std::string& GetDefaultUserAgent() const { return m_defaultUserAgent; } GetDefaultInputstream()161 const std::string& GetDefaultInputstream() const { return m_defaultInputstream; } GetDefaultMimeType()162 const std::string& GetDefaultMimeType() const { return m_defaultMimeType; } 163 GetTvgUrl()164 const std::string& GetTvgUrl() const { return m_tvgUrl; } SetTvgUrl(const std::string & tvgUrl)165 void SetTvgUrl(const std::string& tvgUrl) { m_tvgUrl = tvgUrl; } 166 GetCustomTVChannelGroupNameList()167 std::vector<std::string>& GetCustomTVChannelGroupNameList() { return m_customTVChannelGroupNameList; } GetCustomRadioChannelGroupNameList()168 std::vector<std::string>& GetCustomRadioChannelGroupNameList() { return m_customRadioChannelGroupNameList; } 169 170 private: 171 Settings() = default; 172 173 Settings(Settings const&) = delete; 174 void operator=(Settings const&) = delete; 175 176 template<typename T, typename V> SetSetting(const std::string & settingName,const kodi::CSettingValue & settingValue,T & currentValue,V returnValueIfChanged,V defaultReturnValue)177 V SetSetting(const std::string& settingName, const kodi::CSettingValue& settingValue, T& currentValue, V returnValueIfChanged, V defaultReturnValue) 178 { 179 T newValue; 180 if (std::is_same<T, float>::value) 181 newValue = static_cast<T>(settingValue.GetFloat()); 182 else if (std::is_same<T, bool>::value) 183 newValue = static_cast<T>(settingValue.GetBoolean()); 184 else if (std::is_same<T, unsigned int>::value) 185 newValue = static_cast<T>(settingValue.GetUInt()); 186 else 187 newValue = static_cast<T>(settingValue.GetInt()); 188 189 if (newValue != currentValue) 190 { 191 std::string formatString = "%s - Changed Setting '%s' from %d to %d"; 192 if (std::is_same<T, float>::value) 193 formatString = "%s - Changed Setting '%s' from %f to %f"; 194 utilities::Logger::Log(utilities::LogLevel::LEVEL_INFO, formatString.c_str(), __FUNCTION__, settingName.c_str(), currentValue, newValue); 195 currentValue = newValue; 196 return returnValueIfChanged; 197 } 198 199 return defaultReturnValue; 200 } 201 202 template<typename T, typename V> SetEnumSetting(const std::string & settingName,const kodi::CSettingValue & settingValue,T & currentValue,V returnValueIfChanged,V defaultReturnValue)203 V SetEnumSetting(const std::string& settingName, const kodi::CSettingValue& settingValue, T& currentValue, V returnValueIfChanged, V defaultReturnValue) 204 { 205 T newValue = settingValue.GetEnum<T>(); 206 if (newValue != currentValue) 207 { 208 utilities::Logger::Log(utilities::LogLevel::LEVEL_INFO, "%s - Changed Setting '%s' from %d to %d", __FUNCTION__, settingName.c_str(), currentValue, newValue); 209 currentValue = newValue; 210 return returnValueIfChanged; 211 } 212 213 return defaultReturnValue; 214 } 215 216 template<typename V> SetStringSetting(const std::string & settingName,const kodi::CSettingValue & settingValue,std::string & currentValue,V returnValueIfChanged,V defaultReturnValue)217 V SetStringSetting(const std::string& settingName, const kodi::CSettingValue& settingValue, std::string& currentValue, V returnValueIfChanged, V defaultReturnValue) 218 { 219 const std::string strSettingValue = settingValue.GetString(); 220 221 if (strSettingValue != currentValue) 222 { 223 utilities::Logger::Log(utilities::LogLevel::LEVEL_INFO, "%s - Changed Setting '%s' from '%s' to '%s'", __FUNCTION__, settingName.c_str(), currentValue.c_str(), strSettingValue.c_str()); 224 currentValue = strSettingValue; 225 return returnValueIfChanged; 226 } 227 228 return defaultReturnValue; 229 } 230 231 static bool LoadCustomChannelGroupFile(std::string& file, std::vector<std::string>& channelGroupNameList); 232 233 std::string m_userPath; 234 std::string m_clientPath; 235 236 // M3U 237 PathType m_m3uPathType = PathType::REMOTE_PATH; 238 std::string m_m3uPath; 239 std::string m_m3uUrl; 240 bool m_cacheM3U = false; 241 int m_startChannelNumber = 1; 242 bool m_numberChannelsByM3uOrderOnly = false; 243 RefreshMode m_m3uRefreshMode = RefreshMode::DISABLED; 244 int m_m3uRefreshIntervalMins = 60; 245 int m_m3uRefreshHour = 4; 246 bool m_allowTVChannelGroupsOnly = false; 247 ChannelGroupMode m_tvChannelGroupMode = ChannelGroupMode::ALL_GROUPS; 248 unsigned int m_numTVGroups = DEFAULT_NUM_GROUPS; 249 std::string m_oneTVGroup = ""; 250 std::string m_twoTVGroup = ""; 251 std::string m_threeTVGroup = ""; 252 std::string m_fourTVGroup = ""; 253 std::string m_fiveTVGroup = ""; 254 std::string m_customTVGroupsFile = ""; 255 bool m_allowRadioChannelGroupsOnly = false; 256 ChannelGroupMode m_radioChannelGroupMode = ChannelGroupMode::ALL_GROUPS; 257 unsigned int m_numRadioGroups = DEFAULT_NUM_GROUPS; 258 std::string m_oneRadioGroup = ""; 259 std::string m_twoRadioGroup = ""; 260 std::string m_threeRadioGroup = ""; 261 std::string m_fourRadioGroup = ""; 262 std::string m_fiveRadioGroup = ""; 263 std::string m_customRadioGroupsFile = ""; 264 265 // EPG 266 PathType m_epgPathType = PathType::REMOTE_PATH; 267 std::string m_epgPath; 268 std::string m_epgUrl; 269 bool m_cacheEPG = false; 270 float m_epgTimeShiftHours = 0; 271 bool m_tsOverride = true; 272 273 // Genres 274 bool m_useEpgGenreTextWhenMapping = false; 275 PathType m_genresPathType = PathType::LOCAL_PATH; 276 std::string m_genresPath; 277 std::string m_genresUrl; 278 279 // Channel Logos 280 PathType m_logoPathType = PathType::REMOTE_PATH; 281 std::string m_logoPath; 282 std::string m_logoBaseUrl; 283 EpgLogosMode m_epgLogosMode = EpgLogosMode::IGNORE_XMLTV; 284 bool m_useLocalLogosOnly = false; 285 286 // Timeshift 287 bool m_timeshiftEnabled = false; 288 bool m_timeshiftEnabledAll = false; 289 bool m_timeshiftEnabledHttp = false; 290 bool m_timeshiftEnabledUdp = false; 291 bool m_timeshiftEnabledCustom = false; 292 293 // Catchup 294 bool m_catchupEnabled = false; 295 std::string m_catchupQueryFormat; 296 int m_catchupDays = 3; 297 CatchupMode m_allChannelsCatchupMode = CatchupMode::DISABLED; 298 CatchupOverrideMode m_catchupOverrideMode = CatchupOverrideMode::WITHOUT_TAGS; 299 float m_catchupCorrectionHours = 0; 300 bool m_catchupPlayEpgAsLive = false; 301 int m_catchupWatchEpgBeginBufferMins = 5; 302 int m_catchupWatchEpgEndBufferMins = 15; 303 bool m_catchupOnlyOnFinishedProgrammes = false; 304 305 // Advanced 306 bool m_transformMulticastStreamUrls = false; 307 std::string m_udpxyHost; 308 int m_udpxyPort = DEFAULT_UDPXY_MULTICAST_RELAY_PORT; 309 bool m_useFFmpegReconnect = true; 310 bool m_useInputstreamAdaptiveforHls = false; 311 std::string m_defaultUserAgent; 312 std::string m_defaultInputstream; 313 std::string m_defaultMimeType; 314 315 std::vector<std::string> m_customTVChannelGroupNameList; 316 std::vector<std::string> m_customRadioChannelGroupNameList; 317 318 std::string m_tvgUrl; 319 }; 320 } //namespace iptvsimple 321