vdr  1.7.27
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 2.1 2011/12/04 14:52:38 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 "status.h"
00016 
00017 cInterface *Interface = NULL;
00018 
00019 cInterface::cInterface(int SVDRPport)
00020 {
00021   interrupted = false;
00022   SVDRP = NULL;
00023   if (SVDRPport)
00024      SVDRP = new cSVDRP(SVDRPport);
00025 }
00026 
00027 cInterface::~cInterface()
00028 {
00029   delete SVDRP;
00030 }
00031 
00032 eKeys cInterface::GetKey(bool Wait)
00033 {
00034   if (!cRemote::HasKeys())
00035      Skins.Flush();
00036   if (SVDRP) {
00037      if (SVDRP->Process())
00038         Wait = false;
00039      }
00040   if (!cRemote::IsLearning())
00041      return cRemote::Get(Wait ? 1000 : 10);
00042   else
00043      return kNone;
00044 }
00045 
00046 eKeys cInterface::Wait(int Seconds, bool KeepChar)
00047 {
00048   if (Seconds == 0)
00049      Seconds = Setup.OSDMessageTime;
00050   Skins.Flush();
00051   eKeys Key = kNone;
00052   time_t timeout = time(NULL) + Seconds;
00053   for (;;) {
00054       Key = GetKey();
00055       if (ISRAWKEY(Key) || time(NULL) > timeout || interrupted)
00056          break;
00057       }
00058   if (KeepChar && ISRAWKEY(Key) || Key == k_Plugin)
00059      cRemote::Put(Key);
00060   interrupted = false;
00061   return Key;
00062 }
00063 
00064 bool cInterface::Confirm(const char *s, int Seconds, bool WaitForTimeout)
00065 {
00066   isyslog("confirm: %s", s);
00067   eKeys k = Skins.Message(mtWarning, s, Seconds);
00068   bool result = WaitForTimeout ? k == kNone : k == kOk;
00069   isyslog("%sconfirmed", result ? "" : "not ");
00070   return result;
00071 }
00072 
00073 bool cInterface::QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu)
00074 {
00075   DisplayMenu->SetItem(tr("Phase 1: Detecting RC code type"), 2, false, false);
00076   DisplayMenu->SetItem(tr("Press any key on the RC unit"), 4, false, false);
00077   DisplayMenu->Flush();
00078   if (Remote->Initialize()) {
00079      DisplayMenu->SetItem(tr("RC code detected!"), 4, false, false);
00080      DisplayMenu->SetItem(tr("Do not press any key..."), 5, false, false);
00081      DisplayMenu->Flush();
00082      cCondWait::SleepMs(3000);
00083      DisplayMenu->SetItem("", 4, false, false);
00084      DisplayMenu->SetItem("", 5, false, false);
00085 
00086      DisplayMenu->SetItem(tr("Phase 2: Learning specific key codes"), 2, false, false);
00087      eKeys NewKey = kUp;
00088      while (NewKey != kNone) {
00089            DisplayMenu->SetItem(cString::sprintf(tr("Press key for '%s'"), cKey::ToString(NewKey, true)), 4, false, false);
00090            cRemote::Clear();
00091            DisplayMenu->Flush();
00092            for (eKeys k = NewKey; k == NewKey; ) {
00093                char *NewCode = NULL;
00094                eKeys Key = cRemote::Get(100, &NewCode);
00095                switch (Key) {
00096                  case kUp:   if (NewKey > kUp) {
00097                                 NewKey = eKeys(NewKey - 1);
00098                                 cKey *last = Keys.Last();
00099                                 if (last && last->Key() == NewKey)
00100                                    Keys.Del(last);
00101                                 }
00102                              break;
00103                  case kDown: DisplayMenu->SetItem(tr("Press 'Up' to confirm"), 4, false, false);
00104                              DisplayMenu->SetItem(tr("Press 'Down' to continue"), 5, false, false);
00105                              DisplayMenu->SetItem("", 6, false, false);
00106                              DisplayMenu->SetItem("", 7, false, false);
00107                              DisplayMenu->SetItem("", 8, false, false);
00108                              DisplayMenu->Flush();
00109                              for (;;) {
00110                                  Key = cRemote::Get(100);
00111                                  if (Key == kUp) {
00112                                     DisplayMenu->Clear();
00113                                     return true;
00114                                     }
00115                                  else if (Key == kDown) {
00116                                     DisplayMenu->SetItem("", 5, false, false);
00117                                     k = kNone; // breaks the outer for() loop
00118                                     break;
00119                                     }
00120                                  }
00121                              break;
00122                  case kMenu: NewKey = eKeys(NewKey + 1);
00123                              break;
00124                  case kNone: if (NewCode) {
00125                                 dsyslog("new %s code: %s = %s", Remote->Name(), NewCode, cKey::ToString(NewKey));
00126                                 Keys.Add(new cKey(Remote->Name(), NewCode, NewKey));
00127                                 NewKey = eKeys(NewKey + 1);
00128                                 free(NewCode);
00129                                 }
00130                              break;
00131                  default:    break;
00132                  }
00133                }
00134            if (NewKey > kUp)
00135               DisplayMenu->SetItem(tr("(press 'Up' to go back)"), 6, false, false);
00136            else
00137               DisplayMenu->SetItem("", 6, false, false);
00138            if (NewKey > kDown)
00139               DisplayMenu->SetItem(tr("(press 'Down' to end key definition)"), 7, false, false);
00140            else
00141               DisplayMenu->SetItem("", 7, false, false);
00142            if (NewKey > kMenu)
00143               DisplayMenu->SetItem(tr("(press 'Menu' to skip this key)"), 8, false, false);
00144            else
00145               DisplayMenu->SetItem("", 8, false, false);
00146            }
00147      return true;
00148      }
00149   return false;
00150 }
00151 
00152 void cInterface::LearnKeys(void)
00153 {
00154   for (cRemote *Remote = Remotes.First(); Remote; Remote = Remotes.Next(Remote)) {
00155       if (!Remote->Ready()) {
00156          esyslog("ERROR: remote control %s not ready!", Remote->Name());
00157          continue;
00158          }
00159       bool known = Keys.KnowsRemote(Remote->Name());
00160       dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
00161       if (!known) {
00162          cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu();
00163          char Headline[256];
00164          snprintf(Headline, sizeof(Headline), tr("Learning Remote Control Keys"));
00165          cRemote::Clear();
00166          DisplayMenu->SetTitle(Headline);
00167          DisplayMenu->SetItem(Remote->Name(), 0, false, false);
00168          cRemote::SetLearning(Remote);
00169          bool rc = QueryKeys(Remote, DisplayMenu);
00170          cRemote::SetLearning(NULL);
00171          DisplayMenu->Clear();
00172          if (!rc) {
00173             delete DisplayMenu;
00174             continue;
00175             }
00176          DisplayMenu->SetItem(Remote->Name(), 0, false, false);
00177          DisplayMenu->SetItem(tr("Phase 3: Saving key codes"), 2, false, false);
00178          DisplayMenu->SetItem(tr("Press 'Up' to save, 'Down' to cancel"), 4, false, false);
00179          for (;;) {
00180              eKeys key = GetKey();
00181              if (key == kUp) {
00182                 Keys.Save();
00183                 delete DisplayMenu;
00184                 break;
00185                 }
00186              else if (key == kDown) {
00187                 Keys.Load();
00188                 delete DisplayMenu;
00189                 break;
00190                 }
00191              }
00192          }
00193       }
00194 }