vdr  2.2.0
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 3.8 2014/06/12 08:48:15 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 
75 static cTheme Theme;
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 
106 THEME_CLR(Theme, clrDateFg, CLR_BLACK);
107 THEME_CLR(Theme, clrDateBg, CLR_DATE);
108 THEME_CLR(Theme, clrTimerFg, CLR_BLACK);
109 THEME_CLR(Theme, clrTimerBg, CLR_TIMER);
110 THEME_CLR(Theme, clrDeviceFg, CLR_BLACK);
111 THEME_CLR(Theme, clrDeviceBg, CLR_DEVICE);
112 THEME_CLR(Theme, clrSignalValue, CLR_GREEN);
113 THEME_CLR(Theme, clrSignalRest, CLR_RED);
114 THEME_CLR(Theme, clrSeen, CLR_SEEN);
115 THEME_CLR(Theme, clrTrackName, CLR_TRACK);
116 THEME_CLR(Theme, clrAlertFg, CLR_WHITE);
117 THEME_CLR(Theme, clrAlertBg, CLR_ALERT);
118 THEME_CLR(Theme, clrChannelName, CLR_CHANNEL_NAME);
119 THEME_CLR(Theme, clrEventTitle, CLR_EVENT_TITLE);
120 THEME_CLR(Theme, clrEventTime, CLR_EVENT_TIME);
121 THEME_CLR(Theme, clrEventShortText, CLR_EVENT_SHORTTEXT);
122 THEME_CLR(Theme, clrEventDescription, CLR_TEXT);
123 
124 // Buttons:
125 
126 THEME_CLR(Theme, clrButtonRedFg, CLR_BLACK);
127 THEME_CLR(Theme, clrButtonRedBg, CLR_RED);
128 THEME_CLR(Theme, clrButtonGreenFg, CLR_BLACK);
129 THEME_CLR(Theme, clrButtonGreenBg, CLR_GREEN);
130 THEME_CLR(Theme, clrButtonYellowFg, CLR_BLACK);
131 THEME_CLR(Theme, clrButtonYellowBg, CLR_YELLOW);
132 THEME_CLR(Theme, clrButtonBlueFg, CLR_BLACK);
133 THEME_CLR(Theme, clrButtonBlueBg, CLR_BLUE);
134 
135 // Messages:
136 
137 THEME_CLR(Theme, clrMessageStatusFg, CLR_BLACK);
138 THEME_CLR(Theme, clrMessageStatusBg, CLR_BLUE);
139 THEME_CLR(Theme, clrMessageInfoFg, CLR_BLACK);
140 THEME_CLR(Theme, clrMessageInfoBg, CLR_GREEN);
141 THEME_CLR(Theme, clrMessageWarningFg, CLR_BLACK);
142 THEME_CLR(Theme, clrMessageWarningBg, CLR_YELLOW);
143 THEME_CLR(Theme, clrMessageErrorFg, CLR_BLACK);
144 THEME_CLR(Theme, clrMessageErrorBg, CLR_RED);
145 
146 // Volume:
147 
148 THEME_CLR(Theme, clrVolumeFrame, CLR_MAIN_FRAME);
149 THEME_CLR(Theme, clrVolumeSymbol, CLR_BLACK);
150 THEME_CLR(Theme, clrVolumeBarUpper, RgbShade(CLR_MAIN_FRAME, -0.2));
151 THEME_CLR(Theme, clrVolumeBarLower, CLR_GREEN);
152 
153 // Channel display:
154 
155 THEME_CLR(Theme, clrChannelFrameFg, CLR_BLACK);
156 THEME_CLR(Theme, clrChannelFrameBg, CLR_CHANNEL_FRAME);
157 THEME_CLR(Theme, clrChannelSymbolOn, CLR_BLACK);
158 THEME_CLR(Theme, clrChannelSymbolOff, RgbShade(CLR_CHANNEL_FRAME, -0.2));
159 THEME_CLR(Theme, clrChannelSymbolRecFg, CLR_WHITE);
160 THEME_CLR(Theme, clrChannelSymbolRecBg, CLR_RED);
161 
162 // Menu:
163 
164 THEME_CLR(Theme, clrMenuFrameFg, CLR_BLACK);
165 THEME_CLR(Theme, clrMenuFrameBg, CLR_MAIN_FRAME);
166 THEME_CLR(Theme, clrMenuTitle, CLR_MAIN_FRAME);
167 THEME_CLR(Theme, clrMenuMainBracket, CLR_MENU_ITEMS);
168 THEME_CLR(Theme, clrMenuTimerRecording, CLR_DEVICE);
169 THEME_CLR(Theme, clrMenuDeviceRecording, CLR_TIMER);
170 THEME_CLR(Theme, clrMenuItemCurrentFg, CLR_MAIN_FRAME);
171 THEME_CLR(Theme, clrMenuItemCurrentBg, RgbShade(CLR_MENU_ITEMS, -0.5));
172 THEME_CLR(Theme, clrMenuItemSelectable, CLR_MENU_ITEMS);
173 THEME_CLR(Theme, clrMenuItemNonSelectable, CLR_TEXT);
174 THEME_CLR(Theme, clrMenuScrollbarTotal, RgbShade(CLR_MAIN_FRAME, 0.2));
175 THEME_CLR(Theme, clrMenuScrollbarShown, CLR_SEEN);
176 THEME_CLR(Theme, clrMenuScrollbarArrow, CLR_BLACK);
177 THEME_CLR(Theme, clrMenuText, CLR_TEXT);
178 
179 // Replay display:
180 
181 THEME_CLR(Theme, clrReplayFrameFg, CLR_BLACK);
182 THEME_CLR(Theme, clrReplayFrameBg, CLR_REPLAY_FRAME);
183 THEME_CLR(Theme, clrReplayPosition, CLR_SEEN);
184 THEME_CLR(Theme, clrReplayJumpFg, CLR_BLACK);
185 THEME_CLR(Theme, clrReplayJumpBg, CLR_SEEN);
186 THEME_CLR(Theme, clrReplayProgressSeen, CLR_SEEN);
187 THEME_CLR(Theme, clrReplayProgressRest, RgbShade(CLR_WHITE, -0.2));
188 THEME_CLR(Theme, clrReplayProgressSelected, CLR_EXPOSED);
189 THEME_CLR(Theme, clrReplayProgressMark, CLR_BLACK);
190 THEME_CLR(Theme, clrReplayProgressCurrent, CLR_EXPOSED);
191 
192 // Track display:
193 
194 THEME_CLR(Theme, clrTrackFrameFg, CLR_BLACK);
195 THEME_CLR(Theme, clrTrackFrameBg, CLR_TRACK);
196 THEME_CLR(Theme, clrTrackItemFg, CLR_BLACK);
197 THEME_CLR(Theme, clrTrackItemBg, RgbShade(CLR_TRACK, 0.5));
198 THEME_CLR(Theme, clrTrackItemCurrentFg, CLR_BLACK);
199 THEME_CLR(Theme, clrTrackItemCurrentBg, CLR_TRACK);
200 
201 // --- Helper functions ------------------------------------------------------
202 
203 static bool TwoColors = false;
204 
205 static 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 
222 static 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 
236 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)
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->SlotNumber());
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 
267 static 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 
303 static 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 
344 private:
348  int xs; // starting column for signal display
349  bool withInfo;
354  bool message;
355  const cEvent *present;
356  bool initial;
358  int lastSeen;
368  void DrawDate(void);
369  void DrawTrack(void);
370  void DrawSeen(int Current, int Total);
371  void DrawDevice(void);
372  void DrawSignal(void);
373 public:
374  cSkinLCARSDisplayChannel(bool WithInfo);
375  virtual ~cSkinLCARSDisplayChannel();
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;
396  lastCurrentPosition = -1;
397  lastDeviceNumber = -1;
398  lastCamSlot = NULL;
399  lastSignalStrength = -1;
400  lastSignalQuality = -1;
401  lastSignalDisplay = 0;
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;
417  xc15 = cOsd::OsdWidth();
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);
447  osd->DrawRectangle(xc00, yc00, xc15 - 1, y1 - 1, Theme.Color(clrBackground));
448  // Rectangles:
449  osd->DrawRectangle(xc00, yc00, xc02 - 1, yc02 - 1, frameColor);
450  if (withInfo) {
451  osd->DrawRectangle(xc00, yc03, xc02 - 1, yc04 - 1, frameColor);
452  osd->DrawRectangle(xc00, yc05, xc02 - 1, yc06 - 1, frameColor);
453  // Elbow:
454  osd->DrawRectangle(xc00, yc07, xc01 - 1, yc08 - 1, frameColor);
456  osd->DrawEllipse (xc00, yc08, xc01 - 1, yc12 - 1, frameColor, 3);
457  osd->DrawRectangle(xc01, yc07, xc02 - 1, yc12 - 1, frameColor);
458  osd->DrawEllipse (xc02, yc09, xc04 - 1, yc11 - 1, frameColor, -3);
459  osd->DrawRectangle(xc02, yc11, xc05 - 1, yc12 - 1, frameColor);
460  // Status area:
461  osd->DrawRectangle(xc06, yc11 + lineHeight / 2, xc07 - 1, yc12 - 1, frameColor);
462  osd->DrawRectangle(xc08, yc11, xc09 - 1, yc12 - 1, frameColor);
463  osd->DrawRectangle(xc10, yc11, xc11 - 1, yc12 - 1, Theme.Color(clrDeviceBg));
464  osd->DrawRectangle(xc12, yc11, xc13 - 1, yc12 - 1, Theme.Color(clrDateBg));
465  osd->DrawRectangle(xc14, yc11, xc14 + lineHeight / 2 - 1, yc12 - 1, frameColor);
466  osd->DrawRectangle(xc14 + lineHeight / 2, yc11 + lineHeight / 2, xc15 - 1, yc12 - 1, clrTransparent);
467  osd->DrawEllipse (xc14 + lineHeight / 2, yc11, xc15 - 1, yc12 - 1, frameColor, 5);
468  }
469  // Icons:
470  osd->DrawRectangle(xc14, yc00, xc14 + lineHeight / 2 - 1, yc01 - 1, frameColor);
471  osd->DrawRectangle(xc14 + lineHeight / 2, yc00, xc15 - 1, yc00 + lineHeight / 2 - 1, clrTransparent);
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)) {
486  osd->DrawText(xc12, yc11, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xc13 - xc12, lineHeight, taRight | taBorder);
487  lastDate = s;
488  }
489 }
490 
492 {
493  cDevice *Device = cDevice::PrimaryDevice();
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 
501 void 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:
521  lastSignalStrength = -1;
522  lastSignalQuality = -1;
523  lastSignalDisplay = 0;
524  }
525 }
526 
528 {
529  time_t Now = time(NULL);
530  if (Now != lastSignalDisplay) {
532  lastSignalDisplay = Now;
533  }
534 }
535 
536 void 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()) {
557  x -= bmTeletext.Width() + SymbolSpacing;
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);
578  lastSignalDisplay = 0;
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 
588 void 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) {
599  osd->DrawText(xc00, y, e->GetTimeString(), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - xc00, 0, taRight | taBorder);
600  osd->DrawText(xc03, y, e->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc13 - xc03);
601  osd->DrawText(xc03, y + lineHeight, e->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xc13 - xc03);
602  }
603  else {
605  osd->DrawRectangle(xc02, y, xc13 - 1, y + 2 * lineHeight, Theme.Color(clrBackground));
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 {
634  osd->RestoreRegion();
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 {
647  lastCurrentPosition = -1;
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 
679 private:
689  int xi00, xi01, xi02, xi03;
690  int yi00, yi01;
694  int xs; // starting column for signal display
706  bool initial;
721  int lastSeen;
723  void DrawMainFrameUpper(tColor Color);
724  void DrawMainFrameLower(void);
725  void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font);
726  void DrawMenuFrame(void);
727  void DrawMainBracket(void);
728  void DrawStatusElbows(void);
729  void DrawDate(void);
730  void DrawDisk(void);
731  void DrawLoad(void);
732  void DrawFrameDisplay(void);
733  void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown);
734  void DrawTimer(const cTimer *Timer, int y, bool MultiRec);
735  void DrawTimers(void);
736  void DrawDevice(const cDevice *Device);
737  void DrawDevices(void);
738  void DrawLiveIndicator(void);
739  void DrawSignals(void);
740  void DrawLive(const cChannel *Channel);
741  void DrawPlay(cControl *Control);
742  void DrawInfo(const cEvent *Event, bool WithTime);
743  void DrawSeen(int Current, int Total);
744  void DrawTextScrollbar(void);
745 public:
746  cSkinLCARSDisplayMenu(void);
747  virtual ~cSkinLCARSDisplayMenu();
748  virtual void Scroll(bool Up, bool Page);
749  virtual int MaxItems(void);
750  virtual void Clear(void);
752  virtual void SetTitle(const char *Title);
753  virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
754  virtual void SetMessage(eMessageType Type, const char *Text);
755  virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
756  virtual void SetScrollbar(int Total, int Offset);
757  virtual void SetEvent(const cEvent *Event);
758  virtual void SetRecording(const cRecording *Recording);
759  virtual void SetText(const char *Text, bool FixedFont);
760  virtual int GetTextAreaWidth(void) const;
761  virtual const cFont *GetTextAreaFont(bool FixedFont) const;
762  virtual void Flush(void);
763  };
764 
768 
770 {
772  initial = true;
774  lastChannel = NULL;
775  lastEvent = NULL;
776  lastRecording = NULL;
777  lastSeen = -1;
778  lastTimersState = -1;
779  lastSignalDisplay = 0;
780  lastLiveIndicatorY = -1;
782  lastDiskUsageState = -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;
799  xa09 = cOsd::OsdWidth();
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 
835  yb15 = cOsd::OsdHeight();
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 {
962  if (initial || MenuCategory != cSkinDisplayMenu::MenuCategory()) {
963  cSkinDisplayMenu::SetMenuCategory(MenuCategory);
964  initial = true;
965  osd->DrawRectangle(xa00, yt00, xa09 - 1, yb15 - 1, Theme.Color(clrBackground));
966  if (MenuCategory == mcMain) {
967  yi00 = ym03;
968  yi01 = ym04;
969  xi00 = xm00;
970  xi01 = xm03;
971  xi02 = xm04;
972  xi03 = xm05;
973  lastTimersState = -1;
975  DrawMainBracket();
977  }
978  else {
979  yi00 = yt02;
980  yi01 = yb13;
981  xi00 = xa03;
982  xi01 = xa07;
983  xi02 = xa08;
984  xi03 = xa09;
985  DrawMenuFrame();
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:
1013  osd->DrawRectangle(xa00, yc10, xa01 - 1, yc11 - 1, frameColor);
1014  osd->DrawEllipse (xa00, yc06, xa01 - 1, yc10 - 1, frameColor, 2);
1015  osd->DrawRectangle(xa01, yc06, xa02 - 1, yc11 - 1, frameColor);
1016  osd->DrawEllipse (xa02, yc07, xa04 - 1, yc09 - 1, frameColor, -2);
1017  osd->DrawRectangle(xa02, yc06, xa05 - 1, yc07 - 1, frameColor);
1018  // Lower delimiter:
1019  osd->DrawRectangle(xa06, yc06, xm08 - 1, yc07 - lineHeight / 2 - 1, frameColor);
1020  osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor);
1021  osd->DrawRectangle(xa08, yc06, xa09 - 1, yc07 - 1, frameColor);
1022  // VDR version:
1023  osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor);
1024  osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
1025  osd->DrawText(xa00, yb15 - lineHeight, VDRVERSION, Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1026 }
1027 
1028 void cSkinLCARSDisplayMenu::DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font)
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:
1039  osd->DrawRectangle(xa00, yt05, xa01 - 1, yt06 - 1, frameColor);
1041  osd->DrawEllipse (xa00, yt00, xa01 - 1, yt05 - 1, frameColor, 2);
1042  osd->DrawRectangle(xa01, yt00, xa02 - 1, yt06 - 1, frameColor);
1043  osd->DrawEllipse (xa02, yt01, xa04 - 1, yt03 - 1, frameColor, -2);
1044  osd->DrawRectangle(xa02, yt00, xa05 - 1, yt01 - 1, frameColor);
1045  osd->DrawRectangle(xa06, yt00, xa07 - 1, yt01 - 1, frameColor);
1046  osd->DrawRectangle(xa08, yt00, xa08 + lineHeight / 2 - 1, yt01 - 1, frameColor);
1048  osd->DrawEllipse (xa08 + lineHeight / 2, yt00, xa09 - 1, yt01 - 1, frameColor, 5);
1049  // Center part:
1050  osd->DrawRectangle(xa00, yc00, xa02 - 1, yc11 - 1, frameColor);
1051  // Lower elbow:
1052  osd->DrawRectangle(xa00, yb10, xa02 - 1, yb11 - 1, frameColor);
1054  osd->DrawEllipse (xa00, yb11, xa01 - 1, yb15 - 1, frameColor, 3);
1055  osd->DrawRectangle(xa01, yb11, xa02 - 1, yb15 - 1, frameColor);
1056  osd->DrawEllipse (xa02, yb12, xa04 - 1, yb14 - 1, frameColor, -3);
1057  osd->DrawRectangle(xa02, yb14, xa05 - 1, yb15 - 1, frameColor);
1058  osd->DrawRectangle(xa08, yb14, xa08 + lineHeight / 2 - 1, yb15 - 1, frameColor);
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);
1138  osd->DrawRectangle(xs02, ys00, xs03 - 1, ys01 - 1, frameColor);
1139  osd->DrawEllipse (xs03, ys00, xs05 - 1, ys01 - 1, frameColor, 1);
1140  osd->DrawEllipse (xs03, ys01, xs04 - 1, ys02 - 1, frameColor, -1);
1141  osd->DrawRectangle(xs04, ys01, xs05 - 1, ys03 - 1, frameColor);
1142  osd->DrawRectangle(xs04, ys04, xs05 - 1, ys05 - 1, frameColor);
1143  osd->DrawText (xs10, ys00, tr("DEVICES"), Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs10, lineHeight, taBottom | taRight | taBorder);
1144  osd->DrawRectangle(xs08, ys00, xs09 - 1, ys01 - 1, frameColor);
1145  osd->DrawEllipse (xs06, ys00, xs08 - 1, ys01 - 1, frameColor, 2);
1146  osd->DrawEllipse (xs07, ys01, xs08 - 1, ys02 - 1, frameColor, -2);
1147  osd->DrawRectangle(xs06, ys01, xs07 - 1, ys03 - 1, frameColor);
1148  osd->DrawRectangle(xs06, ys04, xs07 - 1, ys05 - 1, frameColor);
1149  osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor);
1150 }
1151 
1153 {
1154  DrawDate();
1155  DrawDisk();
1156  DrawLoad();
1157  if (initial) {
1158  if (yb06)
1159  osd->DrawRectangle(xa00, yb06, xa02 - 1, yb07 - 1, frameColor);
1160  if (yb08) {
1161  const cFont *font = cFont::GetFont(fontOsd);
1162  osd->DrawRectangle(xa00, yb08, xa02 - 1, yb09 - 1, frameColor);
1163  osd->DrawText(xa00, yb09 - lineHeight, "LCARS", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1164  }
1165  }
1166 }
1167 
1168 void 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 
1207 void 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->StopTime()));
1217  else {
1218  time_t Now = time(NULL);
1219  cString Today = WeekDayName(Now);
1220  cString Time = TimeString(Timer->StartTime());
1221  cString Day = WeekDayName(Timer->StartTime());
1222  if (Timer->StartTime() > Now + 6 * SECSINDAY)
1223  Date = DayDateTime(Timer->StartTime());
1224  else if (strcmp(Day, Today) != 0)
1225  Date = cString::sprintf("%s %s", *Day, *Time);
1226  else
1227  Date = Time;
1228  }
1229  if (Timer->Flags() & tfVps)
1230  Date = cString::sprintf("VPS %s", *Date);
1231  const cChannel *Channel = Timer->Channel();
1232  const cEvent *Event = Timer->Event();
1233  int d = max(TextFrame / 2, 1);
1234  if (Channel) {
1235  osd->DrawText(xs00 + d, y, Channel->Name(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - d);
1236  osd->DrawText(xs03 - tinyFont->Width(Date) - d, y, Date, ColorFg, ColorBg, tinyFont);
1237  }
1238  if (Event)
1239  osd->DrawText(xs00 + d, y + lineHeight - tinyFont->Height(), Event->Title(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - 2 * d);
1240  // The timer recording indicator:
1241  if (Timer->Recording())
1242  osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording));
1243 }
1244 
1246 {
1249  const cFont *font = cFont::GetFont(fontOsd);
1250  osd->DrawRectangle(xs00, ys04, xs04 - 1, ys05 - 1, Theme.Color(clrBackground));
1251  osd->DrawRectangle(xs07, ys04, xs13 - 1, ys05 - 1, Theme.Color(clrBackground));
1252  cSortedTimers SortedTimers;
1253  cVector<int> FreeDeviceSlots;
1254  int NumDevices = 0;
1255  int y = ys04;
1256  // Timers and recording devices:
1257  while (1) {
1258  int NumTimers = 0;
1259  const cDevice *Device = NULL;
1260  for (int i = 0; i < SortedTimers.Size(); i++) {
1261  if (y + lineHeight > ys05)
1262  break;
1263  if (const cTimer *Timer = SortedTimers[i]) {
1264  if (Timer->Recording()) {
1265  if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) {
1266  if (!Device || Device == RecordControl->Device()) {
1267  DrawTimer(Timer, y, NumTimers > 0);
1268  NumTimers++;
1269  if (!Device) {
1270  Device = RecordControl->Device();
1271  deviceOffset[Device->DeviceNumber()] = y;
1272  deviceRecording[Device->DeviceNumber()] = true;
1273  NumDevices++;
1274  }
1275  else
1276  FreeDeviceSlots.Append(y);
1277  y += lineHeight + Gap;
1278  }
1279  else
1280  continue;
1281  }
1282  SortedTimers[i] = NULL;
1283  }
1284  else if (!Device && Timer->HasFlags(tfActive)) {
1285  DrawTimer(Timer, y, false);
1286  FreeDeviceSlots.Append(y);
1287  y += lineHeight + Gap;
1288  SortedTimers[i] = NULL;
1289  }
1290  }
1291  }
1292  if (!Device)
1293  break;
1294  }
1295  // Devices currently not recording:
1296  int Slot = 0;
1297  for (int i = 0; i < cDevice::NumDevices(); i++) {
1298  if (const cDevice *Device = cDevice::GetDevice(i)) {
1299  if (Device->NumProvidedSystems()) {
1300  if (!deviceRecording[Device->DeviceNumber()]) {
1301  if (Slot < FreeDeviceSlots.Size()) {
1302  y = FreeDeviceSlots[Slot];
1303  Slot++;
1304  }
1305  if (y + lineHeight > ys05)
1306  break;
1307  deviceOffset[Device->DeviceNumber()] = y;
1308  y += lineHeight + Gap;
1309  NumDevices++;
1310  }
1311  }
1312  }
1313  }
1314  // Total number of active timers:
1315  int NumTimers = 0;
1316  for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) {
1317  if (Timer->HasFlags(tfActive))
1318  NumTimers++;
1319  }
1320  osd->DrawText(xs02, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder);
1321  osd->DrawText(xs08, ys00, itoa(NumDevices), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder);
1322  lastSignalDisplay = 0;
1323  initial = true; // forces redrawing of devices
1324  }
1325 }
1326 
1328 {
1329  int dn = Device->DeviceNumber();
1330  int y = deviceOffset[dn];
1331  if (y + lineHeight <= ys05) {
1332  if (DrawDeviceData(osd, Device, xs08, y, xs11, y + lineHeight, xs, tinyFont, lastDeviceType[dn], lastCamSlot[dn], initial)) {
1333  // Make sure signal meters are redrawn:
1334  lastSignalStrength[dn] = -1;
1335  lastSignalQuality[dn] = -1;
1336  lastSignalDisplay = 0;
1337  }
1338  // The device recording indicator:
1339  if (deviceRecording[dn])
1340  osd->DrawRectangle(xs07 + Gap / 2, y, xs08 - Gap - 1, y + lineHeight - 1, Theme.Color(clrMenuDeviceRecording));
1341  }
1342 }
1343 
1345 {
1346  for (int i = 0; i < cDevice::NumDevices(); i++) {
1347  if (const cDevice *Device = cDevice::GetDevice(i)) {
1348  if (Device->NumProvidedSystems())
1349  DrawDevice(Device);
1350  }
1351  }
1352 }
1353 
1355 {
1356  cDevice *Device = cDevice::PrimaryDevice();
1357  int y = -1;
1358  bool Transferring = Device->Transferring();
1359  if (!Device->Replaying() || Transferring)
1361  if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) {
1362  if (lastLiveIndicatorY >= 0)
1364  if (y > 0) {
1365  tColor ColorBg = Theme.Color(clrChannelFrameBg);
1366  osd->DrawRectangle(xs12, y, xs12 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
1367  osd->DrawEllipse (xs12 + lineHeight / 2, y, xs13 - 1, y + lineHeight - 1, ColorBg, 5);
1368  if (Transferring) {
1369  int w = bmTransferMode.Width();
1370  int h = bmTransferMode.Height();
1371  int b = w * w + h * h; // the diagonal of the bitmap (squared)
1372  int c = lineHeight * lineHeight; // the diameter of the circle (squared)
1373  const cBitmap *bm = &bmTransferMode;
1374  if (b > c) {
1375  // the bitmap doesn't fit, so scale it down:
1376  double f = sqrt(double(c) / (2 * b));
1377  bm = bmTransferMode.Scaled(f, f);
1378  }
1379  osd->DrawBitmap((xs12 + xs13 - bm->Width()) / 2, y + (lineHeight - bm->Height()) / 2, *bm, Theme.Color(clrChannelFrameFg), ColorBg);
1380  if (bm != &bmTransferMode)
1381  delete bm;
1382  }
1383  }
1384  lastLiveIndicatorY = y;
1385  lastLiveIndicatorTransferring = Transferring;
1386  }
1387 }
1388 
1390 {
1391  time_t Now = time(NULL);
1392  if (initial || Now - lastSignalDisplay >= SIGNALDISPLAYDELTA) {
1393  for (int i = 0; i < cDevice::NumDevices(); i++) {
1394  if (const cDevice *Device = cDevice::GetDevice(i)) {
1395  if (Device->NumProvidedSystems()) {
1396  if (int y = deviceOffset[i])
1398  }
1399  }
1400  }
1401  lastSignalDisplay = Now;
1402  }
1403 }
1404 
1406 {
1407  if (lastMode != cmLive) {
1408  initial = true;
1409  lastMode = cmLive;
1410  }
1411  if (initial) {
1412  DrawMainFrameUpper(Theme.Color(clrChannelFrameBg));
1413  osd->DrawText(xd00, yd00, tr("LIVE"), Theme.Color(clrChannelFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
1414  }
1415  if (!Channel)
1416  return;
1417  if (initial || Channel != lastChannel) {
1418  osd->DrawText(xa00, yt00, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt02 - yt00, taTop | taRight | taBorder);
1419  osd->DrawText(xa03, yt00, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1420  int x = xa00 + (yc03 - yc02); // compensate for the arc
1421  osd->DrawText(x, yc00, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), cFont::GetFont(fontOsd), xa02 - x, yc03 - yc00, taTop | taRight | taBorder);
1422  lastChannel = Channel;
1423  DrawSeen(0, 0);
1424  }
1425  // The current programme:
1426  cSchedulesLock SchedulesLock;
1427  if (const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock)) {
1428  if (const cSchedule *Schedule = Schedules->GetSchedule(Channel)) {
1429  const cEvent *Event = Schedule->GetPresentEvent();
1430  if (initial || Event != lastEvent) {
1431  DrawInfo(Event, true);
1432  lastEvent = Event;
1433  lastSeen = -1;
1434  }
1435  int Current = 0;
1436  int Total = 0;
1437  if (Event) {
1438  time_t t = time(NULL);
1439  if (t > Event->StartTime())
1440  Current = t - Event->StartTime();
1441  Total = Event->Duration();
1442  }
1443  DrawSeen(Current, Total);
1444  }
1445  }
1446 }
1447 
1449 {
1450  if (lastMode != cmPlay) {
1451  initial = true;
1452  lastMode = cmPlay;
1453  }
1454  if (initial) {
1455  DrawMainFrameUpper(Theme.Color(clrReplayFrameBg));
1456  osd->DrawText(xd00, yd00, tr("PLAY"), Theme.Color(clrReplayFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
1457  }
1458  // The current progress:
1459  int Current = 0;
1460  int Total = 0;
1461  if (Control->GetIndex(Current, Total))
1462  DrawSeen(Current, Total);
1463  // The current programme:
1464  if (const cRecording *Recording = Control->GetRecording()) {
1465  if (initial || Recording != lastRecording) {
1466  const cFont *font = cFont::GetFont(fontOsd);
1467  if (const cRecordingInfo *Info = Recording->Info()) {
1468  osd->DrawText(xa03, yt00, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1469  DrawInfo(Info->GetEvent(), false);
1470  }
1471  else
1472  osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03, 0, taTop | taLeft);
1473  osd->DrawText(xa00, yt04, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder);
1474  osd->DrawText(xa00, yt06 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taBottom | taRight | taBorder);
1475  lastRecording = Recording;
1476  }
1477  }
1478  else {
1479  cString Header = Control->GetHeader();
1480  if (!*lastHeader || strcmp(Header, lastHeader)) {
1481  osd->DrawText(xa03, yt00, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1482  lastHeader = Header;
1483  }
1484  }
1485 }
1486 
1487 void cSkinLCARSDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime)
1488 {
1489  if (Event) {
1490  const cFont *font = cFont::GetFont(fontOsd);
1491  int y = yt04;
1492  osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03 - lineHeight, lineHeight, taBottom | taLeft);
1493  y += lineHeight;
1494  osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd00 - xa03 - lineHeight, lineHeight, taTop | taLeft);
1495  if (WithTime) {
1496  osd->DrawText(xa00, yt04, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder);
1497  osd->DrawText(xa00, yt06 - lineHeight, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1498  }
1499  }
1500 }
1501 
1502 void cSkinLCARSDisplayMenu::DrawSeen(int Current, int Total)
1503 {
1504  int Seen = (Total > 0) ? min(xm08 - xm02, int((xm08 - xm02) * double(Current) / Total)) : 0;
1505  if (initial || Seen != lastSeen) {
1506  int y0 = yc04 - ShowSeenExtent;
1507  int y1 = yc04 + lineHeight / 2 - Gap / 2;
1508  osd->DrawRectangle(xm02, y0, xm02 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
1509  osd->DrawRectangle(xm02 + Seen, y0, xm08 - 1, y1 - 1, Theme.Color(clrBackground));
1510  lastSeen = Seen;
1511  }
1512 }
1513 
1515 {
1516  if (textScroller.CanScroll())
1518 }
1519 
1520 void cSkinLCARSDisplayMenu::Scroll(bool Up, bool Page)
1521 {
1522  cSkinDisplayMenu::Scroll(Up, Page);
1524 }
1525 
1527 {
1528  if (MenuCategory() == mcMain)
1529  return (ym04 - ym03) / lineHeight;
1530  else
1531  return (yb13 - yt02) / lineHeight;
1532 }
1533 
1535 {
1536  textScroller.Reset();
1537  osd->DrawRectangle(xi00, yi00, xi03 - 1, yi01 - 1, Theme.Color(clrBackground));
1538 }
1539 
1540 void cSkinLCARSDisplayMenu::SetTitle(const char *Title)
1541 {
1542  if (MenuCategory() != mcMain) {
1543  const cFont *font = cFont::GetFont(fontOsd);
1544  int w = font->Width(Title);
1545  osd->DrawRectangle(xa06, yt00, xa07 - w - Gap - 1, yt01 - 1, frameColor);
1546  osd->DrawText(xa07 - w - Gap, yt00, Title, Theme.Color(clrMenuTitle), Theme.Color(clrBackground), font, w + Gap, yt01 - yt00, taRight);
1547  }
1548 }
1549 
1550 void cSkinLCARSDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
1551 {
1552  const char *lutText[] = { Red, Green, Yellow, Blue };
1553  tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg };
1554  tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
1555  const cFont *font = cFont::GetFont(fontSml);
1556  if (MenuCategory() == mcMain) {
1557  DrawMainButton(lutText[Setup.ColorKey0], xd00, xd01, xd02, xd03, yd02, yd03, Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font);
1558  DrawMainButton(lutText[Setup.ColorKey1], xd04, xd05, xd06, xd07, yd02, yd03, Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font);
1559  DrawMainButton(lutText[Setup.ColorKey2], xd00, xd01, xd02, xd03, yd04, yd05, Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font);
1560  DrawMainButton(lutText[Setup.ColorKey3], xd04, xd05, xd06, xd07, yd04, yd05, Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font);
1561  }
1562  else {
1563  int h = yb15 - yb14;
1564  osd->DrawText(xb02, yb14, lutText[Setup.ColorKey0], Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font, xb03 - xb02, h, taLeft | taBorder);
1565  osd->DrawText(xb06, yb14, lutText[Setup.ColorKey1], Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font, xb07 - xb06, h, taLeft | taBorder);
1566  osd->DrawText(xb10, yb14, lutText[Setup.ColorKey2], Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font, xb11 - xb10, h, taLeft | taBorder);
1567  osd->DrawText(xb14, yb14, lutText[Setup.ColorKey3], Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font, xb15 - xb14, h, taLeft | taBorder);
1568  }
1569 }
1570 
1572 {
1573  if (Text) {
1574  osd->SaveRegion(xb00, yb14, xb15 - 1, yb15 - 1);
1575  osd->DrawText(xb00, yb14, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xb15 - xb00, yb15 - yb14, taCenter);
1576  }
1577  else
1578  osd->RestoreRegion();
1579 }
1580 
1581 void cSkinLCARSDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
1582 {
1583  int y = yi00 + Index * lineHeight;
1584  tColor ColorFg, ColorBg;
1585  if (Current) {
1586  if (TwoColors) {
1587  ColorFg = Theme.Color(clrBackground);
1588  ColorBg = Theme.Color(clrMenuFrameBg);
1589  }
1590  else {
1591  ColorFg = Theme.Color(clrMenuItemCurrentFg);
1592  ColorBg = Theme.Color(clrMenuItemCurrentBg);
1593  }
1594  osd->DrawRectangle(xi00, y, xi01 - 1, y + lineHeight - 1, ColorBg);
1595  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
1596  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, y + lineHeight - 1, ColorBg, 5);
1597  currentIndex = Index;
1598  }
1599  else {
1600  ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
1601  ColorBg = Theme.Color(clrBackground);
1602  if (currentIndex == Index)
1603  osd->DrawRectangle(xi00, y, xi03 - 1, y + lineHeight - 1, Theme.Color(clrBackground));
1604  }
1605  const cFont *font = cFont::GetFont(fontOsd);
1606  for (int i = 0; i < MaxTabs; i++) {
1607  const char *s = GetTabbedText(Text, i);
1608  if (s) {
1609  int xt = xi00 + TextSpacing + Tab(i);
1610  osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xi01 - xt);
1611  }
1612  if (!Tab(i + 1))
1613  break;
1614  }
1616 }
1617 
1618 void cSkinLCARSDisplayMenu::SetScrollbar(int Total, int Offset)
1619 {
1620  DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total);
1621 }
1622 
1624 {
1625  if (!Event)
1626  return;
1627  const cFont *font = cFont::GetFont(fontOsd);
1628  int xl = xi00;
1629  int y = yi00;
1630  cTextScroller ts;
1631  char t[32];
1632  snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
1633  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
1634  if (Event->Vps() && Event->Vps() != Event->StartTime()) {
1635  cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());
1636  const cFont *font = cFont::GetFont(fontSml);
1637  int w = font->Width(buffer);
1638  osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1639  int yb = y + font->Height();
1640  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1641  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1642  }
1643  y += ts.Height();
1644  if (Event->ParentalRating()) {
1645  cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
1646  const cFont *font = cFont::GetFont(fontSml);
1647  int w = font->Width(buffer);
1648  osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1649  int yb = y + font->Height();
1650  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1651  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1652  }
1653  y += font->Height();
1654  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->Title(), font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
1655  y += ts.Height();
1656  if (!isempty(Event->ShortText())) {
1657  const cFont *font = cFont::GetFont(fontSml);
1658  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
1659  y += ts.Height();
1660  }
1661  y += font->Height();
1662  if (!isempty(Event->Description())) {
1663  int yt = y;
1664  int yb = yi01;
1665  textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Event->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
1667  }
1668 }
1669 
1671 {
1672  if (!Recording)
1673  return;
1674  const cRecordingInfo *Info = Recording->Info();
1675  const cFont *font = cFont::GetFont(fontOsd);
1676  int xl = xi00;
1677  int y = yi00;
1678  cTextScroller ts;
1679  cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
1680  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
1681  y += ts.Height();
1682  if (Info->GetEvent()->ParentalRating()) {
1683  cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
1684  const cFont *font = cFont::GetFont(fontSml);
1685  int w = font->Width(buffer);
1686  osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1687  int yb = y + font->Height();
1688  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1689  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1690  }
1691  y += font->Height();
1692  const char *Title = Info->Title();
1693  if (isempty(Title))
1694  Title = Recording->Name();
1695  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Title, font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
1696  y += ts.Height();
1697  if (!isempty(Info->ShortText())) {
1698  const cFont *font = cFont::GetFont(fontSml);
1699  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Info->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
1700  y += ts.Height();
1701  }
1702  y += font->Height();
1703  if (!isempty(Info->Description())) {
1704  int yt = y;
1705  int yb = yi01;
1706  textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Info->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
1708  }
1709 }
1710 
1711 void cSkinLCARSDisplayMenu::SetText(const char *Text, bool FixedFont)
1712 {
1713  textScroller.Set(osd, xi00, yi00, GetTextAreaWidth(), yi01 - yi00, Text, GetTextAreaFont(FixedFont), Theme.Color(clrMenuText), Theme.Color(clrBackground));
1715 }
1716 
1718 {
1719  return xi01 - xi00;
1720 }
1721 
1722 const cFont *cSkinLCARSDisplayMenu::GetTextAreaFont(bool FixedFont) const
1723 {
1724  const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd);
1725  //XXX -> make a way to let the text define which font to use
1726  return font;
1727 }
1728 
1730 {
1731  if (MenuCategory() == mcMain) {
1732  cDevice *Device = cDevice::PrimaryDevice();
1733  if (!Device->Replaying() || Device->Transferring()) {
1734  const cChannel *Channel = Channels.GetByNumber(cDevice::PrimaryDevice()->CurrentChannel());
1735  DrawLive(Channel);
1736  }
1737  else if (cControl *Control = cControl::Control(true))
1738  DrawPlay(Control);
1739  DrawTimers();
1740  DrawDevices();
1742  DrawSignals();
1743  }
1744  DrawFrameDisplay();
1745  osd->Flush();
1746  initial = false;
1747 }
1748 
1749 // --- cSkinLCARSDisplayReplay -----------------------------------------------
1750 
1752 private:
1756  bool modeOnly;
1763  void DrawDate(void);
1764  void DrawTrack(void);
1765 public:
1766  cSkinLCARSDisplayReplay(bool ModeOnly);
1767  virtual ~cSkinLCARSDisplayReplay();
1768  virtual void SetRecording(const cRecording *Recording);
1769  virtual void SetTitle(const char *Title);
1770  virtual void SetMode(bool Play, bool Forward, int Speed);
1771  virtual void SetProgress(int Current, int Total);
1772  virtual void SetCurrent(const char *Current);
1773  virtual void SetTotal(const char *Total);
1774  virtual void SetJump(const char *Jump);
1775  virtual void SetMessage(eMessageType Type, const char *Text);
1776  virtual void Flush(void);
1777  };
1778 
1780 {
1781  const cFont *font = cFont::GetFont(fontOsd);
1782  modeOnly = ModeOnly;
1783  lineHeight = font->Height();
1784  frameColor = Theme.Color(clrReplayFrameBg);
1785  lastCurrentWidth = 0;
1786  lastTotalWidth = 0;
1787  memset(&lastTrackId, 0, sizeof(lastTrackId));
1788  int d = 5 * lineHeight;
1789  xp00 = 0;
1790  xp01 = xp00 + d / 2;
1791  xp02 = xp00 + d;
1792  xp03 = xp02 + lineHeight;
1793  xp04 = xp02 + d / 4;
1794  xp05 = xp02 + d;
1795  xp06 = xp05 + Gap;
1796  xp15 = cOsd::OsdWidth();
1797  xp14 = xp15 - lineHeight;
1798  xp13 = xp14 - Gap;
1799  xp07 = (xp15 + xp00) / 2;
1800  xp08 = xp07 + Gap;
1801  xp09 = xp08 + lineHeight;
1802  xp10 = xp09 + Gap;
1803  xp11 = (xp10 + xp13 + Gap) / 2;
1804  xp12 = xp11 + Gap;
1805 
1806  yp00 = 0;
1807  yp01 = yp00 + 2 * lineHeight;
1808  yp02 = yp01 + Gap;
1809  yp03 = yp02 + 2 * lineHeight;
1810 
1811  yp04 = yp03 + Gap;
1812  yp09 = yp04 + 3 * lineHeight + Gap / 2;
1813  yp08 = yp09 - lineHeight;
1814  yp07 = yp08 - lineHeight;
1815  yp06 = yp08 - d / 4;
1816  yp05 = yp09 - d / 2;
1817 
1820  // Rectangles:
1821  if (!modeOnly)
1822  osd->DrawRectangle(xp00, yp00, xp02 - 1, yp01 - 1, frameColor);
1823  osd->DrawRectangle(xp00, yp02, xp02 - 1, yp03 - 1, frameColor);
1824  if (!modeOnly) {
1825  // Elbow:
1826  osd->DrawRectangle(xp00, yp04, xp01 - 1, yp05 - 1, frameColor);
1828  osd->DrawEllipse (xp00, yp05, xp01 - 1, yp09 - 1, frameColor, 3);
1829  osd->DrawRectangle(xp01, yp04, xp02 - 1, yp09 - 1, frameColor);
1830  osd->DrawEllipse (xp02, yp06, xp04 - 1, yp08 - 1, frameColor, -3);
1831  osd->DrawRectangle(xp02, yp08, xp05 - 1, yp09 - 1, frameColor);
1832  // Status area:
1833  osd->DrawRectangle(xp06, yp08, xp07 - 1, yp09 - 1, frameColor);
1834  osd->DrawRectangle(xp08, yp08, xp09 - 1, yp09 - 1, frameColor);
1835  osd->DrawRectangle(xp10, yp08, xp11 - 1, yp09 - 1, frameColor);
1836  osd->DrawRectangle(xp12, yp08, xp13 - 1, yp09 - 1, Theme.Color(clrDateBg));
1837  osd->DrawRectangle(xp14, yp08, xp14 + lineHeight / 2 - 1, yp09 - 1, frameColor);
1838  osd->DrawRectangle(xp14 + lineHeight / 2, yp08 + lineHeight / 2, xp15 - 1, yp09 - 1, clrTransparent);
1839  osd->DrawEllipse (xp14 + lineHeight / 2, yp08, xp15 - 1, yp09 - 1, frameColor, 5);
1840  }
1841 }
1842 
1844 {
1845  delete osd;
1846 }
1847 
1849 {
1850  cString s = DayDateTime();
1851  if (!*lastDate || strcmp(s, lastDate)) {
1852  osd->DrawText(xp12, yp08, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xp13 - xp12, lineHeight, taRight | taBorder);
1853  lastDate = s;
1854  }
1855 }
1856 
1858 {
1859  cDevice *Device = cDevice::PrimaryDevice();
1860  const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
1861  if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
1862  osd->DrawText(xp03, yp04, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp07 - xp03);
1863  strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
1864  }
1865 }
1866 
1868 {
1869  const cRecordingInfo *RecordingInfo = Recording->Info();
1870  SetTitle(RecordingInfo->Title());
1871  osd->DrawText(xp03, yp01 - lineHeight, RecordingInfo->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xp13 - xp03);
1872  osd->DrawText(xp00, yp00, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taTop | taRight | taBorder);
1873  osd->DrawText(xp00, yp01 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taBottom | taRight | taBorder);
1874 }
1875 
1876 void cSkinLCARSDisplayReplay::SetTitle(const char *Title)
1877 {
1878  osd->DrawText(xp03, yp00, Title, Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp13 - xp03);
1879 }
1880 
1881 static const char *const *ReplaySymbols[2][2][5] = {
1882  { { pause_xpm, srew_xpm, srew1_xpm, srew2_xpm, srew3_xpm },
1883  { pause_xpm, sfwd_xpm, sfwd1_xpm, sfwd2_xpm, sfwd3_xpm }, },
1884  { { play_xpm, frew_xpm, frew1_xpm, frew2_xpm, frew3_xpm },
1885  { play_xpm, ffwd_xpm, ffwd1_xpm, ffwd2_xpm, ffwd3_xpm } }
1886  };
1887 
1888 void cSkinLCARSDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
1889 {
1890  Speed = constrain(Speed, -1, 3);
1891  cBitmap bm(ReplaySymbols[Play][Forward][Speed + 1]);
1892  osd->DrawBitmap(xp01 - bm.Width() / 2, (yp02 + yp03 - bm.Height()) / 2, bm, Theme.Color(clrReplayFrameFg), frameColor);
1893 }
1894 
1895 void cSkinLCARSDisplayReplay::SetProgress(int Current, int Total)
1896 {
1897  cProgressBar pb(xp13 - xp03, lineHeight, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
1898  osd->DrawBitmap(xp03, yp02, pb);
1899 }
1900 
1901 void cSkinLCARSDisplayReplay::SetCurrent(const char *Current)
1902 {
1903  const cFont *font = cFont::GetFont(fontOsd);
1904  int w = font->Width(Current);
1905  osd->DrawText(xp03, yp03 - lineHeight, Current, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastCurrentWidth, w), 0, taLeft);
1906  lastCurrentWidth = w;
1907 }
1908 
1909 void cSkinLCARSDisplayReplay::SetTotal(const char *Total)
1910 {
1911  const cFont *font = cFont::GetFont(fontOsd);
1912  int w = font->Width(Total);
1913  osd->DrawText(xp13 - w, yp03 - lineHeight, Total, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastTotalWidth, w), 0, taRight);
1914  lastTotalWidth = w;
1915 }
1916 
1917 void cSkinLCARSDisplayReplay::SetJump(const char *Jump)
1918 {
1919  osd->DrawText(xp06, yp08, Jump, Theme.Color(clrReplayJumpFg), Jump ? Theme.Color(clrReplayJumpBg) : frameColor, cFont::GetFont(fontOsd), xp07 - xp06, 0, taCenter);
1920 }
1921 
1923 {
1924  if (Text) {
1925  osd->SaveRegion(xp06, yp08, xp13 - 1, yp09 - 1);
1926  osd->DrawText(xp06, yp08, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xp13 - xp06, yp09 - yp08, taCenter);
1927  }
1928  else
1929  osd->RestoreRegion();
1930 }
1931 
1933 {
1934  if (!modeOnly) {
1935  DrawDate();
1936  DrawTrack();
1937  }
1938  osd->Flush();
1939 }
1940 
1941 // --- cSkinLCARSDisplayVolume -----------------------------------------------
1942 
1944 private:
1946  int x0, x1, x2, x3, x4, x5, x6, x7;
1947  int y0, y1;
1949  int mute;
1950 public:
1952  virtual ~cSkinLCARSDisplayVolume();
1953  virtual void SetVolume(int Current, int Total, bool Mute);
1954  virtual void Flush(void);
1955  };
1956 
1958 {
1959  const cFont *font = cFont::GetFont(fontOsd);
1960  int lineHeight = font->Height();
1961  frameColor = Theme.Color(clrVolumeFrame);
1962  mute = -1;
1963  x0 = 0;
1964  x1 = lineHeight / 2;
1965  x2 = lineHeight;
1966  x3 = x2 + Gap;
1967  x7 = cOsd::OsdWidth();
1968  x6 = x7 - lineHeight / 2;
1969  x5 = x6 - lineHeight / 2;
1970  x4 = x5 - Gap;
1971  y0 = 0;
1972  y1 = lineHeight;
1973  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
1974  osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground));
1975  osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
1976  osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
1977  osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
1978  osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
1979  osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
1980  osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
1981  osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
1982 }
1983 
1985 {
1986  delete osd;
1987 }
1988 
1989 void cSkinLCARSDisplayVolume::SetVolume(int Current, int Total, bool Mute)
1990 {
1991  int xl = x3 + TextSpacing;
1992  int xr = x4 - TextSpacing;
1993  int yt = y0 + TextFrame;
1994  int yb = y1 - TextFrame;
1995  if (mute != Mute) {
1996  osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
1997  mute = Mute;
1998  }
1999  cBitmap bm(Mute ? mute_xpm : volume_xpm);
2000  osd->DrawBitmap(xl, y0 + (y1 - y0 - bm.Height()) / 2, bm, Theme.Color(clrVolumeSymbol), frameColor);
2001  if (!Mute) {
2002  xl += bm.Width() + TextSpacing;
2003  int w = (y1 - y0) / 3;
2004  int d = TextFrame;
2005  int n = (xr - xl + d) / (w + d);
2006  int x = xr - n * (w + d);
2007  tColor Color = Theme.Color(clrVolumeBarLower);
2008  for (int i = 0; i < n; i++) {
2009  if (Total * i >= Current * n)
2010  Color = Theme.Color(clrVolumeBarUpper);
2011  osd->DrawRectangle(x, yt, x + w - 1, yb - 1, Color);
2012  x += w + d;
2013  }
2014  }
2015 }
2016 
2018 {
2019  osd->Flush();
2020 }
2021 
2022 // --- cSkinLCARSDisplayTracks -----------------------------------------------
2023 
2025 private:
2033  void SetItem(const char *Text, int Index, bool Current);
2034 public:
2035  cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
2036  virtual ~cSkinLCARSDisplayTracks();
2037  virtual void SetTrack(int Index, const char * const *Tracks);
2038  virtual void SetAudioChannel(int AudioChannel);
2039  virtual void Flush(void);
2040  };
2041 
2045 
2046 cSkinLCARSDisplayTracks::cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
2047 {
2048  const cFont *font = cFont::GetFont(fontOsd);
2049  lineHeight = font->Height();
2050  frameColor = Theme.Color(clrTrackFrameBg);
2051  currentIndex = -1;
2052  xt00 = 0;
2053  xt01 = xt00 + lineHeight / 2;
2054  xt02 = xt01 + Gap;
2055  xt03 = xt00 + 2 * lineHeight;
2056  int ItemsWidth = font->Width(Title) + xt03 - xt02;
2057  for (int i = 0; i < NumTracks; i++)
2058  ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]) + 2 * TextFrame);
2059  xt04 = xt02 + ItemsWidth;
2060  xt05 = xt04 + Gap;
2061  xt06 = xt04 + lineHeight;
2062  xt07 = xt05 + lineHeight;
2063  xt08 = xt07 + lineHeight;
2064  xt09 = xt08 + Gap;
2065  xt10 = xt09 + lineHeight / 2;
2066  xt11 = xt10 + Gap;
2067  xt12 = xt11 + lineHeight;
2068  yt00 = 0;
2069  yt01 = yt00 + lineHeight;
2070  yt02 = yt01 + lineHeight;
2071  yt03 = yt02 + Gap;
2072  yt04 = yt03 + NumTracks * lineHeight + (NumTracks - 1) * Gap;
2073  yt05 = yt04 + Gap;
2074  yt06 = yt05 + lineHeight;
2075  yt07 = yt06 + lineHeight;
2076  while (yt07 > cOsd::OsdHeight()) {
2077  yt04 -= lineHeight + Gap;
2078  yt05 = yt04 + Gap;
2079  yt06 = yt05 + lineHeight;
2080  yt07 = yt06 + lineHeight;
2081  }
2083  // The upper elbow:
2084  osd->DrawRectangle(xt00, yt00, xt12 - 1, yt07 - 1, Theme.Color(clrBackground));
2086  osd->DrawEllipse (xt00, yt00, xt03 - 1, yt02 - 1, frameColor, 2);
2087  osd->DrawRectangle(xt03, yt00, xt04 - 1, yt02 - 1, frameColor);
2088  osd->DrawRectangle(xt04, yt00, xt08 - 1, yt01 - 1, frameColor);
2089  osd->DrawEllipse (xt04, yt01, xt06 - 1, yt02 - 1, frameColor, -2);
2090  osd->DrawRectangle(xt09, yt00, xt10 - 1, yt01 - 1, frameColor);
2091  osd->DrawRectangle(xt11, yt00, xt11 + lineHeight / 2 - 1, yt01 - 1, frameColor);
2092  osd->DrawRectangle(xt11 + lineHeight / 2, yt00, xt12 - 1, yt00 + lineHeight / 2 - 1, clrTransparent);
2093  osd->DrawEllipse (xt11 + lineHeight / 2, yt00, xt12 - 1, yt01 - 1, frameColor, 5);
2094  osd->DrawText(xt03, yt00, Title, Theme.Color(clrTrackFrameFg), frameColor, font, xt04 - xt03, 0, taTop | taRight);
2095  // The items:
2096  for (int i = 0; i < NumTracks; i++)
2097  SetItem(Tracks[i], i, false);
2098  // The lower elbow:
2099  osd->DrawRectangle(xt00, yt05, xt03 - 1, yt07 - 1, clrTransparent);
2100  osd->DrawEllipse (xt00, yt05, xt03 - 1, yt07 - 1, frameColor, 3);
2101  osd->DrawRectangle(xt03, yt05, xt04 - 1, yt07 - 1, frameColor);
2102  osd->DrawRectangle(xt04, yt06, xt08 - 1, yt07 - 1, frameColor);
2103  osd->DrawEllipse (xt04, yt05, xt06 - 1, yt06 - 1, frameColor, -3);
2104  osd->DrawRectangle(xt09, yt06, xt10 - 1, yt07 - 1, frameColor);
2105  osd->DrawRectangle(xt11, yt06, xt11 + lineHeight / 2 - 1, yt07 - 1, frameColor);
2106  osd->DrawRectangle(xt11 + lineHeight / 2, yt06 + lineHeight / 2, xt12 - 1, yt07 - 1, clrTransparent);
2107  osd->DrawEllipse (xt11 + lineHeight / 2, yt06, xt12 - 1, yt07 - 1, frameColor, 5);
2108 }
2109 
2111 {
2112  delete osd;
2113 }
2114 
2115 void cSkinLCARSDisplayTracks::SetItem(const char *Text, int Index, bool Current)
2116 {
2117  int y0 = yt03 + Index * (lineHeight + Gap);
2118  int y1 = y0 + lineHeight;
2119  if (y1 > yt04)
2120  return;
2121  tColor ColorFg, ColorBg;
2122  if (Current) {
2123  ColorFg = Theme.Color(clrTrackItemCurrentFg);
2124  ColorBg = Theme.Color(clrTrackItemCurrentBg);
2125  osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
2126  osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
2127  osd->DrawRectangle(xt05, y0, xt05 + lineHeight / 2 - 1, y1 - 1, ColorBg);
2128  osd->DrawEllipse (xt05 + lineHeight / 2, y0, xt07 - 1, y1 - 1, ColorBg, 5);
2129  currentIndex = Index;
2130  }
2131  else {
2132  ColorFg = Theme.Color(clrTrackItemFg);
2133  ColorBg = Theme.Color(clrTrackItemBg);
2134  osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
2135  osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
2136  if (currentIndex == Index)
2137  osd->DrawRectangle(xt05, y0, xt07 - 1, y1 - 1, Theme.Color(clrBackground));
2138  }
2139  const cFont *font = cFont::GetFont(fontOsd);
2140  osd->DrawText(xt02, y0, Text, ColorFg, ColorBg, font, xt04 - xt02, y1 - y0, taTop | taLeft | taBorder);
2141 }
2142 
2143 void cSkinLCARSDisplayTracks::SetTrack(int Index, const char * const *Tracks)
2144 {
2145  if (currentIndex >= 0)
2146  SetItem(Tracks[currentIndex], currentIndex, false);
2147  SetItem(Tracks[Index], Index, true);
2148 }
2149 
2151 {
2152  cBitmap *bm = NULL;
2153  switch (AudioChannel) {
2154  case 0: bm = &bmAudioStereo; break;
2155  case 1: bm = &bmAudioLeft; break;
2156  case 2: bm = &bmAudioRight; break;
2157  default: ;
2158  }
2159  if (bm)
2160  osd->DrawBitmap(xt04 - bm->Width(), (yt06 + yt07 - bm->Height()) / 2, *bm, Theme.Color(clrTrackFrameFg), frameColor);
2161  else
2162  osd->DrawRectangle(xt03, yt06, xt04 - 1, yt07 - 1, frameColor);
2163 }
2164 
2166 {
2167  osd->Flush();
2168 }
2169 
2170 // --- cSkinLCARSDisplayMessage ----------------------------------------------
2171 
2173 private:
2175  int x0, x1, x2, x3, x4, x5, x6, x7;
2176  int y0, y1;
2177 public:
2179  virtual ~cSkinLCARSDisplayMessage();
2180  virtual void SetMessage(eMessageType Type, const char *Text);
2181  virtual void Flush(void);
2182  };
2183 
2185 {
2186  const cFont *font = cFont::GetFont(fontOsd);
2187  int lineHeight = font->Height();
2188  x0 = 0;
2189  x1 = lineHeight / 2;
2190  x2 = lineHeight;
2191  x3 = x2 + Gap;
2192  x7 = cOsd::OsdWidth();
2193  x6 = x7 - lineHeight / 2;
2194  x5 = x6 - lineHeight / 2;
2195  x4 = x5 - Gap;
2196  y0 = 0;
2197  y1 = lineHeight;
2198  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
2199 }
2200 
2202 {
2203  delete osd;
2204 }
2205 
2207 {
2208  tColor ColorFg = Theme.Color(clrMessageStatusFg + 2 * Type);
2209  tColor ColorBg = Theme.Color(clrMessageStatusBg + 2 * Type);
2210  osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground));
2211  osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
2212  osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
2213  osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, ColorBg);
2214  osd->DrawText(x3, y0, Text, ColorFg, ColorBg, cFont::GetFont(fontSml), x4 - x3, y1 - y0, taCenter);
2215  osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, ColorBg);
2216  osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
2217  osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, ColorBg, 5);
2218 }
2219 
2221 {
2222  osd->Flush();
2223 }
2224 
2225 // --- cSkinLCARS ------------------------------------------------------------
2226 
2228 :cSkin("lcars", &::Theme)
2229 {
2230 }
2231 
2232 const char *cSkinLCARS::Description(void)
2233 {
2234  return "LCARS";
2235 }
2236 
2238 {
2239  return new cSkinLCARSDisplayChannel(WithInfo);
2240 }
2241 
2243 {
2244  return new cSkinLCARSDisplayMenu;
2245 }
2246 
2248 {
2249  return new cSkinLCARSDisplayReplay(ModeOnly);
2250 }
2251 
2253 {
2254  return new cSkinLCARSDisplayVolume;
2255 }
2256 
2257 cSkinDisplayTracks *cSkinLCARS::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
2258 {
2259  return new cSkinLCARSDisplayTracks(Title, NumTracks, Tracks);
2260 }
2261 
2263 {
2264  return new cSkinLCARSDisplayMessage;
2265 }
void DrawPlay(cControl *Control)
Definition: skinlcars.c:1448
virtual int SignalQuality(void) const
Returns the "quality" of the currently received signal.
Definition: device.c:730
virtual void SetTitle(const char *Title)
Sets the title of this menu to Title.
Definition: skinlcars.c:1540
static cBitmap bmAudioLeft
Definition: skinlcars.c:2032
static bool TwoColors
Definition: skinlcars.c:203
cString itoa(int n)
Definition: tools.c:388
static cString ToString(int Code)
Definition: sources.c:55
int Shown(void)
Definition: osd.h:1038
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
bool Replaying(void) const
Returns true if we are currently replaying.
Definition: device.c:1279
static int OsdHeight(void)
Definition: osd.h:789
Definition: epg.h:71
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:197
static cBitmap bmAudioRight
Definition: skinlcars.c:2032
#define CLR_RED
Definition: skinlcars.c:97
eMessageType
Definition: skins.h:24
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:1909
virtual void SetMenuCategory(eMenuCategory MenuCategory)
Sets the current menu category.
Definition: skinlcars.c:960
static cFont * CreateTinyFont(int LineHeight)
Definition: skinlcars.c:222
int Vpid(void) const
Definition: channels.h:154
int Number(void) const
Definition: channels.h:179
static cOsd * CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1)
Definition: skinlcars.c:205
cChannels Channels
Definition: channels.c:810
virtual cSkinDisplayMenu * DisplayMenu(void)
Creates and returns a new object for displaying a menu.
Definition: skinlcars.c:2242
bool isempty(const char *s)
Definition: tools.c:297
const cChannel * lastChannel
Definition: skinlcars.c:717
Definition: font.h:23
time_t Start(void) const
Definition: recording.h:128
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
void DrawTimers(void)
Definition: skinlcars.c:1245
virtual cSkinDisplayChannel * DisplayChannel(bool WithInfo)
Creates and returns a new object for displaying the current channel.
Definition: skinlcars.c:2237
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:1888
virtual ~cSkinLCARSDisplayTracks()
Definition: skinlcars.c:2110
static int NormalizeAngle(int Angle)
Normalizes the given Angle into the range -1800...1800.
Definition: positioner.c:42
const cEvent * lastEvent
Definition: skinlcars.c:718
const cRecordingInfo * Info(void) const
Definition: recording.h:149
time_t Vps(void) const
Definition: epg.h:109
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:1618
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition: osd.c:1823
bool GetIndex(int &Current, int &Total, bool SnapToIFrame=false)
Definition: player.h:102
eCurrentMode lastMode
Definition: skinlcars.c:708
static cBitmap bmEncrypted
Definition: skinlcars.c:367
#define CLR_EVENT_TIME
Definition: skinlcars.c:89
const char * ShortText(void) const
Definition: recording.h:86
char description[32]
Definition: device.h:90
#define CLR_SEEN
Definition: skinlcars.c:93
virtual void SetRecording(const cRecording *Recording)
Sets the Recording that shall be displayed, using the entire central area of the menu.
Definition: skinlcars.c:1670
#define TextSpacing
Definition: skinlcars.c:68
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:1922
int Ca(int Index=0) const
Definition: channels.h:173
static cTheme Theme
Definition: skinlcars.c:75
int Dpid(int i) const
Definition: channels.h:161
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
#define CLR_EXPOSED
Definition: skinlcars.c:95
cString GetParentalRatingString(void) const
Definition: epg.c:402
Definition: osd.h:163
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:1571
virtual void SetEvent(const cEvent *Event)
Sets the Event that shall be displayed, using the entire central area of the menu.
Definition: skinlcars.c:1623
virtual void SetRecording(const cRecording *Recording)
Sets the recording that is currently being played.
Definition: skinlcars.c:1867
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:1922
cTimers Timers
Definition: timers.c:694
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1080
static cBitmap bmRadio
Definition: skinlcars.c:367
int TargetLongitude(void) const
Returns the longitude the dish is supposed to be moved to.
Definition: positioner.h:105
virtual void Append(T Data)
Definition: tools.h:571
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:1962
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2220
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:2137
#define CLR_MENU_ITEMS
Definition: skinlcars.c:84
const cEvent * Event(void) const
Definition: timers.h:69
#define MAXDEVICES
Definition: device.h:29
int Duration(void) const
Definition: epg.h:108
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:1064
int bpp
Definition: osd.h:300
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
virtual void SetVolume(int Current, int Total, bool Mute)
< This class implements the volume/mute display.
Definition: skinlcars.c:1989
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition: device.c:261
#define SymbolSpacing
Definition: skinlcars.c:69
#define CLR_TEXT
Definition: skinlcars.c:91
static cControl * Control(bool Hidden=false)
Returns the current replay control (if any) in case it is currently visible.
Definition: player.c:73
eMenuCategory MenuCategory(void) const
Returns the menu category, set by a previous call to SetMenuCategory().
Definition: skins.h:165
virtual void SetTitle(const char *Title)
Sets the title of the recording.
Definition: skinlcars.c:1876
T max(T a, T b)
Definition: tools.h:55
bool GroupSep(void) const
Definition: channels.h:181
cSkinLCARS(void)
Definition: skinlcars.c:2227
virtual cSkinDisplayMessage * DisplayMessage(void)
Creates and returns a new object for displaying a message.
Definition: skinlcars.c:2262
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:1952
#define VDRVERSION
Definition: config.h:25
virtual ~cSkinLCARSDisplayMenu()
Definition: skinlcars.c:953
static int NumDevices(void)
Returns the total number of devices.
Definition: device.h:118
static cSkinDisplay * Current(void)
Returns the currently active cSkinDisplay.
Definition: skins.h:48
time_t StartTime(void) const
Definition: timers.c:497
virtual const cFont * GetTextAreaFont(bool FixedFont) const
Returns a pointer to the font which is used to display text with SetText().
Definition: skinlcars.c:1722
#define TextFrame
Definition: skinlcars.c:67
time_t StartTime(void) const
Definition: epg.h:106
#define CLR_EVENT_SHORTTEXT
Definition: skinlcars.c:90
int ColorKey2
Definition: config.h:310
T min(T a, T b)
Definition: tools.h:54
cString ChannelString(const cChannel *Channel, int Number)
Definition: channels.c:1061
void DrawSeen(int Current, int Total)
Definition: skinlcars.c:501
void DrawLiveIndicator(void)
Definition: skinlcars.c:1354
virtual ~cSkinLCARSDisplayReplay()
Definition: skinlcars.c:1843
cString lastDeviceType[MAXDEVICES]
Definition: skinlcars.c:702
void DrawDevices(void)
Definition: skinlcars.c:1344
virtual cSkinDisplayReplay * DisplayReplay(bool ModeOnly)
Creates and returns a new object for displaying replay progress.
Definition: skinlcars.c:2247
static const cSchedules * Schedules(cSchedulesLock &SchedulesLock)
Caller must provide a cSchedulesLock which has to survive the entire time the returned cSchedules is ...
Definition: epg.c:1201
void DrawLive(const cChannel *Channel)
Definition: skinlcars.c:1405
virtual void Flush(void)
Actually commits all data to the OSD hardware.
Definition: osd.c:1982
static cBitmap bmAudio
Definition: skinlcars.c:367
const cChannel * Channel(void) const
Definition: timers.h:56
Definition: osd.h:158
Definition: osd.h:169
int Width(void) const
Definition: osd.h:188
int Height(void)
Definition: osd.h:1035
#define clrBackground
Definition: skincurses.c:34
Definition: timers.h:27
#define CLR_WHITE
Definition: skinlcars.c:96
A steerable satellite dish generally points to the south on the northern hemisphere, and to the north on the southern hemisphere (unless you're located directly on the equator, in which case the general direction is "up").
Definition: positioner.h:31
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:833
#define Gap
Definition: skinlcars.c:66
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition: device.c:1284
Definition: osd.h:161
cString GetVpsString(void) const
Definition: epg.c:424
virtual int SignalStrength(void) const
Returns the "strength" of the currently received signal.
Definition: device.c:725
bool Recording(void) const
Definition: timers.h:52
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
virtual int Height(void) const =0
Returns the height of this font in pixel (all characters have the same height).
int ParentalRating(void) const
Definition: epg.h:105
static cBitmap bmArrowDown
Definition: skinlcars.c:722
const char * Name(void) const
Definition: channels.c:122
T * Next(const T *object) const
Definition: tools.h:495
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:653
cTextScroller textScroller
Definition: skins.h:155
void DrawSignals(void)
Definition: skinlcars.c:1389
#define CLR_GREEN
Definition: skinlcars.c:98
int Source(void) const
Definition: channels.h:152
#define DISKUSAGEALERTLIMIT
Definition: skinlcars.c:72
bool Modified(int &State)
Returns true if any of the timers have been modified, which is detected by State being different than...
Definition: timers.c:792
Definition: themes.h:17
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:1901
Definition: font.h:22
T constrain(T v, T l, T h)
Definition: tools.h:60
static int OsdWidth(void)
Definition: osd.h:788
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable)
Sets the item at the given Index to Text.
Definition: skinlcars.c:1581
cString WeekDayName(int WeekDay)
Converts the given WeekDay (0=Sunday, 1=Monday, ...) to a three letter day name.
Definition: tools.c:1103
virtual void SetJump(const char *Jump)
Sets the prompt that allows the user to enter a jump point.
Definition: skinlcars.c:1917
uint Flags(void) const
Definition: timers.h:55
bool lastLiveIndicatorTransferring
Definition: skinlcars.c:716
void DrawStatusElbows(void)
Definition: skinlcars.c:1134
int ChannelInfoPos
Definition: config.h:315
virtual int GetTextAreaWidth(void) const
Returns the width in pixel of the area which is used to display text with SetText().
Definition: skinlcars.c:1717
int Height(void) const
Definition: osd.h:189
#define CLR_MAIN_FRAME
Definition: skinlcars.c:80
Definition: osd.h:162
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas)
Checks whether the OSD can display the given set of sub-areas.
Definition: osd.c:1801
char FontOsd[MAXFONTNAME]
Definition: config.h:323
int Tpid(void) const
Definition: channels.h:171
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:2232
void swap(T &a, T &b)
Definition: tools.h:57
virtual int MaxItems(void)
Returns the maximum number of items the menu can display.
Definition: skinlcars.c:1526
static cBitmap bmDolbyDigital
Definition: skinlcars.c:367
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:197
bool Pending(void) const
Definition: timers.h:53
virtual void SetMessage(eMessageType Type, const char *Text)
< This class implements a simple message display.
Definition: skinlcars.c:2206
#define CLR_BLUE
Definition: skinlcars.c:100
tColor RgbShade(tColor Color, double Factor)
Returns a brighter (Factor > 0) or darker (Factor < 0) version of the given Color.
Definition: osd.c:43
int Tab(int n)
Returns the offset of the given tab from the left border of the item display area.
Definition: skins.h:156
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:2257
static const cCursesFont Font
Definition: skincurses.c:30
virtual void SetChannel(const cChannel *Channel, int Number)
Sets the current channel to Channel.
Definition: skinlcars.c:536
cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
Definition: skinlcars.c:2046
The cOsd class is the interface to the "On Screen Display".
Definition: osd.h:720
static bool Active(void)
Definition: menu.c:5109
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:1932
#define CLR_BACKGROUND
Definition: skinlcars.c:79
Definition: skins.h:94
static cBitmap bmArrowUp
Definition: skinlcars.c:722
cSetup Setup
Definition: config.c:372
virtual void SetEvents(const cEvent *Present, const cEvent *Following)
Sets the Present and Following EPG events.
Definition: skinlcars.c:588
void DrawSeen(int Current, int Total)
Definition: skinlcars.c:1502
Definition: ci.h:131
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:1520
static const char *const * ReplaySymbols[2][2][5]
Definition: skinlcars.c:1881
bool CanScroll(void)
Definition: osd.h:1039
cString DayDateTime(time_t t)
Converts the given time to a string of the form "www dd.mm. hh:mm".
Definition: tools.c:1145
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:423
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:1550
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:1942
static cBitmap bmAudioStereo
Definition: skinlcars.c:2032
void DrawFrameDisplay(void)
Definition: skinlcars.c:1152
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:1729
virtual int CurrentLongitude(void) const
Returns the longitude the dish currently points to.
Definition: positioner.c:114
cSkinLCARSDisplayReplay(bool ModeOnly)
Definition: skinlcars.c:1779
int Size(void) const
Definition: tools.h:551
#define CLR_YELLOW
Definition: skinlcars.c:99
int ColorKey3
Definition: config.h:310
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
Definition: skins.h:370
virtual void Clear(void)
Clears the entire central area of the menu.
Definition: skinlcars.c:1534
static int OsdTop(void)
Definition: osd.h:787
bool CanScrollUp(void)
Definition: osd.h:1040
void SetEditableWidth(int Width)
If an item is set through a call to cSkinDisplayMenu::SetItem(), this function shall be called to set...
Definition: skins.h:36
const char * Title(void) const
Definition: epg.h:100
void DrawMainFrameLower(void)
Definition: skinlcars.c:1009
static int OsdLeft(void)
Definition: osd.h:786
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
cVector< cCamSlot * > lastCamSlot
Definition: skinlcars.c:703
virtual cString DeviceType(void) const
Returns a string identifying the type of this device (like "DVB-S").
Definition: device.c:208
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:1711
void DrawMenuFrame(void)
Definition: skinlcars.c:1036
static cBitmap bmRecording
Definition: skinlcars.c:367
cString GetEndTimeString(void) const
Definition: epg.c:419
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:610
#define CLR_TRACK
Definition: skinlcars.c:92
const cEvent * present
Definition: skinlcars.c:355
cVector< int > deviceOffset
Definition: skinlcars.c:700
T * First(void) const
Definition: tools.h:492
virtual ~cSkinLCARSDisplayVolume()
Definition: skinlcars.c:1984
eMenuCategory
Definition: skins.h:91
void Reset(void)
Definition: osd.c:2154
time_t StopTime(void) const
Definition: timers.c:504
Definition: osd.h:298
cChannel * GetByNumber(int Number, int SkipGap=0)
Definition: channels.c:909
int ColorKey1
Definition: config.h:310
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:137
Definition: epg.h:143
void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown)
Definition: skinlcars.c:1168
virtual void SetMenuCategory(eMenuCategory MenuCategory)
Sets the current menu category.
Definition: skins.c:90
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2165
Definition: timers.h:21
Definition: osd.h:159
virtual cSkinDisplayVolume * DisplayVolume(void)
Creates and returns a new object for displaying the current volume.
Definition: skinlcars.c:2252
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:1049
int Apid(int i) const
Definition: channels.h:160
#define tr(s)
Definition: i18n.h:85
void DrawInfo(const cEvent *Event, bool WithTime)
Definition: skinlcars.c:1487
virtual ~cSkinLCARSDisplayChannel()
Definition: skinlcars.c:475
#define CLR_ALERT
Definition: skinlcars.c:94
#define SECSINDAY
Definition: tools.h:41
cString GetTimeString(void) const
Definition: epg.c:414
const cEvent * GetEvent(void) const
Definition: recording.h:84
const char * Description(void) const
Definition: recording.h:87
const char * Name(void) const
Returns the full name of the recording (without the video directory.
Definition: recording.h:142
cString TimeString(time_t t)
Converts the given time to a string of the form "hh:mm".
Definition: tools.c:1186
void SetItem(const char *Text, int Index, bool Current)
Definition: skinlcars.c:2115
static cRecordControl * GetRecordControl(const char *FileName)
Definition: menu.c:5060
const char * Title(void) const
Definition: recording.h:85
int FontOsdSize
Definition: config.h:329
const char * Description(void) const
Definition: epg.h:102
int ColorKey0
Definition: config.h:310
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise...
Definition: device.c:253
Definition: osd.h:44
Definition: osd.h:160
THEME_CLR(Theme, clrBackground, CLR_BACKGROUND)
virtual int Width(uint c) const =0
Returns the width of the given character in pixel.
#define CLR_EVENT_TITLE
Definition: skinlcars.c:88
#define SIGNALDISPLAYDELTA
Definition: skinlcars.c:73
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
virtual void SetAudioChannel(int AudioChannel)
Sets the audio channel indicator.
Definition: skinlcars.c:2150
#define CLR_TIMER
Definition: skinlcars.c:85
cString ShortDateString(time_t t)
Converts the given time to a string of the form "dd.mm.yy".
Definition: tools.c:1177
#define CLR_CHANNEL_NAME
Definition: skinlcars.c:87
virtual void SetTrack(int Index, const char *const *Tracks)
< This class implements the track display.
Definition: skinlcars.c:2143
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2017
virtual void RestoreRegion(void)
Restores the region previously saved by a call to SaveRegion().
Definition: osd.c:1871
static cBitmap bmTeletext
Definition: skinlcars.c:367
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
void SetAntiAliasGranularity(uint FixedColors, uint BlendColors)
Allows the system to optimize utilization of the limited color palette entries when generating blende...
Definition: osd.c:1695
const char * ChannelName(void) const
Definition: recording.h:83
cVector< bool > deviceRecording
Definition: skinlcars.c:701
#define CLR_DEVICE
Definition: skinlcars.c:86
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
#define CLR_REPLAY_FRAME
Definition: skinlcars.c:82
const cMarks * marks
< This class implements the progress display used during replay of a recording.
Definition: skins.h:291
static int FreeMinutes(void)
Returns the number of minutes that can still be recorded on the video disk.
Definition: videodir.h:117
#define ShowSeenExtent
Definition: skinlcars.c:70
void DrawMainBracket(void)
Definition: skinlcars.c:1120
static void DrawDevicePosition(cOsd *Osd, const cPositioner *Positioner, int x0, int y0, int x1, int y1, int &LastCurrent)
Definition: skinlcars.c:303
cString GetDateString(void) const
Definition: epg.c:409
void DrawDevice(const cDevice *Device)
Definition: skinlcars.c:1327
#define CLR_BLACK
Definition: skinlcars.c:101
const char * ShortText(void) const
Definition: epg.h:101
#define CLR_CHANNEL_FRAME
Definition: skinlcars.c:81
virtual void Clear(void)
Definition: tools.h:602
void DrawTextScrollbar(void)
Definition: skinlcars.c:1514
cVector< int > lastSignalQuality
Definition: skinlcars.c:705
eTrackType GetCurrentAudioTrack(void) const
Definition: device.h:535
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:1855
const cRecording * lastRecording
Definition: skinlcars.c:719
int HardLimitLongitude(ePositionerDirection Direction) const
Returns the longitude of the positioner's hard limit in the given Direction.
Definition: positioner.c:81
cSkinLCARSDisplayChannel(bool WithInfo)
Definition: skinlcars.c:390
tColor Color(int Subject)
Returns the color for the given Subject.
Definition: themes.c:201
#define CLR_DATE
Definition: skinlcars.c:83
Definition: font.h:37
virtual ~cSkinLCARSDisplayMessage()
Definition: skinlcars.c:2201
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
Definition: ci.h:184
The cDevice class is the base from which actual devices can be derived.
Definition: device.h:109
int Offset(void)
Definition: osd.h:1037
Definition: tools.h:168
virtual void SetPositioner(const cPositioner *Positioner)
Sets the Positioner used to move the satellite dish.
Definition: skinlcars.c:639
static cBitmap bmTransferMode
Definition: skinlcars.c:722
static const cFont * GetFont(eDvbFont Font)
Gets the given Font, which was previously set by a call to SetFont().
Definition: font.c:406
void DrawTimer(const cTimer *Timer, int y, bool MultiRec)
Definition: skinlcars.c:1207
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:1895
cString DateString(time_t t)
Converts the given time to a string of the form "www dd.mm.yyyy".
Definition: tools.c:1166
uint32_t tColor
Definition: font.h:29
bool CanScrollDown(void)
Definition: osd.h:1041
cVector< int > lastSignalStrength
Definition: skinlcars.c:704
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:2006
static int UsedPercent(void)
Returns the used space of the video disk in percent.
Definition: videodir.h:111
void DrawMainFrameUpper(tColor Color)
Definition: skinlcars.c:990
int Total(void)
Definition: osd.h:1036