/*
 * DisplayReplay.c: Replay display handling
 *
 * See the main source file 'skinelchi.c' for copyright information and
 * how to reach the author.
 *
 * $Id$
 */

#include <vdr/menu.h>
#include <vdr/device.h>

#include "DisplayReplay.h"
#include "setup.h"
#include "common.h"
#include "vdrstatus.h"
#include "videostatus.h"

#include "symbols/ffwd.xpm"
#include "symbols/ffwd1.xpm"
#include "symbols/ffwd2.xpm"
#include "symbols/ffwd3.xpm"
#include "symbols/ffwd4.xpm"
#include "symbols/ffwd5.xpm"
#include "symbols/ffwd6.xpm"
#include "symbols/ffwd7.xpm"
#include "symbols/ffwd8.xpm"
#include "symbols/frew.xpm"
#include "symbols/frew1.xpm"
#include "symbols/frew2.xpm"
#include "symbols/frew3.xpm"
#include "symbols/frew4.xpm"
#include "symbols/frew5.xpm"
#include "symbols/frew6.xpm"
#include "symbols/frew7.xpm"
#include "symbols/frew8.xpm"
#include "symbols/sfwd.xpm"
#include "symbols/sfwd1.xpm"
#include "symbols/sfwd2.xpm"
#include "symbols/sfwd3.xpm"
#include "symbols/sfwd4.xpm"
#include "symbols/sfwd5.xpm"
#include "symbols/sfwd6.xpm"
#include "symbols/sfwd7.xpm"
#include "symbols/sfwd8.xpm"
#include "symbols/srew.xpm"
#include "symbols/srew1.xpm"
#include "symbols/srew2.xpm"
#include "symbols/srew3.xpm"
#include "symbols/srew4.xpm"
#include "symbols/srew5.xpm"
#include "symbols/srew6.xpm"
#include "symbols/srew7.xpm"
#include "symbols/srew8.xpm"
#include "symbols/pause.xpm"
#include "symbols/play.xpm"
#include "symbols/recording.xpm"
#include "symbols/mail.xpm"
#include "symbols/ar43.xpm"
#include "symbols/arL149.xpm"
#include "symbols/arL169.xpm"
#include "symbols/arLG169.xpm"
#include "symbols/ar169.xpm"
#include "symbols/ar2211.xpm"

