2012-06-02 13:17:16 +02:00
|
|
|
/*
|
|
|
|
* skinlcars.c: A VDR skin with Star Trek's "LCARS" layout
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2016-12-22 14:13:42 +01:00
|
|
|
* $Id: skinlcars.c 4.2 2016/12/22 14:05:56 kls Exp $
|
2012-06-02 13:17:16 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures,
|
|
|
|
// registered in the United States Patent and Trademark Office, all rights reserved.
|
|
|
|
// The LCARS system is based upon the designs of Michael Okuda and his Okudagrams.
|
|
|
|
//
|
|
|
|
// "LCARS" is short for "Library Computer Access and Retrieval System".
|
|
|
|
// Some resources used for writing this skin can be found at
|
|
|
|
// http://www.lcars.org.uk
|
|
|
|
// http://www.lcarsdeveloper.com
|
|
|
|
// http://www.lcarscom.net
|
|
|
|
// http://lds-jedi.deviantart.com/art/LCARS-Swept-Tutorial-213936938
|
|
|
|
// http://lds-jedi.deviantart.com/art/LCARS-Button-Tutorial-210783437
|
|
|
|
// http://zelldenver.deviantart.com/art/LCARS-Color-Standard-179565780
|
|
|
|
// http://www.lcars47.com
|
|
|
|
// http://www.bracercom.com/tutorial/content/CoherentLCARSInterface/LCARSCoherentInterface.html
|
|
|
|
// http://www.bracercom.com/tutorial/content/lcars_manifesto/the_lcars_manifesto.html
|
|
|
|
|
|
|
|
#include "skinlcars.h"
|
|
|
|
#include "font.h"
|
|
|
|
#include "menu.h"
|
|
|
|
#include "osd.h"
|
2013-08-21 11:02:52 +02:00
|
|
|
#include "positioner.h"
|
2012-06-02 13:17:16 +02:00
|
|
|
#include "themes.h"
|
|
|
|
#include "videodir.h"
|
|
|
|
|
|
|
|
#include "symbols/arrowdown.xpm"
|
|
|
|
#include "symbols/arrowup.xpm"
|
|
|
|
#include "symbols/audio.xpm"
|
|
|
|
#include "symbols/audioleft.xpm"
|
|
|
|
#include "symbols/audioright.xpm"
|
|
|
|
#include "symbols/audiostereo.xpm"
|
|
|
|
#include "symbols/dolbydigital.xpm"
|
|
|
|
#include "symbols/encrypted.xpm"
|
|
|
|
#include "symbols/ffwd.xpm"
|
|
|
|
#include "symbols/ffwd1.xpm"
|
|
|
|
#include "symbols/ffwd2.xpm"
|
|
|
|
#include "symbols/ffwd3.xpm"
|
|
|
|
#include "symbols/frew.xpm"
|
|
|
|
#include "symbols/frew1.xpm"
|
|
|
|
#include "symbols/frew2.xpm"
|
|
|
|
#include "symbols/frew3.xpm"
|
|
|
|
#include "symbols/mute.xpm"
|
|
|
|
#include "symbols/pause.xpm"
|
|
|
|
#include "symbols/play.xpm"
|
|
|
|
#include "symbols/radio.xpm"
|
|
|
|
#include "symbols/recording.xpm"
|
|
|
|
#include "symbols/sfwd.xpm"
|
|
|
|
#include "symbols/sfwd1.xpm"
|
|
|
|
#include "symbols/sfwd2.xpm"
|
|
|
|
#include "symbols/sfwd3.xpm"
|
|
|
|
#include "symbols/srew.xpm"
|
|
|
|
#include "symbols/srew1.xpm"
|
|
|
|
#include "symbols/srew2.xpm"
|
|
|
|
#include "symbols/srew3.xpm"
|
|
|
|
#include "symbols/teletext.xpm"
|
|
|
|
#include "symbols/volume.xpm"
|
|
|
|
|
|
|
|
#define Gap (Setup.FontOsdSize / 5 & ~1) // must be even
|
|
|
|
#define TextFrame (Setup.FontOsdSize / TEXT_ALIGN_BORDER)
|
|
|
|
#define TextSpacing (2 * TextFrame)
|
|
|
|
#define SymbolSpacing TextSpacing
|
|
|
|
#define ShowSeenExtent (Setup.FontOsdSize / 5) // pixels by which the "seen" bar extends out of the frame
|
|
|
|
|
|
|
|
#define DISKUSAGEALERTLIMIT 95 // percent of disk usage above which the display goes into alert mode
|
|
|
|
#define SIGNALDISPLAYDELTA 2 // seconds between subsequent device signal displays
|
|
|
|
|
|
|
|
static cTheme Theme;
|
|
|
|
|
|
|
|
// Color domains:
|
|
|
|
|
|
|
|
#define CLR_BACKGROUND 0x99000000
|
2012-06-13 13:37:13 +02:00
|
|
|
#define CLR_MAIN_FRAME 0xFFFF9966
|
|
|
|
#define CLR_CHANNEL_FRAME 0xFF8A9EC9
|
2012-06-02 13:17:16 +02:00
|
|
|
#define CLR_REPLAY_FRAME 0xFFCC6666
|
|
|
|
#define CLR_DATE 0xFF99CCFF
|
2012-06-13 13:37:13 +02:00
|
|
|
#define CLR_MENU_ITEMS 0xFF9999FF
|
2012-06-02 13:17:16 +02:00
|
|
|
#define CLR_TIMER 0xFF99CCFF
|
2012-06-03 09:45:00 +02:00
|
|
|
#define CLR_DEVICE 0xFFF1B1AF
|
2012-06-02 13:17:16 +02:00
|
|
|
#define CLR_CHANNEL_NAME 0xFF99CCFF
|
|
|
|
#define CLR_EVENT_TITLE 0xFF99CCFF
|
|
|
|
#define CLR_EVENT_TIME 0xFFFFCC66
|
|
|
|
#define CLR_EVENT_SHORTTEXT 0xFFFFCC66
|
|
|
|
#define CLR_TEXT 0xFF99CCFF
|
|
|
|
#define CLR_TRACK 0xFFFFCC66
|
|
|
|
#define CLR_SEEN 0xFFCC99CC
|
|
|
|
#define CLR_ALERT 0xFFFF0000
|
|
|
|
#define CLR_EXPOSED 0xFF990000
|
|
|
|
#define CLR_WHITE 0xFFFFFFFF
|
2012-06-07 10:32:35 +02:00
|
|
|
#define CLR_RED 0xFFCC6666
|
|
|
|
#define CLR_GREEN 0xFFA0FF99
|
|
|
|
#define CLR_YELLOW 0xFFF1DF60
|
|
|
|
#define CLR_BLUE 0xFF9A99FF
|
2012-06-02 13:17:16 +02:00
|
|
|
#define CLR_BLACK 0xFF000000
|
|
|
|
|
|
|
|
// General colors:
|
|
|
|
|
|
|
|
THEME_CLR(Theme, clrBackground, CLR_BACKGROUND);
|
|
|
|
THEME_CLR(Theme, clrDateFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrDateBg, CLR_DATE);
|
|
|
|
THEME_CLR(Theme, clrTimerFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrTimerBg, CLR_TIMER);
|
|
|
|
THEME_CLR(Theme, clrDeviceFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrDeviceBg, CLR_DEVICE);
|
|
|
|
THEME_CLR(Theme, clrSignalValue, CLR_GREEN);
|
|
|
|
THEME_CLR(Theme, clrSignalRest, CLR_RED);
|
|
|
|
THEME_CLR(Theme, clrSeen, CLR_SEEN);
|
|
|
|
THEME_CLR(Theme, clrTrackName, CLR_TRACK);
|
|
|
|
THEME_CLR(Theme, clrAlertFg, CLR_WHITE);
|
|
|
|
THEME_CLR(Theme, clrAlertBg, CLR_ALERT);
|
|
|
|
THEME_CLR(Theme, clrChannelName, CLR_CHANNEL_NAME);
|
|
|
|
THEME_CLR(Theme, clrEventTitle, CLR_EVENT_TITLE);
|
|
|
|
THEME_CLR(Theme, clrEventTime, CLR_EVENT_TIME);
|
|
|
|
THEME_CLR(Theme, clrEventShortText, CLR_EVENT_SHORTTEXT);
|
|
|
|
THEME_CLR(Theme, clrEventDescription, CLR_TEXT);
|
|
|
|
|
|
|
|
// Buttons:
|
|
|
|
|
2012-06-07 10:32:35 +02:00
|
|
|
THEME_CLR(Theme, clrButtonRedFg, CLR_BLACK);
|
2012-06-02 13:17:16 +02:00
|
|
|
THEME_CLR(Theme, clrButtonRedBg, CLR_RED);
|
|
|
|
THEME_CLR(Theme, clrButtonGreenFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrButtonGreenBg, CLR_GREEN);
|
|
|
|
THEME_CLR(Theme, clrButtonYellowFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrButtonYellowBg, CLR_YELLOW);
|
2012-06-07 10:32:35 +02:00
|
|
|
THEME_CLR(Theme, clrButtonBlueFg, CLR_BLACK);
|
2012-06-02 13:17:16 +02:00
|
|
|
THEME_CLR(Theme, clrButtonBlueBg, CLR_BLUE);
|
|
|
|
|
|
|
|
// Messages:
|
|
|
|
|
2012-06-12 13:15:53 +02:00
|
|
|
THEME_CLR(Theme, clrMessageStatusFg, CLR_BLACK);
|
2012-06-02 13:17:16 +02:00
|
|
|
THEME_CLR(Theme, clrMessageStatusBg, CLR_BLUE);
|
|
|
|
THEME_CLR(Theme, clrMessageInfoFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrMessageInfoBg, CLR_GREEN);
|
|
|
|
THEME_CLR(Theme, clrMessageWarningFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrMessageWarningBg, CLR_YELLOW);
|
2012-06-12 13:15:53 +02:00
|
|
|
THEME_CLR(Theme, clrMessageErrorFg, CLR_BLACK);
|
2012-06-02 13:17:16 +02:00
|
|
|
THEME_CLR(Theme, clrMessageErrorBg, CLR_RED);
|
|
|
|
|
|
|
|
// Volume:
|
|
|
|
|
|
|
|
THEME_CLR(Theme, clrVolumeFrame, CLR_MAIN_FRAME);
|
|
|
|
THEME_CLR(Theme, clrVolumeSymbol, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrVolumeBarUpper, RgbShade(CLR_MAIN_FRAME, -0.2));
|
|
|
|
THEME_CLR(Theme, clrVolumeBarLower, CLR_GREEN);
|
|
|
|
|
|
|
|
// Channel display:
|
|
|
|
|
|
|
|
THEME_CLR(Theme, clrChannelFrameFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrChannelFrameBg, CLR_CHANNEL_FRAME);
|
|
|
|
THEME_CLR(Theme, clrChannelSymbolOn, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrChannelSymbolOff, RgbShade(CLR_CHANNEL_FRAME, -0.2));
|
|
|
|
THEME_CLR(Theme, clrChannelSymbolRecFg, CLR_WHITE);
|
|
|
|
THEME_CLR(Theme, clrChannelSymbolRecBg, CLR_RED);
|
|
|
|
|
|
|
|
// Menu:
|
|
|
|
|
|
|
|
THEME_CLR(Theme, clrMenuFrameFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrMenuFrameBg, CLR_MAIN_FRAME);
|
|
|
|
THEME_CLR(Theme, clrMenuTitle, CLR_MAIN_FRAME);
|
|
|
|
THEME_CLR(Theme, clrMenuMainBracket, CLR_MENU_ITEMS);
|
|
|
|
THEME_CLR(Theme, clrMenuTimerRecording, CLR_DEVICE);
|
|
|
|
THEME_CLR(Theme, clrMenuDeviceRecording, CLR_TIMER);
|
2012-06-13 13:37:13 +02:00
|
|
|
THEME_CLR(Theme, clrMenuItemCurrentFg, CLR_MAIN_FRAME);
|
|
|
|
THEME_CLR(Theme, clrMenuItemCurrentBg, RgbShade(CLR_MENU_ITEMS, -0.5));
|
2012-06-02 13:17:16 +02:00
|
|
|
THEME_CLR(Theme, clrMenuItemSelectable, CLR_MENU_ITEMS);
|
|
|
|
THEME_CLR(Theme, clrMenuItemNonSelectable, CLR_TEXT);
|
2012-06-13 13:37:13 +02:00
|
|
|
THEME_CLR(Theme, clrMenuScrollbarTotal, RgbShade(CLR_MAIN_FRAME, 0.2));
|
2012-06-02 13:17:16 +02:00
|
|
|
THEME_CLR(Theme, clrMenuScrollbarShown, CLR_SEEN);
|
|
|
|
THEME_CLR(Theme, clrMenuScrollbarArrow, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrMenuText, CLR_TEXT);
|
|
|
|
|
|
|
|
// Replay display:
|
|
|
|
|
|
|
|
THEME_CLR(Theme, clrReplayFrameFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrReplayFrameBg, CLR_REPLAY_FRAME);
|
|
|
|
THEME_CLR(Theme, clrReplayPosition, CLR_SEEN);
|
|
|
|
THEME_CLR(Theme, clrReplayJumpFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrReplayJumpBg, CLR_SEEN);
|
|
|
|
THEME_CLR(Theme, clrReplayProgressSeen, CLR_SEEN);
|
|
|
|
THEME_CLR(Theme, clrReplayProgressRest, RgbShade(CLR_WHITE, -0.2));
|
|
|
|
THEME_CLR(Theme, clrReplayProgressSelected, CLR_EXPOSED);
|
|
|
|
THEME_CLR(Theme, clrReplayProgressMark, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrReplayProgressCurrent, CLR_EXPOSED);
|
|
|
|
|
|
|
|
// Track display:
|
|
|
|
|
|
|
|
THEME_CLR(Theme, clrTrackFrameFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrTrackFrameBg, CLR_TRACK);
|
|
|
|
THEME_CLR(Theme, clrTrackItemFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrTrackItemBg, RgbShade(CLR_TRACK, 0.5));
|
|
|
|
THEME_CLR(Theme, clrTrackItemCurrentFg, CLR_BLACK);
|
|
|
|
THEME_CLR(Theme, clrTrackItemCurrentBg, CLR_TRACK);
|
|
|
|
|
|
|
|
// --- Helper functions ------------------------------------------------------
|
|
|
|
|
2013-01-23 13:53:28 +01:00
|
|
|
static bool TwoColors = false;
|
|
|
|
|
2012-06-02 13:17:16 +02:00
|
|
|
static cOsd *CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1)
|
|
|
|
{
|
|
|
|
cOsd *Osd = cOsdProvider::NewOsd(Left, Top);
|
|
|
|
int Bpp[] = { 32, 8, 4, 2, 1 };
|
|
|
|
tArea Area = { x0, y0, x1, y1, 0 };
|
|
|
|
for (unsigned int i = 0; i < sizeof(Bpp) / sizeof(int); i++) {
|
|
|
|
Area.bpp = Bpp[i];
|
|
|
|
if (Osd->CanHandleAreas(&Area, 1) == oeOk) {
|
|
|
|
Osd->SetAreas(&Area, 1);
|
2013-03-09 10:46:41 +01:00
|
|
|
Osd->SetAntiAliasGranularity(20, 16);
|
2013-01-23 13:53:28 +01:00
|
|
|
TwoColors = Area.bpp == 1;
|
2012-06-02 13:17:16 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cFont *CreateTinyFont(int LineHeight)
|
|
|
|
{
|
|
|
|
// Creates a font that is not higher than half of LineHeight.
|
|
|
|
LineHeight /= 2;
|
|
|
|
int Height = LineHeight;
|
|
|
|
for (;;) {
|
|
|
|
cFont *TinyFont = cFont::CreateFont(Setup.FontOsd, Height);
|
|
|
|
if (Height < 2 || TinyFont->Height() <= LineHeight)
|
|
|
|
return TinyFont;
|
|
|
|
delete TinyFont;
|
|
|
|
Height -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool DrawDeviceData(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &xs, const cFont *TinyFont, cString &LastDeviceType, cCamSlot *&LastCamSlot, bool Initial)
|
|
|
|
{
|
|
|
|
cString DeviceType = Device->DeviceType();
|
|
|
|
cCamSlot *CamSlot = Device->CamSlot();
|
|
|
|
if (Initial || strcmp(DeviceType, LastDeviceType) || CamSlot != LastCamSlot) {
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
tColor ColorFg = Theme.Color(clrDeviceFg);
|
|
|
|
tColor ColorBg = Theme.Color(clrDeviceBg);
|
|
|
|
Osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, ColorBg);
|
|
|
|
int x = x0;
|
|
|
|
// Device number:
|
|
|
|
cString Nr = itoa(Device->DeviceNumber() + 1);
|
|
|
|
int w = max(font->Width(Nr), y1 - y0);
|
|
|
|
Osd->DrawText(x, y0, Nr, ColorFg, ColorBg, font, w, y1 - y0, taCenter);
|
|
|
|
x += w;
|
|
|
|
// Device type:
|
|
|
|
Osd->DrawText(x, y0, DeviceType, ColorFg, ColorBg, TinyFont);
|
|
|
|
xs = max(xs, x + TinyFont->Width(DeviceType));
|
|
|
|
LastDeviceType = DeviceType;
|
|
|
|
// CAM:
|
|
|
|
if (CamSlot) {
|
|
|
|
cString s = cString::sprintf("CAM %d", CamSlot->SlotNumber());
|
|
|
|
Osd->DrawText(x, y1 - TinyFont->Height(), s, ColorFg, ColorBg, TinyFont);
|
|
|
|
xs = max(xs, x + TinyFont->Width(s));
|
|
|
|
}
|
|
|
|
LastCamSlot = CamSlot;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DrawDeviceSignal(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &LastSignalStrength, int &LastSignalQuality, bool Initial)
|
|
|
|
{
|
|
|
|
int SignalStrength = Device->SignalStrength();
|
|
|
|
int SignalQuality = Device->SignalQuality();
|
|
|
|
int d = max((y1 - y0) / 10, 1);
|
|
|
|
int x00 = x0 + d;
|
|
|
|
int x01 = x1 - d;
|
|
|
|
int h = (y1 - y0 - 3 * d) / 2;
|
|
|
|
int w = x01 - x00;
|
|
|
|
int y00 = y0 + d;
|
|
|
|
int y01 = y00 + h;
|
|
|
|
int y03 = y1 - d;
|
|
|
|
int y02 = y03 - h;
|
2013-01-23 13:53:28 +01:00
|
|
|
tColor ColorSignalValue, ColorSignalRest;
|
|
|
|
if (TwoColors) {
|
|
|
|
ColorSignalValue = Theme.Color(clrBackground);
|
|
|
|
ColorSignalRest = Theme.Color(clrMenuFrameBg);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ColorSignalValue = Theme.Color(clrSignalValue);
|
|
|
|
ColorSignalRest = Theme.Color(clrSignalRest);
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
if (SignalStrength >= 0 && (Initial || SignalStrength != LastSignalStrength)) {
|
|
|
|
int s = SignalStrength * w / 100;
|
2013-01-23 13:53:28 +01:00
|
|
|
Osd->DrawRectangle(x00, y00, x00 + s - 1, y01 - 1, ColorSignalValue);
|
|
|
|
Osd->DrawRectangle(x00 + s, y00, x01 - 1, y01 - 1, ColorSignalRest);
|
2012-06-02 13:17:16 +02:00
|
|
|
LastSignalStrength = SignalStrength;
|
|
|
|
}
|
|
|
|
if (SignalQuality >= 0 && (Initial || SignalQuality != LastSignalQuality)) {
|
|
|
|
int q = SignalQuality * w / 100;
|
2013-01-23 13:53:28 +01:00
|
|
|
Osd->DrawRectangle(x00, y02, x00 + q - 1, y03 - 1, ColorSignalValue);
|
|
|
|
Osd->DrawRectangle(x00 + q, y02, x01 - 1, y03 - 1, ColorSignalRest);
|
2012-06-02 13:17:16 +02:00
|
|
|
LastSignalQuality = SignalQuality;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-21 11:02:52 +02:00
|
|
|
static void DrawDevicePosition(cOsd *Osd, const cPositioner *Positioner, int x0, int y0, int x1, int y1, int &LastCurrent)
|
|
|
|
{
|
|
|
|
int HorizonLeft = Positioner->HorizonLongitude(cPositioner::pdLeft);
|
|
|
|
int HorizonRight = Positioner->HorizonLongitude(cPositioner::pdRight);
|
|
|
|
int HardLimitLeft = cPositioner::NormalizeAngle(HorizonLeft - Positioner->HardLimitLongitude(cPositioner::pdLeft));
|
|
|
|
int HardLimitRight = cPositioner::NormalizeAngle(Positioner->HardLimitLongitude(cPositioner::pdRight) - HorizonRight);
|
|
|
|
int HorizonDelta = cPositioner::NormalizeAngle(HorizonLeft - HorizonRight);
|
|
|
|
int Current = cPositioner::NormalizeAngle(HorizonLeft - Positioner->CurrentLongitude());
|
|
|
|
int Target = cPositioner::NormalizeAngle(HorizonLeft - Positioner->TargetLongitude());
|
|
|
|
int d = (y1 - y0) / 2;
|
|
|
|
int w = x1 - x0 - 2 * d;
|
|
|
|
int l = max(x0 + d, x0 + d + w * HardLimitLeft / HorizonDelta);
|
|
|
|
int r = min(x1 - d, x1 - d - w * HardLimitRight / HorizonDelta) - 1;
|
|
|
|
int c = constrain(x0 + d + w * Current / HorizonDelta, l, r);
|
|
|
|
int t = constrain(x0 + d + w * Target / HorizonDelta, l, r);
|
|
|
|
if (c == LastCurrent)
|
|
|
|
return;
|
|
|
|
if (c > t)
|
|
|
|
swap(c, t);
|
|
|
|
tColor ColorRange, ColorMove;
|
|
|
|
if (TwoColors) {
|
|
|
|
ColorRange = Theme.Color(clrChannelFrameBg);
|
|
|
|
ColorMove = Theme.Color(clrBackground);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ColorRange = Theme.Color(clrChannelFrameBg);
|
|
|
|
ColorMove = Theme.Color(clrDeviceBg);
|
|
|
|
}
|
|
|
|
Osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
Osd->DrawEllipse(l - d, y0, l, y1 - 1, ColorRange, 7);
|
|
|
|
Osd->DrawRectangle(l, y0, r, y1 - 1, ColorRange);
|
|
|
|
Osd->DrawEllipse(r, y0, r + d, y1 - 1, ColorRange, 5);
|
|
|
|
Osd->DrawEllipse(c - d, y0, c, y1 - 1, ColorMove, 7);
|
|
|
|
Osd->DrawRectangle(c, y0, t, y1 - 1, ColorMove);
|
|
|
|
Osd->DrawEllipse(t, y0, t + d, y1 - 1, ColorMove, 5);
|
|
|
|
LastCurrent = c;
|
|
|
|
}
|
|
|
|
|
2012-06-02 13:17:16 +02:00
|
|
|
// --- cSkinLCARSDisplayChannel ----------------------------------------------
|
|
|
|
|
|
|
|
class cSkinLCARSDisplayChannel : public cSkinDisplayChannel {
|
|
|
|
private:
|
|
|
|
cOsd *osd;
|
|
|
|
int xc00, xc01, xc02, xc03, xc04, xc05, xc06, xc07, xc08, xc09, xc10, xc11, xc12, xc13, xc14, xc15;
|
|
|
|
int yc00, yc01, yc02, yc03, yc04, yc05, yc06, yc07, yc08, yc09, yc10, yc11, yc12;
|
|
|
|
int xs; // starting column for signal display
|
|
|
|
bool withInfo;
|
|
|
|
int lineHeight;
|
|
|
|
cFont *tinyFont;
|
|
|
|
cFont *tallFont;
|
|
|
|
tColor frameColor;
|
|
|
|
bool message;
|
|
|
|
const cEvent *present;
|
|
|
|
bool initial;
|
|
|
|
cString lastDate;
|
|
|
|
int lastSeen;
|
2013-08-21 11:02:52 +02:00
|
|
|
int lastCurrentPosition;
|
2012-06-02 13:17:16 +02:00
|
|
|
int lastDeviceNumber;
|
|
|
|
cString lastDeviceType;
|
|
|
|
cCamSlot *lastCamSlot;
|
|
|
|
int lastSignalStrength;
|
|
|
|
int lastSignalQuality;
|
|
|
|
time_t lastSignalDisplay;
|
|
|
|
tTrackId lastTrackId;
|
|
|
|
static cBitmap bmTeletext, bmRadio, bmAudio, bmDolbyDigital, bmEncrypted, bmRecording;
|
|
|
|
void DrawDate(void);
|
|
|
|
void DrawTrack(void);
|
|
|
|
void DrawSeen(int Current, int Total);
|
|
|
|
void DrawDevice(void);
|
|
|
|
void DrawSignal(void);
|
|
|
|
public:
|
|
|
|
cSkinLCARSDisplayChannel(bool WithInfo);
|
|
|
|
virtual ~cSkinLCARSDisplayChannel();
|
|
|
|
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);
|
2013-08-21 11:02:52 +02:00
|
|
|
virtual void SetPositioner(const cPositioner *Positioner);
|
2012-06-02 13:17:16 +02:00
|
|
|
virtual void Flush(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
cBitmap cSkinLCARSDisplayChannel::bmTeletext(teletext_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayChannel::bmRadio(radio_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayChannel::bmAudio(audio_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayChannel::bmDolbyDigital(dolbydigital_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayChannel::bmEncrypted(encrypted_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayChannel::bmRecording(recording_xpm);
|
|
|
|
|
|
|
|
cSkinLCARSDisplayChannel::cSkinLCARSDisplayChannel(bool WithInfo)
|
|
|
|
{
|
|
|
|
tallFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize * 1.8);
|
|
|
|
initial = true;
|
|
|
|
present = NULL;
|
|
|
|
lastSeen = -1;
|
2013-08-21 11:02:52 +02:00
|
|
|
lastCurrentPosition = -1;
|
2012-06-02 13:17:16 +02:00
|
|
|
lastDeviceNumber = -1;
|
|
|
|
lastCamSlot = NULL;
|
|
|
|
lastSignalStrength = -1;
|
|
|
|
lastSignalQuality = -1;
|
|
|
|
lastSignalDisplay = 0;
|
|
|
|
memset(&lastTrackId, 0, sizeof(lastTrackId));
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
withInfo = WithInfo;
|
|
|
|
lineHeight = font->Height();
|
|
|
|
tinyFont = CreateTinyFont(lineHeight);
|
|
|
|
frameColor = Theme.Color(clrChannelFrameBg);
|
|
|
|
message = false;
|
|
|
|
int d = 5 * lineHeight;
|
|
|
|
xc00 = 0;
|
|
|
|
xc01 = xc00 + d / 2;
|
|
|
|
xc02 = xc00 + d;
|
|
|
|
xc03 = xc02 + lineHeight;
|
|
|
|
xc04 = xc02 + d / 4;
|
|
|
|
xc05 = xc02 + d;
|
|
|
|
xc06 = xc05 + Gap;
|
|
|
|
xc15 = cOsd::OsdWidth();
|
|
|
|
xc14 = xc15 - lineHeight;
|
|
|
|
xc13 = xc14 - Gap;
|
|
|
|
xc07 = (xc15 + xc00) / 2;
|
|
|
|
xc08 = xc07 + Gap;
|
|
|
|
xc09 = xc08 + lineHeight;
|
|
|
|
xc10 = xc09 + Gap;
|
|
|
|
xc11 = (xc10 + xc13 + Gap) / 2;
|
|
|
|
xc12 = xc11 + Gap;
|
|
|
|
|
|
|
|
yc00 = 0;
|
|
|
|
yc01 = yc00 + lineHeight;
|
|
|
|
yc02 = yc01 + lineHeight;
|
|
|
|
yc03 = yc02 + Gap;
|
|
|
|
yc04 = yc03 + 2 * lineHeight;
|
|
|
|
yc05 = yc04 + Gap;
|
|
|
|
yc06 = yc05 + 2 * lineHeight;
|
|
|
|
|
|
|
|
yc07 = yc06 + Gap;
|
|
|
|
yc12 = yc07 + 3 * lineHeight + Gap / 2;
|
|
|
|
yc11 = yc12 - lineHeight;
|
|
|
|
yc10 = yc11 - lineHeight;
|
|
|
|
yc09 = yc11 - d / 4;
|
|
|
|
yc08 = yc12 - d / 2;
|
|
|
|
|
|
|
|
xs = 0;
|
|
|
|
|
|
|
|
int y1 = withInfo ? yc12 : yc02;
|
|
|
|
int y0 = cOsd::OsdTop() + (Setup.ChannelInfoPos ? 0 : cOsd::OsdHeight() - y1);
|
|
|
|
osd = CreateOsd(cOsd::OsdLeft(), y0, xc00, yc00, xc15 - 1, y1 - 1);
|
|
|
|
osd->DrawRectangle(xc00, yc00, xc15 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
// Rectangles:
|
|
|
|
osd->DrawRectangle(xc00, yc00, xc02 - 1, yc02 - 1, frameColor);
|
|
|
|
if (withInfo) {
|
|
|
|
osd->DrawRectangle(xc00, yc03, xc02 - 1, yc04 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xc00, yc05, xc02 - 1, yc06 - 1, frameColor);
|
|
|
|
// Elbow:
|
|
|
|
osd->DrawRectangle(xc00, yc07, xc01 - 1, yc08 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xc00, yc08, xc01 - 1, yc12 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xc00, yc08, xc01 - 1, yc12 - 1, frameColor, 3);
|
|
|
|
osd->DrawRectangle(xc01, yc07, xc02 - 1, yc12 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xc02, yc09, xc04 - 1, yc11 - 1, frameColor, -3);
|
|
|
|
osd->DrawRectangle(xc02, yc11, xc05 - 1, yc12 - 1, frameColor);
|
|
|
|
// Status area:
|
|
|
|
osd->DrawRectangle(xc06, yc11 + lineHeight / 2, xc07 - 1, yc12 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xc08, yc11, xc09 - 1, yc12 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xc10, yc11, xc11 - 1, yc12 - 1, Theme.Color(clrDeviceBg));
|
|
|
|
osd->DrawRectangle(xc12, yc11, xc13 - 1, yc12 - 1, Theme.Color(clrDateBg));
|
|
|
|
osd->DrawRectangle(xc14, yc11, xc14 + lineHeight / 2 - 1, yc12 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xc14 + lineHeight / 2, yc11 + lineHeight / 2, xc15 - 1, yc12 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xc14 + lineHeight / 2, yc11, xc15 - 1, yc12 - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
// Icons:
|
|
|
|
osd->DrawRectangle(xc14, yc00, xc14 + lineHeight / 2 - 1, yc01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xc14 + lineHeight / 2, yc00, xc15 - 1, yc00 + lineHeight / 2 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xc14 + lineHeight / 2, yc00, xc15 - 1, yc01 - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinLCARSDisplayChannel::~cSkinLCARSDisplayChannel()
|
|
|
|
{
|
|
|
|
delete tallFont;
|
|
|
|
delete tinyFont;
|
|
|
|
delete osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::DrawDate(void)
|
|
|
|
{
|
|
|
|
cString s = DayDateTime();
|
2014-06-12 08:55:32 +02:00
|
|
|
if (initial || !*lastDate || strcmp(s, lastDate)) {
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawText(xc12, yc11, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xc13 - xc12, lineHeight, taRight | taBorder);
|
|
|
|
lastDate = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::DrawTrack(void)
|
|
|
|
{
|
|
|
|
cDevice *Device = cDevice::PrimaryDevice();
|
|
|
|
const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
|
2013-11-15 15:35:21 +01:00
|
|
|
if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawText(xc03, yc07, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc07 - xc03);
|
|
|
|
strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::DrawSeen(int Current, int Total)
|
|
|
|
{
|
2013-08-21 11:02:52 +02:00
|
|
|
if (lastCurrentPosition >= 0)
|
|
|
|
return; // to not interfere with SetPositioner()
|
2013-01-25 14:57:30 +01:00
|
|
|
int Seen = (Total > 0) ? min(xc07 - xc06, int((xc07 - xc06) * double(Current) / Total)) : 0;
|
2012-06-02 13:17:16 +02:00
|
|
|
if (initial || Seen != lastSeen) {
|
|
|
|
int y0 = yc11 - ShowSeenExtent;
|
|
|
|
int y1 = yc11 + lineHeight / 2 - Gap / 2;
|
|
|
|
osd->DrawRectangle(xc06, y0, xc06 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
|
|
|
|
osd->DrawRectangle(xc06 + Seen, y0, xc07 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
lastSeen = Seen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::DrawDevice(void)
|
|
|
|
{
|
|
|
|
const cDevice *Device = cDevice::ActualDevice();
|
|
|
|
if (DrawDeviceData(osd, Device, xc10, yc11, xc11, yc12, xs, tinyFont, lastDeviceType, lastCamSlot, Device->DeviceNumber() != lastDeviceNumber)) {
|
|
|
|
lastDeviceNumber = Device->DeviceNumber();
|
|
|
|
// Make sure signal meters are redrawn:
|
|
|
|
lastSignalStrength = -1;
|
|
|
|
lastSignalQuality = -1;
|
|
|
|
lastSignalDisplay = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::DrawSignal(void)
|
|
|
|
{
|
|
|
|
time_t Now = time(NULL);
|
|
|
|
if (Now != lastSignalDisplay) {
|
|
|
|
DrawDeviceSignal(osd, cDevice::ActualDevice(), xs + lineHeight / 2, yc11, xc11, yc12, lastSignalStrength, lastSignalQuality, initial);
|
|
|
|
lastSignalDisplay = Now;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::SetChannel(const cChannel *Channel, int Number)
|
|
|
|
{
|
|
|
|
int x = xc13;
|
|
|
|
int xi = x - SymbolSpacing -
|
|
|
|
bmRecording.Width() - SymbolSpacing -
|
|
|
|
bmEncrypted.Width() - SymbolSpacing -
|
|
|
|
bmDolbyDigital.Width() - SymbolSpacing -
|
|
|
|
bmAudio.Width() - SymbolSpacing -
|
|
|
|
max(bmTeletext.Width(), bmRadio.Width()) - SymbolSpacing;
|
|
|
|
osd->DrawRectangle(xi, yc00, xc13 - 1, yc01 - 1, frameColor);
|
|
|
|
if (Channel && !Channel->GroupSep()) {
|
|
|
|
bool rec = cRecordControls::Active();
|
|
|
|
x -= bmRecording.Width() + SymbolSpacing;
|
|
|
|
osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : frameColor);
|
|
|
|
x -= bmEncrypted.Width() + SymbolSpacing;
|
|
|
|
osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmEncrypted.Height()) / 2, bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
|
|
|
x -= bmDolbyDigital.Width() + SymbolSpacing;
|
|
|
|
osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmDolbyDigital.Height()) / 2, bmDolbyDigital, Theme.Color(Channel->Dpid(0) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
|
|
|
x -= bmAudio.Width() + SymbolSpacing;
|
|
|
|
osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmAudio.Height()) / 2, bmAudio, Theme.Color(Channel->Apid(1) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
|
|
|
if (Channel->Vpid()) {
|
|
|
|
x -= bmTeletext.Width() + SymbolSpacing;
|
|
|
|
osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
|
|
|
|
}
|
|
|
|
else if (Channel->Apid(0)) {
|
|
|
|
x -= bmRadio.Width() + SymbolSpacing;
|
|
|
|
osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cString ChNumber("");
|
|
|
|
cString ChName("");
|
|
|
|
if (Channel) {
|
|
|
|
ChName = Channel->Name();
|
|
|
|
if (!Channel->GroupSep())
|
|
|
|
ChNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : "");
|
|
|
|
}
|
|
|
|
else if (Number)
|
|
|
|
ChNumber = cString::sprintf("%d-", Number);
|
|
|
|
else
|
2012-06-04 09:41:06 +02:00
|
|
|
ChName = ChannelString(NULL, 0);
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawText(xc00, yc00, ChNumber, Theme.Color(clrChannelFrameFg), frameColor, tallFont, xc02 - xc00, yc02 - yc00, taTop | taRight | taBorder);
|
|
|
|
osd->DrawText(xc03, yc00, ChName, Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xi - xc03 - lineHeight, 0, taTop | taLeft);
|
|
|
|
lastSignalDisplay = 0;
|
2013-08-21 11:02:52 +02:00
|
|
|
if (withInfo) {
|
|
|
|
if (Channel) {
|
|
|
|
int x = xc00 + (yc10 - yc09); // compensate for the arc
|
|
|
|
osd->DrawText(x, yc07, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - x, yc10 - yc07, taTop | taRight | taBorder);
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
DrawDevice();
|
2013-08-21 11:02:52 +02:00
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
|
|
|
|
{
|
|
|
|
if (!withInfo)
|
|
|
|
return;
|
|
|
|
if (present != Present)
|
|
|
|
lastSeen = -1;
|
|
|
|
present = Present;
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
const cEvent *e = !i ? Present : Following;
|
|
|
|
int y = !i ? yc03 : yc05;
|
|
|
|
if (e) {
|
|
|
|
osd->DrawText(xc00, y, e->GetTimeString(), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - xc00, 0, taRight | taBorder);
|
|
|
|
osd->DrawText(xc03, y, e->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc13 - xc03);
|
|
|
|
osd->DrawText(xc03, y + lineHeight, e->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xc13 - xc03);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
osd->DrawRectangle(xc00, y, xc02 - 1, y + lineHeight, frameColor);
|
|
|
|
osd->DrawRectangle(xc02, y, xc13 - 1, y + 2 * lineHeight, Theme.Color(clrBackground));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayChannel::SetMessage(eMessageType Type, const char *Text)
|
|
|
|
{
|
|
|
|
if (Text) {
|
2012-06-13 10:19:15 +02:00
|
|
|
int x0, x1, y0, y1, y2;
|
|
|
|
if (withInfo) {
|
|
|
|
x0 = xc06;
|
|
|
|
x1 = xc13;
|
|
|
|
y0 = yc11 - ShowSeenExtent;
|
|
|
|
y1 = yc11;
|
|
|
|
y2 = yc12;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
x0 = xc03;
|
|
|
|
x1 = xc13;
|
|
|
|
y0 = y1 = yc00;
|
|
|
|
y2 = yc02;
|
|
|
|
}
|
|
|
|
osd->SaveRegion(x0, y0, x1 - 1, y2 - 1);
|
|
|
|
if (withInfo)
|
|
|
|
osd->DrawRectangle(xc06, y0, xc07, y1 - 1, Theme.Color(clrBackground)); // clears the "seen" bar
|
|
|
|
osd->DrawText(x0, y1, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), x1 - x0, y2 - y1, taCenter);
|
|
|
|
message = true;
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
2012-06-13 10:19:15 +02:00
|
|
|
else {
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->RestoreRegion();
|
2012-06-13 10:19:15 +02:00
|
|
|
message = false;
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
|
2013-08-21 11:02:52 +02:00
|
|
|
void cSkinLCARSDisplayChannel::SetPositioner(const cPositioner *Positioner)
|
|
|
|
{
|
|
|
|
if (Positioner) {
|
|
|
|
int y0 = yc11 - ShowSeenExtent;
|
|
|
|
int y1 = yc11 + lineHeight / 2 - Gap / 2;
|
|
|
|
DrawDevicePosition(osd, Positioner, xc06, y0, xc07, y1, lastCurrentPosition);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lastCurrentPosition = -1;
|
|
|
|
initial = true; // to have DrawSeen() refresh the progress bar
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-06-02 13:17:16 +02:00
|
|
|
void cSkinLCARSDisplayChannel::Flush(void)
|
|
|
|
{
|
|
|
|
if (withInfo) {
|
|
|
|
if (!message) {
|
|
|
|
DrawDate();
|
|
|
|
DrawTrack();
|
|
|
|
DrawDevice();
|
|
|
|
DrawSignal();
|
2012-06-13 10:19:15 +02:00
|
|
|
int Current = 0;
|
|
|
|
int Total = 0;
|
|
|
|
if (present) {
|
|
|
|
time_t t = time(NULL);
|
|
|
|
if (t > present->StartTime())
|
|
|
|
Current = t - present->StartTime();
|
|
|
|
Total = present->Duration();
|
|
|
|
}
|
|
|
|
DrawSeen(Current, Total);
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
osd->Flush();
|
|
|
|
initial = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- cSkinLCARSDisplayMenu -------------------------------------------------
|
|
|
|
|
|
|
|
class cSkinLCARSDisplayMenu : public cSkinDisplayMenu {
|
|
|
|
private:
|
|
|
|
cOsd *osd;
|
|
|
|
int xa00, xa01, xa02, xa03, xa04, xa05, xa06, xa07, xa08, xa09;
|
|
|
|
int yt00, yt01, yt02, yt03, yt04, yt05, yt06;
|
|
|
|
int yc00, yc01, yc02, yc03, yc04, yc05, yc06, yc07, yc08, yc09, yc10, yc11;
|
|
|
|
int yb00, yb01, yb02, yb03, yb04, yb05, yb06, yb07, yb08, yb09, yb10, yb11, yb12, yb13, yb14, yb15;
|
|
|
|
int xm00, xm01, xm02, xm03, xm04, xm05, xm06, xm07, xm08;
|
|
|
|
int ym00, ym01, ym02, ym03, ym04, ym05, ym06, ym07;
|
|
|
|
int xs00, xs01, xs02, xs03, xs04, xs05, xs06, xs07, xs08, xs09, xs10, xs11, xs12, xs13;
|
|
|
|
int ys00, ys01, ys02, ys03, ys04, ys05;
|
|
|
|
int xi00, xi01, xi02, xi03;
|
|
|
|
int yi00, yi01;
|
|
|
|
int xb00, xb01, xb02, xb03, xb04, xb05, xb06, xb07, xb08, xb09, xb10, xb11, xb12, xb13, xb14, xb15;
|
|
|
|
int xd00, xd01, xd02, xd03, xd04, xd05, xd06, xd07;
|
|
|
|
int yd00, yd01, yd02, yd03, yd04, yd05;
|
|
|
|
int xs; // starting column for signal display
|
|
|
|
int lineHeight;
|
|
|
|
cFont *tinyFont;
|
|
|
|
cFont *tallFont;
|
|
|
|
tColor frameColor;
|
|
|
|
int currentIndex;
|
|
|
|
cVector<int> deviceOffset;
|
|
|
|
cVector<bool> deviceRecording;
|
|
|
|
cString lastDeviceType[MAXDEVICES];
|
|
|
|
cVector<cCamSlot *> lastCamSlot;
|
|
|
|
cVector<int> lastSignalStrength;
|
|
|
|
cVector<int> lastSignalQuality;
|
|
|
|
bool initial;
|
|
|
|
enum eCurrentMode { cmUnknown, cmLive, cmPlay };
|
|
|
|
eCurrentMode lastMode;
|
|
|
|
cString lastDate;
|
|
|
|
int lastDiskUsageState;
|
|
|
|
bool lastDiskAlert;
|
|
|
|
double lastSystemLoad;
|
2015-09-01 11:14:27 +02:00
|
|
|
cStateKey timersStateKey;
|
2012-06-02 13:17:16 +02:00
|
|
|
time_t lastSignalDisplay;
|
|
|
|
int lastLiveIndicatorY;
|
|
|
|
bool lastLiveIndicatorTransferring;
|
|
|
|
const cChannel *lastChannel;
|
|
|
|
const cEvent *lastEvent;
|
|
|
|
const cRecording *lastRecording;
|
|
|
|
cString lastHeader;
|
|
|
|
int lastSeen;
|
|
|
|
static cBitmap bmArrowUp, bmArrowDown, bmTransferMode;
|
|
|
|
void DrawMainFrameUpper(tColor Color);
|
|
|
|
void DrawMainFrameLower(void);
|
|
|
|
void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font);
|
|
|
|
void DrawMenuFrame(void);
|
|
|
|
void DrawMainBracket(void);
|
|
|
|
void DrawStatusElbows(void);
|
|
|
|
void DrawDate(void);
|
|
|
|
void DrawDisk(void);
|
|
|
|
void DrawLoad(void);
|
|
|
|
void DrawFrameDisplay(void);
|
|
|
|
void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown);
|
|
|
|
void DrawTimer(const cTimer *Timer, int y, bool MultiRec);
|
|
|
|
void DrawTimers(void);
|
|
|
|
void DrawDevice(const cDevice *Device);
|
|
|
|
void DrawDevices(void);
|
|
|
|
void DrawLiveIndicator(void);
|
|
|
|
void DrawSignals(void);
|
|
|
|
void DrawLive(const cChannel *Channel);
|
|
|
|
void DrawPlay(cControl *Control);
|
|
|
|
void DrawInfo(const cEvent *Event, bool WithTime);
|
|
|
|
void DrawSeen(int Current, int Total);
|
|
|
|
void DrawTextScrollbar(void);
|
|
|
|
public:
|
|
|
|
cSkinLCARSDisplayMenu(void);
|
|
|
|
virtual ~cSkinLCARSDisplayMenu();
|
|
|
|
virtual void Scroll(bool Up, bool Page);
|
|
|
|
virtual int MaxItems(void);
|
|
|
|
virtual void Clear(void);
|
|
|
|
virtual void SetMenuCategory(eMenuCategory MenuCategory);
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
|
|
|
cBitmap cSkinLCARSDisplayMenu::bmArrowUp(arrowup_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayMenu::bmArrowDown(arrowdown_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayMenu::bmTransferMode(play_xpm);
|
|
|
|
|
|
|
|
cSkinLCARSDisplayMenu::cSkinLCARSDisplayMenu(void)
|
|
|
|
{
|
|
|
|
tallFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize * 1.8);
|
|
|
|
initial = true;
|
|
|
|
lastMode = cmUnknown;
|
|
|
|
lastChannel = NULL;
|
|
|
|
lastEvent = NULL;
|
|
|
|
lastRecording = NULL;
|
|
|
|
lastSeen = -1;
|
|
|
|
lastSignalDisplay = 0;
|
|
|
|
lastLiveIndicatorY = -1;
|
|
|
|
lastLiveIndicatorTransferring = false;
|
|
|
|
lastDiskUsageState = -1;
|
|
|
|
lastDiskAlert = false;
|
|
|
|
lastSystemLoad = -1;
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
lineHeight = font->Height();
|
|
|
|
tinyFont = CreateTinyFont(lineHeight);
|
|
|
|
frameColor = Theme.Color(clrMenuFrameBg);
|
|
|
|
currentIndex = -1;
|
|
|
|
// The outer frame:
|
|
|
|
int d = 5 * lineHeight;
|
|
|
|
xa00 = 0;
|
|
|
|
xa01 = xa00 + d / 2;
|
|
|
|
xa02 = xa00 + d;
|
|
|
|
xa03 = xa02 + lineHeight;
|
|
|
|
xa04 = xa02 + d / 4;
|
|
|
|
xa05 = xa02 + d;
|
|
|
|
xa06 = xa05 + Gap;
|
|
|
|
xa09 = cOsd::OsdWidth();
|
|
|
|
xa08 = xa09 - lineHeight;
|
|
|
|
xa07 = xa08 - Gap;
|
|
|
|
|
|
|
|
yt00 = 0;
|
|
|
|
yt01 = yt00 + lineHeight;
|
|
|
|
yt02 = yt01 + lineHeight;
|
|
|
|
yt03 = yt01 + d / 4;
|
|
|
|
yt04 = yt02 + Gap;
|
|
|
|
yt05 = yt00 + d / 2;
|
|
|
|
yt06 = yt04 + 2 * lineHeight;
|
|
|
|
|
|
|
|
yc00 = yt06 + Gap;
|
|
|
|
yc05 = yc00 + 3 * lineHeight + Gap / 2;
|
|
|
|
yc04 = yc05 - lineHeight;
|
|
|
|
yc03 = yc04 - lineHeight;
|
|
|
|
yc02 = yc04 - d / 4;
|
|
|
|
yc01 = yc05 - d / 2;
|
|
|
|
|
|
|
|
yc06 = yc05 + Gap;
|
|
|
|
yc07 = yc06 + lineHeight;
|
|
|
|
yc08 = yc07 + lineHeight;
|
|
|
|
yc09 = yc07 + d / 4;
|
|
|
|
yc10 = yc06 + d / 2;
|
|
|
|
yc11 = yc06 + 3 * lineHeight + Gap / 2;
|
|
|
|
|
|
|
|
yb00 = yc11 + Gap;
|
|
|
|
yb01 = yb00 + 2 * lineHeight;
|
|
|
|
yb02 = yb01 + Gap;
|
|
|
|
yb03 = yb02 + 2 * lineHeight;
|
|
|
|
yb04 = yb03 + Gap;
|
|
|
|
yb05 = yb04 + 2 * lineHeight;
|
|
|
|
yb06 = yb05 + Gap;
|
|
|
|
yb07 = yb06 + 2 * lineHeight;
|
|
|
|
yb08 = yb07 + Gap;
|
|
|
|
|
|
|
|
yb15 = cOsd::OsdHeight();
|
|
|
|
yb14 = yb15 - lineHeight;
|
|
|
|
yb13 = yb14 - lineHeight;
|
|
|
|
yb12 = yb14 - d / 4;
|
|
|
|
yb11 = yb15 - d / 2;
|
|
|
|
yb10 = yb13 - Gap - 2 * lineHeight;
|
|
|
|
yb09 = yb10 - Gap;
|
|
|
|
|
|
|
|
// Compensate for large font size:
|
|
|
|
if (yb09 - yb08 < 2 * lineHeight) {
|
|
|
|
yb08 = yb06;
|
|
|
|
yb06 = 0; // drop empty rectangle
|
|
|
|
}
|
|
|
|
if (yb09 - yb08 < 2 * lineHeight) {
|
|
|
|
yb05 = yb09;
|
|
|
|
yb08 = 0; // drop "LCARS" display
|
|
|
|
}
|
|
|
|
if (yb05 - yb04 < 2 * lineHeight) {
|
|
|
|
yb03 = yb09;
|
|
|
|
yb04 = 0; // drop "LOAD" display
|
|
|
|
}
|
|
|
|
if (yb03 - yb02 < 2 * lineHeight) {
|
|
|
|
yb01 = yb09;
|
|
|
|
yb02 = 0; // drop "DISK" display
|
|
|
|
}
|
|
|
|
// Anything else is just insanely large...
|
|
|
|
|
|
|
|
// The main command menu:
|
|
|
|
xm00 = xa03;
|
|
|
|
xm01 = xa05;
|
|
|
|
xm02 = xa06;
|
|
|
|
xm08 = (xa09 + xa00) / 2;
|
|
|
|
xm07 = xm08 - lineHeight;
|
|
|
|
xm06 = xm07 - lineHeight / 2;
|
|
|
|
xm05 = xm06 - lineHeight / 2;
|
|
|
|
xm04 = xm05 - lineHeight;
|
|
|
|
xm03 = xm04 - Gap;
|
|
|
|
ym00 = yc08;
|
|
|
|
ym01 = ym00 + lineHeight / 2;
|
|
|
|
ym02 = ym01 + lineHeight / 2;
|
|
|
|
ym03 = ym02 + Gap;
|
|
|
|
ym07 = yb15;
|
|
|
|
ym06 = ym07 - lineHeight / 2;
|
|
|
|
ym05 = ym06 - lineHeight / 2;
|
|
|
|
ym04 = ym05 - Gap;
|
|
|
|
|
|
|
|
// The status area:
|
|
|
|
xs00 = xm08 + Gap + lineHeight + Gap;
|
|
|
|
xs13 = xa09;
|
|
|
|
xs12 = xa08;
|
|
|
|
xs11 = xa07;
|
|
|
|
xs05 = (xs00 + xs11 + Gap) / 2;
|
|
|
|
xs04 = xs05 - lineHeight / 2;
|
|
|
|
xs03 = xs04 - lineHeight / 2;
|
|
|
|
xs02 = xs03 - 2 * lineHeight;
|
|
|
|
xs01 = xs02 - Gap;
|
|
|
|
xs06 = xs05 + Gap;
|
|
|
|
xs07 = xs06 + lineHeight / 2;
|
|
|
|
xs08 = xs07 + lineHeight / 2;
|
|
|
|
xs09 = xs08 + 2 * lineHeight;
|
|
|
|
xs10 = xs09 + Gap;
|
|
|
|
ys00 = yc06;
|
|
|
|
ys01 = ys00 + lineHeight;
|
|
|
|
ys02 = ys01 + lineHeight / 2;
|
|
|
|
ys04 = ys01 + lineHeight;
|
|
|
|
ys03 = ys04 - Gap;
|
|
|
|
ys05 = yb15;
|
|
|
|
|
2013-11-16 13:26:55 +01:00
|
|
|
// The item area (just to have them initialized, actual setting will be done in SetMenuCategory():
|
|
|
|
|
|
|
|
xi00 = 0;
|
|
|
|
xi01 = 0;
|
|
|
|
xi02 = 0;
|
|
|
|
xi03 = 1;
|
|
|
|
yi00 = 0;
|
|
|
|
yi01 = 1;
|
|
|
|
|
2012-06-02 13:17:16 +02:00
|
|
|
// The color buttons in submenus:
|
|
|
|
xb00 = xa06;
|
|
|
|
xb15 = xa07;
|
|
|
|
int w = (xa08 - xa06) / 4;
|
|
|
|
xb01 = xb00 + lineHeight / 2;
|
|
|
|
xb02 = xb01 + Gap;
|
|
|
|
xb04 = xb00 + w;
|
|
|
|
xb03 = xb04 - Gap;
|
|
|
|
xb05 = xb04 + lineHeight / 2;
|
|
|
|
xb06 = xb05 + Gap;
|
|
|
|
xb08 = xb04 + w;
|
|
|
|
xb07 = xb08 - Gap;
|
|
|
|
xb09 = xb08 + lineHeight / 2;
|
|
|
|
xb10 = xb09 + Gap;
|
|
|
|
xb12 = xb08 + w;
|
|
|
|
xb11 = xb12 - Gap;
|
|
|
|
xb13 = xb12 + lineHeight / 2;
|
2013-04-09 11:10:30 +02:00
|
|
|
xb14 = xb13 + Gap;
|
2012-06-02 13:17:16 +02:00
|
|
|
|
|
|
|
// The color buttons in the main menu:
|
|
|
|
int r = lineHeight;
|
|
|
|
xd07 = xa09;
|
|
|
|
xd06 = xd07 - r;
|
|
|
|
xd05 = xd06 - 4 * r;
|
|
|
|
xd04 = xd05 - r;
|
|
|
|
xd03 = xd04 - Gap;
|
|
|
|
xd02 = xd03 - r;
|
|
|
|
xd01 = xd02 - 4 * r;
|
|
|
|
xd00 = xd01 - r;
|
|
|
|
yd00 = yt00;
|
|
|
|
yd05 = yc04 - Gap;
|
|
|
|
yd04 = yd05 - 2 * r;
|
|
|
|
yd03 = yd04 - Gap;
|
|
|
|
yd02 = yd03 - 2 * r;
|
|
|
|
yd01 = yd02 - Gap;
|
|
|
|
|
|
|
|
xs = 0;
|
|
|
|
|
|
|
|
osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop(), xa00, yt00, xa09 - 1, yb15 - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinLCARSDisplayMenu::~cSkinLCARSDisplayMenu()
|
|
|
|
{
|
|
|
|
delete tallFont;
|
|
|
|
delete tinyFont;
|
|
|
|
delete osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetMenuCategory(eMenuCategory MenuCategory)
|
|
|
|
{
|
|
|
|
if (initial || MenuCategory != cSkinDisplayMenu::MenuCategory()) {
|
|
|
|
cSkinDisplayMenu::SetMenuCategory(MenuCategory);
|
|
|
|
initial = true;
|
|
|
|
osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, Theme.Color(clrBackground));
|
|
|
|
if (MenuCategory == mcMain) {
|
|
|
|
yi00 = ym03;
|
|
|
|
yi01 = ym04;
|
|
|
|
xi00 = xm00;
|
|
|
|
xi01 = xm03;
|
|
|
|
xi02 = xm04;
|
|
|
|
xi03 = xm05;
|
2015-09-01 11:14:27 +02:00
|
|
|
timersStateKey.Reset();
|
2012-06-02 13:17:16 +02:00
|
|
|
DrawMainFrameLower();
|
|
|
|
DrawMainBracket();
|
|
|
|
DrawStatusElbows();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
yi00 = yt02;
|
|
|
|
yi01 = yb13;
|
|
|
|
xi00 = xa03;
|
|
|
|
xi01 = xa07;
|
|
|
|
xi02 = xa08;
|
|
|
|
xi03 = xa09;
|
|
|
|
DrawMenuFrame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawMainFrameUpper(tColor Color)
|
|
|
|
{
|
|
|
|
// Top left rectangles:
|
|
|
|
osd->DrawRectangle(xa00, yt00, xa02 - 1, yt02 - 1, Color);
|
|
|
|
osd->DrawRectangle(xa00, yt04, xa02 - 1, yt06 - 1, Color);
|
|
|
|
// Upper elbow:
|
|
|
|
osd->DrawRectangle(xa00, yc00, xa01 - 1, yc01 - 1, Color);
|
|
|
|
osd->DrawEllipse (xa00, yc01, xa01 - 1, yc05 - 1, Color, 3);
|
|
|
|
osd->DrawRectangle(xa01, yc00, xa02 - 1, yc05 - 1, Color);
|
|
|
|
osd->DrawEllipse (xa02, yc02, xa04 - 1, yc04 - 1, Color, -3);
|
|
|
|
osd->DrawRectangle(xa02, yc04, xa05 - 1, yc05 - 1, Color);
|
|
|
|
// Upper delimiter:
|
|
|
|
osd->DrawRectangle(xa06, yc04 + lineHeight / 2, xm08 - 1, yc05 - 1, Color);
|
|
|
|
osd->DrawRectangle(xm08 + Gap, yc04, xs00 - Gap - 1, yc05 - 1, Color);
|
|
|
|
osd->DrawRectangle(xs00, yc04, xs05 - 1, yc05 - 1, Color);
|
|
|
|
osd->DrawRectangle(xs06, yc04, xa07 - 1, yc05 - 1, Color);
|
|
|
|
osd->DrawRectangle(xa08, yc04, xa09 - 1, yc05 - 1, Color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawMainFrameLower(void)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
// Lower elbow:
|
|
|
|
osd->DrawRectangle(xa00, yc10, xa01 - 1, yc11 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xa00, yc06, xa01 - 1, yc10 - 1, frameColor, 2);
|
|
|
|
osd->DrawRectangle(xa01, yc06, xa02 - 1, yc11 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xa02, yc07, xa04 - 1, yc09 - 1, frameColor, -2);
|
|
|
|
osd->DrawRectangle(xa02, yc06, xa05 - 1, yc07 - 1, frameColor);
|
|
|
|
// Lower delimiter:
|
|
|
|
osd->DrawRectangle(xa06, yc06, xm08 - 1, yc07 - lineHeight / 2 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa08, yc06, xa09 - 1, yc07 - 1, frameColor);
|
|
|
|
// VDR version:
|
|
|
|
osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor);
|
|
|
|
osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
|
|
|
|
osd->DrawText(xa00, yb15 - lineHeight, VDRVERSION, Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font)
|
|
|
|
{
|
|
|
|
int h = y1 - y0;
|
|
|
|
osd->DrawEllipse(x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
|
2012-06-07 10:41:53 +02:00
|
|
|
osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taBottom | taRight);
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawEllipse(x2, y0, x3 - 1, y1 - 1, ColorBg, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawMenuFrame(void)
|
|
|
|
{
|
|
|
|
// Upper elbow:
|
|
|
|
osd->DrawRectangle(xa00, yt05, xa01 - 1, yt06 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa00, yt00, xa01 - 1, yt05 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xa00, yt00, xa01 - 1, yt05 - 1, frameColor, 2);
|
|
|
|
osd->DrawRectangle(xa01, yt00, xa02 - 1, yt06 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xa02, yt01, xa04 - 1, yt03 - 1, frameColor, -2);
|
|
|
|
osd->DrawRectangle(xa02, yt00, xa05 - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa06, yt00, xa07 - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa08, yt00, xa08 + lineHeight / 2 - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa08 + lineHeight / 2, yt00, xa09 - 1, yt00 + lineHeight / 2 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xa08 + lineHeight / 2, yt00, xa09 - 1, yt01 - 1, frameColor, 5);
|
|
|
|
// Center part:
|
|
|
|
osd->DrawRectangle(xa00, yc00, xa02 - 1, yc11 - 1, frameColor);
|
|
|
|
// Lower elbow:
|
|
|
|
osd->DrawRectangle(xa00, yb10, xa02 - 1, yb11 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa00, yb11, xa01 - 1, yb15 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xa00, yb11, xa01 - 1, yb15 - 1, frameColor, 3);
|
|
|
|
osd->DrawRectangle(xa01, yb11, xa02 - 1, yb15 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xa02, yb12, xa04 - 1, yb14 - 1, frameColor, -3);
|
|
|
|
osd->DrawRectangle(xa02, yb14, xa05 - 1, yb15 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa08, yb14, xa08 + lineHeight / 2 - 1, yb15 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xa08 + lineHeight / 2, yb14 + lineHeight / 2, xa09 - 1, yb15 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xa08 + lineHeight / 2, yb14, xa09 - 1, yb15 - 1, frameColor, 5);
|
|
|
|
osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
|
|
|
|
// Color buttons:
|
2012-09-09 14:37:15 +02:00
|
|
|
tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
|
|
|
|
osd->DrawRectangle(xb00, yb14, xb01 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey0]));
|
|
|
|
osd->DrawRectangle(xb04, yb14, xb05 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey1]));
|
|
|
|
osd->DrawRectangle(xb08, yb14, xb09 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey2]));
|
|
|
|
osd->DrawRectangle(xb12, yb14, xb13 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey3]));
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawDate(void)
|
|
|
|
{
|
|
|
|
cString s = DayDateTime();
|
2014-06-12 08:55:32 +02:00
|
|
|
if (initial || !*lastDate || strcmp(s, lastDate)) {
|
2012-06-02 13:17:16 +02:00
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
tColor ColorFg = Theme.Color(clrDateFg);
|
|
|
|
tColor ColorBg = Theme.Color(clrDateBg);
|
|
|
|
lastDate = s;
|
|
|
|
const char *t = strrchr(s, ' ');
|
|
|
|
osd->DrawText(xa00, yb01 - lineHeight, t, ColorFg, ColorBg, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
s.Truncate(t - s);
|
|
|
|
osd->DrawText(xa00, yb00, s, ColorFg, ColorBg, font, xa02 - xa00, yb01 - yb00 - lineHeight, taTop | taRight | taBorder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawDisk(void)
|
|
|
|
{
|
|
|
|
if (yb02) {
|
|
|
|
if (cVideoDiskUsage::HasChanged(lastDiskUsageState) || initial) { // must call HasChanged() first, or it shows an outdated value in the 'initial' case!
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int DiskUsage = cVideoDiskUsage::UsedPercent();
|
|
|
|
bool DiskAlert = DiskUsage > DISKUSAGEALERTLIMIT;
|
|
|
|
tColor ColorFg = DiskAlert ? Theme.Color(clrAlertFg) : Theme.Color(clrMenuFrameFg);
|
|
|
|
tColor ColorBg = DiskAlert ? Theme.Color(clrAlertBg) : frameColor;
|
|
|
|
if (initial || DiskAlert != lastDiskAlert)
|
|
|
|
osd->DrawText(xa00, yb02, tr("DISK"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb03 - yb02, taTop | taLeft | taBorder);
|
|
|
|
osd->DrawText(xa01, yb02, itoa(DiskUsage), ColorFg, ColorBg, font, xa02 - xa01, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
osd->DrawText(xa00, yb03 - lineHeight, cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60), ColorFg, ColorBg, font, xa02 - xa00, 0, taBottom | taRight | taBorder);
|
|
|
|
lastDiskAlert = DiskAlert;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawLoad(void)
|
|
|
|
{
|
|
|
|
if (yb04) {
|
|
|
|
tColor ColorFg = Theme.Color(clrMenuFrameFg);
|
|
|
|
tColor ColorBg = frameColor;
|
|
|
|
if (initial)
|
|
|
|
osd->DrawText(xa00, yb04, tr("LOAD"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb05 - yb04, taTop | taLeft | taBorder);
|
|
|
|
double SystemLoad;
|
|
|
|
if (getloadavg(&SystemLoad, 1) > 0) {
|
|
|
|
if (initial || SystemLoad != lastSystemLoad) {
|
|
|
|
osd->DrawText(xa00, yb05 - lineHeight, cString::sprintf("%.1f", SystemLoad), ColorFg, ColorBg, cFont::GetFont(fontOsd), xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
lastSystemLoad = SystemLoad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawMainBracket(void)
|
|
|
|
{
|
|
|
|
tColor Color = Theme.Color(clrMenuMainBracket);
|
|
|
|
osd->DrawRectangle(xm00, ym00, xm01 - 1, ym01 - 1, Color);
|
|
|
|
osd->DrawRectangle(xm02, ym00, xm07 - 1, ym01 - 1, Color);
|
|
|
|
osd->DrawEllipse (xm07, ym00, xm08 - 1, ym02 - 1, Color, 1);
|
|
|
|
osd->DrawEllipse (xm06, ym01, xm07 - 1, ym02 - 1, Color, -1);
|
|
|
|
osd->DrawRectangle(xm07, ym03, xm08 - 1, ym04 - 1, Color);
|
|
|
|
osd->DrawEllipse (xm06, ym05, xm07 - 1, ym06 - 1, Color, -4);
|
|
|
|
osd->DrawEllipse (xm07, ym05, xm08 - 1, ym07 - 1, Color, 4);
|
|
|
|
osd->DrawRectangle(xm02, ym06, xm07 - 1, ym07 - 1, Color);
|
|
|
|
osd->DrawRectangle(xm00, ym06, xm01 - 1, ym07 - 1, Color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawStatusElbows(void)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
osd->DrawText (xs00, ys00, tr("TIMERS"), Theme.Color(clrMenuFrameFg), frameColor, font, xs01 - xs00, lineHeight, taBottom | taLeft | taBorder);
|
|
|
|
osd->DrawRectangle(xs02, ys00, xs03 - 1, ys01 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xs03, ys00, xs05 - 1, ys01 - 1, frameColor, 1);
|
|
|
|
osd->DrawEllipse (xs03, ys01, xs04 - 1, ys02 - 1, frameColor, -1);
|
|
|
|
osd->DrawRectangle(xs04, ys01, xs05 - 1, ys03 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xs04, ys04, xs05 - 1, ys05 - 1, frameColor);
|
|
|
|
osd->DrawText (xs10, ys00, tr("DEVICES"), Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs10, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
osd->DrawRectangle(xs08, ys00, xs09 - 1, ys01 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xs06, ys00, xs08 - 1, ys01 - 1, frameColor, 2);
|
|
|
|
osd->DrawEllipse (xs07, ys01, xs08 - 1, ys02 - 1, frameColor, -2);
|
|
|
|
osd->DrawRectangle(xs06, ys01, xs07 - 1, ys03 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xs06, ys04, xs07 - 1, ys05 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawFrameDisplay(void)
|
|
|
|
{
|
|
|
|
DrawDate();
|
|
|
|
DrawDisk();
|
|
|
|
DrawLoad();
|
|
|
|
if (initial) {
|
|
|
|
if (yb06)
|
|
|
|
osd->DrawRectangle(xa00, yb06, xa02 - 1, yb07 - 1, frameColor);
|
|
|
|
if (yb08) {
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
osd->DrawRectangle(xa00, yb08, xa02 - 1, yb09 - 1, frameColor);
|
|
|
|
osd->DrawText(xa00, yb09 - lineHeight, "LCARS", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown)
|
|
|
|
{
|
|
|
|
int x0, x1, tt, tb;
|
|
|
|
tColor ClearColor;
|
|
|
|
if (MenuCategory() == mcMain) {
|
|
|
|
x0 = xm07;
|
|
|
|
x1 = xm08;
|
|
|
|
tt = ym03;
|
|
|
|
tb = ym04;
|
|
|
|
ClearColor = Theme.Color(clrMenuMainBracket);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
x0 = xa02 + Gap;
|
|
|
|
x1 = x0 + lineHeight / 2;
|
|
|
|
tt = yc00;
|
|
|
|
tb = yc11;
|
|
|
|
ClearColor = Theme.Color(clrBackground);
|
|
|
|
int d = TextFrame;
|
|
|
|
if (CanScrollUp)
|
|
|
|
osd->DrawBitmap(xa02 - bmArrowUp.Width() - d, yc00 + d, bmArrowUp, Theme.Color(clrMenuScrollbarArrow), frameColor);
|
|
|
|
else
|
|
|
|
osd->DrawRectangle(xa02 - bmArrowUp.Width() - d, yc00 + d, xa02 - d - 1, yc00 + d + bmArrowUp.Height() - 1, frameColor);
|
|
|
|
if (CanScrollDown)
|
|
|
|
osd->DrawBitmap(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), bmArrowDown, Theme.Color(clrMenuScrollbarArrow), frameColor);
|
|
|
|
else
|
|
|
|
osd->DrawRectangle(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), xa02 - d - 1, yc11 - d - 1, frameColor);
|
|
|
|
}
|
|
|
|
if (Total > 0 && Total > Shown) {
|
|
|
|
int sw = x1 - x0;
|
|
|
|
int sh = max(int((tb - tt) * double(Shown) / Total + 0.5), sw);
|
|
|
|
int st = min(int(tt + (tb - tt) * double(Offset) / Total + 0.5), tb - sh);
|
|
|
|
int sb = min(st + sh, tb);
|
|
|
|
osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, Theme.Color(clrMenuScrollbarTotal));
|
|
|
|
osd->DrawRectangle(x0, st, x1 - 1, sb - 1, Theme.Color(clrMenuScrollbarShown));
|
|
|
|
}
|
|
|
|
else if (MenuCategory() != mcMain)
|
|
|
|
osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, ClearColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawTimer(const cTimer *Timer, int y, bool MultiRec)
|
|
|
|
{
|
|
|
|
// The timer data:
|
|
|
|
bool Alert = !Timer->Recording() && Timer->Pending();
|
|
|
|
tColor ColorFg = Alert ? Theme.Color(clrAlertFg) : Theme.Color(clrTimerFg);
|
2013-02-15 15:12:24 +01:00
|
|
|
tColor ColorBg = Alert ? Theme.Color(clrAlertBg) : Theme.Color(clrTimerBg);
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawRectangle(xs00, y, xs03 - 1, y + lineHeight - 1, ColorBg);
|
|
|
|
cString Date;
|
|
|
|
if (Timer->Recording())
|
|
|
|
Date = cString::sprintf("-%s", *TimeString(Timer->StopTime()));
|
|
|
|
else {
|
|
|
|
time_t Now = time(NULL);
|
|
|
|
cString Today = WeekDayName(Now);
|
|
|
|
cString Time = TimeString(Timer->StartTime());
|
|
|
|
cString Day = WeekDayName(Timer->StartTime());
|
|
|
|
if (Timer->StartTime() > Now + 6 * SECSINDAY)
|
|
|
|
Date = DayDateTime(Timer->StartTime());
|
|
|
|
else if (strcmp(Day, Today) != 0)
|
|
|
|
Date = cString::sprintf("%s %s", *Day, *Time);
|
|
|
|
else
|
|
|
|
Date = Time;
|
|
|
|
}
|
|
|
|
if (Timer->Flags() & tfVps)
|
|
|
|
Date = cString::sprintf("VPS %s", *Date);
|
|
|
|
const cChannel *Channel = Timer->Channel();
|
|
|
|
const cEvent *Event = Timer->Event();
|
|
|
|
int d = max(TextFrame / 2, 1);
|
|
|
|
if (Channel) {
|
|
|
|
osd->DrawText(xs00 + d, y, Channel->Name(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - d);
|
|
|
|
osd->DrawText(xs03 - tinyFont->Width(Date) - d, y, Date, ColorFg, ColorBg, tinyFont);
|
|
|
|
}
|
|
|
|
if (Event)
|
|
|
|
osd->DrawText(xs00 + d, y + lineHeight - tinyFont->Height(), Event->Title(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - 2 * d);
|
2015-09-01 11:14:27 +02:00
|
|
|
// The remote timer indicator:
|
|
|
|
if (Timer->Remote())
|
|
|
|
osd->DrawRectangle(xs00 - (lineHeight - Gap) / 2, y, xs00 - Gap - 1, y + lineHeight - 1, Timer->Recording() ? Theme.Color(clrMenuTimerRecording) : ColorBg);
|
2012-06-02 13:17:16 +02:00
|
|
|
// The timer recording indicator:
|
2015-09-01 11:14:27 +02:00
|
|
|
else if (Timer->Recording())
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording));
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawTimers(void)
|
|
|
|
{
|
2015-09-01 11:14:27 +02:00
|
|
|
if (const cTimers *Timers = cTimers::GetTimersRead(timersStateKey)) {
|
2012-06-02 13:17:16 +02:00
|
|
|
deviceRecording.Clear();
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
2015-09-01 11:14:27 +02:00
|
|
|
osd->DrawRectangle(xs00 - (lineHeight - Gap) / 2, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground));
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawRectangle(xs07, ys04, xs13 - 1, ys05 - 1, Theme.Color(clrBackground));
|
2015-09-01 11:14:27 +02:00
|
|
|
cSortedTimers SortedTimers(Timers);
|
2012-06-02 13:17:16 +02:00
|
|
|
cVector<int> FreeDeviceSlots;
|
2012-06-07 11:43:35 +02:00
|
|
|
int NumDevices = 0;
|
2012-06-02 13:17:16 +02:00
|
|
|
int y = ys04;
|
|
|
|
// Timers and recording devices:
|
|
|
|
while (1) {
|
|
|
|
int NumTimers = 0;
|
|
|
|
const cDevice *Device = NULL;
|
|
|
|
for (int i = 0; i < SortedTimers.Size(); i++) {
|
|
|
|
if (y + lineHeight > ys05)
|
|
|
|
break;
|
|
|
|
if (const cTimer *Timer = SortedTimers[i]) {
|
|
|
|
if (Timer->Recording()) {
|
2015-09-01 11:14:27 +02:00
|
|
|
if (Timer->Remote()) {
|
|
|
|
if (!Device && Timer->HasFlags(tfActive)) {
|
|
|
|
DrawTimer(Timer, y, false);
|
|
|
|
FreeDeviceSlots.Append(y);
|
|
|
|
y += lineHeight + Gap;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) {
|
2012-06-02 13:17:16 +02:00
|
|
|
if (!Device || Device == RecordControl->Device()) {
|
|
|
|
DrawTimer(Timer, y, NumTimers > 0);
|
|
|
|
NumTimers++;
|
|
|
|
if (!Device) {
|
|
|
|
Device = RecordControl->Device();
|
|
|
|
deviceOffset[Device->DeviceNumber()] = y;
|
|
|
|
deviceRecording[Device->DeviceNumber()] = true;
|
2012-06-07 11:43:35 +02:00
|
|
|
NumDevices++;
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
FreeDeviceSlots.Append(y);
|
|
|
|
y += lineHeight + Gap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
SortedTimers[i] = NULL;
|
|
|
|
}
|
2012-06-08 10:29:03 +02:00
|
|
|
else if (!Device && Timer->HasFlags(tfActive)) {
|
2012-06-02 13:17:16 +02:00
|
|
|
DrawTimer(Timer, y, false);
|
|
|
|
FreeDeviceSlots.Append(y);
|
|
|
|
y += lineHeight + Gap;
|
|
|
|
SortedTimers[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!Device)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Devices currently not recording:
|
|
|
|
int Slot = 0;
|
|
|
|
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
|
|
|
if (const cDevice *Device = cDevice::GetDevice(i)) {
|
2012-06-04 08:09:19 +02:00
|
|
|
if (Device->NumProvidedSystems()) {
|
|
|
|
if (!deviceRecording[Device->DeviceNumber()]) {
|
|
|
|
if (Slot < FreeDeviceSlots.Size()) {
|
|
|
|
y = FreeDeviceSlots[Slot];
|
|
|
|
Slot++;
|
|
|
|
}
|
|
|
|
if (y + lineHeight > ys05)
|
|
|
|
break;
|
|
|
|
deviceOffset[Device->DeviceNumber()] = y;
|
|
|
|
y += lineHeight + Gap;
|
2012-06-07 11:43:35 +02:00
|
|
|
NumDevices++;
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-08 10:29:03 +02:00
|
|
|
// Total number of active timers:
|
|
|
|
int NumTimers = 0;
|
2015-09-01 11:14:27 +02:00
|
|
|
for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
|
2012-06-08 10:29:03 +02:00
|
|
|
if (Timer->HasFlags(tfActive))
|
|
|
|
NumTimers++;
|
|
|
|
}
|
|
|
|
osd->DrawText(xs02, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder);
|
2012-06-07 11:43:35 +02:00
|
|
|
osd->DrawText(xs08, ys00, itoa(NumDevices), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder);
|
2012-06-02 13:17:16 +02:00
|
|
|
lastSignalDisplay = 0;
|
|
|
|
initial = true; // forces redrawing of devices
|
2015-09-01 11:14:27 +02:00
|
|
|
timersStateKey.Remove();
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawDevice(const cDevice *Device)
|
|
|
|
{
|
|
|
|
int dn = Device->DeviceNumber();
|
|
|
|
int y = deviceOffset[dn];
|
|
|
|
if (y + lineHeight <= ys05) {
|
|
|
|
if (DrawDeviceData(osd, Device, xs08, y, xs11, y + lineHeight, xs, tinyFont, lastDeviceType[dn], lastCamSlot[dn], initial)) {
|
|
|
|
// Make sure signal meters are redrawn:
|
|
|
|
lastSignalStrength[dn] = -1;
|
|
|
|
lastSignalQuality[dn] = -1;
|
|
|
|
lastSignalDisplay = 0;
|
|
|
|
}
|
|
|
|
// The device recording indicator:
|
|
|
|
if (deviceRecording[dn])
|
|
|
|
osd->DrawRectangle(xs07 + Gap / 2, y, xs08 - Gap - 1, y + lineHeight - 1, Theme.Color(clrMenuDeviceRecording));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawDevices(void)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
2012-06-04 08:09:19 +02:00
|
|
|
if (const cDevice *Device = cDevice::GetDevice(i)) {
|
|
|
|
if (Device->NumProvidedSystems())
|
|
|
|
DrawDevice(Device);
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawLiveIndicator(void)
|
|
|
|
{
|
|
|
|
cDevice *Device = cDevice::PrimaryDevice();
|
|
|
|
int y = -1;
|
|
|
|
bool Transferring = Device->Transferring();
|
|
|
|
if (!Device->Replaying() || Transferring)
|
|
|
|
y = deviceOffset[cDevice::ActualDevice()->DeviceNumber()];
|
|
|
|
if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) {
|
|
|
|
if (lastLiveIndicatorY >= 0)
|
|
|
|
osd->DrawRectangle(xs12, lastLiveIndicatorY, xs13 - 1, lastLiveIndicatorY + lineHeight - 1, Theme.Color(clrBackground));
|
2014-03-10 12:09:52 +01:00
|
|
|
if (y > 0) {
|
2012-06-04 07:54:51 +02:00
|
|
|
tColor ColorBg = Theme.Color(clrChannelFrameBg);
|
|
|
|
osd->DrawRectangle(xs12, y, xs12 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
|
|
|
|
osd->DrawEllipse (xs12 + lineHeight / 2, y, xs13 - 1, y + lineHeight - 1, ColorBg, 5);
|
2012-06-04 08:59:10 +02:00
|
|
|
if (Transferring) {
|
|
|
|
int w = bmTransferMode.Width();
|
|
|
|
int h = bmTransferMode.Height();
|
|
|
|
int b = w * w + h * h; // the diagonal of the bitmap (squared)
|
|
|
|
int c = lineHeight * lineHeight; // the diameter of the circle (squared)
|
|
|
|
const cBitmap *bm = &bmTransferMode;
|
|
|
|
if (b > c) {
|
|
|
|
// the bitmap doesn't fit, so scale it down:
|
|
|
|
double f = sqrt(double(c) / (2 * b));
|
|
|
|
bm = bmTransferMode.Scaled(f, f);
|
|
|
|
}
|
|
|
|
osd->DrawBitmap((xs12 + xs13 - bm->Width()) / 2, y + (lineHeight - bm->Height()) / 2, *bm, Theme.Color(clrChannelFrameFg), ColorBg);
|
|
|
|
if (bm != &bmTransferMode)
|
|
|
|
delete bm;
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
lastLiveIndicatorY = y;
|
|
|
|
lastLiveIndicatorTransferring = Transferring;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawSignals(void)
|
|
|
|
{
|
|
|
|
time_t Now = time(NULL);
|
|
|
|
if (initial || Now - lastSignalDisplay >= SIGNALDISPLAYDELTA) {
|
|
|
|
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
|
|
|
if (const cDevice *Device = cDevice::GetDevice(i)) {
|
2012-06-04 08:09:19 +02:00
|
|
|
if (Device->NumProvidedSystems()) {
|
|
|
|
if (int y = deviceOffset[i])
|
|
|
|
DrawDeviceSignal(osd, Device, xs + lineHeight / 2, y, xs11, y + lineHeight, lastSignalStrength[i], lastSignalQuality[i], initial);
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
lastSignalDisplay = Now;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawLive(const cChannel *Channel)
|
|
|
|
{
|
|
|
|
if (lastMode != cmLive) {
|
|
|
|
initial = true;
|
|
|
|
lastMode = cmLive;
|
|
|
|
}
|
|
|
|
if (initial) {
|
|
|
|
DrawMainFrameUpper(Theme.Color(clrChannelFrameBg));
|
|
|
|
osd->DrawText(xd00, yd00, tr("LIVE"), Theme.Color(clrChannelFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
|
|
|
|
}
|
2013-05-19 12:07:07 +02:00
|
|
|
if (!Channel)
|
|
|
|
return;
|
2012-06-02 13:17:16 +02:00
|
|
|
if (initial || Channel != lastChannel) {
|
|
|
|
osd->DrawText(xa00, yt00, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt02 - yt00, taTop | taRight | taBorder);
|
|
|
|
osd->DrawText(xa03, yt00, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
|
2013-08-21 11:02:52 +02:00
|
|
|
int x = xa00 + (yc03 - yc02); // compensate for the arc
|
|
|
|
osd->DrawText(x, yc00, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), cFont::GetFont(fontOsd), xa02 - x, yc03 - yc00, taTop | taRight | taBorder);
|
2012-06-02 13:17:16 +02:00
|
|
|
lastChannel = Channel;
|
2013-01-25 14:57:30 +01:00
|
|
|
DrawSeen(0, 0);
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
// The current programme:
|
2015-09-01 11:14:27 +02:00
|
|
|
LOCK_SCHEDULES_READ;
|
|
|
|
if (const cSchedule *Schedule = Schedules->GetSchedule(Channel)) {
|
|
|
|
const cEvent *Event = Schedule->GetPresentEvent();
|
|
|
|
if (initial || Event != lastEvent) {
|
|
|
|
DrawInfo(Event, true);
|
|
|
|
lastEvent = Event;
|
|
|
|
lastSeen = -1;
|
|
|
|
}
|
|
|
|
int Current = 0;
|
|
|
|
int Total = 0;
|
|
|
|
if (Event) {
|
|
|
|
time_t t = time(NULL);
|
|
|
|
if (t > Event->StartTime())
|
|
|
|
Current = t - Event->StartTime();
|
|
|
|
Total = Event->Duration();
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
2015-09-01 11:14:27 +02:00
|
|
|
DrawSeen(Current, Total);
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawPlay(cControl *Control)
|
|
|
|
{
|
|
|
|
if (lastMode != cmPlay) {
|
|
|
|
initial = true;
|
|
|
|
lastMode = cmPlay;
|
|
|
|
}
|
|
|
|
if (initial) {
|
|
|
|
DrawMainFrameUpper(Theme.Color(clrReplayFrameBg));
|
|
|
|
osd->DrawText(xd00, yd00, tr("PLAY"), Theme.Color(clrReplayFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
|
|
|
|
}
|
|
|
|
// The current progress:
|
|
|
|
int Current = 0;
|
|
|
|
int Total = 0;
|
|
|
|
if (Control->GetIndex(Current, Total))
|
|
|
|
DrawSeen(Current, Total);
|
|
|
|
// The current programme:
|
|
|
|
if (const cRecording *Recording = Control->GetRecording()) {
|
|
|
|
if (initial || Recording != lastRecording) {
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
if (const cRecordingInfo *Info = Recording->Info()) {
|
|
|
|
osd->DrawText(xa03, yt00, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
|
|
|
|
DrawInfo(Info->GetEvent(), false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03, 0, taTop | taLeft);
|
|
|
|
osd->DrawText(xa00, yt04, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder);
|
|
|
|
osd->DrawText(xa00, yt06 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taBottom | taRight | taBorder);
|
|
|
|
lastRecording = Recording;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cString Header = Control->GetHeader();
|
|
|
|
if (!*lastHeader || strcmp(Header, lastHeader)) {
|
|
|
|
osd->DrawText(xa03, yt00, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
|
|
|
|
lastHeader = Header;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime)
|
|
|
|
{
|
|
|
|
if (Event) {
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int y = yt04;
|
|
|
|
osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03 - lineHeight, lineHeight, taBottom | taLeft);
|
|
|
|
y += lineHeight;
|
|
|
|
osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd00 - xa03 - lineHeight, lineHeight, taTop | taLeft);
|
|
|
|
if (WithTime) {
|
|
|
|
osd->DrawText(xa00, yt04, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder);
|
|
|
|
osd->DrawText(xa00, yt06 - lineHeight, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawSeen(int Current, int Total)
|
|
|
|
{
|
2013-01-25 14:57:30 +01:00
|
|
|
int Seen = (Total > 0) ? min(xm08 - xm02, int((xm08 - xm02) * double(Current) / Total)) : 0;
|
2012-06-02 13:17:16 +02:00
|
|
|
if (initial || Seen != lastSeen) {
|
|
|
|
int y0 = yc04 - ShowSeenExtent;
|
|
|
|
int y1 = yc04 + lineHeight / 2 - Gap / 2;
|
|
|
|
osd->DrawRectangle(xm02, y0, xm02 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
|
|
|
|
osd->DrawRectangle(xm02 + Seen, y0, xm08 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
lastSeen = Seen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::DrawTextScrollbar(void)
|
|
|
|
{
|
|
|
|
if (textScroller.CanScroll())
|
|
|
|
DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.CanScrollUp(), textScroller.CanScrollDown());
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::Scroll(bool Up, bool Page)
|
|
|
|
{
|
|
|
|
cSkinDisplayMenu::Scroll(Up, Page);
|
|
|
|
DrawTextScrollbar();
|
|
|
|
}
|
|
|
|
|
|
|
|
int cSkinLCARSDisplayMenu::MaxItems(void)
|
|
|
|
{
|
|
|
|
if (MenuCategory() == mcMain)
|
|
|
|
return (ym04 - ym03) / lineHeight;
|
|
|
|
else
|
|
|
|
return (yb13 - yt02) / lineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::Clear(void)
|
|
|
|
{
|
|
|
|
textScroller.Reset();
|
|
|
|
osd->DrawRectangle(xi00, yi00, xi03 - 1, yi01 - 1, Theme.Color(clrBackground));
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetTitle(const char *Title)
|
|
|
|
{
|
|
|
|
if (MenuCategory() != mcMain) {
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int w = font->Width(Title);
|
|
|
|
osd->DrawRectangle(xa06, yt00, xa07 - w - Gap - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawText(xa07 - w - Gap, yt00, Title, Theme.Color(clrMenuTitle), Theme.Color(clrBackground), font, w + Gap, yt01 - yt00, taRight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
|
|
|
{
|
2012-09-09 14:37:15 +02:00
|
|
|
const char *lutText[] = { Red, Green, Yellow, Blue };
|
|
|
|
tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg };
|
|
|
|
tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
|
2012-06-02 13:17:16 +02:00
|
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
|
|
if (MenuCategory() == mcMain) {
|
2012-09-09 14:37:15 +02:00
|
|
|
DrawMainButton(lutText[Setup.ColorKey0], xd00, xd01, xd02, xd03, yd02, yd03, Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font);
|
|
|
|
DrawMainButton(lutText[Setup.ColorKey1], xd04, xd05, xd06, xd07, yd02, yd03, Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font);
|
|
|
|
DrawMainButton(lutText[Setup.ColorKey2], xd00, xd01, xd02, xd03, yd04, yd05, Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font);
|
|
|
|
DrawMainButton(lutText[Setup.ColorKey3], xd04, xd05, xd06, xd07, yd04, yd05, Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font);
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
int h = yb15 - yb14;
|
2012-09-09 14:37:15 +02:00
|
|
|
osd->DrawText(xb02, yb14, lutText[Setup.ColorKey0], Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font, xb03 - xb02, h, taLeft | taBorder);
|
|
|
|
osd->DrawText(xb06, yb14, lutText[Setup.ColorKey1], Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font, xb07 - xb06, h, taLeft | taBorder);
|
|
|
|
osd->DrawText(xb10, yb14, lutText[Setup.ColorKey2], Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font, xb11 - xb10, h, taLeft | taBorder);
|
|
|
|
osd->DrawText(xb14, yb14, lutText[Setup.ColorKey3], Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font, xb15 - xb14, h, taLeft | taBorder);
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetMessage(eMessageType Type, const char *Text)
|
|
|
|
{
|
|
|
|
if (Text) {
|
|
|
|
osd->SaveRegion(xb00, yb14, xb15 - 1, yb15 - 1);
|
|
|
|
osd->DrawText(xb00, yb14, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xb15 - xb00, yb15 - yb14, taCenter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
osd->RestoreRegion();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
|
|
|
|
{
|
|
|
|
int y = yi00 + Index * lineHeight;
|
|
|
|
tColor ColorFg, ColorBg;
|
|
|
|
if (Current) {
|
2013-01-23 13:53:28 +01:00
|
|
|
if (TwoColors) {
|
|
|
|
ColorFg = Theme.Color(clrBackground);
|
|
|
|
ColorBg = Theme.Color(clrMenuFrameBg);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ColorFg = Theme.Color(clrMenuItemCurrentFg);
|
|
|
|
ColorBg = Theme.Color(clrMenuItemCurrentBg);
|
|
|
|
}
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawRectangle(xi00, y, xi01 - 1, y + lineHeight - 1, ColorBg);
|
|
|
|
osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
|
|
|
|
osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, y + lineHeight - 1, ColorBg, 5);
|
|
|
|
currentIndex = Index;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
|
|
|
|
ColorBg = Theme.Color(clrBackground);
|
|
|
|
if (currentIndex == Index)
|
|
|
|
osd->DrawRectangle(xi00, y, xi03 - 1, y + lineHeight - 1, 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 = xi00 + TextSpacing + Tab(i);
|
|
|
|
osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xi01 - xt);
|
|
|
|
}
|
|
|
|
if (!Tab(i + 1))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SetEditableWidth(xi02 - xi00 - TextSpacing - Tab(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetScrollbar(int Total, int Offset)
|
|
|
|
{
|
|
|
|
DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetEvent(const cEvent *Event)
|
|
|
|
{
|
|
|
|
if (!Event)
|
|
|
|
return;
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int xl = xi00;
|
|
|
|
int y = yi00;
|
|
|
|
cTextScroller ts;
|
2016-12-22 14:13:42 +01:00
|
|
|
cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
|
2012-06-02 13:17:16 +02:00
|
|
|
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), 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(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
|
|
|
|
int yb = y + font->Height();
|
|
|
|
osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
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(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
|
|
|
|
int yb = y + font->Height();
|
|
|
|
osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
y += font->Height();
|
|
|
|
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->Title(), font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
|
|
|
|
y += ts.Height();
|
|
|
|
if (!isempty(Event->ShortText())) {
|
|
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
|
|
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
|
|
|
|
y += ts.Height();
|
|
|
|
}
|
|
|
|
y += font->Height();
|
|
|
|
if (!isempty(Event->Description())) {
|
|
|
|
int yt = y;
|
|
|
|
int yb = yi01;
|
|
|
|
textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Event->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
|
|
|
|
DrawTextScrollbar();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetRecording(const cRecording *Recording)
|
|
|
|
{
|
|
|
|
if (!Recording)
|
|
|
|
return;
|
|
|
|
const cRecordingInfo *Info = Recording->Info();
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int xl = xi00;
|
|
|
|
int y = yi00;
|
|
|
|
cTextScroller ts;
|
2013-03-03 15:38:17 +01:00
|
|
|
cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
|
2012-06-02 13:17:16 +02:00
|
|
|
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), 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(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
|
|
|
|
int yb = y + font->Height();
|
|
|
|
osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
y += font->Height();
|
|
|
|
const char *Title = Info->Title();
|
|
|
|
if (isempty(Title))
|
|
|
|
Title = Recording->Name();
|
|
|
|
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Title, font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
|
|
|
|
y += ts.Height();
|
|
|
|
if (!isempty(Info->ShortText())) {
|
|
|
|
const cFont *font = cFont::GetFont(fontSml);
|
|
|
|
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Info->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
|
|
|
|
y += ts.Height();
|
|
|
|
}
|
|
|
|
y += font->Height();
|
|
|
|
if (!isempty(Info->Description())) {
|
|
|
|
int yt = y;
|
|
|
|
int yb = yi01;
|
|
|
|
textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Info->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
|
|
|
|
DrawTextScrollbar();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::SetText(const char *Text, bool FixedFont)
|
|
|
|
{
|
|
|
|
textScroller.Set(osd, xi00, yi00, GetTextAreaWidth(), yi01 - yi00, Text, GetTextAreaFont(FixedFont), Theme.Color(clrMenuText), Theme.Color(clrBackground));
|
|
|
|
DrawTextScrollbar();
|
|
|
|
}
|
|
|
|
|
|
|
|
int cSkinLCARSDisplayMenu::GetTextAreaWidth(void) const
|
|
|
|
{
|
|
|
|
return xi01 - xi00;
|
|
|
|
}
|
|
|
|
|
|
|
|
const cFont *cSkinLCARSDisplayMenu::GetTextAreaFont(bool FixedFont) const
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd);
|
|
|
|
//XXX -> make a way to let the text define which font to use
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMenu::Flush(void)
|
|
|
|
{
|
|
|
|
if (MenuCategory() == mcMain) {
|
|
|
|
cDevice *Device = cDevice::PrimaryDevice();
|
|
|
|
if (!Device->Replaying() || Device->Transferring()) {
|
2015-09-01 11:14:27 +02:00
|
|
|
LOCK_CHANNELS_READ;
|
|
|
|
const cChannel *Channel = Channels->GetByNumber(cDevice::PrimaryDevice()->CurrentChannel());
|
2012-06-02 13:17:16 +02:00
|
|
|
DrawLive(Channel);
|
|
|
|
}
|
|
|
|
else if (cControl *Control = cControl::Control(true))
|
|
|
|
DrawPlay(Control);
|
|
|
|
DrawTimers();
|
|
|
|
DrawDevices();
|
|
|
|
DrawLiveIndicator();
|
|
|
|
DrawSignals();
|
|
|
|
}
|
|
|
|
DrawFrameDisplay();
|
|
|
|
osd->Flush();
|
|
|
|
initial = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- cSkinLCARSDisplayReplay -----------------------------------------------
|
|
|
|
|
|
|
|
class cSkinLCARSDisplayReplay : public cSkinDisplayReplay {
|
|
|
|
private:
|
|
|
|
cOsd *osd;
|
|
|
|
int xp00, xp01, xp02, xp03, xp04, xp05, xp06, xp07, xp08, xp09, xp10, xp11, xp12, xp13, xp14, xp15;
|
|
|
|
int yp00, yp01, yp02, yp03, yp04, yp05, yp06, yp07, yp08, yp09;
|
|
|
|
bool modeOnly;
|
|
|
|
int lineHeight;
|
|
|
|
tColor frameColor;
|
2012-09-19 11:13:17 +02:00
|
|
|
int lastCurrentWidth;
|
2013-01-23 14:05:03 +01:00
|
|
|
int lastTotalWidth;
|
2012-06-02 13:17:16 +02:00
|
|
|
cString lastDate;
|
|
|
|
tTrackId lastTrackId;
|
|
|
|
void DrawDate(void);
|
|
|
|
void DrawTrack(void);
|
|
|
|
public:
|
|
|
|
cSkinLCARSDisplayReplay(bool ModeOnly);
|
|
|
|
virtual ~cSkinLCARSDisplayReplay();
|
|
|
|
virtual void SetRecording(const cRecording *Recording);
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
|
|
|
cSkinLCARSDisplayReplay::cSkinLCARSDisplayReplay(bool ModeOnly)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
modeOnly = ModeOnly;
|
|
|
|
lineHeight = font->Height();
|
|
|
|
frameColor = Theme.Color(clrReplayFrameBg);
|
2012-09-19 11:13:17 +02:00
|
|
|
lastCurrentWidth = 0;
|
2013-01-23 14:05:03 +01:00
|
|
|
lastTotalWidth = 0;
|
2013-11-15 15:23:43 +01:00
|
|
|
memset(&lastTrackId, 0, sizeof(lastTrackId));
|
2012-06-02 13:17:16 +02:00
|
|
|
int d = 5 * lineHeight;
|
|
|
|
xp00 = 0;
|
|
|
|
xp01 = xp00 + d / 2;
|
|
|
|
xp02 = xp00 + d;
|
|
|
|
xp03 = xp02 + lineHeight;
|
|
|
|
xp04 = xp02 + d / 4;
|
|
|
|
xp05 = xp02 + d;
|
|
|
|
xp06 = xp05 + Gap;
|
|
|
|
xp15 = cOsd::OsdWidth();
|
|
|
|
xp14 = xp15 - lineHeight;
|
|
|
|
xp13 = xp14 - Gap;
|
|
|
|
xp07 = (xp15 + xp00) / 2;
|
|
|
|
xp08 = xp07 + Gap;
|
|
|
|
xp09 = xp08 + lineHeight;
|
|
|
|
xp10 = xp09 + Gap;
|
|
|
|
xp11 = (xp10 + xp13 + Gap) / 2;
|
|
|
|
xp12 = xp11 + Gap;
|
|
|
|
|
|
|
|
yp00 = 0;
|
|
|
|
yp01 = yp00 + 2 * lineHeight;
|
|
|
|
yp02 = yp01 + Gap;
|
|
|
|
yp03 = yp02 + 2 * lineHeight;
|
|
|
|
|
|
|
|
yp04 = yp03 + Gap;
|
|
|
|
yp09 = yp04 + 3 * lineHeight + Gap / 2;
|
|
|
|
yp08 = yp09 - lineHeight;
|
|
|
|
yp07 = yp08 - lineHeight;
|
|
|
|
yp06 = yp08 - d / 4;
|
|
|
|
yp05 = yp09 - d / 2;
|
|
|
|
|
|
|
|
osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - yp09, xp00, yp00, xp15 - 1, yp09 - 1);
|
|
|
|
osd->DrawRectangle(xp00, yp00, xp15 - 1, yp09 - 1, modeOnly ? clrTransparent : Theme.Color(clrBackground));
|
|
|
|
// Rectangles:
|
|
|
|
if (!modeOnly)
|
|
|
|
osd->DrawRectangle(xp00, yp00, xp02 - 1, yp01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xp00, yp02, xp02 - 1, yp03 - 1, frameColor);
|
|
|
|
if (!modeOnly) {
|
|
|
|
// Elbow:
|
|
|
|
osd->DrawRectangle(xp00, yp04, xp01 - 1, yp05 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xp00, yp05, xp01 - 1, yp09 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xp00, yp05, xp01 - 1, yp09 - 1, frameColor, 3);
|
|
|
|
osd->DrawRectangle(xp01, yp04, xp02 - 1, yp09 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xp02, yp06, xp04 - 1, yp08 - 1, frameColor, -3);
|
|
|
|
osd->DrawRectangle(xp02, yp08, xp05 - 1, yp09 - 1, frameColor);
|
|
|
|
// Status area:
|
|
|
|
osd->DrawRectangle(xp06, yp08, xp07 - 1, yp09 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xp08, yp08, xp09 - 1, yp09 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xp10, yp08, xp11 - 1, yp09 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xp12, yp08, xp13 - 1, yp09 - 1, Theme.Color(clrDateBg));
|
|
|
|
osd->DrawRectangle(xp14, yp08, xp14 + lineHeight / 2 - 1, yp09 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xp14 + lineHeight / 2, yp08 + lineHeight / 2, xp15 - 1, yp09 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xp14 + lineHeight / 2, yp08, xp15 - 1, yp09 - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinLCARSDisplayReplay::~cSkinLCARSDisplayReplay()
|
|
|
|
{
|
|
|
|
delete osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::DrawDate(void)
|
|
|
|
{
|
|
|
|
cString s = DayDateTime();
|
|
|
|
if (!*lastDate || strcmp(s, lastDate)) {
|
|
|
|
osd->DrawText(xp12, yp08, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xp13 - xp12, lineHeight, taRight | taBorder);
|
|
|
|
lastDate = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::DrawTrack(void)
|
|
|
|
{
|
|
|
|
cDevice *Device = cDevice::PrimaryDevice();
|
|
|
|
const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
|
2013-11-15 15:35:21 +01:00
|
|
|
if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawText(xp03, yp04, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp07 - xp03);
|
|
|
|
strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetRecording(const cRecording *Recording)
|
|
|
|
{
|
|
|
|
const cRecordingInfo *RecordingInfo = Recording->Info();
|
|
|
|
SetTitle(RecordingInfo->Title());
|
|
|
|
osd->DrawText(xp03, yp01 - lineHeight, RecordingInfo->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xp13 - xp03);
|
|
|
|
osd->DrawText(xp00, yp00, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taTop | taRight | taBorder);
|
|
|
|
osd->DrawText(xp00, yp01 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taBottom | taRight | taBorder);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetTitle(const char *Title)
|
|
|
|
{
|
|
|
|
osd->DrawText(xp03, yp00, Title, Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp13 - xp03);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *const *ReplaySymbols[2][2][5] = {
|
|
|
|
{ { pause_xpm, srew_xpm, srew1_xpm, srew2_xpm, srew3_xpm },
|
|
|
|
{ pause_xpm, sfwd_xpm, sfwd1_xpm, sfwd2_xpm, sfwd3_xpm }, },
|
|
|
|
{ { play_xpm, frew_xpm, frew1_xpm, frew2_xpm, frew3_xpm },
|
|
|
|
{ play_xpm, ffwd_xpm, ffwd1_xpm, ffwd2_xpm, ffwd3_xpm } }
|
|
|
|
};
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
|
|
|
|
{
|
|
|
|
Speed = constrain(Speed, -1, 3);
|
|
|
|
cBitmap bm(ReplaySymbols[Play][Forward][Speed + 1]);
|
|
|
|
osd->DrawBitmap(xp01 - bm.Width() / 2, (yp02 + yp03 - bm.Height()) / 2, bm, Theme.Color(clrReplayFrameFg), frameColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetProgress(int Current, int Total)
|
|
|
|
{
|
|
|
|
cProgressBar pb(xp13 - xp03, lineHeight, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
|
|
|
|
osd->DrawBitmap(xp03, yp02, pb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetCurrent(const char *Current)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
2012-09-19 11:13:17 +02:00
|
|
|
int w = font->Width(Current);
|
2013-01-23 14:05:03 +01:00
|
|
|
osd->DrawText(xp03, yp03 - lineHeight, Current, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastCurrentWidth, w), 0, taLeft);
|
2012-09-19 11:13:17 +02:00
|
|
|
lastCurrentWidth = w;
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetTotal(const char *Total)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
2013-01-23 14:05:03 +01:00
|
|
|
int w = font->Width(Total);
|
|
|
|
osd->DrawText(xp13 - w, yp03 - lineHeight, Total, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastTotalWidth, w), 0, taRight);
|
|
|
|
lastTotalWidth = w;
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetJump(const char *Jump)
|
|
|
|
{
|
|
|
|
osd->DrawText(xp06, yp08, Jump, Theme.Color(clrReplayJumpFg), Jump ? Theme.Color(clrReplayJumpBg) : frameColor, cFont::GetFont(fontOsd), xp07 - xp06, 0, taCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::SetMessage(eMessageType Type, const char *Text)
|
|
|
|
{
|
|
|
|
if (Text) {
|
|
|
|
osd->SaveRegion(xp06, yp08, xp13 - 1, yp09 - 1);
|
2012-06-13 10:19:15 +02:00
|
|
|
osd->DrawText(xp06, yp08, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xp13 - xp06, yp09 - yp08, taCenter);
|
2012-06-02 13:17:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
osd->RestoreRegion();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayReplay::Flush(void)
|
|
|
|
{
|
|
|
|
if (!modeOnly) {
|
|
|
|
DrawDate();
|
|
|
|
DrawTrack();
|
|
|
|
}
|
|
|
|
osd->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- cSkinLCARSDisplayVolume -----------------------------------------------
|
|
|
|
|
|
|
|
class cSkinLCARSDisplayVolume : public cSkinDisplayVolume {
|
|
|
|
private:
|
|
|
|
cOsd *osd;
|
|
|
|
int x0, x1, x2, x3, x4, x5, x6, x7;
|
|
|
|
int y0, y1;
|
|
|
|
tColor frameColor;
|
|
|
|
int mute;
|
|
|
|
public:
|
|
|
|
cSkinLCARSDisplayVolume(void);
|
|
|
|
virtual ~cSkinLCARSDisplayVolume();
|
|
|
|
virtual void SetVolume(int Current, int Total, bool Mute);
|
|
|
|
virtual void Flush(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
cSkinLCARSDisplayVolume::cSkinLCARSDisplayVolume(void)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int lineHeight = font->Height();
|
|
|
|
frameColor = Theme.Color(clrVolumeFrame);
|
|
|
|
mute = -1;
|
|
|
|
x0 = 0;
|
|
|
|
x1 = lineHeight / 2;
|
|
|
|
x2 = lineHeight;
|
|
|
|
x3 = x2 + Gap;
|
|
|
|
x7 = cOsd::OsdWidth();
|
|
|
|
x6 = x7 - lineHeight / 2;
|
|
|
|
x5 = x6 - lineHeight / 2;
|
|
|
|
x4 = x5 - Gap;
|
|
|
|
y0 = 0;
|
|
|
|
y1 = lineHeight;
|
|
|
|
osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
|
|
|
|
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
|
|
|
|
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinLCARSDisplayVolume::~cSkinLCARSDisplayVolume()
|
|
|
|
{
|
|
|
|
delete osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayVolume::SetVolume(int Current, int Total, bool Mute)
|
|
|
|
{
|
|
|
|
int xl = x3 + TextSpacing;
|
|
|
|
int xr = x4 - TextSpacing;
|
|
|
|
int yt = y0 + TextFrame;
|
|
|
|
int yb = y1 - TextFrame;
|
|
|
|
if (mute != Mute) {
|
|
|
|
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
|
|
|
|
mute = Mute;
|
|
|
|
}
|
|
|
|
cBitmap bm(Mute ? mute_xpm : volume_xpm);
|
|
|
|
osd->DrawBitmap(xl, y0 + (y1 - y0 - bm.Height()) / 2, bm, Theme.Color(clrVolumeSymbol), frameColor);
|
|
|
|
if (!Mute) {
|
|
|
|
xl += bm.Width() + TextSpacing;
|
|
|
|
int w = (y1 - y0) / 3;
|
|
|
|
int d = TextFrame;
|
|
|
|
int n = (xr - xl + d) / (w + d);
|
|
|
|
int x = xr - n * (w + d);
|
|
|
|
tColor Color = Theme.Color(clrVolumeBarLower);
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
if (Total * i >= Current * n)
|
|
|
|
Color = Theme.Color(clrVolumeBarUpper);
|
|
|
|
osd->DrawRectangle(x, yt, x + w - 1, yb - 1, Color);
|
|
|
|
x += w + d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayVolume::Flush(void)
|
|
|
|
{
|
|
|
|
osd->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- cSkinLCARSDisplayTracks -----------------------------------------------
|
|
|
|
|
|
|
|
class cSkinLCARSDisplayTracks : public cSkinDisplayTracks {
|
|
|
|
private:
|
|
|
|
cOsd *osd;
|
|
|
|
int xt00, xt01, xt02, xt03, xt04, xt05, xt06, xt07, xt08, xt09, xt10, xt11, xt12;
|
|
|
|
int yt00, yt01, yt02, yt03, yt04, yt05, yt06, yt07;
|
|
|
|
int lineHeight;
|
|
|
|
tColor frameColor;
|
|
|
|
int currentIndex;
|
|
|
|
static cBitmap bmAudioLeft, bmAudioRight, bmAudioStereo;
|
|
|
|
void SetItem(const char *Text, int Index, bool Current);
|
|
|
|
public:
|
|
|
|
cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
|
|
|
|
virtual ~cSkinLCARSDisplayTracks();
|
|
|
|
virtual void SetTrack(int Index, const char * const *Tracks);
|
|
|
|
virtual void SetAudioChannel(int AudioChannel);
|
|
|
|
virtual void Flush(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
cBitmap cSkinLCARSDisplayTracks::bmAudioLeft(audioleft_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayTracks::bmAudioRight(audioright_xpm);
|
|
|
|
cBitmap cSkinLCARSDisplayTracks::bmAudioStereo(audiostereo_xpm);
|
|
|
|
|
|
|
|
cSkinLCARSDisplayTracks::cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
lineHeight = font->Height();
|
|
|
|
frameColor = Theme.Color(clrTrackFrameBg);
|
|
|
|
currentIndex = -1;
|
|
|
|
xt00 = 0;
|
|
|
|
xt01 = xt00 + lineHeight / 2;
|
|
|
|
xt02 = xt01 + Gap;
|
|
|
|
xt03 = xt00 + 2 * lineHeight;
|
|
|
|
int ItemsWidth = font->Width(Title) + xt03 - xt02;
|
|
|
|
for (int i = 0; i < NumTracks; i++)
|
|
|
|
ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]) + 2 * TextFrame);
|
|
|
|
xt04 = xt02 + ItemsWidth;
|
|
|
|
xt05 = xt04 + Gap;
|
|
|
|
xt06 = xt04 + lineHeight;
|
|
|
|
xt07 = xt05 + lineHeight;
|
|
|
|
xt08 = xt07 + lineHeight;
|
|
|
|
xt09 = xt08 + Gap;
|
|
|
|
xt10 = xt09 + lineHeight / 2;
|
|
|
|
xt11 = xt10 + Gap;
|
|
|
|
xt12 = xt11 + lineHeight;
|
|
|
|
yt00 = 0;
|
|
|
|
yt01 = yt00 + lineHeight;
|
|
|
|
yt02 = yt01 + lineHeight;
|
|
|
|
yt03 = yt02 + Gap;
|
|
|
|
yt04 = yt03 + NumTracks * lineHeight + (NumTracks - 1) * Gap;
|
|
|
|
yt05 = yt04 + Gap;
|
|
|
|
yt06 = yt05 + lineHeight;
|
|
|
|
yt07 = yt06 + lineHeight;
|
|
|
|
while (yt07 > cOsd::OsdHeight()) {
|
|
|
|
yt04 -= lineHeight + Gap;
|
|
|
|
yt05 = yt04 + Gap;
|
|
|
|
yt06 = yt05 + lineHeight;
|
|
|
|
yt07 = yt06 + lineHeight;
|
|
|
|
}
|
|
|
|
osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - yt07, xt00, yt00, xt12 - 1, yt07 - 1);
|
|
|
|
// The upper elbow:
|
|
|
|
osd->DrawRectangle(xt00, yt00, xt12 - 1, yt07 - 1, Theme.Color(clrBackground));
|
|
|
|
osd->DrawRectangle(xt00, yt00, xt03 - 1, yt02 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xt00, yt00, xt03 - 1, yt02 - 1, frameColor, 2);
|
|
|
|
osd->DrawRectangle(xt03, yt00, xt04 - 1, yt02 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt04, yt00, xt08 - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xt04, yt01, xt06 - 1, yt02 - 1, frameColor, -2);
|
|
|
|
osd->DrawRectangle(xt09, yt00, xt10 - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt11, yt00, xt11 + lineHeight / 2 - 1, yt01 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt11 + lineHeight / 2, yt00, xt12 - 1, yt00 + lineHeight / 2 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xt11 + lineHeight / 2, yt00, xt12 - 1, yt01 - 1, frameColor, 5);
|
|
|
|
osd->DrawText(xt03, yt00, Title, Theme.Color(clrTrackFrameFg), frameColor, font, xt04 - xt03, 0, taTop | taRight);
|
|
|
|
// The items:
|
|
|
|
for (int i = 0; i < NumTracks; i++)
|
|
|
|
SetItem(Tracks[i], i, false);
|
|
|
|
// The lower elbow:
|
|
|
|
osd->DrawRectangle(xt00, yt05, xt03 - 1, yt07 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xt00, yt05, xt03 - 1, yt07 - 1, frameColor, 3);
|
|
|
|
osd->DrawRectangle(xt03, yt05, xt04 - 1, yt07 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt04, yt06, xt08 - 1, yt07 - 1, frameColor);
|
|
|
|
osd->DrawEllipse (xt04, yt05, xt06 - 1, yt06 - 1, frameColor, -3);
|
|
|
|
osd->DrawRectangle(xt09, yt06, xt10 - 1, yt07 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt11, yt06, xt11 + lineHeight / 2 - 1, yt07 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt11 + lineHeight / 2, yt06 + lineHeight / 2, xt12 - 1, yt07 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (xt11 + lineHeight / 2, yt06, xt12 - 1, yt07 - 1, frameColor, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinLCARSDisplayTracks::~cSkinLCARSDisplayTracks()
|
|
|
|
{
|
|
|
|
delete osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayTracks::SetItem(const char *Text, int Index, bool Current)
|
|
|
|
{
|
|
|
|
int y0 = yt03 + Index * (lineHeight + Gap);
|
|
|
|
int y1 = y0 + lineHeight;
|
|
|
|
if (y1 > yt04)
|
|
|
|
return;
|
|
|
|
tColor ColorFg, ColorBg;
|
|
|
|
if (Current) {
|
|
|
|
ColorFg = Theme.Color(clrTrackItemCurrentFg);
|
|
|
|
ColorBg = Theme.Color(clrTrackItemCurrentBg);
|
|
|
|
osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
|
|
|
|
osd->DrawRectangle(xt05, y0, xt05 + lineHeight / 2 - 1, y1 - 1, ColorBg);
|
|
|
|
osd->DrawEllipse (xt05 + lineHeight / 2, y0, xt07 - 1, y1 - 1, ColorBg, 5);
|
|
|
|
currentIndex = Index;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ColorFg = Theme.Color(clrTrackItemFg);
|
|
|
|
ColorBg = Theme.Color(clrTrackItemBg);
|
|
|
|
osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
|
|
|
|
osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
|
|
|
|
if (currentIndex == Index)
|
|
|
|
osd->DrawRectangle(xt05, y0, xt07 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
}
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
osd->DrawText(xt02, y0, Text, ColorFg, ColorBg, font, xt04 - xt02, y1 - y0, taTop | taLeft | taBorder);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayTracks::SetTrack(int Index, const char * const *Tracks)
|
|
|
|
{
|
|
|
|
if (currentIndex >= 0)
|
|
|
|
SetItem(Tracks[currentIndex], currentIndex, false);
|
|
|
|
SetItem(Tracks[Index], Index, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayTracks::SetAudioChannel(int AudioChannel)
|
|
|
|
{
|
|
|
|
cBitmap *bm = NULL;
|
|
|
|
switch (AudioChannel) {
|
|
|
|
case 0: bm = &bmAudioStereo; break;
|
|
|
|
case 1: bm = &bmAudioLeft; break;
|
|
|
|
case 2: bm = &bmAudioRight; break;
|
|
|
|
default: ;
|
|
|
|
}
|
|
|
|
if (bm)
|
|
|
|
osd->DrawBitmap(xt04 - bm->Width(), (yt06 + yt07 - bm->Height()) / 2, *bm, Theme.Color(clrTrackFrameFg), frameColor);
|
|
|
|
else
|
|
|
|
osd->DrawRectangle(xt03, yt06, xt04 - 1, yt07 - 1, frameColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayTracks::Flush(void)
|
|
|
|
{
|
|
|
|
osd->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- cSkinLCARSDisplayMessage ----------------------------------------------
|
|
|
|
|
|
|
|
class cSkinLCARSDisplayMessage : public cSkinDisplayMessage {
|
|
|
|
private:
|
|
|
|
cOsd *osd;
|
|
|
|
int x0, x1, x2, x3, x4, x5, x6, x7;
|
|
|
|
int y0, y1;
|
|
|
|
public:
|
|
|
|
cSkinLCARSDisplayMessage(void);
|
|
|
|
virtual ~cSkinLCARSDisplayMessage();
|
|
|
|
virtual void SetMessage(eMessageType Type, const char *Text);
|
|
|
|
virtual void Flush(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
cSkinLCARSDisplayMessage::cSkinLCARSDisplayMessage(void)
|
|
|
|
{
|
|
|
|
const cFont *font = cFont::GetFont(fontOsd);
|
|
|
|
int lineHeight = font->Height();
|
|
|
|
x0 = 0;
|
|
|
|
x1 = lineHeight / 2;
|
|
|
|
x2 = lineHeight;
|
|
|
|
x3 = x2 + Gap;
|
|
|
|
x7 = cOsd::OsdWidth();
|
|
|
|
x6 = x7 - lineHeight / 2;
|
|
|
|
x5 = x6 - lineHeight / 2;
|
|
|
|
x4 = x5 - Gap;
|
|
|
|
y0 = 0;
|
|
|
|
y1 = lineHeight;
|
|
|
|
osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinLCARSDisplayMessage::~cSkinLCARSDisplayMessage()
|
|
|
|
{
|
|
|
|
delete osd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMessage::SetMessage(eMessageType Type, const char *Text)
|
|
|
|
{
|
|
|
|
tColor ColorFg = Theme.Color(clrMessageStatusFg + 2 * Type);
|
|
|
|
tColor ColorBg = Theme.Color(clrMessageStatusBg + 2 * Type);
|
|
|
|
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground));
|
|
|
|
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
|
|
|
|
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, ColorBg);
|
2012-06-13 10:19:15 +02:00
|
|
|
osd->DrawText(x3, y0, Text, ColorFg, ColorBg, cFont::GetFont(fontSml), x4 - x3, y1 - y0, taCenter);
|
2012-06-02 13:17:16 +02:00
|
|
|
osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, ColorBg);
|
|
|
|
osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
|
|
|
|
osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, ColorBg, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cSkinLCARSDisplayMessage::Flush(void)
|
|
|
|
{
|
|
|
|
osd->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- cSkinLCARS ------------------------------------------------------------
|
|
|
|
|
|
|
|
cSkinLCARS::cSkinLCARS(void)
|
|
|
|
:cSkin("lcars", &::Theme)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *cSkinLCARS::Description(void)
|
|
|
|
{
|
|
|
|
return "LCARS";
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinDisplayChannel *cSkinLCARS::DisplayChannel(bool WithInfo)
|
|
|
|
{
|
|
|
|
return new cSkinLCARSDisplayChannel(WithInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinDisplayMenu *cSkinLCARS::DisplayMenu(void)
|
|
|
|
{
|
|
|
|
return new cSkinLCARSDisplayMenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinDisplayReplay *cSkinLCARS::DisplayReplay(bool ModeOnly)
|
|
|
|
{
|
|
|
|
return new cSkinLCARSDisplayReplay(ModeOnly);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinDisplayVolume *cSkinLCARS::DisplayVolume(void)
|
|
|
|
{
|
|
|
|
return new cSkinLCARSDisplayVolume;
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinDisplayTracks *cSkinLCARS::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
|
|
|
|
{
|
|
|
|
return new cSkinLCARSDisplayTracks(Title, NumTracks, Tracks);
|
|
|
|
}
|
|
|
|
|
|
|
|
cSkinDisplayMessage *cSkinLCARS::DisplayMessage(void)
|
|
|
|
{
|
|
|
|
return new cSkinLCARSDisplayMessage;
|
|
|
|
}
|