From b9ce6a32f874b72694f4dae2c50d157f630041ed Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sat, 29 Jan 2022 18:24:13 +0000 Subject: [PATCH 1/6] Choose a suitable default stream type for default and append catchup modes --- src/iptvsimple/utilities/StreamUtils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/iptvsimple/utilities/StreamUtils.cpp b/src/iptvsimple/utilities/StreamUtils.cpp index 1cc423ab8..e6a418894 100644 --- a/src/iptvsimple/utilities/StreamUtils.cpp +++ b/src/iptvsimple/utilities/StreamUtils.cpp @@ -256,8 +256,10 @@ const StreamType StreamUtils::InspectStreamType(const std::string& url, const Ch return StreamType::SMOOTH_STREAMING; } - // If we can't inspect the stream type the only option left for shift mode is TS - if (channel.GetCatchupMode() == CatchupMode::SHIFT || + // If we can't inspect the stream type the only option left for default, append or shift mode is TS + if (channel.GetCatchupMode() == CatchupMode::DEFAULT || + channel.GetCatchupMode() == CatchupMode::APPEND || + channel.GetCatchupMode() == CatchupMode::SHIFT || channel.GetCatchupMode() == CatchupMode::TIMESHIFT) return StreamType::TS; From 4dd44654b181fe4f3acd082ec65056273ba152a9 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sun, 30 Jan 2022 11:54:21 +0000 Subject: [PATCH 2/6] Allow catchup tags in M3U header --- src/iptvsimple/PlaylistLoader.cpp | 27 ++++++++++++++++++++++++--- src/iptvsimple/PlaylistLoader.h | 9 +++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/iptvsimple/PlaylistLoader.cpp b/src/iptvsimple/PlaylistLoader.cpp index 9ad1ea98d..2d16f49e5 100644 --- a/src/iptvsimple/PlaylistLoader.cpp +++ b/src/iptvsimple/PlaylistLoader.cpp @@ -101,10 +101,22 @@ bool PlaylistLoader::LoadPlayList() catchupCorrectionSecs = static_cast(catchupCorrectionDecimal * 3600.0); } - std::string strXeevCatchup = ReadMarkerValue(line, CATCHUP); - if (strXeevCatchup == "xc") + // + // If there are catchup values in the M3U header we read them to be used as defaults later on + // + m_m3uHeaderStrings.m_catchup = ReadMarkerValue(line, CATCHUP); + // There is some xeev specific functionality if specificed in the header + if (m_m3uHeaderStrings.m_catchup == "xc") xeevCatchup = true; - + // Some providers use a 'catchup-type' tag instead of 'catchup' + if (m_m3uHeaderStrings.m_catchup.empty()) + m_m3uHeaderStrings.m_catchup = ReadMarkerValue(line, CATCHUP_TYPE); + m_m3uHeaderStrings.m_catchupDays = ReadMarkerValue(line, CATCHUP_DAYS); + m_m3uHeaderStrings.m_catchupSource = ReadMarkerValue(line, CATCHUP_SOURCE); + + // + // Read either of the M3U header based EPG xmltv urls + // std::string tvgUrl = ReadMarkerValue(line, TVG_URL_MARKER); if (tvgUrl.empty()) tvgUrl = ReadMarkerValue(line, TVG_URL_OTHER_MARKER); @@ -247,6 +259,9 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c // Some providers use a 'catchup-type' tag instead of 'catchup' if (strCatchup.empty()) strCatchup = ReadMarkerValue(infoLine, CATCHUP_TYPE); + // If we still don't have a value use the header supplied value if there is one + if (strCatchup.empty() && !m_m3uHeaderStrings.m_catchup.empty()) + strCatchup = m_m3uHeaderStrings.m_catchup; if (strTvgId.empty()) strTvgId = ReadMarkerValue(infoLine, TVG_INFO_ID_MARKER_UC); @@ -278,6 +293,9 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c channel.SetTvgId(strTvgId); channel.SetTvgName(strTvgName); channel.SetCatchupSource(strCatchupSource); + // 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.SetTvgShift(static_cast(tvgShiftDecimal * 3600.0)); channel.SetRadio(isRadio); if (Settings::GetInstance().GetLogoPathType() == PathType::LOCAL_PATH && Settings::GetInstance().UseLocalLogosOnlyIgnoreM3U()) @@ -326,6 +344,9 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c if (!strCatchupDays.empty()) channel.SetCatchupDays(atoi(strCatchupDays.c_str())); + // If we still don't have a value use the header supplied value if there is one + else if (!m_m3uHeaderStrings.m_catchupSource.empty()) + channel.SetCatchupDays(atoi(m_m3uHeaderStrings.m_catchupDays.c_str())); else if (channel.GetCatchupMode() == CatchupMode::VOD) channel.SetCatchupDays(IGNORE_CATCHUP_DAYS); else if (siptvTimeshiftDays > 0) diff --git a/src/iptvsimple/PlaylistLoader.h b/src/iptvsimple/PlaylistLoader.h index c291db462..9de5821bc 100644 --- a/src/iptvsimple/PlaylistLoader.h +++ b/src/iptvsimple/PlaylistLoader.h @@ -43,6 +43,13 @@ namespace iptvsimple class PlaylistLoader { + struct M3UHeaderStrings { + // members will be public without `private:` keyword + std::string m_catchup; + std::string m_catchupDays; + std::string m_catchupSource; + }; + public: PlaylistLoader(kodi::addon::CInstancePVRClient* client, iptvsimple::Channels& channels, iptvsimple::ChannelGroups& channelGroups); @@ -64,5 +71,7 @@ namespace iptvsimple iptvsimple::ChannelGroups& m_channelGroups; iptvsimple::Channels& m_channels; kodi::addon::CInstancePVRClient* m_client; + + M3UHeaderStrings m_m3uHeaderStrings; }; } //namespace iptvsimple From 76fad91bba87386d5fefbdac792c8bb15babf5c9 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sun, 30 Jan 2022 13:07:13 +0000 Subject: [PATCH 3/6] Update flussonic catchup type strings --- src/iptvsimple/PlaylistLoader.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/iptvsimple/PlaylistLoader.cpp b/src/iptvsimple/PlaylistLoader.cpp index 2d16f49e5..efa29be60 100644 --- a/src/iptvsimple/PlaylistLoader.cpp +++ b/src/iptvsimple/PlaylistLoader.cpp @@ -312,8 +312,9 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c if (StringUtils::EqualsNoCase(strCatchup, "default") || StringUtils::EqualsNoCase(strCatchup, "append") || StringUtils::EqualsNoCase(strCatchup, "shift") || StringUtils::EqualsNoCase(strCatchup, "flussonic") || - StringUtils::EqualsNoCase(strCatchup, "flussonic-ts") || StringUtils::EqualsNoCase(strCatchup, "fs") || - StringUtils::EqualsNoCase(strCatchup, "xc") || StringUtils::EqualsNoCase(strCatchup, "vod")) + StringUtils::EqualsNoCase(strCatchup, "flussonic-hls") || StringUtils::EqualsNoCase(strCatchup, "flussonic-ts") || + StringUtils::EqualsNoCase(strCatchup, "fs") || StringUtils::EqualsNoCase(strCatchup, "xc") || + StringUtils::EqualsNoCase(strCatchup, "vod")) channel.SetHasCatchup(true); if (StringUtils::EqualsNoCase(strCatchup, "default")) @@ -322,13 +323,17 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c channel.SetCatchupMode(CatchupMode::APPEND); else if (StringUtils::EqualsNoCase(strCatchup, "shift")) channel.SetCatchupMode(CatchupMode::SHIFT); - else if (StringUtils::EqualsNoCase(strCatchup, "flussonic") || StringUtils::EqualsNoCase(strCatchup, "flussonic-ts") || StringUtils::EqualsNoCase(strCatchup, "fs")) + else if (StringUtils::EqualsNoCase(strCatchup, "flussonic") || StringUtils::EqualsNoCase(strCatchup, "flussonic-hls") || + StringUtils::EqualsNoCase(strCatchup, "flussonic-ts") || StringUtils::EqualsNoCase(strCatchup, "fs")) channel.SetCatchupMode(CatchupMode::FLUSSONIC); else if (StringUtils::EqualsNoCase(strCatchup, "xc")) channel.SetCatchupMode(CatchupMode::XTREAM_CODES); else if (StringUtils::EqualsNoCase(strCatchup, "vod")) channel.SetCatchupMode(CatchupMode::VOD); + if (StringUtils::EqualsNoCase(strCatchup, "flussonic-ts") || StringUtils::EqualsNoCase(strCatchup, "fs")) + channel.SetCatchupTSStream(true); + if (!channel.HasCatchup() && xeevCatchup && (StringUtils::StartsWith(channelName, "* ") || StringUtils::StartsWith(channelName, "[+] "))) { channel.SetHasCatchup(true); From d789dfe79b30af8f25464f3ce04e5f1b86f64a7b Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sun, 30 Jan 2022 14:50:06 +0000 Subject: [PATCH 4/6] For flussonic catchup add support for generic stream types (where any dir name is used after channel id) --- src/iptvsimple/data/Channel.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/iptvsimple/data/Channel.cpp b/src/iptvsimple/data/Channel.cpp index 1c4e9ec91..1fcec266b 100644 --- a/src/iptvsimple/data/Channel.cpp +++ b/src/iptvsimple/data/Channel.cpp @@ -432,12 +432,15 @@ bool Channel::GenerateFlussonicCatchupSource(const std::string& url) // catchup: http://list.tv:8888/325/timeshift_rel-{offset:1}.m3u8?token=secret // stream: http://list.tv:8888/325/mono.m3u8?token=secret // catchup: http://list.tv:8888/325/mono-timeshift_rel-{offset:1}.m3u8?token=secret + // stream: http://list.tv:8888/325/live?token=my_token + // catchup: http://list.tv:8888/325/{utc}.ts?token=my_token static std::regex fsRegex("^(http[s]?://[^/]+)/(.*)/([^/]*)(mpegts|\\.m3u8)(\\?.+=.+)?$"); std::smatch matches; if (std::regex_match(url, matches, fsRegex)) { + // This is path for well defined stream naming if (matches.size() == 6) { const std::string fsHost = matches[1].str(); @@ -462,6 +465,31 @@ bool Channel::GenerateFlussonicCatchupSource(const std::string& url) return true; } } + else + { + // Flussonic servers will return a stream with any directory name after the channel id + // so we handle this case separately + static std::regex genericRegex("^(http[s]?://[^/]+)/(.*)/([^\\?]*)(\\?.+=.+)?$"); + std::smatch genericMmatches; + + if (std::regex_match(url, genericMmatches, genericRegex)) + { + if (genericMmatches.size() == 5) + { + const std::string fsHost = genericMmatches[1].str(); + const std::string fsChannelId = genericMmatches[2].str(); + const std::string fsStreamType = genericMmatches[3].str(); + const std::string fsUrlAppend = genericMmatches[4].str(); + + if (m_isCatchupTSStream) // the catchup type was "flussonic-ts" or "fs" + m_catchupSource = fsHost + "/" + fsChannelId + "/timeshift_abs-${start}.ts" + fsUrlAppend; + else // the catchup type was "flussonic" or "flussonic-hls" + m_catchupSource = fsHost + "/" + fsChannelId + "/timeshift_rel-{offset:1}.m3u8" + fsUrlAppend; + + return true; + } + } + } return false; } From 50b40ccb3def9df8fa5ed725907613b1cfd66071 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sun, 30 Jan 2022 15:14:07 +0000 Subject: [PATCH 5/6] Support alternative tag name for channel number --- src/iptvsimple/PlaylistLoader.cpp | 4 ++++ src/iptvsimple/PlaylistLoader.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/iptvsimple/PlaylistLoader.cpp b/src/iptvsimple/PlaylistLoader.cpp index efa29be60..ad4523d97 100644 --- a/src/iptvsimple/PlaylistLoader.cpp +++ b/src/iptvsimple/PlaylistLoader.cpp @@ -273,6 +273,10 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c strTvgId.append(buff); } + // If don't have a channel number try another format + if (strChnlNo.empty()) + ReadMarkerValue(infoLine, CHANNEL_NUMBER_MARKER); + if (!strChnlNo.empty() && !Settings::GetInstance().NumberChannelsByM3uOrderOnly()) { size_t found = strChnlNo.find('.'); diff --git a/src/iptvsimple/PlaylistLoader.h b/src/iptvsimple/PlaylistLoader.h index 9de5821bc..de4a50825 100644 --- a/src/iptvsimple/PlaylistLoader.h +++ b/src/iptvsimple/PlaylistLoader.h @@ -27,6 +27,7 @@ namespace iptvsimple static const std::string TVG_INFO_LOGO_MARKER = "tvg-logo="; static const std::string TVG_INFO_SHIFT_MARKER = "tvg-shift="; static const std::string TVG_INFO_CHNO_MARKER = "tvg-chno="; + static const std::string CHANNEL_NUMBER_MARKER = "ch-number="; static const std::string TVG_INFO_REC = "tvg-rec="; // some providers use 'tvg-rec' instead of 'catchup-days' static const std::string GROUP_NAME_MARKER = "group-title="; static const std::string CATCHUP = "catchup="; @@ -48,7 +49,7 @@ namespace iptvsimple std::string m_catchup; std::string m_catchupDays; std::string m_catchupSource; - }; + }; public: PlaylistLoader(kodi::addon::CInstancePVRClient* client, iptvsimple::Channels& channels, iptvsimple::ChannelGroups& channelGroups); From 672d04a74bcb6515b2c7c4ec5c08d7338e129639 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sat, 29 Jan 2022 18:32:09 +0000 Subject: [PATCH 6/6] changelog and version - 19.1.0 --- pvr.iptvsimple/addon.xml.in | 9 ++++++++- pvr.iptvsimple/changelog.txt | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pvr.iptvsimple/addon.xml.in b/pvr.iptvsimple/addon.xml.in index 143cb4ca8..eaf46800f 100644 --- a/pvr.iptvsimple/addon.xml.in +++ b/pvr.iptvsimple/addon.xml.in @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ @@ -21,6 +21,13 @@ icon.png +v19.1.0 +- Choose a suitable default stream type for default and append catchup modes +- Allow catchup tags in M3U header +- Update flussonic catchup type strings +- For flussonic catchup add support for generic stream types (where any dir name is used after channel id) +- Support alternative tag name for channel number + v19.0.3 - Translations updates from Weblate - da_dk, es_mx, et_ee, hu_hu, lt_lt, nl_nl, pl_pl, zh_cn, zh_tw diff --git a/pvr.iptvsimple/changelog.txt b/pvr.iptvsimple/changelog.txt index d752507fd..44ac1cd98 100644 --- a/pvr.iptvsimple/changelog.txt +++ b/pvr.iptvsimple/changelog.txt @@ -1,3 +1,10 @@ +v19.1.0 +- Choose a suitable default stream type for default and append catchup modes +- Allow catchup tags in M3U header +- Update flussonic catchup type strings +- For flussonic catchup add support for generic stream types (where any dir name is used after channel id) +- Support alternative tag name for channel number + v19.0.3 - Translations updates from Weblate - da_dk, es_mx, et_ee, hu_hu, lt_lt, nl_nl, pl_pl, zh_cn, zh_tw