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