vdr 2.7.3
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 4.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
21class cDvbSdFfOsd : public cOsd {
22private:
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);
27protected:
28 virtual void SetActive(bool On);
29public:
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
37cDvbSdFfOsd::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
60
62{
63 if (On != Active()) {
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
85eOsdError 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
107eOsdError 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
119void 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
208cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top, uint Level)
209{
210 return new cDvbSdFfOsd(Left, Top, osdDev, Level);
211}
Definition osd.h:169
int Height(void) const
Definition osd.h:189
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
int X0(void) const
Definition osd.h:186
void Clean(void)
Marks the dirty area as clean.
Definition osd.c:354
int Y0(void) const
Definition osd.h:187
int Width(void) const
Definition osd.h:188
const tIndex * Data(int x, int y) const
Returns the address of the index byte at the given coordinates.
Definition osd.c:760
cDvbOsdProvider(int OsdDev)
Definition dvbsdffosd.c:203
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
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 ~cDvbSdFfOsd()
Definition dvbsdffosd.c:56
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
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition dvbsdffosd.c:107
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
cDvbSdFfOsd(int Left, int Top, int OsdDev, uint Level)
Definition dvbsdffosd.c:37
The cOsd class is the interface to the "On Screen Display".
Definition osd.h:753
cOsd(int Left, int Top, uint Level)
Initializes the OSD with the given coordinates.
Definition osd.c:1911
virtual void SetActive(bool On)
Sets this OSD to be the active one.
Definition osd.h:791
int Width(void)
Definition osd.h:844
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
Definition osd.c:2092
cBitmap * GetBitmap(int Area)
Returns a pointer to the bitmap for the given Area, or NULL if no such bitmap exists.
Definition osd.c:1967
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas)
Checks whether the OSD can display the given set of sub-areas.
Definition osd.c:2070
int Left(void)
Definition osd.h:842
int Top(void)
Definition osd.h:843
bool Active(void)
Definition osd.h:790
int Height(void)
Definition osd.h:845
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
int Bpp(void) const
Definition osd.h:111
#define MAXNUMWINDOWS
Definition dvbsdffosd.c:18
#define MAXOSDMEMORY
Definition dvbsdffosd.c:19
uint32_t tColor
Definition font.h:30
eOsdError
Definition osd.h:44
@ oeTooManyAreas
Definition osd.h:45
@ oeWrongAreaSize
Definition osd.h:51
@ oeOutOfMemory
Definition osd.h:50
@ oeWrongAlignment
Definition osd.h:49
@ oeOk
Definition osd.h:44
@ oeBppNotSupported
Definition osd.h:47
Definition osd.h:298
int Width(void) const
Definition osd.h:301
int bpp
Definition osd.h:300
int Height(void) const
Definition osd.h:302
#define esyslog(a...)
Definition tools.h:35