From d62d9613d0e6193d39fa2cd4d95670bf7922d3a7 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sat, 22 Jul 2023 11:21:10 +0100 Subject: [PATCH 1/3] Revert "Support async connect" This reverts commit 34a0b8370efc860190518ee5ff1ab9f23af7cdbe. --- src/IptvSimple.cpp | 10 +--------- src/iptvsimple/PlaylistLoader.cpp | 6 +----- src/iptvsimple/PlaylistLoader.h | 2 +- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/IptvSimple.cpp b/src/IptvSimple.cpp index 86fe3f06b..c19c0a503 100644 --- a/src/IptvSimple.cpp +++ b/src/IptvSimple.cpp @@ -35,8 +35,6 @@ bool IptvSimple::Initialise() { std::lock_guard lock(m_mutex); - ConnectionStateChange("", PVR_CONNECTION_STATE_CONNECTING, ""); - m_channels.Init(); m_channelGroups.Init(); m_providers.Init(); @@ -45,11 +43,6 @@ bool IptvSimple::Initialise() { m_channels.ChannelsLoadFailed(); m_channelGroups.ChannelGroupsLoadFailed(); - ConnectionStateChange("", PVR_CONNECTION_STATE_DISCONNECTED, ""); - } - else - { - ConnectionStateChange("", PVR_CONNECTION_STATE_CONNECTED, ""); } m_epg.Init(EpgMaxPastDays(), EpgMaxFutureDays()); @@ -123,8 +116,7 @@ void IptvSimple::Process() std::this_thread::sleep_for(std::chrono::milliseconds(1000)); m_settings->ReloadAddonInstanceSettings(); - if (m_playlistLoader.ReloadPlayList()) - ConnectionStateChange("", PVR_CONNECTION_STATE_CONNECTED, ""); + m_playlistLoader.ReloadPlayList(); m_epg.ReloadEPG(); // Reloading EPG also updates media m_reloadChannelsGroupsAndEPG = false; diff --git a/src/iptvsimple/PlaylistLoader.cpp b/src/iptvsimple/PlaylistLoader.cpp index a14788e74..3e0e5c013 100644 --- a/src/iptvsimple/PlaylistLoader.cpp +++ b/src/iptvsimple/PlaylistLoader.cpp @@ -535,7 +535,7 @@ void PlaylistLoader::ParseSinglePropertyIntoChannel(const std::string& line, Cha } } -bool PlaylistLoader::ReloadPlayList() +void PlaylistLoader::ReloadPlayList() { m_m3uLocation = m_settings->GetM3ULocation(); @@ -550,15 +550,11 @@ bool PlaylistLoader::ReloadPlayList() m_client->TriggerChannelGroupsUpdate(); m_client->TriggerProvidersUpdate(); m_client->TriggerRecordingUpdate(); - - return true; } else { m_channels.ChannelsLoadFailed(); m_channelGroups.ChannelGroupsLoadFailed(); - - return false; } } diff --git a/src/iptvsimple/PlaylistLoader.h b/src/iptvsimple/PlaylistLoader.h index 8d2009f96..593c93ef8 100644 --- a/src/iptvsimple/PlaylistLoader.h +++ b/src/iptvsimple/PlaylistLoader.h @@ -71,7 +71,7 @@ namespace iptvsimple bool Init(); bool LoadPlayList(); - bool ReloadPlayList(); + void ReloadPlayList(); private: static std::string ReadMarkerValue(const std::string& line, const std::string& markerName); From 6b14d4ee30fa4d8fc886fe98a5dfa713c2eb4028 Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Tue, 25 Jul 2023 21:51:43 +0100 Subject: [PATCH 2/3] M3U format specifier to override realtime processing in Kodi PVR where the stream should not be treated like VOD/Media in the UI --- README.md | 1 + src/iptvsimple/PlaylistLoader.cpp | 39 ++++++++++++++++++++++++++++--- src/iptvsimple/PlaylistLoader.h | 1 + 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c78afb19f..33392d238 100644 --- a/README.md +++ b/README.md @@ -520,6 +520,7 @@ http://path-to-stream/live/channel-z.ts - `media`: Specifies that this entry is a media entry by setting the values true `true`. Same as setting `#EXT-X-PLAYLIST-TYPE` to VOD. - `media-dir`: An optional directory path which should specifiy where in the hierarchy this media entry should be represented. The path separator is `/`. - `media-size`: An optional size of the media entry in bytes. Note: this is not usually available for VOD libraries. + - `realtime`: Live streams in PVR disable features such as passthrough by default. Set this item to "false" to bypass this behaviour if the stream should not be treated like VOD/Media in the UI. - `#EXTGRP`: A semi-colon separted list of channel groups that this channel belongs to. - `#KODIPROP`: A single property in the format `key=value` that can be passed to Kodi. Multiple can be passed each on a separate line. - `#EXTVLCOPT`: A single property in the format `key=value` that can be passed to Kodi. Multiple can be passed each on a separate line. Note that if either a `http-user-agent` or a `http-referrer` property is found it will added to the URL as a HTTP header as `user-agent` or `referrer` respectively if not already provided in the URL. These two fields specifically will be dropped as properties whether or not they are added as header values. They will be added in the same format as the `URL` below. diff --git a/src/iptvsimple/PlaylistLoader.cpp b/src/iptvsimple/PlaylistLoader.cpp index 3e0e5c013..45d611184 100644 --- a/src/iptvsimple/PlaylistLoader.cpp +++ b/src/iptvsimple/PlaylistLoader.cpp @@ -38,6 +38,33 @@ bool PlaylistLoader::Init() return true; } +namespace { + +bool GetOverrideRealTime(std::string& line) +{ + size_t realtimeIndex = line.find(REALTIME_OVERRIDE); + if (realtimeIndex != std::string::npos) + { + size_t startValueIndex = realtimeIndex + REALTIME_OVERRIDE.length(); + size_t endQuoteIndex = line.find('"', startValueIndex); + if (endQuoteIndex != std::string::npos) + { + size_t valueLength = endQuoteIndex - startValueIndex; + std::string value = line.substr(startValueIndex, valueLength); + StringUtils::ToLower(value); + // The only value that matters is if the 'realtime' specifier is 'false' + // that means we want to override the realtime value but not treat the stream + // like media/VOD in the UI + // It's a bit confusing, but hey, that's Kodi for you ;) + return value == "false"; + } + } + + return false; +} + +} + bool PlaylistLoader::LoadPlayList() { auto started = std::chrono::high_resolution_clock::now(); @@ -64,6 +91,7 @@ bool PlaylistLoader::LoadPlayList() /* load channels */ bool isFirstLine = true; bool isRealTime = true; + bool overrideRealTime = false; bool isMediaEntry = false; int epgTimeShift = 0; int catchupCorrectionSecs = m_settings->GetCatchupCorrectionSecs(); @@ -149,6 +177,8 @@ bool PlaylistLoader::LoadPlayList() line.find(MEDIA_SIZE) != std::string::npos || m_settings->MediaForcePlaylist(); + overrideRealTime = GetOverrideRealTime(line); + const std::string groupNamesListString = ParseIntoChannel(line, tmpChannel, tmpMediaEntry, currentChannelGroupIdList, epgTimeShift, catchupCorrectionSecs, xeevCatchup); if (!groupNamesListString.empty()) @@ -187,9 +217,12 @@ bool PlaylistLoader::LoadPlayList() { Logger::Log(LEVEL_DEBUG, "%s - Adding channel '%s' with URL: '%s'", __FUNCTION__, tmpChannel.GetChannelName().c_str(), line.c_str()); - if ((isRealTime || !m_settings->IsMediaEnabled() || !m_settings->ShowVodAsRecordings()) && !isMediaEntry) + if ((isRealTime || overrideRealTime || !m_settings->IsMediaEnabled() || !m_settings->ShowVodAsRecordings()) && !isMediaEntry) { - tmpChannel.AddProperty(PVR_STREAM_PROPERTY_ISREALTIMESTREAM, "true"); + // There are cases where we want the stream to be represetned as a channel with live streaming disabled + // to allow features such as passthrough to work. We don't want this to be VOD as then it would be treated like media. + if (!overrideRealTime) + tmpChannel.AddProperty(PVR_STREAM_PROPERTY_ISREALTIMESTREAM, "true"); Channel channel = tmpChannel; channel.SetStreamURL(line); @@ -206,12 +239,12 @@ bool PlaylistLoader::LoadPlayList() if (!m_media.AddMediaEntry(entry, currentChannelGroupIdList, m_channelGroups, channelHadGroups)) Logger::Log(LEVEL_DEBUG, "%s - Counld not add media entry as an entry with the same gnenerated unique ID already exists", __func__); - } tmpChannel.Reset(); tmpMediaEntry.Reset(); isRealTime = true; + overrideRealTime = false; isMediaEntry = false; channelHadGroups = false; } diff --git a/src/iptvsimple/PlaylistLoader.h b/src/iptvsimple/PlaylistLoader.h index 593c93ef8..ed50102f7 100644 --- a/src/iptvsimple/PlaylistLoader.h +++ b/src/iptvsimple/PlaylistLoader.h @@ -48,6 +48,7 @@ namespace iptvsimple static const std::string MEDIA = "media="; static const std::string MEDIA_DIR = "media-dir="; static const std::string MEDIA_SIZE = "media-size="; + static const std::string REALTIME_OVERRIDE = "realtime=\""; static const std::string KODIPROP_MARKER = "#KODIPROP:"; static const std::string EXTVLCOPT_MARKER = "#EXTVLCOPT:"; static const std::string EXTVLCOPT_DASH_MARKER = "#EXTVLCOPT--"; From 3a4df7b784011f44b905b8bc6276ed3211bc839c Mon Sep 17 00:00:00 2001 From: phunkyfish Date: Sat, 22 Jul 2023 11:55:58 +0100 Subject: [PATCH 3/3] changelog and version 20.11.0 --- pvr.iptvsimple/addon.xml.in | 2 +- pvr.iptvsimple/changelog.txt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pvr.iptvsimple/addon.xml.in b/pvr.iptvsimple/addon.xml.in index e581cf07a..677eb8163 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 8cd8e5434..64ff7afc0 100644 --- a/pvr.iptvsimple/changelog.txt +++ b/pvr.iptvsimple/changelog.txt @@ -1,3 +1,7 @@ +v20.11.0 +- M3U format specifier to override realtime processing in Kodi PVR where the stream should not be treated like VOD/Media in the UI +- Revert the support of Async connect that was causing Connection Lost error messages for users of this add-on + v20.10.1 - Remove empty media groups before sending to Kodi PVR