vdr  2.4.1
skinlcars.c
Go to the documentation of this file.
1 /*
2  * skinlcars.c: A VDR skin with Star Trek's "LCARS" layout
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: skinlcars.c 4.6 2017/11/08 10:10:30 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->MasterSlotNumber());
258  Osd->DrawText(x, y1 - TinyFont->Height(), s, ColorFg, ColorBg, TinyFont);
259  xs = max(xs, x + TinyFont->Width(s));
260  }
261  LastCamSlot = CamSlot;
262  return true;
263  }
264  return false;
265 }
266 
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);
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);
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);
472  osd->DrawEllipse (xc14 + lineHeight / 2, yc00, xc15 - 1, yc01 - 1, frameColor, 5);
473 }
474 
476 {
477  delete tallFont;
478  delete tinyFont;
479  delete osd;
480 }
481 
483 {
484  cString s = DayDateTime();
485  if (initial || !*lastDate || strcmp(s, lastDate)) {
487  lastDate = s;
488  }
489 }
490 
492 {
493  cDevice *Device = cDevice::PrimaryDevice();
494  const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
495  if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
496  osd->DrawText(xc03, yc07, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xc07 - xc03);
497  strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
498  }
499 }
500 
501 void cSkinLCARSDisplayChannel::DrawSeen(int Current, int Total)
502 {
503  if (lastCurrentPosition >= 0)
504  return; // to not interfere with SetPositioner()
505  int Seen = (Total > 0) ? min(xc07 - xc06, int((xc07 - xc06) * double(Current) / Total)) : 0;
506  if (initial || Seen != lastSeen) {
507  int y0 = yc11 - ShowSeenExtent;
508  int y1 = yc11 + lineHeight / 2 - Gap / 2;
509  osd->DrawRectangle(xc06, y0, xc06 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
510  osd->DrawRectangle(xc06 + Seen, y0, xc07 - 1, y1 - 1, Theme.Color(clrBackground));
511  lastSeen = Seen;
512  }
513 }
514 
516 {
517  const cDevice *Device = cDevice::ActualDevice();
519  lastDeviceNumber = Device->DeviceNumber();
520  // Make sure signal meters are redrawn:
521  lastSignalStrength = -1;
522  lastSignalQuality = -1;
523  lastSignalDisplay = 0;
524  }
525 }
526 
528 {
529  time_t Now = time(NULL);
530  if (Now != lastSignalDisplay) {
532  lastSignalDisplay = Now;
533  }
534 }
535 
536 void cSkinLCARSDisplayChannel::SetChannel(const cChannel *Channel, int Number)
537 {
538  int x = xc13;
539  int xi = x - SymbolSpacing -
545  osd->DrawRectangle(xi, yc00, xc13 - 1, yc01 - 1, frameColor);
546  if (Channel && !Channel->GroupSep()) {
547  bool rec = cRecordControls::Active();
549  osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : frameColor);
551  osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmEncrypted.Height()) / 2, bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
553  osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmDolbyDigital.Height()) / 2, bmDolbyDigital, Theme.Color(Channel->Dpid(0) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
554  x -= bmAudio.Width() + SymbolSpacing;
555  osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmAudio.Height()) / 2, bmAudio, Theme.Color(Channel->Apid(1) ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
556  if (Channel->Vpid()) {
557  x -= bmTeletext.Width() + SymbolSpacing;
558  osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), frameColor);
559  }
560  else if (Channel->Apid(0)) {
561  x -= bmRadio.Width() + SymbolSpacing;
562  osd->DrawBitmap(x, yc00 + (yc01 - yc00 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor);
563  }
564  }
565  cString ChNumber("");
566  cString ChName("");
567  if (Channel) {
568  ChName = Channel->Name();
569  if (!Channel->GroupSep())
570  ChNumber = cString::sprintf("%d%s", Channel->Number(), Number ? "-" : "");
571  }
572  else if (Number)
573  ChNumber = cString::sprintf("%d-", Number);
574  else
575  ChName = ChannelString(NULL, 0);
576  osd->DrawText(xc00, yc00, ChNumber, Theme.Color(clrChannelFrameFg), frameColor, tallFont, xc02 - xc00, yc02 - yc00, taTop | taRight | taBorder);
577  osd->DrawText(xc03, yc00, ChName, Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xi - xc03 - lineHeight, 0, taTop | taLeft);
578  lastSignalDisplay = 0;
579  if (withInfo) {
580  if (Channel) {
581  int x = xc00 + (yc10 - yc09); // compensate for the arc
582  osd->DrawText(x, yc07, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - x, yc10 - yc07, taTop | taRight | taBorder);
583  }
584  DrawDevice();
585  }
586 }
587 
588 void cSkinLCARSDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
589 {
590  if (!withInfo)
591  return;
592  if (present != Present)
593  lastSeen = -1;
594  present = Present;
595  for (int i = 0; i < 2; i++) {
596  const cEvent *e = !i ? Present : Following;
597  int y = !i ? yc03 : yc05;
598  if (e) {
599  osd->DrawText(xc00, y, e->GetTimeString(), Theme.Color(clrChannelFrameFg), frameColor, cFont::GetFont(fontOsd), xc02 - xc00, 0, taRight | taBorder);
601  osd->DrawText(xc03, y + lineHeight, e->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xc13 - xc03);
602  }
603  else {
606  }
607  }
608 }
609 
611 {
612  if (Text) {
613  int x0, x1, y0, y1, y2;
614  if (withInfo) {
615  x0 = xc06;
616  x1 = xc13;
617  y0 = yc11 - ShowSeenExtent;
618  y1 = yc11;
619  y2 = yc12;
620  }
621  else {
622  x0 = xc03;
623  x1 = xc13;
624  y0 = y1 = yc00;
625  y2 = yc02;
626  }
627  osd->SaveRegion(x0, y0, x1 - 1, y2 - 1);
628  if (withInfo)
629  osd->DrawRectangle(xc06, y0, xc07, y1 - 1, Theme.Color(clrBackground)); // clears the "seen" bar
630  osd->DrawText(x0, y1, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), x1 - x0, y2 - y1, taCenter);
631  message = true;
632  }
633  else {
634  osd->RestoreRegion();
635  message = false;
636  }
637 }
638 
640 {
641  if (Positioner) {
642  int y0 = yc11 - ShowSeenExtent;
643  int y1 = yc11 + lineHeight / 2 - Gap / 2;
644  DrawDevicePosition(osd, Positioner, xc06, y0, xc07, y1, lastCurrentPosition);
645  }
646  else {
647  lastCurrentPosition = -1;
648  initial = true; // to have DrawSeen() refresh the progress bar
649  }
650  return;
651 }
652 
654 {
655  if (withInfo) {
656  if (!message) {
657  DrawDate();
658  DrawTrack();
659  DrawDevice();
660  DrawSignal();
661  int Current = 0;
662  int Total = 0;
663  if (present) {
664  time_t t = time(NULL);
665  if (t > present->StartTime())
666  Current = t - present->StartTime();
667  Total = present->Duration();
668  }
669  DrawSeen(Current, Total);
670  }
671  }
672  osd->Flush();
673  initial = false;
674 }
675 
676 // --- cSkinLCARSDisplayMenu -------------------------------------------------
677 
679 private:
689  int xi00, xi01, xi02, xi03;
690  int yi00, yi01;
694  int xs; // starting column for signal display
706  bool initial;
722  int lastSeen;
724  void DrawMainFrameUpper(tColor Color);
725  void DrawMainFrameLower(void);
726  void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font);
727  void DrawMenuFrame(void);
728  void DrawMainBracket(void);
729  void DrawStatusElbows(void);
730  void DrawDate(void);
731  void DrawDisk(void);
732  void DrawLoad(void);
733  void DrawFrameDisplay(void);
734  void DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown);
735  void DrawTimer(const cTimer *Timer, int y, bool MultiRec);
736  void DrawTimers(void);
737  void DrawDevice(const cDevice *Device);
738  void DrawDevices(void);
739  void DrawLiveIndicator(void);
740  void DrawSignals(void);
741  void DrawLive(const cChannel *Channel);
742  void DrawPlay(cControl *Control);
743  void DrawInfo(const cEvent *Event, bool WithTime);
744  void DrawSeen(int Current, int Total);
745  void DrawTextScrollbar(void);
746 public:
747  cSkinLCARSDisplayMenu(void);
748  virtual ~cSkinLCARSDisplayMenu();
749  virtual void Scroll(bool Up, bool Page);
750  virtual int MaxItems(void);
751  virtual void Clear(void);
753  virtual void SetTitle(const char *Title);
754  virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
755  virtual void SetMessage(eMessageType Type, const char *Text);
756  virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
757  virtual void SetScrollbar(int Total, int Offset);
758  virtual void SetEvent(const cEvent *Event);
759  virtual void SetRecording(const cRecording *Recording);
760  virtual void SetText(const char *Text, bool FixedFont);
761  virtual int GetTextAreaWidth(void) const;
762  virtual const cFont *GetTextAreaFont(bool FixedFont) const;
763  virtual void Flush(void);
764  };
765 
769 
771 {
773  initial = true;
775  lastChannel = NULL;
776  lastEvent = NULL;
777  lastRecording = NULL;
778  lastSeen = -1;
779  lastSignalDisplay = 0;
780  lastLiveIndicatorY = -1;
782  lastDiskUsageState = -1;
783  lastDiskAlert = false;
784  lastSystemLoad = -1;
785  const cFont *font = cFont::GetFont(fontOsd);
786  lineHeight = font->Height();
788  frameColor = Theme.Color(clrMenuFrameBg);
789  currentIndex = -1;
790  // The outer frame:
791  int d = 5 * lineHeight;
792  xa00 = 0;
793  xa01 = xa00 + d / 2;
794  xa02 = xa00 + d;
795  xa03 = xa02 + lineHeight;
796  xa04 = xa02 + d / 4;
797  xa05 = xa02 + d;
798  xa06 = xa05 + Gap;
799  xa09 = cOsd::OsdWidth();
800  xa08 = xa09 - lineHeight;
801  xa07 = xa08 - Gap;
802 
803  yt00 = 0;
804  yt01 = yt00 + lineHeight;
805  yt02 = yt01 + lineHeight;
806  yt03 = yt01 + d / 4;
807  yt04 = yt02 + Gap;
808  yt05 = yt00 + d / 2;
809  yt06 = yt04 + 2 * lineHeight;
810 
811  yc00 = yt06 + Gap;
812  yc05 = yc00 + 3 * lineHeight + Gap / 2;
813  yc04 = yc05 - lineHeight;
814  yc03 = yc04 - lineHeight;
815  yc02 = yc04 - d / 4;
816  yc01 = yc05 - d / 2;
817 
818  yc06 = yc05 + Gap;
819  yc07 = yc06 + lineHeight;
820  yc08 = yc07 + lineHeight;
821  yc09 = yc07 + d / 4;
822  yc10 = yc06 + d / 2;
823  yc11 = yc06 + 3 * lineHeight + Gap / 2;
824 
825  yb00 = yc11 + Gap;
826  yb01 = yb00 + 2 * lineHeight;
827  yb02 = yb01 + Gap;
828  yb03 = yb02 + 2 * lineHeight;
829  yb04 = yb03 + Gap;
830  yb05 = yb04 + 2 * lineHeight;
831  yb06 = yb05 + Gap;
832  yb07 = yb06 + 2 * lineHeight;
833  yb08 = yb07 + Gap;
834 
835  yb15 = cOsd::OsdHeight();
836  yb14 = yb15 - lineHeight;
837  yb13 = yb14 - lineHeight;
838  yb12 = yb14 - d / 4;
839  yb11 = yb15 - d / 2;
840  yb10 = yb13 - Gap - 2 * lineHeight;
841  yb09 = yb10 - Gap;
842 
843  // Compensate for large font size:
844  if (yb09 - yb08 < 2 * lineHeight) {
845  yb08 = yb06;
846  yb06 = 0; // drop empty rectangle
847  }
848  if (yb09 - yb08 < 2 * lineHeight) {
849  yb05 = yb09;
850  yb08 = 0; // drop "LCARS" display
851  }
852  if (yb05 - yb04 < 2 * lineHeight) {
853  yb03 = yb09;
854  yb04 = 0; // drop "LOAD" display
855  }
856  if (yb03 - yb02 < 2 * lineHeight) {
857  yb01 = yb09;
858  yb02 = 0; // drop "DISK" display
859  }
860  // Anything else is just insanely large...
861 
862  // The main command menu:
863  xm00 = xa03;
864  xm01 = xa05;
865  xm02 = xa06;
866  xm08 = (xa09 + xa00) / 2;
867  xm07 = xm08 - lineHeight;
868  xm06 = xm07 - lineHeight / 2;
869  xm05 = xm06 - lineHeight / 2;
870  xm04 = xm05 - lineHeight;
871  xm03 = xm04 - Gap;
872  ym00 = yc08;
873  ym01 = ym00 + lineHeight / 2;
874  ym02 = ym01 + lineHeight / 2;
875  ym03 = ym02 + Gap;
876  ym07 = yb15;
877  ym06 = ym07 - lineHeight / 2;
878  ym05 = ym06 - lineHeight / 2;
879  ym04 = ym05 - Gap;
880 
881  // The status area:
882  xs00 = xm08 + Gap + lineHeight + Gap;
883  xs13 = xa09;
884  xs12 = xa08;
885  xs11 = xa07;
886  xs05 = (xs00 + xs11 + Gap) / 2;
887  xs04 = xs05 - lineHeight / 2;
888  xs03 = xs04 - lineHeight / 2;
889  xs02 = xs03 - 2 * lineHeight;
890  xs01 = xs02 - Gap;
891  xs06 = xs05 + Gap;
892  xs07 = xs06 + lineHeight / 2;
893  xs08 = xs07 + lineHeight / 2;
894  xs09 = xs08 + 2 * lineHeight;
895  xs10 = xs09 + Gap;
896  ys00 = yc06;
897  ys01 = ys00 + lineHeight;
898  ys02 = ys01 + lineHeight / 2;
899  ys04 = ys01 + lineHeight;
900  ys03 = ys04 - Gap;
901  ys05 = yb15;
902 
903  // The item area (just to have them initialized, actual setting will be done in SetMenuCategory():
904 
905  xi00 = 0;
906  xi01 = 0;
907  xi02 = 0;
908  xi03 = 1;
909  yi00 = 0;
910  yi01 = 1;
911 
912  // The color buttons in submenus:
913  xb00 = xa06;
914  xb15 = xa07;
915  int w = (xa08 - xa06) / 4;
916  xb01 = xb00 + lineHeight / 2;
917  xb02 = xb01 + Gap;
918  xb04 = xb00 + w;
919  xb03 = xb04 - Gap;
920  xb05 = xb04 + lineHeight / 2;
921  xb06 = xb05 + Gap;
922  xb08 = xb04 + w;
923  xb07 = xb08 - Gap;
924  xb09 = xb08 + lineHeight / 2;
925  xb10 = xb09 + Gap;
926  xb12 = xb08 + w;
927  xb11 = xb12 - Gap;
928  xb13 = xb12 + lineHeight / 2;
929  xb14 = xb13 + Gap;
930 
931  // The color buttons in the main menu:
932  int r = lineHeight;
933  xd07 = xa09;
934  xd06 = xd07 - r;
935  xd05 = xd06 - 4 * r;
936  xd04 = xd05 - r;
937  xd03 = xd04 - Gap;
938  xd02 = xd03 - r;
939  xd01 = xd02 - 4 * r;
940  xd00 = xd01 - r;
941  yd00 = yt00;
942  yd05 = yc04 - Gap;
943  yd04 = yd05 - 2 * r;
944  yd03 = yd04 - Gap;
945  yd02 = yd03 - 2 * r;
946  yd01 = yd02 - Gap;
947 
948  xs = 0;
949 
951 }
952 
954 {
955  delete tallFont;
956  delete tinyFont;
957  delete osd;
958 }
959 
961 {
964  initial = true;
966  if (MenuCategory == mcMain) {
967  yi00 = ym03;
968  yi01 = ym04;
969  xi00 = xm00;
970  xi01 = xm03;
971  xi02 = xm04;
972  xi03 = xm05;
975  DrawMainBracket();
977  }
978  else {
979  yi00 = yt02;
980  yi01 = yb13;
981  xi00 = xa03;
982  xi01 = xa07;
983  xi02 = xa08;
984  xi03 = xa09;
985  DrawMenuFrame();
986  }
987  }
988 }
989 
991 {
992  // Top left rectangles:
993  osd->DrawRectangle(xa00, yt00, xa02 - 1, yt02 - 1, Color);
994  osd->DrawRectangle(xa00, yt04, xa02 - 1, yt06 - 1, Color);
995  // Upper elbow:
996  osd->DrawRectangle(xa00, yc00, xa01 - 1, yc01 - 1, Color);
997  osd->DrawEllipse (xa00, yc01, xa01 - 1, yc05 - 1, Color, 3);
998  osd->DrawRectangle(xa01, yc00, xa02 - 1, yc05 - 1, Color);
999  osd->DrawEllipse (xa02, yc02, xa04 - 1, yc04 - 1, Color, -3);
1000  osd->DrawRectangle(xa02, yc04, xa05 - 1, yc05 - 1, Color);
1001  // Upper delimiter:
1002  osd->DrawRectangle(xa06, yc04 + lineHeight / 2, xm08 - 1, yc05 - 1, Color);
1003  osd->DrawRectangle(xm08 + Gap, yc04, xs00 - Gap - 1, yc05 - 1, Color);
1004  osd->DrawRectangle(xs00, yc04, xs05 - 1, yc05 - 1, Color);
1005  osd->DrawRectangle(xs06, yc04, xa07 - 1, yc05 - 1, Color);
1006  osd->DrawRectangle(xa08, yc04, xa09 - 1, yc05 - 1, Color);
1007 }
1008 
1010 {
1011  const cFont *font = cFont::GetFont(fontOsd);
1012  // Lower elbow:
1013  osd->DrawRectangle(xa00, yc10, xa01 - 1, yc11 - 1, frameColor);
1014  osd->DrawEllipse (xa00, yc06, xa01 - 1, yc10 - 1, frameColor, 2);
1015  osd->DrawRectangle(xa01, yc06, xa02 - 1, yc11 - 1, frameColor);
1016  osd->DrawEllipse (xa02, yc07, xa04 - 1, yc09 - 1, frameColor, -2);
1017  osd->DrawRectangle(xa02, yc06, xa05 - 1, yc07 - 1, frameColor);
1018  // Lower delimiter:
1019  osd->DrawRectangle(xa06, yc06, xm08 - 1, yc07 - lineHeight / 2 - 1, frameColor);
1020  osd->DrawRectangle(xm08 + Gap, yc06, xs00 - Gap - 1, yc07 - 1, frameColor);
1021  osd->DrawRectangle(xa08, yc06, xa09 - 1, yc07 - 1, frameColor);
1022  // VDR version:
1023  osd->DrawRectangle(xa00, yb10, xa02 - 1, yb15 - 1, frameColor);
1024  osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
1026 }
1027 
1028 void cSkinLCARSDisplayMenu::DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font)
1029 {
1030  int h = y1 - y0;
1031  osd->DrawEllipse(x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
1032  osd->DrawText(x1, y0, Text, ColorFg, ColorBg, Font, x2 - x1, h, taBottom | taRight);
1033  osd->DrawEllipse(x2, y0, x3 - 1, y1 - 1, ColorBg, 5);
1034 }
1035 
1037 {
1038  // Upper elbow:
1039  osd->DrawRectangle(xa00, yt05, xa01 - 1, yt06 - 1, frameColor);
1041  osd->DrawEllipse (xa00, yt00, xa01 - 1, yt05 - 1, frameColor, 2);
1042  osd->DrawRectangle(xa01, yt00, xa02 - 1, yt06 - 1, frameColor);
1043  osd->DrawEllipse (xa02, yt01, xa04 - 1, yt03 - 1, frameColor, -2);
1044  osd->DrawRectangle(xa02, yt00, xa05 - 1, yt01 - 1, frameColor);
1045  osd->DrawRectangle(xa06, yt00, xa07 - 1, yt01 - 1, frameColor);
1046  osd->DrawRectangle(xa08, yt00, xa08 + lineHeight / 2 - 1, yt01 - 1, frameColor);
1048  osd->DrawEllipse (xa08 + lineHeight / 2, yt00, xa09 - 1, yt01 - 1, frameColor, 5);
1049  // Center part:
1050  osd->DrawRectangle(xa00, yc00, xa02 - 1, yc11 - 1, frameColor);
1051  // Lower elbow:
1052  osd->DrawRectangle(xa00, yb10, xa02 - 1, yb11 - 1, frameColor);
1054  osd->DrawEllipse (xa00, yb11, xa01 - 1, yb15 - 1, frameColor, 3);
1055  osd->DrawRectangle(xa01, yb11, xa02 - 1, yb15 - 1, frameColor);
1056  osd->DrawEllipse (xa02, yb12, xa04 - 1, yb14 - 1, frameColor, -3);
1057  osd->DrawRectangle(xa02, yb14, xa05 - 1, yb15 - 1, frameColor);
1058  osd->DrawRectangle(xa08, yb14, xa08 + lineHeight / 2 - 1, yb15 - 1, frameColor);
1060  osd->DrawEllipse (xa08 + lineHeight / 2, yb14, xa09 - 1, yb15 - 1, frameColor, 5);
1061  osd->DrawText(xa00, yb10, "VDR", Theme.Color(clrMenuFrameFg), frameColor, tallFont, xa02 - xa00, yb11 - yb10, taTop | taRight | taBorder);
1062  // Color buttons:
1063  tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
1064  osd->DrawRectangle(xb00, yb14, xb01 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey0]));
1065  osd->DrawRectangle(xb04, yb14, xb05 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey1]));
1066  osd->DrawRectangle(xb08, yb14, xb09 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey2]));
1067  osd->DrawRectangle(xb12, yb14, xb13 - 1, yb15 - 1, Theme.Color(lutBg[Setup.ColorKey3]));
1068 }
1069 
1071 {
1072  cString s = DayDateTime();
1073  if (initial || !*lastDate || strcmp(s, lastDate)) {
1074  const cFont *font = cFont::GetFont(fontOsd);
1075  tColor ColorFg = Theme.Color(clrDateFg);
1076  tColor ColorBg = Theme.Color(clrDateBg);
1077  lastDate = s;
1078  const char *t = strrchr(s, ' ');
1079  osd->DrawText(xa00, yb01 - lineHeight, t, ColorFg, ColorBg, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1080  s.Truncate(t - s);
1081  osd->DrawText(xa00, yb00, s, ColorFg, ColorBg, font, xa02 - xa00, yb01 - yb00 - lineHeight, taTop | taRight | taBorder);
1082  }
1083 }
1084 
1086 {
1087  if (yb02) {
1088  if (cVideoDiskUsage::HasChanged(lastDiskUsageState) || initial) { // must call HasChanged() first, or it shows an outdated value in the 'initial' case!
1089  const cFont *font = cFont::GetFont(fontOsd);
1090  int DiskUsage = cVideoDiskUsage::UsedPercent();
1091  bool DiskAlert = DiskUsage > DISKUSAGEALERTLIMIT;
1092  tColor ColorFg = DiskAlert ? Theme.Color(clrAlertFg) : Theme.Color(clrMenuFrameFg);
1093  tColor ColorBg = DiskAlert ? Theme.Color(clrAlertBg) : frameColor;
1094  if (initial || DiskAlert != lastDiskAlert)
1095  osd->DrawText(xa00, yb02, tr("DISK"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb03 - yb02, taTop | taLeft | taBorder);
1096  osd->DrawText(xa01, yb02, itoa(DiskUsage), ColorFg, ColorBg, font, xa02 - xa01, lineHeight, taBottom | taRight | taBorder);
1097  osd->DrawText(xa00, yb03 - lineHeight, cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60), ColorFg, ColorBg, font, xa02 - xa00, 0, taBottom | taRight | taBorder);
1098  lastDiskAlert = DiskAlert;
1099  }
1100  }
1101 }
1102 
1104 {
1105  if (yb04) {
1106  tColor ColorFg = Theme.Color(clrMenuFrameFg);
1107  tColor ColorBg = frameColor;
1108  if (initial)
1109  osd->DrawText(xa00, yb04, tr("LOAD"), ColorFg, ColorBg, tinyFont, xa02 - xa00, yb05 - yb04, taTop | taLeft | taBorder);
1110  double SystemLoad;
1111  if (getloadavg(&SystemLoad, 1) > 0) {
1112  if (initial || SystemLoad != lastSystemLoad) {
1113  osd->DrawText(xa00, yb05 - lineHeight, cString::sprintf("%.1f", SystemLoad), ColorFg, ColorBg, cFont::GetFont(fontOsd), xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1114  lastSystemLoad = SystemLoad;
1115  }
1116  }
1117  }
1118 }
1119 
1121 {
1122  tColor Color = Theme.Color(clrMenuMainBracket);
1123  osd->DrawRectangle(xm00, ym00, xm01 - 1, ym01 - 1, Color);
1124  osd->DrawRectangle(xm02, ym00, xm07 - 1, ym01 - 1, Color);
1125  osd->DrawEllipse (xm07, ym00, xm08 - 1, ym02 - 1, Color, 1);
1126  osd->DrawEllipse (xm06, ym01, xm07 - 1, ym02 - 1, Color, -1);
1127  osd->DrawRectangle(xm07, ym03, xm08 - 1, ym04 - 1, Color);
1128  osd->DrawEllipse (xm06, ym05, xm07 - 1, ym06 - 1, Color, -4);
1129  osd->DrawEllipse (xm07, ym05, xm08 - 1, ym07 - 1, Color, 4);
1130  osd->DrawRectangle(xm02, ym06, xm07 - 1, ym07 - 1, Color);
1131  osd->DrawRectangle(xm00, ym06, xm01 - 1, ym07 - 1, Color);
1132 }
1133 
1135 {
1136  const cFont *font = cFont::GetFont(fontOsd);
1137  osd->DrawText (xs00, ys00, tr("TIMERS"), Theme.Color(clrMenuFrameFg), frameColor, font, xs01 - xs00, lineHeight, taBottom | taLeft | taBorder);
1138  osd->DrawRectangle(xs02, ys00, xs03 - 1, ys01 - 1, frameColor);
1139  osd->DrawEllipse (xs03, ys00, xs05 - 1, ys01 - 1, frameColor, 1);
1140  osd->DrawEllipse (xs03, ys01, xs04 - 1, ys02 - 1, frameColor, -1);
1141  osd->DrawRectangle(xs04, ys01, xs05 - 1, ys03 - 1, frameColor);
1142  osd->DrawRectangle(xs04, ys04, xs05 - 1, ys05 - 1, frameColor);
1143  osd->DrawText (xs10, ys00, tr("DEVICES"), Theme.Color(clrMenuFrameFg), frameColor, font, xs11 - xs10, lineHeight, taBottom | taRight | taBorder);
1144  osd->DrawRectangle(xs08, ys00, xs09 - 1, ys01 - 1, frameColor);
1145  osd->DrawEllipse (xs06, ys00, xs08 - 1, ys01 - 1, frameColor, 2);
1146  osd->DrawEllipse (xs07, ys01, xs08 - 1, ys02 - 1, frameColor, -2);
1147  osd->DrawRectangle(xs06, ys01, xs07 - 1, ys03 - 1, frameColor);
1148  osd->DrawRectangle(xs06, ys04, xs07 - 1, ys05 - 1, frameColor);
1149  osd->DrawRectangle(xs12, ys00, xs13 - 1, ys01 - 1, frameColor);
1150 }
1151 
1153 {
1154  DrawDate();
1155  DrawDisk();
1156  DrawLoad();
1157  if (initial) {
1158  if (yb06)
1159  osd->DrawRectangle(xa00, yb06, xa02 - 1, yb07 - 1, frameColor);
1160  if (yb08) {
1161  const cFont *font = cFont::GetFont(fontOsd);
1162  osd->DrawRectangle(xa00, yb08, xa02 - 1, yb09 - 1, frameColor);
1163  osd->DrawText(xa00, yb09 - lineHeight, "LCARS", Theme.Color(clrMenuFrameFg), frameColor, font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1164  }
1165  }
1166 }
1167 
1168 void cSkinLCARSDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, bool CanScrollUp, bool CanScrollDown)
1169 {
1170  int x0, x1, tt, tb;
1171  tColor ClearColor;
1172  if (MenuCategory() == mcMain) {
1173  x0 = xm07;
1174  x1 = xm08;
1175  tt = ym03;
1176  tb = ym04;
1177  ClearColor = Theme.Color(clrMenuMainBracket);
1178  }
1179  else {
1180  x0 = xa02 + Gap;
1181  x1 = x0 + lineHeight / 2;
1182  tt = yc00;
1183  tb = yc11;
1184  ClearColor = Theme.Color(clrBackground);
1185  int d = TextFrame;
1186  if (CanScrollUp)
1187  osd->DrawBitmap(xa02 - bmArrowUp.Width() - d, yc00 + d, bmArrowUp, Theme.Color(clrMenuScrollbarArrow), frameColor);
1188  else
1189  osd->DrawRectangle(xa02 - bmArrowUp.Width() - d, yc00 + d, xa02 - d - 1, yc00 + d + bmArrowUp.Height() - 1, frameColor);
1190  if (CanScrollDown)
1191  osd->DrawBitmap(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), bmArrowDown, Theme.Color(clrMenuScrollbarArrow), frameColor);
1192  else
1193  osd->DrawRectangle(xa02 - bmArrowDown.Width() - d, yc11 - d - bmArrowDown.Height(), xa02 - d - 1, yc11 - d - 1, frameColor);
1194  }
1195  if (Total > 0 && Total > Shown) {
1196  int sw = x1 - x0;
1197  int sh = max(int((tb - tt) * double(Shown) / Total + 0.5), sw);
1198  int st = min(int(tt + (tb - tt) * double(Offset) / Total + 0.5), tb - sh);
1199  int sb = min(st + sh, tb);
1200  osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, Theme.Color(clrMenuScrollbarTotal));
1201  osd->DrawRectangle(x0, st, x1 - 1, sb - 1, Theme.Color(clrMenuScrollbarShown));
1202  }
1203  else if (MenuCategory() != mcMain)
1204  osd->DrawRectangle(x0, tt, x1 - 1, tb - 1, ClearColor);
1205 }
1206 
1207 void cSkinLCARSDisplayMenu::DrawTimer(const cTimer *Timer, int y, bool MultiRec)
1208 {
1209  // The timer data:
1210  bool Alert = !Timer->Recording() && Timer->Pending();
1211  tColor ColorFg = Alert ? Theme.Color(clrAlertFg) : Theme.Color(clrTimerFg);
1212  tColor ColorBg = Alert ? Theme.Color(clrAlertBg) : Theme.Color(clrTimerBg);
1213  osd->DrawRectangle(xs00, y, xs03 - 1, y + lineHeight - 1, ColorBg);
1214  cString Date;
1215  if (Timer->Recording())
1216  Date = cString::sprintf("-%s", *TimeString(Timer->StopTime()));
1217  else {
1218  time_t Now = time(NULL);
1219  cString Today = WeekDayName(Now);
1220  cString Time = TimeString(Timer->StartTime());
1221  cString Day = WeekDayName(Timer->StartTime());
1222  if (Timer->StartTime() > Now + 6 * SECSINDAY)
1223  Date = DayDateTime(Timer->StartTime());
1224  else if (strcmp(Day, Today) != 0)
1225  Date = cString::sprintf("%s %s", *Day, *Time);
1226  else
1227  Date = Time;
1228  }
1229  if (Timer->Flags() & tfVps)
1230  Date = cString::sprintf("VPS %s", *Date);
1231  const cChannel *Channel = Timer->Channel();
1232  const cEvent *Event = Timer->Event();
1233  int d = max(TextFrame / 2, 1);
1234  if (Channel) {
1235  osd->DrawText(xs00 + d, y, Channel->Name(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - d);
1236  osd->DrawText(xs03 - tinyFont->Width(Date) - d, y, Date, ColorFg, ColorBg, tinyFont);
1237  }
1238  if (Event)
1239  osd->DrawText(xs00 + d, y + lineHeight - tinyFont->Height(), Event->Title(), ColorFg, ColorBg, tinyFont, xs03 - xs00 - 2 * d);
1240  // The remote timer indicator:
1241  if (Timer->Remote())
1242  osd->DrawRectangle(xs00 - (lineHeight - Gap) / 2, y, xs00 - Gap - 1, y + lineHeight - 1, Timer->Recording() ? Theme.Color(clrMenuTimerRecording) : ColorBg);
1243  // The timer recording indicator:
1244  else if (Timer->Recording())
1245  osd->DrawRectangle(xs03 + Gap, y - (MultiRec ? Gap : 0), xs04 - Gap / 2 - 1, y + lineHeight - 1, Theme.Color(clrMenuTimerRecording));
1246 }
1247 
1249 {
1250  if (const cTimers *Timers = cTimers::GetTimersRead(timersStateKey)) {
1252  const cFont *font = cFont::GetFont(fontOsd);
1255  cSortedTimers SortedTimers(Timers);
1256  cVector<int> FreeDeviceSlots;
1257  int NumDevices = 0;
1258  int y = ys04;
1259  // Timers and recording devices:
1260  while (1) {
1261  int NumTimers = 0;
1262  const cDevice *Device = NULL;
1263  for (int i = 0; i < SortedTimers.Size(); i++) {
1264  if (y + lineHeight > ys05)
1265  break;
1266  if (const cTimer *Timer = SortedTimers[i]) {
1267  if (Timer->Recording()) {
1268  if (Timer->Remote()) {
1269  if (!Device && Timer->HasFlags(tfActive)) {
1270  DrawTimer(Timer, y, false);
1271  FreeDeviceSlots.Append(y);
1272  y += lineHeight + Gap;
1273  }
1274  else
1275  continue;
1276  }
1277  else if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(Timer)) {
1278  if (!Device || Device == RecordControl->Device()) {
1279  DrawTimer(Timer, y, NumTimers > 0);
1280  NumTimers++;
1281  if (!Device) {
1282  Device = RecordControl->Device();
1283  deviceOffset[Device->DeviceNumber()] = y;
1284  deviceRecording[Device->DeviceNumber()] = true;
1285  NumDevices++;
1286  }
1287  else
1288  FreeDeviceSlots.Append(y);
1289  y += lineHeight + Gap;
1290  }
1291  else
1292  continue;
1293  }
1294  SortedTimers[i] = NULL;
1295  }
1296  else if (!Device && Timer->HasFlags(tfActive)) {
1297  DrawTimer(Timer, y, false);
1298  FreeDeviceSlots.Append(y);
1299  y += lineHeight + Gap;
1300  SortedTimers[i] = NULL;
1301  }
1302  }
1303  }
1304  if (!Device)
1305  break;
1306  }
1307  // Devices currently not recording:
1308  int Slot = 0;
1309  for (int i = 0; i < cDevice::NumDevices(); i++) {
1310  if (const cDevice *Device = cDevice::GetDevice(i)) {
1311  if (Device->NumProvidedSystems()) {
1312  if (!deviceRecording[Device->DeviceNumber()]) {
1313  if (Slot < FreeDeviceSlots.Size()) {
1314  y = FreeDeviceSlots[Slot];
1315  Slot++;
1316  }
1317  if (y + lineHeight > ys05)
1318  break;
1319  deviceOffset[Device->DeviceNumber()] = y;
1320  y += lineHeight + Gap;
1321  NumDevices++;
1322  }
1323  }
1324  }
1325  }
1326  // Total number of active timers:
1327  int NumTimers = 0;
1328  for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
1329  if (Timer->HasFlags(tfActive))
1330  NumTimers++;
1331  }
1332  osd->DrawText(xs02, ys00, itoa(NumTimers), Theme.Color(clrMenuFrameFg), frameColor, font, xs03 - xs02, ys01 - ys00, taBottom | taLeft | taBorder);
1333  osd->DrawText(xs08, ys00, itoa(NumDevices), Theme.Color(clrMenuFrameFg), frameColor, font, xs09 - xs08, ys01 - ys00, taBottom | taRight | taBorder);
1334  lastSignalDisplay = 0;
1335  initial = true; // forces redrawing of devices
1337  }
1338 }
1339 
1341 {
1342  int dn = Device->DeviceNumber();
1343  int y = deviceOffset[dn];
1344  if (y + lineHeight <= ys05) {
1345  if (DrawDeviceData(osd, Device, xs08, y, xs11, y + lineHeight, xs, tinyFont, lastDeviceType[dn], lastCamSlot[dn], initial)) {
1346  // Make sure signal meters are redrawn:
1347  lastSignalStrength[dn] = -1;
1348  lastSignalQuality[dn] = -1;
1349  lastSignalDisplay = 0;
1350  }
1351  // The device recording indicator:
1352  if (deviceRecording[dn])
1353  osd->DrawRectangle(xs07 + Gap / 2, y, xs08 - Gap - 1, y + lineHeight - 1, Theme.Color(clrMenuDeviceRecording));
1354  }
1355 }
1356 
1358 {
1359  for (int i = 0; i < cDevice::NumDevices(); i++) {
1360  if (const cDevice *Device = cDevice::GetDevice(i)) {
1361  if (Device->NumProvidedSystems())
1362  DrawDevice(Device);
1363  }
1364  }
1365 }
1366 
1368 {
1369  cDevice *Device = cDevice::PrimaryDevice();
1370  int y = -1;
1371  bool Transferring = Device->Transferring();
1372  if (!Device->Replaying() || Transferring)
1374  if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) {
1375  if (lastLiveIndicatorY >= 0)
1377  if (y > 0) {
1378  tColor ColorBg = Theme.Color(clrChannelFrameBg);
1379  osd->DrawRectangle(xs12, y, xs12 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
1380  osd->DrawEllipse (xs12 + lineHeight / 2, y, xs13 - 1, y + lineHeight - 1, ColorBg, 5);
1381  if (Transferring) {
1382  int w = bmTransferMode.Width();
1383  int h = bmTransferMode.Height();
1384  int b = w * w + h * h; // the diagonal of the bitmap (squared)
1385  int c = lineHeight * lineHeight; // the diameter of the circle (squared)
1386  const cBitmap *bm = &bmTransferMode;
1387  if (b > c) {
1388  // the bitmap doesn't fit, so scale it down:
1389  double f = sqrt(double(c) / (2 * b));
1390  bm = bmTransferMode.Scaled(f, f);
1391  }
1392  osd->DrawBitmap((xs12 + xs13 - bm->Width()) / 2, y + (lineHeight - bm->Height()) / 2, *bm, Theme.Color(clrChannelFrameFg), ColorBg);
1393  if (bm != &bmTransferMode)
1394  delete bm;
1395  }
1396  }
1397  lastLiveIndicatorY = y;
1398  lastLiveIndicatorTransferring = Transferring;
1399  }
1400 }
1401 
1403 {
1404  time_t Now = time(NULL);
1405  if (initial || Now - lastSignalDisplay >= SIGNALDISPLAYDELTA) {
1406  for (int i = 0; i < cDevice::NumDevices(); i++) {
1407  if (const cDevice *Device = cDevice::GetDevice(i)) {
1408  if (Device->NumProvidedSystems()) {
1409  if (int y = deviceOffset[i])
1411  }
1412  }
1413  }
1414  lastSignalDisplay = Now;
1415  }
1416 }
1417 
1419 {
1420  if (lastMode != cmLive) {
1421  initial = true;
1422  lastMode = cmLive;
1423  }
1424  if (initial) {
1425  DrawMainFrameUpper(Theme.Color(clrChannelFrameBg));
1426  osd->DrawText(xd00, yd00, tr("LIVE"), Theme.Color(clrChannelFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
1427  }
1428  if (!Channel)
1429  return;
1430  if (initial || Channel != lastChannel || strcmp(Channel->Name(), lastChannelName)) {
1431  osd->DrawText(xa00, yt00, itoa(Channel->Number()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), tallFont, xa02 - xa00, yt02 - yt00, taTop | taRight | taBorder);
1432  osd->DrawText(xa03, yt00, Channel->Name(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1433  int x = xa00 + (yc03 - yc02); // compensate for the arc
1434  osd->DrawText(x, yc00, cSource::ToString(Channel->Source()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), cFont::GetFont(fontOsd), xa02 - x, yc03 - yc00, taTop | taRight | taBorder);
1435  lastChannel = Channel;
1436  lastChannelName = Channel->Name();
1437  DrawSeen(0, 0);
1438  }
1439  // The current programme:
1441  if (const cSchedule *Schedule = Schedules->GetSchedule(Channel)) {
1442  const cEvent *Event = Schedule->GetPresentEvent();
1443  if (initial || Event != lastEvent) {
1444  DrawInfo(Event, true);
1445  lastEvent = Event;
1446  lastSeen = -1;
1447  }
1448  int Current = 0;
1449  int Total = 0;
1450  if (Event) {
1451  time_t t = time(NULL);
1452  if (t > Event->StartTime())
1453  Current = t - Event->StartTime();
1454  Total = Event->Duration();
1455  }
1456  DrawSeen(Current, Total);
1457  }
1458 }
1459 
1461 {
1462  if (lastMode != cmPlay) {
1463  initial = true;
1464  lastMode = cmPlay;
1465  }
1466  if (initial) {
1467  DrawMainFrameUpper(Theme.Color(clrReplayFrameBg));
1468  osd->DrawText(xd00, yd00, tr("PLAY"), Theme.Color(clrReplayFrameBg), Theme.Color(clrBackground), tallFont, xd07 - xd00, yd01 - yd00, taTop | taRight | taBorder);
1469  }
1470  // The current progress:
1471  int Current = 0;
1472  int Total = 0;
1473  if (Control->GetIndex(Current, Total))
1474  DrawSeen(Current, Total);
1475  // The current programme:
1476  if (const cRecording *Recording = Control->GetRecording()) {
1477  if (initial || Recording != lastRecording) {
1478  const cFont *font = cFont::GetFont(fontOsd);
1479  if (const cRecordingInfo *Info = Recording->Info()) {
1480  osd->DrawText(xa03, yt00, Info->ChannelName(), Theme.Color(clrChannelName), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1481  DrawInfo(Info->GetEvent(), false);
1482  }
1483  else
1484  osd->DrawText(xa03, yt04, Recording->Name(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03, 0, taTop | taLeft);
1485  osd->DrawText(xa00, yt04, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taTop | taRight | taBorder);
1486  osd->DrawText(xa00, yt06 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), Theme.Color(clrReplayFrameBg), font, xa02 - xa00, 0, taBottom | taRight | taBorder);
1487  lastRecording = Recording;
1488  }
1489  }
1490  else {
1491  cString Header = Control->GetHeader();
1492  if (!*lastHeader || strcmp(Header, lastHeader)) {
1493  osd->DrawText(xa03, yt00, Header, Theme.Color(clrMenuText), Theme.Color(clrBackground), tallFont, xd00 - xa03, yd01 - yd00, taTop | taLeft);
1494  lastHeader = Header;
1495  }
1496  }
1497 }
1498 
1499 void cSkinLCARSDisplayMenu::DrawInfo(const cEvent *Event, bool WithTime)
1500 {
1501  if (Event) {
1502  const cFont *font = cFont::GetFont(fontOsd);
1503  int y = yt04;
1504  osd->DrawText(xa03, y, Event->Title(), Theme.Color(clrEventTitle), Theme.Color(clrBackground), font, xd00 - xa03 - lineHeight, lineHeight, taBottom | taLeft);
1505  y += lineHeight;
1506  osd->DrawText(xa03, y, Event->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xd00 - xa03 - lineHeight, lineHeight, taTop | taLeft);
1507  if (WithTime) {
1508  osd->DrawText(xa00, yt04, Event->GetTimeString(), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taTop | taRight | taBorder);
1509  osd->DrawText(xa00, yt06 - lineHeight, cString::sprintf("-%s", *Event->GetEndTimeString()), Theme.Color(clrChannelFrameFg), Theme.Color(clrChannelFrameBg), font, xa02 - xa00, lineHeight, taBottom | taRight | taBorder);
1510  }
1511  }
1512 }
1513 
1514 void cSkinLCARSDisplayMenu::DrawSeen(int Current, int Total)
1515 {
1516  int Seen = (Total > 0) ? min(xm08 - xm02, int((xm08 - xm02) * double(Current) / Total)) : 0;
1517  if (initial || Seen != lastSeen) {
1518  int y0 = yc04 - ShowSeenExtent;
1519  int y1 = yc04 + lineHeight / 2 - Gap / 2;
1520  osd->DrawRectangle(xm02, y0, xm02 + Seen - 1, y1 - 1, Theme.Color(clrSeen));
1521  osd->DrawRectangle(xm02 + Seen, y0, xm08 - 1, y1 - 1, Theme.Color(clrBackground));
1522  lastSeen = Seen;
1523  }
1524 }
1525 
1527 {
1528  if (textScroller.CanScroll())
1530 }
1531 
1532 void cSkinLCARSDisplayMenu::Scroll(bool Up, bool Page)
1533 {
1534  cSkinDisplayMenu::Scroll(Up, Page);
1536 }
1537 
1539 {
1540  if (MenuCategory() == mcMain)
1541  return (ym04 - ym03) / lineHeight;
1542  else
1543  return (yb13 - yt02) / lineHeight;
1544 }
1545 
1547 {
1548  textScroller.Reset();
1550 }
1551 
1552 void cSkinLCARSDisplayMenu::SetTitle(const char *Title)
1553 {
1554  if (MenuCategory() != mcMain) {
1555  const cFont *font = cFont::GetFont(fontOsd);
1556  int w = min(font->Width(Title), xa07 - xa06 - Gap);
1557  osd->DrawRectangle(xa06, yt00, xa07 - w - Gap - 1, yt01 - 1, frameColor);
1558  osd->DrawText(xa07 - w - Gap, yt00, Title, Theme.Color(clrMenuTitle), Theme.Color(clrBackground), font, w + Gap, yt01 - yt00, taRight);
1559  }
1560 }
1561 
1562 void cSkinLCARSDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
1563 {
1564  const char *lutText[] = { Red, Green, Yellow, Blue };
1565  tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg };
1566  tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
1567  const cFont *font = cFont::GetFont(fontSml);
1568  if (MenuCategory() == mcMain) {
1573  }
1574  else {
1575  int h = yb15 - yb14;
1576  osd->DrawText(xb02, yb14, lutText[Setup.ColorKey0], Theme.Color(lutFg[Setup.ColorKey0]), Theme.Color(lutBg[Setup.ColorKey0]), font, xb03 - xb02, h, taLeft | taBorder);
1577  osd->DrawText(xb06, yb14, lutText[Setup.ColorKey1], Theme.Color(lutFg[Setup.ColorKey1]), Theme.Color(lutBg[Setup.ColorKey1]), font, xb07 - xb06, h, taLeft | taBorder);
1578  osd->DrawText(xb10, yb14, lutText[Setup.ColorKey2], Theme.Color(lutFg[Setup.ColorKey2]), Theme.Color(lutBg[Setup.ColorKey2]), font, xb11 - xb10, h, taLeft | taBorder);
1579  osd->DrawText(xb14, yb14, lutText[Setup.ColorKey3], Theme.Color(lutFg[Setup.ColorKey3]), Theme.Color(lutBg[Setup.ColorKey3]), font, xb15 - xb14, h, taLeft | taBorder);
1580  }
1581 }
1582 
1584 {
1585  if (Text) {
1586  osd->SaveRegion(xb00, yb14, xb15 - 1, yb15 - 1);
1587  osd->DrawText(xb00, yb14, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xb15 - xb00, yb15 - yb14, taCenter);
1588  }
1589  else
1590  osd->RestoreRegion();
1591 }
1592 
1593 void cSkinLCARSDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
1594 {
1595  int y = yi00 + Index * lineHeight;
1596  tColor ColorFg, ColorBg;
1597  if (Current) {
1598  if (TwoColors) {
1599  ColorFg = Theme.Color(clrBackground);
1600  ColorBg = Theme.Color(clrMenuFrameBg);
1601  }
1602  else {
1603  ColorFg = Theme.Color(clrMenuItemCurrentFg);
1604  ColorBg = Theme.Color(clrMenuItemCurrentBg);
1605  }
1606  osd->DrawRectangle(xi00, y, xi01 - 1, y + lineHeight - 1, ColorBg);
1607  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
1608  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, y + lineHeight - 1, ColorBg, 5);
1609  currentIndex = Index;
1610  }
1611  else {
1612  ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
1613  ColorBg = Theme.Color(clrBackground);
1614  if (currentIndex == Index)
1616  }
1617  const cFont *font = cFont::GetFont(fontOsd);
1618  for (int i = 0; i < MaxTabs; i++) {
1619  const char *s = GetTabbedText(Text, i);
1620  if (s) {
1621  int xt = xi00 + TextSpacing + Tab(i);
1622  osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xi01 - xt);
1623  }
1624  if (!Tab(i + 1))
1625  break;
1626  }
1628 }
1629 
1630 void cSkinLCARSDisplayMenu::SetScrollbar(int Total, int Offset)
1631 {
1632  DrawScrollbar(Total, Offset, MaxItems(), Offset > 0, Offset + MaxItems() < Total);
1633 }
1634 
1636 {
1637  if (!Event)
1638  return;
1639  const cFont *font = cFont::GetFont(fontOsd);
1640  int xl = xi00;
1641  int y = yi00;
1642  cTextScroller ts;
1643  cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
1644  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
1645  if (Event->Vps() && Event->Vps() != Event->StartTime()) {
1646  cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());
1647  const cFont *font = cFont::GetFont(fontSml);
1648  int w = font->Width(buffer);
1649  osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1650  int yb = y + font->Height();
1651  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1652  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1653  }
1654  y += ts.Height();
1655  if (Event->ParentalRating()) {
1656  cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
1657  const cFont *font = cFont::GetFont(fontSml);
1658  int w = font->Width(buffer);
1659  osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1660  int yb = y + font->Height();
1661  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1662  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1663  }
1664  y += font->Height();
1665  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->Title(), font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
1666  y += ts.Height();
1667  if (!isempty(Event->ShortText())) {
1668  const cFont *font = cFont::GetFont(fontSml);
1669  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Event->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
1670  y += ts.Height();
1671  }
1672  y += font->Height();
1673  if (!isempty(Event->Description())) {
1674  int yt = y;
1675  int yb = yi01;
1676  textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Event->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
1678  }
1679 }
1680 
1682 {
1683  if (!Recording)
1684  return;
1685  const cRecordingInfo *Info = Recording->Info();
1686  const cFont *font = cFont::GetFont(fontOsd);
1687  int xl = xi00;
1688  int y = yi00;
1689  cTextScroller ts;
1690  cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
1691  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
1692  y += ts.Height();
1693  if (Info->GetEvent()->ParentalRating()) {
1694  cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
1695  const cFont *font = cFont::GetFont(fontSml);
1696  int w = font->Width(buffer);
1697  osd->DrawText(xi01 - w, y, buffer, Theme.Color(clrMenuFrameFg), frameColor, font, w);
1698  int yb = y + font->Height();
1699  osd->DrawRectangle(xi02, y, xi02 + lineHeight / 2 - 1, yb - 1, frameColor);
1700  osd->DrawEllipse (xi02 + lineHeight / 2, y, xi03 - 1, yb - 1, frameColor, 5);
1701  }
1702  y += font->Height();
1703  const char *Title = Info->Title();
1704  if (isempty(Title))
1705  Title = Recording->Name();
1706  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Title, font, Theme.Color(clrEventTitle), Theme.Color(clrBackground));
1707  y += ts.Height();
1708  if (!isempty(Info->ShortText())) {
1709  const cFont *font = cFont::GetFont(fontSml);
1710  ts.Set(osd, xl, y, xi01 - xl, yi01 - y, Info->ShortText(), font, Theme.Color(clrEventShortText), Theme.Color(clrBackground));
1711  y += ts.Height();
1712  }
1713  y += font->Height();
1714  if (!isempty(Info->Description())) {
1715  int yt = y;
1716  int yb = yi01;
1717  textScroller.Set(osd, xl, yt, xi01 - xl, yb - yt, Info->Description(), font, Theme.Color(clrEventDescription), Theme.Color(clrBackground));
1719  }
1720 }
1721 
1722 void cSkinLCARSDisplayMenu::SetText(const char *Text, bool FixedFont)
1723 {
1726 }
1727 
1729 {
1730  return xi01 - xi00;
1731 }
1732 
1733 const cFont *cSkinLCARSDisplayMenu::GetTextAreaFont(bool FixedFont) const
1734 {
1735  const cFont *font = cFont::GetFont(FixedFont ? fontFix : fontOsd);
1736  //XXX -> make a way to let the text define which font to use
1737  return font;
1738 }
1739 
1741 {
1742  if (MenuCategory() == mcMain) {
1743  cDevice *Device = cDevice::PrimaryDevice();
1744  if (!Device->Replaying() || Device->Transferring()) {
1746  const cChannel *Channel = Channels->GetByNumber(cDevice::PrimaryDevice()->CurrentChannel());
1747  DrawLive(Channel);
1748  }
1749  else if (cControl *Control = cControl::Control(true))
1750  DrawPlay(Control);
1751  DrawTimers();
1752  DrawDevices();
1754  DrawSignals();
1755  }
1756  DrawFrameDisplay();
1757  osd->Flush();
1758  initial = false;
1759 }
1760 
1761 // --- cSkinLCARSDisplayReplay -----------------------------------------------
1762 
1764 private:
1768  bool modeOnly;
1775  void DrawDate(void);
1776  void DrawTrack(void);
1777 public:
1778  cSkinLCARSDisplayReplay(bool ModeOnly);
1779  virtual ~cSkinLCARSDisplayReplay();
1780  virtual void SetRecording(const cRecording *Recording);
1781  virtual void SetTitle(const char *Title);
1782  virtual void SetMode(bool Play, bool Forward, int Speed);
1783  virtual void SetProgress(int Current, int Total);
1784  virtual void SetCurrent(const char *Current);
1785  virtual void SetTotal(const char *Total);
1786  virtual void SetJump(const char *Jump);
1787  virtual void SetMessage(eMessageType Type, const char *Text);
1788  virtual void Flush(void);
1789  };
1790 
1792 {
1793  const cFont *font = cFont::GetFont(fontOsd);
1794  modeOnly = ModeOnly;
1795  lineHeight = font->Height();
1796  frameColor = Theme.Color(clrReplayFrameBg);
1797  lastCurrentWidth = 0;
1798  lastTotalWidth = 0;
1799  memset(&lastTrackId, 0, sizeof(lastTrackId));
1800  int d = 5 * lineHeight;
1801  xp00 = 0;
1802  xp01 = xp00 + d / 2;
1803  xp02 = xp00 + d;
1804  xp03 = xp02 + lineHeight;
1805  xp04 = xp02 + d / 4;
1806  xp05 = xp02 + d;
1807  xp06 = xp05 + Gap;
1808  xp15 = cOsd::OsdWidth();
1809  xp14 = xp15 - lineHeight;
1810  xp13 = xp14 - Gap;
1811  xp07 = (xp15 + xp00) / 2;
1812  xp08 = xp07 + Gap;
1813  xp09 = xp08 + lineHeight;
1814  xp10 = xp09 + Gap;
1815  xp11 = (xp10 + xp13 + Gap) / 2;
1816  xp12 = xp11 + Gap;
1817 
1818  yp00 = 0;
1819  yp01 = yp00 + 2 * lineHeight;
1820  yp02 = yp01 + Gap;
1821  yp03 = yp02 + 2 * lineHeight;
1822 
1823  yp04 = yp03 + Gap;
1824  yp09 = yp04 + 3 * lineHeight + Gap / 2;
1825  yp08 = yp09 - lineHeight;
1826  yp07 = yp08 - lineHeight;
1827  yp06 = yp08 - d / 4;
1828  yp05 = yp09 - d / 2;
1829 
1832  // Rectangles:
1833  if (!modeOnly)
1834  osd->DrawRectangle(xp00, yp00, xp02 - 1, yp01 - 1, frameColor);
1835  osd->DrawRectangle(xp00, yp02, xp02 - 1, yp03 - 1, frameColor);
1836  if (!modeOnly) {
1837  // Elbow:
1838  osd->DrawRectangle(xp00, yp04, xp01 - 1, yp05 - 1, frameColor);
1840  osd->DrawEllipse (xp00, yp05, xp01 - 1, yp09 - 1, frameColor, 3);
1841  osd->DrawRectangle(xp01, yp04, xp02 - 1, yp09 - 1, frameColor);
1842  osd->DrawEllipse (xp02, yp06, xp04 - 1, yp08 - 1, frameColor, -3);
1843  osd->DrawRectangle(xp02, yp08, xp05 - 1, yp09 - 1, frameColor);
1844  // Status area:
1845  osd->DrawRectangle(xp06, yp08, xp07 - 1, yp09 - 1, frameColor);
1846  osd->DrawRectangle(xp08, yp08, xp09 - 1, yp09 - 1, frameColor);
1847  osd->DrawRectangle(xp10, yp08, xp11 - 1, yp09 - 1, frameColor);
1848  osd->DrawRectangle(xp12, yp08, xp13 - 1, yp09 - 1, Theme.Color(clrDateBg));
1849  osd->DrawRectangle(xp14, yp08, xp14 + lineHeight / 2 - 1, yp09 - 1, frameColor);
1851  osd->DrawEllipse (xp14 + lineHeight / 2, yp08, xp15 - 1, yp09 - 1, frameColor, 5);
1852  }
1853 }
1854 
1856 {
1857  delete osd;
1858 }
1859 
1861 {
1862  cString s = DayDateTime();
1863  if (!*lastDate || strcmp(s, lastDate)) {
1864  osd->DrawText(xp12, yp08, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xp13 - xp12, lineHeight, taRight | taBorder);
1865  lastDate = s;
1866  }
1867 }
1868 
1870 {
1871  cDevice *Device = cDevice::PrimaryDevice();
1872  const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
1873  if (Track ? strcmp(lastTrackId.description, Track->description) : *lastTrackId.description) {
1874  osd->DrawText(xp03, yp04, Track ? Track->description : "", Theme.Color(clrTrackName), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp07 - xp03);
1875  strn0cpy(lastTrackId.description, Track ? Track->description : "", sizeof(lastTrackId.description));
1876  }
1877 }
1878 
1880 {
1881  const cRecordingInfo *RecordingInfo = Recording->Info();
1882  SetTitle(RecordingInfo->Title());
1883  osd->DrawText(xp03, yp01 - lineHeight, RecordingInfo->ShortText(), Theme.Color(clrEventShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml), xp13 - xp03);
1884  osd->DrawText(xp00, yp00, ShortDateString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taTop | taRight | taBorder);
1885  osd->DrawText(xp00, yp01 - lineHeight, TimeString(Recording->Start()), Theme.Color(clrReplayFrameFg), frameColor, cFont::GetFont(fontOsd), xp02 - xp00, 0, taBottom | taRight | taBorder);
1886 }
1887 
1888 void cSkinLCARSDisplayReplay::SetTitle(const char *Title)
1889 {
1890  osd->DrawText(xp03, yp00, Title, Theme.Color(clrEventTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), xp13 - xp03);
1891 }
1892 
1893 static const char *const *ReplaySymbols[2][2][5] = {
1894  { { pause_xpm, srew_xpm, srew1_xpm, srew2_xpm, srew3_xpm },
1895  { pause_xpm, sfwd_xpm, sfwd1_xpm, sfwd2_xpm, sfwd3_xpm }, },
1896  { { play_xpm, frew_xpm, frew1_xpm, frew2_xpm, frew3_xpm },
1897  { play_xpm, ffwd_xpm, ffwd1_xpm, ffwd2_xpm, ffwd3_xpm } }
1898  };
1899 
1900 void cSkinLCARSDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
1901 {
1902  Speed = constrain(Speed, -1, 3);
1903  cBitmap bm(ReplaySymbols[Play][Forward][Speed + 1]);
1904  osd->DrawBitmap(xp01 - bm.Width() / 2, (yp02 + yp03 - bm.Height()) / 2, bm, Theme.Color(clrReplayFrameFg), frameColor);
1905 }
1906 
1907 void cSkinLCARSDisplayReplay::SetProgress(int Current, int Total)
1908 {
1909  cProgressBar pb(xp13 - xp03, lineHeight, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
1910  osd->DrawBitmap(xp03, yp02, pb);
1911 }
1912 
1913 void cSkinLCARSDisplayReplay::SetCurrent(const char *Current)
1914 {
1915  const cFont *font = cFont::GetFont(fontOsd);
1916  int w = font->Width(Current);
1917  osd->DrawText(xp03, yp03 - lineHeight, Current, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastCurrentWidth, w), 0, taLeft);
1918  lastCurrentWidth = w;
1919 }
1920 
1921 void cSkinLCARSDisplayReplay::SetTotal(const char *Total)
1922 {
1923  const cFont *font = cFont::GetFont(fontOsd);
1924  int w = font->Width(Total);
1925  osd->DrawText(xp13 - w, yp03 - lineHeight, Total, Theme.Color(clrReplayPosition), Theme.Color(clrBackground), font, max(lastTotalWidth, w), 0, taRight);
1926  lastTotalWidth = w;
1927 }
1928 
1929 void cSkinLCARSDisplayReplay::SetJump(const char *Jump)
1930 {
1931  osd->DrawText(xp06, yp08, Jump, Theme.Color(clrReplayJumpFg), Jump ? Theme.Color(clrReplayJumpBg) : frameColor, cFont::GetFont(fontOsd), xp07 - xp06, 0, taCenter);
1932 }
1933 
1935 {
1936  if (Text) {
1937  osd->SaveRegion(xp06, yp08, xp13 - 1, yp09 - 1);
1938  osd->DrawText(xp06, yp08, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), cFont::GetFont(fontSml), xp13 - xp06, yp09 - yp08, taCenter);
1939  }
1940  else
1941  osd->RestoreRegion();
1942 }
1943 
1945 {
1946  if (!modeOnly) {
1947  DrawDate();
1948  DrawTrack();
1949  }
1950  osd->Flush();
1951 }
1952 
1953 // --- cSkinLCARSDisplayVolume -----------------------------------------------
1954 
1956 private:
1958  int x0, x1, x2, x3, x4, x5, x6, x7;
1959  int y0, y1;
1961  int mute;
1962 public:
1964  virtual ~cSkinLCARSDisplayVolume();
1965  virtual void SetVolume(int Current, int Total, bool Mute);
1966  virtual void Flush(void);
1967  };
1968 
1970 {
1971  const cFont *font = cFont::GetFont(fontOsd);
1972  int lineHeight = font->Height();
1973  frameColor = Theme.Color(clrVolumeFrame);
1974  mute = -1;
1975  x0 = 0;
1976  x1 = lineHeight / 2;
1977  x2 = lineHeight;
1978  x3 = x2 + Gap;
1979  x7 = cOsd::OsdWidth();
1980  x6 = x7 - lineHeight / 2;
1981  x5 = x6 - lineHeight / 2;
1982  x4 = x5 - Gap;
1983  y0 = 0;
1984  y1 = lineHeight;
1985  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
1986  osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground));
1987  osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
1988  osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
1989  osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
1990  osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
1991  osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, frameColor);
1992  osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
1993  osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, frameColor, 5);
1994 }
1995 
1997 {
1998  delete osd;
1999 }
2000 
2001 void cSkinLCARSDisplayVolume::SetVolume(int Current, int Total, bool Mute)
2002 {
2003  int xl = x3 + TextSpacing;
2004  int xr = x4 - TextSpacing;
2005  int yt = y0 + TextFrame;
2006  int yb = y1 - TextFrame;
2007  if (mute != Mute) {
2008  osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
2009  mute = Mute;
2010  }
2011  cBitmap bm(Mute ? mute_xpm : volume_xpm);
2012  osd->DrawBitmap(xl, y0 + (y1 - y0 - bm.Height()) / 2, bm, Theme.Color(clrVolumeSymbol), frameColor);
2013  if (!Mute) {
2014  xl += bm.Width() + TextSpacing;
2015  int w = (y1 - y0) / 3;
2016  int d = TextFrame;
2017  int n = (xr - xl + d) / (w + d);
2018  int x = xr - n * (w + d);
2019  tColor Color = Theme.Color(clrVolumeBarLower);
2020  for (int i = 0; i < n; i++) {
2021  if (Total * i >= Current * n)
2022  Color = Theme.Color(clrVolumeBarUpper);
2023  osd->DrawRectangle(x, yt, x + w - 1, yb - 1, Color);
2024  x += w + d;
2025  }
2026  }
2027 }
2028 
2030 {
2031  osd->Flush();
2032 }
2033 
2034 // --- cSkinLCARSDisplayTracks -----------------------------------------------
2035 
2037 private:
2045  void SetItem(const char *Text, int Index, bool Current);
2046 public:
2047  cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
2048  virtual ~cSkinLCARSDisplayTracks();
2049  virtual void SetTrack(int Index, const char * const *Tracks);
2050  virtual void SetAudioChannel(int AudioChannel);
2051  virtual void Flush(void);
2052  };
2053 
2057 
2058 cSkinLCARSDisplayTracks::cSkinLCARSDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
2059 {
2060  const cFont *font = cFont::GetFont(fontOsd);
2061  lineHeight = font->Height();
2062  frameColor = Theme.Color(clrTrackFrameBg);
2063  currentIndex = -1;
2064  xt00 = 0;
2065  xt01 = xt00 + lineHeight / 2;
2066  xt02 = xt01 + Gap;
2067  xt03 = xt00 + 2 * lineHeight;
2068  int ItemsWidth = font->Width(Title) + xt03 - xt02;
2069  for (int i = 0; i < NumTracks; i++)
2070  ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]) + 2 * TextFrame);
2071  xt04 = xt02 + ItemsWidth;
2072  xt05 = xt04 + Gap;
2073  xt06 = xt04 + lineHeight;
2074  xt07 = xt05 + lineHeight;
2075  xt08 = xt07 + lineHeight;
2076  xt09 = xt08 + Gap;
2077  xt10 = xt09 + lineHeight / 2;
2078  xt11 = xt10 + Gap;
2079  xt12 = xt11 + lineHeight;
2080  yt00 = 0;
2081  yt01 = yt00 + lineHeight;
2082  yt02 = yt01 + lineHeight;
2083  yt03 = yt02 + Gap;
2084  yt04 = yt03 + NumTracks * lineHeight + (NumTracks - 1) * Gap;
2085  yt05 = yt04 + Gap;
2086  yt06 = yt05 + lineHeight;
2087  yt07 = yt06 + lineHeight;
2088  while (yt07 > cOsd::OsdHeight()) {
2089  yt04 -= lineHeight + Gap;
2090  yt05 = yt04 + Gap;
2091  yt06 = yt05 + lineHeight;
2092  yt07 = yt06 + lineHeight;
2093  }
2095  // The upper elbow:
2098  osd->DrawEllipse (xt00, yt00, xt03 - 1, yt02 - 1, frameColor, 2);
2099  osd->DrawRectangle(xt03, yt00, xt04 - 1, yt02 - 1, frameColor);
2100  osd->DrawRectangle(xt04, yt00, xt08 - 1, yt01 - 1, frameColor);
2101  osd->DrawEllipse (xt04, yt01, xt06 - 1, yt02 - 1, frameColor, -2);
2102  osd->DrawRectangle(xt09, yt00, xt10 - 1, yt01 - 1, frameColor);
2103  osd->DrawRectangle(xt11, yt00, xt11 + lineHeight / 2 - 1, yt01 - 1, frameColor);
2105  osd->DrawEllipse (xt11 + lineHeight / 2, yt00, xt12 - 1, yt01 - 1, frameColor, 5);
2106  osd->DrawText(xt03, yt00, Title, Theme.Color(clrTrackFrameFg), frameColor, font, xt04 - xt03, 0, taTop | taRight);
2107  // The items:
2108  for (int i = 0; i < NumTracks; i++)
2109  SetItem(Tracks[i], i, false);
2110  // The lower elbow:
2112  osd->DrawEllipse (xt00, yt05, xt03 - 1, yt07 - 1, frameColor, 3);
2113  osd->DrawRectangle(xt03, yt05, xt04 - 1, yt07 - 1, frameColor);
2114  osd->DrawRectangle(xt04, yt06, xt08 - 1, yt07 - 1, frameColor);
2115  osd->DrawEllipse (xt04, yt05, xt06 - 1, yt06 - 1, frameColor, -3);
2116  osd->DrawRectangle(xt09, yt06, xt10 - 1, yt07 - 1, frameColor);
2117  osd->DrawRectangle(xt11, yt06, xt11 + lineHeight / 2 - 1, yt07 - 1, frameColor);
2119  osd->DrawEllipse (xt11 + lineHeight / 2, yt06, xt12 - 1, yt07 - 1, frameColor, 5);
2120 }
2121 
2123 {
2124  delete osd;
2125 }
2126 
2127 void cSkinLCARSDisplayTracks::SetItem(const char *Text, int Index, bool Current)
2128 {
2129  int y0 = yt03 + Index * (lineHeight + Gap);
2130  int y1 = y0 + lineHeight;
2131  if (y1 > yt04)
2132  return;
2133  tColor ColorFg, ColorBg;
2134  if (Current) {
2135  ColorFg = Theme.Color(clrTrackItemCurrentFg);
2136  ColorBg = Theme.Color(clrTrackItemCurrentBg);
2137  osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
2138  osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
2139  osd->DrawRectangle(xt05, y0, xt05 + lineHeight / 2 - 1, y1 - 1, ColorBg);
2140  osd->DrawEllipse (xt05 + lineHeight / 2, y0, xt07 - 1, y1 - 1, ColorBg, 5);
2141  currentIndex = Index;
2142  }
2143  else {
2144  ColorFg = Theme.Color(clrTrackItemFg);
2145  ColorBg = Theme.Color(clrTrackItemBg);
2146  osd->DrawRectangle(xt00, y0, xt01 - 1, y1 - 1, frameColor);
2147  osd->DrawRectangle(xt02, y0, xt04 - 1, y1 - 1, ColorBg);
2148  if (currentIndex == Index)
2149  osd->DrawRectangle(xt05, y0, xt07 - 1, y1 - 1, Theme.Color(clrBackground));
2150  }
2151  const cFont *font = cFont::GetFont(fontOsd);
2152  osd->DrawText(xt02, y0, Text, ColorFg, ColorBg, font, xt04 - xt02, y1 - y0, taTop | taLeft | taBorder);
2153 }
2154 
2155 void cSkinLCARSDisplayTracks::SetTrack(int Index, const char * const *Tracks)
2156 {
2157  if (currentIndex >= 0)
2158  SetItem(Tracks[currentIndex], currentIndex, false);
2159  SetItem(Tracks[Index], Index, true);
2160 }
2161 
2163 {
2164  cBitmap *bm = NULL;
2165  switch (AudioChannel) {
2166  case 0: bm = &bmAudioStereo; break;
2167  case 1: bm = &bmAudioLeft; break;
2168  case 2: bm = &bmAudioRight; break;
2169  default: ;
2170  }
2171  if (bm)
2172  osd->DrawBitmap(xt04 - bm->Width(), (yt06 + yt07 - bm->Height()) / 2, *bm, Theme.Color(clrTrackFrameFg), frameColor);
2173  else
2174  osd->DrawRectangle(xt03, yt06, xt04 - 1, yt07 - 1, frameColor);
2175 }
2176 
2178 {
2179  osd->Flush();
2180 }
2181 
2182 // --- cSkinLCARSDisplayMessage ----------------------------------------------
2183 
2185 private:
2187  int x0, x1, x2, x3, x4, x5, x6, x7;
2188  int y0, y1;
2189 public:
2191  virtual ~cSkinLCARSDisplayMessage();
2192  virtual void SetMessage(eMessageType Type, const char *Text);
2193  virtual void Flush(void);
2194  };
2195 
2197 {
2198  const cFont *font = cFont::GetFont(fontOsd);
2199  int lineHeight = font->Height();
2200  x0 = 0;
2201  x1 = lineHeight / 2;
2202  x2 = lineHeight;
2203  x3 = x2 + Gap;
2204  x7 = cOsd::OsdWidth();
2205  x6 = x7 - lineHeight / 2;
2206  x5 = x6 - lineHeight / 2;
2207  x4 = x5 - Gap;
2208  y0 = 0;
2209  y1 = lineHeight;
2210  osd = CreateOsd(cOsd::OsdLeft(), cOsd::OsdTop() + cOsd::OsdHeight() - y1, x0, y0, x7 - 1, y1 - 1);
2211 }
2212 
2214 {
2215  delete osd;
2216 }
2217 
2219 {
2220  tColor ColorFg = Theme.Color(clrMessageStatusFg + 2 * Type);
2221  tColor ColorBg = Theme.Color(clrMessageStatusBg + 2 * Type);
2222  osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, Theme.Color(clrBackground));
2223  osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
2224  osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, ColorBg, 7);
2225  osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, ColorBg);
2226  osd->DrawText(x3, y0, Text, ColorFg, ColorBg, cFont::GetFont(fontSml), x4 - x3, y1 - y0, taCenter);
2227  osd->DrawRectangle(x5, y0, x6 - 1, y1 - 1, ColorBg);
2228  osd->DrawRectangle(x6, y0, x7 - 1, y1 - 1, clrTransparent);
2229  osd->DrawEllipse (x6, y0, x7 - 1, y1 - 1, ColorBg, 5);
2230 }
2231 
2233 {
2234  osd->Flush();
2235 }
2236 
2237 // --- cSkinLCARS ------------------------------------------------------------
2238 
2240 :cSkin("lcars", &::Theme)
2241 {
2242 }
2243 
2244 const char *cSkinLCARS::Description(void)
2245 {
2246  return "LCARS";
2247 }
2248 
2250 {
2251  return new cSkinLCARSDisplayChannel(WithInfo);
2252 }
2253 
2255 {
2256  return new cSkinLCARSDisplayMenu;
2257 }
2258 
2260 {
2261  return new cSkinLCARSDisplayReplay(ModeOnly);
2262 }
2263 
2265 {
2266  return new cSkinLCARSDisplayVolume;
2267 }
2268 
2269 cSkinDisplayTracks *cSkinLCARS::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
2270 {
2271  return new cSkinLCARSDisplayTracks(Title, NumTracks, Tracks);
2272 }
2273 
2275 {
2276  return new cSkinLCARSDisplayMessage;
2277 }
void DrawPlay(cControl *Control)
Definition: skinlcars.c:1460
virtual void SetTitle(const char *Title)
Sets the title of this menu to Title.
Definition: skinlcars.c:1552
static cBitmap bmAudioLeft
Definition: skinlcars.c:2044
static bool TwoColors
Definition: skinlcars.c:203
cString itoa(int n)
Definition: tools.c:424
static cString ToString(int Code)
Definition: sources.c:55
virtual const cFont * GetTextAreaFont(bool FixedFont) const
Returns a pointer to the font which is used to display text with SetText().
Definition: skinlcars.c:1733
int Shown(void)
Definition: osd.h:1055
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
static int OsdHeight(void)
Definition: osd.h:808
Definition: epg.h:71
static cBitmap bmAudioRight
Definition: skinlcars.c:2044
#define CLR_RED
Definition: skinlcars.c:97
eMessageType
Definition: skins.h:37
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:1921
virtual void SetMenuCategory(eMenuCategory MenuCategory)
Sets the current menu category.
Definition: skinlcars.c:960
static cFont * CreateTinyFont(int LineHeight)
Definition: skinlcars.c:222
static cOsd * CreateOsd(int Left, int Top, int x0, int y0, int x1, int y1)
Definition: skinlcars.c:205
virtual cSkinDisplayMenu * DisplayMenu(void)
Creates and returns a new object for displaying a menu.
Definition: skinlcars.c:2254
bool isempty(const char *s)
Definition: tools.c:331
const cChannel * lastChannel
Definition: skinlcars.c:717
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:469
int MasterSlotNumber(void)
Returns the number of this CAM's master slot within the whole system.
Definition: ci.h:347
time_t StartTime(void) const
Definition: epg.h:109
Definition: font.h:23
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
int Dpid(int i) const
Definition: channels.h:161
void DrawTimers(void)
Definition: skinlcars.c:1248
virtual cSkinDisplayChannel * DisplayChannel(bool WithInfo)
Creates and returns a new object for displaying the current channel.
Definition: skinlcars.c:2249
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:1900
virtual ~cSkinLCARSDisplayTracks()
Definition: skinlcars.c:2122
static int NormalizeAngle(int Angle)
Normalizes the given Angle into the range -1800...1800.
Definition: positioner.c:42
const cEvent * lastEvent
Definition: skinlcars.c:719
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:1630
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition: osd.c:1831
eCurrentMode lastMode
Definition: skinlcars.c:708
static cBitmap bmEncrypted
Definition: skinlcars.c:367
#define CLR_EVENT_TIME
Definition: skinlcars.c:89
const char * Description(void) const
Definition: recording.h:87
char description[32]
Definition: device.h:83
#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:1681
#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:1934
static cTheme Theme
Definition: skinlcars.c:75
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
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:1583
virtual void SetEvent(const cEvent *Event)
Sets the Event that shall be displayed, using the entire central area of the menu.
Definition: skinlcars.c:1635
virtual void SetRecording(const cRecording *Recording)
Sets the recording that is currently being played.
Definition: skinlcars.c:1879
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:1933
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1127
static cBitmap bmRadio
Definition: skinlcars.c:367
virtual void Append(T Data)
Definition: tools.h:737
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:1973
time_t Vps(void) const
Definition: epg.h:112
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2232
const char * Name(void) const
Returns the full name of the recording (without the video directory).
Definition: recording.h:146
int Source(void) const
Definition: channels.h:152
virtual int CurrentLongitude(void) const
Returns the longitude the dish currently points to.
Definition: positioner.c:114
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:2148
#define CLR_MENU_ITEMS
Definition: skinlcars.c:84
#define MAXDEVICES
Definition: device.h:29
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
Definition: thread.c:859
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:1111
cStateKey timersStateKey
Definition: skinlcars.c:713
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:2001
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
int Width(void) const
Definition: osd.h:188
cString GetVpsString(void) const
Definition: epg.c:443
virtual void SetTitle(const char *Title)
Sets the title of the recording.
Definition: skinlcars.c:1888
T max(T a, T b)
Definition: tools.h:60
cSkinLCARS(void)
Definition: skinlcars.c:2239
virtual cSkinDisplayMessage * DisplayMessage(void)
Creates and returns a new object for displaying a message.
Definition: skinlcars.c:2274
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:1963
int HardLimitLongitude(ePositionerDirection Direction) const
Returns the longitude of the positioner's hard limit in the given Direction.
Definition: positioner.c:81
#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:127
const cRecordingInfo * Info(void) const
Definition: recording.h:153
static cSkinDisplay * Current(void)
Returns the currently active cSkinDisplay.
Definition: skins.h:61
#define TextFrame
Definition: skinlcars.c:67
eMenuCategory MenuCategory(void) const
Returns the menu category, set by a previous call to SetMenuCategory().
Definition: skins.h:183
#define CLR_EVENT_SHORTTEXT
Definition: skinlcars.c:90
int ColorKey2
Definition: config.h:315
time_t Start(void) const
Definition: recording.h:131
T min(T a, T b)
Definition: tools.h:59
int Ca(int Index=0) const
Definition: channels.h:173
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:1367
int TargetLongitude(void) const
Returns the longitude the dish is supposed to be moved to.
Definition: positioner.h:105
eTrackType GetCurrentAudioTrack(void) const
Definition: device.h:569
virtual ~cSkinLCARSDisplayReplay()
Definition: skinlcars.c:1855
void Reset(void)
Resets the state of this key, so that the next call to a lock's Lock() function with this key will re...
Definition: thread.c:854
cString lastDeviceType[MAXDEVICES]
Definition: skinlcars.c:702
void DrawDevices(void)
Definition: skinlcars.c:1357
virtual cSkinDisplayReplay * DisplayReplay(bool ModeOnly)
Creates and returns a new object for displaying replay progress.
Definition: skinlcars.c:2259
cString GetEndTimeString(void) const
Definition: epg.c:438
void DrawLive(const cChannel *Channel)
Definition: skinlcars.c:1418
virtual void Flush(void)
Actually commits all data to the OSD hardware.
Definition: osd.c:1993
static cBitmap bmAudio
Definition: skinlcars.c:367
Definition: osd.h:158
Definition: osd.h:169
int Height(void)
Definition: osd.h:1052
#define clrBackground
Definition: skincurses.c:36
cString GetParentalRatingString(void) const
Definition: epg.c:421
Definition: timers.h:27
#define CLR_WHITE
Definition: skinlcars.c:96
A steerable satellite dish generally points to the south on the northern hemisphere,...
Definition: positioner.h:31
cString GetDateString(void) const
Definition: epg.c:428
#define Gap
Definition: skinlcars.c:66
Definition: osd.h:161
void DrawMainButton(const char *Text, int x0, int x1, int x2, int x3, int y0, int y1, tColor ColorFg, tColor ColorBg, const cFont *Font)
Definition: skinlcars.c:1028
virtual int Height(void) const =0
Returns the height of this font in pixel (all characters have the same height).
static cBitmap bmArrowDown
Definition: skinlcars.c:723
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:653
cTextScroller textScroller
Definition: skins.h:173
void DrawSignals(void)
Definition: skinlcars.c:1402
const char * ChannelName(void) const
Definition: recording.h:83
#define CLR_GREEN
Definition: skinlcars.c:98
#define DISKUSAGEALERTLIMIT
Definition: skinlcars.c:72
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:1913
Definition: font.h:22
T constrain(T v, T l, T h)
Definition: tools.h:68
static int OsdWidth(void)
Definition: osd.h:807
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable)
Sets the item at the given Index to Text.
Definition: skinlcars.c:1593
cString WeekDayName(int WeekDay)
Converts the given WeekDay (0=Sunday, 1=Monday, ...) to a three letter day name.
Definition: tools.c:1150
virtual void SetJump(const char *Jump)
Sets the prompt that allows the user to enter a jump point.
Definition: skinlcars.c:1929
bool lastLiveIndicatorTransferring
Definition: skinlcars.c:716
void DrawStatusElbows(void)
Definition: skinlcars.c:1134
int ChannelInfoPos
Definition: config.h:320
int Tpid(void) const
Definition: channels.h:171
#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:1809
int Size(void) const
Definition: tools.h:717
virtual int SignalStrength(void) const
Returns the "strength" of the currently received signal.
Definition: device.c:760
#define LOCK_CHANNELS_READ
Definition: channels.h:267
char FontOsd[MAXFONTNAME]
Definition: config.h:328
virtual int SignalQuality(void) const
Returns the "quality" of the currently received signal.
Definition: device.c:765
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:2244
bool GroupSep(void) const
Definition: channels.h:181
void swap(T &a, T &b)
Definition: tools.h:64
virtual int MaxItems(void)
Returns the maximum number of items the menu can display.
Definition: skinlcars.c:1538
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:205
int Height(void) const
Definition: osd.h:189
virtual void SetMessage(eMessageType Type, const char *Text)
< This class implements a simple message display.
Definition: skinlcars.c:2218
#define CLR_BLUE
Definition: skinlcars.c:100
tColor RgbShade(tColor Color, double Factor)
Returns a brighter (Factor > 0) or darker (Factor < 0) version of the given Color.
Definition: osd.c:43
int Tab(int n)
Returns the offset of the given tab from the left border of the item display area.
Definition: skins.h:174
virtual int GetTextAreaWidth(void) const
Returns the width in pixel of the area which is used to display text with SetText().
Definition: skinlcars.c:1728
const char * ShortText(void) const
Definition: epg.h:104
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:2269
static const cCursesFont Font
Definition: skincurses.c:32
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:2058
The cOsd class is the interface to the "On Screen Display".
Definition: osd.h:724
static bool Active(void)
Definition: menu.c:5608
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:1944
#define CLR_BACKGROUND
Definition: skinlcars.c:79
Definition: skins.h:107
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
static cBitmap bmArrowUp
Definition: skinlcars.c:723
cSetup Setup
Definition: config.c:372
virtual void SetEvents(const cEvent *Present, const cEvent *Following)
Sets the Present and Following EPG events.
Definition: skinlcars.c:588
void DrawSeen(int Current, int Total)
Definition: skinlcars.c:1514
uint Flags(void) const
Definition: timers.h:58
int Duration(void) const
Definition: epg.h:111
Definition: ci.h:232
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:1532
static const char *const * ReplaySymbols[2][2][5]
Definition: skinlcars.c:1893
bool CanScroll(void)
Definition: osd.h:1056
cString DayDateTime(time_t t)
Converts the given time to a string of the form "www dd.mm. hh:mm".
Definition: tools.c:1192
static cFont * CreateFont(const char *Name, int CharHeight, int CharWidth=0)
Creates a new font object with the given Name and makes its characters CharHeight pixels high.
Definition: font.c:428
virtual 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:1562
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:1953
static cBitmap bmAudioStereo
Definition: skinlcars.c:2044
void DrawFrameDisplay(void)
Definition: skinlcars.c:1152
const cChannel * Channel(void) const
Definition: timers.h:59
int Apid(int i) const
Definition: channels.h:160
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:1740
cSkinLCARSDisplayReplay(bool ModeOnly)
Definition: skinlcars.c:1791
#define CLR_YELLOW
Definition: skinlcars.c:99
int ColorKey3
Definition: config.h:315
Definition: skins.h:402
virtual void Clear(void)
Clears the entire central area of the menu.
Definition: skinlcars.c:1546
static int OsdTop(void)
Definition: osd.h:806
bool CanScrollUp(void)
Definition: osd.h:1057
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:49
void DrawMainFrameLower(void)
Definition: skinlcars.c:1009
const char * Name(void) const
Definition: channels.c:108
static int OsdLeft(void)
Definition: osd.h:805
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 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:1722
void DrawMenuFrame(void)
Definition: skinlcars.c:1036
int Vpid(void) const
Definition: channels.h:154
static cBitmap bmRecording
Definition: skinlcars.c:367
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skinlcars.c:610
virtual cString DeviceType(void) const
Returns a string identifying the type of this device (like "DVB-S").
Definition: device.c:169
#define CLR_TRACK
Definition: skinlcars.c:92
virtual int Width(void) const =0
Returns the original character width as requested when the font was created, or 0 if the default widt...
const char * Title(void) const
Definition: epg.h:103
const cEvent * present
Definition: skinlcars.c:355
cVector< int > deviceOffset
Definition: skinlcars.c:700
virtual ~cSkinLCARSDisplayVolume()
Definition: skinlcars.c:1996
time_t StopTime(void) const
Definition: timers.c:530
eMenuCategory
Definition: skins.h:104
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:160
void Reset(void)
Definition: osd.c:2165
Definition: osd.h:298
const cEvent * Event(void) const
Definition: timers.h:74
int ColorKey1
Definition: config.h:315
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:146
Definition: epg.h:150
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:2177
Definition: timers.h:21
const char * ShortText(void) const
Definition: recording.h:86
bool Recording(void) const
Definition: timers.h:55
const char * Remote(void) const
Definition: timers.h:69
Definition: osd.h:159
virtual cSkinDisplayVolume * DisplayVolume(void)
Creates and returns a new object for displaying the current volume.
Definition: skinlcars.c:2264
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:1079
#define tr(s)
Definition: i18n.h:85
void DrawInfo(const cEvent *Event, bool WithTime)
Definition: skinlcars.c:1499
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition: device.c:1314
virtual ~cSkinLCARSDisplayChannel()
Definition: skinlcars.c:475
cListObject * Next(void) const
Definition: tools.h:510
#define CLR_ALERT
Definition: skinlcars.c:94
#define SECSINDAY
Definition: tools.h:42
bool Pending(void) const
Definition: timers.h:56
cString TimeString(time_t t)
Converts the given time to a string of the form "hh:mm".
Definition: tools.c:1233
void SetItem(const char *Text, int Index, bool Current)
Definition: skinlcars.c:2127
static cRecordControl * GetRecordControl(const char *FileName)
Definition: menu.c:5556
int FontOsdSize
Definition: config.h:334
int ColorKey0
Definition: config.h:315
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)
cString GetTimeString(void) const
Definition: epg.c:433
#define CLR_EVENT_TITLE
Definition: skinlcars.c:88
#define SIGNALDISPLAYDELTA
Definition: skinlcars.c:73
virtual cString GetHeader(void)
This can be used by players that don't play a cRecording, but rather do something completely differen...
Definition: player.c:68
virtual void SetAudioChannel(int AudioChannel)
Sets the audio channel indicator.
Definition: skinlcars.c:2162
#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:1224
#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:2155
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skinlcars.c:2029
int ParentalRating(void) const
Definition: epg.h:108
virtual void RestoreRegion(void)
Restores the region previously saved by a call to SaveRegion().
Definition: osd.c:1882
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:1698
cVector< bool > deviceRecording
Definition: skinlcars.c:701
#define CLR_DEVICE
Definition: skinlcars.c:86
const char * GetTabbedText(const char *s, int Tab)
Returns the part of the given string that follows the given Tab (where 0 indicates the beginning of t...
Definition: skins.c:112
#define CLR_REPLAY_FRAME
Definition: skinlcars.c:82
const cMarks * marks
< This class implements the progress display used during replay of a recording.
Definition: skins.h:323
static int FreeMinutes(void)
Returns the number of minutes that can still be recorded on the video disk.
Definition: videodir.h:118
#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
#define LOCK_SCHEDULES_READ
Definition: epg.h:224
void DrawDevice(const cDevice *Device)
Definition: skinlcars.c:1340
#define CLR_BLACK
Definition: skinlcars.c:101
#define CLR_CHANNEL_FRAME
Definition: skinlcars.c:81
virtual void Clear(void)
Definition: tools.h:768
void DrawTextScrollbar(void)
Definition: skinlcars.c:1526
cVector< int > lastSignalQuality
Definition: skinlcars.c:705
static const cTimers * GetTimersRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for read access.
Definition: timers.c:843
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:1866
const cRecording * lastRecording
Definition: skinlcars.c:720
cSkinLCARSDisplayChannel(bool WithInfo)
Definition: skinlcars.c:390
bool Replaying(void) const
Returns true if we are currently replaying.
Definition: device.c:1309
tColor Color(int Subject)
Returns the color for the given Subject.
Definition: themes.c:201
#define CLR_DATE
Definition: skinlcars.c:83
const cEvent * GetEvent(void) const
Definition: recording.h:84
Definition: font.h:37
virtual ~cSkinLCARSDisplayMessage()
Definition: skinlcars.c:2213
const char * Title(void) const
Definition: recording.h:85
int Offset(void)
Definition: osd.h:1054
Definition: tools.h:176
virtual void SetPositioner(const cPositioner *Positioner)
Sets the Positioner used to move the satellite dish.
Definition: skinlcars.c:639
time_t StartTime(void) const
Definition: timers.c:523
static cBitmap bmTransferMode
Definition: skinlcars.c:723
int Number(void) const
Definition: channels.h:179
static const cFont * GetFont(eDvbFont Font)
Gets the given Font, which was previously set by a call to SetFont().
Definition: font.c:411
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:1907
bool GetIndex(int &Current, int &Total, bool SnapToIFrame=false) const
Definition: player.h:111
cString DateString(time_t t)
Converts the given time to a string of the form "www dd.mm.yyyy".
Definition: tools.c:1213
uint32_t tColor
Definition: font.h:29
bool CanScrollDown(void)
Definition: osd.h:1058
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:2017
const char * Description(void) const
Definition: epg.h:105
static int UsedPercent(void)
Returns the used space of the video disk in percent.
Definition: videodir.h:112
void DrawMainFrameUpper(tColor Color)
Definition: skinlcars.c:990
int Total(void)
Definition: osd.h:1053