Skip to content

Commit

Permalink
Test channel list update
Browse files Browse the repository at this point in the history
Reload changed channel  lists during EPG updates
  • Loading branch information
emveepee committed Nov 15, 2024
1 parent 9bf83f5 commit 3c29f0d
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 1 deletion.
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

0 comments on commit 3c29f0d

Please sign in to comment.