1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

There can now be more than one OSD at the same time

This commit is contained in:
Klaus Schmidinger 2007-08-26 09:58:10 +02:00
parent 6a737033ad
commit a80915ff22
6 changed files with 110 additions and 40 deletions

11
HISTORY
View File

@ -5380,7 +5380,7 @@ Video Disk Recorder Revision History
name of the plugin. The "newplugin" script has been changed accordingly, and name of the plugin. The "newplugin" script has been changed accordingly, and
plugin authors should change their Makefiles, too. plugin authors should change their Makefiles, too.
2007-08-25: Version 1.5.9 2007-08-26: Version 1.5.9
- Fixed handling locale directories with a large number of entries (thanks to - Fixed handling locale directories with a large number of entries (thanks to
Anssi Hannula). Anssi Hannula).
@ -5405,3 +5405,12 @@ Video Disk Recorder Revision History
option ':groups' is given (thanks to Andreas Mair). option ':groups' is given (thanks to Andreas Mair).
- Added a missing error report to cCuttingThread::Action() (thanks to Udo - Added a missing error report to cCuttingThread::Action() (thanks to Udo
Richter). Richter).
- There can now be more than one OSD at the same time. At any given time,
however, only one of them can be active (and thus visible). This is to
allow displaying things like subtitles in an easy way. A cOsd therefore
now has a "Level", and only the OSD with the smallest level will be
displayed. The level 0 OSD is special, and there can only be one with
this level. If there is more than one OSD with a particular level, only
the one that was created first will be displayed.
Plugins that provide an OSD need to adjust their cOsdProvider::CreateOsd()
function to hand through the Level.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbosd.c 1.30 2006/01/28 14:24:04 kls Exp $ * $Id: dvbosd.c 1.31 2007/08/26 09:39:20 kls Exp $
*/ */
#include "dvbosd.h" #include "dvbosd.h"
@ -26,15 +26,17 @@ private:
int osdMem; int osdMem;
bool shown; bool shown;
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL); void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
protected:
virtual void SetActive(bool On);
public: public:
cDvbOsd(int Left, int Top, int OsdDev); cDvbOsd(int Left, int Top, int OsdDev, uint Level);
virtual ~cDvbOsd(); virtual ~cDvbOsd();
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
virtual void Flush(void); virtual void Flush(void);
}; };
cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev) cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev, uint Level)
:cOsd(Left, Top) :cOsd(Left, Top, Level)
{ {
osdDev = OsdDev; osdDev = OsdDev;
shown = false; shown = false;
@ -49,23 +51,36 @@ cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev)
if (ioctl(osdDev, OSD_GET_CAPABILITY, &cap) == 0) if (ioctl(osdDev, OSD_GET_CAPABILITY, &cap) == 0)
osdMem = cap.val; osdMem = cap.val;
#endif #endif
// must clear all windows here to avoid flashing effects - doesn't work if done
// in Flush() only for the windows that are actually used...
for (int i = 0; i < MAXNUMWINDOWS; i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Clear);
}
} }
} }
cDvbOsd::~cDvbOsd() cDvbOsd::~cDvbOsd()
{ {
if (shown) { SetActive(false);
cBitmap *Bitmap; }
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
Cmd(OSD_SetWindow, 0, i + 1); void cDvbOsd::SetActive(bool On)
Cmd(OSD_Close); {
} if (On != Active()) {
cOsd::SetActive(On);
if (On) {
// must clear all windows here to avoid flashing effects - doesn't work if done
// in Flush() only for the windows that are actually used...
for (int i = 0; i < MAXNUMWINDOWS; i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Clear);
}
if (GetBitmap(0)) // only flush here if there are already bitmaps
Flush();
}
else if (shown) {
cBitmap *Bitmap;
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Close);
}
shown = false;
}
} }
} }
@ -108,13 +123,20 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
void cDvbOsd::Flush(void) void cDvbOsd::Flush(void)
{ {
if (!Active())
return;
cBitmap *Bitmap; cBitmap *Bitmap;
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
Cmd(OSD_SetWindow, 0, i + 1); Cmd(OSD_SetWindow, 0, i + 1);
if (!shown) if (!shown)
Cmd(OSD_Open, Bitmap->Bpp(), Left() + Bitmap->X0(), Top() + Bitmap->Y0(), Left() + Bitmap->X0() + Bitmap->Width() - 1, Top() + Bitmap->Y0() + Bitmap->Height() - 1, (void *)1); // initially hidden! Cmd(OSD_Open, Bitmap->Bpp(), Left() + Bitmap->X0(), Top() + Bitmap->Y0(), Left() + Bitmap->X0() + Bitmap->Width() - 1, Top() + Bitmap->Y0() + Bitmap->Height() - 1, (void *)1); // initially hidden!
int x1 = 0, y1 = 0, x2 = 0, y2 = 0; int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
if (Bitmap->Dirty(x1, y1, x2, y2)) { if (!shown || Bitmap->Dirty(x1, y1, x2, y2)) {
if (!shown) {
x1 = y1 = 0;
x2 = Bitmap->Width() - 1;
y2 = Bitmap->Height() - 1;
}
//TODO Workaround: apparently the bitmap sent to the driver always has to be a multiple //TODO Workaround: apparently the bitmap sent to the driver always has to be a multiple
//TODO of 8 bits wide, and (dx * dy) also has to be a multiple of 8. //TODO 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!) //TODO Fix driver (should be able to handle any size bitmaps!)
@ -173,7 +195,7 @@ cDvbOsdProvider::cDvbOsdProvider(int OsdDev)
osdDev = OsdDev; osdDev = OsdDev;
} }
cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top) cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top, uint Level)
{ {
return new cDvbOsd(Left, Top, osdDev); return new cDvbOsd(Left, Top, osdDev, Level);
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbosd.h 1.18 2004/06/12 13:09:52 kls Exp $ * $Id: dvbosd.h 1.19 2007/08/25 13:49:34 kls Exp $
*/ */
#ifndef __DVBOSD_H #ifndef __DVBOSD_H
@ -17,7 +17,7 @@ private:
int osdDev; int osdDev;
public: public:
cDvbOsdProvider(int OsdDev); cDvbOsdProvider(int OsdDev);
virtual cOsd *CreateOsd(int Left, int Top); virtual cOsd *CreateOsd(int Left, int Top, uint Level);
}; };
#endif //__DVBOSD_H #endif //__DVBOSD_H

