mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Separated the actual DVB hardware OSD implementation from the abstract OSD interface
This commit is contained in:
parent
b527b27708
commit
37f89dca49
7
HISTORY
7
HISTORY
@ -1254,3 +1254,10 @@ Video Disk Recorder Revision History
|
||||
and '-P' used to load plugins. This first step implements the complete "outer"
|
||||
shell for plugins. The "inner" access to VDR data structures will follow.
|
||||
- The VDR version number is now displayed in the title line of the "Setup" menu.
|
||||
|
||||
2002-05-10: Version 1.1.1
|
||||
|
||||
- Separated the actual DVB hardware OSD implementation from the abstract OSD
|
||||
interface. 'osdbase.c/.h' now implements the abstract OSD, while 'dvbosd.c/.h'
|
||||
is the actual implementation for the DVB hardware. This is in preparation for
|
||||
allowing additional kinds of OSD hardware implementations.
|
||||
|
4
Makefile
4
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 1.34 2002/05/09 09:35:05 kls Exp $
|
||||
# $Id: Makefile 1.35 2002/05/10 10:24:46 kls Exp $
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
@ -22,7 +22,7 @@ INCLUDES = -I$(DVBDIR)/ost/include
|
||||
DTVLIB = $(DTVDIR)/libdtv.a
|
||||
|
||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o\
|
||||
menuitems.o osd.o plugin.o recording.o remote.o remux.o ringbuffer.o\
|
||||
menuitems.o osdbase.o osd.o plugin.o recording.o remote.o remux.o ringbuffer.o\
|
||||
svdrp.o thread.o tools.o vdr.o videodir.o
|
||||
|
||||
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||
|
4
config.h
4
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.113 2002/05/05 12:00:00 kls Exp $
|
||||
* $Id: config.h 1.114 2002/05/10 13:48:00 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -19,7 +19,7 @@
|
||||
#include "eit.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "1.1.0"
|
||||
#define VDRVERSION "1.1.1"
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
|
553
dvbosd.c
553
dvbosd.c
@ -1,383 +1,45 @@
|
||||
/*
|
||||
* dvbosd.c: Interface to the DVB On Screen Display
|
||||
* dvbosd.c: Implementation of the DVB On Screen Display
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbosd.c 1.13 2002/04/13 11:34:48 kls Exp $
|
||||
* $Id: dvbosd.c 1.14 2002/05/10 14:22:04 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbosd.h"
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
#include "tools.h"
|
||||
|
||||
// --- cPalette --------------------------------------------------------------
|
||||
|
||||
cPalette::cPalette(int Bpp)
|
||||
{
|
||||
maxColors = 1 << Bpp;
|
||||
numColors = 0;
|
||||
full = false;
|
||||
}
|
||||
|
||||
int cPalette::Index(eDvbColor Color)
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
Color = eDvbColor(((Color & 0xFF) << 24) | ((Color & 0xFF00) << 8) | ((Color & 0xFF0000) >> 8) | ((Color & 0xFF000000) >> 24));
|
||||
#endif
|
||||
for (int i = 0; i < numColors; i++) {
|
||||
if (color[i] == Color) {
|
||||
used[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (!full) {
|
||||
if (numColors < maxColors) {
|
||||
color[numColors++] = Color;
|
||||
used[numColors - 1] = true;
|
||||
fetched[numColors - 1] = false;
|
||||
return numColors - 1;
|
||||
}
|
||||
for (int i = maxColors; --i >= 0; ) {
|
||||
if (!used[i]) {
|
||||
color[i] = Color;
|
||||
used[i] = true;
|
||||
fetched[i] = false;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
esyslog(LOG_ERR, "ERROR: too many different colors used in palette");
|
||||
full = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cPalette::Reset(void)
|
||||
{
|
||||
for (int i = 0; i < numColors; i++)
|
||||
used[i] = false;
|
||||
full = false;
|
||||
}
|
||||
|
||||
const eDvbColor *cPalette::Colors(int &FirstColor, int &LastColor)
|
||||
{
|
||||
for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
|
||||
if (!fetched[FirstColor]) {
|
||||
for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
|
||||
fetched[LastColor] = true;
|
||||
LastColor--; // the loop ended one past the last one!
|
||||
return &color[FirstColor];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
|
||||
{
|
||||
for (int i = 0; i < Palette.numColors; i++) {
|
||||
if (Palette.used[i]) {
|
||||
int n = Index(Palette.color[i]);
|
||||
if (Indexes)
|
||||
(*Indexes)[i] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cBitmap ---------------------------------------------------------------
|
||||
|
||||
cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
|
||||
:cPalette(Bpp)
|
||||
{
|
||||
width = Width;
|
||||
height = Height;
|
||||
clearWithBackground = ClearWithBackground;
|
||||
bitmap = NULL;
|
||||
fontType = fontOsd;
|
||||
font = NULL;
|
||||
if (width > 0 && height > 0) {
|
||||
bitmap = new char[width * height];
|
||||
if (bitmap) {
|
||||
Clean();
|
||||
memset(bitmap, 0x00, width * height);
|
||||
SetFont(fontOsd);
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: can't allocate bitmap!");
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: illegal bitmap parameters (%d, %d)!", width, height);
|
||||
}
|
||||
|
||||
cBitmap::~cBitmap()
|
||||
{
|
||||
delete font;
|
||||
delete bitmap;
|
||||
}
|
||||
|
||||
eDvbFont cBitmap::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = fontType;
|
||||
if (fontType != Font || !font) {
|
||||
delete font;
|
||||
font = new cFont(Font);
|
||||
fontType = Font;
|
||||
}
|
||||
return oldFont;
|
||||
}
|
||||
|
||||
bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
|
||||
{
|
||||
if (dirtyX2 >= 0) {
|
||||
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
|
||||
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
|
||||
//TODO Fix driver (should be able to handle any size bitmaps!)
|
||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
|
||||
if (dirtyX2 < width - 1)
|
||||
dirtyX2++;
|
||||
else if (dirtyX1 > 0)
|
||||
dirtyX1--;
|
||||
}
|
||||
//XXX "... / 2" <==> Bpp???
|
||||
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||
if (dirtyY2 < height - 1)
|
||||
dirtyY2++;
|
||||
else if (dirtyY1 > 0)
|
||||
dirtyY1--;
|
||||
}
|
||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||
if (dirtyX2 < width - 1)
|
||||
dirtyX2++;
|
||||
else if (dirtyX1 > 0)
|
||||
dirtyX1--;
|
||||
}
|
||||
x1 = dirtyX1;
|
||||
y1 = dirtyY1;
|
||||
x2 = dirtyX2;
|
||||
y2 = dirtyY2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cBitmap::Clean(void)
|
||||
{
|
||||
dirtyX1 = width;
|
||||
dirtyY1 = height;
|
||||
dirtyX2 = -1;
|
||||
dirtyY2 = -1;
|
||||
}
|
||||
|
||||
void cBitmap::SetIndex(int x, int y, char Index)
|
||||
{
|
||||
if (bitmap) {
|
||||
if (0 <= x && x < width && 0 <= y && y < height) {
|
||||
if (bitmap[width * y + x] != Index) {
|
||||
bitmap[width * y + x] = Index;
|
||||
if (dirtyX1 > x) dirtyX1 = x;
|
||||
if (dirtyY1 > y) dirtyY1 = y;
|
||||
if (dirtyX2 < x) dirtyX2 = x;
|
||||
if (dirtyY2 < y) dirtyY2 = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
|
||||
{
|
||||
SetIndex(x, y, Index(Color));
|
||||
}
|
||||
|
||||
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
{
|
||||
if (bitmap && Bitmap.bitmap) {
|
||||
tIndexes Indexes;
|
||||
Take(Bitmap, &Indexes);
|
||||
for (int ix = 0; ix < Bitmap.width; ix++) {
|
||||
for (int iy = 0; iy < Bitmap.height; iy++)
|
||||
SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cBitmap::Width(unsigned char c)
|
||||
{
|
||||
return font ? font->Width(c) : -1;
|
||||
}
|
||||
|
||||
int cBitmap::Width(const char *s)
|
||||
{
|
||||
return font ? font->Width(s) : -1;
|
||||
}
|
||||
|
||||
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||
{
|
||||
if (bitmap) {
|
||||
char fg = Index(ColorFg);
|
||||
char bg = Index(ColorBg);
|
||||
int h = font->Height(s);
|
||||
while (s && *s) {
|
||||
const cFont::tCharData *CharData = font->CharData(*s++);
|
||||
if (int(x + CharData->width) > width)
|
||||
break;
|
||||
for (int row = 0; row < h; row++) {
|
||||
cFont::tPixelData PixelData = CharData->lines[row];
|
||||
for (int col = CharData->width; col-- > 0; ) {
|
||||
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
|
||||
PixelData >>= 1;
|
||||
}
|
||||
}
|
||||
x += CharData->width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||
{
|
||||
if (bitmap) {
|
||||
char c = Index(Color);
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
SetIndex(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::Clear(void)
|
||||
{
|
||||
Reset();
|
||||
if (clearWithBackground)
|
||||
Fill(0, 0, width - 1, height - 1, clrBackground);
|
||||
}
|
||||
|
||||
const char *cBitmap::Data(int x, int y)
|
||||
{
|
||||
return &bitmap[y * width + x];
|
||||
}
|
||||
|
||||
// --- cWindow ---------------------------------------------------------------
|
||||
|
||||
class cWindow : public cBitmap {
|
||||
private:
|
||||
int handle; // the index within the OSD's window array (0...MAXNUMWINDOWS - 1)
|
||||
int x0, y0;
|
||||
int bpp;
|
||||
bool tiled;
|
||||
bool shown;
|
||||
public:
|
||||
cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled);
|
||||
int X0(void) { return x0; }
|
||||
int Y0(void) { return y0; }
|
||||
int Bpp(void) { return bpp; }
|
||||
bool Tiled(void) { return tiled; }
|
||||
bool Shown(void) { bool s = shown; shown = true; return s; }
|
||||
int Handle(void) { return handle; }
|
||||
bool Contains(int x, int y);
|
||||
void Relocate(int x, int y);
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||
const char *Data(int x, int y);
|
||||
};
|
||||
|
||||
cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||
:cBitmap(w, h, Bpp, ClearWithBackground)
|
||||
{
|
||||
handle = Handle;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
bpp = Bpp;
|
||||
tiled = Tiled;
|
||||
shown = false;
|
||||
}
|
||||
|
||||
bool cWindow::Contains(int x, int y)
|
||||
{
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
return x >= 0 && y >= 0 && x < width && y < height;
|
||||
}
|
||||
|
||||
void cWindow::Relocate(int x, int y)
|
||||
{
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
|
||||
void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||
{
|
||||
if (tiled) {
|
||||
x1 -= x0;
|
||||
y1 -= y0;
|
||||
x2 -= x0;
|
||||
y2 -= y0;
|
||||
}
|
||||
cBitmap::Fill(x1, y1, x2, y2, Color);
|
||||
}
|
||||
|
||||
void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
{
|
||||
if (tiled) {
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
}
|
||||
cBitmap::SetBitmap(x, y, Bitmap);
|
||||
}
|
||||
|
||||
void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||
{
|
||||
if (tiled) {
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
}
|
||||
cBitmap::Text(x, y, s, ColorFg, ColorBg);
|
||||
}
|
||||
|
||||
const char *cWindow::Data(int x, int y)
|
||||
{
|
||||
return cBitmap::Data(x, y);
|
||||
}
|
||||
|
||||
// --- cDvbOsd ---------------------------------------------------------------
|
||||
|
||||
cDvbOsd::cDvbOsd(int VideoDev, int x, int y, int w, int h, int Bpp)
|
||||
cDvbOsd::cDvbOsd(int VideoDev, int x, int y)
|
||||
:cOsd(x, y)
|
||||
{
|
||||
videoDev = VideoDev;
|
||||
numWindows = 0;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
if (videoDev >= 0) {
|
||||
if (w > 0 && h > 0)
|
||||
Create(0, 0, w, h, Bpp);
|
||||
}
|
||||
else
|
||||
if (videoDev < 0)
|
||||
esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev);
|
||||
}
|
||||
|
||||
cDvbOsd::~cDvbOsd()
|
||||
{
|
||||
if (videoDev >= 0) {
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
SetWindow(window[i]);
|
||||
Cmd(OSD_Close);
|
||||
delete window[i];
|
||||
}
|
||||
numWindows = 0;
|
||||
}
|
||||
for (int i = 0; i < NumWindows(); i++)
|
||||
CloseWindow(GetWindowNr(i));
|
||||
}
|
||||
|
||||
bool cDvbOsd::SetWindow(cWindow *Window)
|
||||
{
|
||||
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
||||
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
||||
int Handle = Window->Handle();
|
||||
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
||||
Cmd(OSD_SetWindow, 0, Handle + 1);
|
||||
return true;
|
||||
if (Window) {
|
||||
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
||||
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
||||
int Handle = Window->Handle();
|
||||
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
||||
Cmd(OSD_SetWindow, 0, Handle + 1);
|
||||
return true;
|
||||
}
|
||||
esyslog(LOG_ERR, "ERROR: illegal window handle: %d", Handle);
|
||||
}
|
||||
esyslog(LOG_ERR, "ERROR: illegal window handle: %d", Handle);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
|
||||
@ -406,166 +68,51 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
|
||||
}
|
||||
}
|
||||
|
||||
tWindowHandle cDvbOsd::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||
bool cDvbOsd::OpenWindow(cWindow *Window)
|
||||
{
|
||||
if (numWindows < MAXNUMWINDOWS) {
|
||||
if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
|
||||
if ((w & 0x03) != 0) {
|
||||
w += 4 - (w & 0x03);
|
||||
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", w);
|
||||
}
|
||||
cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled);
|
||||
if (SetWindow(win)) {
|
||||
window[win->Handle()] = win;
|
||||
Cmd(OSD_Open, Bpp, x0 + x, y0 + y, x0 + x + w - 1, y0 + y + h - 1, (void *)1); // initially hidden!
|
||||
numWindows++;
|
||||
return win->Handle();
|
||||
}
|
||||
else
|
||||
delete win;
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: illegal OSD parameters");
|
||||
if (SetWindow(Window)) {
|
||||
Cmd(OSD_Open, Window->Bpp(), X0() + Window->X0(), Y0() + Window->Y0(), X0() + Window->X0() + Window->Width() - 1, Y0() + Window->Y0() + Window->Height() - 1, (void *)1); // initially hidden!
|
||||
return true;
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: too many OSD windows");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDvbOsd::AddColor(eDvbColor Color, tWindowHandle Window)
|
||||
void cDvbOsd::CommitWindow(cWindow *Window)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
w->Index(Color);
|
||||
w->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
cWindow *cDvbOsd::GetWindow(int x, int y)
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
if (window[i]->Tiled() && window[i]->Contains(x, y))
|
||||
return window[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cWindow *cDvbOsd::GetWindow(tWindowHandle Window)
|
||||
{
|
||||
if (0 <= Window && Window < numWindows)
|
||||
return window[Window];
|
||||
if (Window == LAST_CREATED_WINDOW && numWindows > 0)
|
||||
return window[numWindows - 1];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cDvbOsd::Flush(void)
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||
if (window[i]->Dirty(x1, y1, x2, y2)) {
|
||||
SetWindow(window[i]);
|
||||
int FirstColor = 0, LastColor = 0;
|
||||
const eDvbColor *pal;
|
||||
while ((pal = window[i]->Colors(FirstColor, LastColor)) != NULL)
|
||||
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
|
||||
Cmd(OSD_SetBlock, window[i]->Width(), x1, y1, x2, y2, window[i]->Data(x1, y1));
|
||||
window[i]->Clean();
|
||||
}
|
||||
}
|
||||
// Showing the windows in a separate loop to avoid seeing them come up one after another
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
if (!window[i]->Shown()) {
|
||||
SetWindow(window[i]);
|
||||
Cmd(OSD_MoveWindow, 0, x0 + window[i]->X0(), y0 + window[i]->Y0());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbOsd::Clear(tWindowHandle Window)
|
||||
{
|
||||
if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) {
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
if (Window == ALL_WINDOWS || window[i]->Tiled())
|
||||
window[i]->Clear();
|
||||
}
|
||||
else {
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w)
|
||||
w->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbOsd::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window);
|
||||
if (w)
|
||||
w->Fill(x1, y1, x2, y2, Color);
|
||||
}
|
||||
|
||||
void cDvbOsd::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||
if (w)
|
||||
w->SetBitmap(x, y, Bitmap);
|
||||
}
|
||||
|
||||
int cDvbOsd::Width(unsigned char c)
|
||||
{
|
||||
return numWindows ? window[0]->Width(c) : 0;
|
||||
}
|
||||
|
||||
int cDvbOsd::Width(const char *s)
|
||||
{
|
||||
return numWindows ? window[0]->Width(s) : 0;
|
||||
}
|
||||
|
||||
eDvbFont cDvbOsd::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = Font;
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
oldFont = window[i]->SetFont(Font);
|
||||
return oldFont;
|
||||
}
|
||||
|
||||
void cDvbOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||
if (w)
|
||||
w->Text(x, y, s, ColorFg, ColorBg);
|
||||
}
|
||||
|
||||
void cDvbOsd::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
SetWindow(w);
|
||||
if (NewWidth > 0 && NewHeight > 0) {
|
||||
if ((NewWidth & 0x03) != 0) {
|
||||
NewWidth += 4 - (NewWidth & 0x03);
|
||||
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", NewWidth);
|
||||
}
|
||||
Cmd(OSD_Close);
|
||||
window[w->Handle()] = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled());
|
||||
delete w;
|
||||
Cmd(OSD_Open, 2, x0 + x, y0 + y, x0 + x + NewWidth - 1, y0 + y + NewHeight - 1, (void *)1); // initially hidden!
|
||||
}
|
||||
else {
|
||||
w->Relocate(x, y);
|
||||
Cmd(OSD_MoveWindow, 0, x0 + x, y0 + y);
|
||||
if (SetWindow(Window)) {
|
||||
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||
if (Window->Dirty(x1, y1, x2, y2)) {
|
||||
// commit colors:
|
||||
int FirstColor = 0, LastColor = 0;
|
||||
const eDvbColor *pal;
|
||||
while ((pal = Window->Colors(FirstColor, LastColor)) != NULL)
|
||||
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
|
||||
// commit modified data:
|
||||
Cmd(OSD_SetBlock, Window->Width(), x1, y1, x2, y2, Window->Data(x1, y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbOsd::Hide(tWindowHandle Window)
|
||||
void cDvbOsd::ShowWindow(cWindow *Window)
|
||||
{
|
||||
if (SetWindow(GetWindow(Window)))
|
||||
Cmd(OSD_Hide, 0);
|
||||
if (SetWindow(Window))
|
||||
Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0());
|
||||
}
|
||||
|
||||
void cDvbOsd::Show(tWindowHandle Window)
|
||||
void cDvbOsd::HideWindow(cWindow *Window, bool Hide)
|
||||
{
|
||||
if (SetWindow(GetWindow(Window)))
|
||||
Cmd(OSD_Show, 0);
|
||||
if (SetWindow(Window))
|
||||
Cmd(Hide ? OSD_Hide : OSD_Show, 0);
|
||||
}
|
||||
|
||||
void cDvbOsd::MoveWindow(cWindow *Window, int x, int y)
|
||||
{
|
||||
if (SetWindow(Window))
|
||||
Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y);
|
||||
}
|
||||
|
||||
void cDvbOsd::CloseWindow(cWindow *Window)
|
||||
{
|
||||
if (SetWindow(Window))
|
||||
Cmd(OSD_Close);
|
||||
}
|
||||
|
171
dvbosd.h
171
dvbosd.h
@ -1,178 +1,33 @@
|
||||
/*
|
||||
* dvbosd.h: Interface to the DVB On Screen Display
|
||||
* dvbosd.h: Implementation of the DVB On Screen Display
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbosd.h 1.10 2002/02/03 16:43:50 kls Exp $
|
||||
* $Id: dvbosd.h 1.11 2002/05/10 14:22:07 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBOSD_H
|
||||
#define __DVBOSD_H
|
||||
|
||||
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
|
||||
#include <ncurses.h>
|
||||
#undef ERR //XXX ncurses defines this - but this clashes with newer system header files
|
||||
#endif
|
||||
#include <ost/osd.h>
|
||||
#include <stdio.h>
|
||||
#include "font.h"
|
||||
#include "osdbase.h"
|
||||
|
||||
#define MAXNUMCOLORS 16
|
||||
|
||||
enum eDvbColor {
|
||||
#ifdef DEBUG_OSD
|
||||
clrBackground,
|
||||
clrTransparent = clrBackground,
|
||||
clrBlack = clrBackground,
|
||||
clrRed,
|
||||
clrGreen,
|
||||
clrYellow,
|
||||
clrBlue,
|
||||
clrMagenta,
|
||||
clrCyan,
|
||||
clrWhite,
|
||||
#else
|
||||
clrTransparent = 0x00000000,
|
||||
clrBackground = 0x7F000000, // 50% gray
|
||||
clrBlack = 0xFF000000,
|
||||
clrRed = 0xFF1414FC,
|
||||
clrGreen = 0xFF24FC24,
|
||||
clrYellow = 0xFF24C0FC,
|
||||
clrMagenta = 0xFFFC00B0,
|
||||
clrBlue = 0xFFFC0000,
|
||||
clrCyan = 0xFFFCFC00,
|
||||
clrWhite = 0xFFFCFCFC,
|
||||
#endif
|
||||
};
|
||||
|
||||
class cPalette {
|
||||
private:
|
||||
eDvbColor color[MAXNUMCOLORS];
|
||||
int maxColors, numColors;
|
||||
bool used[MAXNUMCOLORS];
|
||||
bool fetched[MAXNUMCOLORS];
|
||||
bool full;
|
||||
protected:
|
||||
typedef unsigned char tIndexes[MAXNUMCOLORS];
|
||||
public:
|
||||
cPalette(int Bpp);
|
||||
int Index(eDvbColor Color);
|
||||
void Reset(void);
|
||||
const eDvbColor *Colors(int &FirstColor, int &LastColor);
|
||||
void Take(const cPalette &Palette, tIndexes *Indexes = NULL);
|
||||
};
|
||||
|
||||
class cBitmap : public cPalette {
|
||||
private:
|
||||
cFont *font;
|
||||
eDvbFont fontType;
|
||||
void SetIndex(int x, int y, char Index);
|
||||
char *bitmap;
|
||||
bool clearWithBackground;
|
||||
protected:
|
||||
int width, height;
|
||||
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
||||
public:
|
||||
cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground = true);
|
||||
virtual ~cBitmap();
|
||||
bool ClearWithBackground(void) { return clearWithBackground; }
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
||||
void SetPixel(int x, int y, eDvbColor Color);
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
int Width(void) { return width; }
|
||||
int Width(unsigned char c);
|
||||
int Width(const char *s);
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||
void Clean(void);
|
||||
void Clear(void);
|
||||
const char *Data(int x, int y);
|
||||
};
|
||||
|
||||
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
|
||||
|
||||
class cWindow;
|
||||
|
||||
typedef int tWindowHandle;
|
||||
|
||||
// '-1' is used as an error return value!
|
||||
#define ALL_WINDOWS (-2)
|
||||
#define ALL_TILED_WINDOWS (-3)
|
||||
#define LAST_CREATED_WINDOW (-4)
|
||||
|
||||
class cDvbOsd {
|
||||
class cDvbOsd : public cOsd {
|
||||
private:
|
||||
int videoDev;
|
||||
int numWindows;
|
||||
int x0, y0;
|
||||
cWindow *window[MAXNUMWINDOWS];
|
||||
bool SetWindow(cWindow *Window);
|
||||
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
|
||||
cWindow *GetWindow(int x, int y);
|
||||
cWindow *GetWindow(tWindowHandle Window);
|
||||
protected:
|
||||
virtual bool OpenWindow(cWindow *Window);
|
||||
virtual void CommitWindow(cWindow *Window);
|
||||
virtual void ShowWindow(cWindow *Window);
|
||||
virtual void HideWindow(cWindow *Window, bool Hide);
|
||||
virtual void MoveWindow(cWindow *Window, int x, int y);
|
||||
virtual void CloseWindow(cWindow *Window);
|
||||
public:
|
||||
cDvbOsd(int VideoDev, int x, int y, int w = -1, int h = -1, int Bpp = -1);
|
||||
// Initializes the OSD on the given VideoDev, starting at screen coordinates
|
||||
// (x, y). If w, h and Bpp are given, one window with that width, height and
|
||||
// color depth will be created - otherwise the actual windows will have to
|
||||
// be created by separate calls to Create().
|
||||
~cDvbOsd();
|
||||
// Destroys all windows and shuts down the OSD.
|
||||
tWindowHandle Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true, bool Tiled = true);
|
||||
// Creates a window at coordinates (x, y), which are relative to the OSD's
|
||||
// origin given in the constructor, with the given width, height and color
|
||||
// depth. ClearWithBackground controls whether the window will be filled with
|
||||
// clrBackground when it is cleared. Setting this to 'false' may be useful
|
||||
// for windows that don't need clrBackground but want to save this color
|
||||
// palette entry for a different color. Tiled controls whether this will
|
||||
// be part of a multi section OSD (with several windows that all have
|
||||
// different color depths and palettes and form one large OSD area), or
|
||||
// whether this is a "standalone" window that will be drawn "in front"
|
||||
// of any windows defined *after* this one (this can be used for highlighting
|
||||
// certain parts of the OSD, as would be done in a 'cursor').
|
||||
// Returns a handle that can be used to identify this window.
|
||||
void AddColor(eDvbColor Color, tWindowHandle Window = LAST_CREATED_WINDOW);
|
||||
// Adds the Color to the color palette of the given window if it is not
|
||||
// already contained in the palette (and if the palette still has free
|
||||
// slots for new colors). The default value LAST_CREATED_WINDOW will
|
||||
// access the most recently created window, without the need of explicitly
|
||||
// using a window handle.
|
||||
void Flush(void);
|
||||
// Actually commits all data of all windows to the OSD.
|
||||
void Clear(tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Clears the given window. If ALL_TILED_WINDOWS is given, only the tiled
|
||||
// windows will be cleared, leaving the standalone windows untouched. If
|
||||
// ALL_WINDOWS is given, the standalone windows will also be cleared.
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Fills the rectangle defined by the upper left (x1, y2) and lower right
|
||||
// (x2, y2) corners with the given Color. If a specific window is given,
|
||||
// the coordinates are relative to that window's upper left corner.
|
||||
// Otherwise they are relative to the upper left corner of the entire OSD.
|
||||
// If all tiled windows are selected, only that window which contains the
|
||||
// point (x1, y1) will actually be filled.
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Sets the pixels within the given window with the data from the given
|
||||
// Bitmap. See Fill() for details about the coordinates.
|
||||
int Width(unsigned char c);
|
||||
// Returns the width (in pixels) of the given character in the current font.
|
||||
int Width(const char *s);
|
||||
// Returns the width (in pixels) of the given string in the current font.
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
// Sets the current font for subsequent Width() and Text() operations.
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Writes the given string at coordinates (x, y) with the given foreground
|
||||
// and background color into the given window (see Fill() for details
|
||||
// about the coordinates).
|
||||
void Relocate(tWindowHandle Window, int x, int y, int NewWidth = -1, int NewHeight = -1);
|
||||
// Moves the given window to the new location at (x, y). If NewWidth and
|
||||
// NewHeight are also given, the window will also be resized to the new
|
||||
// width and height.
|
||||
void Hide(tWindowHandle Window);
|
||||
// Hides the given window.
|
||||
void Show(tWindowHandle Window);
|
||||
// Shows the given window.
|
||||
cDvbOsd(int VideoDev, int x, int y);
|
||||
virtual ~cDvbOsd();
|
||||
};
|
||||
|
||||
#endif //__DVBOSD_H
|
||||
|
482
osdbase.c
Normal file
482
osdbase.c
Normal file
@ -0,0 +1,482 @@
|
||||
/*
|
||||
* osdbase.c: Basic interface to the On Screen Display
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osdbase.c 1.1 2002/05/10 14:55:53 kls Exp $
|
||||
*/
|
||||
|
||||
#include "osdbase.h"
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/unistd.h>
|
||||
#include "tools.h"
|
||||
|
||||
// --- cPalette --------------------------------------------------------------
|
||||
|
||||
cPalette::cPalette(int Bpp)
|
||||
{
|
||||
maxColors = 1 << Bpp;
|
||||
numColors = 0;
|
||||
full = false;
|
||||
}
|
||||
|
||||
int cPalette::Index(eDvbColor Color)
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
Color = eDvbColor(((Color & 0xFF) << 24) | ((Color & 0xFF00) << 8) | ((Color & 0xFF0000) >> 8) | ((Color & 0xFF000000) >> 24));
|
||||
#endif
|
||||
for (int i = 0; i < numColors; i++) {
|
||||
if (color[i] == Color) {
|
||||
used[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (!full) {
|
||||
if (numColors < maxColors) {
|
||||
color[numColors++] = Color;
|
||||
used[numColors - 1] = true;
|
||||
fetched[numColors - 1] = false;
|
||||
return numColors - 1;
|
||||
}
|
||||
for (int i = maxColors; --i >= 0; ) {
|
||||
if (!used[i]) {
|
||||
color[i] = Color;
|
||||
used[i] = true;
|
||||
fetched[i] = false;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
esyslog(LOG_ERR, "ERROR: too many different colors used in palette");
|
||||
full = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cPalette::Reset(void)
|
||||
{
|
||||
for (int i = 0; i < numColors; i++)
|
||||
used[i] = false;
|
||||
full = false;
|
||||
}
|
||||
|
||||
const eDvbColor *cPalette::Colors(int &FirstColor, int &LastColor)
|
||||
{
|
||||
for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
|
||||
if (!fetched[FirstColor]) {
|
||||
for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
|
||||
fetched[LastColor] = true;
|
||||
LastColor--; // the loop ended one past the last one!
|
||||
return &color[FirstColor];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
|
||||
{
|
||||
for (int i = 0; i < Palette.numColors; i++) {
|
||||
if (Palette.used[i]) {
|
||||
int n = Index(Palette.color[i]);
|
||||
if (Indexes)
|
||||
(*Indexes)[i] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cBitmap ---------------------------------------------------------------
|
||||
|
||||
cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
|
||||
:cPalette(Bpp)
|
||||
{
|
||||
width = Width;
|
||||
height = Height;
|
||||
clearWithBackground = ClearWithBackground;
|
||||
bitmap = NULL;
|
||||
fontType = fontOsd;
|
||||
font = NULL;
|
||||
if (width > 0 && height > 0) {
|
||||
bitmap = new char[width * height];
|
||||
if (bitmap) {
|
||||
Clean();
|
||||
memset(bitmap, 0x00, width * height);
|
||||
SetFont(fontOsd);
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: can't allocate bitmap!");
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: illegal bitmap parameters (%d, %d)!", width, height);
|
||||
}
|
||||
|
||||
cBitmap::~cBitmap()
|
||||
{
|
||||
delete font;
|
||||
delete bitmap;
|
||||
}
|
||||
|
||||
eDvbFont cBitmap::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = fontType;
|
||||
if (fontType != Font || !font) {
|
||||
delete font;
|
||||
font = new cFont(Font);
|
||||
fontType = Font;
|
||||
}
|
||||
return oldFont;
|
||||
}
|
||||
|
||||
bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
|
||||
{
|
||||
if (dirtyX2 >= 0) {
|
||||
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
|
||||
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
|
||||
//TODO Fix driver (should be able to handle any size bitmaps!)
|
||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
|
||||
if (dirtyX2 < width - 1)
|
||||
dirtyX2++;
|
||||
else if (dirtyX1 > 0)
|
||||
dirtyX1--;
|
||||
}
|
||||
//XXX "... / 2" <==> Bpp???
|
||||
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||
if (dirtyY2 < height - 1)
|
||||
dirtyY2++;
|
||||
else if (dirtyY1 > 0)
|
||||
dirtyY1--;
|
||||
}
|
||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||
if (dirtyX2 < width - 1)
|
||||
dirtyX2++;
|
||||
else if (dirtyX1 > 0)
|
||||
dirtyX1--;
|
||||
}
|
||||
x1 = dirtyX1;
|
||||
y1 = dirtyY1;
|
||||
x2 = dirtyX2;
|
||||
y2 = dirtyY2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cBitmap::Clean(void)
|
||||
{
|
||||
dirtyX1 = width;
|
||||
dirtyY1 = height;
|
||||
dirtyX2 = -1;
|
||||
dirtyY2 = -1;
|
||||
}
|
||||
|
||||
void cBitmap::SetIndex(int x, int y, char Index)
|
||||
{
|
||||
if (bitmap) {
|
||||
if (0 <= x && x < width && 0 <= y && y < height) {
|
||||
if (bitmap[width * y + x] != Index) {
|
||||
bitmap[width * y + x] = Index;
|
||||
if (dirtyX1 > x) dirtyX1 = x;
|
||||
if (dirtyY1 > y) dirtyY1 = y;
|
||||
if (dirtyX2 < x) dirtyX2 = x;
|
||||
if (dirtyY2 < y) dirtyY2 = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
|
||||
{
|
||||
SetIndex(x, y, Index(Color));
|
||||
}
|
||||
|
||||
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
{
|
||||
if (bitmap && Bitmap.bitmap) {
|
||||
tIndexes Indexes;
|
||||
Take(Bitmap, &Indexes);
|
||||
for (int ix = 0; ix < Bitmap.width; ix++) {
|
||||
for (int iy = 0; iy < Bitmap.height; iy++)
|
||||
SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cBitmap::Width(unsigned char c)
|
||||
{
|
||||
return font ? font->Width(c) : -1;
|
||||
}
|
||||
|
||||
int cBitmap::Width(const char *s)
|
||||
{
|
||||
return font ? font->Width(s) : -1;
|
||||
}
|
||||
|
||||
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||
{
|
||||
if (bitmap) {
|
||||
char fg = Index(ColorFg);
|
||||
char bg = Index(ColorBg);
|
||||
int h = font->Height(s);
|
||||
while (s && *s) {
|
||||
const cFont::tCharData *CharData = font->CharData(*s++);
|
||||
if (int(x + CharData->width) > width)
|
||||
break;
|
||||
for (int row = 0; row < h; row++) {
|
||||
cFont::tPixelData PixelData = CharData->lines[row];
|
||||
for (int col = CharData->width; col-- > 0; ) {
|
||||
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
|
||||
PixelData >>= 1;
|
||||
}
|
||||
}
|
||||
x += CharData->width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||
{
|
||||
if (bitmap) {
|
||||
char c = Index(Color);
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
SetIndex(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
void cBitmap::Clear(void)
|
||||
{
|
||||
Reset();
|
||||
if (clearWithBackground)
|
||||
Fill(0, 0, width - 1, height - 1, clrBackground);
|
||||
}
|
||||
|
||||
const char *cBitmap::Data(int x, int y)
|
||||
{
|
||||
return &bitmap[y * width + x];
|
||||
}
|
||||
|
||||
// --- cWindow ---------------------------------------------------------------
|
||||
|
||||
cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||
:cBitmap(w, h, Bpp, ClearWithBackground)
|
||||
{
|
||||
handle = Handle;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
bpp = Bpp;
|
||||
tiled = Tiled;
|
||||
shown = false;
|
||||
}
|
||||
|
||||
bool cWindow::Contains(int x, int y)
|
||||
{
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
return x >= 0 && y >= 0 && x < width && y < height;
|
||||
}
|
||||
|
||||
void cWindow::Relocate(int x, int y)
|
||||
{
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
|
||||
void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||
{
|
||||
if (tiled) {
|
||||
x1 -= x0;
|
||||
y1 -= y0;
|
||||
x2 -= x0;
|
||||
y2 -= y0;
|
||||
}
|
||||
cBitmap::Fill(x1, y1, x2, y2, Color);
|
||||
}
|
||||
|
||||
void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||
{
|
||||
if (tiled) {
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
}
|
||||
cBitmap::SetBitmap(x, y, Bitmap);
|
||||
}
|
||||
|
||||
void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||
{
|
||||
if (tiled) {
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
}
|
||||
cBitmap::Text(x, y, s, ColorFg, ColorBg);
|
||||
}
|
||||
|
||||
const char *cWindow::Data(int x, int y)
|
||||
{
|
||||
return cBitmap::Data(x, y);
|
||||
}
|
||||
|
||||
// --- cOsd ------------------------------------------------------------------
|
||||
|
||||
cOsd::cOsd(int x, int y)
|
||||
{
|
||||
numWindows = 0;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
}
|
||||
|
||||
cOsd::~cOsd()
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
delete window[i];
|
||||
}
|
||||
|
||||
tWindowHandle cOsd::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||
{
|
||||
if (numWindows < MAXNUMWINDOWS) {
|
||||
if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
|
||||
if ((w & 0x03) != 0) {
|
||||
w += 4 - (w & 0x03);
|
||||
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", w);
|
||||
}
|
||||
cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled);
|
||||
if (OpenWindow(win)) {
|
||||
window[win->Handle()] = win;
|
||||
numWindows++;
|
||||
return win->Handle();
|
||||
}
|
||||
else
|
||||
delete win;
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: illegal OSD parameters");
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: too many OSD windows");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cOsd::AddColor(eDvbColor Color, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
w->Index(Color);
|
||||
w->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
cWindow *cOsd::GetWindow(int x, int y)
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
if (window[i]->Tiled() && window[i]->Contains(x, y))
|
||||
return window[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cWindow *cOsd::GetWindow(tWindowHandle Window)
|
||||
{
|
||||
if (0 <= Window && Window < numWindows)
|
||||
return window[Window];
|
||||
if (Window == LAST_CREATED_WINDOW && numWindows > 0)
|
||||
return window[numWindows - 1];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cOsd::Flush(void)
|
||||
{
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
CommitWindow(window[i]);
|
||||
window[i]->Clean();
|
||||
}
|
||||
// Showing the windows in a separate loop to avoid seeing them come up one after another
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
if (!window[i]->Shown())
|
||||
ShowWindow(window[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void cOsd::Clear(tWindowHandle Window)
|
||||
{
|
||||
if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) {
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
if (Window == ALL_WINDOWS || window[i]->Tiled())
|
||||
window[i]->Clear();
|
||||
}
|
||||
else {
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w)
|
||||
w->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void cOsd::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window);
|
||||
if (w)
|
||||
w->Fill(x1, y1, x2, y2, Color);
|
||||
}
|
||||
|
||||
void cOsd::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||
if (w)
|
||||
w->SetBitmap(x, y, Bitmap);
|
||||
}
|
||||
|
||||
int cOsd::Width(unsigned char c)
|
||||
{
|
||||
return numWindows ? window[0]->Width(c) : 0;
|
||||
}
|
||||
|
||||
int cOsd::Width(const char *s)
|
||||
{
|
||||
return numWindows ? window[0]->Width(s) : 0;
|
||||
}
|
||||
|
||||
eDvbFont cOsd::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = Font;
|
||||
for (int i = 0; i < numWindows; i++)
|
||||
oldFont = window[i]->SetFont(Font);
|
||||
return oldFont;
|
||||
}
|
||||
|
||||
void cOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window)
|
||||
{
|
||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||
if (w)
|
||||
w->Text(x, y, s, ColorFg, ColorBg);
|
||||
}
|
||||
|
||||
void cOsd::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
if (NewWidth > 0 && NewHeight > 0) {
|
||||
if ((NewWidth & 0x03) != 0) {
|
||||
NewWidth += 4 - (NewWidth & 0x03);
|
||||
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", NewWidth);
|
||||
}
|
||||
CloseWindow(w);
|
||||
cWindow *NewWindow = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled());
|
||||
window[w->Handle()] = NewWindow;
|
||||
delete w;
|
||||
OpenWindow(NewWindow);
|
||||
}
|
||||
else {
|
||||
MoveWindow(w, x, y);
|
||||
w->Relocate(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cOsd::Hide(tWindowHandle Window)
|
||||
{
|
||||
HideWindow(GetWindow(Window), true);
|
||||
}
|
||||
|
||||
void cOsd::Show(tWindowHandle Window)
|
||||
{
|
||||
HideWindow(GetWindow(Window), false);
|
||||
}
|
211
osdbase.h
Normal file
211
osdbase.h
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* osdbase.h: Basic interface to the On Screen Display
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osdbase.h 1.1 2002/05/10 14:26:09 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSDBASE_H
|
||||
#define __OSDBASE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "font.h"
|
||||
|
||||
#define MAXNUMCOLORS 16
|
||||
|
||||
enum eDvbColor {
|
||||
#ifdef DEBUG_OSD
|
||||
clrBackground,
|
||||
clrTransparent = clrBackground,
|
||||
clrBlack = clrBackground,
|
||||
clrRed,
|
||||
clrGreen,
|
||||
clrYellow,
|
||||
clrBlue,
|
||||
clrMagenta,
|
||||
clrCyan,
|
||||
clrWhite,
|
||||
#else
|
||||
clrTransparent = 0x00000000,
|
||||
clrBackground = 0x7F000000, // 50% gray
|
||||
clrBlack = 0xFF000000,
|
||||
clrRed = 0xFF1414FC,
|
||||
clrGreen = 0xFF24FC24,
|
||||
clrYellow = 0xFF24C0FC,
|
||||
clrMagenta = 0xFFFC00B0,
|
||||
clrBlue = 0xFFFC0000,
|
||||
clrCyan = 0xFFFCFC00,
|
||||
clrWhite = 0xFFFCFCFC,
|
||||
#endif
|
||||
};
|
||||
|
||||
class cPalette {
|
||||
private:
|
||||
eDvbColor color[MAXNUMCOLORS];
|
||||
int maxColors, numColors;
|
||||
bool used[MAXNUMCOLORS];
|
||||
bool fetched[MAXNUMCOLORS];
|
||||
bool full;
|
||||
protected:
|
||||
typedef unsigned char tIndexes[MAXNUMCOLORS];
|
||||
public:
|
||||
cPalette(int Bpp);
|
||||
int Index(eDvbColor Color);
|
||||
void Reset(void);
|
||||
const eDvbColor *Colors(int &FirstColor, int &LastColor);
|
||||
void Take(const cPalette &Palette, tIndexes *Indexes = NULL);
|
||||
};
|
||||
|
||||
class cBitmap : public cPalette {
|
||||
private:
|
||||
cFont *font;
|
||||
eDvbFont fontType;
|
||||
void SetIndex(int x, int y, char Index);
|
||||
char *bitmap;
|
||||
bool clearWithBackground;
|
||||
protected:
|
||||
int width, height;
|
||||
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
||||
public:
|
||||
cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground = true);
|
||||
virtual ~cBitmap();
|
||||
bool ClearWithBackground(void) { return clearWithBackground; }
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
||||
void SetPixel(int x, int y, eDvbColor Color);
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
int Width(void) { return width; }
|
||||
int Width(unsigned char c);
|
||||
int Width(const char *s);
|
||||
int Height(void) { return height; }
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||
void Clean(void);
|
||||
void Clear(void);
|
||||
const char *Data(int x, int y);
|
||||
};
|
||||
|
||||
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
|
||||
|
||||
class cWindow : public cBitmap {
|
||||
private:
|
||||
int handle; // the index within the OSD's window array (0...MAXNUMWINDOWS - 1)
|
||||
int x0, y0;
|
||||
int bpp;
|
||||
bool tiled;
|
||||
bool shown;
|
||||
public:
|
||||
cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled);
|
||||
int X0(void) { return x0; }
|
||||
int Y0(void) { return y0; }
|
||||
int Bpp(void) { return bpp; }
|
||||
bool Tiled(void) { return tiled; }
|
||||
bool Shown(void) { bool s = shown; shown = true; return s; }
|
||||
int Handle(void) { return handle; }
|
||||
bool Contains(int x, int y);
|
||||
void Relocate(int x, int y);
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||
const char *Data(int x, int y);
|
||||
};
|
||||
|
||||
typedef int tWindowHandle;
|
||||
|
||||
// '-1' is used as an error return value!
|
||||
#define ALL_WINDOWS (-2)
|
||||
#define ALL_TILED_WINDOWS (-3)
|
||||
#define LAST_CREATED_WINDOW (-4)
|
||||
|
||||
class cOsd {
|
||||
private:
|
||||
int numWindows;
|
||||
int x0, y0;
|
||||
cWindow *window[MAXNUMWINDOWS];
|
||||
cWindow *GetWindow(int x, int y);
|
||||
cWindow *GetWindow(tWindowHandle Window);
|
||||
protected:
|
||||
cWindow *GetWindowNr(int i) { return i < MAXNUMWINDOWS ? window[i] : NULL; }
|
||||
int NumWindows(void) { return numWindows; }
|
||||
int X0(void) { return x0; }
|
||||
int Y0(void) { return y0; }
|
||||
virtual bool OpenWindow(cWindow *Window) = 0;
|
||||
// Opens the window on the OSD hardware, without actually showing it (the
|
||||
// initial state shall be "hidden").
|
||||
virtual void CommitWindow(cWindow *Window) = 0;
|
||||
// Write any modified data and color definitions to the OSD hardware.
|
||||
// Use the window's Dirty() function to find out which area of data
|
||||
// actually needs to be transferred. If the window has not yet been explicitly
|
||||
// shown through a call to ShowWindow(), no visible activity shall take place.
|
||||
virtual void ShowWindow(cWindow *Window) = 0;
|
||||
// Make the window actually visible on the OSD hardware.
|
||||
virtual void HideWindow(cWindow *Window, bool Hide) = 0;
|
||||
// Temporarily hide the window (if 'Hide' is 'true') or make a previously
|
||||
// hidden window visible again (if 'Hide' is 'false').
|
||||
virtual void MoveWindow(cWindow *Window, int x, int y) = 0;
|
||||
// Move the window to a new location.
|
||||
virtual void CloseWindow(cWindow *Window) = 0;
|
||||
// Close the window and release any OSD hardware resources allocated for it.
|
||||
public:
|
||||
cOsd(int x, int y);
|
||||
// Initializes the OSD, starting at screen coordinates (x, y).
|
||||
virtual ~cOsd();
|
||||
// Destroys all windows and shuts down the OSD.
|
||||
tWindowHandle Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true, bool Tiled = true);
|
||||
// Creates a window at coordinates (x, y), which are relative to the OSD's
|
||||
// origin given in the constructor, with the given width, height and color
|
||||
// depth. ClearWithBackground controls whether the window will be filled with
|
||||
// clrBackground when it is cleared. Setting this to 'false' may be useful
|
||||
// for windows that don't need clrBackground but want to save this color
|
||||
// palette entry for a different color. Tiled controls whether this will
|
||||
// be part of a multi section OSD (with several windows that all have
|
||||
// different color depths and palettes and form one large OSD area), or
|
||||
// whether this is a "standalone" window that will be drawn "in front"
|
||||
// of any windows defined *after* this one (this can be used for highlighting
|
||||
// certain parts of the OSD, as would be done in a 'cursor').
|
||||
// Returns a handle that can be used to identify this window.
|
||||
void AddColor(eDvbColor Color, tWindowHandle Window = LAST_CREATED_WINDOW);
|
||||
// Adds the Color to the color palette of the given window if it is not
|
||||
// already contained in the palette (and if the palette still has free
|
||||
// slots for new colors). The default value LAST_CREATED_WINDOW will
|
||||
// access the most recently created window, without the need of explicitly
|
||||
// using a window handle.
|
||||
void Flush(void);
|
||||
// Actually commits all data of all windows to the OSD.
|
||||
void Clear(tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Clears the given window. If ALL_TILED_WINDOWS is given, only the tiled
|
||||
// windows will be cleared, leaving the standalone windows untouched. If
|
||||
// ALL_WINDOWS is given, the standalone windows will also be cleared.
|
||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Fills the rectangle defined by the upper left (x1, y2) and lower right
|
||||
// (x2, y2) corners with the given Color. If a specific window is given,
|
||||
// the coordinates are relative to that window's upper left corner.
|
||||
// Otherwise they are relative to the upper left corner of the entire OSD.
|
||||
// If all tiled windows are selected, only that window which contains the
|
||||
// point (x1, y1) will actually be filled.
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Sets the pixels within the given window with the data from the given
|
||||
// Bitmap. See Fill() for details about the coordinates.
|
||||
int Width(unsigned char c);
|
||||
// Returns the width (in pixels) of the given character in the current font.
|
||||
int Width(const char *s);
|
||||
// Returns the width (in pixels) of the given string in the current font.
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
// Sets the current font for subsequent Width() and Text() operations.
|
||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||
// Writes the given string at coordinates (x, y) with the given foreground
|
||||
// and background color into the given window (see Fill() for details
|
||||
// about the coordinates).
|
||||
void Relocate(tWindowHandle Window, int x, int y, int NewWidth = -1, int NewHeight = -1);
|
||||
// Moves the given window to the new location at (x, y). If NewWidth and
|
||||
// NewHeight are also given, the window will also be resized to the new
|
||||
// width and height.
|
||||
void Hide(tWindowHandle Window);
|
||||
// Hides the given window.
|
||||
void Show(tWindowHandle Window);
|
||||
// Shows the given window.
|
||||
};
|
||||
|
||||
#endif //__OSDBASE_H
|
Loading…
Reference in New Issue
Block a user