#ifdef VIDEOSTATUS
#include <sys/ioctl.h>
#endif

#if VDRVERSNUM >= 10332
#include <vdr/device.h>
#endif

#ifdef HAVE_IMAGEMAGICK
#include "bitmap.h"
#endif

#include "DisplayChannel.h"
#include "vdrstatus.h"
#ifdef VIDEOSTATUS
#include "videostatus.h"
#endif
#include <vdr/menu.h>

#include "symbols/audio.xpm"
#include "symbols/dolbydigital.xpm"
#include "symbols/encrypted.xpm"
#include "symbols/radio.xpm"
#include "symbols/recording.xpm"
#include "symbols/teletext.xpm"
#include "symbols/vps.xpm"

#define Gap          5

cBitmap cSkinElchiDisplayChannel::bmVps(vps_xpm);
cBitmap cSkinElchiDisplayChannel::bmTeletext(teletext_xpm);
cBitmap cSkinElchiDisplayChannel::bmRadio(radio_xpm);
cBitmap cSkinElchiDisplayChannel::bmAudio(audio_xpm);
cBitmap cSkinElchiDisplayChannel::bmDolbyDigital(dolbydigital_xpm);
cBitmap cSkinElchiDisplayChannel::bmEncrypted(encrypted_xpm);
cBitmap cSkinElchiDisplayChannel::bmRecording(recording_xpm);

#ifdef VIDEOSTATUS
extern int fd_video;
bool video = true;
#endif
extern bool vdrosd;

// --- cSkinElchiDisplayChannel --------------------------------------------

