diff options
Diffstat (limited to 'dvbosd.c')
-rw-r--r-- | dvbosd.c | 160 |
1 files changed, 98 insertions, 62 deletions
@@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbosd.c 1.21 2003/04/12 12:10:12 kls Exp $ + * $Id: dvbosd.c 1.22 2004/05/01 15:10:44 kls Exp $ */ #include "dvbosd.h" @@ -13,40 +13,49 @@ #include <sys/unistd.h> #include "tools.h" -const cDvbDevice *cDvbOsd::dvbDevice = NULL; +// --- cDvbOsd --------------------------------------------------------------- -cDvbOsd::cDvbOsd(int x, int y) -:cOsdBase(x, y) +#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7 +#define MAXOSDMEMORY 92000 // number of bytes available to the OSD (depends on firmware version, but there is no way of determining the actual value) + +cDvbOsd::cDvbOsd(int Left, int Top, int OsdDev) +:cOsd(Left, Top) { - osdDev = dvbDevice ? dvbDevice->OsdDeviceHandle() : -1; - if (dvbDevice && osdDev < 0) + osdDev = OsdDev; + shown = false; + if (osdDev < 0) esyslog("ERROR: illegal OSD device handle (%d)!", osdDev); } cDvbOsd::~cDvbOsd() { - for (int i = 0; i < NumWindows(); i++) - CloseWindow(GetWindowNr(i)); -} - -void cDvbOsd::SetDvbDevice(const cDvbDevice *DvbDevice) -{ - dvbDevice = DvbDevice; + if (shown) { + cBitmap *Bitmap; + for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { + Cmd(OSD_SetWindow, 0, i + 1); + Cmd(OSD_Close); + } + } } -bool cDvbOsd::SetWindow(cWindow *Window) +eOsdError cDvbOsd::CanHandleAreas(const tArea *Areas, int NumAreas) { - if (Window) { - // Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window - // numbers in the driver are used from 1...MAXNUMWINDOWS. - int Handle = Window->Handle(); - if (0 <= Handle && Handle < MAXNUMWINDOWS) { - Cmd(OSD_SetWindow, 0, Handle + 1); - return true; - } - esyslog("ERROR: illegal window handle: %d", Handle); + eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); + if (Result == oeOk) { + if (NumAreas > MAXNUMWINDOWS) + return oeTooManyAreas; + int TotalMemory = 0; + for (int i = 0; i < NumAreas; i++) { + if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8) + return oeBppNotSupported; + if ((Areas[i].Width() & (8 / Areas[i].bpp - 1)) != 0) + return oeWrongAlignment; + TotalMemory += Areas[i].Width() * Areas[i].Height() / (8 / Areas[i].bpp); + } + if (TotalMemory > MAXOSDMEMORY) + return oeOutOfMemory; } - return false; + return Result; } void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data) @@ -64,51 +73,78 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co } } -bool cDvbOsd::OpenWindow(cWindow *Window) -{ - if (SetWindow(Window)) { - Cmd(OSD_Open, Window->Bpp(), X0() + Window->X0(), Y0() + Window->Y0(), X0() + Window->X0() + Window->Width() - 1, Y0() + Window->Y0() + Window->Height() - 1, (void *)1); // initially hidden! - return true; - } - return false; -} - -void cDvbOsd::CommitWindow(cWindow *Window) +void cDvbOsd::Flush(void) { - if (SetWindow(Window)) { - int x1 = 0, y1 = 0, x2 = 0, y2 = 0; - if (Window->Dirty(x1, y1, x2, y2)) { - // commit colors: - int FirstColor = 0, LastColor = 0; - const eDvbColor *pal; - while ((pal = Window->NewColors(FirstColor, LastColor)) != NULL) - Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal); - // commit modified data: - Cmd(OSD_SetBlock, Window->Width(), x1, y1, x2, y2, Window->Data(x1, y1)); - } + 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)) { + //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!) + while ((x1 > 0 || x2 < Bitmap->Width() - 1) && ((x2 - x1) & 7) != 7) { + if (x2 < Bitmap->Width() - 1) + x2++; + else if (x1 > 0) + x1--; + } + //TODO "... / 2" <==> Bpp??? + while ((y1 > 0 || y2 < Bitmap->Height() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) { + if (y2 < Bitmap->Height() - 1) + y2++; + else if (y1 > 0) + y1--; + } + while ((x1 > 0 || x2 < Bitmap->Width() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) { + if (x2 < Bitmap->Width() - 1) + x2++; + else if (x1 > 0) + x1--; + } + // commit colors: + int NumColors; + const tColor *Colors = Bitmap->Colors(NumColors); + if (Colors) { + //TODO this should be fixed in the driver! + tColor colors[NumColors]; + for (int i = 0; i < NumColors; i++) { + // convert AARRGGBB to AABBGGRR (the driver expects the colors the wrong way): + colors[i] = (Colors[i] & 0xFF000000) | ((Colors[i] & 0x0000FF) << 16) | (Colors[i] & 0x00FF00) | ((Colors[i] & 0xFF0000) >> 16); +#if __BYTE_ORDER == __BIG_ENDIAN + // actually the driver itself should access the bytes according to the current endianness! + colors[i] = ((colors[i] & 0xFF) << 24) | ((colors[i] & 0xFF00) << 8) | ((colors[i] & 0xFF0000) >> 8) | ((colors[i] & 0xFF000000) >> 24); +#endif + } + Colors = colors; + //TODO end of stuff that should be fixed in the driver + Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors); + } + // commit modified data: + Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1)); + } + Bitmap->Clean(); + } + if (!shown) { + // Showing the windows in a separate loop to avoid seeing them come up one after another + for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) { + Cmd(OSD_SetWindow, 0, i + 1); + Cmd(OSD_MoveWindow, 0, Left() + Bitmap->X0(), Top() + Bitmap->Y0()); + } + shown = true; } } -void cDvbOsd::ShowWindow(cWindow *Window) -{ - if (SetWindow(Window)) - Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0()); -} - -void cDvbOsd::HideWindow(cWindow *Window, bool Hide) -{ - if (SetWindow(Window)) - Cmd(Hide ? OSD_Hide : OSD_Show, 0); -} +// --- cDvbOsdProvider ------------------------------------------------------- -void cDvbOsd::MoveWindow(cWindow *Window, int x, int y) +cDvbOsdProvider::cDvbOsdProvider(int OsdDev) { - if (SetWindow(Window)) - Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y); + osdDev = OsdDev; } -void cDvbOsd::CloseWindow(cWindow *Window) +cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top) { - if (SetWindow(Window)) - Cmd(OSD_Close); + return new cDvbOsd(Left, Top, osdDev); } |