diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | displaychannel.c | 3 | ||||
-rw-r--r-- | displaymenu.c | 1366 | ||||
-rw-r--r-- | displaymenu.h | 137 | ||||
-rw-r--r-- | displayreplay.c | 3 | ||||
-rw-r--r-- | lcarsng.c | 1543 | ||||
-rw-r--r-- | lcarsng.h | 3 |
7 files changed, 1514 insertions, 1543 deletions
@@ -54,7 +54,7 @@ DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = displaychannel.o displayreplay.o lcarsng.o $(PLUGIN).o +OBJS = displaychannel.o displaymenu.o displayreplay.o lcarsng.o $(PLUGIN).o ### The main target: diff --git a/displaychannel.c b/displaychannel.c index cd17dad..96a2332 100644 --- a/displaychannel.c +++ b/displaychannel.c @@ -345,7 +345,8 @@ void cLCARSNGDisplayChannel::Action(void) { while (Running()) { On = !On; - Flush(); + DrawBlinkingRec(); + osd->Flush(); cCondWait::SleepMs(1000); } } diff --git a/displaymenu.c b/displaymenu.c new file mode 100644 index 0000000..9063df6 --- /dev/null +++ b/displaymenu.c @@ -0,0 +1,1366 @@ +/* + * 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. + * + * $Id: skinlcars.c 4.1 2015/09/01 10:07:07 kls Exp $ + */ + +#include "lcarsng.h" +#include "displaymenu.h" +#include <vdr/font.h> +#include <vdr/menu.h> +#include <vdr/osd.h> +#if APIVERSNUM > 20101 +#include <vdr/positioner.h> +#endif +#include <vdr/themes.h> +#include <vdr/thread.h> +#include <vdr/tools.h> +#include <vdr/videodir.h> +#include <sys/statvfs.h> +#include <string> + +cBitmap cLCARSNGDisplayMenu::bmArrowUp(arrowup_xpm); +cBitmap cLCARSNGDisplayMenu::bmArrowDown(arrowdown_xpm); +cBitmap cLCARSNGDisplayMenu::bmTransferMode(play_xpm); + +cRect availableRect; +cRect videoWindowRect; + +// --- cLCARSNGDisplayMenu ------------------------------------------------- + +cLCARSNGDisplayMenu::cLCARSNGDisplayMenu(void) +{ + tallFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize * 1.6); + initial = true; + lastMode = cmUnknown; + lastChannel = NULL; + lastEvent = NULL; + lastRecording = NULL; + lastSeen = -1; +#if APIVERSNUM < 20301 + lastTimersState = -1; +#endif + lastSignalDisplay = 0; + lastLiveIndicatorY = -1; + lastLiveIndicatorTransferring = false; + currentTitle = NULL; + 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; + yt07 = yt06 + Gap; + yt08 = yt07 + 2 * lineHeight; + +// yc00 = yt06 + Gap; + yc00 = yt08 + Gap; +// yc05 = yc00 + 3 * lineHeight + Gap / 2; // Button in der Mitte + yc05 = yc00 + 5 * lineHeight + Gap / 2; + yc04 = yc05 - lineHeight; + yc03 = yc04 - lineHeight; + yc02 = yc04 - d / 4; + yc01 = yc05 - d / 2; + + yc06 = yc05 + Gap; +// yc06 = yc05 + 2 * lineHeight + Gap; // Button in der Mitte + 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; // Load + yb05 = yb04 + 2 * lineHeight; // Load % + 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; // VDR + yb10 = yb13 - Gap - lineHeight; + yb09 = yb10 - Gap; + + // Compensate for large font size: + if (yb09 - yb08 < 2 * lineHeight) { + yb08 = yb06; + yb06 = 0; // drop "RECORDINGS" display" or empty rectangle + } + if (yb09 - yb08 < 2 * lineHeight) { + yb05 = yb09; + yb08 = 0; // drop "LCARSNG" 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; // Bezug MenĂ¼ oben + 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; //cOsd::OsdWidth() + 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; // Bezug Status oben + ys01 = ys00 + lineHeight; + ys02 = ys01 + lineHeight / 2; + ys04 = ys01 + lineHeight; + ys03 = ys04 - Gap; + ys05 = yb15; + + // 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; + + // 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; + xb14 = xb13 + Gap; + + // The color buttons in the main menu: + int r = lineHeight; +// xd07 = xa09; + xd07 = xm05 - Gap; + xd06 = xd07 - r; + xd05 = xd06 - 6 * r; + xd04 = xd05 - r; + xd03 = xd04 - Gap; + xd02 = xd03 - r; + xd01 = xd02 - 6 * r; + xd00 = xd01 - r; + yd00 = yt00; + yd05 = yc04 - 3 * Gap; +// yd05 = yc06 - Gap; // Button in der Mitte + yd04 = yd05 - r; //0.85 * r; // Button in der Mitte + yd03 = yd04 - Gap; + yd02 = yd03 - r; //0.85 * r; // Button in der Mitte + yd01 = yd02 - Gap; + + xs = 0; + + osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop(), xa00, yt00, xa09 - 1, yb15 - 1); + DrawMenuFrame(); +} + +cLCARSNGDisplayMenu::~cLCARSNGDisplayMenu() +{ + delete tallFont; + delete tinyFont; + delete osd; + cDevice::PrimaryDevice()->ScaleVideo(cRect::Null); +} + +void cLCARSNGDisplayMenu::SetMenuCategory(eMenuCategory MenuCategory) +{ + if (initial || MenuCategory != cSkinDisplayMenu::MenuCategory()) { + cSkinDisplayMenu::SetMenuCategory(MenuCategory); + initial = true; + osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, Theme.Color(clrBackground)); + switch (MenuCategory) { + case mcMain: + case mcSetup: + case mcCommand: + osd->DrawRectangle( xs00, 0, xa09, yc06 - 1, clrTransparent); + yi00 = ym03; + yi01 = ym04; + xi00 = xm00; + xi01 = xm03; + xi02 = xm04; + xi03 = xm05; +#if APIVERSNUM < 20301 + lastTimersState = -1; +#else + timersStateKey.Reset(); +#endif + DrawMainFrameLower(); + DrawMainBracket(); + DrawStatusElbows(); + break; + case mcChannel: + osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, clrTransparent); + yi00 = yt04 + lineHeight; + yi01 = ym04; + xi00 = xm00; + xi01 = xm03; + xi02 = xm04; + xi03 = xm05; + DrawMainFrameChannel(); + DrawMainBracket(); + break; + case mcSchedule: + case mcScheduleNow: + case mcScheduleNext: + case mcEvent: + case mcRecording: + case mcRecordingInfo: + case mcRecordingEdit: + case mcTimer: + case mcTimerEdit: + osd->DrawRectangle( xs00, 0, xa09, yc06 - 1, clrTransparent); + yi00 = ym00; + yi01 = ym07; + xi00 = xa03; + xi01 = xa07; + xi02 = xa08; + xi03 = xa09; + DrawMainFrameLower(); + DrawMainBracket(); + break; + default: + yi00 = yt02; + yi01 = yb13; + xi00 = xa03; + xi01 = xa07; + xi02 = xa08; + xi03 = xa09; + DrawMenuFrame(); + } + } +} + +void cLCARSNGDisplayMenu::DrawMainFrameUpper(tColor Color) +{ + // Top left rectangles: +// osd->DrawRectangle(xa00, yt00, xa02 - 1, yt02 - 1, Color); + osd->DrawRectangle(xa00, yt00, xa02 - 1, yt08 - 1, Color); +// osd->DrawRectangle(xa00, yt04, xa02 - 1, yt06 - 1, Color); +// osd->DrawRectangle(xa00, yt07, xa02 - 1, yt08 - 1, Color); + osd->DrawRectangle(xa00, yt02, xa02 - 1, yt04 - 1, Theme.Color(clrBackground)); + osd->DrawRectangle(xa00, yt06, xa02 - 1, yt07 - 1, Theme.Color(clrBackground)); + // 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); + osd->DrawRectangle(xa00, yc00 + 2 * lineHeight, xa02 - 1, yc00 + 2 * lineHeight + Gap, Theme.Color(clrBackground)); + // Upper delimiter: + osd->DrawRectangle(xa06, yc04 + lineHeight / 2, xm03 - 1, yc05 - 1, Color); + osd->DrawRectangle(xm03 + Gap, yc04 + lineHeight / 2, xm07 - 1, yc05 - 1, Color); + // Top right rectangles: + osd->DrawRectangle(xm07, yt00, xm08 - 1, yc04 -Gap - 1, Color); + osd->DrawEllipse (xm07, yc04, xm08 - 1, yc05 - 1, Color, 4); + osd->DrawEllipse (xm05, yc04, xm07 - 1, yc05 - 1 - lineHeight / 2, Color, -4); +} + +void cLCARSNGDisplayMenu::DrawMainFrameLower(void) +{ +// unterer gelber Rahmen + 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, xm03 - 1, yc07 - lineHeight / 2 - 1, frameColor); + osd->DrawRectangle(xm03 + Gap, yc06, xm08 - 1, yc07 - 1, frameColor); + osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor); + // VDR version: + osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor); + osd->DrawText(xa00, yb10, cString::sprintf("%s-%s", "VDR", VDRVERSION), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); + osd->DrawText(xa00, yb15 - lineHeight, "LCARSNG", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); +} + +void cLCARSNGDisplayMenu::DrawMainFrameChannel(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + // 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(xm04, yt00, xm07 - Gap - 1, yt01 - 1, frameColor); + osd->DrawRectangle(xm07, yt00, xm07 + lineHeight / 2 -1, yt01 - 1, frameColor); + osd->DrawEllipse (xm07 + lineHeight / 2, yt00, xm08 - 1, yt01 - 1, frameColor, 5); + // Center part: + osd->DrawRectangle(xa00, yt06 + Gap, xa02 - 1, yc00 - 1 - Gap, frameColor); + osd->DrawRectangle(xa00, yc00, xa02 - 1, yc11 - 1, frameColor); + // VDR version: + osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor); + osd->DrawText(xa00, yb10, cString::sprintf("%s-%s", "VDR", VDRVERSION), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); + osd->DrawText(xa00, yb15 - lineHeight, "LCARSNG", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); +} + +void cLCARSNGDisplayMenu::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); +// osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taBottom | taRight); + osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taCenter); + osd->DrawEllipse(x2, y0, x3 - 1, y1 - 1, ColorBg, 5); +} + +void cLCARSNGDisplayMenu::DrawMenuFrame(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + // 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, yt06 + Gap, xa02 - 1, yc00 - 1 - Gap, frameColor); + 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, cString::sprintf("%s-%s", "VDR", VDRVERSION), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); + // Color buttons: + 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])); +} + +void cLCARSNGDisplayMenu::DrawDate(void) +{ + cString s = DayDateTime(); + if (initial || !*lastDate || strcmp(s, lastDate)) { + 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 cLCARSNGDisplayMenu::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; + int freemb = FreeMB(currentTitle, initial); + int minutes = 0; + { + LOCK_RECORDINGS_READ; + double MBperMinute = Recordings->MBperMinute(); + minutes = int(double(freemb) / (MBperMinute > 0 ? MBperMinute : MB_PER_MINUTE)); + } + 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, cString::sprintf("%02d%s", DiskUsage, "%"), ColorFg, ColorBg, font, xa02 - xa01, lineHeight, taBottom | taRight | taBorder); + osd->DrawText(xa00, yb03 - lineHeight, freemb ? cString::sprintf("%02d:%02d", minutes / 60, minutes % 60) : cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60), ColorFg, ColorBg, font, xa02 - xa00, 0, taBottom | taRight | taBorder); + lastDiskAlert = DiskAlert; + } + } +} + +void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::DrawNumRecordingsInPath(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + int NumRecordingsInPath = 0; + { +#if APIVERSNUM > 20300 + LOCK_RECORDINGS_READ; +#endif + NumRecordingsInPath = Recordings->GetNumRecordingsInPath(cMenuRecordings::GetActualPath()); + } + osd->DrawText(xm04, ys00, cString::sprintf("%i", NumRecordingsInPath), Theme.Color(clrMenuFrameFg), frameColor, font, xm08 - xm04 - 1, lineHeight, taBottom | taRight | taBorder); +} + +void cLCARSNGDisplayMenu::DrawCountRecordings(void) +{ + if (yb06) { + const cFont *font = cFont::GetFont(fontOsd); + tColor ColorFg = Theme.Color(clrMenuFrameFg); + tColor ColorBg = frameColor; + int CountRecordings = 0; + { +#if APIVERSNUM > 20300 + LOCK_RECORDINGS_READ; +#endif + CountRecordings = Recordings->Count(); + } + osd->DrawText(xa00, yb06, tr("RECORDINGS"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb07 - yb06, taTop | taLeft | taBorder); + osd->DrawText(xa00, yb07 - lineHeight, cString::sprintf("%i", CountRecordings), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + } +} + +void cLCARSNGDisplayMenu::DrawCountTimers(void) +{ + if (yb08) { + const cFont *font = cFont::GetFont(fontOsd); + tColor ColorFg = Theme.Color(clrMenuFrameFg); + tColor ColorBg = frameColor; + int CountTimers = 0; +#if APIVERSNUM > 20300 + LOCK_TIMERS_READ; + for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { +#else + for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { +#endif + if (Timer->HasFlags(tfActive)) + CountTimers++; + } + osd->DrawText(xa00, yb08, tr("TIMER"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb09 - yb08, taTop | taLeft | taBorder); + osd->DrawText(xa00, yb09 - lineHeight, itoa(CountTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + } +} + +void cLCARSNGDisplayMenu::DrawMainBracket(void) +{ + const cFont *font = cFont::GetFont(fontOsd); + tColor Color = Theme.Color(clrMenuMainBracket); + int y0, y1, y2, y3; + if (MenuCategory() == mcChannel) { + y0 = yt00 + lineHeight *2; + y1 = y0 + lineHeight / 2; + y2 = y1 + lineHeight / 2; + y3 = y2 + Gap; + } + else { + y0 = ym00; //yc08 + y1 = ym01; //ym00 + lineHeight / 2 + y2 = ym02; //ym01 + lineHeight / 2 + y3 = ym03; //ym02 + Gap + } + if (MenuCategory() != mcSchedule && MenuCategory() != mcScheduleNow && MenuCategory() != mcScheduleNext && MenuCategory() != mcEvent && MenuCategory() != mcRecording && MenuCategory() != mcRecordingInfo && MenuCategory() != mcRecordingEdit && MenuCategory() != mcTimer && MenuCategory() != mcTimerEdit) { + osd->DrawRectangle(xm00, y0, xm01 - 1, y1 - 1, Color); + osd->DrawRectangle(xm02, y0, xm07 - 1, y1 - 1, Color); + osd->DrawEllipse (xm07, y0, xm08 - 1, y2 - 1, Color, 1); + osd->DrawEllipse (xm06, y1, xm07 - 1, y2 - 1, Color, -1); + osd->DrawRectangle(xm07, y3, 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); + } + if (MenuCategory() == mcSetup) + osd->DrawText(xm02, ys00, tr("Setup"), Theme.Color(clrMenuFrameFg), frameColor, font, xm04 - xm02 - Gap, lineHeight, taBottom | taLeft | taBorder); + if (MenuCategory() == mcCommand) + osd->DrawText(xm02, ys00, tr("Commands"), Theme.Color(clrMenuFrameFg), frameColor, font, xm04 - xm02 - Gap, lineHeight, taBottom | taLeft | taBorder); + if (MenuCategory() == mcChannel) + osd->DrawText(xm02, yt00, tr("Channels"), Theme.Color(clrMenuFrameFg), frameColor, font, xm04 - xm02 - Gap, lineHeight, taBottom | taLeft | taBorder); + if (MenuCategory() != mcMain && MenuCategory() != mcSchedule && MenuCategory() != mcScheduleNow && MenuCategory() != mcScheduleNext && MenuCategory() != mcEvent && MenuCategory() != mcRecording && MenuCategory() != mcRecordingInfo && MenuCategory() != mcRecordingEdit && MenuCategory() != mcTimer && MenuCategory() != mcTimerEdit) { + osd->DrawRectangle(xm04 - Gap, y0, xm04, ym01 - 1, clrTransparent); + osd->DrawRectangle(xm04 - Gap, ym06, xm04, ym07 - 1, clrTransparent); + } +} + +void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::DrawFrameDisplay(void) +{ +// if (MenuCategory() != mcChannel) { + 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 - Gap, "LCARSNG", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + } + } + DrawCountRecordings(); + DrawCountTimers(); + if (MenuCategory() == mcRecording) + DrawNumRecordingsInPath(); +// } +} + +void cLCARSNGDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown) +{ + int x0, x1, tt, tb; + tColor ClearColor; + if (MenuCategory() == mcMain || MenuCategory() == mcSetup || MenuCategory() == mcCommand) { + x0 = xm07; + x1 = xm08; + tt = ym03; + tb = ym04; + ClearColor = Theme.Color(clrMenuMainBracket); + } + else if (MenuCategory() == mcChannel) { + x0 = xm07; + x1 = xm08; + tt = yt04 + lineHeight; + tb = ym04; + ClearColor = Theme.Color(clrMenuMainBracket); + } + else { + x0 = xa02 + Gap; + x1 = x0 + lineHeight / 2; + ClearColor = Theme.Color(clrBackground); + int d = TextFrame; + if (MenuCategory() == mcSchedule || MenuCategory() == mcScheduleNow || MenuCategory() == mcScheduleNext || MenuCategory() == mcEvent || MenuCategory() == mcRecording || MenuCategory() == mcRecordingInfo || MenuCategory() == mcRecordingEdit || MenuCategory() == mcTimer || MenuCategory() == mcTimerEdit) { + tt = yb00; + tb = yb07 + lineHeight + Gap; + } + else { + tt = yc00; + tb = yc11; + if (CanScrollUp) + osd->DrawBitmap(xa02 - bmArrowUp.Width() - d, tt + d, bmArrowUp, Theme.Color(clrMenuScrollbarArrow), frameColor); + else + osd->DrawRectangle(xa02 - bmArrowUp.Width() - d, tt + d, xa02 - d - 1, tt + d + bmArrowUp.Height() - 1, frameColor); + if (CanScrollDown) + osd->DrawBitmap(xa02 - bmArrowDown.Width() - d, tb - d - bmArrowDown.Height(), bmArrowDown, Theme.Color(clrMenuScrollbarArrow), frameColor); + else + osd->DrawRectangle(xa02 - bmArrowDown.Width() - d, tb - d - bmArrowDown.Height(), xa02 - d - 1, tb - 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 && MenuCategory() != mcSetup && MenuCategory() != mcCommand && MenuCategory() != mcChannel) + osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, ClearColor); +} + +void cLCARSNGDisplayMenu::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); + tColor ColorBg = Alert ? Theme.Color(clrAlertBg) : Theme.Color(clrTimerBg); + 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); +#ifdef USE_SWITCHONLY + if (Timer->Flags() & tfSwitchOnly) + Date = cString::sprintf("UST %s", *Date); +#endif + 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); +#if APIVERSNUM > 20300 + // 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); +#endif + // The timer recording indicator: +#if APIVERSNUM > 20300 + else if (Timer->Recording()) +#else + if (Timer->Recording()) +#endif + osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording)); +} + +void cLCARSNGDisplayMenu::DrawTimers(void) +{ +#if APIVERSNUM > 20300 + if (const cTimers *Timers = cTimers::GetTimersRead(timersStateKey)) { +#else + if (Timers.Modified(lastTimersState)) { +#endif + deviceRecording.Clear(); + const cFont *font = cFont::GetFont(fontOsd); +#if APIVERSNUM > 20300 + osd->DrawRectangle(xs00 - (lineHeight - Gap) / 2, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground)); +#else + osd->DrawRectangle(xs00, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground)); +#endif + osd->DrawRectangle(xs07, ys04, xs13 - 1, ys05 - 1, Theme.Color(clrBackground)); +#if APIVERSNUM > 20300 + cSortedTimers SortedTimers(Timers); +#else + cSortedTimers SortedTimers; +#endif + cVector<int> FreeDeviceSlots; + int NumDevices = 0; + 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()) { +#if APIVERSNUM > 20300 + if (Timer->Remote()) { + if (!Device && Timer->HasFlags(tfActive)) { + DrawTimer(Timer, y, false); + FreeDeviceSlots.Append(y); + y += lineHeight + Gap; + } + else + continue; + } + else if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) { +#else + if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) { +#endif + if (!Device || Device == RecordControl->Device()) { + DrawTimer(Timer, y, NumTimers > 0); + NumTimers++; + if (!Device) { + Device = RecordControl->Device(); + deviceOffset[Device->DeviceNumber()] = y; + deviceRecording[Device->DeviceNumber()] = true; + NumDevices++; + } + else + FreeDeviceSlots.Append(y); + y += lineHeight + Gap; + } + else + continue; + } + SortedTimers[i] = NULL; + } + else if (!Device && Timer->HasFlags(tfActive)) { + 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)) { + 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; + NumDevices++; + } + } + } + } + // Total number of active timers: + int NumTimers = 0; +#if APIVERSNUM > 20300 + for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { +#else + for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { +#endif + if (Timer->HasFlags(tfActive)) + NumTimers++; + } + osd->DrawText(xs02, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder); + osd->DrawText(xs08, ys00, itoa(NumDevices), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder); + lastSignalDisplay = 0; + initial = true; // forces redrawing of devices +#if APIVERSNUM > 20300 + timersStateKey.Remove(); +#endif + } +} + +void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::DrawDevices(void) +{ + for (int i = 0; i < cDevice::NumDevices(); i++) { + if (const cDevice *Device = cDevice::GetDevice(i)) { + if (Device->NumProvidedSystems()) + DrawDevice(Device); + } + } +} + +void cLCARSNGDisplayMenu::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)); + if (y > 0) { + 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); + 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; + } + } + lastLiveIndicatorY = y; + lastLiveIndicatorTransferring = Transferring; + } +} + +void cLCARSNGDisplayMenu::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)) { + if (Device->NumProvidedSystems()) { + if (int y = deviceOffset[i]) + DrawDeviceSignal(osd, Device, xs + lineHeight / 2, y, xs11, y + lineHeight, lastSignalStrength[i], lastSignalQuality[i], initial); + } + } + } + lastSignalDisplay = Now; + } +} + +void cLCARSNGDisplayMenu::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, yt02 - yd00, taTop | taRight | taBorder); + } + if (!Channel) + return; + if (initial || Channel != lastChannel || strcmp(Channel->Name(), lastChannelName)) { + osd->DrawText(xa00, yt04, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt06 - yt04, taTop | taRight | taBorder); + osd->DrawText(xa03, yt04, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd07 - xa03, yt06 - yt04, taTop | taLeft); + 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); + osd->DrawText(x, yc00, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), cFont::GetFont(fontOsd), xa02 - x, 2 * lineHeight, taTop | taRight | taBorder); + lastChannel = Channel; + lastChannelName = Channel->Name(); + DrawSeen(0, 0); + } + // The current programme: +#if APIVERSNUM > 20300 + 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(); + } + DrawSeen(Current, Total); +#else + cSchedulesLock SchedulesLock; + if (const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock)) { + 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(); + } + DrawSeen(Current, Total); + } +#endif + } +} + +void cLCARSNGDisplayMenu::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, yt02 - 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, yt04, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd07 - xa03, yt06 - yt04, taTop | taLeft); + DrawInfo(Info->GetEvent(), false); + } + else + osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd07 - xa03, 0, taTop | taLeft); + osd->DrawText(xa00, yt07, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder); + osd->DrawText(xa00, yt07 + 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, yt04, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd07 - xa03, 0, taTop | taLeft); + lastHeader = Header; + } + } +} + +void cLCARSNGDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime) +{ + if (Event) { + const cFont *font = cFont::GetFont(fontOsd); + int y = yt07; + osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd07 - xa03 - lineHeight, lineHeight, taBottom | taLeft); + y += lineHeight; + osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd07 - xa03 - lineHeight, lineHeight, taTop | taLeft); + if (WithTime) { + osd->DrawText(xa00, y - lineHeight, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder); + osd->DrawText(xa00, y, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); + } + } +} + +void cLCARSNGDisplayMenu::DrawSeen(int Current, int Total) +{ +// Fortschrittsbalken + int Seen = (Total > 0) ? min(xm03 - xm02, int((xm03 - xm02) * double(Current) / Total)) : 0; + 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, xm03 - 1, y1 - 1, Theme.Color(clrBackground)); + lastSeen = Seen; + } +} + +void cLCARSNGDisplayMenu::DrawTextScrollbar(void) +{ + if (textScroller.CanScroll()) + DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.CanScrollUp(), textScroller.CanScrollDown()); +} + +void cLCARSNGDisplayMenu::Scroll(bool Up, bool Page) +{ + cSkinDisplayMenu::Scroll(Up, Page); + DrawTextScrollbar(); +} + +int cLCARSNGDisplayMenu::MaxItems(void) +{ + switch (MenuCategory()) { + case mcMain: + case mcSetup: + case mcCommand: + return (ym04 - ym03) / lineHeight; + break; + case mcChannel: + return (ym04 - yt04 - lineHeight) / lineHeight; + break; + case mcSchedule: + case mcScheduleNow: + case mcScheduleNext: + case mcEvent: + case mcRecording: + case mcRecordingInfo: + case mcRecordingEdit: + case mcTimer: + case mcTimerEdit: + return (ym07 - ym00) / lineHeight; + break; + default: + return (yb13 - yt02) / lineHeight; + } +} + +void cLCARSNGDisplayMenu::Clear(void) +{ + textScroller.Reset(); + osd->DrawRectangle(xi00, yi00, xi03 - 1, yi01 - 1, Theme.Color(clrBackground)); +} + +void cLCARSNGDisplayMenu::SetTitle(const char *Title) +{ + const cFont *font = cFont::GetFont(fontOsd); + initial = true; + currentTitle = NULL; + switch (MenuCategory()) { + case mcMain: + case mcSetup: + case mcCommand: + case mcChannel: + break; + case mcRecording: + currentTitle = Title; + case mcRecordingInfo: + case mcRecordingEdit: + case mcTimerEdit: + case mcSchedule: + case mcScheduleNow: + case mcScheduleNext: + case mcEvent: + osd->DrawRectangle(xs00 - Gap, ys00, xs00, ys01 - 1, Theme.Color(clrBackground)); + osd->DrawText(xs00, ys00, Title, Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs00 - 1, lineHeight, taBottom | taRight); + osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor); + break; + case mcTimer: { + osd->DrawText(xs00, ys00, Title, Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs00, lineHeight, taBottom | taRight | taBorder); + osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor); +/* int NumTimers = 0; +#if APIVERSNUM > 20300 + LOCK_TIMERS_READ; + for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { +#else + for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { +#endif + if (Timer->HasFlags(tfActive)) + NumTimers++; + } + osd->DrawText(xs00, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder); */ + } + break; + default: + int w = min(font->Width(Title), xa07 - xa06 - Gap); + 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 cLCARSNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) +{ + const char *lutText[] = { Red, Green, Yellow, Blue }; + tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg }; + tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg }; + int x = 0; + int y = 0; + if (MenuCategory() == mcChannel) { + x = xa09 - xm05; + y = yb15 - yc04; + } + const cFont *font = cFont::GetFont(fontSml); + if (MenuCategory() == mcMain || MenuCategory() == mcSetup || MenuCategory() == mcCommand || MenuCategory() == mcChannel || MenuCategory() == mcSchedule || MenuCategory() == mcScheduleNow || MenuCategory() == mcScheduleNext || MenuCategory() == mcEvent || MenuCategory() == mcRecording || MenuCategory() == mcRecordingInfo || MenuCategory() == mcRecordingEdit || MenuCategory() == mcTimer || MenuCategory() == mcTimerEdit) { + DrawMainButton(lutText[Setup.ColorKey0], xd00 + x, xd01 + x, xd02 + x, xd03 + x, yd02 + y, yd03 + y, Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font); + DrawMainButton(lutText[Setup.ColorKey1], xd04 + x, xd05 + x, xd06 + x, xd07 + x, yd02 + y, yd03 + y, Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font); + DrawMainButton(lutText[Setup.ColorKey2], xd00 + x, xd01 + x, xd02 + x, xd03 + x, yd04 + y, yd05 + y, Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font); + DrawMainButton(lutText[Setup.ColorKey3], xd04 + x, xd05 + x, xd06 + x, xd07 + x, yd04 + y, yd05 + y, Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font); + } + else { + int h = yb15 - yb14; + 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); + } +} + +void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) +{ + int y = yi00 + Index * lineHeight; + tColor ColorFg, ColorBg; + if (Current) { + if (TwoColors) { + ColorFg = Theme.Color(clrBackground); + ColorBg = Theme.Color(clrMenuFrameBg); + } + else { + ColorFg = Theme.Color(clrMenuItemCurrentFg); + ColorBg = Theme.Color(clrMenuItemCurrentBg); + } + 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 cLCARSNGDisplayMenu::SetScrollbar(int Total, int Offset) +{ + DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total); +} + +void cLCARSNGDisplayMenu::SetEvent(const cEvent *Event) +{ + if (!Event) + return; + const cFont *font = cFont::GetFont(fontOsd); + int xl = xi00; + int y = yi00; + cTextScroller ts; + char t[32]; + snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString()); + 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 cLCARSNGDisplayMenu::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; + cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : ""); + 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 cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::GetTextAreaWidth(void) const +{ + return xi01 - xi00; +} + +const cFont *cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::Flush(void) +{ + + int Width; + int Height; + double Aspect; + cDevice *Device = cDevice::PrimaryDevice(); + cDevice::PrimaryDevice()->GetOsdSize(Width, Height, Aspect); + int xrand = (Width - xa09) / 2; + int yrand = (Height - yb15) / 2; + cRect videoWindowRect( xs00 + xrand, yrand + Gap, xs11 - xs00, yc05 - yrand / 2); + DrawFrameDisplay(); + switch (MenuCategory()) { + case mcMain: + case mcSetup: + case mcCommand: +// case mcChannel: + DrawTimers(); + DrawDevices(); + DrawLiveIndicator(); + DrawSignals(); + case mcSchedule: + case mcScheduleNow: + case mcScheduleNext: + case mcEvent: + case mcRecording: + case mcRecordingInfo: + case mcRecordingEdit: + case mcTimer: + case mcTimerEdit: + if (!Device->Replaying() || Device->Transferring()) { +#if APIVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannel *Channel = Channels->GetByNumber(cDevice::PrimaryDevice()->CurrentChannel()); +#else + const cChannel *Channel = Channels.GetByNumber(cDevice::PrimaryDevice()->CurrentChannel()); +#endif + DrawLive(Channel); + } + else if (cControl *Control = cControl::Control(true)) + DrawPlay(Control); + if (initial) { + availableRect = cDevice::PrimaryDevice()->CanScaleVideo(videoWindowRect); + osd->Flush(); + cDevice::PrimaryDevice()->ScaleVideo(availableRect); + } + else + osd->Flush(); + break; + default: + availableRect = cDevice::PrimaryDevice()->CanScaleVideo(cRect::Null); + osd->Flush(); + cDevice::PrimaryDevice()->ScaleVideo(availableRect); + } + initial = false; +} diff --git a/displaymenu.h b/displaymenu.h new file mode 100644 index 0000000..abdf3f8 --- /dev/null +++ b/displaymenu.h @@ -0,0 +1,137 @@ +/* + * 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. + * + * $Id: skinlcars.c 4.1 2015/09/01 10:07:07 kls Exp $ + */ + +// "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 "lcarsng.h" +#include <vdr/font.h> +#include <vdr/menu.h> +#include <vdr/osd.h> +#if APIVERSNUM > 20101 +#include <vdr/positioner.h> +#endif +#include <vdr/themes.h> +#include <vdr/thread.h> +#include <vdr/tools.h> +#include <vdr/videodir.h> +#include <sys/statvfs.h> +#include <string> + +// --- cLCARSNGDisplayMenu ------------------------------------------------- + +class cLCARSNGDisplayMenu : public cSkinDisplayMenu { +private: + cOsd *osd; + int xa00, xa01, xa02, xa03, xa04, xa05, xa06, xa07, xa08, xa09; + int yt00, yt01, yt02, yt03, yt04, yt05, yt06, yt07, yt08; + 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; + const char *currentTitle; + int lastDiskUsageState; + bool lastDiskAlert; + double lastSystemLoad; +#if APIVERSNUM > 20300 + cStateKey timersStateKey; +#else + int lastTimersState; +#endif + time_t lastSignalDisplay; + int lastLiveIndicatorY; + bool lastLiveIndicatorTransferring; + const cChannel *lastChannel; + cString lastChannelName; + const cEvent *lastEvent; + const cRecording *lastRecording; + cString lastHeader; + int lastSeen; + static cBitmap bmArrowUp, bmArrowDown, bmTransferMode; + void DrawMainFrameUpper(tColor Color); + void DrawMainFrameLower(void); + void DrawMainFrameChannel(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 DrawNumRecordingsInPath(void); + void DrawCountRecordings(void); + void DrawCountTimers(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: + cLCARSNGDisplayMenu(void); + virtual ~cLCARSNGDisplayMenu(); + 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); + }; diff --git a/displayreplay.c b/displayreplay.c index 672b5c5..7ccf33d 100644 --- a/displayreplay.c +++ b/displayreplay.c @@ -235,7 +235,8 @@ void cLCARSNGDisplayReplay::Action(void) { while (Running()) { On = !On; - Flush(); + DrawBlinkingRec(); + osd->Flush(); cCondWait::SleepMs(1000); } } @@ -25,6 +25,7 @@ #include "lcarsng.h" #include "displaychannel.h" +#include "displaymenu.h" #include "displayreplay.h" #include <vdr/font.h> #include <vdr/menu.h> @@ -39,113 +40,12 @@ #include <sys/statvfs.h> #include <string> -cRect availableRect; -cRect videoWindowRect; - cTheme Theme; -// 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: - -THEME_CLR(Theme, clrButtonRedFg, CLR_BLACK); -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); -THEME_CLR(Theme, clrButtonBlueFg, CLR_BLACK); -THEME_CLR(Theme, clrButtonBlueBg, CLR_BLUE); - -// Messages: - -THEME_CLR(Theme, clrMessageStatusFg, CLR_BLACK); -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); -THEME_CLR(Theme, clrMessageErrorFg, CLR_BLACK); -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: +bool TwoColors = false; -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); -THEME_CLR(Theme, clrMenuItemCurrentFg, CLR_MAIN_FRAME); -THEME_CLR(Theme, clrMenuItemCurrentBg, RgbShade(CLR_MENU_ITEMS, -0.5)); -THEME_CLR(Theme, clrMenuItemSelectable, CLR_MENU_ITEMS); -THEME_CLR(Theme, clrMenuItemNonSelectable, CLR_TEXT); -THEME_CLR(Theme, clrMenuScrollbarTotal, RgbShade(CLR_MAIN_FRAME, 0.2)); -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 ------------------------------------------------------ -static bool TwoColors = false; - cOsd *CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1) { cOsd *Osd = cOsdProvider::NewOsd(Left, Top); @@ -291,7 +191,7 @@ void DrawDevicePosition(cOsd *Osd, const cPositioner *Positioner, int x0, int y0 static time_t lastDiskSpaceCheck = 0; static int lastFreeMB = -1; -static int FreeMB(const char *Base, bool Initial) +int FreeMB(const char *Base, bool Initial) { bool Directory = false; char *currentBase = NULL; @@ -357,1443 +257,6 @@ static int FreeMB(const char *Base, bool Initial) return lastFreeMB; } -// --- cLCARSNGDisplayMenu ------------------------------------------------- - -class cLCARSNGDisplayMenu : public cSkinDisplayMenu { -private: - cOsd *osd; - int xa00, xa01, xa02, xa03, xa04, xa05, xa06, xa07, xa08, xa09; - int yt00, yt01, yt02, yt03, yt04, yt05, yt06, yt07, yt08; - 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; - const char *currentTitle; - int lastDiskUsageState; - bool lastDiskAlert; - double lastSystemLoad; -#if APIVERSNUM > 20300 - cStateKey timersStateKey; -#else - int lastTimersState; -#endif - time_t lastSignalDisplay; - int lastLiveIndicatorY; - bool lastLiveIndicatorTransferring; - const cChannel *lastChannel; - cString lastChannelName; - const cEvent *lastEvent; - const cRecording *lastRecording; - cString lastHeader; - int lastSeen; - static cBitmap bmArrowUp, bmArrowDown, bmTransferMode; - void DrawMainFrameUpper(tColor Color); - void DrawMainFrameLower(void); - void DrawMainFrameChannel(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 DrawNumRecordingsInPath(void); - void DrawCountRecordings(void); - void DrawCountTimers(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: - cLCARSNGDisplayMenu(void); - virtual ~cLCARSNGDisplayMenu(); - 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 cLCARSNGDisplayMenu::bmArrowUp(arrowup_xpm); -cBitmap cLCARSNGDisplayMenu::bmArrowDown(arrowdown_xpm); -cBitmap cLCARSNGDisplayMenu::bmTransferMode(play_xpm); - -cLCARSNGDisplayMenu::cLCARSNGDisplayMenu(void) -{ - tallFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize * 1.6); - initial = true; - lastMode = cmUnknown; - lastChannel = NULL; - lastEvent = NULL; - lastRecording = NULL; - lastSeen = -1; -#if APIVERSNUM < 20301 - lastTimersState = -1; -#endif - lastSignalDisplay = 0; - lastLiveIndicatorY = -1; - lastLiveIndicatorTransferring = false; - currentTitle = NULL; - 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; - yt07 = yt06 + Gap; - yt08 = yt07 + 2 * lineHeight; - -// yc00 = yt06 + Gap; - yc00 = yt08 + Gap; -// yc05 = yc00 + 3 * lineHeight + Gap / 2; // Button in der Mitte - yc05 = yc00 + 5 * lineHeight + Gap / 2; - yc04 = yc05 - lineHeight; - yc03 = yc04 - lineHeight; - yc02 = yc04 - d / 4; - yc01 = yc05 - d / 2; - - yc06 = yc05 + Gap; -// yc06 = yc05 + 2 * lineHeight + Gap; // Button in der Mitte - 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; // Load - yb05 = yb04 + 2 * lineHeight; // Load % - 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; // VDR - yb10 = yb13 - Gap - lineHeight; - yb09 = yb10 - Gap; - - // Compensate for large font size: - if (yb09 - yb08 < 2 * lineHeight) { - yb08 = yb06; - yb06 = 0; // drop "RECORDINGS" display" or empty rectangle - } - if (yb09 - yb08 < 2 * lineHeight) { - yb05 = yb09; - yb08 = 0; // drop "LCARSNG" 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; // Bezug MenĂ¼ oben - 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; //cOsd::OsdWidth() - 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; // Bezug Status oben - ys01 = ys00 + lineHeight; - ys02 = ys01 + lineHeight / 2; - ys04 = ys01 + lineHeight; - ys03 = ys04 - Gap; - ys05 = yb15; - - // 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; - - // 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; - xb14 = xb13 + Gap; - - // The color buttons in the main menu: - int r = lineHeight; -// xd07 = xa09; - xd07 = xm05 - Gap; - xd06 = xd07 - r; - xd05 = xd06 - 6 * r; - xd04 = xd05 - r; - xd03 = xd04 - Gap; - xd02 = xd03 - r; - xd01 = xd02 - 6 * r; - xd00 = xd01 - r; - yd00 = yt00; - yd05 = yc04 - 3 * Gap; -// yd05 = yc06 - Gap; // Button in der Mitte - yd04 = yd05 - r; //0.85 * r; // Button in der Mitte - yd03 = yd04 - Gap; - yd02 = yd03 - r; //0.85 * r; // Button in der Mitte - yd01 = yd02 - Gap; - - xs = 0; - - osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop(), xa00, yt00, xa09 - 1, yb15 - 1); - DrawMenuFrame(); -} - -cLCARSNGDisplayMenu::~cLCARSNGDisplayMenu() -{ - delete tallFont; - delete tinyFont; - delete osd; - cDevice::PrimaryDevice()->ScaleVideo(cRect::Null); -} - -void cLCARSNGDisplayMenu::SetMenuCategory(eMenuCategory MenuCategory) -{ - if (initial || MenuCategory != cSkinDisplayMenu::MenuCategory()) { - cSkinDisplayMenu::SetMenuCategory(MenuCategory); - initial = true; - osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, Theme.Color(clrBackground)); - switch (MenuCategory) { - case mcMain: - case mcSetup: - case mcCommand: - osd->DrawRectangle( xs00, 0, xa09, yc06 - 1, clrTransparent); - yi00 = ym03; - yi01 = ym04; - xi00 = xm00; - xi01 = xm03; - xi02 = xm04; - xi03 = xm05; -#if APIVERSNUM < 20301 - lastTimersState = -1; -#else - timersStateKey.Reset(); -#endif - DrawMainFrameLower(); - DrawMainBracket(); - DrawStatusElbows(); - break; - case mcChannel: - osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, clrTransparent); - yi00 = yt04 + lineHeight; - yi01 = ym04; - xi00 = xm00; - xi01 = xm03; - xi02 = xm04; - xi03 = xm05; - DrawMainFrameChannel(); - DrawMainBracket(); - break; - case mcSchedule: - case mcScheduleNow: - case mcScheduleNext: - case mcEvent: - case mcRecording: - case mcRecordingInfo: - case mcRecordingEdit: - case mcTimer: - case mcTimerEdit: - osd->DrawRectangle( xs00, 0, xa09, yc06 - 1, clrTransparent); - yi00 = ym00; - yi01 = ym07; - xi00 = xa03; - xi01 = xa07; - xi02 = xa08; - xi03 = xa09; - DrawMainFrameLower(); - DrawMainBracket(); - break; - default: - yi00 = yt02; - yi01 = yb13; - xi00 = xa03; - xi01 = xa07; - xi02 = xa08; - xi03 = xa09; - DrawMenuFrame(); - } - } -} - -void cLCARSNGDisplayMenu::DrawMainFrameUpper(tColor Color) -{ - // Top left rectangles: -// osd->DrawRectangle(xa00, yt00, xa02 - 1, yt02 - 1, Color); - osd->DrawRectangle(xa00, yt00, xa02 - 1, yt08 - 1, Color); -// osd->DrawRectangle(xa00, yt04, xa02 - 1, yt06 - 1, Color); -// osd->DrawRectangle(xa00, yt07, xa02 - 1, yt08 - 1, Color); - osd->DrawRectangle(xa00, yt02, xa02 - 1, yt04 - 1, Theme.Color(clrBackground)); - osd->DrawRectangle(xa00, yt06, xa02 - 1, yt07 - 1, Theme.Color(clrBackground)); - // 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); - osd->DrawRectangle(xa00, yc00 + 2 * lineHeight, xa02 - 1, yc00 + 2 * lineHeight + Gap, Theme.Color(clrBackground)); - // Upper delimiter: - osd->DrawRectangle(xa06, yc04 + lineHeight / 2, xm03 - 1, yc05 - 1, Color); - osd->DrawRectangle(xm03 + Gap, yc04 + lineHeight / 2, xm07 - 1, yc05 - 1, Color); - // Top right rectangles: - osd->DrawRectangle(xm07, yt00, xm08 - 1, yc04 -Gap - 1, Color); - osd->DrawEllipse (xm07, yc04, xm08 - 1, yc05 - 1, Color, 4); - osd->DrawEllipse (xm05, yc04, xm07 - 1, yc05 - 1 - lineHeight / 2, Color, -4); -} - -void cLCARSNGDisplayMenu::DrawMainFrameLower(void) -{ -// unterer gelber Rahmen - 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, xm03 - 1, yc07 - lineHeight / 2 - 1, frameColor); - osd->DrawRectangle(xm03 + Gap, yc06, xm08 - 1, yc07 - 1, frameColor); - osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor); - // VDR version: - osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor); - osd->DrawText(xa00, yb10, cString::sprintf("%s-%s", "VDR", VDRVERSION), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); - osd->DrawText(xa00, yb15 - lineHeight, "LCARSNG", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); -} - -void cLCARSNGDisplayMenu::DrawMainFrameChannel(void) -{ - const cFont *font = cFont::GetFont(fontOsd); - // 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(xm04, yt00, xm07 - Gap - 1, yt01 - 1, frameColor); - osd->DrawRectangle(xm07, yt00, xm07 + lineHeight / 2 -1, yt01 - 1, frameColor); - osd->DrawEllipse (xm07 + lineHeight / 2, yt00, xm08 - 1, yt01 - 1, frameColor, 5); - // Center part: - osd->DrawRectangle(xa00, yt06 + Gap, xa02 - 1, yc00 - 1 - Gap, frameColor); - osd->DrawRectangle(xa00, yc00, xa02 - 1, yc11 - 1, frameColor); - // VDR version: - osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor); - osd->DrawText(xa00, yb10, cString::sprintf("%s-%s", "VDR", VDRVERSION), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); - osd->DrawText(xa00, yb15 - lineHeight, "LCARSNG", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); -} - -void cLCARSNGDisplayMenu::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); -// osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taBottom | taRight); - osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taCenter); - osd->DrawEllipse(x2, y0, x3 - 1, y1 - 1, ColorBg, 5); -} - -void cLCARSNGDisplayMenu::DrawMenuFrame(void) -{ - const cFont *font = cFont::GetFont(fontOsd); - // 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, yt06 + Gap, xa02 - 1, yc00 - 1 - Gap, frameColor); - 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, cString::sprintf("%s-%s", "VDR", VDRVERSION), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder); - // Color buttons: - 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])); -} - -void cLCARSNGDisplayMenu::DrawDate(void) -{ - cString s = DayDateTime(); - if (initial || !*lastDate || strcmp(s, lastDate)) { - 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 cLCARSNGDisplayMenu::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; - int freemb = FreeMB(currentTitle, initial); - int minutes = 0; - { - LOCK_RECORDINGS_READ; - double MBperMinute = Recordings->MBperMinute(); - minutes = int(double(freemb) / (MBperMinute > 0 ? MBperMinute : MB_PER_MINUTE)); - } - 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, cString::sprintf("%02d%s", DiskUsage, "%"), ColorFg, ColorBg, font, xa02 - xa01, lineHeight, taBottom | taRight | taBorder); - osd->DrawText(xa00, yb03 - lineHeight, freemb ? cString::sprintf("%02d:%02d", minutes / 60, minutes % 60) : cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60), ColorFg, ColorBg, font, xa02 - xa00, 0, taBottom | taRight | taBorder); - lastDiskAlert = DiskAlert; - } - } -} - -void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::DrawNumRecordingsInPath(void) -{ - const cFont *font = cFont::GetFont(fontOsd); - int NumRecordingsInPath = 0; - { -#if APIVERSNUM > 20300 - LOCK_RECORDINGS_READ; -#endif - NumRecordingsInPath = Recordings->GetNumRecordingsInPath(cMenuRecordings::GetActualPath()); - } - osd->DrawText(xm04, ys00, cString::sprintf("%i", NumRecordingsInPath), Theme.Color(clrMenuFrameFg), frameColor, font, xm08 - xm04 - 1, lineHeight, taBottom | taRight | taBorder); -} - -void cLCARSNGDisplayMenu::DrawCountRecordings(void) -{ - if (yb06) { - const cFont *font = cFont::GetFont(fontOsd); - tColor ColorFg = Theme.Color(clrMenuFrameFg); - tColor ColorBg = frameColor; - int CountRecordings = 0; - { -#if APIVERSNUM > 20300 - LOCK_RECORDINGS_READ; -#endif - CountRecordings = Recordings->Count(); - } - osd->DrawText(xa00, yb06, tr("RECORDINGS"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb07 - yb06, taTop | taLeft | taBorder); - osd->DrawText(xa00, yb07 - lineHeight, cString::sprintf("%i", CountRecordings), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); - } -} - -void cLCARSNGDisplayMenu::DrawCountTimers(void) -{ - if (yb08) { - const cFont *font = cFont::GetFont(fontOsd); - tColor ColorFg = Theme.Color(clrMenuFrameFg); - tColor ColorBg = frameColor; - int CountTimers = 0; -#if APIVERSNUM > 20300 - LOCK_TIMERS_READ; - for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { -#else - for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { -#endif - if (Timer->HasFlags(tfActive)) - CountTimers++; - } - osd->DrawText(xa00, yb08, tr("TIMER"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb09 - yb08, taTop | taLeft | taBorder); - osd->DrawText(xa00, yb09 - lineHeight, itoa(CountTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); - } -} - -void cLCARSNGDisplayMenu::DrawMainBracket(void) -{ - const cFont *font = cFont::GetFont(fontOsd); - tColor Color = Theme.Color(clrMenuMainBracket); - int y0, y1, y2, y3; - if (MenuCategory() == mcChannel) { - y0 = yt00 + lineHeight *2; - y1 = y0 + lineHeight / 2; - y2 = y1 + lineHeight / 2; - y3 = y2 + Gap; - } - else { - y0 = ym00; //yc08 - y1 = ym01; //ym00 + lineHeight / 2 - y2 = ym02; //ym01 + lineHeight / 2 - y3 = ym03; //ym02 + Gap - } - if (MenuCategory() != mcSchedule && MenuCategory() != mcScheduleNow && MenuCategory() != mcScheduleNext && MenuCategory() != mcEvent && MenuCategory() != mcRecording && MenuCategory() != mcRecordingInfo && MenuCategory() != mcRecordingEdit && MenuCategory() != mcTimer && MenuCategory() != mcTimerEdit) { - osd->DrawRectangle(xm00, y0, xm01 - 1, y1 - 1, Color); - osd->DrawRectangle(xm02, y0, xm07 - 1, y1 - 1, Color); - osd->DrawEllipse (xm07, y0, xm08 - 1, y2 - 1, Color, 1); - osd->DrawEllipse (xm06, y1, xm07 - 1, y2 - 1, Color, -1); - osd->DrawRectangle(xm07, y3, 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); - } - if (MenuCategory() == mcSetup) - osd->DrawText(xm02, ys00, tr("Setup"), Theme.Color(clrMenuFrameFg), frameColor, font, xm04 - xm02 - Gap, lineHeight, taBottom | taLeft | taBorder); - if (MenuCategory() == mcCommand) - osd->DrawText(xm02, ys00, tr("Commands"), Theme.Color(clrMenuFrameFg), frameColor, font, xm04 - xm02 - Gap, lineHeight, taBottom | taLeft | taBorder); - if (MenuCategory() == mcChannel) - osd->DrawText(xm02, yt00, tr("Channels"), Theme.Color(clrMenuFrameFg), frameColor, font, xm04 - xm02 - Gap, lineHeight, taBottom | taLeft | taBorder); - if (MenuCategory() != mcMain && MenuCategory() != mcSchedule && MenuCategory() != mcScheduleNow && MenuCategory() != mcScheduleNext && MenuCategory() != mcEvent && MenuCategory() != mcRecording && MenuCategory() != mcRecordingInfo && MenuCategory() != mcRecordingEdit && MenuCategory() != mcTimer && MenuCategory() != mcTimerEdit) { - osd->DrawRectangle(xm04 - Gap, y0, xm04, ym01 - 1, clrTransparent); - osd->DrawRectangle(xm04 - Gap, ym06, xm04, ym07 - 1, clrTransparent); - } -} - -void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::DrawFrameDisplay(void) -{ -// if (MenuCategory() != mcChannel) { - 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 - Gap, "LCARSNG", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); - } - } - DrawCountRecordings(); - DrawCountTimers(); - if (MenuCategory() == mcRecording) - DrawNumRecordingsInPath(); -// } -} - -void cLCARSNGDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown) -{ - int x0, x1, tt, tb; - tColor ClearColor; - if (MenuCategory() == mcMain || MenuCategory() == mcSetup || MenuCategory() == mcCommand) { - x0 = xm07; - x1 = xm08; - tt = ym03; - tb = ym04; - ClearColor = Theme.Color(clrMenuMainBracket); - } - else if (MenuCategory() == mcChannel) { - x0 = xm07; - x1 = xm08; - tt = yt04 + lineHeight; - tb = ym04; - ClearColor = Theme.Color(clrMenuMainBracket); - } - else { - x0 = xa02 + Gap; - x1 = x0 + lineHeight / 2; - ClearColor = Theme.Color(clrBackground); - int d = TextFrame; - if (MenuCategory() == mcSchedule || MenuCategory() == mcScheduleNow || MenuCategory() == mcScheduleNext || MenuCategory() == mcEvent || MenuCategory() == mcRecording || MenuCategory() == mcRecordingInfo || MenuCategory() == mcRecordingEdit || MenuCategory() == mcTimer || MenuCategory() == mcTimerEdit) { - tt = yb00; - tb = yb07 + lineHeight + Gap; - } - else { - tt = yc00; - tb = yc11; - if (CanScrollUp) - osd->DrawBitmap(xa02 - bmArrowUp.Width() - d, tt + d, bmArrowUp, Theme.Color(clrMenuScrollbarArrow), frameColor); - else - osd->DrawRectangle(xa02 - bmArrowUp.Width() - d, tt + d, xa02 - d - 1, tt + d + bmArrowUp.Height() - 1, frameColor); - if (CanScrollDown) - osd->DrawBitmap(xa02 - bmArrowDown.Width() - d, tb - d - bmArrowDown.Height(), bmArrowDown, Theme.Color(clrMenuScrollbarArrow), frameColor); - else - osd->DrawRectangle(xa02 - bmArrowDown.Width() - d, tb - d - bmArrowDown.Height(), xa02 - d - 1, tb - 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 && MenuCategory() != mcSetup && MenuCategory() != mcCommand && MenuCategory() != mcChannel) - osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, ClearColor); -} - -void cLCARSNGDisplayMenu::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); - tColor ColorBg = Alert ? Theme.Color(clrAlertBg) : Theme.Color(clrTimerBg); - 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); -#ifdef USE_SWITCHONLY - if (Timer->Flags() & tfSwitchOnly) - Date = cString::sprintf("UST %s", *Date); -#endif - 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); -#if APIVERSNUM > 20300 - // 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); -#endif - // The timer recording indicator: -#if APIVERSNUM > 20300 - else if (Timer->Recording()) -#else - if (Timer->Recording()) -#endif - osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording)); -} - -void cLCARSNGDisplayMenu::DrawTimers(void) -{ -#if APIVERSNUM > 20300 - if (const cTimers *Timers = cTimers::GetTimersRead(timersStateKey)) { -#else - if (Timers.Modified(lastTimersState)) { -#endif - deviceRecording.Clear(); - const cFont *font = cFont::GetFont(fontOsd); -#if APIVERSNUM > 20300 - osd->DrawRectangle(xs00 - (lineHeight - Gap) / 2, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground)); -#else - osd->DrawRectangle(xs00, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground)); -#endif - osd->DrawRectangle(xs07, ys04, xs13 - 1, ys05 - 1, Theme.Color(clrBackground)); -#if APIVERSNUM > 20300 - cSortedTimers SortedTimers(Timers); -#else - cSortedTimers SortedTimers; -#endif - cVector<int> FreeDeviceSlots; - int NumDevices = 0; - 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()) { -#if APIVERSNUM > 20300 - if (Timer->Remote()) { - if (!Device && Timer->HasFlags(tfActive)) { - DrawTimer(Timer, y, false); - FreeDeviceSlots.Append(y); - y += lineHeight + Gap; - } - else - continue; - } - else if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) { -#else - if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) { -#endif - if (!Device || Device == RecordControl->Device()) { - DrawTimer(Timer, y, NumTimers > 0); - NumTimers++; - if (!Device) { - Device = RecordControl->Device(); - deviceOffset[Device->DeviceNumber()] = y; - deviceRecording[Device->DeviceNumber()] = true; - NumDevices++; - } - else - FreeDeviceSlots.Append(y); - y += lineHeight + Gap; - } - else - continue; - } - SortedTimers[i] = NULL; - } - else if (!Device && Timer->HasFlags(tfActive)) { - 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)) { - 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; - NumDevices++; - } - } - } - } - // Total number of active timers: - int NumTimers = 0; -#if APIVERSNUM > 20300 - for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { -#else - for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { -#endif - if (Timer->HasFlags(tfActive)) - NumTimers++; - } - osd->DrawText(xs02, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder); - osd->DrawText(xs08, ys00, itoa(NumDevices), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder); - lastSignalDisplay = 0; - initial = true; // forces redrawing of devices -#if APIVERSNUM > 20300 - timersStateKey.Remove(); -#endif - } -} - -void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::DrawDevices(void) -{ - for (int i = 0; i < cDevice::NumDevices(); i++) { - if (const cDevice *Device = cDevice::GetDevice(i)) { - if (Device->NumProvidedSystems()) - DrawDevice(Device); - } - } -} - -void cLCARSNGDisplayMenu::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)); - if (y > 0) { - 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); - 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; - } - } - lastLiveIndicatorY = y; - lastLiveIndicatorTransferring = Transferring; - } -} - -void cLCARSNGDisplayMenu::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)) { - if (Device->NumProvidedSystems()) { - if (int y = deviceOffset[i]) - DrawDeviceSignal(osd, Device, xs + lineHeight / 2, y, xs11, y + lineHeight, lastSignalStrength[i], lastSignalQuality[i], initial); - } - } - } - lastSignalDisplay = Now; - } -} - -void cLCARSNGDisplayMenu::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, yt02 - yd00, taTop | taRight | taBorder); - } - if (!Channel) - return; - if (initial || Channel != lastChannel || strcmp(Channel->Name(), lastChannelName)) { - osd->DrawText(xa00, yt04, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt06 - yt04, taTop | taRight | taBorder); - osd->DrawText(xa03, yt04, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd07 - xa03, yt06 - yt04, taTop | taLeft); - 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); - osd->DrawText(x, yc00, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), cFont::GetFont(fontOsd), xa02 - x, 2 * lineHeight, taTop | taRight | taBorder); - lastChannel = Channel; - lastChannelName = Channel->Name(); - DrawSeen(0, 0); - } - // The current programme: -#if APIVERSNUM > 20300 - 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(); - } - DrawSeen(Current, Total); -#else - cSchedulesLock SchedulesLock; - if (const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock)) { - 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(); - } - DrawSeen(Current, Total); - } -#endif - } -} - -void cLCARSNGDisplayMenu::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, yt02 - 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, yt04, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd07 - xa03, yt06 - yt04, taTop | taLeft); - DrawInfo(Info->GetEvent(), false); - } - else - osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd07 - xa03, 0, taTop | taLeft); - osd->DrawText(xa00, yt07, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder); - osd->DrawText(xa00, yt07 + 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, yt04, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd07 - xa03, 0, taTop | taLeft); - lastHeader = Header; - } - } -} - -void cLCARSNGDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime) -{ - if (Event) { - const cFont *font = cFont::GetFont(fontOsd); - int y = yt07; - osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd07 - xa03 - lineHeight, lineHeight, taBottom | taLeft); - y += lineHeight; - osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd07 - xa03 - lineHeight, lineHeight, taTop | taLeft); - if (WithTime) { - osd->DrawText(xa00, y - lineHeight, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder); - osd->DrawText(xa00, y, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder); - } - } -} - -void cLCARSNGDisplayMenu::DrawSeen(int Current, int Total) -{ -// Fortschrittsbalken - int Seen = (Total > 0) ? min(xm03 - xm02, int((xm03 - xm02) * double(Current) / Total)) : 0; - 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, xm03 - 1, y1 - 1, Theme.Color(clrBackground)); - lastSeen = Seen; - } -} - -void cLCARSNGDisplayMenu::DrawTextScrollbar(void) -{ - if (textScroller.CanScroll()) - DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.CanScrollUp(), textScroller.CanScrollDown()); -} - -void cLCARSNGDisplayMenu::Scroll(bool Up, bool Page) -{ - cSkinDisplayMenu::Scroll(Up, Page); - DrawTextScrollbar(); -} - -int cLCARSNGDisplayMenu::MaxItems(void) -{ - switch (MenuCategory()) { - case mcMain: - case mcSetup: - case mcCommand: - return (ym04 - ym03) / lineHeight; - break; - case mcChannel: - return (ym04 - yt04 - lineHeight) / lineHeight; - break; - case mcSchedule: - case mcScheduleNow: - case mcScheduleNext: - case mcEvent: - case mcRecording: - case mcRecordingInfo: - case mcRecordingEdit: - case mcTimer: - case mcTimerEdit: - return (ym07 - ym00) / lineHeight; - break; - default: - return (yb13 - yt02) / lineHeight; - } -} - -void cLCARSNGDisplayMenu::Clear(void) -{ - textScroller.Reset(); - osd->DrawRectangle(xi00, yi00, xi03 - 1, yi01 - 1, Theme.Color(clrBackground)); -} - -void cLCARSNGDisplayMenu::SetTitle(const char *Title) -{ - const cFont *font = cFont::GetFont(fontOsd); - initial = true; - currentTitle = NULL; - switch (MenuCategory()) { - case mcMain: - case mcSetup: - case mcCommand: - case mcChannel: - break; - case mcRecording: - currentTitle = Title; - case mcRecordingInfo: - case mcRecordingEdit: - case mcTimerEdit: - case mcSchedule: - case mcScheduleNow: - case mcScheduleNext: - case mcEvent: - osd->DrawRectangle(xs00 - Gap, ys00, xs00, ys01 - 1, Theme.Color(clrBackground)); - osd->DrawText(xs00, ys00, Title, Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs00 - 1, lineHeight, taBottom | taRight); - osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor); - break; - case mcTimer: { - osd->DrawText(xs00, ys00, Title, Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs00, lineHeight, taBottom | taRight | taBorder); - osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor); -/* int NumTimers = 0; -#if APIVERSNUM > 20300 - LOCK_TIMERS_READ; - for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) { -#else - for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { -#endif - if (Timer->HasFlags(tfActive)) - NumTimers++; - } - osd->DrawText(xs00, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder); */ - } - break; - default: - int w = min(font->Width(Title), xa07 - xa06 - Gap); - 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 cLCARSNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) -{ - const char *lutText[] = { Red, Green, Yellow, Blue }; - tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg }; - tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg }; - int x = 0; - int y = 0; - if (MenuCategory() == mcChannel) { - x = xa09 - xm05; - y = yb15 - yc04; - } - const cFont *font = cFont::GetFont(fontSml); - if (MenuCategory() == mcMain || MenuCategory() == mcSetup || MenuCategory() == mcCommand || MenuCategory() == mcChannel || MenuCategory() == mcSchedule || MenuCategory() == mcScheduleNow || MenuCategory() == mcScheduleNext || MenuCategory() == mcEvent || MenuCategory() == mcRecording || MenuCategory() == mcRecordingInfo || MenuCategory() == mcRecordingEdit || MenuCategory() == mcTimer || MenuCategory() == mcTimerEdit) { - DrawMainButton(lutText[Setup.ColorKey0], xd00 + x, xd01 + x, xd02 + x, xd03 + x, yd02 + y, yd03 + y, Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font); - DrawMainButton(lutText[Setup.ColorKey1], xd04 + x, xd05 + x, xd06 + x, xd07 + x, yd02 + y, yd03 + y, Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font); - DrawMainButton(lutText[Setup.ColorKey2], xd00 + x, xd01 + x, xd02 + x, xd03 + x, yd04 + y, yd05 + y, Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font); - DrawMainButton(lutText[Setup.ColorKey3], xd04 + x, xd05 + x, xd06 + x, xd07 + x, yd04 + y, yd05 + y, Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font); - } - else { - int h = yb15 - yb14; - 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); - } -} - -void cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) -{ - int y = yi00 + Index * lineHeight; - tColor ColorFg, ColorBg; - if (Current) { - if (TwoColors) { - ColorFg = Theme.Color(clrBackground); - ColorBg = Theme.Color(clrMenuFrameBg); - } - else { - ColorFg = Theme.Color(clrMenuItemCurrentFg); - ColorBg = Theme.Color(clrMenuItemCurrentBg); - } - 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 cLCARSNGDisplayMenu::SetScrollbar(int Total, int Offset) -{ - DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total); -} - -void cLCARSNGDisplayMenu::SetEvent(const cEvent *Event) -{ - if (!Event) - return; - const cFont *font = cFont::GetFont(fontOsd); - int xl = xi00; - int y = yi00; - cTextScroller ts; - char t[32]; - snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString()); - 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 cLCARSNGDisplayMenu::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; - cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : ""); - 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 cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::GetTextAreaWidth(void) const -{ - return xi01 - xi00; -} - -const cFont *cLCARSNGDisplayMenu::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 cLCARSNGDisplayMenu::Flush(void) -{ - - int Width; - int Height; - double Aspect; - cDevice *Device = cDevice::PrimaryDevice(); - cDevice::PrimaryDevice()->GetOsdSize(Width, Height, Aspect); - int xrand = (Width - xa09) / 2; - int yrand = (Height - yb15) / 2; - cRect videoWindowRect( xs00 + xrand, yrand + Gap, xs11 - xs00, yc05 - yrand / 2); - DrawFrameDisplay(); - switch (MenuCategory()) { - case mcMain: - case mcSetup: - case mcCommand: -// case mcChannel: - DrawTimers(); - DrawDevices(); - DrawLiveIndicator(); - DrawSignals(); - case mcSchedule: - case mcScheduleNow: - case mcScheduleNext: - case mcEvent: - case mcRecording: - case mcRecordingInfo: - case mcRecordingEdit: - case mcTimer: - case mcTimerEdit: - if (!Device->Replaying() || Device->Transferring()) { -#if APIVERSNUM > 20300 - LOCK_CHANNELS_READ; - const cChannel *Channel = Channels->GetByNumber(cDevice::PrimaryDevice()->CurrentChannel()); -#else - const cChannel *Channel = Channels.GetByNumber(cDevice::PrimaryDevice()->CurrentChannel()); -#endif - DrawLive(Channel); - } - else if (cControl *Control = cControl::Control(true)) - DrawPlay(Control); - if (initial) { - availableRect = cDevice::PrimaryDevice()->CanScaleVideo(videoWindowRect); - osd->Flush(); - cDevice::PrimaryDevice()->ScaleVideo(availableRect); - } - else - osd->Flush(); - break; - default: - availableRect = cDevice::PrimaryDevice()->CanScaleVideo(cRect::Null); - osd->Flush(); - cDevice::PrimaryDevice()->ScaleVideo(availableRect); - } - initial = false; -} - // --- cLCARSNGDisplayVolume ----------------------------------------------- class cLCARSNGDisplayVolume : public cSkinDisplayVolume { @@ -193,11 +193,14 @@ THEME_CLR(Theme, clrTrackItemBg, RgbShade(CLR_TRACK, 0.5)); THEME_CLR(Theme, clrTrackItemCurrentFg, CLR_BLACK); THEME_CLR(Theme, clrTrackItemCurrentBg, CLR_TRACK); +extern bool TwoColors; + cOsd *CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1); cFont *CreateTinyFont(int LineHeight); 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); void DrawDeviceSignal(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &LastSignalStrength, int &LastSignalQuality, bool Initial); void DrawDevicePosition(cOsd *Osd, const cPositioner *Positioner, int x0, int y0, int x1, int y1, int &LastCurrent); +int FreeMB(const char *Base, bool Initial); class cLCARSNG : public cSkin { public: |