Skip to content

Commit

Permalink
Merge pull request #597 from phunkyfish/default-stream-type
Browse files Browse the repository at this point in the history
Default stream type
  • Loading branch information
phunkyfish authored Jan 30, 2022
2 parents be23c76 + a1a5f0f commit f050a34
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 10 deletions.
2 changes: 1 addition & 1 deletion pvr.iptvsimple/addon.xml.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon
id="pvr.iptvsimple"
version="20.2.1"
version="20.3.0"
name="IPTV Simple Client"
provider-name="nightik and Ross Nicholson">
<requires>@ADDON_DEPENDS@
Expand Down
8 changes: 8 additions & 0 deletions pvr.iptvsimple/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
v20.3.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
- Fix incorrect provider mappings file path

v20.2.1
- Remove redundant PVR from addon name

Expand Down
2 changes: 1 addition & 1 deletion pvr.iptvsimple/resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
</setting>
<setting id="providerMappingFile" type="path" parent="enableProviderMapping" label="30009" help="30472">
<level>2</level>
<default>special://userdata/addon_data/pvr.iptvsimple/providers/providersMappings.xml</default>
<default>special://userdata/addon_data/pvr.iptvsimple/providers/providerMappings.xml</default>
<constraints>
<allowempty>false</allowempty>
<writable>false</writable>
Expand Down
42 changes: 36 additions & 6 deletions src/iptvsimple/PlaylistLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,22 @@ bool PlaylistLoader::LoadPlayList()
catchupCorrectionSecs = static_cast<int>(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);
Expand Down Expand Up @@ -280,6 +292,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);
Expand All @@ -291,6 +306,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('.');
Expand All @@ -311,6 +330,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<int>(tvgShiftDecimal * 3600.0));
channel.SetRadio(isRadio);
if (Settings::GetInstance().GetLogoPathType() == PathType::LOCAL_PATH && Settings::GetInstance().UseLocalLogosOnlyIgnoreM3U())
Expand All @@ -327,8 +349,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"))
Expand All @@ -337,13 +360,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);
Expand All @@ -359,6 +386,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)
Expand Down
10 changes: 10 additions & 0 deletions src/iptvsimple/PlaylistLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,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=";
Expand All @@ -53,6 +54,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, iptvsimple::Providers& providers,
Expand All @@ -78,5 +86,7 @@ namespace iptvsimple
iptvsimple::Channels& m_channels;
iptvsimple::Media& m_media;
kodi::addon::CInstancePVRClient* m_client;

M3UHeaderStrings m_m3uHeaderStrings;
};
} //namespace iptvsimple
28 changes: 28 additions & 0 deletions src/iptvsimple/data/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,12 +435,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();
Expand All @@ -465,6 +468,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;
}
Expand Down
6 changes: 4 additions & 2 deletions src/iptvsimple/utilities/StreamUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit f050a34

Please sign in to comment.