Skip to content

Commit

Permalink
Genre and sub genre mapping
Browse files Browse the repository at this point in the history
Use the genre mapping xml file to map genre sub types from the English codes send by NextPVR.  Extend genre type and sub type matching to recordings.
  • Loading branch information
emveepee committed Dec 19, 2024
1 parent 7b372f6 commit 28924b8
Show file tree
Hide file tree
Showing 10 changed files with 352 additions and 27 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set(NEXTPVR_SOURCES src/addon.cpp
src/buffers/ClientTimeshift.cpp
src/buffers/RecordingBuffer.cpp
src/buffers/CircularBuffer.cpp
src/utilities/GenreMapper.cpp
src/utilities/SettingsMigration.cpp
src/buffers/Seeker.cpp)

Expand All @@ -48,6 +49,7 @@ set(NEXTPVR_HEADERS src/addon.h
src/buffers/RecordingBuffer.h
src/buffers/CircularBuffer.h
src/buffers/Seeker.h
src/utilities/GenreMapper.h
src/utilities/SettingsMigration.h
src/utilities/XMLUtils.h)

Expand Down
83 changes: 83 additions & 0 deletions pvr.nextpvr/resources/genre-mapping.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<translations>
<!-- standard DVB mappings -->
<genre name="Movie / Drama" type="16" subtype="0"/>
<genre name="Detective / Thriller" type="16" subtype="1"/>
<genre name="Adventure / Western / War" type="16" subtype="2"/>
<genre name="Science fiction / Fantasy / Horror" type="16" subtype="3"/>
<genre name="Comedy" type="16" subtype="4"/>
<genre name="Soap / Melodrama / Folkloric" type="16" subtype="5"/>
<genre name="Romance" type="16" subtype="6"/>
<genre name="Serious / Classical /Religious / Historical movie / Drama" type="16" subtype="7"/>
<genre name="Adult movie / Drama" type="16" subtype="8"/>
<genre name="News / Current affairs" type="32" subtype="0"/>
<genre name="News / Weather report" type="32" subtype="1"/>
<genre name="News magazine" type="32" subtype="2"/>
<genre name="Documentary" type="32" subtype="3"/>
<genre name="Discussion / Interview / Debate" type="32" subtype="4"/>
<genre name="Show / Game show" type="48" subtype="0"/>
<genre name="Game show / Quiz / Contest" type="48" subtype="1"/>
<genre name="Variety show" type="48" subtype="2"/>
<genre name="Talk show" type="48" subtype="3"/>
<genre name="Sports" type="64" subtype="0"/>
<genre name="Special event" type="64" subtype="1"/>
<genre name="Sports magazine" type="64" subtype="2"/>
<genre name="Football / Soccer" type="64" subtype="3"/>
<genre name="Tennis / Squash" type="64" subtype="4"/>
<genre name="Team sports" type="64" subtype="5"/>
<genre name="Athletics" type="64" subtype="6"/>
<genre name="Motor sport" type="64" subtype="7"/>
<genre name="Water sport" type="64" subtype="8"/>
<genre name="Winter sports" type="64" subtype="9"/>
<genre name="Equestrian" type="64" subtype="10"/>
<genre name="Martial sports" type="64" subtype="11"/>
<genre name="Childrens / Youth" type="80" subtype="0"/>
<genre name="Pre-school children&apos;s programmes" type="80" subtype="1"/>
<genre name="Entertainment programmes for 6 To14" type="80" subtype="2"/>
<genre name="Entertainment programmes for 10 to 16" type="80" subtype="3"/>
<genre name="Informational / Educational / School programmes" type="80" subtype="4"/>
<genre name="Cartoons / Puppets" type="80" subtype="5"/>
<genre name="Music / Ballet / Dance" type="96" subtype="0"/>
<genre name="Rock / Pop" type="96" subtype="1"/>
<genre name="Serious music / Classical music" type="96" subtype="2"/>
<genre name="Folk / Traditional music" type="96" subtype="3"/>
<genre name="Jazz" type="96" subtype="4"/>
<genre name="Musical / Opera" type="96" subtype="5"/>
<genre name="Ballet" type="96" subtype="6"/>
<genre name="Arts / Culture" type="112" subtype="0"/>
<genre name="Performing srts" type="112" subtype="1"/>
<genre name="Fine arts" type="112" subtype="2"/>
<genre name="Religion" type="112" subtype="3"/>
<genre name="Popular culture / Traditional arts" type="112" subtype="4"/>
<genre name="Literature" type="112" subtype="5"/>
<genre name="Film / Cinema" type="112" subtype="6"/>
<genre name="Experimental film / video" type="112" subtype="7"/>
<genre name="Broadcasting / Press" type="112" subtype="8"/>
<genre name="New media" type="112" subtype="9"/>
<genre name="Arts / Culture magazines" type="112" subtype="10"/>
<genre name="Fashion" type="112" subtype="11"/>
<genre name="Social / Political / Economics" type="128" subtype="0"/>
<genre name="Magazines / Reports / Documentary" type="128" subtype="1"/>
<genre name="Economics / Social advisory" type="128" subtype="2"/>
<genre name="Remarkable people" type="128" subtype="3"/>
<genre name="Education / Science / Factual" type="144" subtype="0"/>
<genre name="Nature / Animals / Environment" type="144" subtype="1"/>
<genre name="Technology / Natural sciences" type="144" subtype="2"/>
<genre name="Medicine / Physiology / Psychology" type="144" subtype="3"/>
<genre name="Foreign countries / Expeditions" type="144" subtype="4"/>
<genre name="Social / Spiritual sciences" type="144" subtype="5"/>
<genre name="Further education" type="144" subtype="6"/>
<genre name="Languages" type="144" subtype="7"/>
<genre name="Leisure / Hobbies" type="160" subtype="0"/>
<genre name="Tourism / Travel" type="160" subtype="1"/>
<genre name="Handicraft" type="160" subtype="2"/>
<genre name="Motoring" type="160" subtype="3"/>
<genre name="Fitness &amp; Health" type="160" subtype="4"/>
<genre name="Cooking" type="160" subtype="5"/>
<genre name="Advertisement / Shopping" type="160" subtype="6"/>
<genre name="Gardening" type="160" subtype="7"/>
<genre name="Original language" type="176" subtype="0"/>
<genre name="Black &amp; white" type="176" subtype="1"/>
<genre name="Unpublished" type="176" subtype="2"/>
<genre name="Live broadcast" type="176" subtype="3"/>
<genre name="Drama" type="240" subtype="0"/>
</translations>
35 changes: 17 additions & 18 deletions src/EPG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ using namespace NextPVR::utilities;
/************************************************************/
/** EPG handling */

