Skip to content

Commit

Permalink
Merge pull request #489 from phunkyfish/sub-channels
Browse files Browse the repository at this point in the history
Sub channels
  • Loading branch information
phunkyfish authored Mar 10, 2021
2 parents 7524ebd + 715d244 commit 03e050f
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 18 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,17 @@ Addon settings for catchup:
* **Enable catchup**: Should be enabled if there are channels supporting catchup in your M3U list.
* **Query format string**: A format string (provider dependent) allowing timestamp information to be appended to a URL to denote when to catchup from. E.g. `&cutv={Y}-{m}-{d}T{H}:{M}:{S}`, which allows year, month, day, hour minute and second to be inserted to give: `&cutv=2019-11-26T22:00:32`. If the M3U entry using has a catchup mode of `default` or `append` and a `catchup-source` tag is provided in the M3U entry this setting will be ignored.
* **Catchup window**: The number of days into the past in which it is possible to catchup on a show. Can be overidden in an M3U entry using a 'catchup-days' tag.
* **All channels support catchup**: If enabled it is assumed that all channels support catchup. If there are no catchup specific tags in the M3U entries then the stream URL will be used as the source, and the URL format and catchup days will come from the addon settings. If this option is disabled then a M3U entry must have at least a `catchup="true"` or `catchup="default"` tag to enable catchup.
* **All channels support catchup using mode**: If enabled it is assumed that all channels support catchup using the selected mode if they do not have catchup tags. In this case the 'Query format string' and 'Catchup window' number of days will come from the addon settings if needed. If this option is disabled then an M3U entry must have at least a `catchup=` tag to enable catchup. The options for how to build the catch URL are:
* **Channels support catchup using mode**: If enabled it is assumed that channels support catchup using the selected catchup mode while also obeying the override mode. If required the 'Query format string' and 'Catchup window' number of days will come from the addon settings. If this option is disabled then an M3U entry must have at least a `catchup=` tag to enable catchup. The options for how to build the catch URL are:
- `Disabled` - Do not assume all channel support catchup.
- `Default` - Use catchup source as the full catchup URL, if there is no catchup source use Append mode.
- `Append` - Append the catchup source to the channel URL, if there is no catchup source append the `Query format string` instead.
- `Shift (SIPTV)` - Append the standard SIPTV catchup string to the channel URL.
- `Flussonic` - Build a flussonic URL from the channel URL.
- `Xtream codes` - Build an Xtream codes URL from the channel URL.
* **Override catchup for channels**: Set the scope for overriding the catchup mode. Options are:
- `without catchup mode` - Only include channels with no catchup mode set (except legacy SIP `timeshift` catchup mode).
- `with catchup mode` - Only include channels with catchup mode set (ignore those without a catchup mode).
- `with and without catchup mode (all channels)` - Include all channels ignoring any catchup mode from the M3U.
* **Play from EPG in Live TV mode (using timeshift)**: When disabled any catchup show from the past will be played like a video (bounded by start and end times). If enabled, it will instead act like a live stream with timeshift, also allowing the ability to skip back and forward programmes. Note that the only effect this option has on streams that do not support timeshifting is whether or not to apply the before/after buffer.
* **Buffer before programme start**: The amount of buffer to give before the playback start point of an EPG entry that will be watched as a video.
* **Buffer after programme end**: The amount of buffer to give after the playback end point of an EPG entry that will be watched as a video.
Expand Down
6 changes: 5 additions & 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="7.4.3"
version="7.5.0"
name="PVR IPTV Simple Client"
provider-name="nightik and Ross Nicholson">
<requires>@ADDON_DEPENDS@
Expand Down Expand Up @@ -169,6 +169,10 @@
<icon>icon.png</icon>
</assets>
<news>
v7.5.0
- Added: Support sub channel numbers
- Added: Allow setting scope for channels using catchup mode setting to enable overriding

v7.4.3
- Fixed: Add support for format specifiers use for detecting terminating catchup and granularity
- Update: Make inputstream add-ons a required dependency
Expand Down
4 changes: 4 additions & 0 deletions pvr.iptvsimple/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
v7.5.0
- Added: Support sub channel numbers
- Added: Allow setting scope for channels using catchup mode setting to enable overriding

v7.4.3
- Fixed: Add support for format specifiers use for detecting terminating catchup and granularity
- Update: Make inputstream add-ons a required dependency
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ msgstr ""

