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