cBitmap cSkinElchiDisplayReplay::bmFfwd(ffwd_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd1(ffwd1_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd2(ffwd2_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd3(ffwd3_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd4(ffwd4_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd5(ffwd5_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd6(ffwd6_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd7(ffwd7_xpm);
cBitmap cSkinElchiDisplayReplay::bmFfwd8(ffwd8_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew(frew_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew1(frew1_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew2(frew2_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew3(frew3_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew4(frew4_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew5(frew5_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew6(frew6_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew7(frew7_xpm);
cBitmap cSkinElchiDisplayReplay::bmFrew8(frew8_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd(sfwd_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd1(sfwd1_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd2(sfwd2_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd3(sfwd3_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd4(sfwd4_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd5(sfwd5_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd6(sfwd6_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd7(sfwd7_xpm);
cBitmap cSkinElchiDisplayReplay::bmSfwd8(sfwd8_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew(srew_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew1(srew1_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew2(srew2_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew3(srew3_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew4(srew4_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew5(srew5_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew6(srew6_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew7(srew7_xpm);
cBitmap cSkinElchiDisplayReplay::bmSrew8(srew8_xpm);
cBitmap cSkinElchiDisplayReplay::bmPause(pause_xpm);
cBitmap cSkinElchiDisplayReplay::bmPlay(play_xpm);
cBitmap cSkinElchiDisplayReplay::bmRecording(recording_xpm);
cBitmap cSkinElchiDisplayReplay::bmMail(mail_xpm);
cBitmap cSkinElchiDisplayReplay::bmAR43(ar43_xpm);
cBitmap cSkinElchiDisplayReplay::bmARL149(arL149_xpm);
cBitmap cSkinElchiDisplayReplay::bmARL169(arL169_xpm);
cBitmap cSkinElchiDisplayReplay::bmARLG169(arLG169_xpm);
cBitmap cSkinElchiDisplayReplay::bmAR169(ar169_xpm);
cBitmap cSkinElchiDisplayReplay::bmAR2211(ar2211_xpm);

extern cSkinElchiStatus *ElchiStatus;

// --- cSkinElchiDisplayReplay ---------------------------------------------
cSkinElchiDisplayReplay::cSkinElchiDisplayReplay(bool ModeOnly)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::cSkinElchiDisplayReplay(%s)", ModeOnly ? "'ModeOnly'" : "'nonModeOnly'")
   //isyslog("skinelchi: cSkinElchiDisplayReplay::cSkinElchiDisplayReplay(%s)", ModeOnly ? "'ModeOnly'" : "'nonModeOnly'");
   if (ElchiConfig.showVideoInfo)
      VideoStatus->Activate(true);

   modeonly = ModeOnly;
   showVolume = false;
   showMessage = false;
   volumechange = ElchiStatus->GetVolumeChange();
   rec = false;
   rectitle = NULL;
   title = NULL;
   oldCurrent = NULL;
   old_ar = ar_unknown;
   old_width = -1;
   old_height = -1;
   font = cFont::GetFont(fontOsd);
   smallfont = cFont::GetFont(fontSml);
   lh = font->Height();
   lhh = lh / 2;
   x0 = 0;

   tOSDsize OSDsize;

#if APIVERSNUM < 10504
   OSDsize.left   = Setup.OSDLeft;
   OSDsize.top    = Setup.OSDTop;
   OSDsize.width  = Setup.OSDWidth;
   OSDsize.height = Setup.OSDHeight;
#ifdef SKINELCHI_USE_AVARDS_PLUGIN
   cPlugin *AvardsPlugin = cPluginManager::GetPlugin("avards");
   if (AvardsPlugin) {
      avards_MaxOSDsize_v1_0 AvardsSize;
      AvardsPlugin->Service(AVARDS_MAXOSDSIZE_SERVICE_STRING_ID, &AvardsSize);
      OSDsize.left   = AvardsSize.left;
      OSDsize.top    = AvardsSize.top;
      OSDsize.width  = AvardsSize.width;
      OSDsize.height = AvardsSize.height;
   }
#endif
#else
   OSDsize.left   = cOsd::OsdLeft();
   OSDsize.top    = cOsd::OsdTop();
   OSDsize.width  = cOsd::OsdWidth();
   OSDsize.height = cOsd::OsdHeight();
#endif
   DSYSLOG("skinelchi: OSDsize Replay left=%d/%d top=%d/%d width=%d/%d heigth=%d/%d",
           OSDsize.left, Setup.OSDLeft, OSDsize.top, Setup.OSDTop, OSDsize.width, Setup.OSDWidth, OSDsize.height, Setup.OSDHeight)

   x1 = x0 + OSDsize.width;
   x2 = x1 - lhh - smallfont->Width("00:00:00.00 / 00:00:00");

   xSymbol = x1 - lh + lhh - bmFrew.Width() - 3 - bmSrew.Width() - 3 - bmPlay.Width() - 3 - bmSfwd.Width() - 3 - bmFfwd.Width();
   x3 = xRecording = xSymbol - bmRecording.Width() - 3;


   if (ElchiConfig.showVideoInfo) {
      xAR = xRecording - bmAR43.Width() - 3;  // space for AR symbol
      x3 -= bmAR43.Width() + 3;
   }

   MailIconState = 0;
   if (ElchiConfig.showMailIcon > 0) {
      cPlugin *MailBoxPlugin = cPluginManager::GetPlugin("mailbox");
      bool fHasNewMail = false;
      if (MailBoxPlugin && MailBoxPlugin->Service("MailBox-HasNewMail-1.0", &fHasNewMail)) {
         if (fHasNewMail)
            MailIconState = 2; // icon: new mail
         else
            if (ElchiConfig.showMailIcon >= 2)
               MailIconState = 1; // icon: no new mail

         if (MailIconState >= 1)
            xMail = x3 - bmMail.Width() - 3;
         x3 -= bmMail.Width() + 3;
      }
   }

   x3 -= lhh;

   x4 = x2 - 2 * lh;
   x5 = x3 - 2 * lh;

   y0 = 0;
   y1 = lh;
   y2 = 2 * lh;
   y3 = 3 * lh;

   osd = cOsdProvider::NewOsd(OSDsize.left, OSDsize.top + OSDsize.height - y3);
   tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } };
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));

   cBitmap *bitmap = osd->GetBitmap(0);
   if (bitmap) {
      bitmap->Reset();
      bitmap->SetColor(0, clrTransparent);
      bitmap->SetColor(1, Theme.Color(clrBackground));
/* used colors:
clrReplayCurrent
clrReplayTitleFg
clrReplayTitleBg
clrReplaySymbolOn
clrReplaySymbolOff
clrReplayProgressSeen
clrReplayProgressRest
clrReplayProgressSelected
clrReplayProgressMark
clrReplayProgressCurrent
clrReplayTotal
clrReplayModeJump
clrMessageStatusBg
clrMessageStatusFg
clrSymbolRecFg
clrSymbolRecBg
clrVolumeBarUpper
clrVolumeBarLower
clrbackground
clrTransparent
:19
*/
   }

   bg = Theme.Color(clrBackground);
   osd->DrawPixel(x3, y3, clrTransparent);
   osd->DrawPixel(x3, y3, bg);
   osd->DrawPixel(x3, y3, Theme.Color(clrReplaySymbolOn));
   osd->DrawPixel(x3, y3, Theme.Color(clrReplaySymbolOff));
   //osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent);

   if (ModeOnly) {
      osd->DrawRectangle(x0, y0, x1 - 1, y2 - 1, clrTransparent);
      osd->DrawRectangle(x3, y2, x3 + lhh - 1, y3 - 1, clrTransparent);
      osd->DrawEllipse(x3, y2, x3 + lhh - 1, y3 - 1, bg, 7);
      osd->DrawRectangle(x3 + lhh, y2, x1 - lhh - 1, y3 - 1, bg);
      osd->DrawRectangle(x1 - lhh, y2, x1 - 1, y3 - 1, clrTransparent);
      osd->DrawEllipse(x1 - lhh, y2, x1 - 1, y3 - 1, bg, 5);
   }
   else {
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayCurrent));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayTitleFg));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayTitleBg));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayProgressSeen));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayProgressRest));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayProgressSelected));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayProgressMark));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayProgressCurrent));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayTotal));
      osd->DrawPixel(x3, y3, Theme.Color(clrReplayModeJump));
      osd->DrawPixel(x3, y3, Theme.Color(clrSymbolRecFg));
      osd->DrawPixel(x3, y3, Theme.Color(clrSymbolRecBg));
      osd->DrawPixel(x3, y3, Theme.Color(clrVolumeBarUpper));
      osd->DrawPixel(x3, y3, Theme.Color(clrVolumeBarLower));

      osd->DrawRectangle(x0, y0, x2 - 1, y1 - 1, clrTransparent);
      osd->DrawSlope(x4, y0, x2 - 1, y1 - 1, bg, 0);

      osd->DrawRectangle(x2, y0, x1 - lhh - 1, y1 - 1, bg);

      osd->DrawRectangle(x1 - lhh, y0, x1 - 1, y1 - lhh - 1, clrTransparent);
      osd->DrawEllipse(x1 - lhh, y0, x1 - 1, y1 - lhh - 1, bg, 1);

      osd->DrawRectangle(x0 + lhh, y1, x0 + lh - 1, y2 - 1, clrTransparent);
      osd->DrawEllipse(x0 + lhh, y1, x0 + lh - 1, y2 - 1, bg, 7);
      osd->DrawRectangle(x0 + lh, y1, x1 - lhh - 1, y2 - 1, bg);
      osd->DrawRectangle(x2, y0, x1 - lhh - 1, y1 - 1, bg);

      if (Setup.ShowReplayMode) {
         osd->DrawRectangle(x0, y2, x3 - 1, y3 - 1, clrTransparent);
         osd->DrawSlope(x5, y2, x3 - 1, y3 - 1, bg, 3);
         osd->DrawRectangle(x1 - lhh, y1 - lhh, x1 - 1, y2 + lhh, bg);
         osd->DrawRectangle(x3, y2, x1 - lhh - 1, y3 - 1, bg);
         osd->DrawRectangle(x1 - lhh, y3 - lhh, x1 - 1, y3 - 1, clrTransparent);
         osd->DrawEllipse(x1 - lhh, y3 - lhh, x1 - 1, y3 - 1, bg, 4);
      }
      else {
         osd->DrawRectangle(x1 - lhh, y1 - lhh, x1 - 1, y1 + lhh, bg);
         osd->DrawRectangle(x1 - lhh, y2 - lhh, x1 - 1, y2 - 1, clrTransparent);
         osd->DrawEllipse(x1 - lhh, y2 - lhh, x1 - 1, y2 - 1, bg, 4);
      }

      const char *separator = " / ";
      xTotalWidth = smallfont->Width("00:00:00");
      xTotal = x1 - xTotalWidth - y1 / 2;
      osd->DrawText(xTotal - smallfont->Width(separator), y0, separator,Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), smallfont);
      xCurrentWidth = smallfont->Width("00:00:00.00");
      xCurrent = xTotal - smallfont->Width(separator) - xCurrentWidth;

   }
   TitleScroll = NULL;

   changed = true;
}

cSkinElchiDisplayReplay::~cSkinElchiDisplayReplay()
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::~cSkinElchiDisplayReplay()")

   if (ElchiConfig.showVideoInfo)
      VideoStatus->Activate(false);

   free(oldCurrent);

   delete TitleScroll; TitleScroll = NULL;
   delete osd;
   changed = true;
}

void cSkinElchiDisplayReplay::SetTitle(const char *Title)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::SetTitle(%s)", Title)

   rectitle = Title;

   SetScrollTitle(rectitle);
}


void cSkinElchiDisplayReplay::SetScrollTitle(const char *Title)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::SetScrollTitle(%s)", Title)

   int w = smallfont->Width(Title);
   if(ElchiConfig.showVideoInfo > 1 && !showVolume)
      w += smallfont->Width(" 720x576");

   w = min(w, x4 - x0);
   int h = font->Height() - smallfont->Height();

   delete TitleScroll;
   osd->DrawRectangle(x0, y0, x4 + 2, y1 - h + 2, clrTransparent);
   TitleScroll = new cCharScroll(x0, y0, w, osd, smallfont,
                   Theme.Color(clrReplayTitleFg), Theme.Color(clrReplayTitleBg));
   TitleScroll->SetText(Title);

   osd->DrawRectangle(w, y0 + 3, w + 3 - 1, y1 - h + 3 - 1, bg);
   osd->DrawRectangle(x0 + 3, y1 - h, w - 1, y1 - h + 3 - 1, bg);
   changed = true;
}

void cSkinElchiDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::SetMode(%s,%s,Speed=%d)", Play ? "'Play'" : "'nonPlay'", Forward ? "'Forward'" : "'nonForward'", Speed)

   if (Setup.ShowReplayMode) {
      tColor clr_on  = Theme.Color(clrReplaySymbolOn);
      tColor clr_off = Theme.Color(clrReplaySymbolOff);

      int x = xSymbol;
      int y = y3 - y2;
      if (Speed < -1)
         Speed = -1;
      if (Speed > 9)
         Speed = 9;

      if (MailIconState > 0) {
         //osd->DrawBitmap(x, y2 + (y - bmMail.Height()) / 2, bmMail, (MailIconState > 1) ? clr_on : clr_off, bg);
         osd->DrawBitmap(xMail, y2 + (y - bmMail.Height()) / 2, bmMail, (MailIconState > 1) ? clr_on : clr_off, bg);
         //x += bmMail.Width() + 3;
      }

      rec = cRecordControls::Active();
      osd->DrawBitmap(xRecording, y2 + (y - bmRecording.Height()) / 2, bmRecording, rec ? Theme.Color(clrSymbolRecFg) : clr_off, rec ? Theme.Color(clrSymbolRecBg) : bg);

      cBitmap *bm = NULL;
      if ((Speed > -1) && Play && !Forward) {
         switch (Speed) {
            case 0:
            case 1: bm = &bmFrew; break;
            case 2: bm = &bmFrew1; break;
            case 3: bm = &bmFrew2; break;
            case 4: bm = &bmFrew3; break;
            case 5: bm = &bmFrew4; break;
            case 6: bm = &bmFrew5; break;
            case 7: bm = &bmFrew6; break;
            case 8: bm = &bmFrew7; break;
            case 9: bm = &bmFrew8; break;
         }
         osd->DrawBitmap(x, y2 + (y - bm->Height()) / 2, *bm, clr_on, bg);
      }
      else
         osd->DrawBitmap(x, y2 + (y - bmFrew.Height()) / 2, bmFrew, clr_off, bg);
      x += bmFrew.Width() + 3;

      if ((Speed > -1) && !Play && !Forward) {
         switch (Speed) {
            case 0:
            case 1: bm = &bmSrew; break;
            case 2: bm = &bmSrew1; break;
            case 3: bm = &bmSrew2; break;
            case 4: bm = &bmSrew3; break;
            case 5: bm = &bmSrew4; break;
            case 6: bm = &bmSrew5; break;
            case 7: bm = &bmSrew6; break;
            case 8: bm = &bmSrew7; break;
            case 9: bm = &bmSrew8; break;
         }
         osd->DrawBitmap(x, y2 + (y - bm->Height()) / 2, *bm, clr_on, bg);
      }
      else
         osd->DrawBitmap(x, y2 + (y - bmSrew.Height()) / 2, bmSrew, clr_off, bg);
      x += bmSrew.Width() + 3;

      if (Speed == -1)
         osd->DrawBitmap(x, y2 + (y - bmPlay.Height()) / 2, Play ? bmPlay : bmPause, clr_on, bg);
      else
         osd->DrawBitmap(x, y2 + (y - bmPlay.Height()) / 2, bmPlay, clr_off, bg);
      x += bmPlay.Width() + 3;

      if ((Speed > -1) && !Play && Forward) {
         switch (Speed) {
            case 0: 
            case 1: bm = &bmSfwd; break;
            case 2: bm = &bmSfwd1; break;
            case 3: bm = &bmSfwd2; break;
            case 4: bm = &bmSfwd3; break;
            case 5: bm = &bmSfwd4; break;
            case 6: bm = &bmSfwd5; break;
            case 7: bm = &bmSfwd6; break;
            case 8: bm = &bmSfwd7; break;
            case 9: bm = &bmSfwd8; break;
         }
         osd->DrawBitmap(x, y2 + (y - bm->Height()) / 2, *bm, clr_on, bg);
      }
      else
         osd->DrawBitmap(x, y2 + (y - bmSfwd.Height()) / 2, bmSfwd, clr_off, bg);
      x += bmSfwd.Width() + 3;

      if ((Speed > -1) && Play && Forward) {
         switch (Speed) {
            case 0: 
            case 1: bm = &bmFfwd; break;
            case 2: bm = &bmFfwd1; break;
            case 3: bm = &bmFfwd2; break;
            case 4: bm = &bmFfwd3; break;
            case 5: bm = &bmFfwd4; break;
            case 6: bm = &bmFfwd5; break;
            case 7: bm = &bmFfwd6; break;
            case 8: bm = &bmFfwd7; break;
            case 9: bm = &bmFfwd8; break;
         }
         osd->DrawBitmap(x, y2 + (y - bm->Height()) / 2, *bm, clr_on, bg);
      }
      else
         osd->DrawBitmap(x, y2 + (y - bmFfwd.Height()) / 2, bmFfwd, clr_off, bg);
      changed = true;
   }
   //isyslog("skinelchi: cSkinElchiDisplayReplay::SetMode end");
}

void cSkinElchiDisplayReplay::SetProgress(int Current, int Total)
{
   DSYSLOG2("skinelchi: cSkinElchiDisplayReplay::SetProgress(%d,%d)", Current, Total)
   if (!showVolume) {
      cProgressBar pb(x1 - x0 - y1 - y1 / 2, y2 - y1 - 8, Current, Total, marks, Theme.Color(clrReplayProgressSeen), Theme.Color(clrReplayProgressRest), Theme.Color(clrReplayProgressSelected), Theme.Color(clrReplayProgressMark), Theme.Color(clrReplayProgressCurrent));
      osd->DrawBitmap(x0 + y1, y1 + 4, pb);
      changed = true;
   }
}

void cSkinElchiDisplayReplay::SetCurrent(const char *Current)
{
   if (!oldCurrent || strcmp(oldCurrent, Current)) {
      DSYSLOG2("skinelchi: cSkinElchiDisplayReplay::SetCurrent(%s)", Current)
      free(oldCurrent);
      oldCurrent = strdup(Current);

      osd->DrawText(xCurrent, y0, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), smallfont, xCurrentWidth, 0, taRight);

      changed = true;
   }
   else
      DSYSLOG2("skinelchi: skipped cSkinElchiDisplayReplay::SetCurrent(%s)", Current)
}

void cSkinElchiDisplayReplay::SetTotal(const char *Total)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::SetTotal(%s)", Total)

   osd->DrawText(xTotal, y0, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), smallfont, xTotalWidth, 0 ,taRight);
   changed = true;
}

