vdr  1.7.31
osddemo.c
Go to the documentation of this file.
1 /*
2  * osddemo.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: osddemo.c 2.6 2012/03/13 15:17:33 kls Exp $
7  */
8 
9 #include <vdr/osd.h>
10 #include <vdr/plugin.h>
11 
12 static const char *VERSION = "0.2.3";
13 static const char *DESCRIPTION = "Demo of arbitrary OSD setup";
14 static const char *MAINMENUENTRY = "Osd Demo";
15 
16 // --- cLineGame -------------------------------------------------------------
17 
18 class cLineGame : public cOsdObject {
19 private:
21  int x;
22  int y;
24 public:
25  cLineGame(void);
26  virtual ~cLineGame();
27  virtual void Show(void);
28  virtual eOSState ProcessKey(eKeys Key);
29  };
30 
32 {
33  osd = NULL;
34  x = y = 50;
35  color = clrRed;
36 }
37 
39 {
40  delete osd;
41 }
42 
43 void cLineGame::Show(void)
44 {
45  osd = cOsdProvider::NewOsd(100, 50, 50);
46  if (osd) {
47  tArea Area = { 0, 0, 99, 199, 4 };
48  osd->SetAreas(&Area, 1);
49  osd->DrawRectangle(0, 0, 99, 199, clrGray50);
50  osd->Flush();
51  }
52 }
53 
55 {
56  eOSState state = cOsdObject::ProcessKey(Key);
57  if (state == osUnknown) {
58  switch (Key & ~k_Repeat) {
59  case kUp: if (y > 0) y--; break;
60  case kDown: if (y < 196) y++; break;
61  case kLeft: if (x > 0) x--; break;
62  case kRight: if (x < 96) x++; break;
63  case kRed: color = clrRed; break;
64  case kGreen: color = clrGreen; break;
65  case kYellow: color = clrYellow; break;
66  case kBlue: color = clrBlue; break;
67  case kOk: return osEnd;
68  default: return state;
69  }
70  osd->DrawRectangle(x, y, x + 3, y + 3, color);
71  osd->Flush();
72  state = osContinue;
73  }
74  return state;
75 }
76 
77 // --- cTrueColorDemo --------------------------------------------------------
78 
79 class cTrueColorDemo : public cOsdObject, public cThread {
80 private:
84  bool clockwise;
87  virtual void Action(void);
88  cPixmap *CreateTextPixmap(const char *s, int Line, int Layer, tColor ColorFg, tColor ColorBg, const cFont *Font);
89 public:
90  cTrueColorDemo(void);
91  virtual ~cTrueColorDemo();
92  virtual void Show(void);
93  virtual eOSState ProcessKey(eKeys Key);
94  };
95 
97 {
98  osd = NULL;
99  clockwise = true;
100  destroyablePixmap = NULL;
101  toggleablePixmap = NULL;
102 }
103 
105 {
106  Cancel(3);
107  delete osd;
108 }
109 
110 cPixmap *cTrueColorDemo::CreateTextPixmap(const char *s, int Line, int Layer, tColor ColorFg, tColor ColorBg, const cFont *Font)
111 {
112  const int h = Font->Height(s);
113  int w = Font->Width(s);
114  cPixmap *Pixmap = osd->CreatePixmap(Layer, cRect((osd->Width() - w) / 2, Line, w, h));
115  if (Pixmap) {
116  Pixmap->Clear();
117  Pixmap->SetAlpha(0);
118  Pixmap->DrawText(cPoint(0, 0), s, ColorFg, ColorBg, Font);
119  }
120  return Pixmap;
121 }
122 
124 {
125  cPixmap *FadeInPixmap = NULL;
126  cPixmap *FadeOutPixmap = NULL;
127  cPixmap *MovePixmap = NULL;
128  cPixmap *NextPixmap = NULL;
129  cPixmap *TilePixmap = NULL;
130  cPixmap *ScrollPixmap = NULL;
131  cPixmap *AnimPixmap = NULL;
134  cFont *LrgFont = cFont::CreateFont(Setup.FontOsd, osd->Height() / 10);
135  int FrameTime = 40; // ms
136  int FadeTime = 1000; // ms
137  int MoveTime = 4000; // ms
138  int TileTime = 6000; // ms
139  int ScrollWaitTime = 1000; // ms
140  int ScrollLineTime = 200; // ms
141  int ScrollTotalTime = 8000; // ms
142  uint64_t Start = 0;
143  uint64_t ScrollStartTime = 0;
144  int ScrollLineNumber = 0;
145  cPoint MoveStart, MoveEnd;
146  cPoint TileStart, TileEnd;
147  cPoint ScrollStart, ScrollEnd;
148  int Line = osd->Height() / 20;
149  int StartLine = Line;
150  cPoint OldCursor;
151  int State = 0;
152  while (Running()) {
153  cPixmap::Lock();
154  bool Animated = false;
155  uint64_t Now = cTimeMs::Now();
156  if (FadeInPixmap) {
157  double t = min(double(Now - Start) / FadeTime, 1.0);
158  int Alpha = t * ALPHA_OPAQUE;
159  FadeInPixmap->SetAlpha(Alpha);
160  if (t >= 1)
161  FadeInPixmap = NULL;
162  Animated = true;
163  }
164  if (FadeOutPixmap) {
165  double t = min(double(Now - Start) / FadeTime, 1.0);
166  int Alpha = ALPHA_OPAQUE - t * ALPHA_OPAQUE;
167  FadeOutPixmap->SetAlpha(Alpha);
168  if (t >= 1)
169  FadeOutPixmap = NULL;
170  Animated = true;
171  }
172  if (MovePixmap) {
173  double t = min(double(Now - Start) / MoveTime, 1.0);
174  int x = MoveStart.X() + t * (MoveEnd.X() - MoveStart.X());
175  int y = MoveStart.Y() + t * (MoveEnd.Y() - MoveStart.Y());
176  cRect r = MovePixmap->ViewPort();
177  r.SetPoint(x, y);
178  MovePixmap->SetViewPort(r);
179  if (t >= 1)
180  MovePixmap = NULL;
181  Animated = true;
182  }
183  if (TilePixmap) {
184  double t = min(double(Now - Start) / TileTime, 1.0);
185  int x = TileStart.X() + t * (TileEnd.X() - TileStart.X());
186  int y = TileStart.Y() + t * (TileEnd.Y() - TileStart.Y());
187  TilePixmap->SetDrawPortPoint(cPoint(x, y));
188  if (t >= 1) {
189  destroyablePixmap = TilePixmap;
190  TilePixmap = NULL;
191  }
192  Animated = true;
193  }
194  if (ScrollPixmap) {
195  if (int(Now - Start) > ScrollWaitTime) {
196  if (ScrollStartTime) {
197  double t = min(double(Now - ScrollStartTime) / ScrollLineTime, 1.0);
198  int x = ScrollStart.X() + t * (ScrollEnd.X() - ScrollStart.X());
199  int y = ScrollStart.Y() + t * (ScrollEnd.Y() - ScrollStart.Y());
200  ScrollPixmap->SetDrawPortPoint(cPoint(x, y));
201  if (t >= 1) {
202  if (int(Now - Start) < ScrollTotalTime) {
203  cRect r = ScrollPixmap->DrawPort();
204  r.SetPoint(-r.X(), -r.Y());
205  ScrollPixmap->Pan(cPoint(0, 0), r);
206  cString s = cString::sprintf("Line %d", ++ScrollLineNumber);
207  ScrollPixmap->DrawRectangle(cRect(0, ScrollPixmap->ViewPort().Height(), ScrollPixmap->DrawPort().Width(), ScrollPixmap->DrawPort().Height()), clrTransparent);
208  ScrollPixmap->DrawText(cPoint(0, ScrollPixmap->ViewPort().Height()), s, clrYellow, clrTransparent, OsdFont);
209  ScrollStartTime = Now;
210  }
211  else {
212  FadeOutPixmap = ScrollPixmap;
213  ScrollPixmap = NULL;
214  Start = cTimeMs::Now();
215  }
216  }
217  }
218  else
219  ScrollStartTime = Now;
220  }
221  Animated = true;
222  }
223  if (AnimPixmap) {
224  int d = AnimPixmap->ViewPort().Height();
225  if (clockwise)
226  d = -d;
227  cPoint p = AnimPixmap->DrawPort().Point().Shifted(0, d);
228  if (clockwise && p.Y() <= -AnimPixmap->DrawPort().Height())
229  p.SetY(0);
230  else if (!clockwise && p.Y() > 0)
231  p.SetY(-(AnimPixmap->DrawPort().Height() - AnimPixmap->ViewPort().Height()));
232  AnimPixmap->SetDrawPortPoint(p);
233  }
234  if (!Animated) {
235  switch (State) {
236  case 0: {
237  FadeInPixmap = CreateTextPixmap("VDR", Line, 1, clrYellow, clrTransparent, LrgFont);
238  if (FadeInPixmap)
239  Line += FadeInPixmap->DrawPort().Height();
240  Start = cTimeMs::Now();
241  State++;
242  }
243  break;
244  case 1: {
245  FadeInPixmap = CreateTextPixmap("Video Disk Recorder", Line, 3, clrYellow, clrTransparent, OsdFont);
246  if (FadeInPixmap)
247  Line += FadeInPixmap->DrawPort().Height();
248  Start = cTimeMs::Now();
249  State++;
250  }
251  break;
252  case 2: {
253  FadeInPixmap = CreateTextPixmap("True Color OSD Demo", Line, 1, clrYellow, clrTransparent, OsdFont);
254  if (FadeInPixmap)
255  Line += FadeInPixmap->DrawPort().Height();
256  Start = cTimeMs::Now();
257  State++;
258  }
259  break;
260  case 3: {
261  NextPixmap = CreateTextPixmap("Millions of colors", Line, 1, clrYellow, clrTransparent, LrgFont);
262  if (NextPixmap) {
263  FadeInPixmap = NextPixmap;
264  Start = cTimeMs::Now();
265  StartLine = Line;
266  Line += NextPixmap->DrawPort().Height();
267  }
268  State++;
269  }
270  break;
271  case 4: {
272  Line += osd->Height() / 10;
273  int w = osd->Width() / 2;
274  int h = osd->Height() - Line - osd->Height() / 10;
275  cImage Image(cSize(w, h));
276  for (int y = 0; y < h; y++) {
277  for (int x = 0; x < w; x++)
278  Image.SetPixel(cPoint(x, y), HsvToColor(360 * double(x) / w, 1 - double(y) / h, 1) | 0xDF000000);
279  }
280  if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, Line, w, h))) {
281  Pixmap->DrawImage(cPoint(0, 0), Image);
282  toggleablePixmap = Pixmap;
283  }
284  State++;
285  }
286  break;
287  case 5: {
288  if (NextPixmap) {
289  MovePixmap = NextPixmap;
290  MoveStart = MovePixmap->ViewPort().Point();
291  MoveEnd.Set(osd->Width() - MovePixmap->ViewPort().Width(), osd->Height() - MovePixmap->ViewPort().Height());
292  Start = cTimeMs::Now();
293  }
294  State++;
295  }
296  break;
297  case 6: {
298  TilePixmap = CreateTextPixmap("Tiled Pixmaps", StartLine, 1, clrRed, clrWhite, OsdFont);
299  if (TilePixmap) {
300  TilePixmap->SetViewPort(TilePixmap->ViewPort().Grown(TilePixmap->DrawPort().Width(), TilePixmap->DrawPort().Height()));
301  TilePixmap->SetAlpha(200);
302  TilePixmap->SetTile(true);
303  TileStart = TilePixmap->DrawPort().Point();
304  TileEnd = TileStart.Shifted(TilePixmap->ViewPort().Width(), TilePixmap->ViewPort().Height());
305  MovePixmap = TilePixmap;
306  MoveStart = MovePixmap->ViewPort().Point();
307  MoveEnd.Set(10, osd->Height() - MovePixmap->ViewPort().Height() - 10);
308  Start = cTimeMs::Now();
309  }
310  State++;
311  }
312  break;
313  case 7: {
314  const char *Text = "Scrolling Pixmaps";
315  int w = OsdFont->Width(Text);
316  int h = OsdFont->Height();
317  if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, StartLine, w, 2 * h), cRect(0, 0, w, 3 * h))) {
318  Pixmap->Clear();
319  Pixmap->DrawText(cPoint(0, 0), Text, clrYellow, clrTransparent, OsdFont);
320  cString s = cString::sprintf("Line %d", ++ScrollLineNumber);
321  Pixmap->DrawText(cPoint(0, Pixmap->ViewPort().Height()), s, clrYellow, clrTransparent, OsdFont);
322  ScrollPixmap = Pixmap;
323  ScrollStart.Set(0, 0);
324  ScrollEnd.Set(0, -h);
325  Start = cTimeMs::Now();
326  }
327  State++;
328  }
329  break;
330  case 8: {
331  const char *Text = "Animation";
332  const int Size = SmlFont->Width(Text) + 10;
333  const int NumDots = 12;
334  const int AnimFrames = NumDots;
335  // Temporarily using pixmap layer 0 to have the text alpha blended:
336  AnimPixmap = osd->CreatePixmap(0, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames));
337  if (AnimPixmap) {
338  AnimPixmap->SetAlpha(0);
339  AnimPixmap->Clear();
340  const int Diameter = Size / 5;
341  int xc = Size / 2 - Diameter / 2;
342  for (int Frame = 0; Frame < AnimFrames; Frame++) {
343  AnimPixmap->DrawEllipse(cRect(0, Frame * Size, Size, Size), 0xDDFFFFFF);
344  int yc = Frame * Size + Size / 2 - Diameter / 2;
345  int Color = 0xFF;
346  int Delta = Color / NumDots / 3;
347  for (int a = 0; a < NumDots; a++) {
348  double t = 2 * M_PI * (Frame + a) / NumDots;
349  int x = xc + ((Size - Diameter) / 2 - 5) * cos(t);
350  int y = yc + ((Size - Diameter) / 2 - 5) * sin(t);
351  AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color));
352  Color -= Delta;
353  }
354  AnimPixmap->DrawText(cPoint(0, Frame * Size), Text, clrBlack, clrTransparent, SmlFont, Size, Size, taCenter);
355  }
356  AnimPixmap->SetLayer(3); // now setting the actual pixmap layer
357  FadeInPixmap = AnimPixmap;
358  LOCK_THREAD;
359  OldCursor = cursor = AnimPixmap->ViewPort().Point();
360  cursorLimits.Set(0, 0, osd->Width(), osd->Height());
363  cursorLimits.Grow(-10, -10);
364  Start = cTimeMs::Now();
365  }
366  State++;
367  }
368  break;
369  case 9: {
370  LOCK_THREAD;
371  if (cursor != OldCursor) {
372  MovePixmap = AnimPixmap;
373  MoveStart = MovePixmap->ViewPort().Point();
374  MoveEnd = OldCursor = cursor;
375  MoveTime = 500;
376  Start = cTimeMs::Now();
377  }
378  }
379  break;
380  }
381  }
382  osd->Flush();
383  cPixmap::Unlock();
384  int Delta = cTimeMs::Now() - Now;
385  if (Delta < FrameTime)
386  cCondWait::SleepMs(FrameTime - Delta);
387  }
388  delete OsdFont;
389  delete SmlFont;
390  delete LrgFont;
391 }
392 
394 {
396  if (osd) {
397  tArea Area = { 0, 0, cOsd::OsdWidth() - 1, cOsd::OsdHeight() - 1, 32 };
398  if (osd->SetAreas(&Area, 1) == oeOk) {
399  osd->DrawRectangle(0, 0, osd->Width() -1 , osd->Height() - 1, clrGray50);
400  osd->Flush();
401  Start();
402  }
403  }
404 }
405 
407 {
408  eOSState state = cOsdObject::ProcessKey(Key);
409  if (state == osUnknown) {
410  LOCK_PIXMAPS;
411  LOCK_THREAD;
412  const int d = 80;
413  switch (Key & ~k_Repeat) {
414  case kUp: cursor.SetY(max(cursorLimits.Top(), cursor.Y() - d)); clockwise = false; break;
415  case kDown: cursor.SetY(min(cursorLimits.Bottom(), cursor.Y() + d)); clockwise = true; break;
416  case kLeft: cursor.SetX(max(cursorLimits.Left(), cursor.X() - d)); clockwise = false; break;
417  case kRight: cursor.SetX(min(cursorLimits.Right(), cursor.X() + d)); clockwise = true; break;
418  case kRed: if (destroyablePixmap) {
420  destroyablePixmap = NULL;
421  }
422  break;
423  case kGreen: if (toggleablePixmap)
425  break;
426  case kOk: return osEnd;
427  default: return state;
428  }
429  state = osContinue;
430  }
431  return state;
432 }
433 
434 // --- cPluginOsddemo --------------------------------------------------------
435 
436 class cPluginOsddemo : public cPlugin {
437 private:
438  // Add any member variables or functions you may need here.
439 public:
440  cPluginOsddemo(void);
441  virtual ~cPluginOsddemo();
442  virtual const char *Version(void) { return VERSION; }
443  virtual const char *Description(void) { return DESCRIPTION; }
444  virtual const char *CommandLineHelp(void);
445  virtual bool ProcessArgs(int argc, char *argv[]);
446  virtual bool Start(void);
447  virtual void Housekeeping(void);
448  virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
449  virtual cOsdObject *MainMenuAction(void);
450  virtual cMenuSetupPage *SetupMenu(void);
451  virtual bool SetupParse(const char *Name, const char *Value);
452  };
453 
455 {
456  // Initialize any member variables here.
457  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
458  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
459 }
460 
462 {
463  // Clean up after yourself!
464 }
465 
467 {
468  // Return a string that describes all known command line options.
469  return NULL;
470 }
471 
472 bool cPluginOsddemo::ProcessArgs(int argc, char *argv[])
473 {
474  // Implement command line argument processing here if applicable.
475  return true;
476 }
477 
479 {
480  // Start any background activities the plugin shall perform.
481  return true;
482 }
483 
485 {
486  // Perform any cleanup or other regular tasks.
487 }
488 
490 {
491  // Perform the action when selected from the main VDR menu.
493  return new cTrueColorDemo;
494  return new cLineGame;
495 }
496 
498 {
499  // Return a setup menu in case the plugin supports one.
500  return NULL;
501 }
502 
503 bool cPluginOsddemo::SetupParse(const char *Name, const char *Value)
504 {
505  // Parse your own setup parameters and store their values.
506  return false;
507 }
508 
509 VDRPLUGINCREATOR(cPluginOsddemo); // Don't touch this!