#. label: Catchup - allChannelsCatchupMode
msgctxt "#30104"
msgid "All channels support catchup using mode"
msgid "Channels support catchup using mode"
msgstr ""

#. label-group: Catchup - Watch From EPG
Expand Down Expand Up @@ -472,7 +472,25 @@ msgctxt "#30115"
msgid "Xtream codes"
msgstr ""

#empty strings from id 30116 to 30119
#. label: Catchup - catchupOverrideMode
msgctxt "#30116"
msgid "Include channels"
msgstr ""

#. label-option: Catchup - catchupOverrideMode
msgctxt "#30117"
msgid "without catchup mode"
msgstr ""

#. label-option: Catchup - catchupOverrideMode
msgctxt "#30118"
msgid "with catchup mode"
msgstr ""

#. label-option: Catchup - catchupOverrideMode
msgctxt "#30119"
msgid "with and without catchup mode (all channels)"
msgstr ""

#. label-category: timeshift
#. label-group: Timeshift - Timeshift
Expand Down Expand Up @@ -830,7 +848,7 @@ msgstr ""

#. help: Catchup - allChannelsCatchupMode
msgctxt "#30704"
msgid "If enabled it is assumed that all channels support catchup using the selected mode if they do not have catchup tags. In this case the 'Query format string' and 'Catchup window' number of days will come from the addon settings if needed. If this option is disabled then an M3U entry must have at least a 'catchup=' tag to enable catchup. The options for how to build the catch URL are: [B]Disabled[/B] - Do not assume all channel support catchup; [B]Default[/B] - Use catchup source as the full catchup URL, if there is no catchup source use Append mode; [B]Append[/B] - Append the catchup source to the channel URL, if there is no catchup source using the 'Query format string'; [B]Shift (SIPTV)[/B] - Append the standard SIPTV catchup string to the channel URL; [B]Flussonic[/B] - Build a flussonic URL from the channel URL; [B]Xtream codes[/B] - Build an Xtream codes URL from the channel URL."
msgid "If enabled it is assumed that channels support catchup using the selected catchup mode while also obeying the override mode. If required the 'Query format string' and 'Catchup window' number of days will come from the addon settings. If this option is disabled then an M3U entry must have at least a 'catchup=' tag to enable catchup. The options for how to build the catch URL are: [B]Disabled[/B] - Do not assume all channel support catchup; [B]Default[/B] - Use catchup source as the full catchup URL, if there is no catchup source use Append mode; [B]Append[/B] - Append the catchup source to the channel URL, if there is no catchup source using the 'Query format string'; [B]Shift (SIPTV)[/B] - Append the standard SIPTV catchup string to the channel URL; [B]Flussonic[/B] - Build a flussonic URL from the channel URL; [B]Xtream codes[/B] - Build an Xtream codes URL from the channel URL."
msgstr ""

#. help: Catchup - catchupPlayEpgAsLive
Expand All @@ -853,7 +871,12 @@ msgctxt "#30708"
msgid "When selected from the EPG the current live programme cannot be watched as catchup until finished."
msgstr ""

#empty strings from id 30709 to 307199
#. help: Catchup - catchupOverrideMode
msgctxt "#30709"
msgid "Set the scope for overriding the catchup mode. Options are: [B]without catchup mode[/B] - Only include channels with no catchup mode set (except legacy SIP [I]timeshift[/I] catchup mode); [B]with catchup mode[/B] - Only include channels with catchup mode set (ignore those without a catchup mode); [B]with and without catchup mode (all channels)[/B] - Include all channels ignoring any catchup mode from the M3U."
msgstr ""

#empty strings from id 30710 to 307019

#. help info - Timeshift

Expand Down
15 changes: 15 additions & 0 deletions pvr.iptvsimple/resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,21 @@
</constraints>
<control type="list" format="integer" />
</setting>
<setting id="catchupOverrideMode" type="integer" parent="allChannelsCatchupMode" label="30116" help="30709">
<level>0</level>
<default>false</default>
<constraints>
<options>
<option label="30117">0</option> <!-- DISABLED -->
<option label="30118">1</option> <!-- DEFAULT -->
<option label="30119">2</option> <!-- APPEND -->
</options>
</constraints>
<dependencies>
<dependency type="visible" setting="allChannelsCatchupMode" operator="!is">0</dependency>
</dependencies>
<control type="list" format="integer" />
</setting>
</group>
<group id="2" label="30105">
<setting id="catchupPlayEpgAsLive" type="boolean" label="30106" help="30705">
Expand Down
13 changes: 12 additions & 1 deletion src/iptvsimple/PlaylistLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,18 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c
}

