vdr 2.6.1
skinlcars.c
Go to the documentation of this file.
1/*
2 * skinlcars.c: A VDR skin with Star Trek's "LCARS" layout
3 *
4 * See the main source file 'vdr.c' for copyright information and
5 * how to reach the author.
6 *
7 * $Id: skinlcars.c 5.3 2021/07/01 15:40:46 kls Exp $
8 */
9
10// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures,
11// registered in the United States Patent and Trademark Office, all rights reserved.
12// The LCARS system is based upon the designs of Michael Okuda and his Okudagrams.
13//
14// "LCARS" is short for "Library Computer Access and Retrieval System".
15// Some resources used for writing this skin can be found at
16// http://www.lcars.org.uk
17// http://www.lcarsdeveloper.com
18// http://www.lcarscom.net
19// http://lds-jedi.deviantart.com/art/LCARS-Swept-Tutorial-213936938
20// http://lds-jedi.deviantart.com/art/LCARS-Button-Tutorial-210783437
21// http://zelldenver.deviantart.com/art/LCARS-Color-Standard-179565780
22// http://www.lcars47.com
23// http://www.bracercom.com/tutorial/content/CoherentLCARSInterface/LCARSCoherentInterface.html
24// http://www.bracercom.com/tutorial/content/lcars_manifesto/the_lcars_manifesto.html
25
26#include "skinlcars.h"
27#include "font.h"
28#include "menu.h"
29#include "osd.h"
30#include "positioner.h"
31#include "themes.h"
32#include "videodir.h"
33
34#include "symbols/arrowdown.xpm"
35#include "symbols/arrowup.xpm"
36#include "symbols/audio.xpm"
37#include "symbols/audioleft.xpm"
38#include "symbols/audioright.xpm"
39#include "symbols/audiostereo.xpm"
40#include "symbols/dolbydigital.xpm"
41#include "symbols/encrypted.xpm"
42#include "symbols/ffwd.xpm"
43#include "symbols/ffwd1.xpm"
44#include "symbols/ffwd2.xpm"
45#include "symbols/ffwd3.xpm"
46#include "symbols/frew.xpm"
47#include "symbols/frew1.xpm"
48#include "symbols/frew2.xpm"
49#include "symbols/frew3.xpm"
50#include "symbols/mute.xpm"
51#include "symbols/pause.xpm"
52#include "symbols/play.xpm"
53#include "symbols/radio.xpm"
54#include "symbols/recording.xpm"
55#include "symbols/sfwd.xpm"
56#include "symbols/sfwd1.xpm"
57#include "symbols/sfwd2.xpm"
58#include "symbols/sfwd3.xpm"
59#include "symbols/srew.xpm"
60#include "symbols/srew1.xpm"
61#include "symbols/srew2.xpm"
62#include "symbols/srew3.xpm"
63#include "symbols/teletext.xpm"
64#include "symbols/volume.xpm"
65
66#define Gap (Setup.FontOsdSize / 5 & ~1) // must be even
67#define TextFrame (Setup.FontOsdSize / TEXT_ALIGN_BORDER)
68#define TextSpacing (2 * TextFrame)
69#define SymbolSpacing TextSpacing
70#define ShowSeenExtent (Setup.FontOsdSize / 5) // pixels by which the "seen" bar extends out of the frame
71
72#define DISKUSAGEALERTLIMIT 95 // percent of disk usage above which the display goes into alert mode
73#define SIGNALDISPLAYDELTA 2 // seconds between subsequent device signal displays
74
76
77// Color domains:
78
79#define CLR_BACKGROUND 0x99000000
80#define CLR_MAIN_FRAME 0xFFFF9966
81#define CLR_CHANNEL_FRAME 0xFF8A9EC9
82#define CLR_REPLAY_FRAME 0xFFCC6666
83#define CLR_DATE 0xFF99CCFF
84#define CLR_MENU_ITEMS 0xFF9999FF
85#define CLR_TIMER 0xFF99CCFF
86#define CLR_DEVICE 0xFFF1B1AF
87#define CLR_CHANNEL_NAME 0xFF99CCFF
88#define CLR_EVENT_TITLE 0xFF99CCFF
89#define CLR_EVENT_TIME 0xFFFFCC66
90#define CLR_EVENT_SHORTTEXT 0xFFFFCC66
91#define CLR_TEXT 0xFF99CCFF
92#define CLR_TRACK 0xFFFFCC66
93#define CLR_SEEN 0xFFCC99CC
94#define CLR_ALERT 0xFFFF0000
95#define CLR_EXPOSED 0xFF990000
96#define CLR_WHITE 0xFFFFFFFF
97#define CLR_RED 0xFFCC6666
98#define CLR_GREEN 0xFFA0FF99
99#define CLR_YELLOW 0xFFF1DF60
100#define CLR_BLUE 0xFF9A99FF
101#define CLR_BLACK 0xFF000000
102
103// General colors:
104
110THEME_CLR(Theme, clrDeviceFg, CLR_BLACK);
112THEME_CLR(Theme, clrSignalValue, CLR_GREEN);
113THEME_CLR(Theme, clrSignalRest, CLR_RED);
115THEME_CLR(Theme, clrTrackName, CLR_TRACK);
122THEME_CLR(Theme, clrEventDescription, CLR_TEXT);
123
124// Buttons:
125
126THEME_CLR(Theme, clrButtonRedFg, CLR_BLACK);
127THEME_CLR(Theme, clrButtonRedBg, CLR_RED);
128THEME_CLR(Theme, clrButtonGreenFg, CLR_BLACK);
129THEME_CLR(Theme, clrButtonGreenBg, CLR_GREEN);
130THEME_CLR(Theme, clrButtonYellowFg, CLR_BLACK);
131THEME_CLR(Theme, clrButtonYellowBg, CLR_YELLOW);
132THEME_CLR(Theme, clrButtonBlueFg, CLR_BLACK);
133THEME_CLR(Theme, clrButtonBlueBg, CLR_BLUE);
134
135// Messages:
136
137THEME_CLR(Theme, clrMessageStatusFg, CLR_BLACK);
138THEME_CLR(Theme, clrMessageStatusBg, CLR_BLUE);
139THEME_CLR(Theme, clrMessageInfoFg, CLR_BLACK);
140THEME_CLR(Theme, clrMessageInfoBg, CLR_GREEN);
141THEME_CLR(Theme, clrMessageWarningFg, CLR_BLACK);
142THEME_CLR(Theme, clrMessageWarningBg, CLR_YELLOW);
143THEME_CLR(Theme, clrMessageErrorFg, CLR_BLACK);
144THEME_CLR(Theme, clrMessageErrorBg, CLR_RED);
145
146// Volume:
147
149THEME_CLR(Theme, clrVolumeSymbol, CLR_BLACK);
150THEME_CLR(Theme, clrVolumeBarUpper, RgbShade(CLR_MAIN_FRAME, -0.2));
151THEME_CLR(Theme, clrVolumeBarLower, CLR_GREEN);
152
153// Channel display:
154
155THEME_CLR(Theme, clrChannelFrameFg, CLR_BLACK);
156THEME_CLR(Theme, clrChannelFrameBg, CLR_CHANNEL_FRAME);
157THEME_CLR(Theme, clrChannelSymbolOn, CLR_BLACK);
158THEME_CLR(Theme, clrChannelSymbolOff, RgbShade(CLR_CHANNEL_FRAME, -0.2));
159THEME_CLR(Theme, clrChannelSymbolRecFg, CLR_WHITE);
160THEME_CLR(Theme, clrChannelSymbolRecBg, CLR_RED);
161
162// Menu:
163
164THEME_CLR(Theme, clrMenuFrameFg, CLR_BLACK);
167THEME_CLR(Theme, clrMenuMainBracket, CLR_MENU_ITEMS);
168THEME_CLR(Theme, clrMenuTimerRecording, CLR_DEVICE);
169THEME_CLR(Theme, clrMenuDeviceRecording, CLR_TIMER);
170THEME_CLR(Theme, clrMenuItemCurrentFg, CLR_MAIN_FRAME);
171THEME_CLR(Theme, clrMenuItemCurrentBg, RgbShade(CLR_MENU_ITEMS, -0.5));
172THEME_CLR(Theme, clrMenuItemSelectable, CLR_MENU_ITEMS);
173THEME_CLR(Theme, clrMenuItemNonSelectable, CLR_TEXT);
174THEME_CLR(Theme, clrMenuScrollbarTotal, RgbShade(CLR_MAIN_FRAME, 0.2));
175THEME_CLR(Theme, clrMenuScrollbarShown, CLR_SEEN);
176THEME_CLR(Theme, clrMenuScrollbarArrow, CLR_BLACK);
177THEME_CLR(Theme, clrMenuText, CLR_TEXT);
178
179// Replay display:
180
181THEME_CLR(Theme, clrReplayFrameFg, CLR_BLACK);
182THEME_CLR(Theme, clrReplayFrameBg, CLR_REPLAY_FRAME);
183THEME_CLR(Theme, clrReplayPosition, CLR_SEEN);
184THEME_CLR(Theme, clrReplayJumpFg, CLR_BLACK);
185THEME_CLR(Theme, clrReplayJumpBg, CLR_SEEN);
186THEME_CLR(Theme, clrReplayProgressSeen, CLR_SEEN);
187THEME_CLR(Theme, clrReplayProgressRest, RgbShade(CLR_WHITE, -0.2));
188THEME_CLR(Theme, clrReplayProgressSelected, CLR_EXPOSED);
189THEME_CLR(Theme, clrReplayProgressMark, CLR_BLACK);
190THEME_CLR(Theme, clrReplayProgressCurrent, CLR_EXPOSED);
191
192// Track display:
193
194THEME_CLR(Theme, clrTrackFrameFg, CLR_BLACK);
195THEME_CLR(Theme, clrTrackFrameBg, CLR_TRACK);
196THEME_CLR(Theme, clrTrackItemFg, CLR_BLACK);
197THEME_CLR(Theme, clrTrackItemBg, RgbShade(CLR_TRACK, 0.5));
198THEME_CLR(Theme, clrTrackItemCurrentFg, CLR_BLACK);
199THEME_CLR(Theme, clrTrackItemCurrentBg, CLR_TRACK);
200
201// --- Helper functions ------------------------------------------------------
202
203static bool TwoColors = false;
204
205static cOsd *CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1)
206{
207 cOsd *Osd = cOsdProvider::NewOsd(Left, Top);
208 int Bpp[] = { 32, 8, 4, 2, 1 };
209 tArea Area = { x0, y0, x1, y1, 0 };
210 for (unsigned int i = 0; i < sizeof(Bpp) / sizeof(int); i++) {
211 Area.bpp = Bpp[i];
212 if (Osd->CanHandleAreas(&Area, 1) == oeOk) {
213 Osd->SetAreas(&Area, 1);
214 Osd->SetAntiAliasGranularity(20, 16);
215 TwoColors = Area.bpp == 1;
216 break;
217 }
218 }
219 return Osd;
220}
221
222static cFont *CreateTinyFont(int LineHeight)
223{
224 // Creates a font that is not higher than half of LineHeight.
225 LineHeight /= 2;
226 int Height = LineHeight;
227 for (;;) {
228 cFont *TinyFont = cFont::CreateFont(Setup.FontOsd, Height);
229 if (Height < 2 || TinyFont->Height() <= LineHeight)
230 return TinyFont;
231 delete TinyFont;
232 Height -= 1;
233 }
234}
235
236static 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)
237{
238 cString DeviceType = Device->DeviceType();
239 cCamSlot *CamSlot = Device->CamSlot();
240 if (Initial || strcmp(DeviceType, LastDeviceType) || CamSlot != LastCamSlot) {
241 const cFont *font = cFont::GetFont(fontOsd);
242 tColor ColorFg = Theme.Color(clrDeviceFg);
243 tColor ColorBg = Theme.Color(clrDeviceBg);
244 Osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, ColorBg);
245 int x = x0;
246 // Device number:
247 cString Nr = itoa(Device->DeviceNumber() + 1);
248 int w = max(font->Width(Nr), y1 - y0);
249 Osd->DrawText(x, y0, Nr, ColorFg, ColorBg, font, w, y1 - y0, taCenter);
250 x += w;
251 // Device type:
252 Osd->DrawText(x, y0, DeviceType, ColorFg, ColorBg, TinyFont);
253 xs = max(xs, x + TinyFont->Width(DeviceType));
254 LastDeviceType = DeviceType;
255 // CAM:
256 if (CamSlot) {
257 cString s = cString::sprintf("CAM %d", CamSlot->MasterSlotNumber());
258 Osd->DrawText(x, y1 - TinyFont->Height(), s, ColorFg, ColorBg, TinyFont);
259 xs = max(xs, x + TinyFont->Width(s));
260 }
261 LastCamSlot = CamSlot;
262 return true;
263 }
264 return false;
265}
266
267static void DrawDeviceSignal(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &LastSignalStrength, int &LastSignalQuality, bool Initial)
268{
269 int SignalStrength = Device->SignalStrength();
270 int SignalQuality = Device->SignalQuality();
271 int d = max((y1 - y0) / 10, 1);
272 int x00 = x0 + d;
273 int x01 = x1 - d;
274 int h = (y1 - y0 - 3 * d) / 2;
275 int w = x01 - x00;
276 int y00 = y0 + d;
277 int y01 = y00 + h;
278 int y03 = y1 - d;
279 int y02 = y03 - h;
280 tColor ColorSignalValue, ColorSignalRest;
281 if (TwoColors) {
282 ColorSignalValue = Theme.Color(clrBackground);
283 ColorSignalRest = Theme.Color(clrMenuFrameBg);
284 }
285 else {
286 ColorSignalValue = Theme.Color(clrSignalValue);
287 ColorSignalRest = Theme.Color(clrSignalRest);
288 }
289 if (SignalStrength >= 0 && (Initial || SignalStrength != LastSignalStrength)) {
290 int s = SignalStrength * w / 100;
291 Osd->DrawRectangle(x00, y00, x00 + s - 1, y01 - 1, ColorSignalValue);
292 Osd->DrawRectangle(x00 + s, y00, x01 - 1, y01 - 1, ColorSignalRest);
293 LastSignalStrength = SignalStrength;
294 }
295 if (SignalQuality >= 0 && (Initial || SignalQuality != LastSignalQuality)) {
296 int q = SignalQuality * w / 100;
297 Osd->DrawRectangle(x00, y02, x00 + q - 1, y03 - 1, ColorSignalValue);
298 Osd->DrawRectangle(x00 + q, y02, x01 - 1, y03 - 1, ColorSignalRest);
299 LastSignalQuality = SignalQuality;
300 }
301}
302
303static void DrawDevicePosition(cOsd *Osd, const cPositioner *Positioner, int x0, int y0, int x1, int y1, int &LastCurrent)
304{
305 int HorizonLeft = Positioner->HorizonLongitude(cPositioner::pdLeft);
306 int HorizonRight = Positioner->HorizonLongitude(cPositioner::pdRight);
307 int HardLimitLeft = cPositioner::NormalizeAngle(HorizonLeft - Positioner->HardLimitLongitude(cPositioner::pdLeft));
308 int HardLimitRight = cPositioner::NormalizeAngle(Positioner->HardLimitLongitude(cPositioner::pdRight) - HorizonRight);
309 int HorizonDelta = cPositioner::NormalizeAngle(HorizonLeft - HorizonRight);
310 int Current = cPositioner::NormalizeAngle(HorizonLeft - Positioner->CurrentLongitude());
311 int Target = cPositioner::NormalizeAngle(HorizonLeft - Positioner->TargetLongitude());
312 int d = (y1 - y0) / 2;
313 int w = x1 - x0 - 2 * d;
314 int l = max(x0 + d, x0 + d + w * HardLimitLeft / HorizonDelta);
315 int r = min(x1 - d, x1 - d - w * HardLimitRight / HorizonDelta) - 1;
316 int c = constrain(x0 + d + w * Current / HorizonDelta, l, r);
317 int t = constrain(x0 + d + w * Target / HorizonDelta, l, r);
318 if (c == LastCurrent)
319 return;
320 if (c > t)
321 swap(c, t);
322 tColor ColorRange, ColorMove;
323 if (TwoColors) {
324 ColorRange = Theme.Color(clrChannelFrameBg);
325 ColorMove = Theme.Color(clrBackground);
326 }
327 else {
328 ColorRange = Theme.Color(clrChannelFrameBg);
329 ColorMove = Theme.Color(clrDeviceBg);
330 }
331 Osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, Theme.Color(clrBackground));
332 Osd->DrawEllipse(l - d, y0, l, y1 - 1, ColorRange, 7);
333 Osd->DrawRectangle(l, y0, r, y1 - 1, ColorRange);
334 Osd->DrawEllipse(r, y0, r + d, y1 - 1, ColorRange, 5);
335 Osd->DrawEllipse(c - d, y0, c, y1 - 1, ColorMove, 7);
336 Osd->DrawRectangle(c, y0, t, y1 - 1, ColorMove);
337 Osd->DrawEllipse(t, y0, t + d, y1 - 1, ColorMove, 5);
338 LastCurrent = c;
339}
340
341// --- cSkinLCARSDisplayChannel ----------------------------------------------
342
344private:
348 int xs; // starting column for signal display
368 void DrawDate(void);
369 void DrawTrack(void);
370 void DrawSeen(int Current, int Total);
371 void DrawDevice(void);
372 void DrawSignal(void);
373public:
374 cSkinLCARSDisplayChannel(bool WithInfo);
376 virtual void SetChannel(const cChannel *Channel, int Number);
377 virtual void SetEvents(const cEvent *Present, const cEvent *Following);
378 virtual void SetMessage(eMessageType Type, const char *Text);
379 virtual void SetPositioner(const cPositioner *Positioner);
380 virtual void Flush(void);
381 };
382
389
391{
393 initial = true;
394 present = NULL;
395 lastSeen = -1;
397 lastDeviceNumber = -1;
398 lastCamSlot = NULL;
402 memset(&lastTrackId, 0, sizeof(lastTrackId));
403 const cFont *font = cFont::GetFont(fontOsd);
404 withInfo = WithInfo;
405 lineHeight = font->Height();
407 frameColor = Theme.Color(clrChannelFrameBg);
408 message = false;
409 int d = 5 * lineHeight;
410 xc00 = 0;
411 xc01 = xc00 + d / 2;
412 xc02 = xc00 + d;
413 xc03 = xc02 + lineHeight;
414 xc04 = xc02 + d / 4;
415 xc05 = xc02 + d;
416 xc06 = xc05 + Gap;
418 xc14 = xc15 - lineHeight;
419 xc13 = xc14 - Gap;
420 xc07 = (xc15 + xc00) / 2;
421 xc08 = xc07 + Gap;
422 xc09 = xc08 + lineHeight;
423 xc10 = xc09 + Gap;
424 xc11 = (xc10 + xc13 + Gap) / 2;
425 xc12 = xc11 + Gap;
426
427 yc00 = 0;
428 yc01 = yc00 + lineHeight;
429 yc02 = yc01 + lineHeight;
430 yc03 = yc02 + Gap;
431 yc04 = yc03 + 2 * lineHeight;
432 yc05 = yc04 + Gap;
433 yc06 = yc05 + 2 * lineHeight;
434
435 yc07 = yc06 + Gap;
436 yc12 = yc07 + 3 * lineHeight + Gap / 2;
437 yc11 = yc12 - lineHeight;
438 yc10 = yc11 - lineHeight;
439 yc09 = yc11 - d / 4;
440 yc08 = yc12 - d / 2;
441
442 xs = 0;
443
444 int y1 = withInfo ? yc12 : yc02;
445 int y0 = cOsd::OsdTop() + (Setup.ChannelInfoPos ? 0 : cOsd::OsdHeight() - y1);
446 osd = CreateOsd(cOsd::OsdLeft(), y0, xc00, yc00, xc15 - 1, y1 - 1);
448 // Rectangles:
450 if (withInfo) {
453 // Elbow:
456 osd->DrawEllipse (xc00, yc08, xc01 - 1, yc12 - 1, frameColor, 3);
458 osd->DrawEllipse (xc02, yc09, xc04 - 1, yc11 - 1, frameColor, -3);
460 // Status area:
463 osd->DrawRectangle(xc10, yc11, xc11 - 1, yc12 - 1, Theme.Color(clrDeviceBg));
464 osd->DrawRectangle(xc12, yc11, xc13 - 1, yc12 - 1, Theme.Color(clrDateBg));
467 osd->DrawEllipse (xc14 + lineHeight / 2, yc11, xc15 - 1, yc12 - 1, frameColor, 5);
468 }
469 // Icons:
472 osd->DrawEllipse (xc14 + lineHeight / 2, yc00, xc15 - 1, yc01 - 1, frameColor, 5);
473}
474
476{
477 delete tallFont;
478 delete tinyFont;
479 delete osd;
480}
481
483{
484 cString s = DayDateTime();
485 if (initial || !*lastDate || strcmp(s, lastDate)) {
487 lastDate = s;
488 }
489}
490
492{
494 const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
495 if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
496 osd->DrawText(xc03, yc07, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc07 - xc03);
497 strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
498 }
499}
500
501void cSkinLCARSDisplayChannel::DrawSeen(int Current, int Total)
502{
503 if (lastCurrentPosition >= 0)
504 return; // to not interfere with SetPositioner()
505 int Seen = (Total > 0) ? min(xc07 - xc06, int((xc07 - xc06) * double(Current) / Total)) : 0;
506 if (initial || Seen != lastSeen) {
507 int y0 = yc11 - ShowSeenExtent;
508 int y1 = yc11 + lineHeight / 2 - Gap / 2;
509 osd->DrawRectangle(xc06, y0, xc06 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
510 osd->DrawRectangle(xc06 + Seen, y0, xc07 - 1, y1 - 1, Theme.Color(clrBackground));
511 lastSeen = Seen;
512 }
513}
514
516{
517 const cDevice *Device = cDevice::ActualDevice();
519 lastDeviceNumber = Device->DeviceNumber();
520 // Make sure signal meters are redrawn:
524 }
525}
526
528{
529 time_t Now = time(NULL);
530 if (Now != lastSignalDisplay) {
532 lastSignalDisplay = Now;
533 }
534}
535
536void cSkinLCARSDisplayChannel::SetChannel(const cChannel *Channel, int Number)
537{
538 int x = xc13;
539 int xi = x - SymbolSpacing -
545 osd->DrawRectangle(xi, yc00, xc13 - 1, yc01 - 1, frameColor);
546 if (Channel && !Channel->GroupSep()) {
547 bool rec = cRecordControls::Active();
549 osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : frameColor);
551 osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmEncrypted.Height()) / 2, bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
553 osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmDolbyDigital.Height()) / 2, bmDolbyDigital, Theme.Color(Channel->Dpid(0) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
554 x -= bmAudio.Width() + SymbolSpacing;
555 osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmAudio.Height()) / 2, bmAudio, Theme.Color(Channel->Apid(1) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
556 if (Channel->Vpid()) {
558 osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
559 }
560 else if (Channel->Apid(0)) {
561 x -= bmRadio.Width() + SymbolSpacing;
562 osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor);
563 }
564 }
565 cString ChNumber("");
566 cString ChName("");
567 if (Channel) {
568 ChName = Channel->Name();
569 if (!Channel->GroupSep())
570 ChNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : "");
571 }
572 else if (Number)
573 ChNumber = cString::sprintf("%d-", Number);
574 else
575 ChName = ChannelString(NULL, 0);
576 osd->DrawText(xc00, yc00, ChNumber, Theme.Color(clrChannelFrameFg), frameColor, tallFont, xc02 - xc00, yc02 - yc00, taTop | taRight | taBorder);
577 osd->DrawText(xc03, yc00, ChName, Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xi - xc03 - lineHeight, 0, taTop | taLeft);
579 if (withInfo) {
580 if (Channel) {
581 int x = xc00 + (yc10 - yc09); // compensate for the arc
582 osd->DrawText(x, yc07, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - x, yc10 - yc07, taTop | taRight | taBorder);
583 }
584 DrawDevice();
585 }
586}
587
588void cSkinLCARSDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
589{
590 if (!withInfo)
591 return;
592 if (present != Present)
593 lastSeen = -1;
594 present = Present;
595 for (int i = 0; i < 2; i++) {
596 const cEvent *e = !i ? Present : Following;
597 int y = !i ? yc03 : yc05;
598 if (e) {
601 osd->DrawText(xc03, y + lineHeight, e->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xc13 - xc03);
602 }
603 else {
606 }
607 }
608}
609
611{
612 if (Text) {
613 int x0, x1, y0, y1, y2;
614 if (withInfo) {
615 x0 = xc06;
616 x1 = xc13;
617 y0 = yc11 - ShowSeenExtent;
618 y1 = yc11;
619 y2 = yc12;
620 }
621 else {
622 x0 = xc03;
623 x1 = xc13;
624 y0 = y1 = yc00;
625 y2 = yc02;
626 }
627 osd->SaveRegion(x0, y0, x1 - 1, y2 - 1);
628 if (withInfo)
629 osd->DrawRectangle(xc06, y0, xc07, y1 - 1, Theme.Color(clrBackground)); // clears the "seen" bar
630 osd->DrawText(x0, y1, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), x1 - x0, y2 - y1, taCenter);
631 message = true;
632 }
633 else {
635 message = false;
636 }
637}
638
640{
641 if (Positioner) {
642 int y0 = yc11 - ShowSeenExtent;
643 int y1 = yc11 + lineHeight / 2 - Gap / 2;
644 DrawDevicePosition(osd, Positioner, xc06, y0, xc07, y1, lastCurrentPosition);
645 }
646 else {
648 initial = true; // to have DrawSeen() refresh the progress bar
649 }
650 return;
651}
652
654{
655 if (withInfo) {
656 if (!message) {
657 DrawDate();
658 DrawTrack();
659 DrawDevice();
660 DrawSignal();
661 int Current = 0;
662 int Total = 0;
663 if (present) {
664 time_t t = time(NULL);
665 if (t > present->StartTime())
666 Current = t - present->StartTime();
667 Total = present->Duration();
668 }
669 DrawSeen(Current, Total);
670 }
671 }
672 osd->Flush();
673 initial = false;
674}
675
676// --- cSkinLCARSDisplayMenu -------------------------------------------------
677
679private:
690 int yi00, yi01;
694 int xs; // starting column for signal display
724 void DrawMainFrameUpper(tColor Color);
725 void DrawMainFrameLower(void);
726 void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font);
727 void DrawMenuFrame(void);
728 void DrawMainBracket(void);
729 void DrawStatusElbows(void);
730 void DrawDate(void);
731 void DrawDisk(void);
732 void DrawLoad(void);
733 void DrawFrameDisplay(void);
734 void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown);
735 void DrawTimer(const cTimer *Timer, int y, bool MultiRec);
736 void DrawTimers(void);
737 void DrawDevice(const cDevice *Device);
738 void DrawDevices(void);
739 void DrawLiveIndicator(void);
740 void DrawSignals(void);
741 void DrawLive(const cChannel *Channel);
742 void DrawPlay(cControl *Control);
743 void DrawInfo(const cEvent *Event, bool WithTime);
744 void DrawSeen(int Current, int Total);
745 void DrawTextScrollbar(void);
746public:
748 virtual ~cSkinLCARSDisplayMenu();
749 virtual void Scroll(bool Up, bool Page);
750 virtual int MaxItems(void);
751 virtual void Clear(void);
753 virtual void SetTitle(const char *Title);
754 virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
755 virtual void SetMessage(eMessageType Type, const char *Text);
756 virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
757 virtual void SetScrollbar(int Total, int Offset);
758 virtual void SetEvent(const cEvent *Event);
759 virtual void SetRecording(const cRecording *Recording);
760 virtual void SetText(const char *Text, bool FixedFont);
761 virtual int GetTextAreaWidth(void) const;
762 virtual const cFont *GetTextAreaFont(bool FixedFont) const;
763 virtual void Flush(void);
764 };
765
769
771{
773 initial = true;
775 lastChannel = NULL;
776 lastEvent = NULL;
777 lastRecording = NULL;
778 lastSeen = -1;
783 lastDiskAlert = false;
784 lastSystemLoad = -1;
785 const cFont *font = cFont::GetFont(fontOsd);
786 lineHeight = font->Height();
788 frameColor = Theme.Color(clrMenuFrameBg);
789 currentIndex = -1;
790 // The outer frame:
791 int d = 5 * lineHeight;
792 xa00 = 0;
793 xa01 = xa00 + d / 2;
794 xa02 = xa00 + d;
795 xa03 = xa02 + lineHeight;
796 xa04 = xa02 + d / 4;
797 xa05 = xa02 + d;
798 xa06 = xa05 + Gap;
800 xa08 = xa09 - lineHeight;
801 xa07 = xa08 - Gap;
802
803 yt00 = 0;
804 yt01 = yt00 + lineHeight;
805 yt02 = yt01 + lineHeight;
806 yt03 = yt01 + d / 4;
807 yt04 = yt02 + Gap;
808 yt05 = yt00 + d / 2;
809 yt06 = yt04 + 2 * lineHeight;
810
811 yc00 = yt06 + Gap;
812 yc05 = yc00 + 3 * lineHeight + Gap / 2;
813 yc04 = yc05 - lineHeight;
814 yc03 = yc04 - lineHeight;
815 yc02 = yc04 - d / 4;
816 yc01 = yc05 - d / 2;
817
818 yc06 = yc05 + Gap;
819 yc07 = yc06 + lineHeight;
820 yc08 = yc07 + lineHeight;
821 yc09 = yc07 + d / 4;
822 yc10 = yc06 + d / 2;
823 yc11 = yc06 + 3 * lineHeight + Gap / 2;
824
825 yb00 = yc11 + Gap;
826 yb01 = yb00 + 2 * lineHeight;
827 yb02 = yb01 + Gap;
828 yb03 = yb02 + 2 * lineHeight;
829 yb04 = yb03 + Gap;
830 yb05 = yb04 + 2 * lineHeight;
831 yb06 = yb05 + Gap;
832 yb07 = yb06 + 2 * lineHeight;
833 yb08 = yb07 + Gap;
834
836 yb14 = yb15 - lineHeight;
837 yb13 = yb14 - lineHeight;
838 yb12 = yb14 - d / 4;
839 yb11 = yb15 - d / 2;
840 yb10 = yb13 - Gap - 2 * lineHeight;
841 yb09 = yb10 - Gap;
842
843 // Compensate for large font size:
844 if (yb09 - yb08 < 2 * lineHeight) {
845 yb08 = yb06;
846 yb06 = 0; // drop empty rectangle
847 }
848 if (yb09 - yb08 < 2 * lineHeight) {
849 yb05 = yb09;
850 yb08 = 0; // drop "LCARS" display
851 }
852 if (yb05 - yb04 < 2 * lineHeight) {
853 yb03 = yb09;
854 yb04 = 0; // drop "LOAD" display
855 }
856 if (yb03 - yb02 < 2 * lineHeight) {
857 yb01 = yb09;
858 yb02 = 0; // drop "DISK" display
859 }
860 // Anything else is just insanely large...
861
862 // The main command menu:
863 xm00 = xa03;
864 xm01 = xa05;
865 xm02 = xa06;
866 xm08 = (xa09 + xa00) / 2;
867 xm07 = xm08 - lineHeight;
868 xm06 = xm07 - lineHeight / 2;
869 xm05 = xm06 - lineHeight / 2;
870 xm04 = xm05 - lineHeight;
871 xm03 = xm04 - Gap;
872 ym00 = yc08;
873 ym01 = ym00 + lineHeight / 2;
874 ym02 = ym01 + lineHeight / 2;
875 ym03 = ym02 + Gap;
876 ym07 = yb15;
877 ym06 = ym07 - lineHeight / 2;
878 ym05 = ym06 - lineHeight / 2;
879 ym04 = ym05 - Gap;
880
881 // The status area:
882 xs00 = xm08 + Gap + lineHeight + Gap;
883 xs13 = xa09;
884 xs12 = xa08;
885 xs11 = xa07;
886 xs05 = (xs00 + xs11 + Gap) / 2;
887 xs04 = xs05 - lineHeight / 2;
888 xs03 = xs04 - lineHeight / 2;
889 xs02 = xs03 - 2 * lineHeight;
890 xs01 = xs02 - Gap;
891 xs06 = xs05 + Gap;
892 xs07 = xs06 + lineHeight / 2;
893 xs08 = xs07 + lineHeight / 2;
894 xs09 = xs08 + 2 * lineHeight;
895 xs10 = xs09 + Gap;
896 ys00 = yc06;
897 ys01 = ys00 + lineHeight;
898 ys02 = ys01 + lineHeight / 2;
899 ys04 = ys01 + lineHeight;
900 ys03 = ys04 - Gap;
901 ys05 = yb15;
902
903 // The item area (just to have them initialized, actual setting will be done in SetMenuCategory():
904
905 xi00 = 0;
906 xi01 = 0;
907 xi02 = 0;
908 xi03 = 1;
909 yi00 = 0;
910 yi01 = 1;
911
912 // The color buttons in submenus:
913 xb00 = xa06;
914 xb15 = xa07;
915 int w = (xa08 - xa06) / 4;
916 xb01 = xb00 + lineHeight / 2;
917 xb02 = xb01 + Gap;
918 xb04 = xb00 + w;
919 xb03 = xb04 - Gap;
920 xb05 = xb04 + lineHeight / 2;
921 xb06 = xb05 + Gap;
922 xb08 = xb04 + w;
923 xb07 = xb08 - Gap;
924 xb09 = xb08 + lineHeight / 2;
925 xb10 = xb09 + Gap;
926 xb12 = xb08 + w;
927 xb11 = xb12 - Gap;
928 xb13 = xb12 + lineHeight / 2;
929 xb14 = xb13 + Gap;
930
931 // The color buttons in the main menu:
932 int r = lineHeight;
933 xd07 = xa09;
934 xd06 = xd07 - r;
935 xd05 = xd06 - 4 * r;
936 xd04 = xd05 - r;
937 xd03 = xd04 - Gap;
938 xd02 = xd03 - r;
939 xd01 = xd02 - 4 * r;
940 xd00 = xd01 - r;
941 yd00 = yt00;
942 yd05 = yc04 - Gap;
943 yd04 = yd05 - 2 * r;
944 yd03 = yd04 - Gap;
945 yd02 = yd03 - 2 * r;
946 yd01 = yd02 - Gap;
947
948 xs = 0;
949
951}
952
954{
955 delete tallFont;
956 delete tinyFont;
957 delete osd;
958}
959
961{
964 initial = true;
966 if (MenuCategory == mcMain) {
967 yi00 = ym03;
968 yi01 = ym04;
969 xi00 = xm00;
970 xi01 = xm03;
971 xi02 = xm04;
972 xi03 = xm05;
977 }
978 else {
979 yi00 = yt02;
980 yi01 = yb13;
981 xi00 = xa03;
982 xi01 = xa07;
983 xi02 = xa08;
984 xi03 = xa09;
986 }
987 }
988}
989
991{
992 // Top left rectangles:
993 osd->DrawRectangle(xa00, yt00, xa02 - 1, yt02 - 1, Color);
994 osd->DrawRectangle(xa00, yt04, xa02 - 1, yt06 - 1, Color);
995 // Upper elbow:
996 osd->DrawRectangle(xa00, yc00, xa01 - 1, yc01 - 1, Color);
997 osd->DrawEllipse (xa00, yc01, xa01 - 1, yc05 - 1, Color, 3);
998 osd->DrawRectangle(xa01, yc00, xa02 - 1, yc05 - 1, Color);
999 osd->DrawEllipse (xa02, yc02, xa04 - 1, yc04 - 1, Color, -3);
1000 osd->DrawRectangle(xa02, yc04, xa05 - 1, yc05 - 1, Color);
1001 // Upper delimiter:
1002 osd->DrawRectangle(xa06, yc04 + lineHeight / 2, xm08 - 1, yc05 - 1, Color);
1003 osd->DrawRectangle(xm08 + Gap, yc04, xs00 - Gap - 1, yc05 - 1, Color);
1004 osd->DrawRectangle(xs00, yc04, xs05 - 1, yc05 - 1, Color);
1005 osd->DrawRectangle(xs06, yc04, xa07 - 1, yc05 - 1, Color);
1006 osd->DrawRectangle(xa08, yc04, xa09 - 1, yc05 - 1, Color);
1007}
1008
1010{
1011 const cFont *font = cFont::GetFont(fontOsd);
1012 // Lower elbow:
1014 osd->DrawEllipse (xa00, yc06, xa01 - 1, yc10 - 1, frameColor, 2);
1016 osd->DrawEllipse (xa02, yc07, xa04 - 1, yc09 - 1, frameColor, -2);
1018 // Lower delimiter:
1020 osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor);
1022 // VDR version:
1024 osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
1026}
1027
1028void cSkinLCARSDisplayMenu::DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font)
1029{
1030 int h = y1 - y0;
1031 osd->DrawEllipse(x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
1032 osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taBottom | taRight);
1033 osd->DrawEllipse(x2, y0, x3 - 1, y1 - 1, ColorBg, 5);
1034}
1035
1037{
1038 // Upper elbow:
1041 osd->DrawEllipse (xa00, yt00, xa01 - 1, yt05 - 1, frameColor, 2);
1043 osd->DrawEllipse (xa02, yt01, xa04 - 1, yt03 - 1, frameColor, -2);
1048 osd->DrawEllipse (xa08 + lineHeight / 2, yt00, xa09 - 1, yt01 - 1, frameColor, 5);
1049 // Center part:
1051 // Lower elbow:
1054 osd->DrawEllipse (xa00, yb11, xa01 - 1, yb15 - 1, frameColor, 3);
1056 osd->DrawEllipse (xa02, yb12, xa04 - 1, yb14 - 1, frameColor, -3);
1060 osd->DrawEllipse (xa08 + lineHeight / 2, yb14, xa09 - 1, yb15 - 1, frameColor, 5);
1061 osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
1062 // Color buttons:
1063 tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
1064 osd->DrawRectangle(xb00, yb14, xb01 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey0]));
1065 osd->DrawRectangle(xb04, yb14, xb05 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey1]));
1066 osd->DrawRectangle(xb08, yb14, xb09 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey2]));
1067 osd->DrawRectangle(xb12, yb14, xb13 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey3]));
1068}
1069
1071{
1072 cString s = DayDateTime();
1073 if (initial || !*lastDate || strcmp(s, lastDate)) {
1074 const cFont *font = cFont::GetFont(fontOsd);
1075 tColor ColorFg = Theme.Color(clrDateFg);
1076 tColor ColorBg = Theme.Color(clrDateBg);
1077 lastDate = s;
1078 const char *t = strrchr(s, ' ');
1079 osd->DrawText(xa00, yb01 - lineHeight, t, ColorFg, ColorBg, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1080 s.Truncate(t - s);
1081 osd->DrawText(xa00, yb00, s, ColorFg, ColorBg, font, xa02 - xa00, yb01 - yb00 - lineHeight, taTop | taRight | taBorder);
1082 }
1083}
1084
1086{
1087 if (yb02) {
1088 if (cVideoDiskUsage::HasChanged(lastDiskUsageState) || initial) { // must call HasChanged() first, or it shows an outdated value in the 'initial' case!
1089 const cFont *font = cFont::GetFont(fontOsd);
1090 int DiskUsage = cVideoDiskUsage::UsedPercent();
1091 bool DiskAlert = DiskUsage > DISKUSAGEALERTLIMIT;
1092 tColor ColorFg = DiskAlert ? Theme.Color(clrAlertFg) : Theme.Color(clrMenuFrameFg);
1093 tColor ColorBg = DiskAlert ? Theme.Color(clrAlertBg) : frameColor;
1094 if (initial || DiskAlert != lastDiskAlert)
1095 osd->DrawText(xa00, yb02, tr("DISK"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb03 - yb02, taTop | taLeft | taBorder);
1096 osd->DrawText(xa01, yb02, itoa(DiskUsage), ColorFg, ColorBg, font, xa02 - xa01, lineHeight, taBottom | taRight | taBorder);
1097 osd->DrawText(xa00, yb03 - lineHeight, cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60), ColorFg, ColorBg, font, xa02 - xa00, 0, taBottom | taRight | taBorder);
1098 lastDiskAlert = DiskAlert;
1099 }
1100 }
1101}
1102
1104{
1105 if (yb04) {
1106 tColor ColorFg = Theme.Color(clrMenuFrameFg);
1107 tColor ColorBg = frameColor;
1108 if (initial)
1109 osd->DrawText(xa00, yb04, tr("LOAD"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb05 - yb04, taTop | taLeft | taBorder);
1110 double SystemLoad;
1111 if (getloadavg(&SystemLoad, 1) > 0) {
1112 if (initial || SystemLoad != lastSystemLoad) {
1113 osd->DrawText(xa00, yb05 - lineHeight, cString::sprintf("%.1f", SystemLoad), ColorFg, ColorBg, cFont::GetFont(fontOsd), xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1114 lastSystemLoad = SystemLoad;
1115 }
1116 }
1117 }
1118}
1119
1121{
1122 tColor Color = Theme.Color(clrMenuMainBracket);
1123 osd->DrawRectangle(xm00, ym00, xm01 - 1, ym01 - 1, Color);
1124 osd->DrawRectangle(xm02, ym00, xm07 - 1, ym01 - 1, Color);
1125 osd->DrawEllipse (xm07, ym00, xm08 - 1, ym02 - 1, Color, 1);
1126 osd->DrawEllipse (xm06, ym01, xm07 - 1, ym02 - 1, Color, -1);
1127 osd->DrawRectangle(xm07, ym03, xm08 - 1, ym04 - 1, Color);
1128 osd->DrawEllipse (xm06, ym05, xm07 - 1, ym06 - 1, Color, -4);
1129 osd->DrawEllipse (xm07, ym05, xm08 - 1, ym07 - 1, Color, 4);
1130 osd->DrawRectangle(xm02, ym06, xm07 - 1, ym07 - 1, Color);
1131 osd->DrawRectangle(xm00, ym06, xm01 - 1, ym07 - 1, Color);
1132}
1133
1135{
1136 const cFont *font = cFont::GetFont(fontOsd);
1137 osd->DrawText (xs00, ys00, tr("TIMERS"), Theme.Color(clrMenuFrameFg), frameColor, font, xs01 - xs00, lineHeight, taBottom | taLeft | taBorder);
1139 osd->DrawEllipse (xs03, ys00, xs05 - 1, ys01 - 1, frameColor, 1);
1140 osd->DrawEllipse (xs03, ys01, xs04 - 1, ys02 - 1, frameColor, -1);
1143 osd->DrawText (xs10, ys00, tr("DEVICES"), Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs10, lineHeight, taBottom | taRight | taBorder);
1145 osd->DrawEllipse (xs06, ys00, xs08 - 1, ys01 - 1, frameColor, 2);
1146 osd->DrawEllipse (xs07, ys01, xs08 - 1, ys02 - 1, frameColor, -2);
1150}
1151
1153{
1154 DrawDate();
1155 DrawDisk();
1156 DrawLoad();
1157 if (initial) {
1158 if (yb06)
1160 if (yb08) {
1161 const cFont *font = cFont::GetFont(fontOsd);
1163 osd->DrawText(xa00, yb09 - lineHeight, "LCARS", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1164 }
1165 }
1166}
1167
1168void cSkinLCARSDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown)
1169{
1170 int x0, x1, tt, tb;
1171 tColor ClearColor;
1172 if (MenuCategory() == mcMain) {
1173 x0 = xm07;
1174 x1 = xm08;
1175 tt = ym03;
1176 tb = ym04;
1177 ClearColor = Theme.Color(clrMenuMainBracket);
1178 }
1179 else {
1180 x0 = xa02 + Gap;
1181 x1 = x0 + lineHeight / 2;
1182 tt = yc00;
1183 tb = yc11;
1184 ClearColor = Theme.Color(clrBackground);
1185 int d = TextFrame;
1186 if (CanScrollUp)
1187 osd->DrawBitmap(xa02 - bmArrowUp.Width() - d, yc00 + d, bmArrowUp, Theme.Color(clrMenuScrollbarArrow), frameColor);
1188 else
1189 osd->DrawRectangle(xa02 - bmArrowUp.Width() - d, yc00 + d, xa02 - d - 1, yc00 + d + bmArrowUp.Height() - 1, frameColor);
1190 if (CanScrollDown)
1191 osd->DrawBitmap(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), bmArrowDown, Theme.Color(clrMenuScrollbarArrow), frameColor);
1192 else
1193 osd->DrawRectangle(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), xa02 - d - 1, yc11 - d - 1, frameColor);
1194 }
1195 if (Total > 0 && Total > Shown) {
1196 int sw = x1 - x0;
1197 int sh = max(int((tb - tt) * double(Shown) / Total + 0.5), sw);
1198 int st = min(int(tt + (tb - tt) * double(Offset) / Total + 0.5), tb - sh);
1199 int sb = min(st + sh, tb);
1200 osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, Theme.Color(clrMenuScrollbarTotal));
1201 osd->DrawRectangle(x0, st, x1 - 1, sb - 1, Theme.Color(clrMenuScrollbarShown));
1202 }
1203 else if (MenuCategory() != mcMain)
1204 osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, ClearColor);
1205}
1206
1207void cSkinLCARSDisplayMenu::DrawTimer(const cTimer *Timer, int y, bool MultiRec)
1208{
1209 // The timer data:
1210 bool Alert = !Timer->Recording() && Timer->Pending();
1211 tColor ColorFg = Alert ? Theme.Color(clrAlertFg) : Theme.Color(clrTimerFg);
1212 tColor ColorBg = Alert ? Theme.Color(clrAlertBg) : Theme.Color(clrTimerBg);
1213 osd->DrawRectangle(xs00, y, xs03 - 1, y + lineHeight - 1, ColorBg);
1214 cString Date;
1215 if (Timer->Recording())
1216 Date = cString::sprintf("-%s", *TimeString(Timer->StopTimeEvent()));
1217 else {
1218 time_t Now = time(NULL);
1219 time_t StartTime = Timer->StartTimeEvent();
1220 cString Today = WeekDayName(Now);
1221 cString Time = TimeString(StartTime);
1222 cString Day = WeekDayName(StartTime);
1223 if (StartTime > Now + 6 * SECSINDAY)
1224 Date = DayDateTime(StartTime);
1225 else if (strcmp(Day, Today) != 0)
1226 Date = cString::sprintf("%s %s", *Day, *Time);
1227 else
1228 Date = Time;
1229 }
1230 if (Timer->Flags() & tfVps)
1231 Date = cString::sprintf("VPS %s", *Date);
1232 const cChannel *Channel = Timer->Channel();
1233 const cEvent *Event = Timer->Event();
1234 int d = max(TextFrame / 2, 1);
1235 if (Channel) {
1236 osd->DrawText(xs00 + d, y, Channel->Name(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - d);
1237 osd->DrawText(xs03 - tinyFont->Width(Date) - d, y, Date, ColorFg, ColorBg, tinyFont);
1238 }
1239 if (Event)
1240 osd->DrawText(xs00 + d, y + lineHeight - tinyFont->Height(), Event->Title(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - 2 * d);
1241 // The remote timer indicator:
1242 if (Timer->Remote())
1243 osd->DrawRectangle(xs00 - (lineHeight - Gap) / 2, y, xs00 - Gap - 1, y + lineHeight - 1, Timer->Recording() ? Theme.Color(clrMenuTimerRecording) : ColorBg);
1244 // The timer recording indicator:
1245 else if (Timer->Recording())
1246 osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording));
1247}
1248
1250{
1251 if (const cTimers *Timers = cTimers::GetTimersRead(timersStateKey)) {
1253 const cFont *font = cFont::GetFont(fontOsd);
1256 cSortedTimers SortedTimers(Timers);
1257 cVector<int> FreeDeviceSlots;
1258 int NumDevices = 0;
1259 int y = ys04;
1260 // Timers and recording devices:
1261 while (1) {
1262 int NumTimers = 0;
1263 const cDevice *Device = NULL;
1264 for (int i = 0; i < SortedTimers.Size(); i++) {
1265 if (y + lineHeight > ys05)
1266 break;
1267 if (const cTimer *Timer = SortedTimers[i]) {
1268 if (Timer->IsPatternTimer())
1269 SortedTimers[i] = NULL;
1270 else if (Timer->Recording()) {
1271 if (Timer->Remote()) {
1272 if (!Device && Timer->HasFlags(tfActive)) {
1273 DrawTimer(Timer, y, false);
1274 FreeDeviceSlots.Append(y);
1275 y += lineHeight + Gap;
1276 }
1277 else
1278 continue;
1279 }
1280 else if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) {
1281 if (!Device || Device == RecordControl->Device()) {
1282 DrawTimer(Timer, y, NumTimers > 0);
1283 NumTimers++;
1284 if (!Device) {
1285 Device = RecordControl->Device();
1286 deviceOffset[Device->DeviceNumber()] = y;
1287 deviceRecording[Device->DeviceNumber()] = true;
1288 NumDevices++;
1289 }
1290 else
1291 FreeDeviceSlots.Append(y);
1292 y += lineHeight + Gap;
1293 }
1294 else
1295 continue;
1296 }
1297 SortedTimers[i] = NULL;
1298 }
1299 else if (!Device && Timer->HasFlags(tfActive)) {
1300 DrawTimer(Timer, y, false);
1301 FreeDeviceSlots.Append(y);
1302 y += lineHeight + Gap;
1303 SortedTimers[i] = NULL;
1304 }
1305 }
1306 }
1307 if (!Device)
1308 break;
1309 }
1310 // Devices currently not recording:
1311 int Slot = 0;
1312 for (int i = 0; i < cDevice::NumDevices(); i++) {
1313 if (const cDevice *Device = cDevice::GetDevice(i)) {
1314 if (Device->NumProvidedSystems()) {
1315 if (!deviceRecording[Device->DeviceNumber()]) {
1316 if (Slot < FreeDeviceSlots.Size()) {
1317 y = FreeDeviceSlots[Slot];
1318 Slot++;
1319 }
1320 if (y + lineHeight > ys05)
1321 break;
1322 deviceOffset[Device->DeviceNumber()] = y;
1323 y += lineHeight + Gap;
1324 NumDevices++;
1325 }
1326 }
1327 }
1328 }
1329 // Total number of active timers:
1330 int NumTimers = 0;
1331 for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
1332 if (Timer->HasFlags(tfActive))
1333 NumTimers++;
1334 }
1335 osd->DrawText(xs02, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder);
1336 osd->DrawText(xs08, ys00, itoa(NumDevices), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder);
1338 initial = true; // forces redrawing of devices
1340 }
1341}
1342
1344{
1345 int dn = Device->DeviceNumber();
1346 int y = deviceOffset[dn];
1347 if (y + lineHeight <= ys05) {
1348 if (DrawDeviceData(osd, Device, xs08, y, xs11, y + lineHeight, xs, tinyFont, lastDeviceType[dn], lastCamSlot[dn], initial)) {
1349 // Make sure signal meters are redrawn:
1350 lastSignalStrength[dn] = -1;
1351 lastSignalQuality[dn] = -1;
1353 }
1354 // The device recording indicator:
1355 if (deviceRecording[dn])
1356 osd->DrawRectangle(xs07 + Gap / 2, y, xs08 - Gap - 1, y + lineHeight - 1, Theme.Color(clrMenuDeviceRecording));
1357 }
1358}
1359
1361{
1362 for (int i = 0; i < cDevice::NumDevices(); i++) {
1363 if (const cDevice *Device = cDevice::GetDevice(i)) {
1364 if (Device->NumProvidedSystems())
1365 DrawDevice(Device);
1366 }
1367 }
1368}
1369
1371{
1372 cDevice *Device = cDevice::PrimaryDevice();
1373 int y = -1;
1374 bool Transferring = Device->Transferring();
1375 if (!Device->Replaying() || Transferring)
1377 if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) {
1378 if (lastLiveIndicatorY >= 0)
1380 if (y > 0) {
1381 tColor ColorBg = Theme.Color(clrChannelFrameBg);
1382 osd->DrawRectangle(xs12, y, xs12 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
1383 osd->DrawEllipse (xs12 + lineHeight / 2, y, xs13 - 1, y + lineHeight - 1, ColorBg, 5);
1384 if (Transferring) {
1385 int w = bmTransferMode.Width();
1386 int h = bmTransferMode.Height();
1387 int b = w * w + h * h; // the diagonal of the bitmap (squared)
1388 int c = lineHeight * lineHeight; // the diameter of the circle (squared)
1389 const cBitmap *bm = &bmTransferMode;
1390 if (b > c) {
1391 // the bitmap doesn't fit, so scale it down:
1392 double f = sqrt(double(c) / (2 * b));
1393 bm = bmTransferMode.Scaled(f, f);
1394 }
1395 osd->DrawBitmap((xs12 + xs13 - bm->Width()) / 2, y + (lineHeight - bm->Height()) / 2, *bm, Theme.Color(clrChannelFrameFg), ColorBg);
1396 if (bm != &bmTransferMode)
1397 delete bm;
1398 }
1399 }
1401 lastLiveIndicatorTransferring = Transferring;
1402 }
1403}
1404
1406{
1407 time_t Now = time(NULL);
1409 for (int i = 0; i < cDevice::NumDevices(); i++) {
1410 if (const cDevice *Device = cDevice::GetDevice(i)) {
1411 if (Device->NumProvidedSystems()) {
1412 if (int y = deviceOffset[i])
1414 }
1415 }
1416 }
1417 lastSignalDisplay = Now;
1418 }
1419}
1420
1422{
1423 if (lastMode != cmLive) {
1424 initial = true;
1425 lastMode = cmLive;
1426 }
1427 if (initial) {
1428 DrawMainFrameUpper(Theme.Color(clrChannelFrameBg));
1429 osd->DrawText(xd00, yd00, tr("LIVE"), Theme.Color(clrChannelFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
1430 }
1431 if (!Channel)
1432 return;
1433 if (initial || Channel != lastChannel || strcmp(Channel->Name(), lastChannelName)) {
1434 osd->DrawText(xa00, yt00, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt02 - yt00, taTop | taRight | taBorder);
1435 osd->DrawText(xa03, yt00, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1436 int x = xa00 + (yc03 - yc02); // compensate for the arc
1437 osd->DrawText(x, yc00, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), cFont::GetFont(fontOsd), xa02 - x, yc03 - yc00, taTop | taRight | taBorder);
1438 lastChannel = Channel;
1439 lastChannelName = Channel->Name();
1440 DrawSeen(0, 0);
1441 }
1442 // The current programme:
1444 if (const cSchedule *Schedule = Schedules->GetSchedule(Channel)) {
1445 const cEvent *Event = Schedule->GetPresentEvent();
1446 if (initial || Event != lastEvent) {
1447 DrawInfo(Event, true);
1448 lastEvent = Event;
1449 lastSeen = -1;
1450 }
1451 int Current = 0;
1452 int Total = 0;
1453 if (Event) {
1454 time_t t = time(NULL);
1455 if (t > Event->StartTime())
1456 Current = t - Event->StartTime();
1457 Total = Event->Duration();
1458 }
1459 DrawSeen(Current, Total);
1460 }
1461}
1462
1464{
1465 if (lastMode != cmPlay) {
1466 initial = true;
1467 lastMode = cmPlay;
1468 }
1469 if (initial) {
1470 DrawMainFrameUpper(Theme.Color(clrReplayFrameBg));
1471 osd->DrawText(xd00, yd00, tr("PLAY"), Theme.Color(clrReplayFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
1472 }
1473 // The current progress:
1474 int Current = 0;
1475 int Total = 0;
1476 if (Control->GetIndex(Current, Total))
1477 DrawSeen(Current, Total);
1478 // The current programme:
1479 if (const cRecording *Recording = Control->GetRecording()) {
1480 if (initial || Recording != lastRecording) {
1481 const cFont *font = cFont::GetFont(fontOsd);
1482 if (const cRecordingInfo *Info = Recording->Info()) {
1483 osd->DrawText(xa03, yt00, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1484 DrawInfo(Info->GetEvent(), false);
1485 }
1486 else
1487 osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03, 0, taTop | taLeft);
1488 osd->DrawText(xa00, yt04, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder);
1489 osd->DrawText(xa00, yt06 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taBottom | taRight | taBorder);
1490 lastRecording = Recording;
1491 }
1492 }
1493 else {
1494 cString Header = Control->GetHeader();
1495 if (!*lastHeader || strcmp(Header, lastHeader)) {
1496 osd->DrawText(xa03, yt00, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1497 lastHeader = Header;
1498 }
1499 }
1500}
1501
1502void cSkinLCARSDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime)
1503{
1504 if (Event) {
1505 const cFont *font = cFont::GetFont(fontOsd);
1506 int y = yt04;
1507 osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03 - lineHeight, lineHeight, taBottom | taLeft);
1508 y += lineHeight;
1509 osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd00 - xa03 - lineHeight, lineHeight, taTop | taLeft);
1510 if (WithTime) {
1511 osd->DrawText(xa00, yt04, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder);
1512 osd->DrawText(xa00, yt06 - lineHeight, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1513 }
1514 }
1515}
1516
1517void cSkinLCARSDisplayMenu::DrawSeen(int Current, int Total)
1518{
1519 int Seen = (Total > 0) ? min(xm08 - xm02, int((xm08 - xm02) * double(Current) / Total)) : 0;
1520 if (initial || Seen != lastSeen) {
1521 int y0 = yc04 - ShowSeenExtent;
1522 int y1 = yc04 + lineHeight / 2 - Gap / 2;
1523 osd->DrawRectangle(xm02, y0, xm02 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
1524 osd->DrawRectangle(xm02 + Seen, y0, xm08 - 1, y1 - 1, Theme.Color(clrBackground));
1525 lastSeen = Seen;
1526 }
1527}
1528
1530{
1531 if (textScroller.CanScroll())
1533}
1534
1535void cSkinLCARSDisplayMenu::Scroll(bool Up, bool Page)
1536{
1537 cSkinDisplayMenu::Scroll(Up, Page);
1539}
1540
1542{
1543 if (MenuCategory() == mcMain)
1544 return (ym04 - ym03) / lineHeight;
1545 else
1546 return (yb13 - yt02) / lineHeight;
1547}
1548
1550{
1553}
1554
1555void cSkinLCARSDisplayMenu::SetTitle(const char *Title)
1556{
1557 if (MenuCategory() != mcMain) {
1558 const cFont *font = cFont::GetFont(fontOsd);
1559 int w = min(font->Width(Title), xa07 - xa06 - Gap);
1560 osd->DrawRectangle(xa06, yt00, xa07 - w - Gap - 1, yt01 - 1, frameColor);
1561 osd->DrawText(xa07 - w - Gap, yt00, Title, Theme.Color(clrMenuTitle), Theme.Color(clrBackground), font, w + Gap, yt01 - yt00, taRight);
1562 }
1563}
1564
1565void cSkinLCARSDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
1566{
1567 const char *lutText[] = { Red, Green, Yellow, Blue };
1568 tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg };
1569 tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
1570 const cFont *font = cFont::GetFont(fontSml);
1571 if (MenuCategory() == mcMain) {
1576 }
1577 else {
1578 int h = yb15 - yb14;
1579 osd->DrawText(xb02, yb14, lutText[Setup.ColorKey0], Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font, xb03 - xb02, h, taLeft | taBorder);
1580 osd->DrawText(xb06, yb14, lutText[Setup.ColorKey1], Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font, xb07 - xb06, h, taLeft | taBorder);
1581 osd->DrawText(xb10, yb14, lutText[Setup.ColorKey2], Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font, xb11 - xb10, h, taLeft | taBorder);
1582 osd->DrawText(xb14, yb14, lutText[Setup.ColorKey3], Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font, xb15 - xb14, h, taLeft | taBorder);
1583 }
1584}
1585
1587{
1588 if (Text) {
1589 osd->SaveRegion(xb00, yb14, xb15 - 1, yb15 - 1);
1590 osd->DrawText(xb00, yb14, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xb15 - xb00, yb15 - yb14, taCenter);
1591 }
1592 else
1593 osd->RestoreRegion();
1594}
1595
1596void cSkinLCARSDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
1597{
1598 int y = yi00 + Index * lineHeight;
1599 tColor ColorFg, ColorBg;
1600 if (Current) {
1601 if (TwoColors) {
1602 ColorFg = Theme.Color(clrBackground);
1603 ColorBg = Theme.Color(clrMenuFrameBg);
1604 }
1605 else {
1606 ColorFg = Theme.Color(clrMenuItemCurrentFg);
1607 ColorBg = Theme.Color(clrMenuItemCurrentBg);
1608 }
1609 osd->DrawRectangle(xi00, y, xi01 - 1, y + lineHeight - 1, ColorBg);
1610 osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
1611 osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, y + lineHeight - 1, ColorBg, 5);
1612 currentIndex = Index;
1613 }
1614 else {
1615 ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
1616 ColorBg = Theme.Color(clrBackground);
1617 if (currentIndex == Index)
1619 }
1620 const cFont *font = cFont::GetFont(fontOsd);
1621 for (int i = 0; i < MaxTabs; i++) {
1622 const char *s = GetTabbedText(Text, i);
1623 if (s) {
1624 int xt = xi00 + TextSpacing + Tab(i);
1625 osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xi01 - xt);
1626 }
1627 if (!Tab(i + 1))
1628 break;
1629 }
1631}
1632
1633void cSkinLCARSDisplayMenu::SetScrollbar(int Total, int Offset)
1634{
1635 DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total);
1636}
1637
1639{
1640 if (!Event)
1641 return;
1642 const cFont *font = cFont::GetFont(fontOsd);
1643 int xl = xi00;
1644 int y = yi00;
1645 cTextScroller ts;
1646 cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
1647 ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
1648 if (Event->Vps() && Event->Vps() != Event->StartTime()) {
1649 cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());
1650 const cFont *font = cFont::GetFont(fontSml);
1651 int w = font->Width(buffer);
1652 osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1653 int yb = y + font->Height();
1654 osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1655 osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1656 }
1657 y += ts.Height();
1658 if (Event->ParentalRating()) {
1659 cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
1660 const cFont *font = cFont::GetFont(fontSml);
1661 int w = font->Width(buffer);
1662 osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1663 int yb = y + font->Height();
1664 osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1665 osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1666 }
1667 y += font->Height();
1668 ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->Title(), font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
1669 y += ts.Height();
1670 if (!isempty(Event->ShortText())) {
1671 const cFont *font = cFont::GetFont(fontSml);
1672 ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
1673 y += ts.Height();
1674 }
1675 y += font->Height();
1676 if (!isempty(Event->Description())) {
1677 int yt = y;
1678 int yb = yi01;
1679 textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Event->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
1681 }
1682}
1683
1685{
1686 if (!Recording)
1687 return;
1688 const cRecordingInfo *Info = Recording->Info();
1689 const cFont *font = cFont::GetFont(fontOsd);
1690 int xl = xi00;
1691 int y = yi00;
1692 cTextScroller ts;
1693 cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
1694 ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
1695 y += ts.Height();
1696 int xt = xi01;
1697 if (Info->GetEvent()->ParentalRating()) {
1698 cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
1699 const cFont *font = cFont::GetFont(fontSml);
1700 int w = font->Width(buffer);
1701 osd->DrawText(xt - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1702 xt -= w + xi02 - xi01;
1703 }
1704 if (Info->Errors() > 0) {
1705 cString buffer = cString::sprintf(" %d %s ", Info->Errors(), tr("errors"));
1706 const cFont *font = cFont::GetFont(fontSml);
1707 int w = font->Width(buffer);
1708 osd->DrawText(xt - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1709 xt -= w + xi02 - xi01;
1710 }
1711 if (xt != xi01) {
1712 const cFont *font = cFont::GetFont(fontSml);
1713 int yb = y + font->Height();
1714 osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1715 osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1716 }
1717 y += font->Height();
1718 const char *Title = Info->Title();
1719 if (isempty(Title))
1720 Title = Recording->Name();
1721 ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Title, font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
1722 y += ts.Height();
1723 if (!isempty(Info->ShortText())) {
1724 const cFont *font = cFont::GetFont(fontSml);
1725 ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Info->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
1726 y += ts.Height();
1727 }
1728 y += font->Height();
1729 if (!isempty(Info->Description())) {
1730 int yt = y;
1731 int yb = yi01;
1732 textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Info->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
1734 }
1735}
1736
1737void cSkinLCARSDisplayMenu::SetText(const char *Text, bool FixedFont)
1738{
1741}
1742
1744{
1745 return xi01 - xi00;
1746}
1747
1749{
1750 const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd);
1751 //XXX -> make a way to let the text define which font to use
1752 return font;
1753}
1754
1756{
1757 if (MenuCategory() == mcMain) {
1758 cDevice *Device = cDevice::PrimaryDevice();
1759 cMutexLock ControlMutexLock;
1760 if (!Device->Replaying() || Device->Transferring()) {
1762 const cChannel *Channel = Channels->GetByNumber(cDevice::PrimaryDevice()->CurrentChannel());
1763 DrawLive(Channel);
1764 }
1765 else if (cControl *Control = cControl::Control(ControlMutexLock, true))
1766 DrawPlay(Control);
1767 DrawTimers();
1768 DrawDevices();
1770 DrawSignals();
1771 }
1773 osd->Flush();
1774 initial = false;
1775}
1776
1777// --- cSkinLCARSDisplayReplay -----------------------------------------------
1778
1780private:
1791 void DrawDate(void);
1792 void DrawTrack(void);
1793public:
1794 cSkinLCARSDisplayReplay(bool ModeOnly);
1795 virtual ~cSkinLCARSDisplayReplay();
1796 virtual void SetRecording(const cRecording *Recording);
1797 virtual void SetTitle(const char *Title);
1798 virtual void SetMode(bool Play, bool Forward, int Speed);
1799 virtual void SetProgress(int Current, int Total);
1800 virtual void SetCurrent(const char *Current);
1801 virtual void SetTotal(const char *Total);
1802 virtual void SetJump(const char *Jump);
1803 virtual void SetMessage(eMessageType Type, const char *Text);
1804 virtual void Flush(void);
1805 };
1806
1808{
1809 const cFont *font = cFont::GetFont(fontOsd);
1810 modeOnly = ModeOnly;
1811 lineHeight = font->Height();
1812 frameColor = Theme.Color(clrReplayFrameBg);
1813 lastCurrentWidth = 0;
1814 lastTotalWidth = 0;
1815 memset(&lastTrackId, 0, sizeof(lastTrackId));
1816 int d = 5 * lineHeight;
1817 xp00 = 0;
1818 xp01 = xp00 + d / 2;
1819 xp02 = xp00 + d;
1820 xp03 = xp02 + lineHeight;
1821 xp04 = xp02 + d / 4;
1822 xp05 = xp02 + d;
1823 xp06 = xp05 + Gap;
1824 xp15 = cOsd::OsdWidth();
1825 xp14 = xp15 - lineHeight;
1826 xp13 = xp14 - Gap;
1827 xp07 = (xp15 + xp00) / 2;
1828 xp08 = xp07 + Gap;
1829 xp09 = xp08 + lineHeight;
1830 xp10 = xp09 + Gap;
1831 xp11 = (xp10 + xp13 + Gap) / 2;
1832 xp12 = xp11 + Gap;
1833
1834 yp00 = 0;
1835 yp01 = yp00 + 2 * lineHeight;
1836 yp02 = yp01 + Gap;
1837 yp03 = yp02 + 2 * lineHeight;
1838
1839 yp04 = yp03 + Gap;
1840 yp09 = yp04 + 3 * lineHeight + Gap / 2;
1841 yp08 = yp09 - lineHeight;
1842 yp07 = yp08 - lineHeight;
1843 yp06 = yp08 - d / 4;
1844 yp05 = yp09 - d / 2;
1845
1848 // Rectangles:
1849 if (!modeOnly)
1852 if (!modeOnly) {
1853 // Elbow:
1856 osd->DrawEllipse (xp00, yp05, xp01 - 1, yp09 - 1, frameColor, 3);
1858 osd->DrawEllipse (xp02, yp06, xp04 - 1, yp08 - 1, frameColor, -3);
1860 // Status area:
1864 osd->DrawRectangle(xp12, yp08, xp13 - 1, yp09 - 1, Theme.Color(clrDateBg));
1867 osd->DrawEllipse (xp14 + lineHeight / 2, yp08, xp15 - 1, yp09 - 1, frameColor, 5);
1868 }
1869}
1870
1872{
1873 delete osd;
1874}
1875
1877{
1878 cString s = DayDateTime();
1879 if (!*lastDate || strcmp(s, lastDate)) {
1881 lastDate = s;
1882 }
1883}
1884
1886{
1887 cDevice *Device = cDevice::PrimaryDevice();
1888 const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
1889 if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
1890 osd->DrawText(xp03, yp04, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp07 - xp03);
1891 strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
1892 }
1893}
1894
1896{
1897 const cRecordingInfo *RecordingInfo = Recording->Info();
1898 SetTitle(RecordingInfo->Title());
1899 osd->DrawText(xp03, yp01 - lineHeight, RecordingInfo->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xp13 - xp03);
1900 osd->DrawText(xp00, yp00, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taTop | taRight | taBorder);
1902}
1903
1905{
1907}
1908
1909static const char *const *ReplaySymbols[2][2][5] = {
1910 { { pause_xpm, srew_xpm, srew1_xpm, srew2_xpm, srew3_xpm },
1911 { pause_xpm, sfwd_xpm, sfwd1_xpm, sfwd2_xpm, sfwd3_xpm }, },
1912 { { play_xpm, frew_xpm, frew1_xpm, frew2_xpm, frew3_xpm },
1913 { play_xpm, ffwd_xpm, ffwd1_xpm, ffwd2_xpm, ffwd3_xpm } }
1914 };
1915
1916void cSkinLCARSDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
1917{
1918 Speed = constrain(Speed, -1, 3);
1919 cBitmap bm(ReplaySymbols[Play][Forward][Speed + 1]);
1920 osd->DrawBitmap(xp01 - bm.Width() / 2, (yp02 + yp03 - bm.Height()) / 2, bm, Theme.Color(clrReplayFrameFg), frameColor);
1921}
1922
1923void cSkinLCARSDisplayReplay::SetProgress(int Current, int Total)
1924{
1925 cProgressBar pb(xp13 - xp03, lineHeight, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
1926 osd->DrawBitmap(xp03, yp02, pb);
1927}
1928
1930{
1931 const cFont *font = cFont::GetFont(fontOsd);
1932 int w = font->Width(Current);
1933 osd->DrawText(xp03, yp03 - lineHeight, Current, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastCurrentWidth, w), 0, taLeft);
1934 lastCurrentWidth = w;
1935}
1936
1938{
1939 const cFont *font = cFont::GetFont(fontOsd);
1940 int w = font->Width(Total);
1941 osd->DrawText(xp13 - w, yp03 - lineHeight, Total, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastTotalWidth, w), 0, taRight);
1942 lastTotalWidth = w;
1943}
1944
1946{
1947 osd->DrawText(xp06, yp08, Jump, Theme.Color(clrReplayJumpFg), Jump ? Theme.Color(clrReplayJumpBg) : frameColor, cFont::GetFont(fontOsd), xp07 - xp06, 0, taCenter);
1948}
1949
1951{
1952 if (Text) {
1953 osd->SaveRegion(xp06, yp08, xp13 - 1, yp09 - 1);
1954 osd->DrawText(xp06, yp08, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xp13 - xp06, yp09 - yp08, taCenter);
1955 }
1956 else
1957 osd->RestoreRegion();
1958}
1959
1961{
1962 if (!modeOnly) {
1963 DrawDate();
1964 DrawTrack();
1965 }
1966 osd->Flush();
1967}
1968
1969// --- cSkinLCARSDisplayVolume -----------------------------------------------
1970
1972private:
1974 int x0, x1, x2, x3, x4, x5, x6, x7;
1975 int y0, y1;
1977 int mute;
1978public:
1980 virtual ~cSkinLCARSDisplayVolume();
1981 virtual void SetVolume(int Current, int Total, bool Mute);
1982 virtual void Flush(void);
1983 };
1984
1986{
1987 const cFont *font = cFont::GetFont(fontOsd);
1988 int lineHeight = font->Height();
1989 frameColor = Theme.Color(clrVolumeFrame);
1990 mute = -1;
1991 x0 = 0;
1992 x1 = lineHeight / 2;
1993 x2 = lineHeight;
1994 x3 = x2 + Gap;
1995 x7 = cOsd::OsdWidth();
1996 x6 = x7 - lineHeight / 2;
1997 x5 = x6 - lineHeight / 2;
1998 x4 = x5 - Gap;
1999 y0 = 0;
2000 y1 = lineHeight;
2001 osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
2003 osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
2004 osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
2005 osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
2006 osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
2007 osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
2008 osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
2009 osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
2010}
2011
2013{
2014 delete osd;
2015}
2016
2017void cSkinLCARSDisplayVolume::SetVolume(int Current, int Total, bool Mute)
2018{
2019 int xl = x3 + TextSpacing;
2020 int xr = x4 - TextSpacing;
2021 int yt = y0 + TextFrame;
2022 int yb = y1 - TextFrame;
2023 if (mute != Mute) {
2024 osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
2025 mute = Mute;
2026 }
2027 cBitmap bm(Mute ? mute_xpm : volume_xpm);
2028 osd->DrawBitmap(xl, y0 + (y1 - y0 - bm.Height()) / 2, bm, Theme.Color(clrVolumeSymbol), frameColor);
2029 if (!Mute) {
2030 xl += bm.Width() + TextSpacing;
2031 int w = (y1 - y0) / 3;
2032 int d = TextFrame;
2033 int n = (xr - xl + d) / (w + d);
2034 int x = xr - n * (w + d);
2035 tColor Color = Theme.Color(clrVolumeBarLower);
2036 for (int i = 0; i < n; i++) {
2037 if (Total * i >= Current * n)
2038 Color = Theme.Color(clrVolumeBarUpper);
2039 osd->DrawRectangle(x, yt, x + w - 1, yb - 1, Color);
2040 x += w + d;
2041 }
2042 }
2043}
2044
2046{
2047 osd->Flush();
2048}
2049
2050// --- cSkinLCARSDisplayTracks -----------------------------------------------
2051
2053private:
2061 void SetItem(const char *Text, int Index, bool Current);
2062public:
2063 cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
2064 virtual ~cSkinLCARSDisplayTracks();
2065 virtual void SetTrack(int Index, const char * const *Tracks);
2066 virtual void SetAudioChannel(int AudioChannel);
2067 virtual void Flush(void);
2068 };
2069
2073
2074cSkinLCARSDisplayTracks::cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
2075{
2076 const cFont *font = cFont::GetFont(fontOsd);
2077 lineHeight = font->Height();
2078 frameColor = Theme.Color(clrTrackFrameBg);
2079 currentIndex = -1;
2080 xt00 = 0;
2081 xt01 = xt00 + lineHeight / 2;
2082 xt02 = xt01 + Gap;
2083 xt03 = xt00 + 2 * lineHeight;
2084 int ItemsWidth = font->Width(Title) + xt03 - xt02;
2085 for (int i = 0; i < NumTracks; i++)
2086 ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]) + 2 * TextFrame);
2087 xt04 = xt02 + ItemsWidth;
2088 xt05 = xt04 + Gap;
2089 xt06 = xt04 + lineHeight;
2090 xt07 = xt05 + lineHeight;
2091 xt08 = xt07 + lineHeight;
2092 xt09 = xt08 + Gap;
2093 xt10 = xt09 + lineHeight / 2;
2094 xt11 = xt10 + Gap;
2095 xt12 = xt11 + lineHeight;
2096 yt00 = 0;
2097 yt01 = yt00 + lineHeight;
2098 yt02 = yt01 + lineHeight;
2099 yt03 = yt02 + Gap;
2100 yt04 = yt03 + NumTracks * lineHeight + (NumTracks - 1) * Gap;
2101 yt05 = yt04 + Gap;
2102 yt06 = yt05 + lineHeight;
2103 yt07 = yt06 + lineHeight;
2104 while (yt07 > cOsd::OsdHeight()) {
2105 yt04 -= lineHeight + Gap;
2106 yt05 = yt04 + Gap;
2107 yt06 = yt05 + lineHeight;
2108 yt07 = yt06 + lineHeight;
2109 }
2111 // The upper elbow:
2114 osd->DrawEllipse (xt00, yt00, xt03 - 1, yt02 - 1, frameColor, 2);
2117 osd->DrawEllipse (xt04, yt01, xt06 - 1, yt02 - 1, frameColor, -2);
2121 osd->DrawEllipse (xt11 + lineHeight / 2, yt00, xt12 - 1, yt01 - 1, frameColor, 5);
2122 osd->DrawText(xt03, yt00, Title, Theme.Color(clrTrackFrameFg), frameColor, font, xt04 - xt03, 0, taTop | taRight);
2123 // The items:
2124 for (int i = 0; i < NumTracks; i++)
2125 SetItem(Tracks[i], i, false);
2126 // The lower elbow:
2128 osd->DrawEllipse (xt00, yt05, xt03 - 1, yt07 - 1, frameColor, 3);
2131 osd->DrawEllipse (xt04, yt05, xt06 - 1, yt06 - 1, frameColor, -3);
2135 osd->DrawEllipse (xt11 + lineHeight / 2, yt06, xt12 - 1, yt07 - 1, frameColor, 5);
2136}
2137
2139{
2140 delete osd;
2141}
2142
2143void cSkinLCARSDisplayTracks::SetItem(const char *Text, int Index, bool Current)
2144{
2145 int y0 = yt03 + Index * (lineHeight + Gap);
2146 int y1 = y0 + lineHeight;
2147 if (y1 > yt04)
2148 return;
2149 tColor ColorFg, ColorBg;
2150 if (Current) {
2151 ColorFg = Theme.Color(clrTrackItemCurrentFg);
2152 ColorBg = Theme.Color(clrTrackItemCurrentBg);
2153 osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
2154 osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
2155 osd->DrawRectangle(xt05, y0, xt05 + lineHeight / 2 - 1, y1 - 1, ColorBg);
2156 osd->DrawEllipse (xt05 + lineHeight / 2, y0, xt07 - 1, y1 - 1, ColorBg, 5);
2157 currentIndex = Index;
2158 }
2159 else {
2160 ColorFg = Theme.Color(clrTrackItemFg);
2161 ColorBg = Theme.Color(clrTrackItemBg);
2162 osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
2163 osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
2164 if (currentIndex == Index)
2165 osd->DrawRectangle(xt05, y0, xt07 - 1, y1 - 1, Theme.Color(clrBackground));
2166 }
2167 const cFont *font = cFont::GetFont(fontOsd);
2168 osd->DrawText(xt02, y0, Text, ColorFg, ColorBg, font, xt04 - xt02, y1 - y0, taTop | taLeft | taBorder);
2169}
2170
2171void cSkinLCARSDisplayTracks::SetTrack(int Index, const char * const *Tracks)
2172{
2173 if (currentIndex >= 0)
2174 SetItem(Tracks[currentIndex], currentIndex, false);
2175 SetItem(Tracks[Index], Index, true);
2176}
2177
2179{
2180 cBitmap *bm = NULL;
2181 switch (AudioChannel) {
2182 case 0: bm = &bmAudioStereo; break;
2183 case 1: bm = &bmAudioLeft; break;
2184 case 2: bm = &bmAudioRight; break;
2185 default: ;
2186 }
2187 if (bm)
2188 osd->DrawBitmap(xt04 - bm->Width(), (yt06 + yt07 - bm->Height()) / 2, *bm, Theme.Color(clrTrackFrameFg), frameColor);
2189 else
2191}
2192
2194{
2195 osd->Flush();
2196}
2197
2198// --- cSkinLCARSDisplayMessage ----------------------------------------------
2199
2201private:
2203 int x0, x1, x2, x3, x4, x5, x6, x7;
2204 int y0, y1;
2205public:
2207 virtual ~cSkinLCARSDisplayMessage();
2208 virtual void SetMessage(eMessageType Type, const char *Text);
2209 virtual void Flush(void);
2210 };
2211
2213{
2214 const cFont *font = cFont::GetFont(fontOsd);
2215 int lineHeight = font->Height();
2216 x0 = 0;
2217 x1 = lineHeight / 2;
2218 x2 = lineHeight;
2219 x3 = x2 + Gap;
2220 x7 = cOsd::OsdWidth();
2221 x6 = x7 - lineHeight / 2;
2222 x5 = x6 - lineHeight / 2;
2223 x4 = x5 - Gap;
2224 y0 = 0;
2225 y1 = lineHeight;
2226 osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
2227}
2228
2230{
2231 delete osd;
2232}
2233
2235{
2236 tColor ColorFg = Theme.Color(clrMessageStatusFg + 2 * Type);
2237 tColor ColorBg = Theme.Color(clrMessageStatusBg + 2 * Type);
2239 osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
2240 osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
2241 osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, ColorBg);
2242 osd->DrawText(x3, y0, Text, ColorFg, ColorBg, cFont::GetFont(fontSml), x4 - x3, y1 - y0, taCenter);
2243 osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, ColorBg);
2244 osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
2245 osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, ColorBg, 5);
2246}
2247
2249{
2250 osd->Flush();
2251}
2252
2253// --- cSkinLCARS ------------------------------------------------------------
2254
2256:cSkin("lcars", &::Theme)
2257{
2258}
2259
2261{
2262 return "LCARS";
2263}
2264
2266{
2267 return new cSkinLCARSDisplayChannel(WithInfo);
2268}
2269
2271{
2272 return new cSkinLCARSDisplayMenu;
2273}
2274
2276{
2277 return new cSkinLCARSDisplayReplay(ModeOnly);
2278}
2279
2281{
2282 return new cSkinLCARSDisplayVolume;
2283}
2284
2285cSkinDisplayTracks *cSkinLCARS::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
2286{
2287 return new cSkinLCARSDisplayTracks(Title, NumTracks, Tracks);
2288}
2289
2291{
2292 return new cSkinLCARSDisplayMessage;
2293}
cString ChannelString(const cChannel *Channel, int Number)
Definition: channels.c:1139
#define LOCK_CHANNELS_READ
Definition: channels.h:269
int Height(void) const
cBitmap * Scaled(double FactorX, double FactorY, bool AntiAlias=false) const
Creates a copy of this bitmap, scaled by the given factors.
Definition: osd.c:838
int Width(void) const
Definition: ci.h:232
int MasterSlotNumber(void)
Returns the number of this CAM's master slot within the whole system.
Definition: ci.h:347
int Tpid(void) const
Definition: channels.h:170
int Vpid(void) const
Definition: channels.h:153
int Source(void) const
Definition: channels.h:151
int Number(void) const
Definition: channels.h:178
const char * Name(void) const
Definition: channels.c:107
int Dpid(int i) const
Definition: channels.h:160
int Apid(int i) const
Definition: channels.h:159
bool GroupSep(void) const
Definition: channels.h:180
int Ca(int Index=0) const
Definition: channels.h:172
virtual cString GetHeader(void)
This can be used by players that don't play a cRecording, but rather do something completely differen...
Definition: player.c:68
bool GetIndex(int &Current, int &Total, bool SnapToIFrame=false) const
virtual const cRecording * GetRecording(void)
Returns the cRecording that is currently being replayed, or NULL if this player is not playing a cRec...
Definition: player.c:63
static cControl * Control(bool Hidden=false)
Old version of this function, for backwards compatibility with plugins.
Definition: player.c:74
bool Replaying(void) const
Returns true if we are currently replaying.
Definition: device.c:1338
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise.
Definition: device.c:220
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:148
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition: device.c:228
eTrackType GetCurrentAudioTrack(void) const
Definition: device.h:581
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:165
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition: device.c:1343
virtual int SignalQuality(void) const
Returns the "quality" of the currently received signal.
Definition: device.c:787
virtual int SignalStrength(void) const
Returns the "strength" of the currently received signal.
Definition: device.c:782
const tTrackId * GetTrack(eTrackType Type)
Returns a pointer to the given track id, or NULL if Type is not less than ttMaxTrackTypes.
Definition: device.c:1108
virtual cString DeviceType(void) const
Returns a string identifying the type of this device (like "DVB-S").
Definition: device.c:174
static int NumDevices(void)
Returns the total number of devices.
Definition: device.h:129
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use.
Definition: device.h:481
Definition: epg.h:73
const char * ShortText(void) const
Definition: epg.h:106
time_t Vps(void) const
Definition: epg.h:114
cString GetDateString(void) const
Definition: epg.c:428
const char * Description(void) const
Definition: epg.h:107
int ParentalRating(void) const
Definition: epg.h:110
time_t StartTime(void) const
Definition: epg.h:111
cString GetTimeString(void) const
Definition: epg.c:433
const char * Title(void) const
Definition: epg.h:105
cString GetEndTimeString(void) const
Definition: epg.c:438
int Duration(void) const
Definition: epg.h:113
cString GetVpsString(void) const
Definition: epg.c:443
cString GetParentalRatingString(void) const
Definition: epg.c:421
Definition: font.h:37
virtual int Width(void) const =0
Returns the original character width as requested when the font was created, or 0 if the default widt...
static cFont * CreateFont(const char *Name, int CharHeight, int CharWidth=0)
Creates a new font object with the given Name and makes its characters CharHeight pixels high.
Definition: font.c:428
virtual int Height(void) const =0
Returns the height of this font in pixel (all characters have the same height).
static const cFont * GetFont(eDvbFont Font)
Gets the given Font, which was previously set by a call to SetFont().
Definition: font.c:411
cListObject * Next(void) const
static cOsd * NewOsd(int Left, int Top, uint Level=OSD_LEVEL_DEFAULT)
Returns a pointer to a newly created cOsd object, which will be located at the given coordinates.
Definition: osd.c:2215
The cOsd class is the interface to the "On Screen Display".
static int OsdHeight(void)
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition: osd.c:2029
virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg=0, tColor ColorBg=0, bool ReplacePalette=false, bool Overlay=false)
Sets the pixels in the OSD with the data from the given Bitmap, putting the upper left corner of the ...
Definition: osd.c:2131
virtual void DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants=0)
Draws a filled ellipse defined by the upper left (x1, y1) and lower right (x2, y2) corners with the g...
Definition: osd.c:2171
void SetAntiAliasGranularity(uint FixedColors, uint BlendColors)
Allows the system to optimize utilization of the limited color palette entries when generating blende...
Definition: osd.c:1896
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas)
Checks whether the OSD can display the given set of sub-areas.
Definition: osd.c:2007
static int OsdTop(void)
virtual void SaveRegion(int x1, int y1, int x2, int y2)
Saves the region defined by the given coordinates for later restoration through RestoreRegion().
Definition: osd.c:2064
virtual void Flush(void)
Actually commits all data to the OSD hardware.
Definition: osd.c:2191
virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
Draws a filled rectangle defined by the upper left (x1, y1) and lower right (x2, y2) corners with the...
Definition: osd.c:2161
static int OsdLeft(void)
static int OsdWidth(void)
virtual void RestoreRegion(void)
Restores the region previously saved by a call to SaveRegion().
Definition: osd.c:2080
virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width=0, int Height=0, int Alignment=taDefault)
Draws the given string at coordinates (x, y) with the given foreground and background color and font.
Definition: osd.c:2151
A steerable satellite dish generally points to the south on the northern hemisphere,...
static int NormalizeAngle(int Angle)
Normalizes the given Angle into the range -1800...1800.
Definition: positioner.c:42
virtual int CurrentLongitude(void) const
Returns the longitude the dish currently points to.
Definition: positioner.c:114
int HardLimitLongitude(ePositionerDirection Direction) const
Returns the longitude of the positioner's hard limit in the given Direction.
Definition: positioner.c:81
static int HorizonLongitude(ePositionerDirection Direction)
Returns the longitude of the satellite position that is just at the horizon when looking in the given...
Definition: positioner.c:69
int TargetLongitude(void) const
Returns the longitude the dish is supposed to be moved to.
static bool Active(void)
Definition: menu.c:5712
static cRecordControl * GetRecordControl(const char *FileName)
Definition: menu.c:5660
const char * ChannelName(void) const
const cEvent * GetEvent(void) const
int Errors(void) const
const char * ShortText(void) const
const char * Title(void) const
const char * Description(void) const
const char * Name(void) const
Returns the full name of the recording (without the video directory).
time_t Start(void) const
cRecordingInfo * Info(void) const
Definition: epg.h:152
int ColorKey3
Definition: config.h:322
int ColorKey2
Definition: config.h:322
int FontOsdSize
Definition: config.h:341
int ColorKey0
Definition: config.h:322
char FontOsd[MAXFONTNAME]
Definition: config.h:335
int ChannelInfoPos
Definition: config.h:327
int ColorKey1
Definition: config.h:322
virtual void Scroll(bool Up, bool Page)
If this menu contains a text area that can be scrolled, this function will be called to actually scro...
Definition: skins.c:107
cTextScroller textScroller
int Tab(int n)
Returns the offset of the given tab from the left border of the item display area.
eMenuCategory MenuCategory(void) const
Returns the menu category, set by a previous call to SetMenuCategory().
const char * GetTabbedText(const char *s, int Tab)
Returns the part of the given string that follows the given Tab (where 0 indicates the beginning of t...
Definition: skins.c:112
virtual void SetMenuCategory(eMenuCategory MenuCategory)
Sets the current menu category.
Definition: skins.c:90
const cMarks * marks
< This class implements the progress display used during replay of a recording.
static cSkinDisplay * Current(void)
Returns the currently active cSkinDisplay.
void SetEditableWidth(int Width)
If an item is set through a call to cSkinDisplayMenu::SetItem(), this function shall be called to set...
const cEvent * present
Definition: skinlcars.c:355
static cBitmap bmTeletext
Definition: skinlcars.c:367
virtual void SetChannel(const cChannel *Channel, int Number)
Sets the current channel to Channel.
Definition: skinlcars.c:536
virtual void SetPositioner(const cPositioner *Positioner)
Sets the Positioner used to move the satellite dish.
Definition: skinlcars.c:639
virtual void SetEvents(const cEvent *Present, const cEvent *Following)
Sets the Present and Following EPG events.
Definition: skinlcars.c:588
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:653
void DrawSeen(int Current, int Total)
Definition: skinlcars.c:501
static cBitmap bmEncrypted
Definition: skinlcars.c:367
static cBitmap bmAudio
Definition: skinlcars.c:367
virtual ~cSkinLCARSDisplayChannel()
Definition: skinlcars.c:475
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:610
static cBitmap bmRecording
Definition: skinlcars.c:367
cSkinLCARSDisplayChannel(bool WithInfo)
Definition: skinlcars.c:390
static cBitmap bmDolbyDigital
Definition: skinlcars.c:367
static cBitmap bmRadio
Definition: skinlcars.c:367
eCurrentMode lastMode
Definition: skinlcars.c:708
virtual ~cSkinLCARSDisplayMenu()
Definition: skinlcars.c:953
cVector< bool > deviceRecording
Definition: skinlcars.c:701
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable)
Sets the item at the given Index to Text.
Definition: skinlcars.c:1596
virtual void SetScrollbar(int Total, int Offset)
Sets the Total number of items in the currently displayed list, and the Offset of the first item that...
Definition: skinlcars.c:1633
virtual void SetButtons(const char *Red, const char *Green=NULL, const char *Yellow=NULL, const char *Blue=NULL)
Sets the color buttons to the given strings.
Definition: skinlcars.c:1565
virtual void SetTitle(const char *Title)
Sets the title of this menu to Title.
Definition: skinlcars.c:1555
void DrawTextScrollbar(void)
Definition: skinlcars.c:1529
bool lastLiveIndicatorTransferring
Definition: skinlcars.c:716
void DrawStatusElbows(void)
Definition: skinlcars.c:1134
void DrawMenuFrame(void)
Definition: skinlcars.c:1036
void DrawLiveIndicator(void)
Definition: skinlcars.c:1370
void DrawDevice(const cDevice *Device)
Definition: skinlcars.c:1343
virtual void Scroll(bool Up, bool Page)
If this menu contains a text area that can be scrolled, this function will be called to actually scro...
Definition: skinlcars.c:1535
virtual const cFont * GetTextAreaFont(bool FixedFont) const
Returns a pointer to the font which is used to display text with SetText().
Definition: skinlcars.c:1748
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:1755
virtual void SetEvent(const cEvent *Event)
Sets the Event that shall be displayed, using the entire central area of the menu.
Definition: skinlcars.c:1638
cVector< cCamSlot * > lastCamSlot
Definition: skinlcars.c:703
virtual int MaxItems(void)
Returns the maximum number of items the menu can display.
Definition: skinlcars.c:1541
static cBitmap bmArrowDown
Definition: skinlcars.c:723
virtual int GetTextAreaWidth(void) const
Returns the width in pixel of the area which is used to display text with SetText().
Definition: skinlcars.c:1743
void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font)
Definition: skinlcars.c:1028
void DrawDevices(void)
Definition: skinlcars.c:1360
const cRecording * lastRecording
Definition: skinlcars.c:720
cString lastDeviceType[MAXDEVICES]
Definition: skinlcars.c:702
void DrawLive(const cChannel *Channel)
Definition: skinlcars.c:1421
void DrawSignals(void)
Definition: skinlcars.c:1405
const cChannel * lastChannel
Definition: skinlcars.c:717
void DrawPlay(cControl *Control)
Definition: skinlcars.c:1463
void DrawMainFrameLower(void)
Definition: skinlcars.c:1009
void DrawSeen(int Current, int Total)
Definition: skinlcars.c:1517
cVector< int > lastSignalStrength
Definition: skinlcars.c:704
void DrawTimer(const cTimer *Timer, int y, bool MultiRec)
Definition: skinlcars.c:1207
static cBitmap bmTransferMode
Definition: skinlcars.c:723
void DrawInfo(const cEvent *Event, bool WithTime)
Definition: skinlcars.c:1502
cStateKey timersStateKey
Definition: skinlcars.c:713
void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown)
Definition: skinlcars.c:1168
virtual void SetRecording(const cRecording *Recording)
Sets the Recording that shall be displayed, using the entire central area of the menu.
Definition: skinlcars.c:1684
cVector< int > lastSignalQuality
Definition: skinlcars.c:705
virtual void Clear(void)
Clears the entire central area of the menu.
Definition: skinlcars.c:1549
void DrawMainBracket(void)
Definition: skinlcars.c:1120
const cEvent * lastEvent
Definition: skinlcars.c:719
virtual void SetMenuCategory(eMenuCategory MenuCategory)
Sets the current menu category.
Definition: skinlcars.c:960
void DrawMainFrameUpper(tColor Color)
Definition: skinlcars.c:990
void DrawTimers(void)
Definition: skinlcars.c:1249
void DrawFrameDisplay(void)
Definition: skinlcars.c:1152
virtual void SetText(const char *Text, bool FixedFont)
Sets the Text that shall be displayed, using the entire central area of the menu.
Definition: skinlcars.c:1737
static cBitmap bmArrowUp
Definition: skinlcars.c:723
cVector< int > deviceOffset
Definition: skinlcars.c:700
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:1586
virtual ~cSkinLCARSDisplayMessage()
Definition: skinlcars.c:2229
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2248
virtual void SetMessage(eMessageType Type, const char *Text)
< This class implements a simple message display.
Definition: skinlcars.c:2234
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:1960
virtual void SetCurrent(const char *Current)
Sets the current position within the recording, as a user readable string if the form "h:mm:ss....
Definition: skinlcars.c:1929
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:1950
virtual void SetProgress(int Current, int Total)
This function will be called whenever the position in or the total length of the recording has change...
Definition: skinlcars.c:1923
virtual void SetMode(bool Play, bool Forward, int Speed)
Sets the current replay mode, which can be used to display some indicator, showing the user whether w...
Definition: skinlcars.c:1916
cSkinLCARSDisplayReplay(bool ModeOnly)
Definition: skinlcars.c:1807
virtual void SetRecording(const cRecording *Recording)
Sets the recording that is currently being played.
Definition: skinlcars.c:1895
virtual void SetTotal(const char *Total)
Sets the total length of the recording, as a user readable string if the form "h:mm:ss".
Definition: skinlcars.c:1937
virtual void SetTitle(const char *Title)
Sets the title of the recording.
Definition: skinlcars.c:1904
virtual void SetJump(const char *Jump)
Sets the prompt that allows the user to enter a jump point.
Definition: skinlcars.c:1945
virtual ~cSkinLCARSDisplayReplay()
Definition: skinlcars.c:1871
static cBitmap bmAudioLeft
Definition: skinlcars.c:2060
static cBitmap bmAudioRight
Definition: skinlcars.c:2060
cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
Definition: skinlcars.c:2074
static cBitmap bmAudioStereo
Definition: skinlcars.c:2060
virtual void SetAudioChannel(int AudioChannel)
Sets the audio channel indicator.
Definition: skinlcars.c:2178
void SetItem(const char *Text, int Index, bool Current)
Definition: skinlcars.c:2143
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2193
virtual ~cSkinLCARSDisplayTracks()
Definition: skinlcars.c:2138
virtual void SetTrack(int Index, const char *const *Tracks)
< This class implements the track display.
Definition: skinlcars.c:2171
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2045
virtual ~cSkinLCARSDisplayVolume()
Definition: skinlcars.c:2012
virtual void SetVolume(int Current, int Total, bool Mute)
< This class implements the volume/mute display.
Definition: skinlcars.c:2017
virtual cSkinDisplayMenu * DisplayMenu(void)
Creates and returns a new object for displaying a menu.
Definition: skinlcars.c:2270
virtual cSkinDisplayMessage * DisplayMessage(void)
Creates and returns a new object for displaying a message.
Definition: skinlcars.c:2290
cSkinLCARS(void)
Definition: skinlcars.c:2255
virtual cSkinDisplayVolume * DisplayVolume(void)
Creates and returns a new object for displaying the current volume.
Definition: skinlcars.c:2280
virtual cSkinDisplayTracks * DisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
Creates and returns a new object for displaying the available tracks.
Definition: skinlcars.c:2285
virtual const char * Description(void)
Returns a user visible, single line description of this skin, which may consist of arbitrary text and...
Definition: skinlcars.c:2260
virtual cSkinDisplayReplay * DisplayReplay(bool ModeOnly)
Creates and returns a new object for displaying replay progress.
Definition: skinlcars.c:2275
virtual cSkinDisplayChannel * DisplayChannel(bool WithInfo)
Creates and returns a new object for displaying the current channel.
Definition: skinlcars.c:2265
static cString ToString(int Code)
Definition: sources.c:55
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
Definition: thread.c:859
void Reset(void)
Resets the state of this key, so that the next call to a lock's Lock() function with this key will re...
Definition: thread.c:854
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1149
cString & Truncate(int Index)
Truncate the string at the given Index (if Index is < 0 it is counted from the end of the string).
Definition: tools.c:1133
bool CanScroll(void)
void Set(cOsd *Osd, int Left, int Top, int Width, int Height, const char *Text, const cFont *Font, tColor ColorFg, tColor ColorBg)
Definition: osd.c:2346
void Reset(void)
Definition: osd.c:2363
bool CanScrollDown(void)
bool CanScrollUp(void)
tColor Color(int Subject)
Returns the color for the given Subject.
Definition: themes.c:201
bool Recording(void) const
time_t StopTimeEvent(void) const
or by the user (for normal timers)
Definition: timers.c:730
const cEvent * Event(void) const
uint Flags(void) const
const cChannel * Channel(void) const
bool Pending(void) const
time_t StartTimeEvent(void) const
the start/stop times as given by the event (for VPS timers), by event plus margins (for spawned non-V...
Definition: timers.c:719
const char * Remote(void) const
static const cTimers * GetTimersRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for read access.
Definition: timers.c:1168
int Size(void) const
virtual void Clear(void)
virtual void Append(T Data)
static int FreeMinutes(void)
Returns the number of minutes that can still be recorded on the video disk.
static bool HasChanged(int &State)
Returns true if the usage of the video disk space has changed since the last call to this function wi...
Definition: videodir.c:210
static int UsedPercent(void)
Returns the used space of the video disk in percent.
cSetup Setup
Definition: config.c:372
#define VDRVERSION
Definition: config.h:25
#define MAXDEVICES
Definition: device.h:29
#define LOCK_SCHEDULES_READ
Definition: epg.h:233
@ fontOsd
Definition: font.h:22
@ fontFix
Definition: font.h:23
uint32_t tColor
Definition: font.h:30
#define tr(s)
Definition: i18n.h:85
@ taCenter
@ taBorder
@ taTop
@ taBottom
@ taRight
@ taLeft
tColor RgbShade(tColor Color, double Factor)
Returns a brighter (Factor > 0) or darker (Factor < 0) version of the given Color.
Definition: osd.c:43
@ oeOk
eMenuCategory
@ mcMain
eMessageType
@ tfActive
@ tfVps
cString TimeString(time_t t)
Converts the given time to a string of the form "hh:mm".
Definition: tools.c:1255
T constrain(T v, T l, T h)
bool isempty(const char *s)
Definition: tools.c:349
#define SECSINDAY
cString WeekDayName(int WeekDay)
Converts the given WeekDay (0=Sunday, 1=Monday, ...) to a three letter day name.
Definition: tools.c:1172
cString ShortDateString(time_t t)
Converts the given time to a string of the form "dd.mm.yy".
Definition: tools.c:1246
cString DayDateTime(time_t t=0)
Converts the given time to a string of the form "www dd.mm. hh:mm".
Definition: tools.c:1214
cString DateString(time_t t)
Converts the given time to a string of the form "www dd.mm.yyyy".
Definition: tools.c:1235
T min(T a, T b)
void swap(T &a, T &b)
T max(T a, T b)
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
cString itoa(int n)
Definition: tools.c:442
#define clrTransparent
Definition: skincurses.c:36
#define clrBackground
Definition: skincurses.c:35
static const cCursesFont Font
Definition: skincurses.c:31
#define CLR_SEEN
Definition: skinlcars.c:93
#define CLR_BACKGROUND
Definition: skinlcars.c:79
static cTheme Theme
Definition: skinlcars.c:75
#define CLR_EVENT_TITLE
Definition: skinlcars.c:88
#define CLR_GREEN
Definition: skinlcars.c:98
#define CLR_BLUE
Definition: skinlcars.c:100
#define ShowSeenExtent
Definition: skinlcars.c:70
static const char *const * ReplaySymbols[2][2][5]
Definition: skinlcars.c:1909
#define CLR_EXPOSED
Definition: skinlcars.c:95
#define CLR_WHITE
Definition: skinlcars.c:96
#define CLR_REPLAY_FRAME
Definition: skinlcars.c:82
static cFont * CreateTinyFont(int LineHeight)
Definition: skinlcars.c:222
static bool DrawDeviceData(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &xs, const cFont *TinyFont, cString &LastDeviceType, cCamSlot *&LastCamSlot, bool Initial)
Definition: skinlcars.c:236
#define CLR_EVENT_TIME
Definition: skinlcars.c:89
#define CLR_RED
Definition: skinlcars.c:97
#define CLR_MENU_ITEMS
Definition: skinlcars.c:84
static void DrawDevicePosition(cOsd *Osd, const cPositioner *Positioner, int x0, int y0, int x1, int y1, int &LastCurrent)
Definition: skinlcars.c:303
static cOsd * CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1)
Definition: skinlcars.c:205
THEME_CLR(Theme, clrBackground, CLR_BACKGROUND)
#define TextFrame
Definition: skinlcars.c:67
#define CLR_ALERT
Definition: skinlcars.c:94
#define CLR_CHANNEL_FRAME
Definition: skinlcars.c:81
#define CLR_CHANNEL_NAME
Definition: skinlcars.c:87
static void DrawDeviceSignal(cOsd *Osd, const cDevice *Device, int x0, int y0, int x1, int y1, int &LastSignalStrength, int &LastSignalQuality, bool Initial)
Definition: skinlcars.c:267
#define DISKUSAGEALERTLIMIT
Definition: skinlcars.c:72
#define CLR_TRACK
Definition: skinlcars.c:92
#define CLR_MAIN_FRAME
Definition: skinlcars.c:80
#define SymbolSpacing
Definition: skinlcars.c:69
#define CLR_DEVICE
Definition: skinlcars.c:86
#define SIGNALDISPLAYDELTA
Definition: skinlcars.c:73
#define TextSpacing
Definition: skinlcars.c:68
#define Gap
Definition: skinlcars.c:66
static bool TwoColors
Definition: skinlcars.c:203
#define CLR_EVENT_SHORTTEXT
Definition: skinlcars.c:90
#define CLR_TIMER
Definition: skinlcars.c:85
#define CLR_TEXT
Definition: skinlcars.c:91
#define CLR_DATE
Definition: skinlcars.c:83
#define CLR_BLACK
Definition: skinlcars.c:101
#define CLR_YELLOW
Definition: skinlcars.c:99
char description[32]
Definition: device.h:83