Skip to content

Commit

Permalink
Changes for Matrix API changes (#115)
Browse files Browse the repository at this point in the history
* Changes for Matrix EPG persistance

Cache EPG event ID to make system usable after daily update.   Use end date as the link.  Control new flag from backend

* Live, Premiere, Finale

Add new iFlag values for EPG and add Premiere and Finale to Recordings
  • Loading branch information
emveepee committed Apr 9, 2020
1 parent ba6fb19 commit f7d488d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 43 deletions.
2 changes: 1 addition & 1 deletion pvr.nextpvr/addon.xml.in
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon
id="pvr.nextpvr"
version="4.3.5"
version="4.3.6"
name="NextPVR PVR Client"
provider-name="Graeme Blackley">
<requires>@ADDON_DEPENDS@</requires>
Expand Down
5 changes: 5 additions & 0 deletions pvr.nextpvr/changelog.txt
@@ -1,3 +1,8 @@
v4.3.6
- Cache EPG event ID to make system usable after daily update. Lose link to recordings.
- Disable New flag from backend
- Add Live, Premiere and Finale flags

v4.3.5
- PVR API 6.3.0

Expand Down
106 changes: 64 additions & 42 deletions src/pvrclient-nextpvr.cpp
Expand Up @@ -159,6 +159,10 @@ cPVRClientNextPVR::~cPVRClientNextPVR()
delete m_timeshiftBuffer;
delete m_recordingBuffer;
delete m_realTimeBuffer;
m_epgOidLookup.clear();
m_hostFilenames.clear();
m_channelTypes.clear();
m_liveStreams.clear();
}

std::vector<std::string> cPVRClientNextPVR::split(const std::string& s, const std::string& delim, const bool keep_empty)
Expand Down Expand Up @@ -346,6 +350,10 @@ bool cPVRClientNextPVR::Connect()
m_iDefaultPostPadding = atoi( settingsDoc.RootElement()->FirstChildElement("PostPadding")->FirstChild()->Value());
}

m_showNew = false;
XMLUtils::GetBoolean(settingsDoc.RootElement(),"ShowNewInGuide",m_showNew);
XBMC->Log(LOG_NOTICE, "Show new %d",m_showNew);