if (!strChnlNo.empty() && !Settings::GetInstance().NumberChannelsByM3uOrderOnly())
channel.SetChannelNumber(std::atoi(strChnlNo.c_str()));
{
size_t found = strChnlNo.find('.');
if (found != std::string::npos)
{
channel.SetChannelNumber(std::atoi(strChnlNo.substr(0, found).c_str()));
channel.SetSubChannelNumber(std::atoi(strChnlNo.substr(found + 1).c_str()));
}
else
{
channel.SetChannelNumber(std::atoi(strChnlNo.c_str()));
}
}

double tvgShiftDecimal = std::atof(strTvgShift.c_str());

Expand Down
3 changes: 3 additions & 0 deletions src/iptvsimple/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ void Settings::ReadFromAddon(const std::string& userPath, const std::string& cli
m_catchupQueryFormat = kodi::GetSettingString("catchupQueryFormat");
m_catchupDays = kodi::GetSettingInt("catchupDays", 5);
m_allChannelsCatchupMode = kodi::GetSettingEnum<CatchupMode>("allChannelsCatchupMode", CatchupMode::DISABLED);
m_catchupOverrideMode = kodi::GetSettingEnum<CatchupOverrideMode>("catchupOverrideMode", CatchupOverrideMode::WITHOUT_TAGS);
m_catchupPlayEpgAsLive = kodi::GetSettingBoolean("catchupPlayEpgAsLive", false);
m_catchupWatchEpgBeginBufferMins = kodi::GetSettingInt("catchupWatchEpgBeginBufferMins", 5);
m_catchupWatchEpgEndBufferMins = kodi::GetSettingInt("catchupWatchEpgEndBufferMins", 15);
Expand Down Expand Up @@ -263,6 +264,8 @@ ADDON_STATUS Settings::SetValue(const std::string& settingName, const kodi::CSet
return SetSetting<int, ADDON_STATUS>(settingName, settingValue, m_catchupDays, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "allChannelsCatchupMode")
return SetEnumSetting<CatchupMode, ADDON_STATUS>(settingName, settingValue, m_allChannelsCatchupMode, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "catchupOverrideMode")
return SetEnumSetting<CatchupOverrideMode, ADDON_STATUS>(settingName, settingValue, m_catchupOverrideMode, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "catchupPlayEpgAsLive")
return SetSetting<bool, ADDON_STATUS>(settingName, settingValue, m_catchupPlayEpgAsLive, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "catchupWatchEpgBeginBufferMins")
Expand Down
10 changes: 10 additions & 0 deletions src/iptvsimple/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ namespace iptvsimple
PREFER_XMLTV
};

enum class CatchupOverrideMode
: int // same type as addon settings
{
WITHOUT_TAGS = 0,
WITH_TAGS,
ALL_CHANNELS
};

class Settings
{
public:
Expand Down Expand Up @@ -133,6 +141,7 @@ namespace iptvsimple
int GetCatchupDays() const { return m_catchupDays; }
time_t GetCatchupDaysInSeconds() const { return static_cast<time_t>(m_catchupDays) * 24 * 60 * 60; }
const CatchupMode& GetAllChannelsCatchupMode() const { return m_allChannelsCatchupMode; }
const CatchupOverrideMode& GetCatchupOverrideMode() const { return m_catchupOverrideMode; }
bool CatchupPlayEpgAsLive() const { return m_catchupPlayEpgAsLive; }
int GetCatchupWatchEpgBeginBufferMins() const { return m_catchupWatchEpgBeginBufferMins; }
time_t GetCatchupWatchEpgBeginBufferSecs() const { return static_cast<time_t>(m_catchupWatchEpgBeginBufferMins) * 60; }
Expand Down Expand Up @@ -282,6 +291,7 @@ namespace iptvsimple
std::string m_catchupQueryFormat;
int m_catchupDays = 3;
CatchupMode m_allChannelsCatchupMode = CatchupMode::DISABLED;
CatchupOverrideMode m_catchupOverrideMode = CatchupOverrideMode::WITHOUT_TAGS;
bool m_catchupPlayEpgAsLive = false;
int m_catchupWatchEpgBeginBufferMins = 5;
int m_catchupWatchEpgEndBufferMins = 15;
Expand Down
34 changes: 28 additions & 6 deletions src/iptvsimple/data/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void Channel::UpdateTo(Channel& left) const
left.m_uniqueId = m_uniqueId;
left.m_radio = m_radio;
left.m_channelNumber = m_channelNumber;
left.m_subChannelNumber = m_subChannelNumber;
left.m_encryptionSystem = m_encryptionSystem;
left.m_tvgShift = m_tvgShift;
left.m_channelName = m_channelName;
Expand All @@ -78,6 +79,7 @@ void Channel::UpdateTo(kodi::addon::PVRChannel& left) const
left.SetUniqueId(m_uniqueId);
left.SetIsRadio(m_radio);
left.SetChannelNumber(m_channelNumber);
left.SetSubChannelNumber(m_subChannelNumber);
left.SetChannelName(m_channelName);
left.SetEncryptionSystem(m_encryptionSystem);
left.SetIconPath(m_iconPath);
Expand All @@ -90,6 +92,7 @@ void Channel::Reset()
m_uniqueId = 0;
m_radio = false;
m_channelNumber = 0;
m_subChannelNumber = 0;
m_encryptionSystem = 0;
m_tvgShift = 0;
m_channelName.clear();
Expand Down Expand Up @@ -300,13 +303,32 @@ void Channel::ConfigureCatchupMode()
protocolOptions = m_streamURL.substr(found, m_streamURL.length());
}

if (Settings::GetInstance().GetAllChannelsCatchupMode() != CatchupMode::DISABLED &&
(m_catchupMode == CatchupMode::DISABLED || m_catchupMode == CatchupMode::TIMESHIFT))
if (Settings::GetInstance().GetAllChannelsCatchupMode() != CatchupMode::DISABLED)
{
// As CatchupMode::TIMESHIFT is obsolete and some providers use it
// incorrectly we allow this setting to override it
m_catchupMode = Settings::GetInstance().GetAllChannelsCatchupMode();
m_hasCatchup = true;
bool overrideCatchupMode = false;

if (Settings::GetInstance().GetCatchupOverrideMode() == CatchupOverrideMode::WITHOUT_TAGS &&
(m_catchupMode == CatchupMode::DISABLED || m_catchupMode == CatchupMode::TIMESHIFT))
{
// As CatchupMode::TIMESHIFT is obsolete and some providers use it
// incorrectly we allow this setting to override it
overrideCatchupMode = true;
}
else if (Settings::GetInstance().GetCatchupOverrideMode() == CatchupOverrideMode::WITH_TAGS &&
m_catchupMode != CatchupMode::DISABLED)
{
overrideCatchupMode = true;
}
else if (Settings::GetInstance().GetCatchupOverrideMode() == CatchupOverrideMode::ALL_CHANNELS)
{
overrideCatchupMode = true;
}

if (overrideCatchupMode)
{
m_catchupMode = Settings::GetInstance().GetAllChannelsCatchupMode();
m_hasCatchup = true;
}
}

switch (m_catchupMode)
Expand Down
12 changes: 8 additions & 4 deletions src/iptvsimple/data/Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ namespace iptvsimple

Channel() = default;
Channel(const Channel &c) : m_radio(c.IsRadio()), m_uniqueId(c.GetUniqueId()),
m_channelNumber(c.GetChannelNumber()), 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_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_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 All @@ -60,6 +60,9 @@ namespace iptvsimple
int GetChannelNumber() const { return m_channelNumber; }
void SetChannelNumber(int value) { m_channelNumber = value; }

int GetSubChannelNumber() const { return m_subChannelNumber; }
void SetSubChannelNumber(int value) { m_subChannelNumber = value; }

int GetEncryptionSystem() const { return m_encryptionSystem; }
void SetEncryptionSystem(int value) { m_encryptionSystem = value; }

Expand Down Expand Up @@ -142,6 +145,7 @@ namespace iptvsimple
bool m_radio = false;
int m_uniqueId = 0;
int m_channelNumber = 0;
int m_subChannelNumber = 0;
int m_encryptionSystem = 0;
int m_tvgShift = 0;
std::string m_channelName = "";
Expand Down

0 comments on commit 03e050f

Please sign in to comment.