cSkinElchiDisplayChannel::cSkinElchiDisplayChannel(bool WithInfo)
{
  noflush = true;
#ifdef DEBUG
  isyslog("skinelchi: cSkinElchiDisplayChannel::cSkinElchiDisplayChannel(%s)", WithInfo ? "'WithInfo'" : "'WithoutInfo'");
#endif
#ifdef VIDEOSTATUS
  asprintf(&oldvideoformatchar, " ");
  oldvideow = -1;
  VideoStatus.Update();
  oldbm = NULL;
#endif
  message = changed = false;
  showVolume = false;
  volumechange = VdrStatus.VolumeChange;
  asprintf(&olddate, " ");
  oldaudiow = -1;
  rec = false;
  present = NULL;
  track = NULL;
  oldpresentvps = -1;
  lastSeen = -1;
  withInfo = WithInfo;
  smallfont = cFont::GetFont(fontSml);
  font = cFont::GetFont(fontOsd);
  lh = font->Height();
  slh = smallfont->Height();
  lhh = lh / 2;
  lineOffset = (lh - slh) / 2;
  bg = Theme.Color(clrBackground);
  if (withInfo)
    GetEvent = new cGetEvent;
  if (SkinElchiSetup.logo) {
#ifdef HAVE_IMAGEMAGICK
    Logo = new cLogo;
    if (SkinElchiSetup.logousemagick) {
	logox = SkinElchiSetup.logox;
	logoy = SkinElchiSetup.logoy;
	Logo->logox = logox;
	Logo->logoy = logoy;
	}
    else {
	logox = 64;
	logoy = 48;
	Logo->logox = logox;
	Logo->logoy = logoy;
	}
#else
	logox = 64;
	logoy = 48;
#endif
	}
  else
    logox = logoy = 0;
  x0 = 0;
  x1 = SkinElchiSetup.logo ? 16 : 0;
  x2 = x1 + lh - lhh;
  x3 = logox + lh - lhh;
  x4 = x2 + font->Width("00:00");
  x5 = x4 + lhh + Gap;
  x6 = x3 + font->Width("00000-") + smallfont->Width("_000 00.00 00:00");
  x7 = x6 + lh - lhh;
#ifdef VIDEOSTATUS
  if (SkinElchiSetup.videostatus)
    vdrosd = (VideoStatus.NTSC() == (SkinElchiSetup.videosystem == vsNTSC));
  else
#endif
    vdrosd = (cDevice::PrimaryDevice()->GetVideoSystem() == vsNTSC) == (SkinElchiSetup.videosystem == vsNTSC);
  x11 = vdrosd ? Setup.OSDWidth : SkinElchiSetup.osdwidth;
  x8 = x11 - lh;
  x10 = x8 + lhh;
  x9 = x10 - lh - bmRecording.Width() - 3 - bmEncrypted.Width() - 3 - bmDolbyDigital.Width() - 3 - bmAudio.Width() - 3 - bmTeletext.Width() - 3 - bmVps.Width() - 3;
#ifdef VIDEOSTATUS
  if ((fd_video >= 0) && (SkinElchiSetup.videostatus & 1))
    x9 -= bmRecording.Width()/*dummy*/ + 3;
#endif
  y0 = 0;
  y1 = SkinElchiSetup.logo ? (logoy - 32) : 0;
  y3 = y1 + lh;
  y2 = y3 - lhh;
  y4 = y3 + 3;
  y6 = y4 + lh;
  y5 = y6 - lhh;
  y9 = y6 + (withInfo ? lh * 4 : 0);
  y7 = y9 - lh;
  y8 = y9 - lhh;

  osd = cOsdProvider::NewOsd(vdrosd ? Setup.OSDLeft : SkinElchiSetup.osdleft, vdrosd ? (Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y9)) : (SkinElchiSetup.osdtop + (Setup.ChannelInfoPos ? 0 : SkinElchiSetup.osdheight - y9)));
  if (withInfo) {
    tArea Areas[] = { { 0, 0, x11 - 1, y9 - 1, 8 } };
    if ((osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) && (SkinElchiSetup.singlearea)) {
    	osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
        if (SkinElchiSetup.logo) {
	    for (int i = 0; i < MAX_ELCHI_THEME_COLORS; i++) {
		osd->GetBitmap(0)->SetColor(i,SkinElchiSetup.ThemeColors[i]);
		}
    	    osd->DrawRectangle(logox, y0, x11 - 1, y1 - 1, Theme.Color(Transparent));
    	    osd->DrawRectangle(x0, logoy, x1 - 1, y9 - 1, Theme.Color(Transparent));
    	    }
        }
    else {
        if (SkinElchiSetup.logo) {
    	    tArea Areas[] = {{ logox, y1, x11 - 1, y6 - 1, 4 },
			    { x1, logoy, logox - 1, y6 - 1, 4 }, 
			    { x0, y0, logox - 1, logoy - 1, 4/*8*/},//only 16 colors are available, no more
			    { x1, y6, x11 - 1, y9 - 1, 4 },};
    	    osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
        }
	else {
    	    tArea Areas[] = { { x0, y0, x11 - 1, y6 - 1, 4 },
			    { x0, y6, x11 - 1, y9 - 1, 4 }, };
    	    osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
	}
    }

    if (SkinElchiSetup.logo) 
	osd->DrawRectangle(logox, y1, x3 - 1, y3 - 1, Theme.Color(clrChannelDateBg));
    else {
	osd->DrawRectangle(logox, y1, x3 - 1, y2 - 1, Theme.Color(Transparent));
	osd->DrawEllipse  (logox, y1, x3 - 1, y2 - 1, Theme.Color(clrChannelDateBg), 2);
	osd->DrawRectangle(logox, y2, x3 - 1, y3 - 1, Theme.Color(clrChannelDateBg));
	}

    osd->DrawRectangle(x3, y1, x6 - 1, y3 - 1, Theme.Color(clrChannelDateBg));
    osd->DrawRectangle(x6, y1, x10 - 1, y3 - 1, bg);
    osd->DrawEllipse  (x6, y1, x7 - 1, y3 - 1, Theme.Color(clrChannelDateBg), 5);

    osd->DrawRectangle(x10, y1, x11 - 1, y2 - 1, Theme.Color(Transparent));
    osd->DrawEllipse  (x10, y1, x11 - 1, y2 - 1, bg, 1);
    osd->DrawRectangle(x10, y2, x11 - 1, y3 - 1, bg);

    osd->DrawRectangle(logox, y3, x11 - 1, y4 - 1, bg);

    if (SkinElchiSetup.logo) 
	osd->DrawRectangle(x1, logoy, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));

    osd->DrawRectangle(logox, y4, x3 - 1, y6 - 1, Theme.Color(clrChannelNameBg));

    osd->DrawRectangle(x3, y4, x9 - 1, y6 - 1, Theme.Color(clrChannelNameBg));

    osd->DrawRectangle(x9, y4, x11 - 1, y6 - 1, bg);
    osd->DrawEllipse  (x9, y4, x9 + lhh - 1, y6 - 1, Theme.Color(clrChannelNameBg), 5);

    osd->DrawRectangle(x1, y6, x4 - 1, y8 - 1, Theme.Color(clrChannelEpgTimeBg));
    osd->DrawRectangle(x4, y6, x11 - 1, y8 - 1, Theme.Color(clrChannelEpgTitleBg));
  
    osd->DrawRectangle(x1, y8, x2 - 1, y9 - 1, Theme.Color(Transparent));
    osd->DrawEllipse  (x1, y8, x2 - 1, y9 - 1, Theme.Color(clrChannelEpgTimeBg), 3);

    osd->DrawRectangle(x2, y8, x4 - 1, y9 - 1, Theme.Color(clrChannelEpgTimeBg));
    osd->DrawRectangle(x4, y8, x10 - 1, y9 - 1, Theme.Color(clrChannelEpgTitleBg));

    osd->DrawRectangle(x10, y8, x11 - 1, y9 - 1, Theme.Color(Transparent));
    osd->DrawEllipse  (x10, y8, x11 - 1, y9 - 1, Theme.Color(clrChannelEpgTitleBg), 4);

    EventScroll.DestWidth = x10 - x5 - 2;
    EventScroll.Fg = Theme.Color(clrChannelEpgTitle);
    EventScroll.Bg = Theme.Color(clrChannelEpgTitleBg);
    EventScroll.Font = font;
    EventScroll.xOff = x5 + 2;
    EventScroll.yOff = y6;

    EventShortScroll.DestWidth = EventScroll.DestWidth;
    EventShortScroll.Fg = Theme.Color(clrChannelEpgShortText);
    EventShortScroll.Bg = Theme.Color(clrChannelEpgTitleBg);
    EventShortScroll.Font = smallfont;
    EventShortScroll.xOff = EventScroll.xOff;
    EventShortScroll.yOff = y6 + lh;

    NextEventScroll.DestWidth = EventScroll.DestWidth;
    NextEventScroll.Fg = Theme.Color(clrChannelEpgTitle);
    NextEventScroll.Bg = Theme.Color(clrChannelEpgTitleBg);
    NextEventScroll.Font = font;
    NextEventScroll.xOff = EventScroll.xOff;
    NextEventScroll.yOff = EventShortScroll.yOff + lh;

    NextEventShortScroll.DestWidth = EventScroll.DestWidth;
    NextEventShortScroll.Fg = Theme.Color(clrChannelEpgShortText);
    NextEventShortScroll.Bg = Theme.Color(clrChannelEpgTitleBg);
    NextEventShortScroll.Font = smallfont;
    NextEventShortScroll.xOff = EventScroll.xOff;
    NextEventShortScroll.yOff = NextEventScroll.yOff + lh;
    }
  else {
    tArea Areas[] = { { 0, 0, x11 - 1, y9 - 1, 8 } };
    if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
    	osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
        if (SkinElchiSetup.logo) {
	    for (int i = 0; i < MAX_ELCHI_THEME_COLORS; i++) {
		osd->GetBitmap(0)->SetColor(i,SkinElchiSetup.ThemeColors[i]);
		}
    	    osd->DrawRectangle(logox, y0, x11 - 1, y1 - 1, Theme.Color(Transparent));
    	    osd->DrawRectangle(x0, logoy, x1 - 1, y9 - 1, Theme.Color(Transparent));
    	    }
        }
    else {
	if (SkinElchiSetup.logo) {
    	    tArea Areas[] ={{ logox, y1, x11 - 1, y9 - 1, 4 },
			    { x1, logoy, logox - 1, y9 - 1, 4 }, 
			    { x0, y0, logox - 1, logoy - 1, 4/*8*/},};//only 16 colors are available, no more
    	    osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));

    	    osd->DrawRectangle(logox, y0, x11 - 1, y1 - 1, Theme.Color(Transparent));
    	    osd->DrawRectangle(x0, logoy, x1 - 1, y9 - 1, Theme.Color(Transparent));
        }
	else {
    	    tArea Areas[] = { { x0, y0, x11 - 1, y9 - 1, 4 } };
    	    osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
	}
    }

    if (SkinElchiSetup.logo) {
        osd->DrawRectangle(logox, y1, x3 - 1, y3 - 1, Theme.Color(clrChannelDateBg));
        }
    else {
        osd->DrawRectangle(logox, y1, x3 - 1, y2 - 1, Theme.Color(Transparent));
        osd->DrawEllipse  (logox, y1, x3 - 1, y2 - 1, Theme.Color(clrChannelDateBg), 2);
        osd->DrawRectangle(logox, y2, x3 - 1, y3 - 1, Theme.Color(clrChannelDateBg));
    }
    osd->DrawRectangle(x3, y1, x6 - 1, y3 - 1, Theme.Color(clrChannelDateBg));
    osd->DrawRectangle(x6, y1, x10 - 1, y3 - 1, bg);
    osd->DrawEllipse  (x6, y1, x7 - 1, y3 - 1, Theme.Color(clrChannelDateBg), 5);

    osd->DrawRectangle(x10, y1, x11 - 1, y2 - 1, Theme.Color(Transparent));
    osd->DrawEllipse  (x10, y1, x11 - 1, y2 - 1, bg, 1);
    osd->DrawRectangle(x10, y2, x11 - 1, y3 - 1, bg);

    osd->DrawRectangle(logox, y3, x11 - 1, y4 - 1, bg);

    if (SkinElchiSetup.logo) {
	osd->DrawRectangle(x1, logoy, logox - 1, y5 - 1, Theme.Color(clrChannelNameBg));
        osd->DrawRectangle(x2, y5, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
        osd->DrawRectangle(logox, y4, x3 - 1, y6 - 1, Theme.Color(clrChannelNameBg));
	}
    else
        osd->DrawRectangle(logox, y4, x3 - 1, y5 - 1, Theme.Color(clrChannelNameBg));

    osd->DrawRectangle(x1, y5, x2 - 1, y6 - 1, Theme.Color(Transparent));
    osd->DrawEllipse  (x1, y5, x2 - 1, y6 - 1, Theme.Color(clrChannelNameBg), 3);

    osd->DrawRectangle(x3, y4, x9 - 1, y6 - 1, Theme.Color(clrChannelNameBg));

    osd->DrawRectangle(x9, y4, x11 - 1, y6 - 1, bg);
    osd->DrawEllipse  (x9, y4, x9 + lhh - 1, y6 - 1, Theme.Color(clrChannelNameBg), 5);

    osd->DrawRectangle(x9 + lhh, y4, x11 - 1, y5 - 1, bg);
    osd->DrawRectangle(x9 + lhh, y5, x10 - 1, y6 - 1, bg);

    osd->DrawRectangle(x10, y5, x11 - 1, y6 - 1, Theme.Color(Transparent));
    osd->DrawEllipse  (x10, y5, x11 - 1, y6 - 1, bg, 4);
    }

    if (SkinElchiSetup.logo) {
        osd->DrawRectangle(x0, y0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
        osd->DrawRectangle(logox, y1/*0 + 2*/, logox + 2 - 1, logoy + 2 - 1, bg);
        osd->DrawRectangle(x1, logoy, logox - 1, logoy + 2 - 1, bg);
    }
    //for scrolling
    AudioStringScroll.DestWidth = x10 - x7;
    AudioStringScroll.Fg = Theme.Color(clrChannelSymbolOn);
    AudioStringScroll.Bg = bg;
    AudioStringScroll.Font = smallfont;
    AudioStringScroll.xOff = x7;
    AudioStringScroll.yOff = y1 + lineOffset;

    ChannelNameScroll.DestWidth = x9 -
#ifdef VIDEOSTATUS
(((fd_video >= 0) && (SkinElchiSetup.videostatus & 2)) ? smallfont->Width(" 0000*0000 2.21:1 (2:2:2:2:2)") : 0) - 
#endif
x3;
    ChannelNameScroll.Fg = Theme.Color(clrChannelNameFg);
    ChannelNameScroll.Bg = Theme.Color(clrChannelNameBg);
    ChannelNameScroll.Font = smallfont;
    ChannelNameScroll.xOff = x3;
    ChannelNameScroll.yOff = y4 + lineOffset;
    noflush = false;
}