43
osd.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.c 1.73 2007/08/17 15:23:50 kls Exp $ * $Id: osd.c 1.74 2007/08/26 09:44:50 kls Exp $
*/ */
#include "osd.h" #include "osd.h"
@ -646,18 +646,24 @@ int cOsd::osdLeft = 0;
int cOsd::osdTop = 0; int cOsd::osdTop = 0;
int cOsd::osdWidth = 0; int cOsd::osdWidth = 0;
int cOsd::osdHeight = 0; int cOsd::osdHeight = 0;
int cOsd::isOpen = 0; cVector<cOsd *> cOsd::Osds;
cOsd::cOsd(int Left, int Top) cOsd::cOsd(int Left, int Top, uint Level)
{ {
if (isOpen)
esyslog("ERROR: OSD opened without closing previous OSD!");
savedRegion = NULL; savedRegion = NULL;
numBitmaps = 0; numBitmaps = 0;
left = Left; left = Left;
top = Top; top = Top;
width = height = 0; width = height = 0;
isOpen++; level = Level;
active = false;
for (int i = 0; i < Osds.Size(); i++) {
if (Osds[i]->level > level) {
Osds.Insert(this, i);
return;
}
}
Osds.Append(this);
} }
cOsd::~cOsd() cOsd::~cOsd()
@ -665,7 +671,14 @@ cOsd::~cOsd()
for (int i = 0; i < numBitmaps; i++) for (int i = 0; i < numBitmaps; i++)
delete bitmaps[i]; delete bitmaps[i];
delete savedRegion; delete savedRegion;
isOpen--; for (int i = 0; i < Osds.Size(); i++) {
if (Osds[i] == this) {
Osds.Remove(i);
if (Osds.Size())
Osds[0]->SetActive(true);
break;
}
}
} }
void cOsd::SetOsdPosition(int Left, int Top, int Width, int Height) void cOsd::SetOsdPosition(int Left, int Top, int Width, int Height)
@ -803,15 +816,23 @@ cOsdProvider::~cOsdProvider()
osdProvider = NULL; osdProvider = NULL;
} }
cOsd *cOsdProvider::NewOsd(int Left, int Top) cOsd *cOsdProvider::NewOsd(int Left, int Top, uint Level)
{ {
if (Level == 0 && cOsd::IsOpen()) if (Level == 0 && cOsd::IsOpen())
esyslog("ERROR: attempt to open OSD while it is already open - using dummy OSD!"); esyslog("ERROR: attempt to open OSD while it is already open - using dummy OSD!");
else if (osdProvider) else if (osdProvider) {
return osdProvider->CreateOsd(Left, Top); cOsd *ActiveOsd = cOsd::Osds.Size() ? cOsd::Osds[0] : NULL;
cOsd *Osd = osdProvider->CreateOsd(Left, Top, Level);
if (Osd == cOsd::Osds[0]) {
if (ActiveOsd)
ActiveOsd->SetActive(false);
Osd->SetActive(true);
}
return Osd;
}
else else
esyslog("ERROR: no OSD provider available - using dummy OSD!"); esyslog("ERROR: no OSD provider available - using dummy OSD!");
return new cOsd(Left, Top); // create a dummy cOsd, so that access won't result in a segfault return new cOsd(Left, Top, 999); // create a dummy cOsd, so that access won't result in a segfault
} }
void cOsdProvider::Shutdown(void) void cOsdProvider::Shutdown(void)

