vdr  1.7.31
skinclassic.c
Go to the documentation of this file.
1 /*
2  * skinclassic.c: The 'classic' VDR skin
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: skinclassic.c 2.8 2012/09/09 11:39:06 kls Exp $
8  */
9 
10 #include "skinclassic.h"
11 #include "font.h"
12 #include "i18n.h"
13 #include "osd.h"
14 #include "themes.h"
15 #include "videodir.h"
16 
17 #define ScrollWidth (Setup.FontOsdSize / 4)
18 #define TextFrame (Setup.FontOsdSize / 10)
19 #define TextSpacing (Setup.FontOsdSize / 4)
20 
21 static cTheme Theme;
22 
24 THEME_CLR(Theme, clrButtonRedFg, clrWhite);
25 THEME_CLR(Theme, clrButtonRedBg, clrRed);
26 THEME_CLR(Theme, clrButtonGreenFg, clrBlack);
27 THEME_CLR(Theme, clrButtonGreenBg, clrGreen);
28 THEME_CLR(Theme, clrButtonYellowFg, clrBlack);
29 THEME_CLR(Theme, clrButtonYellowBg, clrYellow);
30 THEME_CLR(Theme, clrButtonBlueFg, clrWhite);
31 THEME_CLR(Theme, clrButtonBlueBg, clrBlue);
32 THEME_CLR(Theme, clrMessageStatusFg, clrBlack);
33 THEME_CLR(Theme, clrMessageStatusBg, clrCyan);
34 THEME_CLR(Theme, clrMessageInfoFg, clrBlack);
35 THEME_CLR(Theme, clrMessageInfoBg, clrGreen);
36 THEME_CLR(Theme, clrMessageWarningFg, clrBlack);
37 THEME_CLR(Theme, clrMessageWarningBg, clrYellow);
38 THEME_CLR(Theme, clrMessageErrorFg, clrWhite);
39 THEME_CLR(Theme, clrMessageErrorBg, clrRed);
40 THEME_CLR(Theme, clrVolumePrompt, clrGreen);
41 THEME_CLR(Theme, clrVolumeBarUpper, clrWhite);
42 THEME_CLR(Theme, clrVolumeBarLower, clrGreen);
43 THEME_CLR(Theme, clrChannelName, clrWhite);
44 THEME_CLR(Theme, clrChannelDate, clrWhite);
45 THEME_CLR(Theme, clrChannelEpgTimeFg, clrWhite);
46 THEME_CLR(Theme, clrChannelEpgTimeBg, clrRed);
47 THEME_CLR(Theme, clrChannelEpgTitle, clrCyan);
48 THEME_CLR(Theme, clrChannelEpgShortText, clrYellow);
49 THEME_CLR(Theme, clrMenuTitleFg, clrBlack);
50 THEME_CLR(Theme, clrMenuTitleBg, clrCyan);
51 THEME_CLR(Theme, clrMenuDate, clrBlack);
52 THEME_CLR(Theme, clrMenuItemCurrentFg, clrBlack);
53 THEME_CLR(Theme, clrMenuItemCurrentBg, clrCyan);
54 THEME_CLR(Theme, clrMenuItemSelectable, clrWhite);
55 THEME_CLR(Theme, clrMenuItemNonSelectable, clrCyan);
56 THEME_CLR(Theme, clrMenuEventTime, clrWhite);
57 THEME_CLR(Theme, clrMenuEventVpsFg, clrBlack);
58 THEME_CLR(Theme, clrMenuEventVpsBg, clrWhite);
59 THEME_CLR(Theme, clrMenuEventTitle, clrCyan);
60 THEME_CLR(Theme, clrMenuEventShortText, clrWhite);
61 THEME_CLR(Theme, clrMenuEventDescription, clrCyan);
62 THEME_CLR(Theme, clrMenuScrollbarTotal, clrWhite);
63 THEME_CLR(Theme, clrMenuScrollbarShown, clrCyan);
64 THEME_CLR(Theme, clrMenuText, clrWhite);
65 THEME_CLR(Theme, clrReplayTitle, clrWhite);
66 THEME_CLR(Theme, clrReplayCurrent, clrWhite);
67 THEME_CLR(Theme, clrReplayTotal, clrWhite);
68 THEME_CLR(Theme, clrReplayModeJump, clrWhite);
69 THEME_CLR(Theme, clrReplayProgressSeen, clrGreen);
70 THEME_CLR(Theme, clrReplayProgressRest, clrWhite);
71 THEME_CLR(Theme, clrReplayProgressSelected, clrRed);
72 THEME_CLR(Theme, clrReplayProgressMark, clrBlack);
73 THEME_CLR(Theme, clrReplayProgressCurrent, clrRed);
74 
75 // --- cSkinClassicDisplayChannel --------------------------------------------
76 
78 private:
81  int timeWidth;
82  bool message;
84 public:
85  cSkinClassicDisplayChannel(bool WithInfo);
87  virtual void SetChannel(const cChannel *Channel, int Number);
88  virtual void SetEvents(const cEvent *Present, const cEvent *Following);
89  virtual void SetMessage(eMessageType Type, const char *Text);
90  virtual void Flush(void);
91  };
92 
94 {
95  int Lines = WithInfo ? 5 : 1;
96  const cFont *font = cFont::GetFont(fontOsd);
97  lineHeight = font->Height();
98  message = false;
100  timeWidth = font->Width("00:00") + 2 * TextFrame;
101  tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, Lines * lineHeight - 1, 8 } };
102  if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
103  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
104  else {
105  tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, Lines * lineHeight - 1, 4 } };
106  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
107  }
108  osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrBackground));
109 }
110 
112 {
113  delete osd;
114 }
115 
116 void cSkinClassicDisplayChannel::SetChannel(const cChannel *Channel, int Number)
117 {
118  osd->DrawRectangle(0, 0, osd->Width() - 1, lineHeight - 1, Theme.Color(clrBackground));
119  osd->DrawText(TextFrame, 0, ChannelString(Channel, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
120  lastDate = NULL;
121 }
122 
123 void cSkinClassicDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
124 {
125  osd->DrawRectangle(0, lineHeight, timeWidth - 1, osd->Height(), Theme.Color(clrChannelEpgTimeBg));
127  for (int i = 0; i < 2; i++) {
128  const cEvent *e = !i ? Present : Following;
129  if (e) {
130  osd->DrawText( TextFrame, (2 * i + 1) * lineHeight, e->GetTimeString(), Theme.Color(clrChannelEpgTimeFg), Theme.Color(clrChannelEpgTimeBg), cFont::GetFont(fontOsd));
131  osd->DrawText(timeWidth + 2 * TextSpacing, (2 * i + 1) * lineHeight, e->Title(), Theme.Color(clrChannelEpgTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
132  osd->DrawText(timeWidth + 2 * TextSpacing, (2 * i + 2) * lineHeight, e->ShortText(), Theme.Color(clrChannelEpgShortText), Theme.Color(clrBackground), cFont::GetFont(fontSml));
133  }
134  }
135 }
136 
138 {
139  const cFont *font = cFont::GetFont(fontOsd);
140  if (Text) {
141  osd->SaveRegion(0, 0, osd->Width() - 1, lineHeight - 1);
142  osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, osd->Width(), 0, taCenter);
143  message = true;
144  }
145  else {
146  osd->RestoreRegion();
147  message = false;
148  }
149 }
150 
152 {
153  if (!message) {
154  cString date = DayDateTime();
155  if (!*lastDate || strcmp(date, lastDate)) {
156  const cFont *font = cFont::GetFont(fontSml);
157  int w = font->Width(date);
158  osd->DrawText(osd->Width() - w - TextFrame, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml), w);
159  lastDate = date;
160  }
161  }
162  osd->Flush();
163 }
164 
165 // --- cSkinClassicDisplayMenu -----------------------------------------------
166 
168 private:
170  int x0, x1, x2, x3;
171  int y0, y1, y2, y3, y4, y5;
177  void DrawTitle(void);
178  void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
179  void SetTextScrollbar(void);
180 public:
182  virtual ~cSkinClassicDisplayMenu();
183  virtual void Scroll(bool Up, bool Page);
184  virtual int MaxItems(void);
185  virtual void Clear(void);
186  virtual void SetTitle(const char *Title);
187  virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
188  virtual void SetMessage(eMessageType Type, const char *Text);
189  virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
190  virtual void SetScrollbar(int Total, int Offset);
191  virtual void SetEvent(const cEvent *Event);
192  virtual void SetRecording(const cRecording *Recording);
193  virtual void SetText(const char *Text, bool FixedFont);
194  virtual int GetTextAreaWidth(void) const;
195  virtual const cFont *GetTextAreaFont(bool FixedFont) const;
196  virtual void Flush(void);
197  };
198 
200 {
201  const cFont *font = cFont::GetFont(fontOsd);
202  lineHeight = font->Height();
203  lastDiskUsageState = -1;
204  dateWidth = 0;
205  x0 = 0;
206  x1 = x0 + 2 * TextSpacing;
207  x3 = cOsd::OsdWidth();
208  x2 = x3 - 2 * ScrollWidth;
209  y0 = 0;
210  y1 = lineHeight;
211  y2 = y1 + lineHeight;
212  y5 = cOsd::OsdHeight();
213  y4 = y5 - lineHeight;
214  y3 = y4 - lineHeight;
216  tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 8 } };
217  if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
218  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
219  else {
220  tArea Areas[] = { { x0, y0, x3 - 1, y5 - 1, 4 } };
221  if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
222  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
223  else {
224  tArea Areas[] = { { x0, y0, x3 - 1, y1 - 1, 2 },
225  { x0, y1, x3 - 1, y3 - 1, 2 },
226  { x0, y3, x3 - 1, y5 - 1, 4 }
227  };
228  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
229  }
230  }
231  osd->DrawRectangle(x0, y0, x3 - 1, y5 - 1, Theme.Color(clrBackground));
232 }
233 
235 {
236  delete osd;
237 }
238 
239 void cSkinClassicDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown)
240 {
241  if (Total > 0 && Total > Shown) {
242  int yt = Top;
243  int yb = yt + Height;
244  int st = yt;
245  int sb = yb;
246  int th = max(int((sb - st) * double(Shown) / Total + 0.5), ScrollWidth);
247  int tt = min(int(st + (sb - st) * double(Offset) / Total + 0.5), sb - th);
248  int tb = min(tt + th, sb);
249  int xl = x3 - ScrollWidth;
250  osd->DrawRectangle(xl, st, x3 - 1, sb - 1, Theme.Color(clrMenuScrollbarTotal));
251  osd->DrawRectangle(xl, tt, x3 - 1, tb - 1, Theme.Color(clrMenuScrollbarShown));
252  }
253 }
254 
256 {
257  if (textScroller.CanScroll())
259 }
260 
261 void cSkinClassicDisplayMenu::Scroll(bool Up, bool Page)
262 {
263  cSkinDisplayMenu::Scroll(Up, Page);
265 }
266 
268 {
269  return (y3 - y2) / lineHeight;
270 }
271 
273 {
275  osd->DrawRectangle(x0, y1, x3 - 1, y4 - 1, Theme.Color(clrBackground));
276 }
277 
279 {
280  const cFont *font = cFont::GetFont(fontOsd);
281  bool WithDisk = MenuCategory() == mcMain || MenuCategory() == mcRecording;
282  osd->DrawText(x0, y0, WithDisk ? cString::sprintf("%s - %s", *title, *cVideoDiskUsage::String()) : title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x3 - x0 - dateWidth);
283 }
284 
285 void cSkinClassicDisplayMenu::SetTitle(const char *Title)
286 {
287  title = Title;
288  DrawTitle();
289 }
290 
291 void cSkinClassicDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
292 {
293  const cFont *font = cFont::GetFont(fontOsd);
294  const char *lutText[] = { Red, Green, Yellow, Blue };
295  tColor lutFg[] = { clrButtonRedFg, clrButtonGreenFg, clrButtonYellowFg, clrButtonBlueFg };
296  tColor lutBg[] = { clrButtonRedBg, clrButtonGreenBg, clrButtonYellowBg, clrButtonBlueBg };
297  int w = x3 - x0;
298  int t0 = x0;
299  int t1 = x0 + w / 4;
300  int t2 = x0 + w / 2;
301  int t3 = x3 - w / 4;
302  int t4 = x3;
303  osd->DrawText(t0, y4, lutText[Setup.ColorKey0], Theme.Color(lutFg[Setup.ColorKey0]), lutText[Setup.ColorKey0] ? Theme.Color(lutBg[Setup.ColorKey0]) : Theme.Color(clrBackground), font, t1 - t0, 0, taCenter);
304  osd->DrawText(t1, y4, lutText[Setup.ColorKey1], Theme.Color(lutFg[Setup.ColorKey1]), lutText[Setup.ColorKey1] ? Theme.Color(lutBg[Setup.ColorKey1]) : Theme.Color(clrBackground), font, t2 - t1, 0, taCenter);
305  osd->DrawText(t2, y4, lutText[Setup.ColorKey2], Theme.Color(lutFg[Setup.ColorKey2]), lutText[Setup.ColorKey2] ? Theme.Color(lutBg[Setup.ColorKey2]) : Theme.Color(clrBackground), font, t3 - t2, 0, taCenter);
306  osd->DrawText(t3, y4, lutText[Setup.ColorKey3], Theme.Color(lutFg[Setup.ColorKey3]), lutText[Setup.ColorKey3] ? Theme.Color(lutBg[Setup.ColorKey3]) : Theme.Color(clrBackground), font, t4 - t3, 0, taCenter);
307 }
308 
310 {
311  const cFont *font = cFont::GetFont(fontOsd);
312  if (Text)
313  osd->DrawText(x0, y3, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x3 - x0, 0, taCenter);
314  else
315  osd->DrawRectangle(x0, y3, x3 - 1, y4 - 1, Theme.Color(clrBackground));
316 }
317 
318 void cSkinClassicDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
319 {
320  int y = y2 + Index * lineHeight;
321  tColor ColorFg, ColorBg;
322  if (Current) {
323  ColorFg = Theme.Color(clrMenuItemCurrentFg);
324  ColorBg = Theme.Color(clrMenuItemCurrentBg);
325  }
326  else {
327  ColorFg = Theme.Color(Selectable ? clrMenuItemSelectable : clrMenuItemNonSelectable);
328  ColorBg = Theme.Color(clrBackground);
329  }
330  const cFont *font = cFont::GetFont(fontOsd);
331  for (int i = 0; i < MaxTabs; i++) {
332  const char *s = GetTabbedText(Text, i);
333  if (s) {
334  int xt = x0 + Tab(i);
335  osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt);
336  }
337  if (!Tab(i + 1))
338  break;
339  }
340  SetEditableWidth(x2 - x0 - Tab(1));
341 }
342 
343 void cSkinClassicDisplayMenu::SetScrollbar(int Total, int Offset)
344 {
345  DrawScrollbar(Total, Offset, MaxItems(), y2, MaxItems() * lineHeight, Offset > 0, Offset + MaxItems() < Total);
346 }
347 
349 {
350  if (!Event)
351  return;
352  const cFont *font = cFont::GetFont(fontOsd);
353  int y = y2;
354  cTextScroller ts;
355  char t[32];
356  snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
357  ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
358  if (Event->Vps() && Event->Vps() != Event->StartTime()) {
359  cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());
360  const cFont *font = cFont::GetFont(fontSml);
361  int w = font->Width(buffer);
362  osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
363  }
364  y += ts.Height();
365  if (Event->ParentalRating()) {
366  cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
367  const cFont *font = cFont::GetFont(fontSml);
368  int w = font->Width(buffer);
369  osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
370  }
371  y += font->Height();
372  ts.Set(osd, x1, y, x2 - x1, y3 - y, Event->Title(), font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
373  y += ts.Height();
374  if (!isempty(Event->ShortText())) {
375  const cFont *font = cFont::GetFont(fontSml);
376  ts.Set(osd, x1, y, x2 - x1, y3 - y, Event->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
377  y += ts.Height();
378  }
379  y += font->Height();
380  if (!isempty(Event->Description())) {
381  textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Event->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
383  }
384 }
385 
387 {
388  if (!Recording)
389  return;
390  const cRecordingInfo *Info = Recording->Info();
391  const cFont *font = cFont::GetFont(fontOsd);
392  int y = y2;
393  cTextScroller ts;
394  char t[32];
395  snprintf(t, sizeof(t), "%s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()));
396  ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
397  y += ts.Height();
398  if (Info->GetEvent()->ParentalRating()) {
399  cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
400  const cFont *font = cFont::GetFont(fontSml);
401  int w = font->Width(buffer);
402  osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
403  }
404  y += font->Height();
405  const char *Title = Info->Title();
406  if (isempty(Title))
407  Title = Recording->Name();
408  ts.Set(osd, x1, y, x2 - x1, y3 - y, Title, font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
409  y += ts.Height();
410  if (!isempty(Info->ShortText())) {
411  const cFont *font = cFont::GetFont(fontSml);
412  ts.Set(osd, x1, y, x2 - x1, y3 - y, Info->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
413  y += ts.Height();
414  }
415  y += font->Height();
416  if (!isempty(Info->Description())) {
417  textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Info->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
419  }
420 }
421 
422 void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
423 {
424  textScroller.Set(osd, x1, y2, GetTextAreaWidth(), y3 - y2, Text, GetTextAreaFont(FixedFont), Theme.Color(clrMenuText), Theme.Color(clrBackground));
426 }
427 
429 {
430 return x2 - x1;
431 }
432 
434 {
435  return cFont::GetFont(FixedFont ? fontFix : fontOsd);
436 }
437 
439 {
441  DrawTitle();
442  cString date = DayDateTime();
443  if (!*lastDate || strcmp(date, lastDate)) {
444  const cFont *font = cFont::GetFont(fontOsd);
445  int w = font->Width(date);
446  osd->DrawText(x3 - w - TextFrame, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font, w);
447  lastDate = date;
449  }
450  osd->Flush();
451 }
452 
453 // --- cSkinClassicDisplayReplay ---------------------------------------------
454 
456 private:
458  int x0, x1;
459  int y0, y1, y2, y3;
461 public:
462  cSkinClassicDisplayReplay(bool ModeOnly);
463  virtual ~cSkinClassicDisplayReplay();
464  virtual void SetTitle(const char *Title);
465  virtual void SetMode(bool Play, bool Forward, int Speed);
466  virtual void SetProgress(int Current, int Total);
467  virtual void SetCurrent(const char *Current);
468  virtual void SetTotal(const char *Total);
469  virtual void SetJump(const char *Jump);
470  virtual void SetMessage(eMessageType Type, const char *Text);
471  virtual void Flush(void);
472  };
473 
475 {
476  const cFont *font = cFont::GetFont(fontOsd);
477  int lineHeight = font->Height();
478  lastCurrentWidth = 0;
479  x0 = 0;
480  x1 = cOsd::OsdWidth();
481  y0 = 0;
482  y1 = lineHeight;
483  y2 = 2 * lineHeight;
484  y3 = 3 * lineHeight;
486  tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 8 } };
487  if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
488  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
489  else {
490  tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } };
491  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
492  }
493  osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
494 }
495 
497 {
498  delete osd;
499 }
500 
501 void cSkinClassicDisplayReplay::SetTitle(const char *Title)
502 {
503  osd->DrawText(x0, y0, Title, Theme.Color(clrReplayTitle), Theme.Color(clrBackground), cFont::GetFont(fontOsd), x1 - x0);
504 }
505 
506 void cSkinClassicDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
507 {
508  if (Setup.ShowReplayMode) {
509  const char *Mode;
510  if (Speed == -1) Mode = Play ? " > " : " || ";
511  else if (Play) Mode = Forward ? " X>> " : " <<X ";
512  else Mode = Forward ? " X|> " : " <|X ";
513  char buf[16];
514  strn0cpy(buf, Mode, sizeof(buf));
515  char *p = strchr(buf, 'X');
516  if (p)
517  *p = Speed > 0 ? '1' + Speed - 1 : ' ';
518  SetJump(buf);
519  }
520 }
521 
522 void cSkinClassicDisplayReplay::SetProgress(int Current, int Total)
523 {
524  cProgressBar pb(x1 - x0, y2 - y1, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
525  osd->DrawBitmap(x0, y1, pb);
526 }
527 
528 void cSkinClassicDisplayReplay::SetCurrent(const char *Current)
529 {
530  const cFont *font = cFont::GetFont(fontOsd);
531  int w = font->Width(Current);
532  osd->DrawText(x0, y2, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), font, lastCurrentWidth > w ? lastCurrentWidth : w);
533  lastCurrentWidth = w;
534 }
535 
536 void cSkinClassicDisplayReplay::SetTotal(const char *Total)
537 {
538  const cFont *font = cFont::GetFont(fontOsd);
539  int w = font->Width(Total);
540  osd->DrawText(x1 - font->Width(Total), y2, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), font, w);
541 }
542 
544 {
545  osd->DrawText(x0 + (x1 - x0) / 4, y2, Jump, Theme.Color(clrReplayModeJump), Theme.Color(clrBackground), cFont::GetFont(fontOsd), (x1 - x0) / 2, 0, taCenter);
546 }
547 
549 {
550  const cFont *font = cFont::GetFont(fontOsd);
551  if (Text) {
552  osd->SaveRegion(x0, y2, x1 - 1, y3 - 1);
553  osd->DrawText(x0, y2, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x1 - x0, y3 - y2, taCenter);
554  }
555  else
556  osd->RestoreRegion();
557 }
558 
560 {
561  osd->Flush();
562 }
563 
564 // --- cSkinClassicDisplayVolume ---------------------------------------------
565 
567 private:
569 public:
571  virtual ~cSkinClassicDisplayVolume();
572  virtual void SetVolume(int Current, int Total, bool Mute);
573  virtual void Flush(void);
574  };
575 
577 {
578  const cFont *font = cFont::GetFont(fontOsd);
579  int lineHeight = font->Height();
581  tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 8 } };
582  if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
583  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
584  else {
585  tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 4 } };
586  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
587  }
588 }
589 
591 {
592  delete osd;
593 }
594 
595 void cSkinClassicDisplayVolume::SetVolume(int Current, int Total, bool Mute)
596 {
597  const cFont *font = cFont::GetFont(fontOsd);
598  if (Mute) {
599  osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrTransparent);
600  osd->DrawText(0, 0, tr("Key$Mute"), Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
601  }
602  else {
603  // TRANSLATORS: note the trailing blank!
604  const char *Prompt = tr("Volume ");
605  int l = font->Width(Prompt);
606  int p = (osd->Width() - l) * Current / Total;
607  osd->DrawText(0, 0, Prompt, Theme.Color(clrVolumePrompt), Theme.Color(clrBackground), font);
608  osd->DrawRectangle(l, 0, l + p - 1, osd->Height() - 1, Theme.Color(clrVolumeBarLower));
609  osd->DrawRectangle(l + p, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrVolumeBarUpper));
610  }
611 }
612 
614 {
615  osd->Flush();
616 }
617 
618 // --- cSkinClassicDisplayTracks ---------------------------------------------
619 
621 private:
623  int x0, x1;
624  int y0, y1, y2;
627  void SetItem(const char *Text, int Index, bool Current);
628 public:
629  cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
630  virtual ~cSkinClassicDisplayTracks();
631  virtual void SetTrack(int Index, const char * const *Tracks);
632  virtual void SetAudioChannel(int AudioChannel) {}
633  virtual void Flush(void);
634  };
635 
636 cSkinClassicDisplayTracks::cSkinClassicDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
637 {
638  const cFont *font = cFont::GetFont(fontOsd);
639  lineHeight = font->Height();
640  currentIndex = -1;
641  int ItemsWidth = font->Width(Title);
642  for (int i = 0; i < NumTracks; i++)
643  ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
644  ItemsWidth += 2 * TextSpacing;
645  x0 = 0;
646  x1 = cOsd::OsdWidth();
647  int d = x1 - x0;
648  if (d > ItemsWidth) {
649  d = (d - ItemsWidth) & ~0x07; // must be multiple of 8
650  x1 -= d;
651  }
652  y0 = 0;
653  y1 = lineHeight;
654  y2 = y1 + NumTracks * lineHeight;
656  tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 8 } };
657  if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
658  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
659  else {
660  tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 4 } };
661  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
662  }
663  osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0);
664  for (int i = 0; i < NumTracks; i++)
665  SetItem(Tracks[i], i, false);
666 }
667 
669 {
670  delete osd;
671 }
672 
673 void cSkinClassicDisplayTracks::SetItem(const char *Text, int Index, bool Current)
674 {
675  int y = y1 + Index * lineHeight;
676  tColor ColorFg, ColorBg;
677  if (Current) {
678  ColorFg = Theme.Color(clrMenuItemCurrentFg);
679  ColorBg = Theme.Color(clrMenuItemCurrentBg);
680  currentIndex = Index;
681  }
682  else {
683  ColorFg = Theme.Color(clrMenuItemSelectable);
684  ColorBg = Theme.Color(clrBackground);
685  }
686  const cFont *font = cFont::GetFont(fontOsd);
687  osd->DrawText(x0, y, Text, ColorFg, ColorBg, font, x1 - x0);
688 }
689 
690 void cSkinClassicDisplayTracks::SetTrack(int Index, const char * const *Tracks)
691 {
692  if (currentIndex >= 0)
693  SetItem(Tracks[currentIndex], currentIndex, false);
694  SetItem(Tracks[Index], Index, true);
695 }
696 
698 {
699  osd->Flush();
700 }
701 
702 // --- cSkinClassicDisplayMessage --------------------------------------------
703 
705 private:
707 public:
709  virtual ~cSkinClassicDisplayMessage();
710  virtual void SetMessage(eMessageType Type, const char *Text);
711  virtual void Flush(void);
712  };
713 
715 {
716  const cFont *font = cFont::GetFont(fontOsd);
717  int lineHeight = font->Height();
719  tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 8 } };
720  if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
721  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
722  else {
723  tArea Areas[] = { { 0, 0, cOsd::OsdWidth() - 1, lineHeight - 1, 2 } };
724  osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
725  }
726 }
727 
729 {
730  delete osd;
731 }
732 
734 {
735  const cFont *font = cFont::GetFont(fontOsd);
736  osd->DrawText(0, 0, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, cOsd::OsdWidth(), 0, taCenter);
737 }
738 
740 {
741  osd->Flush();
742 }
743 
744 // --- cSkinClassic ----------------------------------------------------------
745 
747 :cSkin("classic", &::Theme)//XXX naming problem???
748 {
749 }
750 
751 const char *cSkinClassic::Description(void)
752 {
753  return tr("Classic VDR");
754 }
755 
757 {
758  return new cSkinClassicDisplayChannel(WithInfo);
759 }
760 
762 {
763  return new cSkinClassicDisplayMenu;
764 }
765 
767 {
768  return new cSkinClassicDisplayReplay(ModeOnly);
769 }
770 
772 {
773  return new cSkinClassicDisplayVolume;
774 }
775 
776 
777 cSkinDisplayTracks *cSkinClassic::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
778 {
779  return new cSkinClassicDisplayTracks(Title, NumTracks, Tracks);
780 }
781 
783 {
784  return new cSkinClassicDisplayMessage;
785 }