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 
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:
681  int xa00, xa01, xa02, xa03, xa04, xa05, xa06, xa07, xa08, xa09;
682  int yt00, yt01, yt02, yt03, yt04, yt05, yt06;
684  int yb00, yb01, yb02, yb03, yb04, yb05, yb06, yb07, yb08, yb09, yb10, yb11, yb12, yb13, yb14, yb15;
685  int xm00, xm01, xm02, xm03, xm04, xm05, xm06, xm07, xm08;
686  int ym00, ym01, ym02, ym03, ym04, ym05, ym06, ym07;
687  int xs00, xs01, xs02, xs03, xs04, xs05, xs06, xs07, xs08, xs09, xs10, xs11, xs12, xs13;
688  int ys00, ys01, ys02, ys03, ys04, ys05;
689  int xi00, xi01, xi02, xi03;
690  int yi00, yi01;
691  int xb00, xb01, xb02, xb03, xb04, xb05, xb06, xb07, xb08, xb09, xb10, xb11, xb12, xb13, xb14, xb15;
692  int xd00, xd01, xd02, xd03, xd04, xd05, xd06, xd07;
693  int yd00, yd01, yd02, yd03, yd04, yd05;
694  int xs; // starting column for signal display
706  bool initial;
707  enum eCurrentMode { cmUnknown, cmLive, cmPlay };
721  int lastSeen;
722  static cBitmap bmArrowUp, bmArrowDown, bmTransferMode;
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);
751  virtual void SetMenuCategory(eMenuCategory MenuCategory);
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;
773  lastMode = cmUnknown;
774  lastChannel = NULL;
775  lastEvent = NULL;
776  lastRecording = NULL;
777  lastSeen = -1;
778  lastTimersState = -1;
779  lastSignalDisplay = 0;
780  lastLiveIndicatorY = -1;
781  lastLiveIndicatorTransferring = false;
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 
950  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop(), xa00, yt00, xa09 - 1, yb15 - 1);
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;
974  DrawMainFrameLower();
975  DrawMainBracket();
976  DrawStatusElbows();
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);
1040  osd->DrawRectangle(xa00, yt00, xa01 - 1, yt05 - 1, clrTransparent);
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);
1047  osd->DrawRectangle(xa08 + lineHeight / 2, yt00, xa09 - 1, yt00 + lineHeight / 2 - 1, clrTransparent);
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);
1053  osd->DrawRectangle(xa00, yb11, xa01 - 1, yb15 - 1, clrTransparent);
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);
1059  osd->DrawRectangle(xa08 + lineHeight / 2, yb14 + lineHeight / 2, xa09 - 1, yb15 - 1, clrTransparent);
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 {
1247  if (Timers.Modified(lastTimersState)) {
1248  deviceRecording.Clear();
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)
1360  y = deviceOffset[cDevice::ActualDevice()->DeviceNumber()];
1361  if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) {
1362  if (lastLiveIndicatorY >= 0)
1363  osd->DrawRectangle(xs12, lastLiveIndicatorY, xs13 - 1, lastLiveIndicatorY + lineHeight - 1, Theme.Color(clrBackground));
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 
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())
1517  DrawScrollbar(textScroller.Total(), textScroller.Offset(), textScroller.Shown(), textScroller.CanScrollUp(), textScroller.CanScrollDown());
1518 }
1519 
1520 void cSkinLCARSDisplayMenu::Scroll(bool Up, bool Page)
1521 {
1522  cSkinDisplayMenu::Scroll(Up, Page);
1523  DrawTextScrollbar();
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  }
1615  SetEditableWidth(xi02 - xi00 - TextSpacing - Tab(1));
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));
1666  DrawTextScrollbar();
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));
1707  DrawTextScrollbar();
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));
1714  DrawTextScrollbar();
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();
1741  DrawLiveIndicator();
1742  DrawSignals();
1743  }
1744  DrawFrameDisplay();
1745  osd->Flush();
1746  initial = false;
1747 }
1748 
1749 // --- cSkinLCARSDisplayReplay -----------------------------------------------
1750 
1752 private:
1754  int xp00, xp01, xp02, xp03, xp04, xp05, xp06, xp07, xp08, xp09, xp10, xp11, xp12, xp13, xp14, xp15;
1755  int yp00, yp01, yp02, yp03, yp04, yp05, yp06, yp07, yp08, yp09;
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 
1818  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - yp09, xp00, yp00, xp15 - 1, yp09 - 1);
1819  osd->DrawRectangle(xp00, yp00, xp15 - 1, yp09 - 1, modeOnly ? clrTransparent : Theme.Color(clrBackground));
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);
1827  osd->DrawRectangle(xp00, yp05, xp01 - 1, yp09 - 1, clrTransparent);
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 
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 
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:
2027  int xt00, xt01, xt02, xt03, xt04, xt05, xt06, xt07, xt08, xt09, xt10, xt11, xt12;
2028  int yt00, yt01, yt02, yt03, yt04, yt05, yt06, yt07;
2032  static cBitmap bmAudioLeft, bmAudioRight, bmAudioStereo;
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  }
2082  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - yt07, xt00, yt00, xt12 - 1, yt07 - 1);
2083  // The upper elbow:
2084  osd->DrawRectangle(xt00, yt00, xt12 - 1, yt07 - 1, Theme.Color(clrBackground));
2085  osd->DrawRectangle(xt00, yt00, xt03 - 1, yt02 - 1, clrTransparent);
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:677
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
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:1217
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:161
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:170
int Number(void) const
Definition: channels.h:197
static cOsd * CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1)
Definition: skinlcars.c:205
cChannels Channels
Definition: channels.c:864
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:191
static cTheme Theme
Definition: skinlcars.c:75
int Dpid(int i) const
Definition: channels.h:177
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:223
#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:199
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:311
T min(T a, T b)
Definition: tools.h:54
cString ChannelString(const cChannel *Channel, int Number)
Definition: channels.c:1147
void DrawSeen(int Current, int Total)
Definition: skinlcars.c:501
void DrawLiveIndicator(void)
Definition: skinlcars.c:1354
virtual ~cSkinLCARSDisplayReplay()
Definition: skinlcars.c:1843
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
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, provided this cSkinDisplay actually has a color button d...
Definition: skins.h:40
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&#39;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:436
#define Gap
Definition: skinlcars.c:66
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition: device.c:1222
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:672
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
int ParentalRating(void) const
Definition: epg.h:105
static cBitmap bmArrowDown
Definition: skinlcars.c:722
const char * Name(void) const
Definition: channels.c:123
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
void DrawSignals(void)
Definition: skinlcars.c:1389
#define CLR_GREEN
Definition: skinlcars.c:98
int Source(void) const
Definition: channels.h:168
#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:316
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:324
int Tpid(void) const
Definition: channels.h:187
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
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:5321
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:373
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:128
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
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:311
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
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:170
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
time_t StopTime(void) const
Definition: timers.c:504
Definition: osd.h:298
cChannel * GetByNumber(int Number, int SkipGap=0)
Definition: channels.c:995
int ColorKey1
Definition: config.h:311
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:137
virtual int Width(uint c) const =0
Returns the width of the given character in pixel.
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:987
int Apid(int i) const
Definition: channels.h:176
void DrawInfo(const cEvent *Event, bool WithTime)
Definition: skinlcars.c:1487
#define tr(s)
Definition: i18n.h:85
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:5272
const char * Title(void) const
Definition: recording.h:85
int FontOsdSize
Definition: config.h:330
const char * Description(void) const
Definition: epg.h:102
int ColorKey0
Definition: config.h:311
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise...
Definition: device.c:215
Definition: osd.h:44
Definition: osd.h:160
THEME_CLR(Theme, clrBackground, CLR_BACKGROUND)
#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&#39;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 int Height(void) const =0
Returns the height of this font in pixel (all characters have the same height).
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
#define CLR_REPLAY_FRAME
Definition: skinlcars.c:82
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
void DrawTextScrollbar(void)
Definition: skinlcars.c:1514
cVector< int > lastSignalQuality
Definition: skinlcars.c:705
eTrackType GetCurrentAudioTrack(void) const
Definition: device.h:542
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&#39;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:181
The cDevice class is the base from which actual devices can be derived.
Definition: device.h:109
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
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