void cSkinElchiDisplayReplay::SetJump(const char *Jump)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::SetJump(%s)", Jump)
   osd->DrawRectangle(x0, y2, x5 - 1, y3 - 1, clrTransparent);
   if (Jump) {
      int w = font->Width(Jump);
      osd->DrawText(x5 - w, y2, Jump, Theme.Color(clrReplayModeJump), Theme.Color(clrBackground), font, w);
   }
   changed = true;
}

void cSkinElchiDisplayReplay::SetMessage(eMessageType Type, const char *Text)
{
   DSYSLOG("skinelchi: cSkinElchiDisplayReplay::SetMessage(%d,%s)", (int)Type, Text)
   if (Text) {
      if (showVolume) {  // destroy Volume Display first
         showVolume = false;
         osd->RestoreRegion();
         if (modeonly) {
            osd->DrawRectangle(x5, y2, x3 + lhh - 1, y3 - 1, clrTransparent);
            osd->DrawEllipse(x3, y2, x3 + lhh - 1, y3 - 1, bg, 7);
            osd->DrawRectangle(x1 - lhh, y2, x1 - 1, y3 - 1, clrTransparent);
            osd->DrawEllipse(x1 - lhh, y2, x1 - 1, y3 - 1, bg, 5);
         }
         else {
            SetScrollTitle(rectitle);
            old_width = -1;
         }
      }

      tColor msbg = Theme.Color(clrMessageStatusBg + 2 * Type);
      int y = y3 - 1;
      if (!showMessage) {
         osd->SaveRegion(x0, y2, x1 - 1, y);
         showMessage = true;
      }
      osd->DrawEllipse(x0, y2, lhh - 1, y, msbg, 7);
      osd->DrawText(x0 + lhh, y2, Text, Theme.Color(clrMessageStatusFg + 2 * Type), msbg, font, x1 - x0 - 2 * lhh, y3 - y2, taCenter);
      osd->DrawEllipse(x1 - lhh, y2, x1 - 1, y, msbg, 5);
      changed = true;
   }
   else {
      if (showMessage) {
         osd->RestoreRegion();
         showMessage = false;
         changed = true;
      }
   }
}

