2000-10-03 10:34:48 +02:00
|
|
|
/*
|
2002-05-10 14:55:53 +02:00
|
|
|
* dvbosd.c: Implementation of the DVB On Screen Display
|
2000-10-03 10:34:48 +02:00
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2002-05-18 14:03:22 +02:00
|
|
|
* $Id: dvbosd.c 1.17 2002/05/18 13:39:02 kls Exp $
|
2000-10-03 10:34:48 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "dvbosd.h"
|
2000-10-08 09:25:20 +02:00
|
|
|
#include <signal.h>
|
2000-10-03 10:34:48 +02:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/unistd.h>
|
|
|
|
#include "tools.h"
|
|
|
|
|
2002-05-18 14:03:22 +02:00
|
|
|
cDvbOsd::cDvbOsd(int OsdDev, int x, int y)
|
2002-05-18 12:41:18 +02:00
|
|
|
:cOsdBase(x, y)
|
2000-10-03 10:34:48 +02:00
|
|
|
{
|
2002-05-18 14:03:22 +02:00
|
|
|
osdDev = OsdDev;
|
|
|
|
if (osdDev < 0)
|
|
|
|
esyslog("ERROR: illegal OSD device handle (%d)!", osdDev);
|
2000-10-03 10:34:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
cDvbOsd::~cDvbOsd()
|
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
for (int i = 0; i < NumWindows(); i++)
|
|
|
|
CloseWindow(GetWindowNr(i));
|
2000-10-03 10:34:48 +02:00
|
|
|
}
|
|
|
|
|
2002-01-13 15:55:08 +01:00
|
|
|
bool cDvbOsd::SetWindow(cWindow *Window)
|
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
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;
|
|
|
|
}
|
2002-05-13 16:35:49 +02:00
|
|
|
esyslog("ERROR: illegal window handle: %d", Handle);
|
2002-01-13 15:55:08 +01:00
|
|
|
}
|
2002-05-10 14:55:53 +02:00
|
|
|
return false;
|
2002-01-13 15:55:08 +01:00
|
|
|
}
|
|
|
|
|
2000-10-03 10:34:48 +02:00
|
|
|
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
|
|
|
|
{
|
2002-05-18 14:03:22 +02:00
|
|
|
if (osdDev >= 0) {
|
2001-06-02 10:47:40 +02:00
|
|
|
osd_cmd_t dc;
|
2000-10-03 10:34:48 +02:00
|
|
|
dc.cmd = cmd;
|
|
|
|
dc.color = color;
|
|
|
|
dc.x0 = x0;
|
|
|
|
dc.y0 = y0;
|
|
|
|
dc.x1 = x1;
|
|
|
|
dc.y1 = y1;
|
|
|
|
dc.data = (void *)data;
|
2000-10-08 09:25:20 +02:00
|
|
|
// must block all signals, otherwise the command might not be fully executed
|
|
|
|
sigset_t set, oldset;
|
|
|
|
sigfillset(&set);
|
2002-01-13 16:27:39 +01:00
|
|
|
sigdelset(&set, SIGALRM);
|
2000-10-08 09:25:20 +02:00
|
|
|
sigprocmask(SIG_BLOCK, &set, &oldset);
|
2002-05-18 14:03:22 +02:00
|
|
|
ioctl(osdDev, OSD_SEND_CMD, &dc);
|
2002-01-13 15:55:08 +01:00
|
|
|
if (cmd == OSD_SetBlock) // XXX this is the only command that takes longer
|
|
|
|
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.
|
2000-10-08 09:25:20 +02:00
|
|
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
2000-10-03 10:34:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-10 14:55:53 +02:00
|
|
|
bool cDvbOsd::OpenWindow(cWindow *Window)
|
2000-10-03 10:34:48 +02:00
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
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;
|
2002-01-13 15:55:08 +01:00
|
|
|
}
|
2002-05-10 14:55:53 +02:00
|
|
|
return false;
|
2001-07-22 12:33:45 +02:00
|
|
|
}
|
|
|
|
|
2002-05-10 14:55:53 +02:00
|
|
|
void cDvbOsd::CommitWindow(cWindow *Window)
|
2001-07-22 12:33:45 +02:00
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
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->Colors(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));
|
|
|
|
}
|
2002-01-13 15:55:08 +01:00
|
|
|
}
|
2001-07-22 12:33:45 +02:00
|
|
|
}
|
|
|
|
|
2002-05-10 14:55:53 +02:00
|
|
|
void cDvbOsd::ShowWindow(cWindow *Window)
|
2001-07-22 12:33:45 +02:00
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
if (SetWindow(Window))
|
|
|
|
Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0());
|
2001-07-22 12:33:45 +02:00
|
|
|
}
|
|
|
|
|
2002-05-10 14:55:53 +02:00
|
|
|
void cDvbOsd::HideWindow(cWindow *Window, bool Hide)
|
2001-07-22 12:33:45 +02:00
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
if (SetWindow(Window))
|
|
|
|
Cmd(Hide ? OSD_Hide : OSD_Show, 0);
|
2001-07-22 12:33:45 +02:00
|
|
|
}
|
|
|
|
|
2002-05-10 14:55:53 +02:00
|
|
|
void cDvbOsd::MoveWindow(cWindow *Window, int x, int y)
|
2001-07-22 12:33:45 +02:00
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
if (SetWindow(Window))
|
|
|
|
Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y);
|
2001-07-22 12:33:45 +02:00
|
|
|
}
|
|
|
|
|
2002-05-10 14:55:53 +02:00
|
|
|
void cDvbOsd::CloseWindow(cWindow *Window)
|
2001-07-22 12:33:45 +02:00
|
|
|
{
|
2002-05-10 14:55:53 +02:00
|
|
|
if (SetWindow(Window))
|
|
|
|
Cmd(OSD_Close);
|
2001-07-22 12:33:45 +02:00
|
|
|
}
|