From 84c7324437e7e9719bba4bbbdd913ecb588799d7 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Tue, 2 Jan 2024 18:43:41 +0000 Subject: [PATCH 1/2] Add support for catchup source for the latest programme --- src/IptvSimple.cpp | 2 +- src/iptvsimple/CatchupController.cpp | 30 +++++++++++++++++++--------- src/iptvsimple/CatchupController.h | 4 ++-- src/iptvsimple/PlaylistLoader.cpp | 3 +++ src/iptvsimple/PlaylistLoader.h | 1 + src/iptvsimple/data/Channel.cpp | 2 ++ src/iptvsimple/data/Channel.h | 6 +++++- 7 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/IptvSimple.cpp b/src/IptvSimple.cpp index c19c0a503..cc0d36236 100644 --- a/src/IptvSimple.cpp +++ b/src/IptvSimple.cpp @@ -324,7 +324,7 @@ PVR_ERROR IptvSimple::IsEPGTagPlayable(const kodi::addon::PVREPGTag& tag, bool& bIsPlayable = bIsPlayable && tag.GetStartTime() < now && tag.GetStartTime() >= (now - static_cast(channel.GetCatchupDaysInSeconds())) && - (!m_settings->CatchupOnlyOnFinishedProgrammes() || tag.GetEndTime() < now); + ((!m_settings->CatchupOnlyOnFinishedProgrammes() || !channel.GetCatchupLatestSource().empty()) || tag.GetEndTime() < now); } return PVR_ERROR_NO_ERROR; diff --git a/src/iptvsimple/CatchupController.cpp b/src/iptvsimple/CatchupController.cpp index 9fa81f193..770442ded 100644 --- a/src/iptvsimple/CatchupController.cpp +++ b/src/iptvsimple/CatchupController.cpp @@ -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()); @@ -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); } } @@ -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) @@ -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 { @@ -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) @@ -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 { @@ -179,7 +186,7 @@ void CatchupController::ProcessEPGTagForVideoPlayback(const kodi::addon::PVREPGT m_playbackIsVideo = true; } -void CatchupController::SetCatchupInputStreamProperties(bool playbackAsLive, const Channel& channel, std::map& catchupProperties, const StreamType& streamType) +void CatchupController::SetCatchupInputStreamProperties(bool playbackAsLive, const Channel& channel, std::map& catchupProperties, const StreamType& streamType, bool isLiveEntry) { catchupProperties.insert({PVR_STREAM_PROPERTY_EPGPLAYBACKASLIVE, playbackAsLive ? "true" : "false"}); @@ -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)}); @@ -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()); @@ -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 (isLiveEntry && !channel.GetCatchupLatestSource().empty()) + return channel.GetCatchupLatestSource(); + else + return channel.GetCatchupSource(); + } return ""; } diff --git a/src/iptvsimple/CatchupController.h b/src/iptvsimple/CatchupController.h index 423f29556..d2cadee6c 100644 --- a/src/iptvsimple/CatchupController.h +++ b/src/iptvsimple/CatchupController.h @@ -33,7 +33,7 @@ namespace iptvsimple void ProcessEPGTagForTimeshiftedPlayback(const kodi::addon::PVREPGTag& epgTag, const data::Channel& channel, std::map& catchupProperties); void ProcessEPGTagForVideoPlayback(const kodi::addon::PVREPGTag& epgTag, const data::Channel& channel, std::map& 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; @@ -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& catchupProperties, const StreamType& streamType); + void SetCatchupInputStreamProperties(bool playbackAsLive, const iptvsimple::data::Channel& channel, std::map& 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; diff --git a/src/iptvsimple/PlaylistLoader.cpp b/src/iptvsimple/PlaylistLoader.cpp index d05abf8f4..3bdea185d 100644 --- a/src/iptvsimple/PlaylistLoader.cpp +++ b/src/iptvsimple/PlaylistLoader.cpp @@ -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); @@ -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()) @@ -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.SetCatchupLatestSource(strCatchupLatestSource); channel.SetTvgShift(static_cast(tvgShiftDecimal * 3600.0)); channel.SetRadio(isRadio); if (m_settings->GetLogoPathType() == PathType::LOCAL_PATH && m_settings->UseLocalLogosOnlyIgnoreM3U()) diff --git a/src/iptvsimple/PlaylistLoader.h b/src/iptvsimple/PlaylistLoader.h index b2cdaa6cb..0c38094b3 100644 --- a/src/iptvsimple/PlaylistLoader.h +++ b/src/iptvsimple/PlaylistLoader.h @@ -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="; diff --git a/src/iptvsimple/data/Channel.cpp b/src/iptvsimple/data/Channel.cpp index 974f774cb..dd3391119 100644 --- a/src/iptvsimple/data/Channel.cpp +++ b/src/iptvsimple/data/Channel.cpp @@ -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; @@ -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; diff --git a/src/iptvsimple/data/Channel.h b/src/iptvsimple/data/Channel.h index 36447ca01..de03aed9b 100644 --- a/src/iptvsimple/data/Channel.h +++ b/src/iptvsimple/data/Channel.h @@ -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()), @@ -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; } @@ -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; From 4fbacdef97a8248f1c390064fc6e52bc1625d5f1 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sat, 9 Dec 2023 16:40:32 +0000 Subject: [PATCH 2/2] changelog and version 21.7.1 --- pvr.iptvsimple/addon.xml.in | 2 +- pvr.iptvsimple/changelog.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pvr.iptvsimple/addon.xml.in b/pvr.iptvsimple/addon.xml.in index e06e80313..60954a5b3 100644 --- a/pvr.iptvsimple/addon.xml.in +++ b/pvr.iptvsimple/addon.xml.in @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ diff --git a/pvr.iptvsimple/changelog.txt b/pvr.iptvsimple/changelog.txt index 7a6c169bd..7ce44541d 100644 --- a/pvr.iptvsimple/changelog.txt +++ b/pvr.iptvsimple/changelog.txt @@ -1,3 +1,6 @@ +v21.7.1 +- Add support for catchup source for the latest programme + v21.6.0 - Only reset channel group list when a channel URL is read from M3U Playlist - Modify EXTGRP behaviour so it is a begin directive for channels groups, i.e. it carries across channels unless reset by an empty EXTGRP directive or any group-title tag for a EXTINF channel directive