From 91d06d15a2a1e3fed3ab1484401e2328a5c5ec4e Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Sun, 24 Jan 2021 09:46:47 +0100 Subject: [PATCH 1/5] update version, extend history --- HISTORY | 4 ++++ skindesigner.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY b/HISTORY index e6b5e0f..7c074dc 100644 --- a/HISTORY +++ b/HISTORY @@ -465,3 +465,7 @@ Version 1.2.9 Version 1.2.10 - [pbiering] added tokens for recordings: isUHD, isRadio - [pbiering] added token for channels: isUHD + +Version 1.2.11 +- expose to displaymenurecordings: recchannelname, recchannelid, recchannelnumber +- add fallback to get name/id from 'info' in case channel is no longer in active channel list diff --git a/skindesigner.c b/skindesigner.c index 33f249b..7714879 100644 --- a/skindesigner.c +++ b/skindesigner.c @@ -21,7 +21,7 @@ #endif -static const char *VERSION = "1.2.9"; +static const char *VERSION = "1.2.11"; static const char *DESCRIPTION = trNOOP("Skin Designer"); class cPluginSkinDesigner : public cPlugin, public skindesignerapi::SkindesignerAPI { From 646fcad7d53c9622cfe3c9c8273f797f723a26f9 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Sun, 24 Jan 2021 12:11:23 +0100 Subject: [PATCH 2/5] - retrieve ChannelName from 'info' and fallback via ChannelID from active channel list (reverse mechanism) - remove exposing ChannelID (senseless as default 'info' is not containing it) --- HISTORY | 4 +- coreengine/definitions.h | 2 - coreengine/listelements.c | 52 +++++++++---------- coreengine/viewdetail.c | 29 ++++++----- coreengine/viewelementsdisplaymenu.c | 28 +++++----- .../xmlfiles/displaymenurecordings.xml | 2 - 6 files changed, 57 insertions(+), 60 deletions(-) diff --git a/HISTORY b/HISTORY index 7c074dc..7acd942 100644 --- a/HISTORY +++ b/HISTORY @@ -467,5 +467,5 @@ Version 1.2.10 - [pbiering] added token for channels: isUHD Version 1.2.11 -- expose to displaymenurecordings: recchannelname, recchannelid, recchannelnumber -- add fallback to get name/id from 'info' in case channel is no longer in active channel list +- expose to displaymenurecordings: recchannelname, recchannelid +- retrieve ChannelName from 'info' and fallback via ChannelID from active channel list diff --git a/coreengine/definitions.h b/coreengine/definitions.h index 57ce803..534f154 100644 --- a/coreengine/definitions.h +++ b/coreengine/definitions.h @@ -1168,7 +1168,6 @@ enum class eLeMenuRecordingsIT { hasposter, posterwidth, posterheight, - recchannelnumber, framesPerSecond, isHD, isUHD, @@ -1218,7 +1217,6 @@ enum class eCeMenuRecordingsIT { hasposter, posterwidth, posterheight, - recchannelnumber, framesPerSecond, isHD, isUHD, diff --git a/coreengine/listelements.c b/coreengine/listelements.c index 6f66097..6c500bf 100644 --- a/coreengine/listelements.c +++ b/coreengine/listelements.c @@ -1756,7 +1756,6 @@ void cLeMenuRecordings::SetTokenContainer(void) { tokenContainer->DefineIntToken("{isRadio}", (int)eLeMenuRecordingsIT::isRadio); tokenContainer->DefineStringToken("{recchannelname}", (int)eLeMenuRecordingsST::recchannelname); tokenContainer->DefineStringToken("{recchannelid}", (int)eLeMenuRecordingsST::recchannelid); - tokenContainer->DefineIntToken("{recchannelnumber}", (int)eLeMenuRecordingsIT::recchannelnumber); InheritTokenContainer(); } @@ -1856,21 +1855,21 @@ bool cLeMenuRecordings::Parse(bool forced) { delete[] recName; if (info) { + if (info->ChannelName() && (strlen(info->ChannelName()) > 0)) { + tokenContainer->AddStringToken((int)eLeMenuRecordingsST::recchannelname, info->ChannelName()); + tokenContainer->AddStringToken((int)eLeMenuRecordingsST::recchannelid, info->ChannelID().ToString()); + } else { #if defined (APIVERSNUM) && (APIVERSNUM >= 20301) - LOCK_CHANNELS_READ; - const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); #else - const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); + const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); #endif - if (channel) { - tokenContainer->AddStringToken((int)eLeMenuRecordingsST::recchannelname, channel->Name()); - tokenContainer->AddStringToken((int)eLeMenuRecordingsST::recchannelid, *channel->GetChannelID().ToString()); - tokenContainer->AddIntToken((int)eLeMenuRecordingsIT::recchannelnumber, channel->Number()); - } else { - // fallback to information provided in 'info' if channel is no longer found in active channels - tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelname, info->ChannelName()); - tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelid, info->ChannelID().ToString()); - } + if (channel) { + tokenContainer->AddStringToken((int)eLeMenuRecordingsST::recchannelname, channel->Name()); + tokenContainer->AddStringToken((int)eLeMenuRecordingsST::recchannelid, *channel->GetChannelID().ToString()); + } + } } cString recDate = event->GetDateString(); @@ -2031,7 +2030,6 @@ void cCeMenuRecordings::SetTokenContainer(void) { tokenContainer->DefineIntToken("{isRadio}", (int)eCeMenuRecordingsIT::isRadio); tokenContainer->DefineStringToken("{recchannelname}", (int)eCeMenuRecordingsST::recchannelname); tokenContainer->DefineStringToken("{recchannelid}", (int)eCeMenuRecordingsST::recchannelid); - tokenContainer->DefineIntToken("{recchannelnumber}", (int)eCeMenuRecordingsIT::recchannelnumber); InheritTokenContainer(); } @@ -2137,21 +2135,21 @@ bool cCeMenuRecordings::Parse(bool forced) { if (!event) return true; if (info) { -#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) - LOCK_CHANNELS_READ; - const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); -#else - const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); -#endif - if (channel) { - tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelname, channel->Name()); - tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelid, *channel->GetChannelID().ToString()); - tokenContainer->AddIntToken((int)eCeMenuRecordingsIT::recchannelnumber, channel->Number()); - } else { - // fallback to information provided in 'info' if channel is no longer found in active channels + if (info->ChannelName() && (strlen(info->ChannelName()) > 0)) { tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelname, info->ChannelName()); tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelid, info->ChannelID().ToString()); - } + } else { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); +#else + const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); +#endif + if (channel) { + tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelname, channel->Name()); + tokenContainer->AddStringToken((int)eCeMenuRecordingsST::recchannelid, *channel->GetChannelID().ToString()); + } + } } tokenContainer->AddStringToken((int)eCeMenuRecordingsST::epgname, info->Title() ? info->Title() : buffer.c_str()); diff --git a/coreengine/viewdetail.c b/coreengine/viewdetail.c index e4791c6..b63e9df 100644 --- a/coreengine/viewdetail.c +++ b/coreengine/viewdetail.c @@ -812,24 +812,25 @@ void cViewDetailRec::SetRecInfos(void) { const cRecordingInfo *info = recording->Info(); if (info) { -#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) - LOCK_CHANNELS_READ; - const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); -#else - const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); -#endif - if (channel) { - tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, channel->Name()); - tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, *channel->GetChannelID().ToString()); - tokenContainer->AddIntToken((int)eDmDetailedRecIT::recchannelnumber, channel->Number()); - } else { - // fallback to information provided in 'info' if channel is no longer found in active channels + if (info->ChannelName() && (strlen(info->ChannelName()) > 0)) { tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, info->ChannelName()); tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, info->ChannelID().ToString()); - } + tokenContainer->AddIntToken((int)eDmDetailedRecIT::recchannelnumber, 0); // cannot be provided, for backward compatibility only + } else { +#if defined (APIVERSNUM) && (APIVERSNUM >= 20301) + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); +#else + const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); +#endif + if (channel) { + tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, channel->Name()); + tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, *channel->GetChannelID().ToString()); + tokenContainer->AddIntToken((int)eDmDetailedRecIT::recchannelnumber, channel->Number()); + } + } } - if (index) { int nLastIndex = index->Last(); if (nLastIndex) { diff --git a/coreengine/viewelementsdisplaymenu.c b/coreengine/viewelementsdisplaymenu.c index dad279a..5887f26 100644 --- a/coreengine/viewelementsdisplaymenu.c +++ b/coreengine/viewelementsdisplaymenu.c @@ -1219,22 +1219,24 @@ bool cVeDmDetailheaderRec::Parse(bool forced) { tokenContainer->AddIntToken((int)eDmDetailedHeaderRecIT::isUHD, RecordingIsUHD(event)); // detect UHD from 'info' tokenContainer->AddIntToken((int)eDmDetailedHeaderRecIT::isRadio, RecordingIsRadio(event, info->FramesPerSecond())); // detect Radio from 'info' and FPS } + + if (info->ChannelName() && (strlen(info->ChannelName()) > 0)) { + tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, info->ChannelName()); + tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, info->ChannelID().ToString()); + tokenContainer->AddIntToken((int)eDmDetailedRecIT::recchannelnumber, 0); // cannot be provided, for backward compatibility only + } else { #if defined (APIVERSNUM) && (APIVERSNUM >= 20301) - LOCK_CHANNELS_READ; - const cChannels* channels = Channels; + LOCK_CHANNELS_READ; + const cChannel *channel = Channels->GetByChannelID(info->ChannelID()); #else - cChannels* channels = &Channels; + const cChannel *channel = Channels.GetByChannelID(info->ChannelID()); #endif - const cChannel *channel = channels->GetByChannelID(info->ChannelID()); - if (channel) { - tokenContainer->AddStringToken((int)eDmDetailedHeaderRecST::recchannelname, channel->Name()); - tokenContainer->AddStringToken((int)eDmDetailedHeaderRecST::recchannelid, *channel->GetChannelID().ToString()); - tokenContainer->AddIntToken((int)eDmDetailedHeaderRecIT::recchannelnumber, channel->Number()); - } else { - // fallback to information provided in 'info' if channel is no longer found in active channels - tokenContainer->AddStringToken((int)eDmDetailedHeaderRecST::recchannelname, info->ChannelName()); - tokenContainer->AddStringToken((int)eDmDetailedHeaderRecST::recchannelid, info->ChannelID().ToString()); - } + if (channel) { + tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, channel->Name()); + tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, *channel->GetChannelID().ToString()); + tokenContainer->AddIntToken((int)eDmDetailedRecIT::recchannelnumber, channel->Number()); + } + } } string recImage = ""; string path = recording->FileName() ? recording->FileName() : ""; diff --git a/skinskeleton/xmlfiles/displaymenurecordings.xml b/skinskeleton/xmlfiles/displaymenurecordings.xml index 9bde817..e46fd12 100644 --- a/skinskeleton/xmlfiles/displaymenurecordings.xml +++ b/skinskeleton/xmlfiles/displaymenurecordings.xml @@ -35,7 +35,6 @@ {posterpath} absolute path of scraped poster {recchannelname} name of channel from which was recorded {recchannelid} id of channel from which was recorded - {recchannelnumber} number of channel from which was recorded {framesPerSecond} frames per second (from EPG info) {isHD} true if recording is HD/UHD (from EPG info) {isUHD} true if recording is UHD (from EPG info) @@ -81,7 +80,6 @@ {bannerpath} absolute path of scraped banner {recchannelname} name of channel from which was recorded {recchannelid} id of channel from which was recorded - {recchannelnumber} number of channel from which was recorded {framesPerSecond} frames per second (from EPG info) {isHD} true if recording is HD/UHD (from EPG info) {isUHD} true if recording is UHD (from EPG info) From 5e269ecaaa5c935a36190206b6decc68d6d46e6d Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Tue, 2 Feb 2021 22:12:35 +0100 Subject: [PATCH 3/5] mark deprecated functions --- extensions/imageloader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/imageloader.c b/extensions/imageloader.c index bd2d268..88ecb14 100644 --- a/extensions/imageloader.c +++ b/extensions/imageloader.c @@ -178,14 +178,14 @@ cImageImporterSVG::cImageImporterSVG() { cImageImporterSVG::~cImageImporterSVG() { if (handle) { - rsvg_handle_close(handle, NULL); + rsvg_handle_close(handle, NULL); // deprecated since version 2.46 g_object_unref(handle); } } bool cImageImporterSVG::LoadImage(const char *path) { if (handle) { - rsvg_handle_close(handle, NULL); + rsvg_handle_close(handle, NULL); // deprecated since version 2.46 g_object_unref(handle); } From 68d4d6acae8c4cd061305daa05b794265e9cc114 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Wed, 3 Feb 2021 07:10:24 +0100 Subject: [PATCH 4/5] SVDRP: do not reload in case plugin is not fully initialized (results in VDR crash) SVDRP: respond with proper error message in case of OSD is active or parsing error --- HISTORY | 2 ++ designer.c | 8 ++++++-- designer.h | 4 +++- skindesigner.c | 23 ++++++++++++++++++++--- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/HISTORY b/HISTORY index 5b33437..c849765 100644 --- a/HISTORY +++ b/HISTORY @@ -471,3 +471,5 @@ Version 1.2.10 Version 1.2.10+ - [pbiering] align displayed tuner number (0,1,2 -> 1,2,3) +- [pbiering] SVDRP: do not reload in case plugin is not fully initialized (results in VDR crash) +- [pbiering] SVDRP: respond with proper error message in case of OSD is active or parsing error diff --git a/designer.c b/designer.c index c0dd20a..af2df60 100644 --- a/designer.c +++ b/designer.c @@ -3,6 +3,7 @@ cSkinDesigner::cSkinDesigner(string skin, cTheme *theme) : cSkin(skin.c_str(), theme) { init = true; + initialized = false; this->skin = skin; backupSkin = NULL; @@ -106,11 +107,11 @@ cSkinDisplayMessage *cSkinDesigner::DisplayMessage(void) { return displayMessage; } -void cSkinDesigner::Reload(void) { +int cSkinDesigner::Reload(void) { dsyslog("skindesigner: forcing full reload of templates"); if (cOsd::IsOpen()) { esyslog("skindesigner: OSD is open, close first!"); - return; + return 2; } cStopWatch watch; @@ -120,11 +121,13 @@ void cSkinDesigner::Reload(void) { if (!backupSkin) backupSkin = new cSkinLCARS(); useBackupSkin = true; + return 1; } else { CacheViews(); useBackupSkin = false; watch.Stop("templates reloaded and cache created"); } + return 0; } void cSkinDesigner::ListAvailableFonts(void) { @@ -218,6 +221,7 @@ void cSkinDesigner::Init(void) { watch.Stop("templates loaded and caches created"); } init = false; + initialized = true; } else if (config.OsdFontsChanged()) { diff --git a/designer.h b/designer.h index 8870392..c58c974 100644 --- a/designer.h +++ b/designer.h @@ -22,6 +22,7 @@ class cSkinDesigner; class cSkinDesigner : public cSkin { private: bool init; + bool initialized; string skin; cSkinLCARS *backupSkin; bool useBackupSkin; @@ -51,7 +52,8 @@ public: virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks); virtual cSkinDisplayMessage *DisplayMessage(void); void ActivateBackupSkin(void) { useBackupSkin = true; }; - void Reload(void); + int Reload(void); + bool Initialized(void) { return initialized; }; void ListAvailableFonts(void); bool SetCustomIntToken(string option); bool SetCustomStringToken(string option); diff --git a/skindesigner.c b/skindesigner.c index c3f3e66..71eb363 100644 --- a/skindesigner.c +++ b/skindesigner.c @@ -241,6 +241,7 @@ cString cPluginSkinDesigner::SVDRPCommand(const char *Command, const char *Optio cSkinDesigner *activeSkin = NULL; cSkinDesigner *availableSkin = NULL; config.InitSkinRefsIterator(); + int result = 0; while (availableSkin = config.GetNextSkinRef()) { string activeSkinName = Setup.OSDSkin; string currentSkinName = availableSkin->Description(); @@ -256,6 +257,10 @@ cString cPluginSkinDesigner::SVDRPCommand(const char *Command, const char *Optio } if (strcasecmp(Command, "RELD") == 0) { + if (!activeSkin->Initialized()) { + ReplyCode = 503; + return "SKINDESIGNER reload of templates and caches failed: initialization not finished."; + } config.ClearSkinSetups(); config.InitSkinIterator(); string skin = ""; @@ -264,9 +269,21 @@ cString cPluginSkinDesigner::SVDRPCommand(const char *Command, const char *Optio } config.TranslateSetup(); config.SetSkinSetupParameters(); - activeSkin->Reload(); - ReplyCode = 250; - return "SKINDESIGNER reload of templates and caches forced."; + result = activeSkin->Reload(); + switch (result) { + case 0: + ReplyCode = 250; + return "SKINDESIGNER reload of templates and caches forced."; + case 1: + ReplyCode = 501; + return "SKINDESIGNER reload of templates and caches failed: error during loading - using LCARS as backup."; + case 2: + ReplyCode = 503; + return "SKINDESIGNER reload of templates and caches failed: OSD is open, close first."; + default: + ReplyCode = 500; + return "SKINDESIGNER reload of templates and caches failed: unknown reason (check code)."; + }; } else if (strcasecmp(Command, "DLIC") == 0) { if (imgCache) delete imgCache; From b044321b1f7626aab43b9297c8d594c8f1749ca6 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Wed, 3 Feb 2021 07:13:41 +0100 Subject: [PATCH 5/5] also be initialized in case of backup skin is active --- designer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/designer.c b/designer.c index af2df60..974a5ef 100644 --- a/designer.c +++ b/designer.c @@ -216,6 +216,7 @@ void cSkinDesigner::Init(void) { esyslog("skindesigner: error during loading of templates - using LCARS as backup"); backupSkin = new cSkinLCARS(); useBackupSkin = true; + initialized = true; } else { CacheViews(); watch.Stop("templates loaded and caches created");