From 8f9cc68f76c4fd0960f919a77fb16a6455922deb Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 29 Jul 2001 18:00:00 +0200 Subject: =?UTF-8?q?Version=200.85=20-=20Added=20Norwegian=20language=20tex?= =?UTF-8?q?ts=20(thanks=20to=20J=F8rgen=20Tvedt).=20-=20Increased=20the=20?= =?UTF-8?q?usleep=20value=20in=20cDvbOsd::Cmd()=20to=205000=20in=20order?= =?UTF-8?q?=20to=20work=20on=20=20=20systems=20with=20the=20KURT/utime-pat?= =?UTF-8?q?ch=20(thanks=20to=20Guido=20Fiala).=20-=20Changed=20the=20check?= =?UTF-8?q?=20whether=20the=20driver=20is=20loaded=20in=20runvdr=20to=20ch?= =?UTF-8?q?eck=20for=20the=20=20=20'dvb'=20module=20(the=20last=20one=20lo?= =?UTF-8?q?aded).=20-=20Fixed=20repeat=20function=20with=20LIRC=20(thanks?= =?UTF-8?q?=20to=20Stefan=20Huelswitt).=20-=20Increased=20the=20upper=20li?= =?UTF-8?q?mit=20for=20the=20symbol=20rate=20to=2030000=20(thanks=20to=20U?= =?UTF-8?q?lrich=20=20=20R=F6der).=20-=20Made=20the=20position=20of=20the?= =?UTF-8?q?=20channel=20display=20configurable=20(thanks=20to=20Stefan=20?= =?UTF-8?q?=20=20Huelswitt).=20-=20Made=20the=20width=20and=20height=20of?= =?UTF-8?q?=20the=20OSD=20configurable=20(thanks=20to=20Stefan=20Huelswitt?= =?UTF-8?q?).=20-=20DiSEqC=20support=20can=20now=20be=20generally=20enable?= =?UTF-8?q?d/disabled=20in=20the=20Setup=20menu.=20This=20=20=20may=20be?= =?UTF-8?q?=20necessary=20if=20your=20multiswitch=20gets=20irritated=20by?= =?UTF-8?q?=20the=20default=20DiSEqC=20=20=20codes=20'0'=20(thanks=20to=20?= =?UTF-8?q?Markus=20Lang).=20-=20Fixed=20replaying=20in=20case=20there=20i?= =?UTF-8?q?s=20no=20index=20file.=20-=20Fixed=20jumping=20to=20an=20editin?= =?UTF-8?q?g=20mark=20when=20replay=20has=20been=20paused.=20-=20Avoiding?= =?UTF-8?q?=20unnecessary=20code=20execution=20in=20the=20replay=20progres?= =?UTF-8?q?s=20display=20(thanks=20=20=20to=20Guido=20Fiala).=20-=20When?= =?UTF-8?q?=20entering=20time=20values=20the=20digits=20that=20still=20hav?= =?UTF-8?q?e=20to=20be=20entered=20are=20now=20=20=20shown=20as=20'-'=20(a?= =?UTF-8?q?s=20in=20"1-:--").=20-=20When=20setting=20an=20editing=20mark?= =?UTF-8?q?=20while=20the=20progress=20display=20is=20not=20active,=20the?= =?UTF-8?q?=20=20=20display=20will=20now=20be=20turned=20on=20for=20a=20sh?= =?UTF-8?q?ort=20while=20to=20indicate=20the=20successful=20=20=20setting?= =?UTF-8?q?=20of=20the=20mark.=20-=20Updated=20'channels.conf'=20for=20Pre?= =?UTF-8?q?miere=20World=20(thanks=20to=20Helmut=20Sch=E4chner).=20=20=20C?= =?UTF-8?q?heck=20your=20timers=20if=20you=20use=20this=20channels.conf=20?= =?UTF-8?q?file,=20since=20the=20sequence=20of=20=20=20several=20PW=20chan?= =?UTF-8?q?nels=20has=20been=20changed.=20-=20Changed=20the=20color=20of?= =?UTF-8?q?=20"Info"=20messages=20to=20"black=20on=20green"=20and=20that?= =?UTF-8?q?=20of=20the=20=20=20confirmation=20messages=20(like=20"Delete..?= =?UTF-8?q?.")=20to=20"black=20on=20yellow".=20-=20Fixed=20display=20with?= =?UTF-8?q?=20DEBUG=5FOSD=20(it=20still=20crashes=20sometimes,=20esp.=20wh?= =?UTF-8?q?en=20replaying,=20=20=20but=20I=20can't=20seem=20to=20find=20wh?= =?UTF-8?q?at=20causes=20this...=20any=20ideas=20anybody=3F).=20-=20Avoidi?= =?UTF-8?q?ng=20audio/video=20distortions=20in=20'Transfer=20Mode'=20by=20?= =?UTF-8?q?no=20longer=20actually=20=20=20tuning=20the=20primary=20interfa?= =?UTF-8?q?ce=20(which=20can't=20receive=20this=20channel,=20anyway).=20?= =?UTF-8?q?=20=20Apparently=20the=20driver=20gets=20irritated=20when=20the?= =?UTF-8?q?=20channel=20is=20switched=20and=20a=20=20=20replay=20session?= =?UTF-8?q?=20is=20started=20immediately=20after=20that.=20-=20Increased?= =?UTF-8?q?=20timeout=20until=20reporting=20"video=20data=20stream=20broke?= =?UTF-8?q?n"=20when=20recording.=20-=20Explicitly=20switching=20back=20to?= =?UTF-8?q?=20the=20previously=20active=20channel=20after=20ending=20a=20?= =?UTF-8?q?=20=20replay=20session=20(to=20have=20it=20shown=20correctly=20?= =?UTF-8?q?in=20case=20it=20was=20in=20'Transfer=20Mode').?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dvbosd.c | 352 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 305 insertions(+), 47 deletions(-) (limited to 'dvbosd.c') diff --git a/dvbosd.c b/dvbosd.c index 395ad32..90ac067 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.7 2000/12/09 11:13:00 kls Exp $ + * $Id: dvbosd.c 1.10 2001/07/24 16:25:34 kls Exp $ */ #include "dvbosd.h" @@ -14,12 +14,83 @@ #include #include "tools.h" +// --- cPalette -------------------------------------------------------------- + +cPalette::cPalette(int Bpp) +{ + maxColors = 1 << Bpp; + numColors = 0; + full = false; +} + +int cPalette::Index(eDvbColor Color) +{ + for (int i = 0; i < numColors; i++) { + if (color[i] == Color) { + used[i] = true; + return i; + } + } + if (!full) { + if (numColors < maxColors) { + color[numColors++] = Color; + used[numColors - 1] = true; + fetched[numColors - 1] = false; + return numColors - 1; + } + for (int i = maxColors; --i >= 0; ) { + if (!used[i]) { + color[i] = Color; + used[i] = true; + fetched[i] = false; + return i; + } + } + esyslog(LOG_ERR, "ERROR: too many different colors used in palette"); + full = true; + } + return 0; +} + +void cPalette::Reset(void) +{ + for (int i = 0; i < numColors; i++) + used[i] = false; + full = false; +} + +const eDvbColor *cPalette::Colors(int &FirstColor, int &LastColor) +{ + for (FirstColor = 0; FirstColor < numColors; FirstColor++) { + if (!fetched[FirstColor]) { + for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++) + fetched[LastColor] = true; + LastColor--; // the loop ended one past the last one! + return &color[FirstColor]; + } + } + return NULL; +} + +void cPalette::Take(const cPalette &Palette, tIndexes *Indexes) +{ + for (int i = 0; i < Palette.numColors; i++) { + if (Palette.used[i]) { + int n = Index(Palette.color[i]); + if (Indexes) + (*Indexes)[i] = n; + } + } +} + // --- cBitmap --------------------------------------------------------------- -cBitmap::cBitmap(int Width, int Height) +cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground) +:cPalette(Bpp) { width = Width; height = Height; + clearWithBackground = ClearWithBackground; bitmap = NULL; fontType = fontOsd; font = NULL; @@ -27,7 +98,7 @@ cBitmap::cBitmap(int Width, int Height) bitmap = new char[width * height]; if (bitmap) { Clean(); - memset(bitmap, clrTransparent, width * height); + memset(bitmap, 0x00, width * height); SetFont(fontOsd); } else @@ -54,9 +125,38 @@ eDvbFont cBitmap::SetFont(eDvbFont Font) return oldFont; } -bool cBitmap::Dirty(void) +bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2) { - return dirtyX2 >= 0; + if (dirtyX2 >= 0) { + //XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple + //XXX 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 ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) { + if (dirtyX2 < width - 1) + dirtyX2++; + else if (dirtyX1 > 0) + dirtyX1--; + } + //XXX "... / 2" <==> Bpp??? + while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) { + if (dirtyY2 < height - 1) + dirtyY2++; + else if (dirtyY1 > 0) + dirtyY1--; + } + while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) { + if (dirtyX2 < width - 1) + dirtyX2++; + else if (dirtyX1 > 0) + dirtyX1--; + } + x1 = dirtyX1; + y1 = dirtyY1; + x2 = dirtyX2; + y2 = dirtyY2; + return true; + } + return false; } void cBitmap::Clean(void) @@ -67,12 +167,12 @@ void cBitmap::Clean(void) dirtyY2 = -1; } -void cBitmap::SetPixel(int x, int y, eDvbColor Color) +void cBitmap::SetIndex(int x, int y, char Index) { if (bitmap) { if (0 <= x && x < width && 0 <= y && y < height) { - if (bitmap[width * y + x] != Color) { - bitmap[width * y + x] = Color; + if (bitmap[width * y + x] != Index) { + bitmap[width * y + x] = Index; if (dirtyX1 > x) dirtyX1 = x; if (dirtyY1 > y) dirtyY1 = y; if (dirtyX2 < x) dirtyX2 = x; @@ -82,12 +182,19 @@ void cBitmap::SetPixel(int x, int y, eDvbColor Color) } } +void cBitmap::SetPixel(int x, int y, eDvbColor Color) +{ + SetIndex(x, y, Index(Color)); +} + void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap) { if (bitmap && Bitmap.bitmap) { + tIndexes Indexes; + Take(Bitmap, &Indexes); for (int ix = 0; ix < Bitmap.width; ix++) { for (int iy = 0; iy < Bitmap.height; iy++) - SetPixel(x + ix, y + iy, eDvbColor(Bitmap.bitmap[Bitmap.width * iy + ix])); + SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]); } } } @@ -105,6 +212,8 @@ int cBitmap::Width(const char *s) void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg) { if (bitmap) { + char fg = Index(ColorFg); + char bg = Index(ColorBg); int h = font->Height(s); while (s && *s) { const cFont::tCharData *CharData = font->CharData(*s++); @@ -113,7 +222,7 @@ void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor Col for (int row = 0; row < h; row++) { cFont::tPixelData PixelData = CharData->lines[row]; for (int col = CharData->width; col-- > 0; ) { - SetPixel(x + col, y + row, (PixelData & 1) ? ColorFg : ColorBg); + SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg); PixelData >>= 1; } } @@ -125,39 +234,109 @@ void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor Col void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color) { if (bitmap) { + char c = Index(Color); for (int y = y1; y <= y2; y++) for (int x = x1; x <= x2; x++) - SetPixel(x, y, Color); + SetIndex(x, y, c); } } void cBitmap::Clear(void) { - Fill(0, 0, width - 1, height - 1, clrBackground); + Reset(); + if (clearWithBackground) + Fill(0, 0, width - 1, height - 1, clrBackground); +} + +const char *cBitmap::Data(int x, int y) +{ + return &bitmap[y * width + x]; +} + +// --- cWindow --------------------------------------------------------------- + +class cWindow : public cBitmap { +private: + int x0, y0; + bool shown; +public: + cWindow(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true); + int X0(void) { return x0; } + int Y0(void) { return y0; } + bool Shown(void) { bool s = shown; shown = true; return s; } + bool Contains(int x, int y); + void Fill(int x1, int y1, int x2, int y2, eDvbColor Color); + void SetBitmap(int x, int y, const cBitmap &Bitmap); + void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground); + const char *Data(int x, int y); + }; + +cWindow::cWindow(int x, int y, int w, int h, int Bpp, bool ClearWithBackground) +:cBitmap(w, h, Bpp, ClearWithBackground) +{ + x0 = x; + y0 = y; + shown = false; +} + +bool cWindow::Contains(int x, int y) +{ + x -= x0; + y -= y0; + return x >= 0 && y >= 0 && x < width && y < height; +} + +void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color) +{ + cBitmap::Fill(x1 - x0, y1 - y0, x2 - x0, y2 - y0, Color); +} + +void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap) +{ + cBitmap::SetBitmap(x - x0, y - y0, Bitmap); +} + +void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg) +{ + cBitmap::Text(x - x0, y - y0, s, ColorFg, ColorBg); +} + +const char *cWindow::Data(int x, int y) +{ + return cBitmap::Data(x, y); } // --- cDvbOsd --------------------------------------------------------------- -cDvbOsd::cDvbOsd(int VideoDev, int x1, int y1, int x2, int y2, int Bpp) -:cBitmap(x2 - x1 + 1, y2 - y1 + 1) +cDvbOsd::cDvbOsd(int VideoDev, int x, int y, int w, int h, int Bpp) { videoDev = VideoDev; - if (videoDev >= 0) - Cmd(OSD_Open, Bpp, x1, y1, x2, y2); + numWindows = 0; + x0 = x; + y0 = y; + if (videoDev >= 0) { + if (w > 0 && h > 0) + Create(0, 0, w, h, Bpp); + } else esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev); } cDvbOsd::~cDvbOsd() { - if (videoDev >= 0) - Cmd(OSD_Close); + if (videoDev >= 0) { + while (numWindows > 0) { + Cmd(OSD_SetWindow, 0, numWindows--); + Cmd(OSD_Close); + delete window[numWindows]; + } + } } void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data) { if (videoDev >= 0) { - struct drawcmd dc; + osd_cmd_t dc; dc.cmd = cmd; dc.color = color; dc.x0 = x0; @@ -169,41 +348,120 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co sigset_t set, oldset; sigfillset(&set); sigprocmask(SIG_BLOCK, &set, &oldset); - ioctl(videoDev, VIDIOCSOSDCOMMAND, &dc); - usleep(10); // XXX Workaround for a driver bug (cInterface::DisplayChannel() displayed texts at wrong places - // XXX and sometimes the OSD was no longer displayed). - // XXX Increase the value if the problem still persists on your particular system. - // TODO Check if this is still necessary with driver versions after 0.7. + ioctl(videoDev, OSD_SEND_CMD, &dc); + usleep(5000); // XXX Workaround for a driver bug (cInterface::DisplayChannel() displayed texts at wrong places + // XXX and sometimes the OSD was no longer displayed). + // XXX Increase the value if the problem still persists on your particular system. + // TODO Check if this is still necessary with driver versions after 0.7. sigprocmask(SIG_SETMASK, &oldset, NULL); } } -void cDvbOsd::Flush(void) +bool cDvbOsd::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, eDvbColor Color0, eDvbColor Color1, eDvbColor Color2, eDvbColor Color3) { - if (Dirty()) { - //XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple - //XXX 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 ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) { - if (dirtyX2 < width - 1) - dirtyX2++; - else if (dirtyX1 > 0) - dirtyX1--; - } - while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) { - if (dirtyY2 < height - 1) - dirtyY2++; - else if (dirtyY1 > 0) - dirtyY1--; + /* TODO XXX + - check that no two windows overlap + */ + if (numWindows < MAXNUMWINDOWS) { + if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) { + if ((w & 0x03) != 0) { + w += 4 - (w & 0x03); + esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", w); } - while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) { - if (dirtyX2 < width - 1) - dirtyX2++; - else if (dirtyX1 > 0) - dirtyX1--; + cWindow *win = new cWindow(x, y, w, h, Bpp, ClearWithBackground); + if (Color0 != clrTransparent) { + win->Index(Color0); + win->Index(Color1); + win->Index(Color2); + win->Index(Color3); + win->Reset(); } - Cmd(OSD_SetBlock, width, dirtyX1, dirtyY1, dirtyX2, dirtyY2, &bitmap[dirtyY1 * width + dirtyX1]); - Clean(); + window[numWindows++] = win; + Cmd(OSD_SetWindow, 0, numWindows); + Cmd(OSD_Open, Bpp, x0 + x, y0 + y, x0 + x + w - 1, y0 + y + h - 1, (void *)1); // initially hidden! + } + else + esyslog(LOG_ERR, "ERROR: illegal OSD parameters"); } + else + esyslog(LOG_ERR, "ERROR: too many OSD windows"); + return false; +} + +cWindow *cDvbOsd::GetWindow(int x, int y) +{ + for (int i = 0; i < numWindows; i++) { + if (window[i]->Contains(x, y)) + return window[i]; + } + return NULL; +} + +void cDvbOsd::Flush(void) +{ + for (int i = 0; i < numWindows; i++) { + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + if (window[i]->Dirty(x1, y1, x2, y2)) { + Cmd(OSD_SetWindow, 0, i + 1); + int FirstColor = 0, LastColor = 0; + const eDvbColor *pal; + while ((pal = window[i]->Colors(FirstColor, LastColor)) != NULL) + Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal); + Cmd(OSD_SetBlock, window[i]->Width(), x1, y1, x2, y2, window[i]->Data(x1, y1)); + window[i]->Clean(); + } + } + // Showing the windows in a separate loop to avoid seeing them come up one after another + for (int i = 0; i < numWindows; i++) { + if (!window[i]->Shown()) { + Cmd(OSD_SetWindow, 0, i + 1); + Cmd(OSD_MoveWindow, 0, x0 + window[i]->X0(), y0 + window[i]->Y0()); + } + } +} + +void cDvbOsd::Clear(void) +{ + for (int i = 0; i < numWindows; i++) + window[i]->Clear(); +} + +void cDvbOsd::Fill(int x1, int y1, int x2, int y2, eDvbColor Color) +{ + cWindow *w = GetWindow(x1, y1); + if (w) + w->Fill(x1, y1, x2, y2, Color); +} + +void cDvbOsd::SetBitmap(int x, int y, const cBitmap &Bitmap) +{ + cWindow *w = GetWindow(x, y); + if (w) + w->SetBitmap(x, y, Bitmap); +} + +int cDvbOsd::Width(unsigned char c) +{ + return numWindows ? window[0]->Width(c) : 0; +} + +int cDvbOsd::Width(const char *s) +{ + return numWindows ? window[0]->Width(s) : 0; +} + +eDvbFont cDvbOsd::SetFont(eDvbFont Font) +{ + eDvbFont oldFont = Font; + for (int i = 0; i < numWindows; i++) + oldFont = window[i]->SetFont(Font); + return oldFont; +} + +void cDvbOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground) +{ + cWindow *w = GetWindow(x, y); + if (w) + w->Text(x, y, s, ColorFg, ColorBg); } -- cgit v1.2.3