1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
/*
* interface.c: Abstract user interface layer
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.c 4.1 2015/04/28 11:16:06 kls Exp $
*/
#include "interface.h"
#include <ctype.h>
#include <stdlib.h>
#ifdef SDNOTIFY
#include <systemd/sd-daemon.h>
#endif
#include <unistd.h>
#include "i18n.h"
#include "status.h"
cInterface *Interface = NULL;
cInterface::cInterface(void)
{
interrupted = false;
}
cInterface::~cInterface()
{
}
eKeys cInterface::GetKey(bool Wait)
{
if (!cRemote::HasKeys())
Skins.Flush();
if (!cRemote::IsLearning())
return cRemote::Get(Wait ? 1000 : 10);
else
return kNone;
}
eKeys cInterface::Wait(int Seconds, bool KeepChar)
{
if (Seconds == 0)
Seconds = Setup.OSDMessageTime;
Skins.Flush();
eKeys Key = kNone;
time_t timeout = time(NULL) + Seconds;
for (;;) {
Key = GetKey();
if (ISRAWKEY(Key) || time(NULL) > timeout || interrupted)
break;
}
if (KeepChar && ISRAWKEY(Key) || Key == k_Plugin)
cRemote::Put(Key);
interrupted = false;
return Key;
}
bool cInterface::Confirm(const char *s, int Seconds, bool WaitForTimeout)
{
isyslog("confirm: %s", s);
eKeys k = Skins.Message(mtWarning, s, Seconds);
bool result = WaitForTimeout ? k == kNone : k == kOk;
isyslog("%sconfirmed", result ? "" : "not ");
return result;
}
bool cInterface::QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu)
{
DisplayMenu->SetItem(tr("Phase 1: Detecting RC code type"), 2, false, false);
DisplayMenu->SetItem(tr("Press any key on the RC unit"), 4, false, false);
DisplayMenu->Flush();
if (Remote->Initialize()) {
DisplayMenu->SetItem(tr("RC code detected!"), 4, false, false);
DisplayMenu->SetItem(tr("Do not press any key..."), 5, false, false);
DisplayMenu->Flush();
cCondWait::SleepMs(3000);
DisplayMenu->SetItem("", 4, false, false);
DisplayMenu->SetItem("", 5, false, false);
DisplayMenu->SetItem(tr("Phase 2: Learning specific key codes"), 2, false, false);
eKeys NewKey = kUp;
while (NewKey != kNone) {
DisplayMenu->SetItem(cString::sprintf(tr("Press key for '%s'"), cKey::ToString(NewKey, true)), 4, false, false);
cRemote::Clear();
DisplayMenu->Flush();
for (eKeys k = NewKey; k == NewKey; ) {
char *NewCode = NULL;
eKeys Key = cRemote::Get(100, &NewCode);
switch (Key) {
case kUp: if (NewKey > kUp) {
NewKey = eKeys(NewKey - 1);
cKey *last = Keys.Last();
if (last && last->Key() == NewKey)
Keys.Del(last);
}
break;
case kDown: DisplayMenu->SetItem(tr("Press 'Up' to confirm"), 4, false, false);
DisplayMenu->SetItem(tr("Press 'Down' to continue"), 5, false, false);
DisplayMenu->SetItem("", 6, false, false);
DisplayMenu->SetItem("", 7, false, false);
DisplayMenu->SetItem("", 8, false, false);
DisplayMenu->Flush();
for (;;) {
Key = cRemote::Get(100);
if (Key == kUp) {
DisplayMenu->Clear();
return true;
}
else if (Key == kDown) {
DisplayMenu->SetItem("", 5, false, false);
k = kNone; // breaks the outer for() loop
break;
}
}
break;
case kMenu: NewKey = eKeys(NewKey + 1);
break;
case kNone: if (NewCode) {
dsyslog("new %s code: %s = %s", Remote->Name(), NewCode, cKey::ToString(NewKey));
Keys.Add(new cKey(Remote->Name(), NewCode, NewKey));
NewKey = eKeys(NewKey + 1);
free(NewCode);
}
break;
default: break;
}
}
if (NewKey > kUp)
DisplayMenu->SetItem(tr("(press 'Up' to go back)"), 6, false, false);
else
DisplayMenu->SetItem("", 6, false, false);
if (NewKey > kDown)
DisplayMenu->SetItem(tr("(press 'Down' to end key definition)"), 7, false, false);
else
DisplayMenu->SetItem("", 7, false, false);
if (NewKey > kMenu)
DisplayMenu->SetItem(tr("(press 'Menu' to skip this key)"), 8, false, false);
else
DisplayMenu->SetItem("", 8, false, false);
}
return true;
}
return false;
}
void cInterface::LearnKeys(void)
{
for (cRemote *Remote = Remotes.First(); Remote; Remote = Remotes.Next(Remote)) {
if (!Remote->Ready()) {
esyslog("ERROR: remote control %s not ready!", Remote->Name());
continue;
}
bool known = Keys.KnowsRemote(Remote->Name());
dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
if (!known) {
#ifdef SDNOTIFY
sd_notify(0, "READY=1\nSTATUS=Learning keys...");
#endif
cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu();
DisplayMenu->SetMenuCategory(mcUnknown);
char Headline[256];
snprintf(Headline, sizeof(Headline), tr("Learning Remote Control Keys"));
cRemote::Clear();
DisplayMenu->SetTitle(Headline);
DisplayMenu->SetItem(Remote->Name(), 0, false, false);
cRemote::SetLearning(Remote);
bool rc = QueryKeys(Remote, DisplayMenu);
cRemote::SetLearning(NULL);
DisplayMenu->Clear();
if (!rc) {
delete DisplayMenu;
continue;
}
DisplayMenu->SetItem(Remote->Name(), 0, false, false);
DisplayMenu->SetItem(tr("Phase 3: Saving key codes"), 2, false, false);
DisplayMenu->SetItem(tr("Press 'Up' to save, 'Down' to cancel"), 4, false, false);
for (;;) {
eKeys key = GetKey();
if (key == kUp) {
Keys.Save();
delete DisplayMenu;
break;
}
else if (key == kDown) {
Keys.Load();
delete DisplayMenu;
break;
}
}
}
}
}
|