void cSkinElchiDisplayReplay::Flush(void)
{
   DSYSLOG2("skinelchi: cSkinElchiDisplayReplay::Flush()")

   // update volume if changed
   if (!showMessage && (ElchiStatus->GetVolumeChange() != volumechange)) {
      volumechange = ElchiStatus->GetVolumeChange();
      int x = x0 + y1;
      int w = x1 - y1 / 2;
      int y = y1 + 4;
      int h = y2 - 5;
      if (!showVolume) {
         showVolume = true;
         if (modeonly) {
            osd->SaveRegion(x0, y0, x1 - 1, y2 - 1);
            osd->DrawRectangle(x1 - lhh, y1, x1 - 1, y2 - lhh - 1, clrTransparent);
            osd->DrawEllipse(x1 - lhh, y1, x1 - 1, y2 - lhh - 1, bg, 1);
            osd->DrawRectangle(x0 + lhh, y1, x0 + lh - 1, y2 - 1, clrTransparent);
            osd->DrawEllipse(x0 + lhh, y1, x0 + lh - 1, y2 - 1, bg, 7);
            osd->DrawRectangle(x0 + lh, y1, x1 - lhh - 1, y2 - 1, bg);
            osd->DrawRectangle(x0, y2, x3 - 1, y3 - 1, clrTransparent);
            osd->DrawSlope(x5, y2, x3 - 1, y3 - 1, bg, 3);
            osd->DrawRectangle(x3, y2, x3 + lhh - 1, y3 - 1, bg);
            osd->DrawRectangle(x1 - lhh, y2 - lhh, x1 - 1, y2 + lhh, bg);
         }
         else
            osd->SaveRegion(x, y, w, h);

         //isyslog("skinelchi:Replay (%s:%d)",__FILE__,__LINE__);
         SetScrollTitle(trVDR("Volume "));
      }
      int p = (w - x) * ElchiStatus->GetVolume() / 255;
      int xp = x + p;
      osd->DrawRectangle(x, y, xp - 1, h, Theme.Color(clrVolumeBarUpper));
      osd->DrawRectangle(xp, y, w - 1, h, Theme.Color(clrVolumeBarLower));
      changed = true;
      volumeTimer.Set(1000);
   }
   else {
      if (showVolume && volumeTimer.TimedOut()) {
         showVolume = false;
         osd->RestoreRegion();
         if (modeonly) {
            osd->DrawRectangle(x5, y2, x3 + lhh - 1, y3 - 1, clrTransparent);
            osd->DrawEllipse(x3, y2, x3 + lhh - 1, y3 - 1, bg, 7);
            osd->DrawRectangle(x1 - lhh, y2, x1 - 1, y3 - 1, clrTransparent);
            osd->DrawEllipse(x1 - lhh, y2, x1 - 1, y3 - 1, bg, 5);
         }
         else {
            //isyslog("skinelchi:Replay (%s:%d)",__FILE__,__LINE__);
            SetScrollTitle(rectitle);
            old_width = -1;
         }
         changed = true;
      }
   }

   // show video format info (size in title and AR-bitmap)
   if (ElchiConfig.showVideoInfo) {
      cVideoInfo videoinfo;
      VideoStatus->GetVideoInfo(&videoinfo);
      if (Setup.ShowReplayMode && !showMessage && old_ar != videoinfo.aspectratio) {
         cBitmap *bmp = NULL;
         switch (videoinfo.aspectratio) {
            case ar4_3:
                  bmp = &bmAR43;
                  break;
            case arL14_9:
                  bmp = &bmARL149;
                  break;
            case arL16_9:
                  bmp = &bmARL169;
                  break;
            case arLG16_9:
                  bmp = &bmARL169;
                  break;
            case ar16_9:
                  bmp = &bmAR169;
                  break;
            case ar221_1:
                  bmp = &bmAR2211;
                  break;
            default:
                  break;
         }

         if (bmp)
            osd->DrawBitmap(xAR, y2 + (y3 - y2 - bmp->Height()) / 2, *bmp, Theme.Color(clrReplaySymbolOn), Theme.Color(clrBackground));
         else
            osd->DrawRectangle(xAR, y2, x1 - y1/2 - 1, y3 - 1, Theme.Color(clrBackground));

         changed = true;
         old_ar = videoinfo.aspectratio;
      }

      if (ElchiConfig.showVideoInfo == 2 && !modeonly && !showVolume) {
         if ((old_width != videoinfo.width) || (old_height != videoinfo.height)) {
            if (videoinfo.width && videoinfo.height) {
               title = cString::sprintf("%s %dx%d", (const char *)rectitle, videoinfo.width, videoinfo.height);
            }
            else {
               title = rectitle;
            }
            //isyslog("skinelchi:Replay %dx%d (%s:%d)", videoinfo.width, videoinfo.height, __FILE__,__LINE__);
            TitleScroll->SetText(title);
            old_width = videoinfo.width;
            old_height = videoinfo.height;
            changed = true;
         }
      }
      //}  // end HasVideoInfo
   }  //end videoinfo

   if (TitleScroll) changed |= TitleScroll->DrawIfNeeded();

   // update "rec" symbol
   if (Setup.ShowReplayMode && !showMessage) {
      bool rectemp = cRecordControls::Active();
      if (rec != rectemp) {
         rec = rectemp;
         osd->DrawBitmap(xRecording, y2 + (y3 - y2 - bmRecording.Height()) / 2, bmRecording, rec ? Theme.Color(clrSymbolRecFg) : Theme.Color(clrReplaySymbolOff), rec ? Theme.Color(clrSymbolRecBg) : bg);
         changed = true;
      }
   }

   if (changed) {
      DSYSLOG2("skinelchi: cSkinElchiDisplayReplay::Flush()")
      osd->Flush();
      changed = false;
   }
   //isyslog("skinelchi: cSkinElchiDisplayReplay::Flush() end");
}
