Skip to content

Commit

Permalink
Add support for catchup source for the latest programme
Browse files Browse the repository at this point in the history
  • Loading branch information
phunkyfish committed Dec 9, 2023
1 parent b0d3ad1 commit 71241a7
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/IptvSimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ PVR_ERROR IptvSimple::IsEPGTagPlayable(const kodi::addon::PVREPGTag& tag, bool&
bIsPlayable = bIsPlayable &&
tag.GetStartTime() < now &&
tag.GetStartTime() >= (now - static_cast<time_t>(channel.GetCatchupDaysInSeconds())) &&
(!m_settings->CatchupOnlyOnFinishedProgrammes() || tag.GetEndTime() < now);
((!m_settings->CatchupOnlyOnFinishedProgrammes() || !channel.GetCatchupLatestSource().empty()) || tag.GetEndTime() < now);
}

return PVR_ERROR_NO_ERROR;
Expand Down
30 changes: 21 additions & 9 deletions src/iptvsimple/CatchupController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ void CatchupController::ProcessChannelForPlayback(const Channel& channel, std::m
{
StreamType streamType = StreamTypeLookup(channel);

bool isLiveEntry = false;

// Anything from here is live!
m_playbackIsVideo = false; // TODO: possible time jitter on UI as this will effect get stream times

if (!m_fromEpgTag || m_controlsLiveStream)
{
EpgEntry* liveEpgEntry = GetLiveEPGEntry(channel);
if (m_controlsLiveStream && liveEpgEntry && !m_settings->CatchupOnlyOnFinishedProgrammes())
isLiveEntry = liveEpgEntry != nullptr;
if (m_controlsLiveStream && liveEpgEntry && (!m_settings->CatchupOnlyOnFinishedProgrammes() || !channel.GetCatchupLatestSource().empty()))
{
// Live timeshifting support with EPG entry
UpdateProgrammeFrom(*liveEpgEntry, channel.GetTvgShift());
Expand Down Expand Up @@ -84,7 +87,7 @@ void CatchupController::ProcessChannelForPlayback(const Channel& channel, std::m
// TODO: Need a method of updating an inputstream if already running such as web call to stream etc.
// this will avoid inputstream restarts which are expensive, may be better placed in client.cpp
// this also mean knowing when a stream has stopped
SetCatchupInputStreamProperties(true, channel, catchupProperties, streamType);
SetCatchupInputStreamProperties(true, channel, catchupProperties, streamType, isLiveEntry);
}
}

Expand All @@ -95,6 +98,8 @@ void CatchupController::ProcessEPGTagForTimeshiftedPlayback(const kodi::addon::P
if (epgEntry)
m_programmeCatchupId = epgEntry->GetCatchupId();

bool isLiveEntry = epgEntry == GetLiveEPGEntry(channel);

StreamType streamType = StreamTypeLookup(channel, true);

if (m_controlsLiveStream)
Expand All @@ -116,7 +121,7 @@ void CatchupController::ProcessEPGTagForTimeshiftedPlayback(const kodi::addon::P
// TODO: Need a method of updating an inputstream if already running such as web call to stream etc.
// this will avoid inputstream restarts which are expensive, may be better placed in client.cpp
// this also mean knowing when a stream has stopped
SetCatchupInputStreamProperties(true, channel, catchupProperties, streamType);
SetCatchupInputStreamProperties(true, channel, catchupProperties, streamType, isLiveEntry);
}
else
{
Expand All @@ -138,6 +143,8 @@ void CatchupController::ProcessEPGTagForVideoPlayback(const kodi::addon::PVREPGT
if (epgEntry)
m_programmeCatchupId = epgEntry->GetCatchupId();

bool isLiveEntry = epgEntry == GetLiveEPGEntry(channel);

StreamType streamType = StreamTypeLookup(channel, true);

if (m_controlsLiveStream)
Expand All @@ -161,7 +168,7 @@ void CatchupController::ProcessEPGTagForVideoPlayback(const kodi::addon::PVREPGT
// TODO: Need a method of updating an inputstream if already running such as web call to stream etc.
// this will avoid inputstream restarts which are expensive, may be better placed in client.cpp
// this also mean knowing when a stream has stopped
SetCatchupInputStreamProperties(false, channel, catchupProperties, streamType);
SetCatchupInputStreamProperties(false, channel, catchupProperties, streamType, isLiveEntry);
}
else
{
Expand All @@ -179,7 +186,7 @@ void CatchupController::ProcessEPGTagForVideoPlayback(const kodi::addon::PVREPGT
m_playbackIsVideo = true;
}

void CatchupController::SetCatchupInputStreamProperties(bool playbackAsLive, const Channel& channel, std::map<std::string, std::string>& catchupProperties, const StreamType& streamType)
void CatchupController::SetCatchupInputStreamProperties(bool playbackAsLive, const Channel& channel, std::map<std::string, std::string>& catchupProperties, const StreamType& streamType, bool isLiveEntry)
{
catchupProperties.insert({PVR_STREAM_PROPERTY_EPGPLAYBACKASLIVE, playbackAsLive ? "true" : "false"});

Expand All @@ -189,7 +196,7 @@ void CatchupController::SetCatchupInputStreamProperties(bool playbackAsLive, con

catchupProperties.insert({"inputstream.ffmpegdirect.default_url", channel.GetStreamURL()});
catchupProperties.insert({"inputstream.ffmpegdirect.playback_as_live", playbackAsLive ? "true" : "false"});
catchupProperties.insert({"inputstream.ffmpegdirect.catchup_url_format_string", GetCatchupUrlFormatString(channel)});
catchupProperties.insert({"inputstream.ffmpegdirect.catchup_url_format_string", GetCatchupUrlFormatString(channel, isLiveEntry)});
catchupProperties.insert({"inputstream.ffmpegdirect.catchup_buffer_start_time", std::to_string(m_catchupStartTime)});
catchupProperties.insert({"inputstream.ffmpegdirect.catchup_buffer_end_time", std::to_string(m_catchupEndTime)});
catchupProperties.insert({"inputstream.ffmpegdirect.catchup_buffer_offset", std::to_string(m_timeshiftBufferOffset)});
Expand All @@ -205,7 +212,7 @@ void CatchupController::SetCatchupInputStreamProperties(bool playbackAsLive, con

Logger::Log(LEVEL_DEBUG, "default_url - %s", WebUtils::RedactUrl(channel.GetStreamURL()).c_str());
Logger::Log(LEVEL_DEBUG, "playback_as_live - %s", playbackAsLive ? "true" : "false");
Logger::Log(LEVEL_DEBUG, "catchup_url_format_string - %s", WebUtils::RedactUrl(GetCatchupUrlFormatString(channel)).c_str());
Logger::Log(LEVEL_DEBUG, "catchup_url_format_string - %s", WebUtils::RedactUrl(GetCatchupUrlFormatString(channel, isLiveEntry)).c_str());
Logger::Log(LEVEL_DEBUG, "catchup_buffer_start_time - %s", std::to_string(m_catchupStartTime).c_str());
Logger::Log(LEVEL_DEBUG, "catchup_buffer_end_time - %s", std::to_string(m_catchupEndTime).c_str());
Logger::Log(LEVEL_DEBUG, "catchup_buffer_offset - %s", std::to_string(m_timeshiftBufferOffset).c_str());
Expand Down Expand Up @@ -437,10 +444,15 @@ std::string BuildEpgTagUrl(time_t startTime, time_t duration, const Channel& cha

} // unnamed namespace

std::string CatchupController::GetCatchupUrlFormatString(const Channel& channel) const
std::string CatchupController::GetCatchupUrlFormatString(const Channel& channel, bool isLiveEntry) const
{
if (m_catchupStartTime > 0)
return channel.GetCatchupSource();
{
if (true == true)
return channel.GetCatchupLatestSource();
else
return channel.GetCatchupSource();
}

return "";
}
Expand Down
4 changes: 2 additions & 2 deletions src/iptvsimple/CatchupController.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace iptvsimple
void ProcessEPGTagForTimeshiftedPlayback(const kodi::addon::PVREPGTag& epgTag, const data::Channel& channel, std::map<std::string, std::string>& catchupProperties);
void ProcessEPGTagForVideoPlayback(const kodi::addon::PVREPGTag& epgTag, const data::Channel& channel, std::map<std::string, std::string>& catchupProperties);

std::string GetCatchupUrlFormatString(const data::Channel& channel) const;
std::string GetCatchupUrlFormatString(const data::Channel& channel, bool isLiveEntry) const;
std::string GetCatchupUrl(const data::Channel& channel) const;
std::string ProcessStreamUrl(const data::Channel& channel) const;

Expand All @@ -43,7 +43,7 @@ namespace iptvsimple

private:
data::EpgEntry* GetLiveEPGEntry(const iptvsimple::data::Channel& myChannel);
void SetCatchupInputStreamProperties(bool playbackAsLive, const iptvsimple::data::Channel& channel, std::map<std::string, std::string>& catchupProperties, const StreamType& streamType);
void SetCatchupInputStreamProperties(bool playbackAsLive, const iptvsimple::data::Channel& channel, std::map<std::string, std::string>& catchupProperties, const StreamType& streamType, bool isLiveEntry);
StreamType StreamTypeLookup(const data::Channel& channel, bool fromEpg = false);
std::string GetStreamTestUrl(const data::Channel& channel, bool fromEpg) const;
std::string GetStreamKey(const data::Channel& channel, bool fromEpg) const;
Expand Down
3 changes: 3 additions & 0 deletions src/iptvsimple/PlaylistLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c
std::string strCatchupDays = ReadMarkerValue(infoLine, CATCHUP_DAYS);
std::string strTvgRec = ReadMarkerValue(infoLine, TVG_INFO_REC);
std::string strCatchupSource = ReadMarkerValue(infoLine, CATCHUP_SOURCE);
std::string strCatchupLatestSource = ReadMarkerValue(infoLine, CATCHUP_LATEST_SOURCE);
std::string strCatchupSiptv = ReadMarkerValue(infoLine, CATCHUP_SIPTV);
std::string strCatchupCorrection = ReadMarkerValue(infoLine, CATCHUP_CORRECTION);
std::string strProviderName = ReadMarkerValue(infoLine, PROVIDER);
Expand All @@ -343,6 +344,7 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c

kodi::UnknownToUTF8(strTvgName, strTvgName);
kodi::UnknownToUTF8(strCatchupSource, strCatchupSource);
kodi::UnknownToUTF8(strCatchupLatestSource, strCatchupLatestSource);

// Some providers use a 'catchup-type' tag instead of 'catchup'
if (strCatchup.empty())
Expand Down Expand Up @@ -388,6 +390,7 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c
// If we still don't have a value use the header supplied value if there is one
if (strCatchupSource.empty() && !m_m3uHeaderStrings.m_catchupSource.empty())
strCatchupSource = m_m3uHeaderStrings.m_catchupSource;
channel.SetCatchupSource(strCatchupLatestSource);
channel.SetTvgShift(static_cast<int>(tvgShiftDecimal * 3600.0));
channel.SetRadio(isRadio);
if (m_settings->GetLogoPathType() == PathType::LOCAL_PATH && m_settings->UseLocalLogosOnlyIgnoreM3U())
Expand Down
1 change: 1 addition & 0 deletions src/iptvsimple/PlaylistLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace iptvsimple
static const std::string CATCHUP_TYPE = "catchup-type=";
static const std::string CATCHUP_DAYS = "catchup-days=";
static const std::string CATCHUP_SOURCE = "catchup-source=";
static const std::string CATCHUP_LATEST_SOURCE = "catchup-latest-source=";
static const std::string CATCHUP_SIPTV = "timeshift=";
static const std::string CATCHUP_CORRECTION = "catchup-correction=";
static const std::string PROVIDER = "provider=";
Expand Down
2 changes: 2 additions & 0 deletions src/iptvsimple/data/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void Channel::UpdateTo(Channel& left) const
left.m_catchupMode = m_catchupMode;
left.m_catchupDays = m_catchupDays;
left.m_catchupSource = m_catchupSource;
left.m_catchupLatestSource = m_catchupLatestSource;
left.m_isCatchupTSStream = m_isCatchupTSStream;
left.m_catchupSupportsTimeshifting = m_catchupSupportsTimeshifting;
left.m_catchupSourceTerminates = m_catchupSourceTerminates;
Expand Down Expand Up @@ -104,6 +105,7 @@ void Channel::Reset()
m_catchupMode = CatchupMode::DISABLED;
m_catchupDays = 0;
m_catchupSource.clear();
m_catchupLatestSource.clear();
m_catchupSupportsTimeshifting = false;
m_catchupSourceTerminates = false;
m_catchupGranularitySeconds = 1;
Expand Down
6 changes: 5 additions & 1 deletion src/iptvsimple/data/Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace iptvsimple
m_channelNumber(c.GetChannelNumber()), m_subChannelNumber(c.GetSubChannelNumber()),
m_encryptionSystem(c.GetEncryptionSystem()), m_tvgShift(c.GetTvgShift()), m_channelName(c.GetChannelName()),
m_iconPath(c.GetIconPath()), m_streamURL(c.GetStreamURL()), m_hasCatchup(c.HasCatchup()),
m_catchupMode(c.GetCatchupMode()), m_catchupDays(c.GetCatchupDays()), m_catchupSource(c.GetCatchupSource()),
m_catchupMode(c.GetCatchupMode()), m_catchupDays(c.GetCatchupDays()), m_catchupSource(c.GetCatchupSource()), m_catchupLatestSource(c.GetCatchupLatestSource()),
m_isCatchupTSStream(c.IsCatchupTSStream()), m_catchupSupportsTimeshifting(c.CatchupSupportsTimeshifting()),
m_catchupSourceTerminates(c.CatchupSourceTerminates()), m_catchupGranularitySeconds(c.GetCatchupGranularitySeconds()),
m_catchupCorrectionSecs(c.GetCatchupCorrectionSecs()), m_tvgId(c.GetTvgId()), m_tvgName(c.GetTvgName()),
Expand Down Expand Up @@ -95,6 +95,9 @@ namespace iptvsimple
const std::string& GetCatchupSource() const { return m_catchupSource; }
void SetCatchupSource(const std::string& value) { m_catchupSource = value; }

const std::string& GetCatchupLatestSource() const { return m_catchupLatestSource; }
void SetCatchupLatestSource(const std::string& value) { m_catchupLatestSource = value; }

bool IsCatchupTSStream() const { return m_isCatchupTSStream; }
void SetCatchupTSStream(bool value) { m_isCatchupTSStream = value; }

Expand Down Expand Up @@ -161,6 +164,7 @@ namespace iptvsimple
CatchupMode m_catchupMode = CatchupMode::DISABLED;
int m_catchupDays = 0;
std::string m_catchupSource = "";
std::string m_catchupLatestSource = "";
bool m_isCatchupTSStream = false;
bool m_catchupSupportsTimeshifting = false;
bool m_catchupSourceTerminates = false;
Expand Down

0 comments on commit 71241a7

Please sign in to comment.