if ( settingsDoc.RootElement()->FirstChildElement("RecordingDirectories") != NULL && settingsDoc.RootElement()->FirstChildElement("RecordingDirectories")->FirstChild() != NULL)
{
vector<std::string> directories = split(settingsDoc.RootElement()->FirstChildElement("RecordingDirectories")->FirstChild()->Value(), ",", false);
Expand Down Expand Up @@ -608,37 +616,34 @@ PVR_ERROR cPVRClientNextPVR::GetEpg(ADDON_HANDLE handle, int iChannelUid, time_t
string description;
string subtitle;
XMLUtils::GetString(pListingNode,"name",title);
if ( ! XMLUtils::GetString(pListingNode,"description",description))
description = "";
XMLUtils::GetString(pListingNode,"description",description);

if (XMLUtils::GetString(pListingNode,"subtitle",subtitle))
{
if (description == subtitle + ":")
{
description.clear();
}
else if (StringUtils::StartsWith(description,subtitle + ": "))
if (description != subtitle + ":" && StringUtils::StartsWith(description,subtitle + ": "))
{
description = description.substr(subtitle.length()+2);
}
}
else
{
subtitle.clear();
}

broadcast.iYear = XmlGetInt(pListingNode,"year");;

string startTime, endTime;
XMLUtils::GetString(pListingNode,"start",startTime);
startTime.resize(10);
XMLUtils::GetString(pListingNode,"end",endTime);
endTime.resize(10);
broadcast.iUniqueBroadcastId = XmlGetInt(pListingNode,"id");

const std::string oidLookup(endTime + ":" + to_string(iChannelUid));

const int epgOid = XmlGetInt(pListingNode,"id");
m_epgOidLookup[oidLookup] = epgOid;

broadcast.strTitle = title.c_str();
broadcast.strEpisodeName = subtitle.c_str();
broadcast.iUniqueChannelId = iChannelUid;
broadcast.startTime = stol(startTime);
broadcast.iUniqueBroadcastId = stoi(endTime);
broadcast.endTime = stol(endTime);
broadcast.strPlotOutline = NULL; //unused
broadcast.strPlot = description.c_str();
Expand All @@ -653,7 +658,7 @@ PVR_ERROR cPVRClientNextPVR::GetEpg(ADDON_HANDLE handle, int iChannelUid, time_t
artworkPath[0] = '\0';
if (g_bDownloadGuideArtwork)
{
snprintf(artworkPath, sizeof(artworkPath), "http://%s:%d/service?method=channel.show.artwork&sid=%s&event_id=%d", g_szHostname.c_str(), g_iPort, m_sid, broadcast.iUniqueBroadcastId);
snprintf(artworkPath, sizeof(artworkPath), "http://%s:%d/service?method=channel.show.artwork&sid=%s&event_id=%d", g_szHostname.c_str(), g_iPort, m_sid, epgOid);
broadcast.strIconPath = artworkPath;
}
std::string sGenre;
Expand Down Expand Up @@ -686,24 +691,32 @@ PVR_ERROR cPVRClientNextPVR::GetEpg(ADDON_HANDLE handle, int iChannelUid, time_t
broadcast.iEpisodePartNumber = EPG_TAG_INVALID_SERIES_EPISODE;

std::string original;
original.clear();
XMLUtils::GetString(pListingNode,"original",original);
broadcast.strFirstAired = original.c_str();

std::string significance;
significance.clear();
XMLUtils::GetString(pListingNode,"significance",significance);
if (significance == "Live")
bool firstrun;
if (XMLUtils::GetBoolean(pListingNode,"firstrun",firstrun))
{
broadcast.iFlags = EPG_TAG_FLAG_IS_NEW;
}
else
{
bool firstrun;
if (XMLUtils::GetBoolean(pListingNode,"firstrun",firstrun))
if (firstrun)
{
if (firstrun)
std::string significance;
XMLUtils::GetString(pListingNode,"significance",significance);
if (significance == "Live")
{
broadcast.iFlags = EPG_TAG_FLAG_IS_LIVE;
}
else if (significance.find("Premiere") != string::npos)
{
broadcast.iFlags = EPG_TAG_FLAG_IS_PREMIERE;
}
else if (significance.find("Finale") != string::npos)
{
broadcast.iFlags = EPG_TAG_FLAG_IS_FINALE;
}
else if (m_showNew)
{
broadcast.iFlags = EPG_TAG_FLAG_IS_NEW;
}
}
}
PVR->TransferEpgEntry(handle, &broadcast);
Expand Down Expand Up @@ -1190,20 +1203,15 @@ bool cPVRClientNextPVR::UpdatePvrRecording(TiXmlElement* pRecordingNode, PVR_REC
XBMC->Log(LOG_ERROR, "Unknown status %s",status.c_str());
return false;
}
if (status == "Recording")

if (status == "Recording" || status == "Pending" )
{
if (pRecordingNode->FirstChildElement("epg_event_oid"))
{
// EPG Event ID is not valid on most older recordings
if (atoi(pRecordingNode->FirstChildElement("recurring_parent")->FirstChild()->Value()) != 0 && pRecordingNode->FirstChildElement("epg_event_oid") != NULL && pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild() != NULL)
{
tag->iEpgEventId = atoi(pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild()->Value());
}
else
{
// need check for older one offs
tag->iEpgEventId = atoi(pRecordingNode->FirstChildElement("epg_event_oid")->FirstChild()->Value());
}
// EPG Event ID is likely not valid on most older recordings so current or pending only
// Linked tags need to be on end time because recordingTime can change because of pre-padding

tag->iEpgEventId = tag->recordingTime + tag->iDuration;
}
}

Expand Down Expand Up @@ -1291,6 +1299,17 @@ bool cPVRClientNextPVR::UpdatePvrRecording(TiXmlElement* pRecordingNode, PVR_REC
PVR_STRCPY(tag->strGenreDescription,genres.c_str());
}

std::string significance;
XMLUtils::GetString(pRecordingNode,"significance",significance);
if (significance.find("Premiere") != string::npos)
{
tag->iFlags = PVR_RECORDING_FLAG_IS_PREMIERE;
}
else if (significance.find("Finale") != string::npos)
{
tag->iFlags = PVR_RECORDING_FLAG_IS_FINALE;
}

return true;
}

Expand Down Expand Up @@ -2097,10 +2116,13 @@ PVR_ERROR cPVRClientNextPVR::AddTimer(const PVR_TIMER &timerinfo)
else
strcpy(preventDuplicates, "false");

std::string encodedName = UriEncode(timerinfo.strTitle);
std::string encodedKeyword = UriEncode(timerinfo.strEpgSearchString);
std::string days = GetDayString(timerinfo.iWeekdays);
std:string directory = UriEncode( m_recordingDirectories[timerinfo.iRecordingGroup]);
const std::string encodedName = UriEncode(timerinfo.strTitle);
const std::string encodedKeyword = UriEncode(timerinfo.strEpgSearchString);
const std::string days = GetDayString(timerinfo.iWeekdays);
const std::string directory = UriEncode( m_recordingDirectories[timerinfo.iRecordingGroup]);
const std::string oidKey = to_string(timerinfo.iEpgUid) + ":" + to_string(timerinfo.iClientChannelUid);
const int epgOid = m_epgOidLookup[oidKey];
XBMC->Log(LOG_DEBUG, "TIMER_%d %s",epgOid,oidKey.c_str());
switch (timerinfo.iTimerType)
{
case TIMER_ONCE_MANUAL:
Expand All @@ -2122,7 +2144,7 @@ PVR_ERROR cPVRClientNextPVR::AddTimer(const PVR_TIMER &timerinfo)
// build one-off recording request
snprintf(request, sizeof(request), "/service?method=recording.save&recording_id=%d&event_id=%d&pre_padding=%d&post_padding=%d&directory_id=%s",
timerinfo.iClientIndex,
timerinfo.iEpgUid,
epgOid,
(int)timerinfo.iMarginStart,
(int)timerinfo.iMarginEnd,
directory.c_str());
Expand Down Expand Up @@ -2153,7 +2175,7 @@ PVR_ERROR cPVRClientNextPVR::AddTimer(const PVR_TIMER &timerinfo)
// build recurring recording request
snprintf(request, sizeof(request), "/service?method=recording.recurring.save&recurring_id=%d&event_id=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s&only_new=%s",
timerinfo.iClientIndex,
timerinfo.iEpgUid,
epgOid,
(int)timerinfo.iMaxRecordings,
(int)timerinfo.iMarginStart,
(int)timerinfo.iMarginEnd,
Expand Down
2 changes: 2 additions & 0 deletions src/pvrclient-nextpvr.h
Expand Up @@ -201,6 +201,8 @@ class cPVRClientNextPVR : P8PLATFORM::CThread
std::map<std::string, std::string> m_hostFilenames;
std::map<int, bool> m_channelTypes; // returns isRadio
std::map<int, std::string> m_liveStreams;
std::map<std::string,int> m_epgOidLookup;
bool m_showNew;

void SendWakeOnLan();
bool SaveSettings(std::string name, std::string value);
Expand Down

0 comments on commit f7d488d

Please sign in to comment.