summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schirrmacher <vdr.skinflatplus@schirrmacher.eu>2013-11-17 18:20:35 +0100
committerMartin Schirrmacher <vdr.skinflatplus@schirrmacher.eu>2013-11-17 18:20:35 +0100
commite96728cf26c71f8f76143057bb0594c101370303 (patch)
treed2efa5c302c8f128ff66c09a43c2fb54bda643f8
parenta0c769064b4f93f1dbe852f3cfe6150adc809deb (diff)
downloadskin-flatplus-e96728cf26c71f8f76143057bb0594c101370303.tar.gz
skin-flatplus-e96728cf26c71f8f76143057bb0594c101370303.tar.bz2
add option for additional info for epg and recording (lent from skinelchi)
-rw-r--r--HISTORY1
-rw-r--r--config.c5
-rw-r--r--config.h2
-rw-r--r--displaymenu.c314
-rw-r--r--po/de_DE.po41
-rw-r--r--setup.c5
6 files changed, 356 insertions, 12 deletions
diff --git a/HISTORY b/HISTORY
index f6284c75..7b65dbdf 100644
--- a/HISTORY
+++ b/HISTORY
@@ -14,6 +14,7 @@ VDR Plugin 'skinflatplus' Revision History
- [add] option menu content full size background
- [add] option to display resolution & aspect
- [add] default logo for channels without channel logo
+- [add] use icon from default theme if current theme does not have the icon
2013-23-09: Version 0.0.1
difference to skinflat
diff --git a/config.c b/config.c
index e95e922a..b3cdc46b 100644
--- a/config.c
+++ b/config.c
@@ -14,6 +14,9 @@ cFlatConfig::cFlatConfig(void) {
MenuContentFullSize = true;
ResolutionAspectShow = false;
+
+ RecordingAdditionalInfoShow = true;
+ EpgAdditionalInfoShow = true;
MenuItemPadding = 5;
marginOsdVer = 5;
@@ -145,6 +148,8 @@ bool cFlatConfig::SetupParse(const char *Name, const char *Value) {
else if (strcmp(Name, "TopBarFontSize") == 0) TopBarFontSize = atod(Value);
else if (strcmp(Name, "MenuContentFullSize") == 0) MenuContentFullSize = atoi(Value);
else if (strcmp(Name, "ResolutionAspectShow") == 0) ResolutionAspectShow = atoi(Value);
+ else if (strcmp(Name, "RecordingAdditionalInfoShow") == 0) RecordingAdditionalInfoShow = atoi(Value);
+ else if (strcmp(Name, "EpgAdditionalInfoShow") == 0) EpgAdditionalInfoShow = atoi(Value);
else return false;
return true;
}
diff --git a/config.h b/config.h
index 52f92705..9cff595e 100644
--- a/config.h
+++ b/config.h
@@ -156,4 +156,6 @@ class cFlatConfig
double TopBarFontSize;
int ResolutionAspectShow;
+ int RecordingAdditionalInfoShow;
+ int EpgAdditionalInfoShow;
};
diff --git a/displaymenu.c b/displaymenu.c
index 1e158ea9..e1a4b295 100644
--- a/displaymenu.c
+++ b/displaymenu.c
@@ -1,5 +1,11 @@
#include "displaymenu.h"
+#include <ctype.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
#include "symbols/720/Bvpssml.xpm"
#include "symbols/1080/Cnew.xpm"
#include "symbols/1080/Carrowturn.xpm"
@@ -15,6 +21,18 @@ cBitmap cFlatDisplayMenu::bmCClock(Cclock_xpm);
cBitmap cFlatDisplayMenu::bmCClocksml(Cclocksml_xpm);
cBitmap cFlatDisplayMenu::bmCVPS(Bvpssml_xpm);
+/* Possible values of the stream content descriptor according to ETSI EN 300 468 */
+enum stream_content
+{
+ sc_reserved = 0x00,
+ sc_video_MPEG2 = 0x01,
+ sc_audio_MP2 = 0x02, // MPEG 1 Layer 2 audio
+ sc_subtitle = 0x03,
+ sc_audio_AC3 = 0x04,
+ sc_video_H264_AVC = 0x05,
+ sc_audio_HEAAC = 0x06,
+};
+
cFlatDisplayMenu::cFlatDisplayMenu(void) {
CreateFullOsd();
TopBarCreate();
@@ -491,13 +509,6 @@ void cFlatDisplayMenu::SetEvent(const cEvent *Event) {
buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3 +
chHeight + Config.decorBorderMenuContentHeadSize*2 + Config.decorBorderMenuContentSize*2);
- bool contentScrollable = ContentWillItBeScrollable(cWidth, cHeight, Event->Description(), false);
- if( contentScrollable ) {
- cWidth -= scrollBarWidth;
- }
-
- ContentCreate(cLeft, cTop, cWidth, cHeight, false);
-
contentHeadPixmap->Fill(clrTransparent);
contentHeadPixmap->DrawRectangle(cRect(0, 0, menuWidth, fontHeight + fontSmlHeight*2 + marginItem*2), Theme.Color(clrScrollbarBg));
@@ -517,7 +528,89 @@ void cFlatDisplayMenu::SetEvent(const cEvent *Event) {
DecorBorderDraw(chLeft, chTop, chWidth, chHeight, Config.decorBorderMenuContentHeadSize, Config.decorBorderMenuContentHeadType,
Config.decorBorderMenuContentHeadFg, Config.decorBorderMenuContentHeadBg);
- ContentSet( Event->Description(), false, Theme.Color(clrMenuEventFontInfo), Theme.Color(clrMenuEventBg) );
+ // Description
+ ostringstream text;
+ if( !isempty(Event->Description()) ) {
+ text << Event->Description();
+ }
+
+ if( Config.EpgAdditionalInfoShow ) {
+ text << endl;
+ const cComponents *Components = Event->Components();
+ if (Components) {
+ ostringstream audio;
+ bool firstAudio = true;
+ const char *audio_type = NULL;
+ ostringstream subtitle;
+ bool firstSubtitle = true;
+ for (int i = 0; i < Components->NumComponents(); i++) {
+ const tComponent *p = Components->Component(i);
+ switch (p->stream) {
+ case sc_video_MPEG2:
+ if (p->description)
+ text << endl << tr("Video") << ": " << p->description << " (MPEG2)";
+ else
+ text << endl << tr("Video") << ": MPEG2";
+ break;
+ case sc_video_H264_AVC:
+ if (p->description)
+ text << endl << tr("Video") << ": " << p->description << " (H.264)";
+ else
+ text << endl << tr("Video") << ": H.264";
+ break;
+
+ case sc_audio_MP2:
+ case sc_audio_AC3:
+ case sc_audio_HEAAC:
+ if (firstAudio)
+ firstAudio = false;
+ else
+ audio << ", ";
+ switch (p->stream) {
+ case sc_audio_MP2:
+ // workaround for wrongfully used stream type X 02 05 for AC3
+ if (p->type == 5)
+ audio_type = "AC3";
+ else
+ audio_type = "MP2";
+ break;
+ case sc_audio_AC3:
+ audio_type = "AC3"; break;
+ case sc_audio_HEAAC:
+ audio_type = "HEAAC"; break;
+ }
+ if (p->description)
+ audio << p->description << " (" << audio_type << ", " << p->language << ")";
+ else
+ audio << p->language << " (" << audio_type << ")";
+ break;
+ case sc_subtitle:
+ if (firstSubtitle)
+ firstSubtitle = false;
+ else
+ subtitle << ", ";
+ if (p->description)
+ subtitle << p->description << " (" << p->language << ")";
+ else
+ subtitle << p->language;
+ break;
+ }
+ }
+ if (audio.str().length() > 0)
+ text << endl << tr("Audio") << ": "<< audio.str();
+ if (subtitle.str().length() > 0)
+ text << endl << tr("Subtitle") << ": "<< subtitle.str();
+ }
+ }
+
+ bool contentScrollable = ContentWillItBeScrollable(cWidth, cHeight, text.str().c_str(), false);
+ if( contentScrollable ) {
+ cWidth -= scrollBarWidth;
+ }
+
+ ContentCreate(cLeft, cTop, cWidth, cHeight, false);
+
+ ContentSet( text.str().c_str(), false, Theme.Color(clrMenuEventFontInfo), Theme.Color(clrMenuEventBg) );
if( ContentScrollable() )
DrawScrollbar(ContentScrollTotal(), ContentScrollOffset(), ContentVisibleLines(), contentTop - scrollBarTop, ContentGetHeight(), ContentScrollOffset() > 0, ContentScrollOffset() + ContentVisibleLines() < ContentScrollTotal());
@@ -529,6 +622,18 @@ void cFlatDisplayMenu::SetEvent(const cEvent *Event) {
Config.decorBorderMenuContentFg, Config.decorBorderMenuContentBg);
}
+// returns the string between start and end or an empty string if not found
+string xml_substring(string source, const char* str_start, const char* str_end) {
+ size_t start = source.find(str_start);
+ size_t end = source.find(str_end);
+
+ if (string::npos != start && string::npos != end) {
+ return (source.substr(start + strlen(str_start), end - start - strlen(str_start)));
+ }
+
+ return string();
+}
+
void cFlatDisplayMenu::SetRecording(const cRecording *Recording) {
if( !Recording )
return;
@@ -554,7 +659,196 @@ void cFlatDisplayMenu::SetRecording(const cRecording *Recording) {
buttonsHeight + Config.decorBorderButtonSize*2 + marginItem*3 +
chHeight + Config.decorBorderMenuContentHeadSize*2 + Config.decorBorderMenuContentSize*2);
- bool contentScrollable = ContentWillItBeScrollable(cWidth, cHeight, recInfo->Description(), false);
+ ostringstream text;
+ text.imbue(std::locale(""));
+
+ if (!isempty(recInfo->Description()))
+ text << recInfo->Description() << endl << endl;
+
+ // lent from skinelchi
+ if( Config.RecordingAdditionalInfoShow ) {
+ cChannel *channel = Channels.GetByChannelID(((cRecordingInfo *)recInfo)->ChannelID());
+ if (channel)
+ text << trVDR("Channel") << ": " << channel->Number() << " - " << channel->Name() << endl;
+
+ cMarks marks;
+ bool hasMarks = marks.Load(Recording->FileName(), Recording->FramesPerSecond(), Recording->IsPesRecording()) && marks.Count();
+ cIndexFile *index = new cIndexFile(Recording->FileName(), false, Recording->IsPesRecording());
+
+ int lastIndex = 0;
+
+ int cuttedLength = 0;
+ long cutinframe = 0;
+ unsigned long long recsize = 0;
+ unsigned long long recsizecutted = 0;
+ unsigned long long cutinoffset = 0;
+ unsigned long long filesize[100000];
+ filesize[0] = 0;
+
+ int i = 0;
+ int imax = 999;
+ struct stat filebuf;
+ cString filename;
+ int rc = 0;
+
+ do {
+ if (Recording->IsPesRecording())
+ filename = cString::sprintf("%s/%03d.vdr", Recording->FileName(), ++i);
+ else {
+ filename = cString::sprintf("%s/%05d.ts", Recording->FileName(), ++i);
+ imax = 99999;
+ }
+ rc=stat(filename, &filebuf);
+ if (rc == 0)
+ filesize[i] = filesize[i-1] + filebuf.st_size;
+ else {
+ if (ENOENT != errno) {
+ esyslog ("skinelchi: error determining file size of \"%s\" %d (%s)", (const char *)filename, errno, strerror(errno));
+ recsize = 0;
+ }
+ }
+ } while( i <= imax && !rc );
+ recsize = filesize[i-1];
+
+ if (hasMarks && index) {
+ uint16_t FileNumber;
+ off_t FileOffset;
+
+ bool cutin = true;
+ cMark *mark = marks.First();
+ while (mark) {
+ long position = mark->Position();
+ index->Get(position, &FileNumber, &FileOffset);
+ if (cutin) {
+ cutinframe = position;
+ cutin = false;
+ cutinoffset = filesize[FileNumber-1] + FileOffset;
+ } else {
+ cuttedLength += position - cutinframe;
+ cutin = true;
+ recsizecutted += filesize[FileNumber-1] + FileOffset - cutinoffset;
+ }
+ cMark *nextmark = marks.Next(mark);
+ mark = nextmark;
+ }
+ if( !cutin ) {
+ cuttedLength += index->Last() - cutinframe;
+ index->Get(index->Last() - 1, &FileNumber, &FileOffset);
+ recsizecutted += filesize[FileNumber-1] + FileOffset - cutinoffset;
+ }
+ }
+ if (index) {
+ lastIndex = index->Last();
+ text << tr("Length") << ": " << *IndexToHMSF(lastIndex, false, Recording->FramesPerSecond());
+ if (hasMarks)
+ text << " (" << tr("cutted") << ": " << *IndexToHMSF(cuttedLength, false, Recording->FramesPerSecond()) << ")";
+ text << endl;
+ }
+ delete index;
+
+ if (recsize > MEGABYTE(1023))
+ text << tr("Size") << ": " << fixed << setprecision(2) << (float)recsize / MEGABYTE(1024) << " GB";
+ else
+ text << tr("Size") << ": " << recsize / MEGABYTE(1) << " MB";
+ if( hasMarks )
+ if (recsize > MEGABYTE(1023))
+ text << " (" << tr("cutted") << ": " << fixed << setprecision(2) << (float)recsizecutted/MEGABYTE(1024) << " GB)";
+ else
+ text << " (" << tr("cutted") << ": " << recsizecutted/MEGABYTE(1) << " MB)";
+
+ text << endl << trVDR("Priority") << ": " << Recording->Priority() << ", " << trVDR("Lifetime") << ": " << Recording->Lifetime() << endl;
+
+ if( lastIndex ) {
+ text << tr("format") << ": " << (Recording->IsPesRecording() ? "PES" : "TS") << ", " << tr("bit rate") << ": ~ " << fixed << setprecision (2) << (float)recsize/lastIndex*Recording->FramesPerSecond()*8/MEGABYTE(1) << " MBit/s (Video + Audio)";
+ }
+ const cComponents *Components = recInfo->Components();
+ if( Components ) {
+ ostringstream audio;
+ bool firstAudio = true;
+ const char *audio_type = NULL;
+ ostringstream subtitle;
+ bool firstSubtitle = true;
+ for (int i = 0; i < Components->NumComponents(); i++) {
+ const tComponent *p = Components->Component(i);
+
+ switch (p->stream) {
+ case sc_video_MPEG2:
+ text << endl << tr("Video") << ": " << p->description << " (MPEG2)";
+ break;
+ case sc_video_H264_AVC:
+ text << endl << tr("Video") << ": " << p->description << " (H.264)";
+ break;
+ case sc_audio_MP2:
+ case sc_audio_AC3:
+ case sc_audio_HEAAC:
+ if (firstAudio)
+ firstAudio = false;
+ else
+ audio << ", ";
+ switch (p->stream) {
+ case sc_audio_MP2:
+ // workaround for wrongfully used stream type X 02 05 for AC3
+ if (p->type == 5)
+ audio_type = "AC3";
+ else
+ audio_type = "MP2";
+ break;
+ case sc_audio_AC3:
+ audio_type = "AC3"; break;
+ case sc_audio_HEAAC:
+ audio_type = "HEAAC"; break;
+ }
+ if (p->description)
+ audio << p->description << " (" << audio_type << ", " << p->language << ")";
+ else
+ audio << p->language << " (" << audio_type << ")";
+ break;
+ case sc_subtitle:
+ if (firstSubtitle)
+ firstSubtitle = false;
+ else
+ subtitle << ", ";
+ if (p->description)
+ subtitle << p->description << " (" << p->language << ")";
+ else
+ subtitle << p->language;
+ break;
+ }
+ }
+ if (audio.str().length() > 0)
+ text << endl << tr("Audio") << ": "<< audio.str();
+ if (subtitle.str().length() > 0)
+ text << endl << tr("Subtitle") << ": "<< subtitle.str();
+ }
+ if (recInfo->Aux()) {
+ string str_epgsearch = xml_substring(recInfo->Aux(), "<epgsearch>", "</epgsearch>");
+ string channel, searchtimer, pattern;
+
+ if (!str_epgsearch.empty()) {
+ channel = xml_substring(str_epgsearch, "<channel>", "</channel>");
+ searchtimer = xml_substring(str_epgsearch, "<searchtimer>", "</searchtimer>");
+ if (searchtimer.empty())
+ searchtimer = xml_substring(str_epgsearch, "<Search timer>", "</Search timer>");
+ }
+
+ string str_vdradmin = xml_substring(recInfo->Aux(), "<vdradmin-am>", "</vdradmin-am>");
+ if (!str_vdradmin.empty()) {
+ pattern = xml_substring(str_vdradmin, "<pattern>", "</pattern>");
+ }
+
+ if ((!channel.empty() && !searchtimer.empty()) || !pattern.empty()) {
+ text << endl << endl << tr("additional information") << ":" << endl;
+ if (!channel.empty() && !searchtimer.empty()) {
+ text << "EPGsearch: " << tr("channel") << ": " << channel << ", " << tr("search pattern") << ": " << searchtimer;
+ }
+ if (!pattern.empty()) {
+ text << "VDRadmin-AM: " << tr("search pattern") << ": " << pattern;
+ }
+ }
+ }
+ }
+
+ bool contentScrollable = ContentWillItBeScrollable(cWidth, cHeight, text.str().c_str(), false);
if( contentScrollable ) {
cWidth -= scrollBarWidth;
}
@@ -578,7 +872,7 @@ void cFlatDisplayMenu::SetRecording(const cRecording *Recording) {
DecorBorderDraw(chLeft, chTop, chWidth, chHeight, Config.decorBorderMenuContentHeadSize, Config.decorBorderMenuContentHeadType,
Config.decorBorderMenuContentHeadFg, Config.decorBorderMenuContentHeadBg);
- ContentSet( recInfo->Description(), false, Theme.Color(clrMenuRecFontInfo), Theme.Color(clrMenuRecBg) );
+ ContentSet( text.str().c_str(), false, Theme.Color(clrMenuRecFontInfo), Theme.Color(clrMenuRecBg) );
if( ContentScrollable() ) {
DrawScrollbar(ContentScrollTotal(), ContentScrollOffset(), ContentVisibleLines(), contentTop - scrollBarTop, ContentGetHeight(), ContentScrollOffset() > 0, ContentScrollOffset() + ContentVisibleLines() < ContentScrollTotal());
}
diff --git a/po/de_DE.po b/po/de_DE.po
index da1970e5..82c6c291 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: vdr-skinflat 0.0.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2013-11-17 16:20+0100\n"
+"POT-Creation-Date: 2013-11-17 18:16+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -24,6 +24,39 @@ msgstr "Plattennutzung"
msgid "free"
msgstr "frei"
+msgid "Video"
+msgstr "Video"
+
+msgid "Audio"
+msgstr "Audio"
+
+msgid "Subtitle"
+msgstr "Untertitel"
+
+msgid "Length"
+msgstr "Länge"
+
+msgid "cutted"
+msgstr "geschnitten"
+
+msgid "Size"
+msgstr "Größe"
+
+msgid "format"
+msgstr "Format"
+
+msgid "bit rate"
+msgstr "Bitrate"
+
+msgid "additional information"
+msgstr "Zusatzinformationen"
+
+msgid "channel"
+msgstr "Kanal"
+
+msgid "search pattern"
+msgstr "Suchmuster"
+
msgid "Volume"
msgstr "Lautstärke"
@@ -183,6 +216,12 @@ msgstr "Menüitem Abstand"
msgid "Menu content fullsize background"
msgstr "Menü Content voller Hintergrund"
+msgid "Show additional recording info"
+msgstr "Zeige Zusatzinfo bei Aufnahmen"
+
+msgid "Show additional EPG info"
+msgstr "Zeige Zusatzinfo bei EPG"
+
msgid "Menuitem border by theme?"
msgstr "Menüitem Rand vom Theme?"
diff --git a/setup.c b/setup.c
index cc687d57..ecce494b 100644
--- a/setup.c
+++ b/setup.c
@@ -135,11 +135,12 @@ void cFlatSetup::Store(void) {
SetupStore("MessageOffset", Config.MessageOffset);
SetupStore("MenuContentFullSize", Config.MenuContentFullSize);
SetupStore("ResolutionAspectShow", Config.ResolutionAspectShow);
+ SetupStore("RecordingAdditionalInfoShow", Config.RecordingAdditionalInfoShow);
+ SetupStore("EpgAdditionalInfoShow", Config.EpgAdditionalInfoShow);
Config.Init();
}
-
//------------------------------------------------------------------------------------------------------------------
cMenuSetupSubMenu::cMenuSetupSubMenu(const char* Title, cFlatConfig* data) : cOsdMenu(Title, 30) {
@@ -319,6 +320,8 @@ void cFlatSetupMenu::Setup(void) {
Add(new cMenuEditIntItem(tr("Menuitem padding"), &SetupConfig->MenuItemPadding));
Add(new cMenuEditBoolItem(tr("Menu content fullsize background"), &SetupConfig->MenuContentFullSize));
+ Add(new cMenuEditBoolItem(tr("Show additional recording info"), &SetupConfig->RecordingAdditionalInfoShow));
+ Add(new cMenuEditBoolItem(tr("Show additional EPG info"), &SetupConfig->EpgAdditionalInfoShow));
Add(new cMenuEditBoolItem(tr("Menuitem border by theme?"), &SetupConfig->decorBorderMenuItemByTheme));
if( SetupConfig->decorBorderMenuItemByTheme ) {