Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update channel list with EPG #275

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion src/Channels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "utilities/XMLUtils.h"
#include "pvrclient-nextpvr.h"

#include <kodi/General.h>
#include <kodi/tools/StringUtils.h>
#include "zlib.h"

Expand All @@ -26,6 +27,7 @@ Channels::Channels(const std::shared_ptr<InstanceSettings>& settings, Request& r
int Channels::GetNumChannels()
{
// Kodi polls this while recordings are open avoid calls to backend
std::lock_guard<std::recursive_mutex> lock(m_channelMutex);
int channelCount = m_channelDetails.size();
if (channelCount == 0)
{
Expand Down Expand Up @@ -91,6 +93,7 @@ PVR_ERROR Channels::GetChannels(bool radio, kodi::addon::PVRChannelsResultSet& r
return PVR_ERROR_NO_ERROR;
PVR_ERROR returnValue = PVR_ERROR_NO_ERROR;
std::string stream;
std::lock_guard<std::recursive_mutex> lock(m_channelMutex);
std::map<int, std::pair<bool, bool>>::iterator itr = m_channelDetails.begin();
while (itr != m_channelDetails.end())
{
Expand Down Expand Up @@ -168,6 +171,44 @@ PVR_ERROR Channels::GetChannels(bool radio, kodi::addon::PVRChannelsResultSet& r
return returnValue;
}

bool Channels::ResetChannelList(time_t updateTime)
{
// normally GetChannels loads the internal channel list;
// force update in case GetChannels is not called before EPG triggers
std::string checksum = m_checksumChannelList;
CacheAllChannels(updateTime);
if (checksum != m_checksumChannelList)
{
std::lock_guard<std::recursive_mutex> lock(m_channelMutex);
m_channelDetails.clear();
tinyxml2::XMLDocument doc;
if (ReadCachedChannelList(doc) == tinyxml2::XML_SUCCESS)
{
tinyxml2::XMLNode* channelsNode = doc.RootElement()->FirstChildElement("channels");
tinyxml2::XMLNode* pChannelNode;
for (pChannelNode = channelsNode->FirstChildElement("channel"); pChannelNode; pChannelNode = pChannelNode->NextSiblingElement())
{
std::string buffer;
bool isRadio = false;
XMLUtils::GetString(pChannelNode, "type", buffer);
if (buffer == "0xa")
{
if (!m_settings->m_showRadio)
continue;
isRadio = true;
}
std::string epg;
if (XMLUtils::GetString(pChannelNode, "epg", epg))
m_channelDetails[XMLUtils::GetUIntValue(pChannelNode, "id")] = std::make_pair(epg == "None", isRadio);
else
m_channelDetails[XMLUtils::GetUIntValue(pChannelNode, "id")] = std::make_pair(false, isRadio);
}
return true;
}
}
return false;
}


/************************************************************/
/** Channel group handling **/
Expand All @@ -182,6 +223,7 @@ PVR_ERROR Channels::GetChannelGroupsAmount(int& amount)
PVR_RECORDING_CHANNEL_TYPE Channels::GetChannelType(unsigned int uid)
{
// when uid is invalid we assume TV because Kodi will
std::lock_guard<std::recursive_mutex> lock(m_channelMutex);
if (m_channelDetails.count(uid) > 0 && m_channelDetails[uid].second == true)
return PVR_RECORDING_CHANNEL_TYPE_RADIO;

Expand All @@ -192,7 +234,7 @@ PVR_ERROR Channels::GetChannelGroups(bool radio, kodi::addon::PVRChannelGroupsRe
{
if (radio && !m_settings->m_showRadio)
return PVR_ERROR_NO_ERROR;

std::lock_guard<std::recursive_mutex> lock(m_channelMutex);
PVR_ERROR returnValue = PVR_ERROR_NO_ERROR;
int priority = 1;

Expand Down Expand Up @@ -299,6 +341,7 @@ PVR_ERROR Channels::GetChannelGroupMembers(const kodi::addon::PVRChannelGroup& g

if (retCode == tinyxml2::XML_SUCCESS)
{
std::lock_guard<std::recursive_mutex> lock(m_channelMutex);
tinyxml2::XMLNode* channelsNode = doc.RootElement()->FirstChildElement("channels");
tinyxml2::XMLNode* pChannelNode;
for (pChannelNode = channelsNode->FirstChildElement("channel"); pChannelNode; pChannelNode = pChannelNode->NextSiblingElement())
Expand Down Expand Up @@ -399,6 +442,12 @@ bool Channels::CacheAllChannels(time_t updateTime)
{
gz_file = gzopen(kodi::vfs::TranslateSpecialProtocol(filename).c_str(), "rb");
gzread(gz_file, (void*)&header, sizeof(header));
if (m_checksumChannelList.empty())
{
response.resize(header.size / sizeof(char));
gzread(gz_file, (void*)response.data(), header.size);
m_checksumChannelList = kodi::GetMD5(response);
}
gzclose(gz_file);
if (updateTime == header.update)
{
Expand All @@ -407,6 +456,7 @@ bool Channels::CacheAllChannels(time_t updateTime)
}
if (m_request.DoRequest("/service?method=channel.list&extras=true", response) == HTTP_OK)
{
m_checksumChannelList = kodi::GetMD5(response);
gz_file = gzopen(kodi::vfs::TranslateSpecialProtocol(filename).c_str(), "wb");
header.size = sizeof(char) * response.size();
header.update = updateTime - m_settings->m_serverTimeOffset;
Expand Down
3 changes: 3 additions & 0 deletions src/Channels.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace NextPVR
bool CacheAllChannels(time_t updateTime);

PVR_ERROR GetChannels(bool radio, kodi::addon::PVRChannelsResultSet& results);
bool ResetChannelList(time_t updateTime);
/* Channel group handling */
PVR_ERROR GetChannelGroupsAmount(int& amount);
PVR_ERROR GetChannelGroups(bool radio, kodi::addon::PVRChannelGroupsResultSet& results);
Expand All @@ -43,6 +44,7 @@ namespace NextPVR
std::map<int, std::pair<bool, bool>> m_channelDetails;
std::unordered_set<std::string> m_tvGroups;
std::unordered_set<std::string> m_radioGroups;
mutable std::recursive_mutex m_channelMutex;

private:
Channels() = default;
Expand All @@ -54,5 +56,6 @@ namespace NextPVR
const std::shared_ptr<InstanceSettings> m_settings;
Request& m_request;
tinyxml2::XMLError ReadCachedChannelList(tinyxml2::XMLDocument& doc);
std::string m_checksumChannelList;
};
} // namespace NextPVR
2 changes: 2 additions & 0 deletions src/EPG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ EPG::EPG(const std::shared_ptr<InstanceSettings>& settings, Request& request, Re
PVR_ERROR EPG::GetEPGForChannel(int channelUid, time_t start, time_t end, kodi::addon::PVREPGTagsResultSet& results)
{
std::pair<bool, bool> channelDetail;
std::lock_guard<std::recursive_mutex> lock(m_channels.m_channelMutex);
channelDetail = m_channels.m_channelDetails[channelUid];
std::lock_guard<std::recursive_mutex> unlock(m_channels.m_channelMutex);
if (channelDetail.first == true)
{
kodi::Log(ADDON_LOG_DEBUG, "Skipping %d", channelUid);
Expand Down
1 change: 1 addition & 0 deletions src/Timers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ PVR_ERROR Timers::GetTimers(kodi::addon::PVRTimersResultSet& results)
int timerCount = 0;
// first add the recurring recordings
tinyxml2::XMLDocument doc;
std::lock_guard<std::recursive_mutex> lock(m_channels.m_channelMutex);
if (m_request.DoMethodRequest("recording.recurring.list", doc) == tinyxml2::XML_SUCCESS)
{
tinyxml2::XMLNode* recurringsNode = doc.RootElement()->FirstChildElement("recurrings");
Expand Down
8 changes: 8 additions & 0 deletions src/pvrclient-nextpvr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,14 @@ bool cPVRClientNextPVR::IsUp()
{
if (lastUpdate > m_lastEPGUpdateTime)
{
// if channel list changed trigger channel updates
if (m_channels.ResetChannelList(lastUpdate))
{
kodi::Log(ADDON_LOG_DEBUG, "Trigger Channel update start");
TriggerChannelUpdate();
kodi::Log(ADDON_LOG_DEBUG, "Trigger Channel Groups update start");
TriggerChannelGroupsUpdate();
}
// trigger EPG updates for all channels with a guide source
kodi::Log(ADDON_LOG_DEBUG, "Trigger EPG update start");
int channels = 0;
Expand Down