cSkinElchiDisplayChannel::~cSkinElchiDisplayChannel()
{
#ifdef DEBUG
    isyslog("skinelchi: cSkinElchiDisplayChannel::~cSkinElchiDisplayChannel()");
#endif
    noflush = true;
    message = changed = false;
#ifdef HAVE_IMAGEMAGICK
    if (SkinElchiSetup.logo) {
	Logo->Pid++;
	Logo->Update();
	}
#endif
    if (withInfo) {
	GetEvent->Pid++;
	GetEvent->Update();
	}
    if (olddate != NULL)
	free(olddate);
#ifdef VIDEOSTATUS
    if (oldvideoformatchar != NULL)
	free(oldvideoformatchar);
    if (fd_video != -1 && !SkinElchiSetup.videostatus) {
	close(fd_video);
	fd_video = -1;
	}
#endif
    delete osd;
}

void cSkinElchiDisplayChannel::SetChannel(const cChannel *Channel, int Number)
{
#ifdef DEBUG
  isyslog("skinelchi: cSkinElchiDisplayChannel::SetChannel(...,%d)", Number);
#endif
  if (AudioStringScroll.Text != NULL)
    free(AudioStringScroll.Text);
  asprintf(&AudioStringScroll.Text, " ");
#ifdef VIDEOSTATUS
  if (oldvideoformatchar != NULL)
    free(oldvideoformatchar);
  asprintf(&oldvideoformatchar, " ");
#endif
  changed = true;
  oldpresentvps = -1;
  osd->DrawRectangle(x9 + lh / 2, y4, x10 - 1, y6 - 1, bg);
  int x = x10;
  if (Channel) {
    if (!Channel->GroupSep()) {
	int d = 3;
	x -= bmRecording.Width();
	osd->DrawBitmap(x, y4 + (y6 - y4 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : bg);
        x -= bmEncrypted.Width() + d;
        osd->DrawBitmap(x, y4 + (y6 - y4 - bmEncrypted.Height()) / 2, bmEncrypted, Theme.Color(Channel->Ca() ? clrChannelSymbolOn : clrChannelSymbolOff), bg);
	x -= bmDolbyDigital.Width() + d;
	osd->DrawBitmap(x, y4 + (y6 - y4 - bmDolbyDigital.Height()) / 2, bmDolbyDigital, Theme.Color(Channel->Dpid(0) ? clrChannelSymbolOn : clrChannelSymbolOff), bg);
        x -= bmAudio.Width() + d;
        osd->DrawBitmap(x, y4 + (y6 - y4 - bmAudio.Height()) / 2, bmAudio, Theme.Color(Channel->Apid(1) ? clrChannelSymbolOn : clrChannelSymbolOff), bg);
	if (Channel->Vpid()) {
    	    x -= bmTeletext.Width() + d;
    	    osd->DrawBitmap(x, y4 + (y6 - y4 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(Channel->Tpid() ? clrChannelSymbolOn : clrChannelSymbolOff), bg);
#ifdef VIDEOSTATUS
	    video = true;
#endif
	    }
	else
#ifdef VIDEOSTATUS
	     {
	    video = false;
#endif
	    if (Channel->Apid(0)) {
#ifdef VIDEOSTATUS
    		x -= bmTeletext.Width() + d;
		if (Channel->Tpid())
    		    osd->DrawBitmap(x, y4 + (y6 - y4 - bmTeletext.Height()) / 2, bmTeletext, Theme.Color(clrChannelSymbolOn), bg);
		osd->DrawBitmap(x9 + lh, y4 + (y6 - y4 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), bg);
#else
    	        x -= bmRadio.Width() + d;
    	        osd->DrawBitmap(x, y4 + (y6 - y4 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), bg);
#endif
    	        }
#ifdef VIDEOSTATUS
	    }
#endif
	setchannel_x = x;
	snprintf(number, sizeof(number), "%d%s", Number ? Number : Channel->Number(), Number ? "-" : "");
        }
    else {
	snprintf(number, sizeof(number), "#");
#ifdef VIDEOSTATUS
	video = false;
#endif
	x = x10 - x7;
	osd->DrawRectangle(x10 - ((oldaudiow > x) ? x : oldaudiow), y1, x10 - 1, y3 - 1, bg);
	}

    ChannelNameScroll.DestWidth = x9
#ifdef VIDEOSTATUS
    - (((fd_video >= 0 && video) && (SkinElchiSetup.videostatus & 2)) ? smallfont->Width(" 0000*0000 2.21:1 (2:2:2:2:2)") : 0) 
#endif
    - x3;
    if (ChannelNameScroll.SetText(Channel->Name())) {
	ChannelNameScroll.pos = 0;
	ChannelNameScroll.dir = -1;
	ChannelNameScroll.delay = 5;
	ChannelNameScroll.Time.Set();
	}
    else
	ChannelNameScroll.dir = 0;
    if (showVolume) {
	osd->DrawText(x3, y1, number, Theme.Color(clrChannelNumberFg), Theme.Color(clrChannelDateBg), font, font->Width(tr("Volume ")));
	if (SkinElchiSetup.logo) {
            if (withInfo)
		osd->DrawRectangle(x1, logoy, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
	    else {
		osd->DrawRectangle(x1, logoy, logox - 1, y5 - 1, Theme.Color(clrChannelNameBg));
    		osd->DrawRectangle(x2, y5, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
		osd->DrawRectangle(x1, y5, x2 - 1, y6 - 1, Theme.Color(Transparent));
		osd->DrawEllipse  (x1, y5, x2 - 1, y6 - 1, Theme.Color(clrChannelNameBg), 3);
		}
    	    osd->DrawRectangle(logox, y0 + 2, logox + 2 - 1, logoy + 2 - 1, bg);
    	    osd->DrawRectangle(x1, logoy, logox - 1, logoy + 2 - 1, bg);
	    }
	osd->RestoreRegion();
	showVolume = false;
	}
    osd->DrawText(x3, y1, number, Theme.Color(clrChannelNumberFg), Theme.Color(clrChannelDateBg), font, font->Width("00000-"));
    osd->DrawText(ChannelNameScroll.xOff, ChannelNameScroll.yOff, ChannelNameScroll.Text, ChannelNameScroll.Fg, ChannelNameScroll.Bg, ChannelNameScroll.Font, ChannelNameScroll.DestWidth);
    if (showVolume)
	osd->SaveRegion(logox, y4, x11 - 1, y6 - 1);
    if (SkinElchiSetup.logo) {
        if (ChannelNameScroll.Font->Width(ChannelNameScroll.Text) != 0) {
	    cBitmap bmp(logox, logoy, osd->GetBitmap(2)?4:8);
	    char *filename;
	    asprintf(&filename, "%s/%s%s", SkinElchiSetup.logodir, ChannelNameScroll.Text, ".xpm");
#ifdef HAVE_IMAGEMAGICK
	    if (SkinElchiSetup.logousemagick) {
		Logo->Update(SkinElchiSetup.logodir, ChannelNameScroll.Text, bmp.Bpp());
		osd->DrawRectangle(0, 0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
		}
	    else {
#endif
		if (bmp.LoadXpm(filename)) {
		    if ((bmp.Width() == logox) && (bmp.Height() == logoy)) {
			int colors;
			bmp.Colors(colors);
			if (osd->GetBitmap(2)) {
			    osd->GetBitmap(2)->Reset();
#ifdef HAVE_IMAGEMAGICK
			    if (colors > 16) {
				bmp.SetBpp(4);
				Logo->Update(SkinElchiSetup.logodir, ChannelNameScroll.Text, bmp.Bpp());
				osd->DrawRectangle(0, 0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
				}
#endif
			    }
			else {
			    osd->GetBitmap(0)->Reset();
			    for (int i = 0; i < MAX_ELCHI_THEME_COLORS; i++)
				osd->GetBitmap(0)->SetColor(i,SkinElchiSetup.ThemeColors[i]);
#ifdef HAVE_IMAGEMAGICK
			    if (colors > (256 - MAX_ELCHI_THEME_COLORS))
				Logo->Update(SkinElchiSetup.logodir, ChannelNameScroll.Text, bmp.Bpp());
				osd->DrawRectangle(0, 0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
#endif
			    }
			osd->DrawBitmap(0, 0, bmp);
			}
#ifdef HAVE_IMAGEMAGICK
		    else {
			Logo->Update(SkinElchiSetup.logodir, ChannelNameScroll.Text, bmp.Bpp());
			osd->DrawRectangle(0, 0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
			}
#endif
		    }
		else
#ifdef HAVE_IMAGEMAGICK
		     {
		    Logo->Update(SkinElchiSetup.logodir, ChannelNameScroll.Text, bmp.Bpp());
#endif
		    osd->DrawRectangle(0, 0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
#ifdef HAVE_IMAGEMAGICK
		    }
	    }
#endif
	    free(filename);
	    }
    	else
	    osd->DrawRectangle(0, 0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
	}
    }
}

void cSkinElchiDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
{
  if (present != Present) {
    lastSeen = -1;
    present = Present;
    }
  else if ((lastSeen < 0) || (oldpresentvps == -1)) {
    present = Present;
    }
  if (!withInfo)
#ifdef DEBUG
    {
  isyslog("skinelchi: skip cSkinElchiDisplayChannel::SetEvents(%d,%d)", !Present ? 0 : Present->EventID(), !Following ? 0 : Following->EventID());
#endif
    return;
#ifdef DEBUG
    }
  else
    isyslog("skinelchi: cSkinElchiDisplayChannel::SetEvents(%d,%d)", !Present ? 0 : Present->EventID(), !Following ? 0 : Following->EventID());
#endif
  GetEvent->Update(Present, Following);
}

void cSkinElchiDisplayChannel::SetMessage(eMessageType Type, const char *Text)
{
#ifdef DEBUG
  isyslog("skinelchi: cSkinElchiDisplayChannel::SetMessage(%d,%s)", (int)Type, Text);
#endif
  if (Text) {
    char *text;
    asprintf(&text, "%s", Text);
/*    if (!strcasecmp(text, tr("Going to sleep in about one minute"))) {
	asprintf(&text, "\"%s\" <- Sleeptimer-Message received -> not printed on screen", Text);
	esyslog(text);
	}
    else */{
	if (!message) {
	    osd->SaveRegion(logox, y4, x11 - 1, y6 - 1);
	    message = true;
	    }
	if (withInfo) {
	    if (SkinElchiSetup.logo)
		osd->DrawRectangle(x1, y5, logox-1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type));
	    osd->DrawRectangle(logox, y5, x3-1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type));
	    osd->DrawRectangle(x10, y4, x11 - 1, y6 - 1, bg);
	    }
	else {
	    if (SkinElchiSetup.logo) {
	        osd->DrawRectangle(x1, y5, x2 - 1, y6 - 1, Theme.Color(Transparent));
	        osd->DrawEllipse  (x1, y5, x2 - 1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type), 3);
		osd->DrawRectangle(x2, y5, logox - 1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type));
	    	osd->DrawRectangle(logox, y5, x3 - 1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type));
	    	}
	    else {
	        osd->DrawRectangle(logox, y5, x3 - 1, y6 - 1, Theme.Color(Transparent));
	        osd->DrawEllipse  (logox, y5, x3 - 1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type), 3);
	        }
	    osd->DrawRectangle(x10, y5, x11 - 1, y6 - 1, Theme.Color(Transparent));
	    }
	    osd->DrawRectangle(x10, y4, x11 - 1, y5 - 1, bg);
	osd->DrawEllipse(x10, y4, x11 - 1, y6 - 1, Theme.Color(clrMessageStatusBg + 2 * Type), 5);
	osd->DrawText(x3, y4, Text, Theme.Color(clrMessageStatusFg + 2 * Type), Theme.Color(clrMessageStatusBg + 2 * Type), font, x10 - x3, 0, taCenter);
	osd->DrawRectangle(logox, y4, x3-1, y5 - 1, Theme.Color(clrMessageStatusBg + 2 * Type));
	if (SkinElchiSetup.logo) {
	    osd->DrawRectangle(x0, y0, logox - 1, logoy - 1, Theme.Color(clrChannelNameBg));
	    osd->DrawRectangle(x1, logoy, logox - 1, y5 - 1, Theme.Color(clrMessageStatusBg + 2 * Type));
    	    osd->DrawRectangle(logox, y1/*0 + 2*/, logox + 2 - 1, logoy + 2 - 1, bg);
    	    osd->DrawRectangle(x1, logoy, logox - 1, logoy + 2 - 1, bg);
	    }
	changed = true;
	}
	free(text);
    }
    else {
	if (message) {
	    if (SkinElchiSetup.logo) {
         	if (withInfo)
		    osd->DrawRectangle(x1, logoy, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
		else {
		    osd->DrawRectangle(x1, logoy, logox - 1, y5 - 1, Theme.Color(clrChannelNameBg));
    		    osd->DrawRectangle(x2, y5, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
		    osd->DrawRectangle(x1, y5, x2 - 1, y6 - 1, Theme.Color(Transparent));
		    osd->DrawEllipse  (x1, y5, x2 - 1, y6 - 1, Theme.Color(clrChannelNameBg), 3);
		    }
    		osd->DrawRectangle(logox, y0 + 2, logox + 2 - 1, logoy + 2 - 1, bg);
    		osd->DrawRectangle(x1, logoy, logox - 1, logoy + 2 - 1, bg);
		}
	    osd->RestoreRegion();
	    changed = true;
	    message = false;
	    }
    }
}

void cSkinElchiDisplayChannel::Flush(void)
{
if (!noflush) {
#ifdef DEBUG
  isyslog("skinelchi: cSkinElchiDisplayChannel::Flush() is called");
#endif
  noflush = true;
#ifdef HAVE_IMAGEMAGICK
  if (SkinElchiSetup.logo) {
    if (Logo && Logo->Ready()) {
	if (osd->GetBitmap(2))
	    osd->GetBitmap(2)->Reset();
	else {
	    osd->GetBitmap(0)->Reset();
	    for (int i = 0; i < MAX_ELCHI_THEME_COLORS; i++)
		osd->GetBitmap(0)->SetColor(i,SkinElchiSetup.ThemeColors[i]);
	    }
	if (Logo->LogoBmp) {
	    osd->DrawBitmap(0, 0, *(Logo->LogoBmp));
	    Logo->Drawed();
	    changed = true;
	    }
	}
    }
#endif
    if (present) {
    	time_t presentstarttime = present->StartTime();
	if (withInfo) {
    	    time_t t = time(NULL);
	    if (t > presentstarttime) {
    		int seen = min(y9 - y6 - 1, int((y9 - y6) * double(t - presentstarttime) / present->Duration()));
		if (seen < 0)
		    seen = 0;
		if (seen != lastSeen) {
#ifdef DEBUG
		    isyslog("skinelchi: show seenbar in DisplayChannel::Flush()");
#endif
		    osd->DrawRectangle(x4 + Gap, y6 + seen, x4 + Gap + ScrollWidth - 1, y9 - 1, Theme.Color(clrChannelTimebarRest));
    		    osd->DrawRectangle(x4 + Gap, y6, x4 + Gap + ScrollWidth - 1, y6 + seen - 1, Theme.Color(clrChannelTimebarSeen));
    		    lastSeen = seen;
		    changed = true;
		    }
#ifdef DEBUG
		else
		    isyslog("skinelchi: skip show seenbar in DisplayChannel::Flush()");
#endif
		}
	    }
	time_t presentvps = present->Vps();
    	if((presentvps)!=oldpresentvps) {
	    if (presentvps != 0) {
		int d = 3;
		int x = setchannel_x;
		x -= bmVps.Width() + d;
		bool vps = (presentvps != presentstarttime);
		if (oldvps != vps || oldpresentvps == -1) {
#ifdef DEBUG
		    isyslog("skinelchi: show VPS-symbol in DisplayChannel::Flush()");
#endif
		    osd->DrawBitmap(x, y4 + (y6 - y4 - bmVps.Height()) / 2, bmVps, Theme.Color(vps ? clrChannelSymbolOn:clrChannelSymbolOff), bg);
		    changed = true;
		    oldvps = vps;
		    }
#ifdef DEBUG
		else
		    isyslog("skinelchi: skip show VPS-symbol in DisplayChannel::Flush()");
#endif
    		}
    	    oldpresentvps = presentvps;
	    }
	}
    else {
	if (withInfo) {
	    if (lastSeen) {
#ifdef DEBUG
		isyslog("skinelchi: clear seenbar in DisplayChannel::Flush()");
#endif
		lastSeen = 0;
		osd->DrawRectangle(x4 + Gap, y6, x4 + Gap + ScrollWidth - 1, y9 - 1, Theme.Color(clrChannelEpgTitleBg));
		changed = true;
		}
#ifdef DEBUG
	    else
		isyslog("skinelchi: skip clear seenbar in DisplayChannel::Flush()");
#endif
	    }
	oldpresentvps = -1;
	}
    if (!message && !showVolume) {
#ifdef VIDEOSTATUS
    if (fd_video >= 0) {
	if (video) {
	    char *videoformatchar = NULL;
	    char *tempvideo;
	    int videoformat = VideoStatus.Ar();
	    asprintf(&tempvideo, "%d*%d %s", VideoStatus.Width(), VideoStatus.Height(), VideoStatus.VideoFormat());
	    if (videoformat != -1) {
		cBitmap *bm = VideoStatus.DFbmp();
		if (!showVolume && !message) {
		    if (bm) {
			if ((SkinElchiSetup.videostatus & 1) && (bm != oldbm || changed)) {
			    osd->DrawBitmap(x9 + lh, y4 + (y6 - y4 - bm->Height()) / 2, *bm, Theme.Color(clrChannelSymbolOn), bg);
			    oldbm = bm;
			    changed = true;
#ifdef DEBUG
			    isyslog("skinelchi: show videodisplayformatsymbol in DisplayChannel::Flush()");
#endif
			    }
#ifdef DEBUG
			else
			    isyslog("skinelchi: skip show videodisplayformatsymbol in DisplayChannel::Flush()");
#endif
			}
		    else {
			if (oldbm) {
			    osd->DrawRectangle(x9 + lh, y4, x9 + lh + bmRecording.Width()/*dummy*/ - 1, y6 - 1, bg);
			    oldbm = NULL;
			    changed = true;
#ifdef DEBUG
			    isyslog("skinelchi: erase  videodisplayformatsymbol in DisplayChannel::Flush()");
#endif
			    }
#ifdef DEBUG
			else
			    isyslog("skinelchi: skip erase  videodisplayformatsymbol in DisplayChannel::Flush()");
#endif
			}
		    }
		asprintf(&videoformatchar, " %s %s", tempvideo, VideoStatus.DisplayFormat());
		if (tempvideo)
		    free(tempvideo);
		}
	    int w = smallfont->Width(videoformatchar);
	    int x = x9 - x3;
	    if (w > x)
	        w = x;
	    if (w != oldvideow) {
		if ((w < oldvideow) && (SkinElchiSetup.videostatus & 2)) {
#ifdef DEBUG
		    isyslog("skinelchi: erase videoformatchar in DisplayChannel::Flush()");
#endif
		    osd->DrawRectangle(x9 - oldvideow, y4 + lineOffset, x9 - w - 1, y4 + lineOffset + slh - 1, Theme.Color(clrChannelNameBg));
		    changed = true;
		    }
#ifdef DEBUG
		else    
		    isyslog("skinelchi: skip erase videoformatchar in DisplayChannel::Flush()");
#endif
		oldvideow = w;
		}
	    if (videoformatchar) {
		if (strcmp(oldvideoformatchar, videoformatchar) && (SkinElchiSetup.videostatus & 2)) {
#ifdef DEBUG
		    isyslog("skinelchi: show videoformatchar in DisplayChannel::Flush()");
#endif
		    osd->DrawText(x9 - w, y4 + lineOffset, videoformatchar, Theme.Color(clrChannelNameFg), Theme.Color(clrChannelNameBg), smallfont, w);
		    if (oldvideoformatchar)
			free(oldvideoformatchar);
		    asprintf(&oldvideoformatchar, "%s", videoformatchar);
		    changed = true;
		    }
#ifdef DEBUG
		else
		    isyslog("skinelchi: skip show videoformatchar in DisplayChannel::Flush()");
#endif
		free(videoformatchar);
		}
    	    }
        }
#endif
	cDevice *Device = cDevice::PrimaryDevice();
	const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
	int w = 0;
	if (Track) {
	    char *audiostring = NULL;
	    int numaudiotracks = Device->NumAudioTracks();
	    if (numaudiotracks) {
		if (VdrStatus.AudioTrack) {
		    asprintf(&audiostring, "%s", VdrStatus.AudioTrack);
		    if (numaudiotracks > 1)
			asprintf(&audiostring, "%s %d/%d", audiostring, VdrStatus.AudioTrackIndex, numaudiotracks);
		    }
		else {
		    asprintf(&audiostring, "%s", Track->description);
		    w = smallfont->Width(audiostring);
		    if (!w)
	    		asprintf(&audiostring, "%s", Track->language);
		    if (numaudiotracks > 1)
			asprintf(&audiostring, "%s /%d", audiostring, numaudiotracks);
		    }
		if (VdrStatus.AudioChannel)
		    asprintf(&audiostring, "%s (%s)",audiostring, VdrStatus.AudioChannel);
		}
	    else
		asprintf(&audiostring, "%s", tr("No audio available!"));
	    if (VdrStatus.RecordingNumbers) {
		for (int i = 0; i < MAXDEVICES; i++)
		    if (VdrStatus.RecordingNumber[i] > 0) {
			if (VdrStatus.RecordingNumber[i] == 1)
			    asprintf(&audiostring, "%s | DVB%d: %d %s",audiostring, i + 1, VdrStatus.RecordingNumber[i], tr("Recording"));
			else
			    asprintf(&audiostring, "%s | DVB%d: %d %s",audiostring, i + 1, VdrStatus.RecordingNumber[i], tr("Recordings"));
		    }
		}
	    w = smallfont->Width(audiostring);
	    if (strcmp(AudioStringScroll.Text, audiostring)) {
#ifdef DEBUG
		isyslog("skinelchi: show audiostring - DisplayChannel::Flush()");
#endif
		if (AudioStringScroll.SetText(audiostring)) {
		    AudioStringScroll.pos = 0;
		    AudioStringScroll.dir = -1;
		    AudioStringScroll.delay = 5;
		    AudioStringScroll.Time.Set();
		    osd->DrawText(AudioStringScroll.xOff, AudioStringScroll.yOff, AudioStringScroll.Text, AudioStringScroll.Fg, AudioStringScroll.Bg, AudioStringScroll.Font, AudioStringScroll.DestWidth);
		    }
		else {
		    AudioStringScroll.dir = 0;
		    if (AudioStringScroll.DestWidth > w)
			osd->DrawText(x10 - w, AudioStringScroll.yOff, AudioStringScroll.Text, AudioStringScroll.Fg, AudioStringScroll.Bg, AudioStringScroll.Font, w);
		    else
			osd->DrawText(x10 - AudioStringScroll.DestWidth, AudioStringScroll.yOff, AudioStringScroll.Text, AudioStringScroll.Fg, AudioStringScroll.Bg, AudioStringScroll.Font, AudioStringScroll.DestWidth);
		    }
		changed = true;
		}
#ifdef DEBUG
	    else
		isyslog("skinelchi: skip show audiostring - DisplayChannel::Flush()");
#endif
	    free(audiostring);
	    }
	if (oldaudiow != w) {
	    if (oldaudiow > w) {
		int x = x10 - x7;
		if (w < x) {
		    osd->DrawRectangle(x10 - ((oldaudiow > x) ? x : oldaudiow), y1, x10 - w - 1, y3 - 1, bg);
		    changed = true;
#ifdef DEBUG
		    isyslog("skinelchi: erase unused audiostring - DisplayChannel::Flush()");
#endif
		    }
		}
#ifdef DEBUG
	    else
		isyslog("skinelchi: no unused audiostring - DisplayChannel::Flush()");
#endif
	    oldaudiow = w;
	    }
#ifdef DEBUG
	else
	    isyslog("skinelchi: skip erase unused audiostring - DisplayChannel::Flush()");
#endif
	}
    if (AudioStringScroll.dir) {
	if (AudioStringScroll.DrawNeeded()) {
	    for (int i = 0; i < AudioStringScroll.DestWidth; i++) {
		for (int j = 0; j < AudioStringScroll.Height(); j++)
		    osd->DrawPixel(AudioStringScroll.xOff + i, AudioStringScroll.yOff + j, AudioStringScroll.bmp->Color(*(AudioStringScroll.bmp->Data(i + AudioStringScroll.pos, j))));
		}
	    changed = true;
	    }
	}
    bool rectemp = cRecordControls::Active();
    if (!showVolume && !message && rec != rectemp) {
	rec = rectemp;
	osd->DrawBitmap(x10 - bmRecording.Width(), y4 + (y6 - y4 - bmRecording.Height()) / 2, bmRecording, Theme.Color(rec ? clrChannelSymbolRecFg : clrChannelSymbolOff), rec ? Theme.Color(clrChannelSymbolRecBg) : bg);
	changed = true;
	}
    if (VdrStatus.VolumeChange != volumechange) {
	volumechange = VdrStatus.VolumeChange;
	oldvolume = VdrStatus.Volume;
	int w = x10;
	int y = y4 + 4;
	int h = y6 - 5;
	if (!showVolume) {
	    if (olddate)
		free(olddate);
	    asprintf(&olddate, " ");
	    osd->SaveRegion(logox, y4, x11 - 1, y6 - 1);
	    osd->DrawText(x3, y1, tr("Volume "), Theme.Color(clrChannelDateFg), Theme.Color(clrChannelDateBg), font, x6 - x3);
	    osd->DrawRectangle(x3, y4, x9 + lh / 2 - 1, y - 1, bg);
	    osd->DrawRectangle(x3, h + 1, x9 + lh / 2 - 1, y6 - 1, bg);
	    if (withInfo) {
		if (SkinElchiSetup.logo)
		    osd->DrawRectangle(x1, y5, logox-1, y6 - 1, bg);
		osd->DrawRectangle(logox, y5, x3-1, y6 - 1, bg);
		osd->DrawRectangle(x10, y4, x11 - 1, y6 - 1, bg);
		}
	    else {
		if (SkinElchiSetup.logo) {
	    	    osd->DrawRectangle(x1, y5, x2 - 1, y6 - 1, Theme.Color(Transparent));
	    	    osd->DrawEllipse  (x1, y5, x2 - 1, y6 - 1, bg, 3);
		    osd->DrawRectangle(x2, y5, logox - 1, y6 - 1, bg);
	    	    osd->DrawRectangle(logox, y5, x3 - 1, y6 - 1, bg);
	    	    }
		else {
	    	    osd->DrawRectangle(logox, y5, x3 - 1, y6 - 1, Theme.Color(Transparent));
	    	    osd->DrawEllipse  (logox, y5, x3 - 1, y6 - 1, bg, 3);
	    	    }
		osd->DrawRectangle(x10, y5, x11 - 1, y6 - 1, Theme.Color(Transparent));
		osd->DrawEllipse  (x10, y5, x11 - 1, y6 - 1, bg, 4);
		}
	    osd->DrawRectangle(x10, y4, x11 - 1, y5 - 1, bg);
	    osd->DrawRectangle(logox, y4, x3-1, y5 - 1, bg);
	    if (SkinElchiSetup.logo) {
		osd->DrawRectangle(x1, logoy, logox-1, y5 - 1, bg);
    		osd->DrawRectangle(logox, y0 + 2, logox + 2 - 1, logoy + 2 - 1, bg);
    		osd->DrawRectangle(x1, logoy, logox - 1, logoy + 2 - 1, bg);
		}
    	    showVolume = true;
	    }
	int p = (w - x3) * oldvolume / 255;
	int xp = x3 + p;
	osd->DrawRectangle(x3, y, xp - 1, h, Theme.Color(clrVolumeBarUpper));
	osd->DrawRectangle(xp, y, w - 1, h, Theme.Color(clrVolumeBarLower));
	changed = true;
	volume.Set(1000);
	}
    else { 
	if (showVolume) {
	    if(volume.TimedOut()) {
		osd->DrawText(x3, y1, number, Theme.Color(clrChannelNumberFg), Theme.Color(clrChannelDateBg), font, font->Width(tr("Volume ")));
		if (SkinElchiSetup.logo) {
         	    if (withInfo)
			osd->DrawRectangle(x1, logoy, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
		    else {
			osd->DrawRectangle(x1, logoy, logox - 1, y5 - 1, Theme.Color(clrChannelNameBg));
    			osd->DrawRectangle(x2, y5, logox - 1, y6 - 1, Theme.Color(clrChannelNameBg));
			osd->DrawRectangle(x1, y5, x2 - 1, y6 - 1, Theme.Color(Transparent));
			osd->DrawEllipse  (x1, y5, x2 - 1, y6 - 1, Theme.Color(clrChannelNameBg), 3);
			}
    		    osd->DrawRectangle(logox, y0 + 2, logox + 2 - 1, logoy + 2 - 1, bg);
    		    osd->DrawRectangle(x1, logoy, logox - 1, logoy + 2 - 1, bg);
		    }
		osd->RestoreRegion();
		showVolume = false;
		changed = true;
		}
	    }
	else {
	cString date = DayDateTime();
	    if (strcmp(olddate, date)) {
#ifdef DEBUG
		isyslog("skinelchi: show DayDateTime in DisplayChannel::Flush()");
#endif
		changed = true;
		if (olddate)
		    free(olddate);
		asprintf(&olddate, date);
		osd->DrawText(x6 - smallfont->Width(date), y1 + lineOffset, date, Theme.Color(clrChannelDateFg), Theme.Color(clrChannelDateBg), smallfont);
		}
#ifdef DEBUG
	    else
		isyslog("skinelchi: skip show DayDateTime in DisplayChannel::Flush()");
#endif
	    if (!message && ChannelNameScroll.dir) {
		if (ChannelNameScroll.DrawNeeded()) {
		    for (int i = 0; i < ChannelNameScroll.DestWidth; i++) {
			for (int j = 0; j < ChannelNameScroll.Height(); j++)
			    osd->DrawPixel(ChannelNameScroll.xOff + i, ChannelNameScroll.yOff + j, ChannelNameScroll.bmp->Color(*(ChannelNameScroll.bmp->Data(i + ChannelNameScroll.pos, j))));
		        }
		    changed = true;
		    }
	        }
	    }
	}

    if (withInfo) {
	if (GetEvent->Ready()) {
	    tColor cetb = Theme.Color(clrChannelEpgTimeBg);
	    osd->DrawRectangle(x1, y6, x4 - 1, y9 - 1, cetb);
	    osd->DrawRectangle(x1, y8, x2 - 1, y9 - 1, Theme.Color(Transparent));
	    osd->DrawEllipse  (x1, y8, x2 - 1, y9 - 1, cetb, 3);
	    osd->DrawRectangle(x5, y6, x10 - 1, y9 - 1, Theme.Color(clrChannelEpgTitleBg));
	    if (GetEvent->PresentTimeString()) {
    		osd->DrawText(x1 + 4, y6, GetEvent->PresentTimeString(), Theme.Color(clrChannelEpgTimeFg), cetb, font);
		if (EventScroll.SetText(GetEvent->PresentTitle())) {
		    EventScroll.pos = 0;
		    EventScroll.dir = -1;
		    EventScroll.delay = 5;
		    EventScroll.Time.Set();
		    }
		else	
		    EventScroll.dir = 0;
		osd->DrawText(EventScroll.xOff, EventScroll.yOff, EventScroll.Text, EventScroll.Fg, EventScroll.Bg, EventScroll.Font, EventScroll.DestWidth);
		if (EventShortScroll.SetText(GetEvent->PresentShortText())) {
		    EventShortScroll.pos = 0;
		    EventShortScroll.dir = -1;
		    EventShortScroll.delay = 5;
		    EventShortScroll.Time.Set();
		    }
		else
		    EventShortScroll.dir = 0;
		osd->DrawText(EventShortScroll.xOff, EventShortScroll.yOff, EventShortScroll.Text, EventShortScroll.Fg, EventShortScroll.Bg, EventShortScroll.Font, EventShortScroll.DestWidth);
		}
	    else {
		EventScroll.dir = 0;
    		EventShortScroll.dir = 0;
		}
	    if (GetEvent->FollowingTimeString()) {
    		osd->DrawText(x1 + 4, y6 + 2 * lh, GetEvent->FollowingTimeString(), Theme.Color(clrChannelEpgTimeFg), cetb, font);
		if (NextEventScroll.SetText(GetEvent->FollowingTitle())) {
		    NextEventScroll.pos = 0;
		    NextEventScroll.dir = -1;
		    NextEventScroll.delay = 5;
		    NextEventScroll.Time.Set();
		    }
		else
		    NextEventScroll.dir = 0;
		osd->DrawText(NextEventScroll.xOff, NextEventScroll.yOff, NextEventScroll.Text, NextEventScroll.Fg, NextEventScroll.Bg, NextEventScroll.Font, NextEventScroll.DestWidth);
		if (NextEventShortScroll.SetText(GetEvent->FollowingShortText())) {
		    NextEventShortScroll.pos = 0;
		    NextEventShortScroll.dir = -1;
		    NextEventShortScroll.delay = 5;
		    NextEventShortScroll.Time.Set();
		    }
		else
		    NextEventShortScroll.dir = 0;
    		osd->DrawText(NextEventShortScroll.xOff, NextEventShortScroll.yOff, NextEventShortScroll.Text, NextEventShortScroll.Fg, NextEventShortScroll.Bg, NextEventShortScroll.Font, NextEventShortScroll.DestWidth);
		}
	    else {
		NextEventScroll.dir = 0;
    		NextEventShortScroll.dir = 0;
		}
	    GetEvent->Drawed();
	    changed = true;
	    }
	if (EventScroll.dir) {
	    if (EventScroll.DrawNeeded()) {
		for (int i = 0; i < EventScroll.DestWidth; i++) {
		    for (int j = 0; j < EventScroll.Height(); j++)
			osd->DrawPixel(EventScroll.xOff + i, EventScroll.yOff + j, EventScroll.bmp->Color(*(EventScroll.bmp->Data(i + EventScroll.pos, j))));
	    	    }
		changed = true;
		}
	    }
	if (EventShortScroll.dir) {
	    if (EventShortScroll.DrawNeeded()) {
		for (int i = 0; i < EventShortScroll.DestWidth; i++) {
		    for (int j = 0; j < EventShortScroll.Height(); j++)
			osd->DrawPixel(EventShortScroll.xOff + i, EventShortScroll.yOff + j, EventShortScroll.bmp->Color(*(EventShortScroll.bmp->Data(i + EventShortScroll.pos, j))));
	    	    }
		changed = true;
		}
	    }
	if (NextEventScroll.dir) {
	    if (NextEventScroll.DrawNeeded()) {
		for (int i = 0; i < NextEventScroll.DestWidth; i++) {
		    for (int j = 0; j < NextEventScroll.Height(); j++)
			osd->DrawPixel(NextEventScroll.xOff + i, NextEventScroll.yOff + j, NextEventScroll.bmp->Color(*(NextEventScroll.bmp->Data(i + NextEventScroll.pos, j))));
	    	    }
		changed = true;
		}
	    }
	if (NextEventShortScroll.dir) {
	    if (NextEventShortScroll.DrawNeeded()) {
		for (int i = 0; i < NextEventShortScroll.DestWidth; i++) {
		    for (int j = 0; j < NextEventShortScroll.Height(); j++)
			osd->DrawPixel(NextEventShortScroll.xOff + i, NextEventShortScroll.yOff + j, NextEventShortScroll.bmp->Color(*(NextEventShortScroll.bmp->Data(i + NextEventShortScroll.pos, j))));
	    	    }
		changed = true;
		}
	    }
	}
    if (changed) {
#ifdef DEBUG
	isyslog("skinelchi: DisplayChannel::Flush()");
#endif
	osd->Flush();
	changed = false;
	}
#ifdef DEBUG
    else
	isyslog("skinelchi: skip DisplayChannel::Flush()");
#endif
    noflush = false;
  }
#ifdef DEBUG
else
  isyslog("skinelchi: skip cSkinElchiDisplayChannel::Flush() because cSkinElchiDisplayChannel::Flush() is active");
#endif
}

#ifdef HAVE_IMAGEMAGICK
cLogo::cLogo(void) {
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cLogo::cLogo()");
#endif
    ready = update = false;
    LogoBmp = NULL;
    Start();
}

cLogo::~cLogo() {
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cLogo::~cLogo()");
#endif
    Pid++;
    if (filename) {
	free (filename);
	filename = NULL;
	}
    if (LogoBmp) {
	delete LogoBmp;
	LogoBmp = NULL;
	}
    if (file)
	fclose(file);
}

void cLogo::Update(const char *Path, const char *ChannelName, int Bpp) {
    Lock();
    ready = false;
    bpp = Bpp;
    if (Path)
	path = strdup(Path);
    else
	path = "";
    if (ChannelName)
	channelname = strdup(ChannelName);
    else
	ChannelName = "";	
    update = true;
    Unlock();
    Wait.Signal();
}

bool cLogo::Ready(void) {
    bool r;
    Lock();
    r = ready;
    Unlock();
    return r;
}

void cLogo::Drawed(void) {
    Lock();
    ready = false;
    Unlock();
}

void cLogo::Action(void) {
    pid = Pid = (int)getpid();
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cLogo::Action() - pid=%d", pid);
#endif
    file = NULL;
    filename = NULL;
    channelname = "  ";
    LogoBmp = new cBitmap(8,8,1);
    cOSDImageBitmap image;
    const char *oldchannelname = " ";
    int oldbpp = 1;
    while(Pid == pid) {
	Wait.Wait(0);
	while (update) {
	    update = false;
	    if ((!strcmp(oldchannelname, channelname) == 0) || (oldbpp != bpp)) {
		oldchannelname = strdup(channelname);
		oldbpp = bpp;
//		if (bpp == 8) {
	    	    asprintf(&filename, "%s/../hqlogos/%s", path, oldchannelname);
		    file = fopen(filename, "r");
//		    }
		if (!file) {
	    	    asprintf(&filename, "%s/%s%s", path, oldchannelname, ".xpm");
		    file = fopen(filename, "r");
		    }
		bool r = false;
		if (file) {
		    fclose(file);
		    file = NULL;
		    if (image.LoadZoomed(filename, 0, 0, 0, 0)) {
			if (!update) {
    		    	    image.Render(*LogoBmp, logox, logoy, (bpp == 4)?16:256 - MAX_ELCHI_THEME_COLORS, 1);
			    if ((Pid == pid) && !update)			    
	    			ready = true;
				r = true;
			    }
			}
		    }
		if (!r && filename) {
		    free(filename);
		    filename = NULL;
		    }
		}
	    else {
		if (filename && (Pid == pid) && !update) {
		    ready = true;
		    }
		}
	    }
	}
    ready = false;	
    if (filename) {
	free (filename);
	filename = NULL;
	}
    if (LogoBmp) {
	delete LogoBmp;
	LogoBmp = NULL;
	}
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cLogo-thread end (pid=%d)", pid);
#endif
}
#endif

cGetEvent::cGetEvent(void) {
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cGetEvent::cGetEvent()");
#endif
    ready = update = false;
    Start();
}

cGetEvent::~cGetEvent() {
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cGetEvent::~cGetEvent()");
#endif
    Pid++;
}

void cGetEvent::Update(const cEvent *Present, const cEvent *Following) {
    Lock();
    ready = false;
    present = Present;
    following = Following;
    update = true;
    Unlock();
    Wait.Signal();
}

bool cGetEvent::Ready(void) {
    bool r;
    Lock();
    r = ready;
    Unlock();
    return r;
}

void cGetEvent::Drawed(void) {
    Lock();
    ready = false;
    Unlock();
}

const char *cGetEvent::PresentTitle(void) {
    Lock();
    Presenttitle = strdup(presenttitle);
    Unlock();
    return Presenttitle;
}

const char *cGetEvent::PresentShortText(void) {
    Lock();
    Presentshorttext = strdup(presentshorttext);
    Unlock();
    return Presentshorttext;
}

const char *cGetEvent::PresentTimeString(void) {
    Lock();
    Presenttimestring = strdup(presenttimestring);
    Unlock();
    return Presenttimestring;
}

const char *cGetEvent::FollowingTitle(void) {
    Lock();
    Followingtitle = strdup(followingtitle);
    Unlock();
    return Followingtitle;
}

const char *cGetEvent::FollowingShortText(void) {
    Lock();
    Followingshorttext = strdup(followingshorttext);
    Unlock();
    return Followingshorttext;
}

const char *cGetEvent::FollowingTimeString(void) {
    Lock();
    Followingtimestring = strdup(followingtimestring);
    Unlock();
    return Followingtimestring;
}

void cGetEvent::Action(void) {
    pid = Pid = (int)getpid();
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cGetEvent::Action() - pid=%d", pid);
#endif
    while(Pid == pid) {
	Wait.Wait(0);
	if (present) {
	    if (present->Title())
		presenttitle = strdup(present->Title());
	    else
		presenttitle = "";
	    if (present->ShortText())
		presentshorttext = strdup(present->ShortText());
	    else
		presentshorttext = "";
	    if (present->GetTimeString())
		presenttimestring = strdup(present->GetTimeString());
	    else
		presenttimestring = "";
	    }
	else
	    presenttitle = presentshorttext = presenttimestring = "";
	if (following) {
	    if (following->Title())
		followingtitle = strdup(following->Title());
	    else
		followingtitle = "";
	    if (following->ShortText())
	    	followingshorttext = strdup(following->ShortText());
	    else
		followingshorttext = "";
	    if (following->GetTimeString())
		followingtimestring = strdup(following->GetTimeString());
	    else
		followingtimestring = "";
	    }
	else
	    followingtitle = followingshorttext = followingtimestring = "";
	if (Pid == pid)
	    ready = true;
	}
    ready = false;	
#ifdef DEBUG
    isyslog("skinelchi: DisplayChannel - cGetEvent-thread end (pid=%d)", pid);
#endif
}
