vdr  2.2.0
dvbsdffosd.c
Go to the documentation of this file.
1 /*
2  * dvbsdffosd.c: Implementation of the DVB SD Full Featured On Screen Display
3  *
4  * See the README file for copyright information and how to reach the author.
5  *
6  * $Id: dvbsdffosd.c 3.0 2011/04/17 12:55:09 kls Exp $
7  */
8 
9 #include "dvbsdffosd.h"
10 #include <linux/dvb/osd.h>
11 #include <signal.h>
12 #include <sys/ioctl.h>
13 #include <sys/unistd.h>
14 #include <vdr/tools.h>
15 
16 // --- cDvbSdFfOsd -----------------------------------------------------------
17 
18 #define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
19 #define MAXOSDMEMORY 92000 // number of bytes available to the OSD (for unmodified DVB cards)
20 
21 class cDvbSdFfOsd : public cOsd {
22 private:
23  int osdDev;
24  int osdMem;
25  bool shown;
26  void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
27 protected:
28  virtual void SetActive(bool On);
29 public:
30  cDvbSdFfOsd(int Left, int Top, int OsdDev, uint Level);
31  virtual ~cDvbSdFfOsd();
32  virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
33  virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
34  virtual void Flush(void);
35  };
36 
37 cDvbSdFfOsd::cDvbSdFfOsd(int Left, int Top, int OsdDev, uint Level)
38 :cOsd(Left, Top, Level)
39 {
40  osdDev = OsdDev;
41  shown = false;
42  if (osdDev < 0)
43  esyslog("ERROR: invalid OSD device handle (%d)!", osdDev);
44  else {
46 #ifdef OSD_CAP_MEMSIZE
47  // modified DVB cards may have more OSD memory:
48  osd_cap_t cap;
49  cap.cmd = OSD_CAP_MEMSIZE;
50  if (ioctl(osdDev, OSD_GET_CAPABILITY, &cap) == 0)
51  osdMem = cap.val;
52 #endif
53  }
54 }
55 
57 {
58  SetActive(false);
59 }
60 
62 {
63  if (On != Active()) {
64  cOsd::SetActive(On);
65  if (On) {
66  // must clear all windows here to avoid flashing effects - doesn't work if done
67  // in Flush() only for the windows that are actually used...
68  for (int i = 0; i < MAXNUMWINDOWS; i++) {
69  Cmd(OSD_SetWindow, 0, i + 1);
70  Cmd(OSD_Clear);
71  }
72  if (GetBitmap(0)) // only flush here if there are already bitmaps
73  Flush();
74  }
75  else if (shown) {
76  for (int i = 0; GetBitmap(i); i++) {
77  Cmd(OSD_SetWindow, 0, i + 1);
78  Cmd(OSD_Close);
79  }
80  shown = false;
81  }
82  }
83 }
84 
85 eOsdError cDvbSdFfOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
86 {
87  eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
88  if (Result == oeOk) {
89  if (NumAreas > MAXNUMWINDOWS)
90  return oeTooManyAreas;
91  int TotalMemory = 0;
92  for (int i = 0; i < NumAreas; i++) {
93  if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8)
94  return oeBppNotSupported;
95  if ((Areas[i].Width() & (8 / Areas[i].bpp - 1)) != 0)
96  return oeWrongAlignment;
97  if (Areas[i].Width() < 1 || Areas[i].Height() < 1 || Areas[i].Width() > 720 || Areas[i].Height() > 576)
98  return oeWrongAreaSize;
99  TotalMemory += Areas[i].Width() * Areas[i].Height() / (8 / Areas[i].bpp);
100  }
101  if (TotalMemory > osdMem)
102  return oeOutOfMemory;
103  }
104  return Result;
105 }
106 
107 eOsdError cDvbSdFfOsd::SetAreas(const tArea *Areas, int NumAreas)
108 {
109  if (shown) {
110  for (int i = 0; GetBitmap(i); i++) {
111  Cmd(OSD_SetWindow, 0, i + 1);
112  Cmd(OSD_Close);
113  }
114  shown = false;
115  }
116  return cOsd::SetAreas(Areas, NumAreas);
117 }
118 
119 void cDvbSdFfOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
120 {
121  if (osdDev >= 0) {
122  osd_cmd_t dc;
123  dc.cmd = cmd;
124  dc.color = color;
125  dc.x0 = x0;
126  dc.y0 = y0;
127  dc.x1 = x1;
128  dc.y1 = y1;
129  dc.data = (void *)data;
130  ioctl(osdDev, OSD_SEND_CMD, &dc);
131  }
132 }
133 
135 {
136  if (!Active())
137  return;
138  cBitmap *Bitmap;
139  for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
140  Cmd(OSD_SetWindow, 0, i + 1);
141  if (!shown)
142  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!
143  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
144  if (!shown || Bitmap->Dirty(x1, y1, x2, y2)) {
145  if (!shown) {
146  x1 = y1 = 0;
147  x2 = Bitmap->Width() - 1;
148  y2 = Bitmap->Height() - 1;
149  }
150  //TODO Workaround: apparently the bitmap sent to the driver always has to be a multiple
151  //TODO of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
152  //TODO Fix driver (should be able to handle any size bitmaps!)
153  while ((x1 > 0 || x2 < Bitmap->Width() - 1) && ((x2 - x1) & 7) != 7) {
154  if (x2 < Bitmap->Width() - 1)
155  x2++;
156  else if (x1 > 0)
157  x1--;
158  }
159  //TODO "... / 2" <==> Bpp???
160  while ((y1 > 0 || y2 < Bitmap->Height() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) {
161  if (y2 < Bitmap->Height() - 1)
162  y2++;
163  else if (y1 > 0)
164  y1--;
165  }
166  while ((x1 > 0 || x2 < Bitmap->Width() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) {
167  if (x2 < Bitmap->Width() - 1)
168  x2++;
169  else if (x1 > 0)
170  x1--;
171  }
172  // commit colors:
173  int NumColors;
174  const tColor *Colors = Bitmap->Colors(NumColors);
175  if (Colors) {
176  //TODO this should be fixed in the driver!
177  tColor colors[NumColors];
178  for (int i = 0; i < NumColors; i++) {
179  // convert AARRGGBB to AABBGGRR (the driver expects the colors the wrong way):
180  colors[i] = (Colors[i] & 0xFF000000) | ((Colors[i] & 0x0000FF) << 16) | (Colors[i] & 0x00FF00) | ((Colors[i] & 0xFF0000) >> 16);
181  }
182  Colors = colors;
183  //TODO end of stuff that should be fixed in the driver
184  Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors);
185  }
186  // commit modified data:
187  Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
188  }
189  Bitmap->Clean();
190  }
191  if (!shown) {
192  // Showing the windows in a separate loop to avoid seeing them come up one after another
193  for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
194  Cmd(OSD_SetWindow, 0, i + 1);
195  Cmd(OSD_MoveWindow, 0, Left() + Bitmap->X0(), Top() + Bitmap->Y0());
196  }
197  shown = true;
198  }
199 }
200 
201 // --- cDvbOsdProvider -------------------------------------------------------
202 
204 {
205  osdDev = OsdDev;
206 }
207 
208 cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top, uint Level)
209 {
210  return new cDvbSdFfOsd(Left, Top, osdDev, Level);
211 }
#define MAXNUMWINDOWS
Definition: dvbsdffosd.c:18
void Clean(void)
Marks the dirty area as clean.
Definition: osd.c:354
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition: osd.c:1823
virtual void SetActive(bool On)
Sets this OSD to be the active one.
Definition: osd.h:757
const tColor * Colors(int &NumColors) const
Returns a pointer to the complete color table and stores the number of valid entries in NumColors...
Definition: osd.c:185
#define esyslog(a...)
Definition: tools.h:34
int bpp
Definition: osd.h:300
bool Active(void)
Definition: osd.h:756
#define MAXOSDMEMORY
Definition: dvbsdffosd.c:19
virtual void Flush(void)
Actually commits all data to the OSD hardware.
Definition: dvbsdffosd.c:134
virtual void SetActive(bool On)
Sets this OSD to be the active one.
Definition: dvbsdffosd.c:61
int Bpp(void) const
Definition: osd.h:111
virtual ~cDvbSdFfOsd()
Definition: dvbsdffosd.c:56
Definition: osd.h:169
int Width(void) const
Definition: osd.h:188
int Width(void) const
Definition: osd.h:301
int Top(void)
Definition: osd.h:801
bool Dirty(int &x1, int &y1, int &x2, int &y2)
Tells whether there is a dirty area and returns the bounding rectangle of that area (relative to the ...
Definition: osd.c:342
cDvbOsdProvider(int OsdDev)
Definition: dvbsdffosd.c:203
int Height(void) const
Definition: osd.h:189
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas)
Checks whether the OSD can display the given set of sub-areas.
Definition: osd.c:1801
The cOsd class is the interface to the "On Screen Display".
Definition: osd.h:720
void Cmd(OSD_Command cmd, int color=0, int x0=0, int y0=0, int x1=0, int y1=0, const void *data=NULL)
Definition: dvbsdffosd.c:119
int Height(void)
Definition: osd.h:803
int Y0(void) const
Definition: osd.h:187
virtual cOsd * CreateOsd(int Left, int Top, uint Level)
Returns a pointer to a newly created cOsd object, which will be located at the given coordinates...
Definition: dvbsdffosd.c:208
const tIndex * Data(int x, int y) const
Returns the address of the index byte at the given coordinates.
Definition: osd.c:760
int Height(void) const
Definition: osd.h:302
cDvbSdFfOsd(int Left, int Top, int OsdDev, uint Level)
Definition: dvbsdffosd.c:37
Definition: osd.h:298
int Width(void)
Definition: osd.h:802
eOsdError
Definition: osd.h:44
int Left(void)
Definition: osd.h:800
Definition: osd.h:44
int X0(void) const
Definition: osd.h:186
bool shown
Definition: dvbsdffosd.c:25
cBitmap * GetBitmap(int Area)
Returns a pointer to the bitmap for the given Area, or NULL if no such bitmap exists.
Definition: osd.c:1703
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas)
Checks whether the OSD can display the given set of sub-areas.
Definition: dvbsdffosd.c:85
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition: dvbsdffosd.c:107
uint32_t tColor
Definition: font.h:29