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