EPG::EPG(const std::shared_ptr<InstanceSettings>& settings, Request& request, Recordings& recordings, Channels& channels) :
EPG::EPG(const std::shared_ptr<InstanceSettings>& settings, Request& request, Recordings& recordings, Channels& channels,GenreMapper& genreMapper) :
m_settings(settings),
m_request(request),
m_recordings(recordings),
m_genreMapper(genreMapper),
m_channels(channels)
{
}
Expand Down Expand Up @@ -51,7 +52,7 @@ PVR_ERROR EPG::GetEPGForChannel(int channelUid, time_t start, time_t end, kodi::
if (m_request.DoMethodRequest(request, doc) == tinyxml2::XML_SUCCESS)
{
tinyxml2::XMLNode* listingsNode = doc.RootElement()->FirstChildElement("listings");
for (tinyxml2::XMLNode* pListingNode = listingsNode->FirstChildElement("l"); pListingNode; pListingNode = pListingNode->NextSiblingElement())
for (const tinyxml2::XMLNode* pListingNode = listingsNode->FirstChildElement("l"); pListingNode; pListingNode = pListingNode->NextSiblingElement())
{
kodi::addon::PVREPGTag broadcast;
std::string title;
Expand Down Expand Up @@ -82,6 +83,14 @@ PVR_ERROR EPG::GetEPGForChannel(int channelUid, time_t start, time_t end, kodi::
broadcast.SetStartTime(stol(startTime));
broadcast.SetUniqueBroadcastId(stoi(endTime));
broadcast.SetEndTime(stol(endTime));

static std::regex yearRegex("^(.+[12]\\d{3})\\n");
std::smatch base_match;
if (std::regex_search(description, base_match, yearRegex))
{
kodi::tools::StringUtils::Replace(description, base_match[0].str(), base_match[1].str() + " ");
}

broadcast.SetPlot(description);

std::string artworkPath;
Expand Down Expand Up @@ -111,23 +120,13 @@ PVR_ERROR EPG::GetEPGForChannel(int channelUid, time_t start, time_t end, kodi::
broadcast.SetGenreSubType(XMLUtils::GetIntValue(pListingNode, "genre_sub_type"));

}
std::string allGenres;
if (XMLUtils::GetAdditiveString(pListingNode->FirstChildElement("genres"), "genre", EPG_STRING_TOKEN_SEPARATOR, allGenres, true))
{
if (allGenres.find(EPG_STRING_TOKEN_SEPARATOR) != std::string::npos)
{
if (broadcast.GetGenreType() != EPG_GENRE_USE_STRING)
{
broadcast.SetGenreSubType(EPG_GENRE_USE_STRING);
}
broadcast.SetGenreDescription(allGenres);
}
else if (m_settings->m_genreString && broadcast.GetGenreSubType() != EPG_GENRE_USE_STRING)
{
broadcast.SetGenreDescription(allGenres);
broadcast.SetGenreSubType(EPG_GENRE_USE_STRING);
}

NextPVR::GenreBlock genreBlock = { sGenre, broadcast.GetGenreType(), EPG_EVENT_CONTENTMASK_UNDEFINED };
if (m_genreMapper.ParseAllGenres(pListingNode, genreBlock))
{
broadcast.SetGenreDescription(genreBlock.description);
broadcast.SetGenreType(genreBlock.genreType);
broadcast.SetGenreSubType(genreBlock.genreSubType);
}

int season{ EPG_TAG_INVALID_SERIES_EPISODE };
Expand Down
4 changes: 3 additions & 1 deletion src/EPG.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
#include <kodi/addon-instance/PVR.h>
#include "Channels.h"
#include "Recordings.h"
#include "utilities/GenreMapper.h"

namespace NextPVR
{
class ATTR_DLL_LOCAL EPG
{
public:
EPG(const std::shared_ptr<InstanceSettings>& settings, Request& request, Recordings& recordings, Channels& channels);
EPG(const std::shared_ptr<InstanceSettings>& settings, Request& request, Recordings& recordings, Channels& channels, GenreMapper& genreMapper);
PVR_ERROR GetEPGForChannel(int channelUid, time_t start, time_t end, kodi::addon::PVREPGTagsResultSet& results);

private:
Expand All @@ -30,5 +31,6 @@ namespace NextPVR
Request& m_request;
Recordings& m_recordings;
Channels& m_channels;
GenreMapper& m_genreMapper;
};
} // namespace NextPVR
14 changes: 9 additions & 5 deletions src/Recordings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ using namespace NextPVR::utilities;
/************************************************************/
/** Record handling **/

Recordings::Recordings(const std::shared_ptr<InstanceSettings>& settings, Request& request, Timers& timers, Channels& channels, cPVRClientNextPVR& pvrclient) :
Recordings::Recordings(const std::shared_ptr<InstanceSettings>& settings, Request& request, Timers& timers, Channels& channels,
GenreMapper& genreMapper, cPVRClientNextPVR& pvrclient) :
m_settings(settings),
m_request(request),
m_timers(timers),
m_channels(channels),
m_genreMapper(genreMapper),
m_pvrclient(pvrclient)
{

Expand Down Expand Up @@ -443,11 +445,13 @@ bool Recordings::UpdatePvrRecording(const tinyxml2::XMLNode* pRecordingNode, kod
tag.SetFanartPath(artworkPath + "&prefer=fanart");
tag.SetThumbnailPath(artworkPath + "&prefer=poster");
}
if (XMLUtils::GetAdditiveString(pRecordingNode->FirstChildElement("genres"), "genre", EPG_STRING_TOKEN_SEPARATOR, buffer, true))

NextPVR::GenreBlock genreBlock = { "", EPG_EVENT_CONTENTMASK_UNDEFINED, EPG_EVENT_CONTENTMASK_UNDEFINED };
if (m_genreMapper.ParseAllGenres(pRecordingNode, genreBlock))
{
tag.SetGenreType(EPG_GENRE_USE_STRING);
tag.SetGenreSubType(0);
tag.SetGenreDescription(buffer);
tag.SetGenreDescription(genreBlock.description);
tag.SetGenreType(genreBlock.genreType);
tag.SetGenreSubType(genreBlock.genreSubType);
}

std::string significance;
Expand Down
5 changes: 4 additions & 1 deletion src/Recordings.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "BackendRequest.h"
#include "Timers.h"
#include "utilities/GenreMapper.h"
#include <kodi/addon-instance/PVR.h>


Expand All @@ -21,7 +22,8 @@ namespace NextPVR
{

public:
Recordings(const std::shared_ptr<InstanceSettings>& settings, Request& request, Timers& timers, Channels& channels, cPVRClientNextPVR& pvrclent);
Recordings(const std::shared_ptr<InstanceSettings>& settings, Request& request, Timers& timers, Channels& channels,
GenreMapper& genreMapper, cPVRClientNextPVR& pvrclent);
/* Recording handling **/
PVR_ERROR GetRecordingsAmount(bool deleted, int& amount);
PVR_ERROR GetDriveSpace(uint64_t& total, uint64_t& used);
Expand All @@ -48,6 +50,7 @@ namespace NextPVR
Request& m_request;
Timers& m_timers;
Channels& m_channels;
GenreMapper& m_genreMapper;
cPVRClientNextPVR& m_pvrclient;

// update these at end of counting loop can be called during action
Expand Down
5 changes: 3 additions & 2 deletions src/pvrclient-nextpvr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ cPVRClientNextPVR::cPVRClientNextPVR(const CNextPVRAddon& base, const kodi::addo
m_request(m_settings),
m_channels(m_settings, m_request),
m_timers(m_settings, m_request, m_channels, *this),
m_recordings(m_settings, m_request, m_timers, m_channels, *this),
m_recordings(m_settings, m_request, m_timers, m_channels,m_genreMapper, *this),
m_menuhook(m_settings, m_recordings, m_channels, *this),
m_epg(m_settings, m_request, m_recordings, m_channels)
m_genreMapper(m_settings),
m_epg(m_settings, m_request, m_recordings, m_channels, m_genreMapper)
{
if (!kodi::vfs::DirectoryExists(m_settings->m_instanceDirectory))
{
Expand Down
2 changes: 2 additions & 0 deletions src/pvrclient-nextpvr.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "Recordings.h"
#include "InstanceSettings.h"
#include "Timers.h"
#include "utilities/GenreMapper.h"
#include "buffers/ClientTimeshift.h"
#include "buffers/DummyBuffer.h"
#include "buffers/RecordingBuffer.h"
Expand Down Expand Up @@ -156,6 +157,7 @@ class ATTR_DLL_LOCAL cPVRClientNextPVR : public kodi::addon::CInstancePVRClient
EPG m_epg;
MenuHook m_menuhook;
Recordings m_recordings;
GenreMapper m_genreMapper;
Timers m_timers;

void SetConnectionState(PVR_CONNECTION_STATE state, std::string displayMessage = "");
Expand Down
Loading

0 comments on commit 28924b8

Please sign in to comment.