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:
parent
6a737033ad
commit
a80915ff22
11
HISTORY
11
HISTORY
@ -5380,7 +5380,7 @@ Video Disk Recorder Revision History
|
||||
name of the plugin. The "newplugin" script has been changed accordingly, and
|
||||
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
|
||||
Anssi Hannula).
|
||||
@ -5405,3 +5405,12 @@ Video Disk Recorder Revision History
|
||||
option ':groups' is given (thanks to Andreas Mair).
|
||||
- Added a missing error report to cCuttingThread::Action() (thanks to Udo
|
||||
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.
|
||||
|
60
dvbosd.c
60
dvbosd.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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"
|
||||
@ -26,15 +26,17 @@ private:
|
||||
int osdMem;
|
||||
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);
|
||||
protected:
|
||||
virtual void SetActive(bool On);
|
||||
public:
|
||||
cDvbOsd(int Left, int Top, int OsdDev);
|
||||
cDvbOsd(int Left, int Top, int OsdDev, uint Level);
|
||||
virtual ~cDvbOsd();
|
||||
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
|
||||
virtual void Flush(void);
|
||||
};
|
||||
|
||||
cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev)
|
||||
:cOsd(Left, Top)
|
||||
cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev, uint Level)
|
||||
:cOsd(Left, Top, Level)
|
||||
{
|
||||
osdDev = OsdDev;
|
||||
shown = false;
|
||||
@ -49,23 +51,36 @@ cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev)
|
||||
if (ioctl(osdDev, OSD_GET_CAPABILITY, &cap) == 0)
|
||||
osdMem = cap.val;
|
||||
#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()
|
||||
{
|
||||
if (shown) {
|
||||
cBitmap *Bitmap;
|
||||
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
|
||||
Cmd(OSD_SetWindow, 0, i + 1);
|
||||
Cmd(OSD_Close);
|
||||
}
|
||||
SetActive(false);
|
||||
}
|
||||
|
||||
void cDvbOsd::SetActive(bool On)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!Active())
|
||||
return;
|
||||
cBitmap *Bitmap;
|
||||
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
|
||||
Cmd(OSD_SetWindow, 0, i + 1);
|
||||
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!
|
||||
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 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!)
|
||||
@ -173,7 +195,7 @@ cDvbOsdProvider::cDvbOsdProvider(int 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);
|
||||
}
|
||||
|
4
dvbosd.h
4
dvbosd.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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
|
||||
@ -17,7 +17,7 @@ private:
|
||||
int osdDev;
|
||||
public:
|
||||
cDvbOsdProvider(int OsdDev);
|
||||
virtual cOsd *CreateOsd(int Left, int Top);
|
||||
virtual cOsd *CreateOsd(int Left, int Top, uint Level);
|
||||
};
|
||||
|
||||
#endif //__DVBOSD_H
|
||||
|
43
osd.c
43
osd.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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"
|
||||
@ -646,18 +646,24 @@ int cOsd::osdLeft = 0;
|
||||
int cOsd::osdTop = 0;
|
||||
int cOsd::osdWidth = 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;
|
||||
numBitmaps = 0;
|
||||
left = Left;
|
||||
top = Top;
|
||||
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()
|
||||
@ -665,7 +671,14 @@ cOsd::~cOsd()
|
||||
for (int i = 0; i < numBitmaps; i++)
|
||||
delete bitmaps[i];
|
||||
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)
|
||||
@ -803,15 +816,23 @@ cOsdProvider::~cOsdProvider()
|
||||
osdProvider = NULL;
|
||||
}
|
||||
|
||||
cOsd *cOsdProvider::NewOsd(int Left, int Top)
|
||||
cOsd *cOsdProvider::NewOsd(int Left, int Top, uint Level)
|
||||
{
|
||||
if (Level == 0 && cOsd::IsOpen())
|
||||
esyslog("ERROR: attempt to open OSD while it is already open - using dummy OSD!");
|
||||
else if (osdProvider)
|
||||
return osdProvider->CreateOsd(Left, Top);
|
||||
else if (osdProvider) {
|
||||
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
|
||||
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)
|
||||
|
24
osd.h
24
osd.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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
|
||||
@ -15,6 +15,7 @@
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
#include "font.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define MAXNUMCOLORS 256
|
||||
|
||||
@ -247,13 +248,15 @@ class cOsd {
|
||||
friend class cOsdProvider;
|
||||
private:
|
||||
static int osdLeft, osdTop, osdWidth, osdHeight;
|
||||
static int isOpen;
|
||||
static cVector<cOsd *> Osds;
|
||||
cBitmap *savedRegion;
|
||||
cBitmap *bitmaps[MAXOSDAREAS];
|
||||
int numBitmaps;
|
||||
int left, top, width, height;
|
||||
uint level;
|
||||
bool active;
|
||||
protected:
|
||||
cOsd(int Left, int Top);
|
||||
cOsd(int Left, int Top, uint Level);
|
||||
///< Initializes the OSD with the given coordinates.
|
||||
///< 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
|
||||
@ -269,6 +272,14 @@ protected:
|
||||
///< 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
|
||||
///< 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:
|
||||
virtual ~cOsd();
|
||||
///< Shuts down the OSD.
|
||||
@ -281,7 +292,8 @@ public:
|
||||
///< 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
|
||||
///< 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 Top(void) { return top; }
|
||||
int Width(void) { return width; }
|
||||
@ -379,14 +391,14 @@ class cOsdProvider {
|
||||
private:
|
||||
static cOsdProvider *osdProvider;
|
||||
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
|
||||
///< at the given coordinates.
|
||||
public:
|
||||
cOsdProvider(void);
|
||||
//XXX maybe parameter to make this one "sticky"??? (frame-buffer etc.)
|
||||
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
|
||||
///< 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
|
||||
|
8
tools.h
8
tools.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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
|
||||
@ -464,6 +464,12 @@ public:
|
||||
Realloc(allocated * 4 / 2); // increase size by 50%
|
||||
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) {}
|
||||
void Sort(__compar_fn_t Compare)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user