Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pvr media new #892

Open
wants to merge 2 commits into
base: Piers
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ Settings related to Channel Logos.
- `Prefer XMLTV` - Use the channel logo from the XMLTV file if available otherwise use the M3U logo.

### Media
Media entries can be used to access the Video-On-Demand (VOD) library provided by IPTV services. The IPTV media library can be organized either as a plain list of channels or the hierarchy tree made of folders and PVR recordings.
Media entries can be used to access the Video-On-Demand (VOD) library provided by IPTV services. The IPTV media library can be organized either as a plain list of channels or the hierarchy tree made of folders and PVR media items.

An M3U entry can denote that it's media by having:
* an M3U property of `EXT-X-PLAYLIST-TYPE` set to `VOD`,
Expand All @@ -188,7 +188,7 @@ More detail on these can be found in [Supported M3U and XMLTV elements](#support

Note that the media item will read from the XMLTV file, where it will read just the first entry. The entry must have a start time greater than now and be within the boundaries of the Kodi PVR Guide settings.

* **Show media as recordings**: If enabled, all IPTV media entries can be shown as PVR recordings. Otherwise, they appear as regular PVR channels.
* **Show media as media**: If enabled, all IPTV media entries can be shown as PVR media items. Otherwise, they appear as regular PVR channels.
* **Group entries by title**: If multiple entries exist with matching titles, create a virtual folder to group them together.
* **Group entries by season**: If multiple entries exist with matching titles, try additionally grouping them in sub-folders representing seasons.
* **Include season and episode number in title**: Prepend the season and episode numbers to the title.
Expand All @@ -197,7 +197,7 @@ Note that the media item will read from the XMLTV file, where it will read just
- `Always append` - Always append it.
- `When no media-dir is present` - Only use the group title of the M3U when no media-dir is provided.
* **Force all M3U entries to be media**: Force the full playlist to be media, regardless of what tags are present. Since the introduction of multiple instances for PVR add-ons this option can be useful.
* **Include VODs as media**: Show VOD as recordings if enabled. If disabled only M3U entries with media attributes will be shown as PVR recordings.
* **Include VODs as media**: Show VOD as media if enabled. If disabled only M3U entries with media attributes will be shown as PVR media items.

### Timeshift
Timeshift settings for pausing/rewinding and fast-forwarding live streams.
Expand Down Expand Up @@ -447,7 +447,7 @@ plugin://plugin.video.my-vod-addon/play/catalog/channels/d8659669-b964-414c-aa9c
http://path-to-stream/live/channel-l.mkv
#EXTINF:-1 media="true",Channel M
http://path-to-stream/live/channel-m.mkv
#EXTINF:-1 radio="true" media="true" media-size="102400000",Channel N
#EXTINF:-1 radio="true" media="true" media-size="102400000" media-type="tv-show",Channel N
http://path-to-stream/live/channel-n.mkv
#EXTINF:-1 media-dir="/movies/scifi",Channel O
http://path-to-stream/live/channel-o.mkv
Expand All @@ -467,7 +467,7 @@ http://path-to-stream/live/channel-o.mkv
- For `Channel K` this is an example of a VOD style entry which uses a default `catchup-source` of `{catchup-id}` and will allow playback of any EPG entry with a `catchup-id` past, present or future via a Kodi plugin URL.
- For `Channel L` this is a tv media entry specified by the M3U `EXT-X-PLAYLIST-TYPE` property.
- For `Channel M` this is a tv media entry specified by the `media` attribute on the M3U entry.
- For `Channel N` this is a radio media entry of size 102400000 bytes.
- For `Channel N` this is a radio media entry of size 102400000 bytes, and the type is a TV show. Available `media-type` values are: `tv-show`, `movie`, `music-video`, `music`, `radio-show` and `podcast`.
- For `Channel O` this is a tv media entry specifying a directory path.

*Channel k Plugin example:*
Expand Down
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="22.1.1"
version="22.2.0"
name="IPTV Simple Client"
provider-name="nightik and Ross Nicholson">
<requires>@ADDON_DEPENDS@
Expand Down
3 changes: 3 additions & 0 deletions pvr.iptvsimple/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v22.2.0
- Move from recordings for IPTV library to PVR Media

v22.1.1
- Always add mimetype for inputstream.adaptive
- Better handled user-agent header for inputstream.adaptive use cases
Expand Down
2 changes: 1 addition & 1 deletion pvr.iptvsimple/resources/instance-settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@
</dependencies>
<control type="toggle" />
</setting>
<setting id="mediaVODAsRecordings" type="boolean" parent="mediaEnabled" label="30154" help="30804">
<setting id="mediaVODAsMedia" type="boolean" parent="mediaEnabled" label="30154" help="30804">
<level>2</level>
<default>true</default>
<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -621,14 +621,14 @@ msgctxt "#30153"
msgid "Include season and episode number in title"
msgstr ""

#. label: Media - mediaVODAsRecordings
#. label: Media - mediaVODAsMedia
msgctxt "#30154"
msgid "Include VODs as media"
msgstr ""

#. label: Media - mediaEnabled
msgctxt "#30155"
msgid "Show Media as recordings"
msgid "Show Media as media items"
msgstr ""

#. label: Media - mediaUseM3UGroupForGrouping
Expand Down Expand Up @@ -1111,14 +1111,14 @@ msgctxt "#30803"
msgid "Prepend the season and episode numbers to the title."
msgstr ""

#. help: Media - mediaVODAsRecordings
#. help: Media - mediaVODAsMedia
msgctxt "#30804"
msgid "Show VOD as recordings if enabled. If disabled only M3U entries with media attributes will be shown as recordings."
msgid "Show VOD as media if enabled. If disabled only M3U entries with media attributes will be shown as media items."
msgstr ""

#. label: Media - mediaEnabled
msgctxt "#30805"
msgid "If enabled, all IPTV media entries can be shown as PVR recordings. Otherwise, they appear as regular PVR channels."
msgid "If enabled, all IPTV media entries can be shown as PVR media. Otherwise, they appear as regular PVR channels."
msgstr ""

#. label: Media - mediaM3UGroupPath
Expand Down
36 changes: 14 additions & 22 deletions src/IptvSimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,9 @@ PVR_ERROR IptvSimple::GetCapabilities(kodi::addon::PVRCapabilities& capabilities
capabilities.SetSupportsRadio(true);
capabilities.SetSupportsChannelGroups(true);
capabilities.SetSupportsProviders(true);
capabilities.SetSupportsRecordingsRename(false);
capabilities.SetSupportsRecordingsLifetimeChange(false);
capabilities.SetSupportsDescrambleInfo(false);
capabilities.SetSupportsRecordings(true);
capabilities.SetSupportsRecordingsDelete(false);
capabilities.SetSupportsMedia(true);
capabilities.SetSupportsMediaTagSize(false);

return PVR_ERROR_NO_ERROR;
}
Expand Down Expand Up @@ -380,39 +378,33 @@ PVR_ERROR IptvSimple::SetEPGMaxFutureDays(int epgMaxFutureDays)
* Media
**************************************************************************/

PVR_ERROR IptvSimple::GetRecordingsAmount(bool deleted, int& amount)
PVR_ERROR IptvSimple::GetMediaAmount(int& amount)
{
std::lock_guard<std::mutex> lock(m_mutex);
if (deleted)
amount = 0;
else
amount = m_media.GetNumMedia();
amount = m_media.GetNumMedia();

return PVR_ERROR_NO_ERROR;
}

PVR_ERROR IptvSimple::GetRecordings(bool deleted, kodi::addon::PVRRecordingsResultSet& results)
PVR_ERROR IptvSimple::GetMedia(kodi::addon::PVRMediaTagsResultSet& results)
{
if (!deleted)
std::vector<kodi::addon::PVRMediaTag> media;
{
std::vector<kodi::addon::PVRRecording> media;
{
std::lock_guard<std::mutex> lock(m_mutex);
m_media.GetMedia(media);
}
std::lock_guard<std::mutex> lock(m_mutex);
m_media.GetMedia(media);
}

for (const auto& mediaTag : media)
results.Add(mediaTag);
for (const auto& mediaTag : media)
results.Add(mediaTag);

Logger::Log(LEVEL_DEBUG, "%s - media available '%d'", __func__, media.size());
}
Logger::Log(LEVEL_DEBUG, "%s - media available '%d'", __func__, media.size());

return PVR_ERROR_NO_ERROR;
}

