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