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