vdr  1.7.27
osddemo.c
Go to the documentation of this file.
00001 /*
00002  * osddemo.c: A plugin for the Video Disk Recorder
00003  *
00004  * See the README file for copyright information and how to reach the author.
00005  *
00006  * $Id: osddemo.c 2.6 2012/03/13 15:17:33 kls Exp $
00007  */
00008 
00009 #include <vdr/osd.h>
00010 #include <vdr/plugin.h>
00011 
00012 static const char *VERSION        = "0.2.3";
00013 static const char *DESCRIPTION    = "Demo of arbitrary OSD setup";
00014 static const char *MAINMENUENTRY  = "Osd Demo";
00015 
00016 // --- cLineGame -------------------------------------------------------------
00017 
00018 class cLineGame : public cOsdObject {
00019 private:
00020   cOsd *osd;
00021   int x;
00022   int y;
00023   tColor color;
00024 public:
00025   cLineGame(void);
00026   virtual ~cLineGame();
00027   virtual void Show(void);
00028   virtual eOSState ProcessKey(eKeys Key);
00029   };
00030 
00031 cLineGame::cLineGame(void)
00032 {
00033   osd = NULL;
00034   x = y = 50;
00035   color = clrRed;
00036 }
00037 
00038 cLineGame::~cLineGame()
00039 {
00040   delete osd;
00041 }
00042 
00043 void cLineGame::Show(void)
00044 {
00045   osd = cOsdProvider::NewOsd(100, 50, 50);
00046   if (osd) {
00047      tArea Area = { 0, 0, 99, 199,  4 };
00048      osd->SetAreas(&Area, 1);
00049      osd->DrawRectangle(0, 0, 99, 199, clrGray50);
00050      osd->Flush();
00051      }
00052 }
00053 
00054 eOSState cLineGame::ProcessKey(eKeys Key)
00055 {
00056   eOSState state = cOsdObject::ProcessKey(Key);
00057   if (state == osUnknown) {
00058      switch (Key & ~k_Repeat) {
00059        case kUp:     if (y > 0)   y--; break;
00060        case kDown:   if (y < 196) y++; break;
00061        case kLeft:   if (x > 0)   x--; break;
00062        case kRight:  if (x < 96)  x++; break;
00063        case kRed:    color = clrRed; break;
00064        case kGreen:  color = clrGreen; break;
00065        case kYellow: color = clrYellow; break;
00066        case kBlue:   color = clrBlue; break;
00067        case kOk:     return osEnd;
00068        default: return state;
00069        }
00070      osd->DrawRectangle(x, y, x + 3, y + 3, color);
00071      osd->Flush();
00072      state = osContinue;
00073      }
00074   return state;
00075 }
00076 
00077 // --- cTrueColorDemo --------------------------------------------------------
00078 
00079 class cTrueColorDemo : public cOsdObject, public cThread {
00080 private:
00081   cOsd *osd;
00082   cPoint cursor;
00083   cRect cursorLimits;
00084   bool clockwise;
00085   cPixmap *destroyablePixmap;
00086   cPixmap *toggleablePixmap;
00087   virtual void Action(void);
00088   cPixmap *CreateTextPixmap(const char *s, int Line, int Layer, tColor ColorFg, tColor ColorBg, const cFont *Font);
00089 public:
00090   cTrueColorDemo(void);
00091   virtual ~cTrueColorDemo();
00092   virtual void Show(void);
00093   virtual eOSState ProcessKey(eKeys Key);
00094   };
00095 
00096 cTrueColorDemo::cTrueColorDemo(void)
00097 {
00098   osd = NULL;
00099   clockwise = true;
00100   destroyablePixmap = NULL;
00101   toggleablePixmap = NULL;
00102 }
00103 
00104 cTrueColorDemo::~cTrueColorDemo()
00105 {
00106   Cancel(3);
00107   delete osd;
00108 }
00109 
00110 cPixmap *cTrueColorDemo::CreateTextPixmap(const char *s, int Line, int Layer, tColor ColorFg, tColor ColorBg, const cFont *Font)
00111 {
00112   const int h = Font->Height(s);
00113   int w = Font->Width(s);
00114   cPixmap *Pixmap = osd->CreatePixmap(Layer, cRect((osd->Width() - w) / 2, Line, w, h));
00115   if (Pixmap) {
00116      Pixmap->Clear();
00117      Pixmap->SetAlpha(0);
00118      Pixmap->DrawText(cPoint(0, 0), s, ColorFg, ColorBg, Font);
00119      }
00120   return Pixmap;
00121 }
00122 
00123 void cTrueColorDemo::Action(void)
00124 {
00125   cPixmap *FadeInPixmap = NULL;
00126   cPixmap *FadeOutPixmap = NULL;
00127   cPixmap *MovePixmap = NULL;
00128   cPixmap *NextPixmap = NULL;
00129   cPixmap *TilePixmap = NULL;
00130   cPixmap *ScrollPixmap = NULL;
00131   cPixmap *AnimPixmap = NULL;
00132   cFont *OsdFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize);
00133   cFont *SmlFont = cFont::CreateFont(Setup.FontSml, Setup.FontSmlSize);
00134   cFont *LrgFont = cFont::CreateFont(Setup.FontOsd, osd->Height() / 10);
00135   int FrameTime = 40; // ms
00136   int FadeTime = 1000; // ms
00137   int MoveTime = 4000; // ms
00138   int TileTime = 6000; // ms
00139   int ScrollWaitTime = 1000; // ms
00140   int ScrollLineTime = 200; // ms
00141   int ScrollTotalTime = 8000; // ms
00142   uint64_t Start = 0;
00143   uint64_t ScrollStartTime = 0;
00144   int ScrollLineNumber = 0;
00145   cPoint MoveStart, MoveEnd;
00146   cPoint TileStart, TileEnd;
00147   cPoint ScrollStart, ScrollEnd;
00148   int Line = osd->Height() / 20;
00149   int StartLine = Line;
00150   cPoint OldCursor;
00151   int State = 0;
00152   while (Running()) {
00153         cPixmap::Lock();
00154         bool Animated = false;
00155         uint64_t Now = cTimeMs::Now();
00156         if (FadeInPixmap) {
00157            double t = min(double(Now - Start) / FadeTime, 1.0);
00158            int Alpha = t * ALPHA_OPAQUE;
00159            FadeInPixmap->SetAlpha(Alpha);
00160            if (t >= 1)
00161               FadeInPixmap = NULL;
00162            Animated = true;
00163            }
00164         if (FadeOutPixmap) {
00165            double t = min(double(Now - Start) / FadeTime, 1.0);
00166            int Alpha = ALPHA_OPAQUE - t * ALPHA_OPAQUE;
00167            FadeOutPixmap->SetAlpha(Alpha);
00168            if (t >= 1)
00169               FadeOutPixmap = NULL;
00170            Animated = true;
00171            }
00172         if (MovePixmap) {
00173            double t = min(double(Now - Start) / MoveTime, 1.0);
00174            int x = MoveStart.X() + t * (MoveEnd.X() - MoveStart.X());
00175            int y = MoveStart.Y() + t * (MoveEnd.Y() - MoveStart.Y());
00176            cRect r = MovePixmap->ViewPort();
00177            r.SetPoint(x, y);
00178            MovePixmap->SetViewPort(r);
00179            if (t >= 1)
00180               MovePixmap = NULL;
00181            Animated = true;
00182            }
00183         if (TilePixmap) {
00184            double t = min(double(Now - Start) / TileTime, 1.0);
00185            int x = TileStart.X() + t * (TileEnd.X() - TileStart.X());
00186            int y = TileStart.Y() + t * (TileEnd.Y() - TileStart.Y());
00187            TilePixmap->SetDrawPortPoint(cPoint(x, y));
00188            if (t >= 1) {
00189               destroyablePixmap = TilePixmap;
00190               TilePixmap = NULL;
00191               }
00192            Animated = true;
00193            }
00194         if (ScrollPixmap) {
00195            if (int(Now - Start) > ScrollWaitTime) {
00196               if (ScrollStartTime) {
00197                  double t = min(double(Now - ScrollStartTime) / ScrollLineTime, 1.0);
00198                  int x = ScrollStart.X() + t * (ScrollEnd.X() - ScrollStart.X());
00199                  int y = ScrollStart.Y() + t * (ScrollEnd.Y() - ScrollStart.Y());
00200                  ScrollPixmap->SetDrawPortPoint(cPoint(x, y));
00201                  if (t >= 1) {
00202                     if (int(Now - Start) < ScrollTotalTime) {
00203                        cRect r = ScrollPixmap->DrawPort();
00204                        r.SetPoint(-r.X(), -r.Y());
00205                        ScrollPixmap->Pan(cPoint(0, 0), r);
00206                        cString s = cString::sprintf("Line %d", ++ScrollLineNumber);
00207                        ScrollPixmap->DrawRectangle(cRect(0, ScrollPixmap->ViewPort().Height(), ScrollPixmap->DrawPort().Width(), ScrollPixmap->DrawPort().Height()), clrTransparent);
00208                        ScrollPixmap->DrawText(cPoint(0, ScrollPixmap->ViewPort().Height()), s, clrYellow, clrTransparent, OsdFont);
00209                        ScrollStartTime = Now;
00210                        }
00211                     else {
00212                        FadeOutPixmap = ScrollPixmap;
00213                        ScrollPixmap = NULL;
00214                        Start = cTimeMs::Now();
00215                        }
00216                     }
00217                  }
00218               else
00219                  ScrollStartTime = Now;
00220               }
00221            Animated = true;
00222            }
00223         if (AnimPixmap) {
00224            int d = AnimPixmap->ViewPort().Height();
00225            if (clockwise)
00226               d = -d;
00227            cPoint p = AnimPixmap->DrawPort().Point().Shifted(0, d);
00228            if (clockwise && p.Y() <= -AnimPixmap->DrawPort().Height())
00229               p.SetY(0);
00230            else if (!clockwise && p.Y() > 0)
00231               p.SetY(-(AnimPixmap->DrawPort().Height() - AnimPixmap->ViewPort().Height()));
00232            AnimPixmap->SetDrawPortPoint(p);
00233            }
00234         if (!Animated) {
00235            switch (State) {
00236              case 0: {
00237                        FadeInPixmap = CreateTextPixmap("VDR", Line, 1, clrYellow, clrTransparent, LrgFont);
00238                        if (FadeInPixmap)
00239                           Line += FadeInPixmap->DrawPort().Height();
00240                        Start = cTimeMs::Now();
00241                        State++;
00242                      }
00243                      break;
00244              case 1: { 
00245                        FadeInPixmap = CreateTextPixmap("Video Disk Recorder", Line, 3, clrYellow, clrTransparent, OsdFont);
00246                        if (FadeInPixmap)
00247                           Line += FadeInPixmap->DrawPort().Height();
00248                        Start = cTimeMs::Now();
00249                        State++;
00250                      }
00251                      break;
00252              case 2: {
00253                        FadeInPixmap = CreateTextPixmap("True Color OSD Demo", Line, 1, clrYellow, clrTransparent, OsdFont);
00254                        if (FadeInPixmap)
00255                           Line += FadeInPixmap->DrawPort().Height();
00256                        Start = cTimeMs::Now();
00257                        State++;
00258                      }
00259                      break;
00260              case 3: {
00261                        NextPixmap = CreateTextPixmap("Millions of colors", Line, 1, clrYellow, clrTransparent, LrgFont);
00262                        if (NextPixmap) {
00263                           FadeInPixmap = NextPixmap;
00264                           Start = cTimeMs::Now();
00265                           StartLine = Line;
00266                           Line += NextPixmap->DrawPort().Height();
00267                           }
00268                        State++;
00269                      }
00270                      break;
00271              case 4: {
00272                        Line += osd->Height() / 10;
00273                        int w = osd->Width() / 2;
00274                        int h = osd->Height() - Line - osd->Height() / 10;
00275                        cImage Image(cSize(w, h));
00276                        for (int y = 0; y < h; y++) {
00277                            for (int x = 0; x < w; x++)
00278                                Image.SetPixel(cPoint(x, y), HsvToColor(360 * double(x) / w, 1 - double(y) / h, 1) | 0xDF000000);
00279                            }
00280                        if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, Line, w, h))) {
00281                           Pixmap->DrawImage(cPoint(0, 0), Image);
00282                           toggleablePixmap = Pixmap;
00283                           }
00284                        State++;
00285                      }
00286                      break;
00287              case 5: {
00288                        if (NextPixmap) {
00289                           MovePixmap = NextPixmap;
00290                           MoveStart = MovePixmap->ViewPort().Point();
00291                           MoveEnd.Set(osd->Width() - MovePixmap->ViewPort().Width(), osd->Height() - MovePixmap->ViewPort().Height());
00292                           Start = cTimeMs::Now();
00293                           }
00294                        State++;
00295                      }
00296                      break;
00297              case 6: {
00298                        TilePixmap = CreateTextPixmap("Tiled Pixmaps", StartLine, 1, clrRed, clrWhite, OsdFont);
00299                        if (TilePixmap) {
00300                           TilePixmap->SetViewPort(TilePixmap->ViewPort().Grown(TilePixmap->DrawPort().Width(), TilePixmap->DrawPort().Height()));
00301                           TilePixmap->SetAlpha(200);
00302                           TilePixmap->SetTile(true);
00303                           TileStart = TilePixmap->DrawPort().Point();
00304                           TileEnd = TileStart.Shifted(TilePixmap->ViewPort().Width(), TilePixmap->ViewPort().Height());
00305                           MovePixmap = TilePixmap;
00306                           MoveStart = MovePixmap->ViewPort().Point();
00307                           MoveEnd.Set(10, osd->Height() - MovePixmap->ViewPort().Height() - 10);
00308                           Start = cTimeMs::Now();
00309                           }
00310                        State++;
00311                      }
00312                      break;
00313              case 7: {
00314                        const char *Text = "Scrolling Pixmaps";
00315                        int w = OsdFont->Width(Text);
00316                        int h = OsdFont->Height();
00317                        if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, StartLine, w, 2 * h), cRect(0, 0, w, 3 * h))) {
00318                           Pixmap->Clear();
00319                           Pixmap->DrawText(cPoint(0, 0), Text, clrYellow, clrTransparent, OsdFont);
00320                           cString s = cString::sprintf("Line %d", ++ScrollLineNumber);
00321                           Pixmap->DrawText(cPoint(0, Pixmap->ViewPort().Height()), s, clrYellow, clrTransparent, OsdFont);
00322                           ScrollPixmap = Pixmap;
00323                           ScrollStart.Set(0, 0);
00324                           ScrollEnd.Set(0, -h);
00325                           Start = cTimeMs::Now();
00326                           }
00327                        State++;
00328                      }
00329                      break;
00330              case 8: {
00331                        const char *Text = "Animation";
00332                        const int Size = SmlFont->Width(Text) + 10;
00333                        const int NumDots = 12;
00334                        const int AnimFrames = NumDots;
00335                        // Temporarily using pixmap layer 0 to have the text alpha blended:
00336                        AnimPixmap = osd->CreatePixmap(0, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames));
00337                        if (AnimPixmap) {
00338                           AnimPixmap->SetAlpha(0);
00339                           AnimPixmap->Clear();
00340                           const int Diameter = Size / 5;
00341                           int xc = Size / 2 - Diameter / 2;
00342                           for (int Frame = 0; Frame < AnimFrames; Frame++) {
00343                               AnimPixmap->DrawEllipse(cRect(0, Frame * Size, Size, Size), 0xDDFFFFFF);
00344                               int yc = Frame * Size + Size / 2 - Diameter / 2;
00345                               int Color = 0xFF;
00346                               int Delta = Color / NumDots / 3;
00347                               for (int a = 0; a < NumDots; a++) {
00348                                   double t = 2 * M_PI * (Frame + a) / NumDots;
00349                                   int x = xc + ((Size - Diameter) / 2 - 5) * cos(t);
00350                                   int y = yc + ((Size - Diameter) / 2 - 5) * sin(t);
00351                                   AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color));
00352                                   Color -= Delta;
00353                                   }
00354                               AnimPixmap->DrawText(cPoint(0, Frame * Size), Text, clrBlack, clrTransparent, SmlFont, Size, Size, taCenter);
00355                               }
00356                           AnimPixmap->SetLayer(3); // now setting the actual pixmap layer
00357                           FadeInPixmap = AnimPixmap;
00358                           LOCK_THREAD;
00359                           OldCursor = cursor = AnimPixmap->ViewPort().Point();
00360                           cursorLimits.Set(0, 0, osd->Width(), osd->Height());
00361                           cursorLimits.SetRight(cursorLimits.Right() - Size);
00362                           cursorLimits.SetBottom(cursorLimits.Bottom() - Size);
00363                           cursorLimits.Grow(-10, -10);
00364                           Start = cTimeMs::Now();
00365                           }
00366                        State++;
00367                      }
00368                      break;
00369              case 9: {
00370                        LOCK_THREAD;
00371                        if (cursor != OldCursor) {
00372                           MovePixmap = AnimPixmap;
00373                           MoveStart = MovePixmap->ViewPort().Point();
00374                           MoveEnd = OldCursor = cursor;
00375                           MoveTime = 500;
00376                           Start = cTimeMs::Now();
00377                           }
00378                      }
00379                      break;
00380              }
00381            }
00382         osd->Flush();
00383         cPixmap::Unlock();
00384         int Delta = cTimeMs::Now() - Now;
00385         if (Delta < FrameTime)
00386            cCondWait::SleepMs(FrameTime - Delta);
00387         }
00388   delete OsdFont;
00389   delete SmlFont;
00390   delete LrgFont;
00391 }
00392 
00393 void cTrueColorDemo::Show(void)
00394 {
00395   osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop(), 50);
00396   if (osd) {
00397      tArea Area = { 0, 0, cOsd::OsdWidth() - 1, cOsd::OsdHeight() - 1,  32 };
00398      if (osd->SetAreas(&Area, 1) == oeOk) {
00399         osd->DrawRectangle(0, 0, osd->Width() -1 , osd->Height() - 1, clrGray50);
00400         osd->Flush();
00401         Start();
00402         }
00403      }
00404 }
00405 
00406 eOSState cTrueColorDemo::ProcessKey(eKeys Key)
00407 {
00408   eOSState state = cOsdObject::ProcessKey(Key);
00409   if (state == osUnknown) {
00410      LOCK_PIXMAPS;
00411      LOCK_THREAD;
00412      const int d = 80;
00413      switch (Key & ~k_Repeat) {
00414        case kUp:     cursor.SetY(max(cursorLimits.Top(),    cursor.Y() - d)); clockwise = false; break;
00415        case kDown:   cursor.SetY(min(cursorLimits.Bottom(), cursor.Y() + d)); clockwise = true; break;
00416        case kLeft:   cursor.SetX(max(cursorLimits.Left(),   cursor.X() - d)); clockwise = false; break;
00417        case kRight:  cursor.SetX(min(cursorLimits.Right(),  cursor.X() + d)); clockwise = true; break;
00418        case kRed:    if (destroyablePixmap) {
00419                         osd->DestroyPixmap(destroyablePixmap);
00420                         destroyablePixmap = NULL;
00421                         }
00422                      break;
00423        case kGreen:  if (toggleablePixmap)
00424                         toggleablePixmap->SetLayer(-toggleablePixmap->Layer());
00425                      break;
00426        case kOk:     return osEnd;
00427        default: return state;
00428        }
00429      state = osContinue;
00430      }
00431   return state;
00432 }
00433 
00434 // --- cPluginOsddemo --------------------------------------------------------
00435 
00436 class cPluginOsddemo : public cPlugin {
00437 private:
00438   // Add any member variables or functions you may need here.
00439 public:
00440   cPluginOsddemo(void);
00441   virtual ~cPluginOsddemo();
00442   virtual const char *Version(void) { return VERSION; }
00443   virtual const char *Description(void) { return DESCRIPTION; }
00444   virtual const char *CommandLineHelp(void);
00445   virtual bool ProcessArgs(int argc, char *argv[]);
00446   virtual bool Start(void);
00447   virtual void Housekeeping(void);
00448   virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
00449   virtual cOsdObject *MainMenuAction(void);
00450   virtual cMenuSetupPage *SetupMenu(void);
00451   virtual bool SetupParse(const char *Name, const char *Value);
00452   };
00453 
00454 cPluginOsddemo::cPluginOsddemo(void)
00455 {
00456   // Initialize any member variables here.
00457   // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
00458   // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
00459 }
00460 
00461 cPluginOsddemo::~cPluginOsddemo()
00462 {
00463   // Clean up after yourself!
00464 }
00465 
00466 const char *cPluginOsddemo::CommandLineHelp(void)
00467 {
00468   // Return a string that describes all known command line options.
00469   return NULL;
00470 }
00471 
00472 bool cPluginOsddemo::ProcessArgs(int argc, char *argv[])
00473 {
00474   // Implement command line argument processing here if applicable.
00475   return true;
00476 }
00477 
00478 bool cPluginOsddemo::Start(void)
00479 {
00480   // Start any background activities the plugin shall perform.
00481   return true;
00482 }
00483 
00484 void cPluginOsddemo::Housekeeping(void)
00485 {
00486   // Perform any cleanup or other regular tasks.
00487 }
00488 
00489 cOsdObject *cPluginOsddemo::MainMenuAction(void)
00490 {
00491   // Perform the action when selected from the main VDR menu.
00492   if (cOsdProvider::SupportsTrueColor())
00493      return new cTrueColorDemo;
00494   return new cLineGame;
00495 }
00496 
00497 cMenuSetupPage *cPluginOsddemo::SetupMenu(void)
00498 {
00499   // Return a setup menu in case the plugin supports one.
00500   return NULL;
00501 }
00502 
00503 bool cPluginOsddemo::SetupParse(const char *Name, const char *Value)
00504 {
00505   // Parse your own setup parameters and store their values.
00506   return false;
00507 }
00508 
00509 VDRPLUGINCREATOR(cPluginOsddemo); // Don't touch this!