mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Implemented support for TrueColor OSD
This commit is contained in:
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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 <vdr/osd.h>
|
||||
#include <vdr/plugin.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: skincurses.c 2.4 2010/02/28 12:50:13 kls Exp $
|
||||
* $Id: skincurses.c 2.5 2011/01/04 08:52:03 kls Exp $
|
||||
*/
|
||||
|
||||
#include <ncurses.h>
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
virtual int Width(const char *s) const { return s ? Utf8StrLen(s) : 0; }
|
||||
virtual int Height(void) const { return 1; }
|
||||
virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {}
|
||||
virtual void DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {}
|
||||
};
|
||||
|
||||
static const cCursesFont Font;
|
||||
|
Reference in New Issue
Block a user