summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/RssManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/RssManager.cpp')
-rw-r--r--xbmc/utils/RssManager.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/xbmc/utils/RssManager.cpp b/xbmc/utils/RssManager.cpp
new file mode 100644
index 0000000..2e26b4e
--- /dev/null
+++ b/xbmc/utils/RssManager.cpp
@@ -0,0 +1,198 @@
1/*
2 * Copyright (C) 2005-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 "RssManager.h"
10
11#include "ServiceBroker.h"
12#include "addons/AddonInstaller.h"
13#include "addons/AddonManager.h"
14#include "filesystem/File.h"
15#include "interfaces/builtins/Builtins.h"
16#include "messaging/helpers/DialogHelper.h"
17#include "profiles/ProfileManager.h"
18#include "settings/Settings.h"
19#include "settings/SettingsComponent.h"
20#include "settings/lib/Setting.h"
21#include "threads/SingleLock.h"
22#include "utils/RssReader.h"
23#include "utils/StringUtils.h"
24#include "utils/Variant.h"
25#include "utils/log.h"
26
27#include <utility>
28
29using namespace XFILE;
30using namespace KODI::MESSAGING;
31
32
33CRssManager::CRssManager()
34{
35 m_bActive = false;
36}
37
38CRssManager::~CRssManager()
39{
40 Stop();
41}
42
43CRssManager& CRssManager::GetInstance()
44{
45 static CRssManager sRssManager;
46 return sRssManager;
47}
48
49void CRssManager::OnSettingsLoaded()
50{
51 Load();
52}
53
54void CRssManager::OnSettingsUnloaded()
55{
56 Clear();
57}
58
59void CRssManager::OnSettingAction(std::shared_ptr<const CSetting> setting)
60{
61 if (setting == NULL)
62 return;
63
64 const std::string &settingId = setting->GetId();
65 if (settingId == CSettings::SETTING_LOOKANDFEEL_RSSEDIT)
66 {
67 ADDON::AddonPtr addon;
68 if (!CServiceBroker::GetAddonMgr().GetAddon("script.rss.editor", addon))
69 {
70 if (!CAddonInstaller::GetInstance().InstallModal("script.rss.editor", addon))
71 return;
72 }
73 CBuiltins::GetInstance().Execute("RunScript(script.rss.editor)");
74 }
75}
76
77void CRssManager::Start()
78 {
79 m_bActive = true;
80}
81
82void CRssManager::Stop()
83{
84 CSingleLock lock(m_critical);
85 m_bActive = false;
86 for (unsigned int i = 0; i < m_readers.size(); i++)
87 {
88 if (m_readers[i].reader)
89 delete m_readers[i].reader;
90 }
91 m_readers.clear();
92}
93
94bool CRssManager::Load()
95{
96 const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
97
98 CSingleLock lock(m_critical);
99
100 std::string rssXML = profileManager->GetUserDataItem("RssFeeds.xml");
101 if (!CFile::Exists(rssXML))
102 return false;
103
104 CXBMCTinyXML rssDoc;
105 if (!rssDoc.LoadFile(rssXML))
106 {
107 CLog::Log(LOGERROR, "CRssManager: error loading %s, Line %d\n%s", rssXML.c_str(), rssDoc.ErrorRow(), rssDoc.ErrorDesc());
108 return false;
109 }
110
111 const TiXmlElement *pRootElement = rssDoc.RootElement();
112 if (pRootElement == NULL || !StringUtils::EqualsNoCase(pRootElement->ValueStr(), "rssfeeds"))
113 {
114 CLog::Log(LOGERROR, "CRssManager: error loading %s, no <rssfeeds> node", rssXML.c_str());
115 return false;
116 }
117
118 m_mapRssUrls.clear();
119 const TiXmlElement* pSet = pRootElement->FirstChildElement("set");
120 while (pSet != NULL)
121 {
122 int iId;
123 if (pSet->QueryIntAttribute("id", &iId) == TIXML_SUCCESS)
124 {
125 RssSet set;
126 set.rtl = pSet->Attribute("rtl") != NULL &&
127 StringUtils::CompareNoCase(pSet->Attribute("rtl"), "true") == 0;
128 const TiXmlElement* pFeed = pSet->FirstChildElement("feed");
129 while (pFeed != NULL)
130 {
131 int iInterval;
132 if (pFeed->QueryIntAttribute("updateinterval", &iInterval) != TIXML_SUCCESS)
133 {
134 iInterval = 30; // default to 30 min
135 CLog::Log(LOGDEBUG, "CRssManager: no interval set, default to 30!");
136 }
137
138 if (pFeed->FirstChild() != NULL)
139 {
140 //! @todo UTF-8: Do these URLs need to be converted to UTF-8?
141 //! What about the xml encoding?
142 std::string strUrl = pFeed->FirstChild()->ValueStr();
143 set.url.push_back(strUrl);
144 set.interval.push_back(iInterval);
145 }
146 pFeed = pFeed->NextSiblingElement("feed");
147 }
148
149 m_mapRssUrls.insert(std::make_pair(iId,set));
150 }
151 else
152 CLog::Log(LOGERROR, "CRssManager: found rss url set with no id in RssFeeds.xml, ignored");
153
154 pSet = pSet->NextSiblingElement("set");
155 }
156
157 return true;
158}
159
160bool CRssManager::Reload()
161{
162 Stop();
163 if (!Load())
164 return false;
165 Start();
166
167 return true;
168}
169
170void CRssManager::Clear()
171{
172 CSingleLock lock(m_critical);
173 m_mapRssUrls.clear();
174}
175
176// returns true if the reader doesn't need creating, false otherwise
177bool CRssManager::GetReader(int controlID, int windowID, IRssObserver* observer, CRssReader *&reader)
178{
179 CSingleLock lock(m_critical);
180 // check to see if we've already created this reader
181 for (unsigned int i = 0; i < m_readers.size(); i++)
182 {
183 if (m_readers[i].controlID == controlID && m_readers[i].windowID == windowID)
184 {
185 reader = m_readers[i].reader;
186 reader->SetObserver(observer);
187 reader->UpdateObserver();
188 return true;
189 }
190 }
191 // need to create a new one
192 READERCONTROL readerControl;
193 readerControl.controlID = controlID;
194 readerControl.windowID = windowID;
195 reader = readerControl.reader = new CRssReader;
196 m_readers.push_back(readerControl);
197 return false;
198}