vdr
1.7.27
|
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!