24
osd.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.h 1.56 2007/07/20 14:50:17 kls Exp $ * $Id: osd.h 1.57 2007/08/26 09:45:38 kls Exp $
*/ */
#ifndef __OSD_H #ifndef __OSD_H
@ -15,6 +15,7 @@
#include <stdint.h> #include <stdint.h>
#include "config.h" #include "config.h"
#include "font.h" #include "font.h"
#include "tools.h"
#define MAXNUMCOLORS 256 #define MAXNUMCOLORS 256
@ -247,13 +248,15 @@ class cOsd {
friend class cOsdProvider; friend class cOsdProvider;
private: private:
static int osdLeft, osdTop, osdWidth, osdHeight; static int osdLeft, osdTop, osdWidth, osdHeight;
static int isOpen; static cVector<cOsd *> Osds;
cBitmap *savedRegion; cBitmap *savedRegion;
cBitmap *bitmaps[MAXOSDAREAS]; cBitmap *bitmaps[MAXOSDAREAS];
int numBitmaps; int numBitmaps;
int left, top, width, height; int left, top, width, height;
uint level;
bool active;
protected: protected:
cOsd(int Left, int Top); cOsd(int Left, int Top, uint Level);
///< Initializes the OSD with the given coordinates. ///< Initializes the OSD with the given coordinates.
///< By default it is assumed that the full area will be able to display ///< By default it is assumed that the full area will be able to display
///< full 32 bit graphics (ARGB with eight bit for each color and the alpha ///< full 32 bit graphics (ARGB with eight bit for each color and the alpha
@ -269,6 +272,14 @@ protected:
///< and should require only the minimum necessary color depth. This is ///< and should require only the minimum necessary color depth. This is
///< because a derived cOsd class may or may not be able to handle more ///< because a derived cOsd class may or may not be able to handle more
///< than one area. ///< than one area.
///< There can be any number of cOsd objects at the same time, but only
///< one of them will be active at any given time. The active OSD is the
///< one with the lowest value of Level. If there are several cOsd objects
///< with the same Level, the one that was created first will be active.
bool Active(void) { return active; }
virtual void SetActive(bool On) { active = On; }
///< Sets this OSD to be the active one.
///< A derived class must call cOsd::SetActive(On).
public: public:
virtual ~cOsd(); virtual ~cOsd();
///< Shuts down the OSD. ///< Shuts down the OSD.
@ -281,7 +292,8 @@ public:
///< This may be useful for plugins that determine the scaling of the ///< This may be useful for plugins that determine the scaling of the
///< video image and need to scale the OSD accordingly to fit on the ///< video image and need to scale the OSD accordingly to fit on the
///< screen. ///< screen.
static int IsOpen(void) { return isOpen; } static int IsOpen(void) { return Osds.Size() && Osds[0]->level == 0; }
///< Returns true if there is currently a level 0 OSD open.
int Left(void) { return left; } int Left(void) { return left; }
int Top(void) { return top; } int Top(void) { return top; }
int Width(void) { return width; } int Width(void) { return width; }
@ -379,14 +391,14 @@ class cOsdProvider {
private: private:
static cOsdProvider *osdProvider; static cOsdProvider *osdProvider;
protected: protected:
virtual cOsd *CreateOsd(int Left, int Top) = 0; virtual cOsd *CreateOsd(int Left, int Top, uint Level) = 0;
///< Returns a pointer to a newly created cOsd object, which will be located ///< Returns a pointer to a newly created cOsd object, which will be located
///< at the given coordinates. ///< at the given coordinates.
public: public:
cOsdProvider(void); cOsdProvider(void);
//XXX maybe parameter to make this one "sticky"??? (frame-buffer etc.) //XXX maybe parameter to make this one "sticky"??? (frame-buffer etc.)
virtual ~cOsdProvider(); virtual ~cOsdProvider();
static cOsd *NewOsd(int Left, int Top); static cOsd *NewOsd(int Left, int Top, uint Level = 0);
///< Returns a pointer to a newly created cOsd object, which will be located ///< Returns a pointer to a newly created cOsd object, which will be located
///< at the given coordinates. When the cOsd object is no longer needed, the ///< at the given coordinates. When the cOsd object is no longer needed, the
///< caller must delete it. If the OSD is already in use, or there is no OSD ///< caller must delete it. If the OSD is already in use, or there is no OSD

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.107 2007/08/05 12:11:52 kls Exp $ * $Id: tools.h 1.108 2007/08/25 14:16:39 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -464,6 +464,12 @@ public:
Realloc(allocated * 4 / 2); // increase size by 50% Realloc(allocated * 4 / 2); // increase size by 50%
data[size++] = Data; data[size++] = Data;
} }
virtual void Remove(int Index)
{
if (Index < size - 1)
memmove(&data[Index], &data[Index + 1], (size - Index) * sizeof(T));
size--;
}
virtual void Clear(void) {} virtual void Clear(void) {}
void Sort(__compar_fn_t Compare) void Sort(__compar_fn_t Compare)
{ {