summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY11
-rw-r--r--dvbosd.c60
-rw-r--r--dvbosd.h4
-rw-r--r--osd.c43
-rw-r--r--osd.h24
-rw-r--r--tools.h8
6 files changed, 110 insertions, 40 deletions
diff --git a/HISTORY b/HISTORY
index a09b711b..e55f4cca 100644
--- a/HISTORY
+++ b/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.
diff --git a/dvbosd.c b/dvbosd.c
index 469ef1fb..87c8dec2 100644
--- a/dvbosd.c
+++ b/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);
}
diff --git a/dvbosd.h b/dvbosd.h
index 752b9fa1..ae8afb6d 100644
--- a/dvbosd.h
+++ b/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
diff --git a/osd.c b/osd.c
index 96dfc2e4..1c91184d 100644
--- a/osd.c
+++ b/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)
diff --git a/osd.h b/osd.h
index 08bc4184..604b2d22 100644
--- a/osd.h
+++ b/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
diff --git a/tools.h b/tools.h
index bd77f857..28dbd5ea 100644
--- a/tools.h
+++ b/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)
{