vdr  2.0.5
interface.c
Go to the documentation of this file.
1 /*
2  * interface.c: Abstract user interface layer
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: interface.c 2.2 2012/11/19 12:21:43 kls Exp $
8  */
9 
10 #include "interface.h"
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include "i18n.h"
15 #include "status.h"
16 
18 
19 cInterface::cInterface(int SVDRPport)
20 {
21  interrupted = false;
22  SVDRP = NULL;
23  if (SVDRPport)
24  SVDRP = new cSVDRP(SVDRPport);
25 }
26 
28 {
29  delete SVDRP;
30 }
31 
33 {
34  if (!cRemote::HasKeys())
35  Skins.Flush();
36  if (SVDRP) {
37  if (SVDRP->Process())
38  Wait = false;
39  }
40  if (!cRemote::IsLearning())
41  return cRemote::Get(Wait ? 1000 : 10);
42  else
43  return kNone;
44 }
45 
46 eKeys cInterface::Wait(int Seconds, bool KeepChar)
47 {
48  if (Seconds == 0)
49  Seconds = Setup.OSDMessageTime;
50  Skins.Flush();
51  eKeys Key = kNone;
52  time_t timeout = time(NULL) + Seconds;
53  for (;;) {
54  Key = GetKey();
55  if (ISRAWKEY(Key) || time(NULL) > timeout || interrupted)
56  break;
57  }
58  if (KeepChar && ISRAWKEY(Key) || Key == k_Plugin)
59  cRemote::Put(Key);
60  interrupted = false;
61  return Key;
62 }
63 
64 bool cInterface::Confirm(const char *s, int Seconds, bool WaitForTimeout)
65 {
66  isyslog("confirm: %s", s);
67  eKeys k = Skins.Message(mtWarning, s, Seconds);
68  bool result = WaitForTimeout ? k == kNone : k == kOk;
69  isyslog("%sconfirmed", result ? "" : "not ");
70  return result;
71 }
72 
73 bool cInterface::QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu)
74 {
75  DisplayMenu->SetItem(tr("Phase 1: Detecting RC code type"), 2, false, false);
76  DisplayMenu->SetItem(tr("Press any key on the RC unit"), 4, false, false);
77  DisplayMenu->Flush();
78  if (Remote->Initialize()) {
79  DisplayMenu->SetItem(tr("RC code detected!"), 4, false, false);
80  DisplayMenu->SetItem(tr("Do not press any key..."), 5, false, false);
81  DisplayMenu->Flush();
82  cCondWait::SleepMs(3000);
83  DisplayMenu->SetItem("", 4, false, false);
84  DisplayMenu->SetItem("", 5, false, false);
85 
86  DisplayMenu->SetItem(tr("Phase 2: Learning specific key codes"), 2, false, false);
87  eKeys NewKey = kUp;
88  while (NewKey != kNone) {
89  DisplayMenu->SetItem(cString::sprintf(tr("Press key for '%s'"), cKey::ToString(NewKey, true)), 4, false, false);
91  DisplayMenu->Flush();
92  for (eKeys k = NewKey; k == NewKey; ) {
93  char *NewCode = NULL;
94  eKeys Key = cRemote::Get(100, &NewCode);
95  switch (Key) {
96  case kUp: if (NewKey > kUp) {
97  NewKey = eKeys(NewKey - 1);
98  cKey *last = Keys.Last();
99  if (last && last->Key() == NewKey)
100  Keys.Del(last);
101  }
102  break;
103  case kDown: DisplayMenu->SetItem(tr("Press 'Up' to confirm"), 4, false, false);
104  DisplayMenu->SetItem(tr("Press 'Down' to continue"), 5, false, false);
105  DisplayMenu->SetItem("", 6, false, false);
106  DisplayMenu->SetItem("", 7, false, false);
107  DisplayMenu->SetItem("", 8, false, false);
108  DisplayMenu->Flush();
109  for (;;) {
110  Key = cRemote::Get(100);
111  if (Key == kUp) {
112  DisplayMenu->Clear();
113  return true;
114  }
115  else if (Key == kDown) {
116  DisplayMenu->SetItem("", 5, false, false);
117  k = kNone; // breaks the outer for() loop
118  break;
119  }
120  }
121  break;
122  case kMenu: NewKey = eKeys(NewKey + 1);
123  break;
124  case kNone: if (NewCode) {
125  dsyslog("new %s code: %s = %s", Remote->Name(), NewCode, cKey::ToString(NewKey));
126  Keys.Add(new cKey(Remote->Name(), NewCode, NewKey));
127  NewKey = eKeys(NewKey + 1);
128  free(NewCode);
129  }
130  break;
131  default: break;
132  }
133  }
134  if (NewKey > kUp)
135  DisplayMenu->SetItem(tr("(press 'Up' to go back)"), 6, false, false);
136  else
137  DisplayMenu->SetItem("", 6, false, false);
138  if (NewKey > kDown)
139  DisplayMenu->SetItem(tr("(press 'Down' to end key definition)"), 7, false, false);
140  else
141  DisplayMenu->SetItem("", 7, false, false);
142  if (NewKey > kMenu)
143  DisplayMenu->SetItem(tr("(press 'Menu' to skip this key)"), 8, false, false);
144  else
145  DisplayMenu->SetItem("", 8, false, false);
146  }
147  return true;
148  }
149  return false;
150 }
151 
153 {
154  for (cRemote *Remote = Remotes.First(); Remote; Remote = Remotes.Next(Remote)) {
155  if (!Remote->Ready()) {
156  esyslog("ERROR: remote control %s not ready!", Remote->Name());
157  continue;
158  }
159  bool known = Keys.KnowsRemote(Remote->Name());
160  dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
161  if (!known) {
162  cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu();
163  DisplayMenu->SetMenuCategory(mcUnknown);
164  char Headline[256];
165  snprintf(Headline, sizeof(Headline), tr("Learning Remote Control Keys"));
166  cRemote::Clear();
167  DisplayMenu->SetTitle(Headline);
168  DisplayMenu->SetItem(Remote->Name(), 0, false, false);
169  cRemote::SetLearning(Remote);
170  bool rc = QueryKeys(Remote, DisplayMenu);
171  cRemote::SetLearning(NULL);
172  DisplayMenu->Clear();
173  if (!rc) {
174  delete DisplayMenu;
175  continue;
176  }
177  DisplayMenu->SetItem(Remote->Name(), 0, false, false);
178  DisplayMenu->SetItem(tr("Phase 3: Saving key codes"), 2, false, false);
179  DisplayMenu->SetItem(tr("Press 'Up' to save, 'Down' to cancel"), 4, false, false);
180  for (;;) {
181  eKeys key = GetKey();
182  if (key == kUp) {
183  Keys.Save();
184  delete DisplayMenu;
185  break;
186  }
187  else if (key == kDown) {
188  Keys.Load();
189  delete DisplayMenu;
190  break;
191  }
192  }
193  }
194  }
195 }
static void SetLearning(cRemote *Learning)
Definition: remote.h:47
bool KnowsRemote(const char *Remote)
Definition: keys.c:158
#define dsyslog(a...)
Definition: tools.h:36
bool Confirm(const char *s, int Seconds=10, bool WaitForTimeout=false)
Definition: interface.c:64
Definition: keys.h:90
Definition: keys.h:19
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:1945
eKeys Key(void)
Definition: keys.h:101
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1011
static eKeys Get(int WaitMs=1000, char **UnknownCode=NULL)
Definition: remote.c:181
Definition: keys.h:17
#define esyslog(a...)
Definition: tools.h:34
bool Load(const char *FileName=NULL, bool AllowComments=false, bool MustExist=false)
Definition: config.h:119
bool QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu)
Definition: interface.c:73
virtual cSkinDisplayMenu * DisplayMenu(void)=0
Creates and returns a new object for displaying a menu.
#define ISRAWKEY(k)
Definition: keys.h:76
static void Clear(void)
Definition: remote.c:72
cRemotes Remotes
Definition: remote.c:211
virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable)=0
Sets the item at the given Index to Text.
Definition: keys.h:55
Definition: keys.h:58
T * Last(void) const
Definition: tools.h:483
static bool IsLearning()
Definition: remote.h:48
bool interrupted
Definition: interface.h:20
eKeys Wait(int Seconds=0, bool KeepChar=false)
Definition: interface.c:46
T * Next(const T *object) const
Definition: tools.h:485
~cInterface()
Definition: interface.c:27
virtual void Flush(void)
Actually draws the OSD display to the output device.
Definition: skins.h:45
cInterface(int SVDRPport=0)
Definition: interface.c:19
bool Save(void)
Definition: config.h:166
cSVDRP * SVDRP
Definition: interface.h:21
void Flush(void)
Flushes the currently active cSkinDisplay, if any.
Definition: skins.c:375
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
Definition: thread.c:57
Definition: keys.h:18
cKeys Keys
Definition: keys.c:156
cSetup Setup
Definition: config.c:373
bool Put(uint64_t Code, bool Repeat=false, bool Release=false)
Definition: remote.c:124
Definition: keys.h:20
static bool HasKeys(void)
Definition: remote.c:175
eKeys Message(eMessageType Type, const char *s, int Seconds=0)
Displays the given message, either through a currently visible display object that is capable of doin...
Definition: skins.c:234
Definition: remote.h:20
virtual bool Initialize(void)
Definition: remote.c:61
T * First(void) const
Definition: tools.h:482
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:1977
eKeys GetKey(bool Wait=true)
Definition: interface.c:32
virtual void SetMenuCategory(eMenuCategory MenuCategory)
Sets the current menu category.
Definition: skins.c:74
#define tr(s)
Definition: i18n.h:85
Definition: svdrp.h:42
#define isyslog(a...)
Definition: tools.h:35
const char * Name(void)
Definition: remote.h:46
virtual void SetTitle(const char *Title)=0
Sets the title of this menu to Title.
virtual void Clear(void)=0
Clears the entire central area of the menu.
cInterface * Interface
Definition: interface.c:17
int OSDMessageTime
Definition: config.h:314
cSkin * Current(void)
Returns a pointer to the current skin.
Definition: skins.h:408
bool Process(void)
Definition: svdrp.c:1743
eKeys
Definition: keys.h:16
static const char * ToString(eKeys Key, bool Translate=false)
Definition: keys.c:138
void LearnKeys(void)
Definition: interface.c:152
cSkins Skins
Definition: skins.c:203