vdr  2.0.4
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 }
196