PVR_ERROR IptvSimple::GetRecordingStreamProperties(const kodi::addon::PVRRecording& recording, std::vector<kodi::addon::PVRStreamProperty>& properties)
PVR_ERROR IptvSimple::GetMediaTagStreamProperties(const kodi::addon::PVRMediaTag& mediaTag, std::vector<kodi::addon::PVRStreamProperty>& properties)
{
std::string url = m_media.GetMediaEntryURL(recording);
std::string url = m_media.GetMediaEntryURL(mediaTag);

if (!url.empty())
{
Expand Down
6 changes: 3 additions & 3 deletions src/IptvSimple.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ class ATTR_DLL_LOCAL IptvSimple : public iptvsimple::IConnectionListener

PVR_ERROR StreamClosed() override;

PVR_ERROR GetRecordingsAmount(bool deleted, int& amount) override;
PVR_ERROR GetRecordings(bool deleted, kodi::addon::PVRRecordingsResultSet& results) override;
PVR_ERROR GetRecordingStreamProperties(const kodi::addon::PVRRecording& recording, std::vector<kodi::addon::PVRStreamProperty>& properties) override;
PVR_ERROR GetMediaAmount(int& amount) override;
PVR_ERROR GetMedia(kodi::addon::PVRMediaTagsResultSet& results) override;
PVR_ERROR GetMediaTagStreamProperties(const kodi::addon::PVRMediaTag& mediaTag, std::vector<kodi::addon::PVRStreamProperty>& properties) override;

//@}

Expand Down
2 changes: 1 addition & 1 deletion src/iptvsimple/Epg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ void Epg::ReloadEPG()
for (const auto& myChannel : m_channels.GetChannelsList())
m_client->TriggerEpgUpdate(myChannel.GetUniqueId());

m_client->TriggerRecordingUpdate();
m_client->TriggerMediaUpdate();
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/iptvsimple/InstanceSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void InstanceSettings::ReadSettings()

// Media
m_instance.CheckInstanceSettingBoolean("mediaEnabled", m_mediaEnabled);
m_instance.CheckInstanceSettingBoolean("mediaVODAsRecordings", m_showVodAsRecordings);
m_instance.CheckInstanceSettingBoolean("mediaVODAsMedia", m_showVodAsMedia);
m_instance.CheckInstanceSettingBoolean("mediaGroupByTitle", m_groupMediaByTitle);
m_instance.CheckInstanceSettingBoolean("mediaGroupBySeason", m_groupMediaBySeason);
m_instance.CheckInstanceSettingEnum<MediaUseM3UGroupPathMode>("mediaM3UGroupPath", m_mediaUseM3UGroupPathMode);
Expand Down Expand Up @@ -291,8 +291,8 @@ ADDON_STATUS InstanceSettings::SetSetting(const std::string& settingName, const
return SetEnumSetting<MediaUseM3UGroupPathMode, ADDON_STATUS>(settingName, settingValue, m_mediaUseM3UGroupPathMode, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "mediaForcePlaylist")
return SetSetting<bool, ADDON_STATUS>(settingName, settingValue, m_mediaForcePlaylist, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "mediaVODAsRecordings")
return SetSetting<bool, ADDON_STATUS>(settingName, settingValue, m_showVodAsRecordings, ADDON_STATUS_OK, ADDON_STATUS_OK);
else if (settingName == "mediaVODAsMedia")
return SetSetting<bool, ADDON_STATUS>(settingName, settingValue, m_showVodAsMedia, ADDON_STATUS_OK, ADDON_STATUS_OK);
// Timeshift
else if (settingName == "timeshiftEnabled")
return SetSetting<bool, ADDON_STATUS>(settingName, settingValue, m_timeshiftEnabled, ADDON_STATUS_OK, ADDON_STATUS_OK);
Expand Down
4 changes: 2 additions & 2 deletions src/iptvsimple/InstanceSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ namespace iptvsimple
bool UseLocalLogosOnlyIgnoreM3U() const { return m_useLocalLogosOnly; }

bool IsMediaEnabled() const { return m_mediaEnabled; }
bool ShowVodAsRecordings() const { return m_showVodAsRecordings; }
bool ShowVodAsMedia() const { return m_showVodAsMedia; }
bool GroupMediaByTitle() const { return m_groupMediaByTitle; }
bool GroupMediaBySeason() const { return m_groupMediaBySeason; }
const MediaUseM3UGroupPathMode& GetMediaUseM3UGroupPathMode() { return m_mediaUseM3UGroupPathMode; }
Expand Down Expand Up @@ -312,7 +312,7 @@ namespace iptvsimple
bool m_includeShowInfoInMediaTitle = false;
MediaUseM3UGroupPathMode m_mediaUseM3UGroupPathMode = MediaUseM3UGroupPathMode::IGNORE_GROUP_NAME;
bool m_mediaForcePlaylist = false;
bool m_showVodAsRecordings = true;
bool m_showVodAsMedia = true;

// Timeshift
bool m_timeshiftEnabled = false;
Expand Down
12 changes: 6 additions & 6 deletions src/iptvsimple/Media.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ Media::Media(std::shared_ptr<iptvsimple::InstanceSettings>& settings) : m_settin
{
}

void Media::GetMedia(std::vector<kodi::addon::PVRRecording>& kodiRecordings)
void Media::GetMedia(std::vector<kodi::addon::PVRMediaTag>& kodiMedia)
{
for (auto& mediaEntry : m_media)
{
Logger::Log(LEVEL_DEBUG, "%s - Transfer mediaEntry '%s', MediaEntry Id '%s'", __func__, mediaEntry.GetTitle().c_str(), mediaEntry.GetMediaEntryId().c_str());
kodi::addon::PVRRecording kodiRecording;
kodi::addon::PVRMediaTag kodiMediaEntry;

mediaEntry.UpdateTo(kodiRecording, IsInVirtualMediaEntryFolder(mediaEntry), m_haveMediaTypes);
mediaEntry.UpdateTo(kodiMediaEntry, IsInVirtualMediaEntryFolder(mediaEntry), m_haveMediaTypes);

kodiRecordings.emplace_back(kodiRecording);
kodiMedia.emplace_back(kodiMediaEntry);
}
}

Expand Down Expand Up @@ -136,11 +136,11 @@ bool Media::IsInVirtualMediaEntryFolder(const MediaEntry& mediaEntryToCheck) con
return false;
}

const std::string Media::GetMediaEntryURL(const kodi::addon::PVRRecording& recording)
const std::string Media::GetMediaEntryURL(const kodi::addon::PVRMediaTag& mediaTag)
{
Logger::Log(LEVEL_INFO, "%s", __func__);

auto mediaEntry = GetMediaEntry(recording.GetRecordingId());
auto mediaEntry = GetMediaEntry(mediaTag.GetMediaTagId());

if (!mediaEntry.GetMediaEntryId().empty())
return mediaEntry.GetStreamURL();
Expand Down
4 changes: 2 additions & 2 deletions src/iptvsimple/Media.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ namespace iptvsimple
{
public:
Media(std::shared_ptr<iptvsimple::InstanceSettings>& settings);
void GetMedia(std::vector<kodi::addon::PVRRecording>& kodiRecordings);
void GetMedia(std::vector<kodi::addon::PVRMediaTag>& kodiMedia);
int GetNumMedia() const;
void Clear();
const std::string GetMediaEntryURL(const kodi::addon::PVRRecording& mediaEntry);
const std::string GetMediaEntryURL(const kodi::addon::PVRMediaTag& mediaEntry);
const iptvsimple::data::MediaEntry* FindMediaEntry(const std::string& id, const std::string& displayName) const;

bool AddMediaEntry(iptvsimple::data::MediaEntry& entry, std::vector<int>& groupIdList, iptvsimple::ChannelGroups& channelGroups, bool channelHadGroups);
Expand Down
11 changes: 9 additions & 2 deletions src/iptvsimple/PlaylistLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ bool PlaylistLoader::LoadPlayList()
isMediaEntry = line.find(MEDIA) != std::string::npos ||
line.find(MEDIA_DIR) != std::string::npos ||
line.find(MEDIA_SIZE) != std::string::npos ||
line.find(MEDIA_TYPE) != std::string::npos ||
m_settings->MediaForcePlaylist();

overrideRealTime = GetOverrideRealTime(line);
Expand Down Expand Up @@ -224,7 +225,7 @@ bool PlaylistLoader::LoadPlayList()
Logger::Log(LEVEL_DEBUG, "%s - Adding channel or Media Entry '%s' with URL: '%s'", __FUNCTION__, tmpChannel.GetChannelName().c_str(), line.c_str());

if (m_settings->IsMediaEnabled() &&
(isMediaEntry || (m_settings->ShowVodAsRecordings() && !isRealTime)))
(isMediaEntry || (m_settings->ShowVodAsMedia() && !isRealTime)))
{
MediaEntry entry = tmpMediaEntry;
entry.UpdateFrom(tmpChannel);
Expand Down Expand Up @@ -340,6 +341,7 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c
std::string strMedia = ReadMarkerValue(infoLine, MEDIA);
std::string strMediaDir = ReadMarkerValue(infoLine, MEDIA_DIR);
std::string strMediaSize = ReadMarkerValue(infoLine, MEDIA_SIZE);
std::string strMediaType = ReadMarkerValue(infoLine, MEDIA_TYPE);

kodi::UnknownToUTF8(strTvgName, strTvgName);
kodi::UnknownToUTF8(strCatchupSource, strCatchupSource);
Expand Down Expand Up @@ -521,6 +523,11 @@ std::string PlaylistLoader::ParseIntoChannel(const std::string& line, Channel& c
if (!strMediaSize.empty())
mediaEntry.SetSizeInBytes(std::strtoll(strMediaSize.c_str(), nullptr, 10));

if (!strMediaType.empty())
{
mediaEntry.SetMediaType(strMediaType);
}

return groupNames;
}

Expand Down Expand Up @@ -595,7 +602,7 @@ void PlaylistLoader::ReloadPlayList()
m_client->TriggerChannelUpdate();
m_client->TriggerChannelGroupsUpdate();
m_client->TriggerProvidersUpdate();
m_client->TriggerRecordingUpdate();
m_client->TriggerMediaUpdate();
}
else
{
Expand Down
1 change: 1 addition & 0 deletions src/iptvsimple/PlaylistLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 MEDIA_TYPE = "media-type=";
static const std::string REALTIME_OVERRIDE = "realtime=\"";
static const std::string KODIPROP_MARKER = "#KODIPROP:";
static const std::string EXTVLCOPT_MARKER = "#EXTVLCOPT:";
Expand Down
Loading
Loading