vdr  2.2.0
skincurses.c
Go to the documentation of this file.
1 /*
2  * skincurses.c: A plugin for the Video Disk Recorder
3  *
4  * See the README file for copyright information and how to reach the author.
5  *
6  * $Id: skincurses.c 3.3 2015/02/17 13:13:17 kls Exp $
7  */
8 
9 #include <ncurses.h>
10 #include <vdr/osd.h>
11 #include <vdr/plugin.h>
12 #include <vdr/skins.h>
13 #include <vdr/videodir.h>
14 
15 static const char *VERSION = "2.2.0";
16 static const char *DESCRIPTION = trNOOP("A text only skin");
17 static const char *MAINMENUENTRY = NULL;
18 
19 // --- cCursesFont -----------------------------------------------------------
20 
21 class cCursesFont : public cFont {
22 public:
23  virtual int Width(uint c) const { return 1; }
24  virtual int Width(const char *s) const { return s ? Utf8StrLen(s) : 0; }
25  virtual int Height(void) const { return 1; }
26  virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {}
27  virtual void DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {}
28  };
29 
30 static const cCursesFont Font = cCursesFont(); // w/o the '= cCursesFont()' gcc 4.6 complains - can anybody explain why this is necessary?
31 
32 // --- cCursesOsd ------------------------------------------------------------
33 
34 #define clrBackground COLOR_BLACK
35 #define clrTransparent clrBackground
36 #define clrBlack clrBackground
37 #define clrRed COLOR_RED
38 #define clrGreen COLOR_GREEN
39 #define clrYellow COLOR_YELLOW
40 #define clrBlue COLOR_BLUE
41 #define clrMagenta COLOR_MAGENTA
42 #define clrCyan COLOR_CYAN
43 #define clrWhite COLOR_WHITE
44 
45 static int clrMessage[] = {
46  clrBlack,
47  clrCyan,
48  clrBlack,
49  clrGreen,
50  clrBlack,
51  clrYellow,
52  clrWhite,
53  clrRed
54  };
55 
56 static int ScOsdWidth = 50;
57 static int ScOsdHeight = 20;
58 
59 class cCursesOsd : public cOsd {
60 private:
61  WINDOW *savedRegion;
62  WINDOW *window;
63  enum { MaxColorPairs = 16 };
65  void SetColor(int colorFg, int colorBg = clrBackground);
66 public:
67  cCursesOsd(int Left, int Top);
68  virtual ~cCursesOsd();
69  virtual void SaveRegion(int x1, int y1, int x2, int y2);
70  virtual void RestoreRegion(void);
71  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);
72  virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color);
73  virtual void Flush(void);
74  };
75 
76 cCursesOsd::cCursesOsd(int Left, int Top)
77 :cOsd(Left, Top, 0)
78 {
79  savedRegion = NULL;
80 
81  memset(colorPairs, 0x00, sizeof(colorPairs));
82  start_color();
83  leaveok(stdscr, true);
84 
85  window = subwin(stdscr, ScOsdHeight, ScOsdWidth, 0, 0);
86  syncok(window, true);
87 }
88 
90 {
91  if (window) {
92  werase(window);
93  Flush();
94  delwin(window);
95  window = NULL;
96  }
97 }
98 
99 void cCursesOsd::SetColor(int colorFg, int colorBg)
100 {
101  int color = (colorBg << 16) | colorFg | 0x80000000;
102  for (int i = 0; i < MaxColorPairs; i++) {
103  if (!colorPairs[i]) {
104  colorPairs[i] = color;
105  init_pair(i + 1, colorFg, colorBg);
106  //XXX??? attron(COLOR_PAIR(WHITE_ON_BLUE));
107  wattrset(window, COLOR_PAIR(i + 1));
108  break;
109  }
110  else if (color == colorPairs[i]) {
111  wattrset(window, COLOR_PAIR(i + 1));
112  break;
113  }
114  }
115 }
116 
117 void cCursesOsd::SaveRegion(int x1, int y1, int x2, int y2)
118 {
119  if (savedRegion) {
120  delwin(savedRegion);
121  savedRegion = NULL;
122  }
123  savedRegion = newwin(y2 - y1 + 1, x2 - x1 + 1, y1, x1);
124  copywin(window, savedRegion, y1, x1, 0, 0, y2 - y1, x2 - x1, false);
125 }
126 
128 {
129  if (savedRegion) {
130  copywin(savedRegion, window, 0, 0, savedRegion->_begy, savedRegion->_begx, savedRegion->_maxy - savedRegion->_begy, savedRegion->_maxx - savedRegion->_begx, false);
131  delwin(savedRegion);
132  savedRegion = NULL;
133  }
134 }
135 
136 void cCursesOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment)
137 {
138  int w = Font->Width(s);
139  int h = Font->Height();
140  if (Width || Height) {
141  int cw = Width ? Width : w;
142  int ch = Height ? Height : h;
143  DrawRectangle(x, y, x + cw - 1, y + ch - 1, ColorBg);
144  if (Width) {
145  if ((Alignment & taLeft) != 0)
146  ;
147  else if ((Alignment & taRight) != 0) {
148  if (w < Width)
149  x += Width - w;
150  }
151  else { // taCentered
152  if (w < Width)
153  x += (Width - w) / 2;
154  }
155  }
156  if (Height) {
157  if ((Alignment & taTop) != 0)
158  ;
159  else if ((Alignment & taBottom) != 0) {
160  if (h < Height)
161  y += Height - h;
162  }
163  else { // taCentered
164  if (h < Height)
165  y += (Height - h) / 2;
166  }
167  }
168  }
169  SetColor(ColorFg, ColorBg);
170  wmove(window, y, x); // ncurses wants 'y' before 'x'!
171  waddnstr(window, s, Width ? Width : ScOsdWidth - x);
172 }
173 
174 void cCursesOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
175 {
176  SetColor(Color, Color);
177  for (int y = y1; y <= y2; y++) {
178  wmove(window, y, x1); // ncurses wants 'y' before 'x'!
179  whline(window, ' ', x2 - x1 + 1);
180  }
181  wsyncup(window); // shouldn't be necessary because of 'syncok()', but w/o it doesn't work
182 }
183 
185 {
186  refresh();
187 }
188 
189 // --- cSkinCursesDisplayChannel ---------------------------------------------
190 
192 private:
195  bool message;
196 public:
197  cSkinCursesDisplayChannel(bool WithInfo);
198  virtual ~cSkinCursesDisplayChannel();
199  virtual void SetChannel(const cChannel *Channel, int Number);
200  virtual void SetEvents(const cEvent *Present, const cEvent *Following);
201  virtual void SetMessage(eMessageType Type, const char *Text);
202  virtual void Flush(void);
203  };
204 
206 {
207  int Lines = WithInfo ? 5 : 1;
208  message = false;
209  osd = new cCursesOsd(0, Setup.ChannelInfoPos ? 0 : ScOsdHeight - Lines);
210  timeWidth = strlen("00:00");
211  osd->DrawRectangle(0, 0, ScOsdWidth - 1, Lines - 1, clrBackground);
212 }
213 
215 {
216  delete osd;
217 }
218 
219 void cSkinCursesDisplayChannel::SetChannel(const cChannel *Channel, int Number)
220 {
221  osd->DrawRectangle(0, 0, ScOsdWidth - 1, 0, clrBackground);
222  osd->DrawText(0, 0, ChannelString(Channel, Number), clrWhite, clrBackground, &Font);
223 }
224 
225 void cSkinCursesDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
226 {
227  osd->DrawRectangle(0, 1, timeWidth - 1, 4, clrRed);
229  for (int i = 0; i < 2; i++) {
230  const cEvent *e = !i ? Present : Following;
231  if (e) {
232  osd->DrawText( 0, 2 * i + 1, e->GetTimeString(), clrWhite, clrRed, &Font);
233  osd->DrawText(timeWidth + 1, 2 * i + 1, e->Title(), clrCyan, clrBackground, &Font);
234  osd->DrawText(timeWidth + 1, 2 * i + 2, e->ShortText(), clrYellow, clrBackground, &Font);
235  }
236  }
237 }
238 
240 {
241  if (Text) {
242  osd->SaveRegion(0, 0, ScOsdWidth - 1, 0);
243  osd->DrawText(0, 0, Text, clrMessage[2 * Type], clrMessage[2 * Type + 1], &Font, ScOsdWidth, 0, taCenter);
244  message = true;
245  }
246  else {
247  osd->RestoreRegion();
248  message = false;
249  }
250 }
251 
253 {
254  if (!message) {
255  cString date = DayDateTime();
256  osd->DrawText(ScOsdWidth - Utf8StrLen(date), 0, date, clrWhite, clrBackground, &Font);
257  }
258  osd->Flush();
259 }
260 
261 // --- cSkinCursesDisplayMenu ------------------------------------------------
262 
264 private:
268  void DrawTitle(void);
269  void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown);
270  void SetTextScrollbar(void);
271 public:
273  virtual ~cSkinCursesDisplayMenu();
274  virtual void Scroll(bool Up, bool Page);
275  virtual int MaxItems(void);
276  virtual void Clear(void);
277  virtual void SetTitle(const char *Title);
278  virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
279  virtual void SetMessage(eMessageType Type, const char *Text);
280  virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
281  virtual void SetScrollbar(int Total, int Offset);
282  virtual void SetEvent(const cEvent *Event);
283  virtual void SetRecording(const cRecording *Recording);
284  virtual void SetText(const char *Text, bool FixedFont);
285  virtual const cFont *GetTextAreaFont(bool FixedFont) const { return &Font; }
286  virtual void Flush(void);
287  };
288 
290 {
291  osd = new cCursesOsd(0, 0);
292  lastDiskUsageState = -1;
294 }
295 
297 {
298  delete osd;
299 }
300 
301 void cSkinCursesDisplayMenu::DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown)
302 {
303  if (Total > 0 && Total > Shown) {
304  int yt = Top;
305  int yb = yt + Height;
306  int st = yt;
307  int sb = yb;
308  int th = max(int((sb - st) * double(Shown) / Total + 0.5), 1);
309  int tt = min(int(st + (sb - st) * double(Offset) / Total + 0.5), sb - th);
310  int tb = min(tt + th, sb);
311  int xl = ScOsdWidth - 1;
312  osd->DrawRectangle(xl, st, xl, sb - 1, clrWhite);
313  osd->DrawRectangle(xl, tt, xl, tb - 1, clrCyan);
314  }
315 }
316 
318 {
319  if (textScroller.CanScroll())
321 }
322 
323 void cSkinCursesDisplayMenu::Scroll(bool Up, bool Page)
324 {
325  cSkinDisplayMenu::Scroll(Up, Page);
327 }
328 
330 {
331  return ScOsdHeight - 4;
332 }
333 
335 {
338 }
339 
341 {
342  bool WithDisk = MenuCategory() == mcMain || MenuCategory() == mcRecording;
343  osd->DrawText(0, 0, WithDisk ? cString::sprintf("%s - %s", *title, *cVideoDiskUsage::String()) : title, clrBlack, clrCyan, &Font, ScOsdWidth);
344 }
345 
346 void cSkinCursesDisplayMenu::SetTitle(const char *Title)
347 {
348  title = Title;
349  DrawTitle();
350 }
351 
352 void cSkinCursesDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
353 {
354  int w = ScOsdWidth;
355  int t0 = 0;
356  int t1 = 0 + w / 4;
357  int t2 = 0 + w / 2;
358  int t3 = w - w / 4;
359  int t4 = w;
360  int y = ScOsdHeight - 1;
361  osd->DrawText(t0, y, Red, clrWhite, Red ? clrRed : clrBackground, &Font, t1 - t0, 0, taCenter);
362  osd->DrawText(t1, y, Green, clrBlack, Green ? clrGreen : clrBackground, &Font, t2 - t1, 0, taCenter);
363  osd->DrawText(t2, y, Yellow, clrBlack, Yellow ? clrYellow : clrBackground, &Font, t3 - t2, 0, taCenter);
364  osd->DrawText(t3, y, Blue, clrWhite, Blue ? clrBlue : clrBackground, &Font, t4 - t3, 0, taCenter);
365 }
366 
368 {
369  if (Text)
370  osd->DrawText(0, ScOsdHeight - 2, Text, clrMessage[2 * Type], clrMessage[2 * Type + 1], &Font, ScOsdWidth, 0, taCenter);
371  else
373 }
374 
375 void cSkinCursesDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
376 {
377  int y = 2 + Index;
378  int ColorFg, ColorBg;
379  if (Current) {
380  ColorFg = clrBlack;
381  ColorBg = clrCyan;
382  }
383  else {
384  ColorFg = Selectable ? clrWhite : clrCyan;
385  ColorBg = clrBackground;
386  }
387  for (int i = 0; i < MaxTabs; i++) {
388  const char *s = GetTabbedText(Text, i);
389  if (s) {
390  int xt = Tab(i) / AvgCharWidth();// Tab() is in "pixel" - see also skins.c!!!
391  osd->DrawText(xt, y, s, ColorFg, ColorBg, &Font, ScOsdWidth - 2 - xt);
392  }
393  if (!Tab(i + 1))
394  break;
395  }
396  SetEditableWidth(ScOsdWidth - 2 - Tab(1) / AvgCharWidth()); // Tab() is in "pixel" - see also skins.c!!!
397 }
398 
399 void cSkinCursesDisplayMenu::SetScrollbar(int Total, int Offset)
400 {
401  DrawScrollbar(Total, Offset, MaxItems(), 2, MaxItems(), Offset > 0, Offset + MaxItems() < Total);
402 }
403 
405 {
406  if (!Event)
407  return;
408  int y = 2;
409  cTextScroller ts;
410  char t[32];
411  snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
412  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
413  if (Event->Vps() && Event->Vps() != Event->StartTime()) {
414  cString buffer = cString::sprintf(" VPS: %s", *Event->GetVpsString());
415  osd->DrawText(ScOsdWidth - Utf8StrLen(buffer), y, buffer, clrBlack, clrYellow, &Font);
416  }
417  y += ts.Height();
418  if (Event->ParentalRating()) {
419  cString buffer = cString::sprintf(" %s ", *Event->GetParentalRatingString());
420  osd->DrawText(ScOsdWidth - Utf8StrLen(buffer), y, buffer, clrBlack, clrYellow, &Font);
421  }
422  y += 1;
423  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, Event->Title(), &Font, clrCyan, clrBackground);
424  y += ts.Height();
425  if (!isempty(Event->ShortText())) {
426  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, Event->ShortText(), &Font, clrYellow, clrBackground);
427  y += ts.Height();
428  }
429  for (int i = 0; Event->Contents(i); i++) {
430  const char *s = Event->ContentToString(Event->Contents(i));
431  if (!isempty(s)) {
432  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, s, &Font, clrYellow, clrBackground);
433  y += 1;
434  }
435  }
436  y += 1;
437  if (!isempty(Event->Description())) {
438  textScroller.Set(osd, 0, y, ScOsdWidth - 2, ScOsdHeight - y - 2, Event->Description(), &Font, clrCyan, clrBackground);
440  }
441 }
442 
444 {
445  if (!Recording)
446  return;
447  const cRecordingInfo *Info = Recording->Info();
448  int y = 2;
449  cTextScroller ts;
450  cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
451  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
452  y += ts.Height();
453  if (Info->GetEvent()->ParentalRating()) {
454  cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
455  osd->DrawText(ScOsdWidth - Utf8StrLen(buffer), y, buffer, clrBlack, clrYellow, &Font);
456  }
457  y += 1;
458  const char *Title = Info->Title();
459  if (isempty(Title))
460  Title = Recording->Name();
461  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, Title, &Font, clrCyan, clrBackground);
462  y += ts.Height();
463  if (!isempty(Info->ShortText())) {
464  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, Info->ShortText(), &Font, clrYellow, clrBackground);
465  y += ts.Height();
466  }
467  for (int i = 0; Info->GetEvent()->Contents(i); i++) {
468  const char *s = Info->GetEvent()->ContentToString(Info->GetEvent()->Contents(i));
469  if (!isempty(s)) {
470  ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, s, &Font, clrYellow, clrBackground);
471  y += 1;
472  }
473  }
474  y += 1;
475  if (!isempty(Info->Description())) {
476  textScroller.Set(osd, 0, y, ScOsdWidth - 2, ScOsdHeight - y - 2, Info->Description(), &Font, clrCyan, clrBackground);
478  }
479 }
480 
481 void cSkinCursesDisplayMenu::SetText(const char *Text, bool FixedFont)
482 {
483  textScroller.Set(osd, 0, 2, ScOsdWidth - 2, ScOsdHeight - 4, Text, &Font, clrWhite, clrBackground);
485 }
486 
488 {
490  DrawTitle();
491  cString date = DayDateTime();
492  osd->DrawText(ScOsdWidth - Utf8StrLen(date) - 2, 0, date, clrBlack, clrCyan, &Font);
493  osd->Flush();
494 }
495 
496 // --- cSkinCursesDisplayReplay ----------------------------------------------
497 
499 private:
501  bool message;
502 public:
503  cSkinCursesDisplayReplay(bool ModeOnly);
504  virtual ~cSkinCursesDisplayReplay();
505  virtual void SetTitle(const char *Title);
506  virtual void SetMode(bool Play, bool Forward, int Speed);
507  virtual void SetProgress(int Current, int Total);
508  virtual void SetCurrent(const char *Current);
509  virtual void SetTotal(const char *Total);
510  virtual void SetJump(const char *Jump);
511  virtual void SetMessage(eMessageType Type, const char *Text);
512  virtual void Flush(void);
513  };
514 
516 {
517  message = false;
518  osd = new cCursesOsd(0, ScOsdHeight - 3);
519  osd->DrawRectangle(0, 0, ScOsdWidth - 1, 2, ModeOnly ? clrTransparent : clrBackground);
520 }
521 
523 {
524  delete osd;
525 }
526 
527 void cSkinCursesDisplayReplay::SetTitle(const char *Title)
528 {
529  osd->DrawText(0, 0, Title, clrWhite, clrBackground, &Font, ScOsdWidth);
530 }
531 
532 void cSkinCursesDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
533 {
534  if (Setup.ShowReplayMode) {
535  const char *Mode;
536  if (Speed == -1) Mode = Play ? " > " : " || ";
537  else if (Play) Mode = Forward ? " X>> " : " <<X ";
538  else Mode = Forward ? " X|> " : " <|X ";
539  char buf[16];
540  strn0cpy(buf, Mode, sizeof(buf));
541  char *p = strchr(buf, 'X');
542  if (p)
543  *p = Speed > 0 ? '1' + Speed - 1 : ' ';
544  SetJump(buf);
545  }
546 }
547 
548 void cSkinCursesDisplayReplay::SetProgress(int Current, int Total)
549 {
550  int p = Total > 0 ? ScOsdWidth * Current / Total : 0;
551  osd->DrawRectangle(0, 1, p, 1, clrGreen);
552  osd->DrawRectangle(p, 1, ScOsdWidth, 1, clrWhite);
553 }
554 
555 void cSkinCursesDisplayReplay::SetCurrent(const char *Current)
556 {
557  osd->DrawText(0, 2, Current, clrWhite, clrBackground, &Font, Utf8StrLen(Current) + 3);
558 }
559 
560 void cSkinCursesDisplayReplay::SetTotal(const char *Total)
561 {
562  osd->DrawText(ScOsdWidth - Utf8StrLen(Total), 2, Total, clrWhite, clrBackground, &Font);
563 }
564 
565 void cSkinCursesDisplayReplay::SetJump(const char *Jump)
566 {
567  osd->DrawText(ScOsdWidth / 4, 2, Jump, clrWhite, clrBackground, &Font, ScOsdWidth / 2, 0, taCenter);
568 }
569 
571 {
572  if (Text) {
573  osd->SaveRegion(0, 2, ScOsdWidth - 1, 2);
574  osd->DrawText(0, 2, Text, clrMessage[2 * Type], clrMessage[2 * Type + 1], &Font, ScOsdWidth, 0, taCenter);
575  message = true;
576  }
577  else {
578  osd->RestoreRegion();
579  message = false;
580  }
581 }
582 
584 {
585  osd->Flush();
586 }
587 
588 // --- cSkinCursesDisplayVolume ----------------------------------------------
589 
591 private:
593 public:
595  virtual ~cSkinCursesDisplayVolume();
596  virtual void SetVolume(int Current, int Total, bool Mute);
597  virtual void Flush(void);
598  };
599 
601 {
602  osd = new cCursesOsd(0, ScOsdHeight - 1);
603 }
604 
606 {
607  delete osd;
608 }
609 
610 void cSkinCursesDisplayVolume::SetVolume(int Current, int Total, bool Mute)
611 {
612  if (Mute) {
613  osd->DrawRectangle(0, 0, ScOsdWidth - 1, 0, clrTransparent);
614  osd->DrawText(0, 0, tr("Key$Mute"), clrGreen, clrBackground, &Font);
615  }
616  else {
617  // TRANSLATORS: note the trailing blank!
618  const char *Prompt = tr("Volume ");
619  int l = Utf8StrLen(Prompt);
620  int p = (ScOsdWidth - l) * Current / Total;
621  osd->DrawText(0, 0, Prompt, clrGreen, clrBackground, &Font);
622  osd->DrawRectangle(l, 0, l + p - 1, 0, clrGreen);
623  osd->DrawRectangle(l + p, 0, ScOsdWidth - 1, 0, clrWhite);
624  }
625 }
626 
628 {
629  osd->Flush();
630 }
631 
632 // --- cSkinCursesDisplayTracks ----------------------------------------------
633 
635 private:
639  void SetItem(const char *Text, int Index, bool Current);
640 public:
641  cSkinCursesDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
642  virtual ~cSkinCursesDisplayTracks();
643  virtual void SetTrack(int Index, const char * const *Tracks);
644  virtual void SetAudioChannel(int AudioChannel) {}
645  virtual void Flush(void);
646  };
647 
648 cSkinCursesDisplayTracks::cSkinCursesDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
649 {
650  currentIndex = -1;
651  itemsWidth = Font.Width(Title);
652  for (int i = 0; i < NumTracks; i++)
653  itemsWidth = max(itemsWidth, Font.Width(Tracks[i]));
655  osd = new cCursesOsd(0, 0);
657  osd->DrawText(0, 0, Title, clrBlack, clrCyan, &Font, itemsWidth);
658  for (int i = 0; i < NumTracks; i++)
659  SetItem(Tracks[i], i, false);
660 }
661 
663 {
664  delete osd;
665 }
666 
667 void cSkinCursesDisplayTracks::SetItem(const char *Text, int Index, bool Current)
668 {
669  int y = 1 + Index;
670  int ColorFg, ColorBg;
671  if (Current) {
672  ColorFg = clrBlack;
673  ColorBg = clrCyan;
674  currentIndex = Index;
675  }
676  else {
677  ColorFg = clrWhite;
678  ColorBg = clrBackground;
679  }
680  osd->DrawText(0, y, Text, ColorFg, ColorBg, &Font, itemsWidth);
681 }
682 
683 void cSkinCursesDisplayTracks::SetTrack(int Index, const char * const *Tracks)
684 {
685  if (currentIndex >= 0)
686  SetItem(Tracks[currentIndex], currentIndex, false);
687  SetItem(Tracks[Index], Index, true);
688 }
689 
691 {
692  osd->Flush();
693 }
694 
695 // --- cSkinCursesDisplayMessage ---------------------------------------------
696 
698 private:
700 public:
702  virtual ~cSkinCursesDisplayMessage();
703  virtual void SetMessage(eMessageType Type, const char *Text);
704  virtual void Flush(void);
705  };
706 
708 {
709  osd = new cCursesOsd(0, ScOsdHeight - 1);
710 }
711 
713 {
714  delete osd;
715 }
716 
718 {
719  osd->DrawText(0, 0, Text, clrMessage[2 * Type], clrMessage[2 * Type + 1], &Font, ScOsdWidth, 0, taCenter);
720 }
721 
723 {
724  osd->Flush();
725 }
726 
727 // --- cSkinCurses -----------------------------------------------------------
728 
729 class cSkinCurses : public cSkin {
730 public:
731  cSkinCurses(void);
732  virtual const char *Description(void);
733  virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
734  virtual cSkinDisplayMenu *DisplayMenu(void);
735  virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
736  virtual cSkinDisplayVolume *DisplayVolume(void);
737  virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
738  virtual cSkinDisplayMessage *DisplayMessage(void);
739  };
740 
742 :cSkin("curses")
743 {
744 }
745 
746 const char *cSkinCurses::Description(void)
747 {
748  return tr("Text mode");
749 }
750 
752 {
753  return new cSkinCursesDisplayChannel(WithInfo);
754 }
755 
757 {
758  return new cSkinCursesDisplayMenu;
759 }
760 
762 {
763  return new cSkinCursesDisplayReplay(ModeOnly);
764 }
765 
767 {
768  return new cSkinCursesDisplayVolume;
769 }
770 
771 cSkinDisplayTracks *cSkinCurses::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
772 {
773  return new cSkinCursesDisplayTracks(Title, NumTracks, Tracks);
774 }
775 
777 {
778  return new cSkinCursesDisplayMessage;
779 }
780 
781 // --- cPluginSkinCurses -----------------------------------------------------
782 
783 class cPluginSkinCurses : public cPlugin {
784 private:
785  // Add any member variables or functions you may need here.
786 public:
787  cPluginSkinCurses(void);
788  virtual ~cPluginSkinCurses();
789  virtual const char *Version(void) { return VERSION; }
790  virtual const char *Description(void) { return tr(DESCRIPTION); }
791  virtual const char *CommandLineHelp(void);
792  virtual bool ProcessArgs(int argc, char *argv[]);
793  virtual bool Initialize(void);
794  virtual bool Start(void);
795  virtual void Housekeeping(void);
796  virtual const char *MainMenuEntry(void) { return tr(MAINMENUENTRY); }
797  virtual cOsdObject *MainMenuAction(void);
798  virtual cMenuSetupPage *SetupMenu(void);
799  virtual bool SetupParse(const char *Name, const char *Value);
800  };
801 
803 {
804  // Initialize any member variables here.
805  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
806  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
807 }
808 
810 {
811  // Clean up after yourself!
812  endwin();
813 }
814 
816 {
817  // Return a string that describes all known command line options.
818  return NULL;
819 }
820 
821 bool cPluginSkinCurses::ProcessArgs(int argc, char *argv[])
822 {
823  // Implement command line argument processing here if applicable.
824  return true;
825 }
826 
828 {
829  // Initialize any background activities the plugin shall perform.
830  WINDOW *w = initscr();
831  if (w) {
832  ScOsdWidth = w->_maxx - w->_begx + 1;
833  ScOsdHeight = w->_maxy - w->_begy + 1;
834  return true;
835  }
836  return false;
837 }
838 
840 {
841  // Start any background activities the plugin shall perform.
842  cSkin *Skin = new cSkinCurses;
843  // This skin is normally used for debugging, so let's make it the current one:
844  Skins.SetCurrent(Skin->Name());
845  return true;
846 }
847 
849 {
850  // Perform any cleanup or other regular tasks.
851 }
852 
854 {
855  // Perform the action when selected from the main VDR menu.
856  return NULL;
857 }
858 
860 {
861  // Return a setup menu in case the plugin supports one.
862  return NULL;
863 }
864 
865 bool cPluginSkinCurses::SetupParse(const char *Name, const char *Value)
866 {
867  // Parse your own setup parameters and store their values.
868  return false;
869 }
870 
871 VDRPLUGINCREATOR(cPluginSkinCurses); // Don't touch this!
#define clrRed
Definition: skincurses.c:37
int Shown(void)
Definition: osd.h:1038
virtual void Scroll(bool Up, bool Page)
If this menu contains a text area that can be scrolled, this function will be called to actually scro...
Definition: skins.c:107
static int AvgCharWidth(void)
Returns the average width of a character in pixel (just a raw estimate).
Definition: skins.h:33
virtual cSkinDisplayVolume * DisplayVolume(void)
Creates and returns a new object for displaying the current volume.
Definition: skincurses.c:766
Definition: epg.h:71
eMessageType
Definition: skins.h:24
virtual void SetTrack(int Index, const char *const *Tracks)
< This class implements the track display.
Definition: skincurses.c:683
virtual ~cSkinCursesDisplayMenu()
Definition: skincurses.c:296
Definition: osd.h:454
#define clrWhite
Definition: skincurses.c:43
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: skincurses.c:136
bool isempty(const char *s)
Definition: tools.c:297
VDRPLUGINCREATOR(cPluginSkinCurses)
int Utf8StrLen(const char *s)
Returns the number of UTF-8 symbols formed by the given string of character bytes.
Definition: tools.c:833
cCursesOsd(int Left, int Top)
Definition: skincurses.c:76
virtual bool SetupParse(const char *Name, const char *Value)
Definition: skincurses.c:865
virtual ~cPluginSkinCurses()
Definition: skincurses.c:809
time_t Start(void) const
Definition: recording.h:128
static int clrMessage[]
Definition: skincurses.c:45
static cString String(void)
Returns a localized string of the form "Disk nn% - hh:mm free".
Definition: videodir.c:220
const cRecordingInfo * Info(void) const
Definition: recording.h:149
time_t Vps(void) const
Definition: epg.h:109
void DrawScrollbar(int Total, int Offset, int Shown, int Top, int Height, bool CanScrollUp, bool CanScrollDown)
Definition: skincurses.c:301
const char * Name(void)
Definition: plugin.h:34
const char * ShortText(void) const
Definition: recording.h:86
virtual void DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const
Definition: skincurses.c:27
static const char * VERSION
Definition: skincurses.c:15
static const char * ContentToString(uchar Content)
Definition: epg.c:260
cString GetParentalRatingString(void) const
Definition: epg.c:402
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable)
Sets the item at the given Index to Text.
Definition: skincurses.c:375
static int ScOsdHeight
Definition: skincurses.c:57
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1080
void Set(cOsd *Osd, int Left, int Top, int Width, int Height, const char *Text, const cFont *Font, tColor ColorFg, tColor ColorBg)
Definition: osd.c:2137
Definition: plugin.h:20
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skincurses.c:722
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
virtual const char * Description(void)
Returns a user visible, single line description of this skin, which may consist of arbitrary text and...
Definition: skincurses.c:746
uchar Contents(int i=0) const
Definition: epg.h:104
eMenuCategory MenuCategory(void) const
Returns the menu category, set by a previous call to SetMenuCategory().
Definition: skins.h:165
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skincurses.c:487
virtual void SetChannel(const cChannel *Channel, int Number)
Sets the current channel to Channel.
Definition: skincurses.c:219
T max(T a, T b)
Definition: tools.h:55
virtual void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
Draws a filled rectangle defined by the upper left (x1, y1) and lower right (x2, y2) corners with the...
Definition: osd.c:1952
cSkinCursesDisplayReplay(bool ModeOnly)
Definition: skincurses.c:515
virtual const char * CommandLineHelp(void)
Definition: skincurses.c:815
static cSkinDisplay * Current(void)
Returns the currently active cSkinDisplay.
Definition: skins.h:48
const char * Name(void)
Definition: skins.h:389
time_t StartTime(void) const
Definition: epg.h:106
int ShowReplayMode
Definition: config.h:340
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skincurses.c:583
T min(T a, T b)
Definition: tools.h:54
cString ChannelString(const cChannel *Channel, int Number)
Definition: channels.c:1147
virtual cSkinDisplayMenu * DisplayMenu(void)
Creates and returns a new object for displaying a menu.
Definition: skincurses.c:756
virtual void SetTitle(const char *Title)
Sets the title of the recording.
Definition: skincurses.c:527
#define clrTransparent
Definition: skincurses.c:35
virtual void Flush(void)
Actually commits all data to the OSD hardware.
Definition: osd.c:1982
Definition: osd.h:158
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skincurses.c:252
virtual bool ProcessArgs(int argc, char *argv[])
Definition: skincurses.c:821
Definition: osd.h:169
int Height(void)
Definition: osd.h:1035
#define clrBackground
Definition: skincurses.c:34
virtual ~cSkinCursesDisplayVolume()
Definition: skincurses.c:605
virtual cOsdObject * MainMenuAction(void)
Definition: skincurses.c:853
cPluginSkinCurses(void)
Definition: skincurses.c:802
virtual cMenuSetupPage * SetupMenu(void)
Definition: skincurses.c:859
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skincurses.c:367
static int ScOsdWidth
Definition: skincurses.c:56
void SetColor(int colorFg, int colorBg=clrBackground)
Definition: skincurses.c:99
virtual const char * MainMenuEntry(void)
Definition: skincurses.c:796
virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const
Draws the given text into the Bitmap at position (x, y) with the given colors.
Definition: skincurses.c:26
virtual const char * Version(void)
Definition: skincurses.c:789
Definition: osd.h:161
cString GetVpsString(void) const
Definition: epg.c:424
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skincurses.c:690
virtual const char * Description(void)
Definition: skincurses.c:790
virtual int Height(void) const =0
Returns the height of this font in pixel (all characters have the same height).
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: skincurses.c:117
WINDOW * window
Definition: skincurses.c:62
int ParentalRating(void) const
Definition: epg.h:105
int Top(void)
Definition: osd.h:801
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: skincurses.c:555
virtual cSkinDisplayChannel * DisplayChannel(bool WithInfo)
Creates and returns a new object for displaying the current channel.
Definition: skincurses.c:751
virtual void SetMessage(eMessageType Type, const char *Text)
< This class implements a simple message display.
Definition: skincurses.c:717
virtual bool Initialize(void)
Definition: skincurses.c:827
cTextScroller textScroller
Definition: skins.h:155
#define clrBlack
Definition: skincurses.c:36
virtual int Height(void) const
Returns the height of this font in pixel (all characters have the same height).
Definition: skincurses.c:25
#define trNOOP(s)
Definition: i18n.h:88
WINDOW * savedRegion
Definition: skincurses.c:61
void SetTextScrollbar(void)
Definition: skincurses.c:317
cSkinCursesDisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
Definition: skincurses.c:648
int ChannelInfoPos
Definition: config.h:316
virtual void SetAudioChannel(int AudioChannel)
Sets the audio channel indicator.
Definition: skincurses.c:644
Definition: osd.h:162
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skincurses.c:627
Definition: osd.h:164
cSkinCursesDisplayChannel(bool WithInfo)
Definition: skincurses.c:205
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: skincurses.c:174
virtual void SetText(const char *Text, bool FixedFont)
Sets the Text that shall be displayed, using the entire central area of the menu. ...
Definition: skincurses.c:481
cSkinCurses(void)
Definition: skincurses.c:741
static bool HasChanged(int &State)
Returns true if the usage of the video disk space has changed since the last call to this function wi...
Definition: videodir.c:197
#define clrGreen
Definition: skincurses.c:38
int Tab(int n)
Returns the offset of the given tab from the left border of the item display area.
Definition: skins.h:156
virtual ~cSkinCursesDisplayReplay()
Definition: skincurses.c:522
static const cCursesFont Font
Definition: skincurses.c:30
The cOsd class is the interface to the "On Screen Display".
Definition: osd.h:720
int Top(void)
Definition: osd.h:1033
Definition: skins.h:94
static const char * DESCRIPTION
Definition: skincurses.c:16
cSetup Setup
Definition: config.c:373
void SetItem(const char *Text, int Index, bool Current)
Definition: skincurses.c:667
bool CanScroll(void)
Definition: osd.h:1039
virtual ~cSkinCursesDisplayChannel()
Definition: skincurses.c:214
cString DayDateTime(time_t t)
Converts the given time to a string of the form "www dd.mm. hh:mm".
Definition: tools.c:1145
virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width=0, int Height=0, int Alignment=taDefault)
Draws the given string at coordinates (x, y) with the given foreground and background color and font...
Definition: osd.c:1942
virtual void SetEvent(const cEvent *Event)
Sets the Event that shall be displayed, using the entire central area of the menu.
Definition: skincurses.c:404
Definition: skins.h:370
virtual void Housekeeping(void)
Definition: skincurses.c:848
virtual int MaxItems(void)
Returns the maximum number of items the menu can display.
Definition: skincurses.c:329
bool CanScrollUp(void)
Definition: osd.h:1040
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: skincurses.c:352
void SetEditableWidth(int Width)
If an item is set through a call to cSkinDisplayMenu::SetItem(), this function shall be called to set...
Definition: skins.h:36
int Height(void)
Definition: osd.h:803
const char * Title(void) const
Definition: epg.h:100
virtual void RestoreRegion(void)
Restores the region previously saved by a call to SaveRegion().
Definition: skincurses.c:127
cString GetEndTimeString(void) const
Definition: epg.c:419
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skincurses.c:239
virtual void Clear(void)
Clears the entire central area of the menu.
Definition: skincurses.c:334
virtual void SetEvents(const cEvent *Present, const cEvent *Following)
Sets the Present and Following EPG events.
Definition: skincurses.c:225
virtual void SetMessage(eMessageType Type, const char *Text)
Sets a one line message Text, with the given Type.
Definition: skincurses.c:570
virtual void SetTitle(const char *Title)
Sets the title of this menu to Title.
Definition: skincurses.c:346
void Reset(void)
Definition: osd.c:2154
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: skincurses.c:560
virtual int Width(uint c) const
Returns the width of the given character in pixel.
Definition: skincurses.c:23
int Width(void)
Definition: osd.h:802
virtual void SetJump(const char *Jump)
Sets the prompt that allows the user to enter a jump point.
Definition: skincurses.c:565
virtual void SetVolume(int Current, int Total, bool Mute)
< This class implements the volume/mute display.
Definition: skincurses.c:610
Definition: osd.h:159
#define tr(s)
Definition: i18n.h:85
virtual int Width(const char *s) const
Returns the width of the given string in pixel.
Definition: skincurses.c:24
int Left(void)
Definition: osd.h:800
cString GetTimeString(void) const
Definition: epg.c:414
const cEvent * GetEvent(void) const
Definition: recording.h:84
const char * Description(void) const
Definition: recording.h:87
const char * Name(void) const
Returns the full name of the recording (without the video directory.
Definition: recording.h:142
cString TimeString(time_t t)
Converts the given time to a string of the form "hh:mm".
Definition: tools.c:1186
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: skincurses.c:323
#define clrBlue
Definition: skincurses.c:40
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: skincurses.c:532
const char * Title(void) const
Definition: recording.h:85
virtual const cFont * GetTextAreaFont(bool FixedFont) const
Returns a pointer to the font which is used to display text with SetText().
Definition: skincurses.c:285
const char * Description(void) const
Definition: epg.h:102
Definition: osd.h:160
virtual int Width(uint c) const =0
Returns the width of the given character in pixel.
#define clrCyan
Definition: skincurses.c:42
virtual void Flush(void)
Actually commits all data to the OSD hardware.
Definition: skincurses.c:184
virtual void RestoreRegion(void)
Restores the region previously saved by a call to SaveRegion().
Definition: osd.c:1871
virtual void SetRecording(const cRecording *Recording)
Sets the Recording that shall be displayed, using the entire central area of the menu.
Definition: skincurses.c:443
const char * ChannelName(void) const
Definition: recording.h:83
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: skincurses.c:399
#define clrYellow
Definition: skincurses.c:39
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: skincurses.c:548
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
int colorPairs[MaxColorPairs]
Definition: skincurses.c:64
cString GetDateString(void) const
Definition: epg.c:409
const char * ShortText(void) const
Definition: epg.h:101
static const char * MAINMENUENTRY
Definition: skincurses.c:17
virtual void SaveRegion(int x1, int y1, int x2, int y2)
Saves the region defined by the given coordinates for later restoration through RestoreRegion().
Definition: osd.c:1855
bool SetCurrent(const char *Name=NULL)
Sets the current skin to the one indicated by name.
Definition: skins.c:231
Definition: font.h:37
virtual bool Start(void)
Definition: skincurses.c:839
virtual cSkinDisplayMessage * DisplayMessage(void)
Creates and returns a new object for displaying a message.
Definition: skincurses.c:776
int Offset(void)
Definition: osd.h:1037
Definition: tools.h:168
virtual cSkinDisplayTracks * DisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
Creates and returns a new object for displaying the available tracks.
Definition: skincurses.c:771
cString DateString(time_t t)
Converts the given time to a string of the form "www dd.mm.yyyy".
Definition: tools.c:1166
virtual ~cSkinCursesDisplayTracks()
Definition: skincurses.c:662
virtual ~cSkinCursesDisplayMessage()
Definition: skincurses.c:712
virtual cSkinDisplayReplay * DisplayReplay(bool ModeOnly)
Creates and returns a new object for displaying replay progress.
Definition: skincurses.c:761
virtual ~cCursesOsd()
Definition: skincurses.c:89
uint32_t tColor
Definition: font.h:29
bool CanScrollDown(void)
Definition: osd.h:1041
cSkins Skins
Definition: skins.c:219
int Total(void)
Definition: osd.h:1036