Home

Dokumentation

Impressum

Dokumentation VDR
 

Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

interface.c

Go to the documentation of this file.
00001 /*
00002  * interface.c: Abstract user interface layer
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: interface.c 1.61 2002/12/06 14:13:16 kls Exp $
00008  */
00009 
00010 #include "interface.h"
00011 #include <ctype.h>
00012 #include <stdlib.h>
00013 #include <unistd.h>
00014 #include "i18n.h"
00015 #include "osd.h"
00016 #include "status.h"
00017 
00018 cInterface *Interface = NULL;
00019 
00020 cInterface::cInterface(int SVDRPport)
00021 {
00022   open = 0;
00023   cols[0] = 0;
00024   width = height = 0;
00025   interrupted = false;
00026   SVDRP = NULL;
00027   if (SVDRPport)
00028      SVDRP = new cSVDRP(SVDRPport);
00029 }
00030 
00031 cInterface::~cInterface()
00032 {
00033   delete SVDRP;
00034 }
00035 
00036 void cInterface::Open(int NumCols, int NumLines)
00037 {
00038   if (!open++) {
00039      if (NumCols == 0)
00040         NumCols = Setup.OSDwidth;
00041      if (NumLines == 0)
00042         NumLines = Setup.OSDheight;
00043      cOsd::Open(width = NumCols, height = NumLines);
00044      }
00045 }
00046 
00047 void cInterface::Close(void)
00048 {
00049   if (open == 1)
00050      Clear();
00051   if (!--open) {
00052      cOsd::Close();
00053      width = height = 0;
00054      }
00055 }
00056 
00057 eKeys cInterface::GetKey(bool Wait)
00058 {
00059   Flush();
00060   if (SVDRP) {
00061      if (SVDRP->Process())
00062         Wait = false;
00063      if (!open) {
00064         char *message = SVDRP->GetMessage();
00065         if (message) {
00066            Info(message);
00067            free(message);
00068            }
00069         }
00070      }
00071   return cRemote::Get(Wait ? 1000 : 10);
00072 }
00073 
00074 eKeys cInterface::Wait(int Seconds, bool KeepChar)
00075 {
00076   if (Seconds == 0)
00077      Seconds = Setup.OSDMessageTime;
00078   Flush();
00079   eKeys Key = kNone;
00080   time_t timeout = time(NULL) + Seconds;
00081   for (;;) {
00082       Key = GetKey();
00083       if ((Key != kNone && (RAWKEY(Key) != kOk || RAWKEY(Key) == Key)) || time(NULL) > timeout || interrupted)
00084          break;
00085       }
00086   if (KeepChar && ISRAWKEY(Key))
00087      cRemote::Put(Key);
00088   interrupted = false;
00089   return Key;
00090 }
00091 
00092 void cInterface::Clear(void)
00093 {
00094   if (open)
00095      cOsd::Clear();
00096   cStatus::MsgOsdClear();
00097 }
00098 
00099 void cInterface::ClearEol(int x, int y, eDvbColor Color)
00100 {
00101   if (open)
00102      cOsd::ClrEol(x, y, Color);
00103 }
00104 
00105 void cInterface::Fill(int x, int y, int w, int h, eDvbColor Color)
00106 {
00107   if (open)
00108      cOsd::Fill(x, y, w, h, Color);
00109 }
00110 
00111 void cInterface::SetBitmap(int x, int y, const cBitmap &Bitmap)
00112 {
00113   if (open)
00114      cOsd::SetBitmap(x, y, Bitmap);
00115 }
00116 
00117 void cInterface::Flush(void)
00118 {
00119   if (open)
00120      cOsd::Flush();
00121 }
00122 
00123 void cInterface::SetCols(int *c)
00124 {
00125   for (int i = 0; i < MaxCols; i++) {
00126       cols[i] = *c++;
00127       if (cols[i] == 0)
00128          break;
00129       }
00130 }
00131 
00132 eDvbFont cInterface::SetFont(eDvbFont Font)
00133 {
00134   return cOsd::SetFont(Font);
00135 }
00136 
00137 char *cInterface::WrapText(const char *Text, int Width, int *Height)
00138 {
00139   // Wraps the Text to make it fit into the area defined by the given Width
00140   // (which is given in character cells).
00141   // The actual number of lines resulting from this operation is returned in
00142   // Height.
00143   // The returned string is newly created on the heap and the caller
00144   // is responsible for deleting it once it is no longer used.
00145   // Wrapping is done by inserting the necessary number of newline
00146   // characters into the string.
00147 
00148   int Lines = 1;
00149   char *t = strdup(Text);
00150   char *Blank = NULL;
00151   char *Delim = NULL;
00152   int w = 0;
00153 
00154   Width *= cOsd::CellWidth();
00155 
00156   while (*t && t[strlen(t) - 1] == '\n')
00157         t[strlen(t) - 1] = 0; // skips trailing newlines
00158 
00159   for (char *p = t; *p; ) {
00160       if (*p == '|')
00161          *p = '\n';
00162       if (*p == '\n') {
00163          Lines++;
00164          w = 0;
00165          Blank = Delim = NULL;
00166          p++;
00167          continue;
00168          }
00169       else if (isspace(*p))
00170          Blank = p;
00171       int cw = cOsd::Width(*p);
00172       if (w + cw > Width) {
00173          if (Blank) {
00174             *Blank = '\n';
00175             p = Blank;
00176             continue;
00177             }
00178          else {
00179             // Here's the ugly part, where we don't have any whitespace to
00180             // punch in a newline, so we need to make room for it:
00181             if (Delim)
00182                p = Delim + 1; // let's fall back to the most recent delimiter
00183             char *s = MALLOC(char, strlen(t) + 2); // The additional '\n' plus the terminating '\0'
00184             int l = p - t;
00185             strncpy(s, t, l);
00186             s[l] = '\n';
00187             strcpy(s + l + 1, p);
00188             free(t);
00189             t = s;
00190             p = t + l;
00191             continue;
00192             }
00193          }
00194       else
00195          w += cw;
00196       if (strchr("-.,:;!?_", *p)) {
00197          Delim = p;
00198          Blank = NULL;
00199          }
00200       p++;
00201       }
00202 
00203   *Height = Lines;
00204   return t;
00205 }
00206 
00207 void cInterface::Write(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
00208 {
00209   if (open)
00210      cOsd::Text(x, y, s, FgColor, BgColor);
00211 }
00212 
00213 void cInterface::WriteText(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
00214 {
00215   if (open) {
00216      ClearEol(x, y, BgColor);
00217      int col = 0;
00218      for (;;) {
00219          const char *t = strchr(s, '\t');
00220          const char *p = s;
00221          char buf[1000];
00222          if (t && col < MaxCols && cols[col] > 0) {
00223             unsigned int n = t - s;
00224             if (n >= sizeof(buf))
00225                n = sizeof(buf) - 1;
00226             strncpy(buf, s, n);
00227             buf[n] = 0;
00228             p = buf;
00229             s = t + 1;
00230             }
00231          Write(x, y, p, FgColor, BgColor);
00232          if (p == s)
00233             break;
00234          x += cols[col++];
00235          }
00236      }
00237 }
00238 
00239 void cInterface::Title(const char *s)
00240 {
00241   ClearEol(0, 0, clrCyan);
00242   const char *t = strchr(s, '\t');
00243   if (t) {
00244      char buffer[Width() + 1];
00245      unsigned int n = t - s;
00246      if (n >= sizeof(buffer))
00247         n = sizeof(buffer) - 1;
00248      strn0cpy(buffer, s, n + 1);
00249      Write(1, 0, buffer, clrBlack, clrCyan);
00250      t++;
00251      Write(-(cOsd::WidthInCells(t) + 1), 0, t, clrBlack, clrCyan);
00252      }
00253   else {
00254      int x = (Width() - strlen(s)) / 2;
00255      if (x < 0)
00256         x = 0;
00257      Write(x, 0, s, clrBlack, clrCyan);
00258      }
00259   cStatus::MsgOsdTitle(s);
00260 }
00261 
00262 void cInterface::Status(const char *s, eDvbColor FgColor, eDvbColor BgColor)
00263 {
00264   int Line = (abs(height) == 1) ? 0 : -2;
00265   ClearEol(0, Line, s ? BgColor : clrBackground);
00266   if (s) {
00267      int x = (Width() - strlen(s)) / 2;
00268      if (x < 0)
00269         x = 0;
00270      Write(x, Line, s, FgColor, BgColor);
00271      }
00272   cStatus::MsgOsdStatusMessage(s);
00273 }
00274 
00275 void cInterface::Info(const char *s)
00276 {
00277   Open(Setup.OSDwidth, -1);
00278   isyslog("info: %s", s);
00279   Status(s, clrBlack, clrGreen);
00280   Wait();
00281   Status(NULL);
00282   Close();
00283 }
00284 
00285 void cInterface::Error(const char *s)
00286 {
00287   Open(Setup.OSDwidth, -1);
00288   esyslog("ERROR: %s", s);
00289   Status(s, clrWhite, clrRed);
00290   Wait();
00291   Status(NULL);
00292   Close();
00293 }
00294 
00295 bool cInterface::Confirm(const char *s, int Seconds, bool WaitForTimeout)
00296 {
00297   Open(Setup.OSDwidth, -1);
00298   isyslog("confirm: %s", s);
00299   Status(s, clrBlack, clrYellow);
00300   eKeys k = Wait(Seconds);
00301   bool result = WaitForTimeout ? k == kNone : k == kOk;
00302   Status(NULL);
00303   Close();
00304   isyslog("%sconfirmed", result ? "" : "not ");
00305   return result;
00306 }
00307 
00308 void cInterface::HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor)
00309 {
00310   if (open) {
00311      const int w = Width() / 4;
00312      cOsd::Fill(Index * w, -1, w, 1, Text ? BgColor : clrBackground);
00313      if (Text) {
00314         int l = (w - int(strlen(Text))) / 2;
00315         if (l < 0)
00316            l = 0;
00317         cOsd::Text(Index * w + l, -1, Text, FgColor, BgColor);
00318         }
00319      }
00320 }
00321 
00322 void cInterface::Help(const char *Red, const char *Green, const char *Yellow, const char *Blue)
00323 {
00324   HelpButton(0, Red,    clrBlack, clrRed);
00325   HelpButton(1, Green,  clrBlack, clrGreen);
00326   HelpButton(2, Yellow, clrBlack, clrYellow);
00327   HelpButton(3, Blue,   clrWhite, clrBlue);
00328   cStatus::MsgOsdHelpKeys(Red, Green, Yellow, Blue);
00329 }
00330 
00331 void cInterface::QueryKeys(cRemote *Remote)
00332 {
00333   WriteText(1, 3, tr("Phase 1: Detecting RC code type"));
00334   WriteText(1, 5, tr("Press any key on the RC unit"));
00335   Flush();
00336   if (Remote->Initialize()) {
00337      WriteText(1, 5, tr("RC code detected!"));
00338      WriteText(1, 6, tr("Do not press any key..."));
00339      Flush();
00340      sleep(3);
00341      ClearEol(0, 5);
00342      ClearEol(0, 6);
00343 
00344      WriteText(1, 3, tr("Phase 2: Learning specific key codes"));
00345      eKeys NewKey = kUp;
00346      while (NewKey != kNone) {
00347            char *Prompt;
00348            asprintf(&Prompt, tr("Press key for '%s'"), tr(cKey::ToString(NewKey)));
00349            WriteText(1, 5, Prompt);
00350            free(Prompt);
00351            cRemote::Clear();
00352            Flush();
00353            for (eKeys k = NewKey; k == NewKey; ) {
00354                char *NewCode = NULL;
00355                eKeys Key = cRemote::Get(100, &NewCode);
00356                switch (Key) {
00357                  case kUp:   if (NewKey > kUp) {
00358                                 NewKey = eKeys(NewKey - 1);
00359                                 cKey *last = Keys.Last();
00360                                 if (last && last->Key() == NewKey)
00361                                    Keys.Del(last);
00362                                 }
00363                              break;
00364                  case kDown: WriteText(1, 5, tr("Press 'Up' to confirm"));
00365                              WriteText(1, 6, tr("Press 'Down' to continue"));
00366                              ClearEol(0, 7);
00367                              ClearEol(0, 8);
00368                              ClearEol(0, 9);
00369                              Flush();
00370                              for (;;) {
00371                                  Key = cRemote::Get(100);
00372                                  if (Key == kUp) {
00373                                     Clear();
00374                                     return;
00375                                     }
00376                                  else if (Key == kDown) {
00377                                     ClearEol(0, 6);
00378                                     k = kNone; // breaks the outer for() loop
00379                                     break;
00380                                     }
00381                                  }
00382                              break;
00383                  case kMenu: NewKey = eKeys(NewKey + 1);
00384                              break;
00385                  case kNone: if (NewCode) {
00386                                 dsyslog("new %s code: %s = %s", Remote->Name(), NewCode, cKey::ToString(NewKey));
00387                                 Keys.Add(new cKey(Remote->Name(), NewCode, NewKey));
00388                                 NewKey = eKeys(NewKey + 1);
00389                                 free(NewCode);
00390                                 }
00391                              break;
00392                  default:    break;
00393                  }
00394                }
00395            if (NewKey > kUp)
00396               WriteText(1, 7, tr("(press 'Up' to go back)"));
00397            else
00398               ClearEol(0, 7);
00399            if (NewKey > kDown)
00400               WriteText(1, 8, tr("(press 'Down' to end key definition)"));
00401            else
00402               ClearEol(0, 8);
00403            if (NewKey > kMenu)
00404               WriteText(1, 9, tr("(press 'Menu' to skip this key)"));
00405            else
00406               ClearEol(0, 9);
00407            }
00408      }
00409 }
00410 
00411 void cInterface::LearnKeys(void)
00412 {
00413   for (cRemote *Remote = Remotes.First(); Remote; Remote = Remotes.Next(Remote)) {
00414       bool known = Keys.KnowsRemote(Remote->Name());
00415       dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
00416       if (!known) {
00417          Open();
00418          char Headline[Width()];
00419          snprintf(Headline, sizeof(Headline), tr("Learning Remote Control Keys (%s)"), Remote->Name());
00420          Clear();
00421          cRemote::Clear();
00422          WriteText(1, 1, Headline);
00423          cRemote::SetLearning(Remote);
00424          QueryKeys(Remote);
00425          cRemote::SetLearning(NULL);
00426          Clear();
00427          WriteText(1, 1, Headline);
00428          WriteText(1, 3, tr("Phase 3: Saving key codes"));
00429          WriteText(1, 5, tr("Press 'Up' to save, 'Down' to cancel"));
00430          for (;;) {
00431              eKeys key = GetKey();
00432              if (key == kUp) {
00433                 Keys.Save();
00434                 Close();
00435                 break;
00436                 }
00437              else if (key == kDown) {
00438                 Keys.Load();
00439                 Close();
00440                 break;
00441                 }
00442              }
00443          }
00444       }
00445 }

Generated on Wed Feb 5 23:30:09 2003 for VDR by doxygen1.3-rc2