mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
- Fixed resetting the file size when regenerating the index file. - The new function cDevice::PatPmtParser() can be used in derived devices to access the PAT/PMT of the currently replayed material. - Updated the Italian OSD texts (thanks to Diego Pierotto). - The PCR pid in generated PMTs is now set to 0x1FFF ("no PCR pid") in cPatPmtGenerator::GeneratePmt(), because VDR doesn't record the PCR pid. - Updated the Estonian OSD texts (thanks to Arthur Konovalov). - The 'sky' plugin is no longer part of the VDR source. - Improved SPU handling on devices with limited OSD capabilities (thanks to Matthieu Castet). - Several code modifications to avoid compiler warnings (thanks to Winfried Köhler). - Added stream type 11172 AUDIO to cPatPmtParser::ParsePmt() (thanks to Johann Friedrichs). - Removed debug output of '-' from cTransfer::Receive(). - Added defines for large files to the 'newplugin' script (reported by Udo Richter). - Removed the workaround for short channel names of "Kabel Deutschland", because apparently they now have their data according to the DVB standard (thanks to Johann Friedrichs). - Some fixes to dvbspu.[hc] (thanks to Johann Friedrichs). - Fixed a busy loop when moving editing marks (thanks to Johann Friedrichs). - Updated sources.conf (thanks to Derek Kelly). - Modified cCharSetConv so that it can be used to convert from "whatever VDR uses" to a given code (thanks to Joachim Wilke). - Channel names containing commas are now handled correctly in channels.conf. If a channel's short name contains a comma, it is replaced with a '.'. - cDevice now logs the device number when a new device is created. - Fixed handling STREAMTYPE_11172_AUDIO in cPatPmtParser::ParsePmt(). - cParsePatPmt now has functions to retrieve the audio, dolby and subtitle pids. - cPatFilter::Process() now only stores CA descriptors for video and audio pids (thanks to Francesco Saverio Schiavarelli for reporting a problem with channels that have some encrypted components that VDR doesn't use). - cDevice::AddPid() now stores the stream type of the given pid (thanks to Andreas Regel). - Added cFont::FontName() and cFont::Size() (thanks to Andreas Regel). - cPatPmtParser now also stores the audio stream types. - The support for full featured DVB cards of the TT/FuSi design has been moved into the new plugin 'dvbsddevice'. On systems that use such a card as their primary device, this plugin now needs to be loaded when running VDR in order to view live or recorded video. If the plugin is not loaded, the card will be treated like a budget DVB card, and there will be no OSD or viewing capability. - Fixed handling the "CA PMT" generation (revised a change not mentioned in version 1.7.9's changes, which caused a malfunction with Conax and Viaccess CAMs). - Fixed stopping subtitle display when switching the primary device (thanks to Anssi Hannula). IMPORTANT NOTE TO PLUGIN AUTHORS: a plugin that implements a derived cDevice class that can replay video must now call the MakePrimaryDevice() function of its base class. - Fixed compiler warnings "format not a string literal and no format arguments" in some syslog calls (thanks to Rolf Ahrenberg). - The new command line options --edit and --genindex can be used to edit a recording or generate its index without actually starting the entire VDR (based on a patch from Helmut Auer). - Improved the description of the transponder parameters in vdr.5 (thanks to Winfried Köhler). - Avoiding setting the video stream type to 2 if the vpid is 0 (problem reported by Arthur Konovalov). - Implemented handling the "Content Descriptor" (based on a patch from Rolf Ahrenberg). The 'classic', 'sttng' and 'curses' skins display the textual representation of the content descriptors as "genre". The epg.data file stores the genre using the tag character 'G'. - Implemented handling the "Parental Rating Descriptor" (based on a patch from Rolf Ahrenberg). The 'classic', 'sttng' and 'curses' skins display the parental rating (if given) in their event displays. The epg.data file stores the parental rating using the tag character 'R'. IMPORTANT NOTE: if VDR doesn't display a parental rating, this does not necessarily mean that the given programme is suitable for all audiences! - Rearranged cEvent members to minimize memory waste. - After a CLRE command, no further EPG processing is now done for 10 seconds, so that data sent with subsequent PUTE commands doesn't interfere with data from the broadcasters (suggested by Helmut Auer). - Added support for DVB cards with multiple fontends. Note that this only works for DVB cards where each frontend can be used independently of all the others on the same adapter. - Fixed plugin arguments corruption with glibc 2.11 on x86_64 (thanks to Anssi Hannula).
783 lines
28 KiB
C
783 lines
28 KiB
C
/*
|
|
* skinclassic.c: The 'classic' VDR skin
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* $Id: skinclassic.c 2.3 2010/01/03 14:55:10 kls Exp $
|
|
*/
|
|
|
|
#include "skinclassic.h"
|
|
#include "font.h"
|
|
#include "i18n.h"
|
|
#include "osd.h"
|
|
#include "themes.h"
|
|
|
|
#define ScrollWidth 5
|
|
|
|
static cTheme Theme;
|
|
|
|
THEME_CLR(Theme, clrBackground, clrGray50);
|
|
THEME_CLR(Theme, clrButtonRedFg, clrWhite);
|
|
THEME_CLR(Theme, clrButtonRedBg, clrRed);
|
|
THEME_CLR(Theme, clrButtonGreenFg, clrBlack);
|
|
THEME_CLR(Theme, clrButtonGreenBg, clrGreen);
|
|
THEME_CLR(Theme, clrButtonYellowFg, clrBlack);
|
|
THEME_CLR(Theme, clrButtonYellowBg, clrYellow);
|
|
THEME_CLR(Theme, clrButtonBlueFg, clrWhite);
|
|
THEME_CLR(Theme, clrButtonBlueBg, clrBlue);
|
|
THEME_CLR(Theme, clrMessageStatusFg, clrBlack);
|
|
THEME_CLR(Theme, clrMessageStatusBg, clrCyan);
|
|
THEME_CLR(Theme, clrMessageInfoFg, clrBlack);
|
|
THEME_CLR(Theme, clrMessageInfoBg, clrGreen);
|
|
THEME_CLR(Theme, clrMessageWarningFg, clrBlack);
|
|
THEME_CLR(Theme, clrMessageWarningBg, clrYellow);
|
|
THEME_CLR(Theme, clrMessageErrorFg, clrWhite);
|
|
THEME_CLR(Theme, clrMessageErrorBg, clrRed);
|
|
THEME_CLR(Theme, clrVolumePrompt, clrGreen);
|
|
THEME_CLR(Theme, clrVolumeBarUpper, clrWhite);
|
|
THEME_CLR(Theme, clrVolumeBarLower, clrGreen);
|
|
THEME_CLR(Theme, clrChannelName, clrWhite);
|
|
THEME_CLR(Theme, clrChannelDate, clrWhite);
|
|
THEME_CLR(Theme, clrChannelEpgTimeFg, clrWhite);
|
|
THEME_CLR(Theme, clrChannelEpgTimeBg, clrRed);
|
|
THEME_CLR(Theme, clrChannelEpgTitle, clrCyan);
|
|
THEME_CLR(Theme, clrChannelEpgShortText, clrYellow);
|
|
THEME_CLR(Theme, clrMenuTitleFg, clrBlack);
|
|
THEME_CLR(Theme, clrMenuTitleBg, clrCyan);
|
|
THEME_CLR(Theme, clrMenuDate, clrBlack);
|
|
THEME_CLR(Theme, clrMenuItemCurrentFg, clrBlack);
|
|
THEME_CLR(Theme, clrMenuItemCurrentBg, clrCyan);
|
|
THEME_CLR(Theme, clrMenuItemSelectable, clrWhite);
|
|
THEME_CLR(Theme, clrMenuItemNonSelectable, clrCyan);
|
|
THEME_CLR(Theme, clrMenuEventTime, clrWhite);
|
|
THEME_CLR(Theme, clrMenuEventVpsFg, clrBlack);
|
|
THEME_CLR(Theme, clrMenuEventVpsBg, clrWhite);
|
|
THEME_CLR(Theme, clrMenuEventTitle, clrCyan);
|
|
THEME_CLR(Theme, clrMenuEventShortText, clrWhite);
|
|
THEME_CLR(Theme, clrMenuEventDescription, clrCyan);
|
|
THEME_CLR(Theme, clrMenuScrollbarTotal, clrWhite);
|
|
THEME_CLR(Theme, clrMenuScrollbarShown, clrCyan);
|
|
THEME_CLR(Theme, clrMenuText, clrWhite);
|
|
THEME_CLR(Theme, clrReplayTitle, clrWhite);
|
|
THEME_CLR(Theme, clrReplayCurrent, clrWhite);
|
|
THEME_CLR(Theme, clrReplayTotal, clrWhite);
|
|
THEME_CLR(Theme, clrReplayModeJump, clrWhite);
|
|
THEME_CLR(Theme, clrReplayProgressSeen, clrGreen);
|
|
THEME_CLR(Theme, clrReplayProgressRest, clrWhite);
|
|
THEME_CLR(Theme, clrReplayProgressSelected, clrRed);
|
|
THEME_CLR(Theme, clrReplayProgressMark, clrBlack);
|
|
THEME_CLR(Theme, clrReplayProgressCurrent, clrRed);
|
|
|
|
// --- cSkinClassicDisplayChannel --------------------------------------------
|
|
|
|
class cSkinClassicDisplayChannel : public cSkinDisplayChannel {
|
|
private:
|
|
cOsd *osd;
|
|
int lineHeight;
|
|
int timeWidth;
|
|
bool message;
|
|
cString lastDate;
|
|
public:
|
|
cSkinClassicDisplayChannel(bool WithInfo);
|
|
virtual ~cSkinClassicDisplayChannel();
|
|
virtual void SetChannel(const cChannel *Channel, int Number);
|
|
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
|
|
virtual void SetMessage(eMessageType Type, const char *Text);
|
|
virtual void Flush(void);
|
|
};
|
|
|
|
cSkinClassicDisplayChannel::cSkinClassicDisplayChannel(bool WithInfo)
|
|
{
|
|
int Lines = WithInfo ? 5 : 1;
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
lineHeight = font->Height();
|
|
message = false;
|
|
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + (Setup.ChannelInfoPos ? 0 : cOsd::OsdHeight() - Lines * lineHeight));
|
|
timeWidth = font->Width("00:00") + 4;
|
|
tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, Lines * lineHeight - 1, 8 } };
|
|
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, Lines * lineHeight - 1, 4 } };
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
}
|
|
osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrBackground));
|
|
}
|
|
|
|
cSkinClassicDisplayChannel::~cSkinClassicDisplayChannel()
|
|
{
|
|
delete osd;
|
|
}
|
|
|
|
void cSkinClassicDisplayChannel::SetChannel(const cChannel *Channel, int Number)
|
|
{
|
|
osd->DrawRectangle(0, 0, osd->Width() - 1, lineHeight - 1, Theme.Color(clrBackground));
|
|
osd->DrawText(2, 0, ChannelString(Channel, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
|
|
lastDate = NULL;
|
|
}
|
|
|
|
void cSkinClassicDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
|
|
{
|
|
osd->DrawRectangle(0, lineHeight, timeWidth - 1, osd->Height(), Theme.Color(clrChannelEpgTimeBg));
|
|
osd->DrawRectangle(timeWidth, lineHeight, osd->Width() - 1, osd->Height(), Theme.Color(clrBackground));
|
|
for (int i = 0; i < 2; i++) {
|
|
const cEvent *e = !i ? Present : Following;
|
|
if (e) {
|
|
osd->DrawText( 2, (2 * i + 1) * lineHeight, e->GetTimeString(), Theme.Color(clrChannelEpgTimeFg), Theme.Color(clrChannelEpgTimeBg), cFont::GetFont(fontOsd));
|
|
osd->DrawText(timeWidth + 10, (2 * i + 1) * lineHeight, e->Title(), Theme.Color(clrChannelEpgTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
|
|
osd->DrawText(timeWidth + 10, (2 * i + 2) * lineHeight, e->ShortText(), Theme.Color(clrChannelEpgShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml));
|
|
}
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayChannel::SetMessage(eMessageType Type, const char *Text)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
if (Text) {
|
|
osd->SaveRegion(0, 0, osd->Width() - 1, lineHeight - 1);
|
|
osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, osd->Width(), 0, taCenter);
|
|
message = true;
|
|
}
|
|
else {
|
|
osd->RestoreRegion();
|
|
message = false;
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayChannel::Flush(void)
|
|
{
|
|
if (!message) {
|
|
cString date = DayDateTime();
|
|
if (!*lastDate || strcmp(date, lastDate)) {
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
int w = font->Width(date);
|
|
osd->DrawText(osd->Width() - w - 2, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml), w);
|
|
lastDate = date;
|
|
}
|
|
}
|
|
osd->Flush();
|
|
}
|
|
|
|
// --- cSkinClassicDisplayMenu -----------------------------------------------
|
|
|
|
class cSkinClassicDisplayMenu : public cSkinDisplayMenu {
|
|
private:
|
|
cOsd *osd;
|
|
int x0, x1, x2, x3;
|
|
int y0, y1, y2, y3, y4, y5;
|
|
int lineHeight;
|
|
int dateWidth;
|
|
cString lastDate;
|
|
void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
|
|
void SetTextScrollbar(void);
|
|
public:
|
|
cSkinClassicDisplayMenu(void);
|
|
virtual ~cSkinClassicDisplayMenu();
|
|
virtual void Scroll(bool Up, bool Page);
|
|
virtual int MaxItems(void);
|
|
virtual void Clear(void);
|
|
virtual void SetTitle(const char *Title);
|
|
virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
|
virtual void SetMessage(eMessageType Type, const char *Text);
|
|
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
|
|
virtual void SetScrollbar(int Total, int Offset);
|
|
virtual void SetEvent(const cEvent *Event);
|
|
virtual void SetRecording(const cRecording *Recording);
|
|
virtual void SetText(const char *Text, bool FixedFont);
|
|
virtual int GetTextAreaWidth(void) const;
|
|
virtual const cFont *GetTextAreaFont(bool FixedFont) const;
|
|
virtual void Flush(void);
|
|
};
|
|
|
|
cSkinClassicDisplayMenu::cSkinClassicDisplayMenu(void)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
lineHeight = font->Height();
|
|
dateWidth = 0;
|
|
x0 = 0;
|
|
x1 = x0 + 10;
|
|
x3 = cOsd::OsdWidth();
|
|
x2 = x3 - 2 * ScrollWidth;
|
|
y0 = 0;
|
|
y1 = lineHeight;
|
|
y2 = y1 + lineHeight;
|
|
y5 = cOsd::OsdHeight();
|
|
y4 = y5 - lineHeight;
|
|
y3 = y4 - lineHeight;
|
|
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
|
|
tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 8 } };
|
|
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 4 } };
|
|
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { x0, y0, x3 - 1, y1 - 1, 2 },
|
|
{ x0, y1, x3 - 1, y3 - 1, 2 },
|
|
{ x0, y3, x3 - 1, y5 - 1, 4 }
|
|
};
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
}
|
|
}
|
|
osd->DrawRectangle(x0, y0, x3 - 1, y5 - 1, Theme.Color(clrBackground));
|
|
}
|
|
|
|
cSkinClassicDisplayMenu::~cSkinClassicDisplayMenu()
|
|
{
|
|
delete osd;
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown)
|
|
{
|
|
if (Total > 0 && Total > Shown) {
|
|
int yt = Top;
|
|
int yb = yt + Height;
|
|
int st = yt;
|
|
int sb = yb;
|
|
int th = max(int((sb - st) * double(Shown) / Total + 0.5), ScrollWidth);
|
|
int tt = min(int(st + (sb - st) * double(Offset) / Total + 0.5), sb - th);
|
|
int tb = min(tt + th, sb);
|
|
int xl = x3 - ScrollWidth;
|
|
osd->DrawRectangle(xl, st, x3 - 1, sb - 1, Theme.Color(clrMenuScrollbarTotal));
|
|
osd->DrawRectangle(xl, tt, x3 - 1, tb - 1, Theme.Color(clrMenuScrollbarShown));
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetTextScrollbar(void)
|
|
{
|
|
if (textScroller.CanScroll())
|
|
DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.Top(), textScroller.Height(), textScroller.CanScrollUp(), textScroller.CanScrollDown());
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::Scroll(bool Up, bool Page)
|
|
{
|
|
cSkinDisplayMenu::Scroll(Up, Page);
|
|
SetTextScrollbar();
|
|
}
|
|
|
|
int cSkinClassicDisplayMenu::MaxItems(void)
|
|
{
|
|
return (y3 - y2) / lineHeight;
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::Clear(void)
|
|
{
|
|
textScroller.Reset();
|
|
osd->DrawRectangle(x0, y1, x3 - 1, y4 - 1, Theme.Color(clrBackground));
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetTitle(const char *Title)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x3 - x0 - dateWidth);
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int w = x3 - x0;
|
|
int t0 = x0;
|
|
int t1 = x0 + w / 4;
|
|
int t2 = x0 + w / 2;
|
|
int t3 = x3 - w / 4;
|
|
int t4 = x3;
|
|
osd->DrawText(t0, y4, Red, Theme.Color(clrButtonRedFg), Red ? Theme.Color(clrButtonRedBg) : Theme.Color(clrBackground), font, t1 - t0, 0, taCenter);
|
|
osd->DrawText(t1, y4, Green, Theme.Color(clrButtonGreenFg), Green ? Theme.Color(clrButtonGreenBg) : Theme.Color(clrBackground), font, t2 - t1, 0, taCenter);
|
|
osd->DrawText(t2, y4, Yellow, Theme.Color(clrButtonYellowFg), Yellow ? Theme.Color(clrButtonYellowBg) : Theme.Color(clrBackground), font, t3 - t2, 0, taCenter);
|
|
osd->DrawText(t3, y4, Blue, Theme.Color(clrButtonBlueFg), Blue ? Theme.Color(clrButtonBlueBg) : Theme.Color(clrBackground), font, t4 - t3, 0, taCenter);
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetMessage(eMessageType Type, const char *Text)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
if (Text)
|
|
osd->DrawText(x0, y3, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x3 - x0, 0, taCenter);
|
|
else
|
|
osd->DrawRectangle(x0, y3, x3 - 1, y4 - 1, Theme.Color(clrBackground));
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
|
|
{
|
|
int y = y2 + Index * lineHeight;
|
|
tColor ColorFg, ColorBg;
|
|
if (Current) {
|
|
ColorFg = Theme.Color(clrMenuItemCurrentFg);
|
|
ColorBg = Theme.Color(clrMenuItemCurrentBg);
|
|
}
|
|
else {
|
|
ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
|
|
ColorBg = Theme.Color(clrBackground);
|
|
}
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
for (int i = 0; i < MaxTabs; i++) {
|
|
const char *s = GetTabbedText(Text, i);
|
|
if (s) {
|
|
int xt = x0 + Tab(i);
|
|
osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt);
|
|
}
|
|
if (!Tab(i + 1))
|
|
break;
|
|
}
|
|
SetEditableWidth(x2 - x0 - Tab(1));
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetScrollbar(int Total, int Offset)
|
|
{
|
|
DrawScrollbar(Total, Offset, MaxItems(), y2, MaxItems() * lineHeight, Offset > 0, Offset + MaxItems() < Total);
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
|
|
{
|
|
if (!Event)
|
|
return;
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int y = y2;
|
|
cTextScroller ts;
|
|
char t[32];
|
|
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
|
|
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
|
|
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
int w = font->Width(buffer);
|
|
osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
|
|
}
|
|
y += ts.Height();
|
|
if (Event->ParentalRating()) {
|
|
cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
int w = font->Width(buffer);
|
|
osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
|
|
}
|
|
y += font->Height();
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, Event->Title(), font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
if (!isempty(Event->ShortText())) {
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, Event->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
}
|
|
for (int i = 0; Event->Contents(i); i++) {
|
|
const char *s = Event->ContentToString(Event->Contents(i));
|
|
if (!isempty(s)) {
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, s, font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
}
|
|
}
|
|
y += font->Height();
|
|
if (!isempty(Event->Description())) {
|
|
textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Event->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
|
|
SetTextScrollbar();
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetRecording(const cRecording *Recording)
|
|
{
|
|
if (!Recording)
|
|
return;
|
|
const cRecordingInfo *Info = Recording->Info();
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int y = y2;
|
|
cTextScroller ts;
|
|
char t[32];
|
|
snprintf(t, sizeof(t), "%s %s", *DateString(Recording->start), *TimeString(Recording->start));
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
if (Info->GetEvent()->ParentalRating()) {
|
|
cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
int w = font->Width(buffer);
|
|
osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
|
|
}
|
|
y += font->Height();
|
|
const char *Title = Info->Title();
|
|
if (isempty(Title))
|
|
Title = Recording->Name();
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, Title, font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
if (!isempty(Info->ShortText())) {
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, Info->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
}
|
|
for (int i = 0; Info->GetEvent()->Contents(i); i++) {
|
|
const char *s = Info->GetEvent()->ContentToString(Info->GetEvent()->Contents(i));
|
|
if (!isempty(s)) {
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
ts.Set(osd, x1, y, x2 - x1, y3 - y, s, font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
|
y += ts.Height();
|
|
}
|
|
}
|
|
y += font->Height();
|
|
if (!isempty(Info->Description())) {
|
|
textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Info->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
|
|
SetTextScrollbar();
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
|
|
{
|
|
textScroller.Set(osd, x1, y2, GetTextAreaWidth(), y3 - y2, Text, GetTextAreaFont(FixedFont), Theme.Color(clrMenuText), Theme.Color(clrBackground));
|
|
SetTextScrollbar();
|
|
}
|
|
|
|
int cSkinClassicDisplayMenu::GetTextAreaWidth(void) const
|
|
{
|
|
return x2 - x1;
|
|
}
|
|
|
|
const cFont *cSkinClassicDisplayMenu::GetTextAreaFont(bool FixedFont) const
|
|
{
|
|
return cFont::GetFont(FixedFont ? fontFix : fontOsd);
|
|
}
|
|
|
|
void cSkinClassicDisplayMenu::Flush(void)
|
|
{
|
|
cString date = DayDateTime();
|
|
if (!*lastDate || strcmp(date, lastDate)) {
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int w = font->Width(date);
|
|
osd->DrawText(x3 - w - 2, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font, w);
|
|
lastDate = date;
|
|
dateWidth = max(w + 2, dateWidth);
|
|
}
|
|
osd->Flush();
|
|
}
|
|
|
|
// --- cSkinClassicDisplayReplay ---------------------------------------------
|
|
|
|
class cSkinClassicDisplayReplay : public cSkinDisplayReplay {
|
|
private:
|
|
cOsd *osd;
|
|
int x0, x1;
|
|
int y0, y1, y2, y3;
|
|
int lastCurrentWidth;
|
|
public:
|
|
cSkinClassicDisplayReplay(bool ModeOnly);
|
|
virtual ~cSkinClassicDisplayReplay();
|
|
virtual void SetTitle(const char *Title);
|
|
virtual void SetMode(bool Play, bool Forward, int Speed);
|
|
virtual void SetProgress(int Current, int Total);
|
|
virtual void SetCurrent(const char *Current);
|
|
virtual void SetTotal(const char *Total);
|
|
virtual void SetJump(const char *Jump);
|
|
virtual void SetMessage(eMessageType Type, const char *Text);
|
|
virtual void Flush(void);
|
|
};
|
|
|
|
cSkinClassicDisplayReplay::cSkinClassicDisplayReplay(bool ModeOnly)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int lineHeight = font->Height();
|
|
lastCurrentWidth = 0;
|
|
x0 = 0;
|
|
x1 = cOsd::OsdWidth();
|
|
y0 = 0;
|
|
y1 = lineHeight;
|
|
y2 = 2 * lineHeight;
|
|
y3 = 3 * lineHeight;
|
|
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y3);
|
|
tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 8 } };
|
|
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } };
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
}
|
|
osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
|
|
}
|
|
|
|
cSkinClassicDisplayReplay::~cSkinClassicDisplayReplay()
|
|
{
|
|
delete osd;
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetTitle(const char *Title)
|
|
{
|
|
osd->DrawText(x0, y0, Title, Theme.Color(clrReplayTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), x1 - x0);
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
|
|
{
|
|
if (Setup.ShowReplayMode) {
|
|
const char *Mode;
|
|
if (Speed == -1) Mode = Play ? " > " : " || ";
|
|
else if (Play) Mode = Forward ? " X>> " : " <<X ";
|
|
else Mode = Forward ? " X|> " : " <|X ";
|
|
char buf[16];
|
|
strn0cpy(buf, Mode, sizeof(buf));
|
|
char *p = strchr(buf, 'X');
|
|
if (p)
|
|
*p = Speed > 0 ? '1' + Speed - 1 : ' ';
|
|
SetJump(buf);
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetProgress(int Current, int Total)
|
|
{
|
|
cProgressBar pb(x1 - x0, y2 - y1, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
|
|
osd->DrawBitmap(x0, y1, pb);
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetCurrent(const char *Current)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int w = font->Width(Current);
|
|
osd->DrawText(x0, y2, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), font, lastCurrentWidth > w ? lastCurrentWidth : w);
|
|
lastCurrentWidth = w;
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetTotal(const char *Total)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int w = font->Width(Total);
|
|
osd->DrawText(x1 - font->Width(Total), y2, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), font, w);
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetJump(const char *Jump)
|
|
{
|
|
osd->DrawText(x0 + (x1 - x0) / 4, y2, Jump, Theme.Color(clrReplayModeJump), Theme.Color(clrBackground), cFont::GetFont(fontOsd), (x1 - x0) / 2, 0, taCenter);
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::SetMessage(eMessageType Type, const char *Text)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
if (Text) {
|
|
osd->SaveRegion(x0, y2, x1 - 1, y3 - 1);
|
|
osd->DrawText(x0, y2, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x1 - x0, y3 - y2, taCenter);
|
|
}
|
|
else
|
|
osd->RestoreRegion();
|
|
}
|
|
|
|
void cSkinClassicDisplayReplay::Flush(void)
|
|
{
|
|
osd->Flush();
|
|
}
|
|
|
|
// --- cSkinClassicDisplayVolume ---------------------------------------------
|
|
|
|
class cSkinClassicDisplayVolume : public cSkinDisplayVolume {
|
|
private:
|
|
cOsd *osd;
|
|
public:
|
|
cSkinClassicDisplayVolume(void);
|
|
virtual ~cSkinClassicDisplayVolume();
|
|
virtual void SetVolume(int Current, int Total, bool Mute);
|
|
virtual void Flush(void);
|
|
};
|
|
|
|
cSkinClassicDisplayVolume::cSkinClassicDisplayVolume(void)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int lineHeight = font->Height();
|
|
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - lineHeight);
|
|
tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 8 } };
|
|
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 4 } };
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
}
|
|
}
|
|
|
|
cSkinClassicDisplayVolume::~cSkinClassicDisplayVolume()
|
|
{
|
|
delete osd;
|
|
}
|
|
|
|
void cSkinClassicDisplayVolume::SetVolume(int Current, int Total, bool Mute)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
if (Mute) {
|
|
osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrTransparent);
|
|
osd->DrawText(0, 0, tr("Key$Mute"), Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
|
|
}
|
|
else {
|
|
// TRANSLATORS: note the trailing blank!
|
|
const char *Prompt = tr("Volume ");
|
|
int l = font->Width(Prompt);
|
|
int p = (osd->Width() - l) * Current / Total;
|
|
osd->DrawText(0, 0, Prompt, Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
|
|
osd->DrawRectangle(l, 0, l + p - 1, osd->Height() - 1, Theme.Color(clrVolumeBarLower));
|
|
osd->DrawRectangle(l + p, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrVolumeBarUpper));
|
|
}
|
|
}
|
|
|
|
void cSkinClassicDisplayVolume::Flush(void)
|
|
{
|
|
osd->Flush();
|
|
}
|
|
|
|
// --- cSkinClassicDisplayTracks ---------------------------------------------
|
|
|
|
class cSkinClassicDisplayTracks : public cSkinDisplayTracks {
|
|
private:
|
|
cOsd *osd;
|
|
int x0, x1;
|
|
int y0, y1, y2;
|
|
int lineHeight;
|
|
int currentIndex;
|
|
void SetItem(const char *Text, int Index, bool Current);
|
|
public:
|
|
cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
|
|
virtual ~cSkinClassicDisplayTracks();
|
|
virtual void SetTrack(int Index, const char * const *Tracks);
|
|
virtual void SetAudioChannel(int AudioChannel) {}
|
|
virtual void Flush(void);
|
|
};
|
|
|
|
cSkinClassicDisplayTracks::cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
lineHeight = font->Height();
|
|
currentIndex = -1;
|
|
int ItemsWidth = font->Width(Title);
|
|
for (int i = 0; i < NumTracks; i++)
|
|
ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
|
|
ItemsWidth += 10;
|
|
x0 = 0;
|
|
x1 = cOsd::OsdWidth();
|
|
int d = x1 - x0;
|
|
if (d > ItemsWidth) {
|
|
d = (d - ItemsWidth) & ~0x07; // must be multiple of 8
|
|
x1 -= d;
|
|
}
|
|
y0 = 0;
|
|
y1 = lineHeight;
|
|
y2 = y1 + NumTracks * lineHeight;
|
|
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y2);
|
|
tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 8 } };
|
|
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 4 } };
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
}
|
|
osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0);
|
|
for (int i = 0; i < NumTracks; i++)
|
|
SetItem(Tracks[i], i, false);
|
|
}
|
|
|
|
cSkinClassicDisplayTracks::~cSkinClassicDisplayTracks()
|
|
{
|
|
delete osd;
|
|
}
|
|
|
|
void cSkinClassicDisplayTracks::SetItem(const char *Text, int Index, bool Current)
|
|
{
|
|
int y = y1 + Index * lineHeight;
|
|
tColor ColorFg, ColorBg;
|
|
if (Current) {
|
|
ColorFg = Theme.Color(clrMenuItemCurrentFg);
|
|
ColorBg = Theme.Color(clrMenuItemCurrentBg);
|
|
currentIndex = Index;
|
|
}
|
|
else {
|
|
ColorFg = Theme.Color(clrMenuItemSelectable);
|
|
ColorBg = Theme.Color(clrBackground);
|
|
}
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
osd->DrawText(x0, y, Text, ColorFg, ColorBg, font, x1 - x0);
|
|
}
|
|
|
|
void cSkinClassicDisplayTracks::SetTrack(int Index, const char * const *Tracks)
|
|
{
|
|
if (currentIndex >= 0)
|
|
SetItem(Tracks[currentIndex], currentIndex, false);
|
|
SetItem(Tracks[Index], Index, true);
|
|
}
|
|
|
|
void cSkinClassicDisplayTracks::Flush(void)
|
|
{
|
|
osd->Flush();
|
|
}
|
|
|
|
// --- cSkinClassicDisplayMessage --------------------------------------------
|
|
|
|
class cSkinClassicDisplayMessage : public cSkinDisplayMessage {
|
|
private:
|
|
cOsd *osd;
|
|
public:
|
|
cSkinClassicDisplayMessage(void);
|
|
virtual ~cSkinClassicDisplayMessage();
|
|
virtual void SetMessage(eMessageType Type, const char *Text);
|
|
virtual void Flush(void);
|
|
};
|
|
|
|
cSkinClassicDisplayMessage::cSkinClassicDisplayMessage(void)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
int lineHeight = font->Height();
|
|
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - lineHeight);
|
|
tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 8 } };
|
|
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
else {
|
|
tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 2 } };
|
|
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
|
|
}
|
|
}
|
|
|
|
cSkinClassicDisplayMessage::~cSkinClassicDisplayMessage()
|
|
{
|
|
delete osd;
|
|
}
|
|
|
|
void cSkinClassicDisplayMessage::SetMessage(eMessageType Type, const char *Text)
|
|
{
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, cOsd::OsdWidth(), 0, taCenter);
|
|
}
|
|
|
|
void cSkinClassicDisplayMessage::Flush(void)
|
|
{
|
|
osd->Flush();
|
|
}
|
|
|
|
// --- cSkinClassic ----------------------------------------------------------
|
|
|
|
cSkinClassic::cSkinClassic(void)
|
|
:cSkin("classic", &::Theme)//XXX naming problem???
|
|
{
|
|
}
|
|
|
|
const char *cSkinClassic::Description(void)
|
|
{
|
|
return tr("Classic VDR");
|
|
}
|
|
|
|
cSkinDisplayChannel *cSkinClassic::DisplayChannel(bool WithInfo)
|
|
{
|
|
return new cSkinClassicDisplayChannel(WithInfo);
|
|
}
|
|
|
|
cSkinDisplayMenu *cSkinClassic::DisplayMenu(void)
|
|
{
|
|
return new cSkinClassicDisplayMenu;
|
|
}
|
|
|
|
cSkinDisplayReplay *cSkinClassic::DisplayReplay(bool ModeOnly)
|
|
{
|
|
return new cSkinClassicDisplayReplay(ModeOnly);
|
|
}
|
|
|
|
cSkinDisplayVolume *cSkinClassic::DisplayVolume(void)
|
|
{
|
|
return new cSkinClassicDisplayVolume;
|
|
}
|
|
|
|
|
|
cSkinDisplayTracks *cSkinClassic::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
|
|
{
|
|
return new cSkinClassicDisplayTracks(Title, NumTracks, Tracks);
|
|
}
|
|
|
|
cSkinDisplayMessage *cSkinClassic::DisplayMessage(void)
|
|
{
|
|
return new cSkinClassicDisplayMessage;
|
|
}
|