From 6c7089afd257df3a9033a5bd2f205b8f03eccfaf Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 20 Feb 2011 15:12:56 +0100 Subject: Implemented support for TrueColor OSD --- PLUGINS/src/osddemo/HISTORY | 4 + PLUGINS/src/osddemo/README | 7 + PLUGINS/src/osddemo/osddemo.c | 367 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 375 insertions(+), 3 deletions(-) (limited to 'PLUGINS/src/osddemo') diff --git a/PLUGINS/src/osddemo/HISTORY b/PLUGINS/src/osddemo/HISTORY index 4217cb1e..1270fbf6 100644 --- a/PLUGINS/src/osddemo/HISTORY +++ b/PLUGINS/src/osddemo/HISTORY @@ -21,3 +21,7 @@ VDR Plugin 'osddemo' Revision History 2008-04-13: Version 0.1.3 - Fixed setting the OSD level (thanks to Wolfgang Rohdewald). + +2011-02-20: Version 0.2.0 + +- Added support for TrueColor OSD. diff --git a/PLUGINS/src/osddemo/README b/PLUGINS/src/osddemo/README index 50d36d8c..90ae2952 100644 --- a/PLUGINS/src/osddemo/README +++ b/PLUGINS/src/osddemo/README @@ -19,4 +19,11 @@ Demonstration of how a plugin can have its very own OSD setup. It's a very primitive game that opens a small window in which the user can draw lines with the Up, Down, Left and Right buttons. The color buttons are used to switch color. + +On a VDR system with TrueColor support it displays some of the +possibilities available with the TrueColor OSD. Once the "Animation" +pixmap is displayed, it can be moved around with the Up, Down, Left +and Right buttons. The Red button turns off the "Tiled Pixmaps" +display, and the Green button toggles the color display. + Press Ok to close the window. diff --git a/PLUGINS/src/osddemo/osddemo.c b/PLUGINS/src/osddemo/osddemo.c index 2a9e09a6..87d94638 100644 --- a/PLUGINS/src/osddemo/osddemo.c +++ b/PLUGINS/src/osddemo/osddemo.c @@ -3,12 +3,13 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: osddemo.c 2.1 2008/04/13 12:59:57 kls Exp $ + * $Id: osddemo.c 2.2 2011/02/20 15:06:18 kls Exp $ */ +#include #include -static const char *VERSION = "0.1.3"; +static const char *VERSION = "0.2.0"; static const char *DESCRIPTION = "Demo of arbitrary OSD setup"; static const char *MAINMENUENTRY = "Osd Demo"; @@ -22,7 +23,7 @@ private: tColor color; public: cLineGame(void); - ~cLineGame(); + virtual ~cLineGame(); virtual void Show(void); virtual eOSState ProcessKey(eKeys Key); }; @@ -73,6 +74,364 @@ eOSState cLineGame::ProcessKey(eKeys Key) return state; } +// --- cTrueColorDemo -------------------------------------------------------- + +class cTrueColorDemo : public cOsdObject, public cThread { +private: + cOsd *osd; + cPoint cursor; + cRect cursorLimits; + bool clockwise; + cPixmap *destroyablePixmap; + cPixmap *toggleablePixmap; + virtual void Action(void); + cPixmap *CreateTextPixmap(const char *s, int Line, int Layer, tColor ColorFg, tColor ColorBg, const cFont *Font = NULL); +public: + cTrueColorDemo(void); + virtual ~cTrueColorDemo(); + virtual void Show(void); + virtual eOSState ProcessKey(eKeys Key); + }; + +cTrueColorDemo::cTrueColorDemo(void) +{ + osd = NULL; + clockwise = true; + destroyablePixmap = NULL; + toggleablePixmap = NULL; +} + +cTrueColorDemo::~cTrueColorDemo() +{ + delete osd; +} + +cPixmap *cTrueColorDemo::CreateTextPixmap(const char *s, int Line, int Layer, tColor ColorFg, tColor ColorBg, const cFont *Font) +{ + if (!Font) + Font = cFont::GetFont(fontOsd); + const int h = Font->Height(s); + int w = Font->Width(s); + cPixmap *Pixmap = osd->CreatePixmap(Layer, cRect((osd->Width() - w) / 2, Line, w, h)); + if (Pixmap) { + Pixmap->Clear(); + Pixmap->SetAlpha(0); + Pixmap->DrawText(cPoint(0, 0), s, ColorFg, ColorBg, Font); + } + return Pixmap; +} + +void cTrueColorDemo::Action(void) +{ + cPixmap *FadeInPixmap = NULL; + cPixmap *FadeOutPixmap = NULL; + cPixmap *MovePixmap = NULL; + cPixmap *NextPixmap = NULL; + cPixmap *TilePixmap = NULL; + cPixmap *ScrollPixmap = NULL; + cPixmap *AnimPixmap = NULL; + int FrameTime = 40; // ms + int FadeTime = 1000; // ms + int MoveTime = 4000; // ms + int TileTime = 6000; // ms + int ScrollWaitTime = 1000; // ms + int ScrollLineTime = 200; // ms + int ScrollTotalTime = 8000; // ms + uint64_t Start = 0; + uint64_t ScrollStartTime = 0; + int ScrollLineNumber = 0; + cPoint MoveStart, MoveEnd; + cPoint TileStart, TileEnd; + cPoint ScrollStart, ScrollEnd; + int Line = osd->Height() / 20; + int StartLine = Line; + cPoint OldCursor; + int State = 0; + while (Running()) { + cPixmap::Lock(); + bool Animated = false; + uint64_t Now = cTimeMs::Now(); + if (FadeInPixmap) { + double t = min(double(Now - Start) / FadeTime, 1.0); + int Alpha = t * ALPHA_OPAQUE; + FadeInPixmap->SetAlpha(Alpha); + if (t >= 1) + FadeInPixmap = NULL; + Animated = true; + } + if (FadeOutPixmap) { + double t = min(double(Now - Start) / FadeTime, 1.0); + int Alpha = ALPHA_OPAQUE - t * ALPHA_OPAQUE; + FadeOutPixmap->SetAlpha(Alpha); + if (t >= 1) + FadeOutPixmap = NULL; + Animated = true; + } + if (MovePixmap) { + double t = min(double(Now - Start) / MoveTime, 1.0); + int x = MoveStart.X() + t * (MoveEnd.X() - MoveStart.X()); + int y = MoveStart.Y() + t * (MoveEnd.Y() - MoveStart.Y()); + cRect r = MovePixmap->ViewPort(); + r.SetPoint(x, y); + MovePixmap->SetViewPort(r); + if (t >= 1) + MovePixmap = NULL; + Animated = true; + } + if (TilePixmap) { + double t = min(double(Now - Start) / TileTime, 1.0); + int x = TileStart.X() + t * (TileEnd.X() - TileStart.X()); + int y = TileStart.Y() + t * (TileEnd.Y() - TileStart.Y()); + TilePixmap->SetDrawPortPoint(cPoint(x, y)); + if (t >= 1) { + destroyablePixmap = TilePixmap; + TilePixmap = NULL; + } + Animated = true; + } + if (ScrollPixmap) { + if (int(Now - Start) > ScrollWaitTime) { + if (ScrollStartTime) { + double t = min(double(Now - ScrollStartTime) / ScrollLineTime, 1.0); + int x = ScrollStart.X() + t * (ScrollEnd.X() - ScrollStart.X()); + int y = ScrollStart.Y() + t * (ScrollEnd.Y() - ScrollStart.Y()); + ScrollPixmap->SetDrawPortPoint(cPoint(x, y)); + if (t >= 1) { + if (int(Now - Start) < ScrollTotalTime) { + cRect r = ScrollPixmap->DrawPort(); + r.SetPoint(-r.X(), -r.Y()); + ScrollPixmap->Pan(cPoint(0, 0), r); + const cFont *Font = cFont::GetFont(fontOsd); + cString s = cString::sprintf("Line %d", ++ScrollLineNumber); + ScrollPixmap->DrawRectangle(cRect(0, ScrollPixmap->ViewPort().Height(), ScrollPixmap->DrawPort().Width(), ScrollPixmap->DrawPort().Height()), clrTransparent); + ScrollPixmap->DrawText(cPoint(0, ScrollPixmap->ViewPort().Height()), s, clrYellow, clrTransparent, Font); + ScrollStartTime = Now; + } + else { + FadeOutPixmap = ScrollPixmap; + ScrollPixmap = NULL; + Start = cTimeMs::Now(); + } + } + } + else + ScrollStartTime = Now; + } + Animated = true; + } + if (AnimPixmap) { + int d = AnimPixmap->ViewPort().Height(); + if (clockwise) + d = -d; + cPoint p = AnimPixmap->DrawPort().Point().Shifted(0, d); + if (clockwise && p.Y() <= -AnimPixmap->DrawPort().Height()) + p.SetY(0); + else if (!clockwise && p.Y() > 0) + p.SetY(-(AnimPixmap->DrawPort().Height() - AnimPixmap->ViewPort().Height())); + AnimPixmap->SetDrawPortPoint(p); + } + if (!Animated) { + switch (State) { + case 0: { + if (cFont *Font = cFont::CreateFont(DefaultFontOsd, osd->Height() / 10)) { + FadeInPixmap = CreateTextPixmap("VDR", Line, 1, clrYellow, clrTransparent, Font); + if (FadeInPixmap) + Line += FadeInPixmap->DrawPort().Height(); + delete Font; + Start = cTimeMs::Now(); + } + State++; + } + break; + case 1: { + FadeInPixmap = CreateTextPixmap("Video Disk Recorder", Line, 3, clrYellow, clrTransparent); + if (FadeInPixmap) + Line += FadeInPixmap->DrawPort().Height(); + Start = cTimeMs::Now(); + State++; + } + break; + case 2: { + FadeInPixmap = CreateTextPixmap("True Color OSD Demo", Line, 1, clrYellow, clrTransparent); + if (FadeInPixmap) + Line += FadeInPixmap->DrawPort().Height(); + Start = cTimeMs::Now(); + State++; + } + break; + case 3: { + if (cFont *Font = cFont::CreateFont(DefaultFontOsd, osd->Height() / 10)) { + NextPixmap = CreateTextPixmap("Millions of colors", Line, 1, clrYellow, clrTransparent, Font); + if (NextPixmap) { + FadeInPixmap = NextPixmap; + } + Start = cTimeMs::Now(); + StartLine = Line; + Line += NextPixmap->DrawPort().Height(); + } + State++; + } + break; + case 4: { + Line += osd->Height() / 10; + int w = osd->Width() / 2; + int h = osd->Height() - Line - osd->Height() / 10; + cImage Image(cSize(w, h)); + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + Image.SetPixel(cPoint(x, y), HsvToColor(360 * double(x) / w, 1 - double(y) / h, 1) | 0xDF000000); + } + if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, Line, w, h))) { + Pixmap->DrawImage(cPoint(0, 0), Image); + toggleablePixmap = Pixmap; + } + State++; + } + break; + case 5: { + if (NextPixmap) { + MovePixmap = NextPixmap; + MoveStart = MovePixmap->ViewPort().Point(); + MoveEnd.Set(osd->Width() - MovePixmap->ViewPort().Width(), osd->Height() - MovePixmap->ViewPort().Height()); + Start = cTimeMs::Now(); + } + State++; + } + break; + case 6: { + TilePixmap = CreateTextPixmap("Tiled Pixmaps", StartLine, 1, clrRed, clrWhite); + if (TilePixmap) { + TilePixmap->SetViewPort(TilePixmap->ViewPort().Grown(TilePixmap->DrawPort().Width(), TilePixmap->DrawPort().Height())); + TilePixmap->SetAlpha(200); + TilePixmap->SetTile(true); + TileStart = TilePixmap->DrawPort().Point(); + TileEnd = TileStart.Shifted(TilePixmap->ViewPort().Width(), TilePixmap->ViewPort().Height()); + MovePixmap = TilePixmap; + MoveStart = MovePixmap->ViewPort().Point(); + MoveEnd.Set(10, osd->Height() - MovePixmap->ViewPort().Height() - 10); + Start = cTimeMs::Now(); + } + State++; + } + break; + case 7: { + const cFont *Font = cFont::GetFont(fontOsd); + const char *Text = "Scrolling Pixmaps"; + int w = Font->Width(Text); + int h = Font->Height(); + if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, StartLine, w, 2 * h), cRect(0, 0, w, 3 * h))) { + Pixmap->Clear(); + Pixmap->DrawText(cPoint(0, 0), Text, clrYellow, clrTransparent, Font); + cString s = cString::sprintf("Line %d", ++ScrollLineNumber); + Pixmap->DrawText(cPoint(0, Pixmap->ViewPort().Height()), s, clrYellow, clrTransparent, Font); + ScrollPixmap = Pixmap; + ScrollStart.Set(0, 0); + ScrollEnd.Set(0, -h); + Start = cTimeMs::Now(); + } + State++; + } + break; + case 8: { + const cFont *Font = cFont::GetFont(fontSml); + const char *Text = "Animation"; + const int Size = Font->Width(Text) + 10; + const int NumDots = 12; + const int AnimFrames = NumDots; + AnimPixmap = osd->CreatePixmap(3, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames)); + if (AnimPixmap) { + AnimPixmap->SetAlpha(0); + AnimPixmap->Clear(); + const int Diameter = Size / 5; + int xc = Size / 2 - Diameter / 2; + for (int Frame = 0; Frame < AnimFrames; Frame++) { + AnimPixmap->DrawEllipse(cRect(0, Frame * Size, Size, Size), 0xDDFFFFFF); + int yc = Frame * Size + Size / 2 - Diameter / 2; + int Color = 0xFF; + int Delta = Color / NumDots / 3; + for (int a = 0; a < NumDots; a++) { + double t = 2 * M_PI * (Frame + a) / NumDots; + int x = xc + ((Size - Diameter) / 2 - 5) * cos(t); + int y = yc + ((Size - Diameter) / 2 - 5) * sin(t); + AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color)); + Color -= Delta; + } + AnimPixmap->DrawText(cPoint(0, Frame * Size), "Animation", clrBlack, clrTransparent, cFont::GetFont(fontSml), Size, Size, taCenter); + } + FadeInPixmap = AnimPixmap; + LOCK_THREAD; + OldCursor = cursor = AnimPixmap->ViewPort().Point(); + cursorLimits.Set(0, 0, osd->Width(), osd->Height()); + cursorLimits.SetRight(cursorLimits.Right() - Size); + cursorLimits.SetBottom(cursorLimits.Bottom() - Size); + cursorLimits.Grow(-10, -10); + Start = cTimeMs::Now(); + } + State++; + } + break; + case 9: { + LOCK_THREAD; + if (cursor != OldCursor) { + MovePixmap = AnimPixmap; + MoveStart = MovePixmap->ViewPort().Point(); + MoveEnd = OldCursor = cursor; + MoveTime = 500; + Start = cTimeMs::Now(); + } + } + break; + } + } + osd->Flush(); + cPixmap::Unlock(); + int Delta = cTimeMs::Now() - Now; + if (Delta < FrameTime) + cCondWait::SleepMs(FrameTime - Delta); + } +} + +void cTrueColorDemo::Show(void) +{ + osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop(), 50); + if (osd) { + tArea Area = { 0, 0, cOsd::OsdWidth() - 1, cOsd::OsdHeight() - 1, 32 }; + if (osd->SetAreas(&Area, 1) == oeOk) { + osd->DrawRectangle(0, 0, osd->Width() -1 , osd->Height() - 1, clrGray50); + osd->Flush(); + Start(); + } + } +} + +eOSState cTrueColorDemo::ProcessKey(eKeys Key) +{ + eOSState state = cOsdObject::ProcessKey(Key); + if (state == osUnknown) { + LOCK_PIXMAPS; + LOCK_THREAD; + const int d = 80; + switch (Key & ~k_Repeat) { + case kUp: cursor.SetY(max(cursorLimits.Top(), cursor.Y() - d)); clockwise = false; break; + case kDown: cursor.SetY(min(cursorLimits.Bottom(), cursor.Y() + d)); clockwise = true; break; + case kLeft: cursor.SetX(max(cursorLimits.Left(), cursor.X() - d)); clockwise = false; break; + case kRight: cursor.SetX(min(cursorLimits.Right(), cursor.X() + d)); clockwise = true; break; + case kRed: if (destroyablePixmap) { + osd->DestroyPixmap(destroyablePixmap); + destroyablePixmap = NULL; + } + break; + case kGreen: if (toggleablePixmap) + toggleablePixmap->SetLayer(-toggleablePixmap->Layer()); + break; + case kOk: return osEnd; + default: return state; + } + state = osContinue; + } + return state; +} + // --- cPluginOsddemo -------------------------------------------------------- class cPluginOsddemo : public cPlugin { @@ -131,6 +490,8 @@ void cPluginOsddemo::Housekeeping(void) cOsdObject *cPluginOsddemo::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. + if (cOsdProvider::SupportsTrueColor()) + return new cTrueColorDemo; return new cLineGame; } -- cgit v1.2.3