vdr/interface.c
Klaus Schmidinger 8c63e0fd96 Version 1.3.37
- Added compiler options "-fPIC -g" to all plugins (thanks to Rolf Ahrenberg).
- Fixed initializing the day index when editing the weekday parameter of a
  repeating timer (thanks to Marco Schlüßler).
- No longer removing superfluous hyphens in EPG data - would become too
  language dependent to handle all kinds of exceptions.
- Modified switching to Dolby Digital audio in live mode, if the driver
  and firmware can handle live DD without the need of a Transfer Mode (thanks
  to Werner Fink). Live DD mode requires a full featured DVB card and a
  LinuxDVB driver with firmware version 0x2622 or higher. Older versions will
  use Transfer Mode just like before.
- Implemented handling of the "CA PMT Reply" for CAMs (thanks to Marco
  Schlüßler for figuring out some obscure length bytes in the CA PMT Reply
  data of AlphaCrypt CAMs).
- Some preparations for being able to record several encrypted channels from
  the same transponder at the same time (or record and view different encrypted
  channels), provided the CAM in use can handle this. This is work in progress
  and isn't actively used, yet.
- Fixed SetProgress() in the 'skincurses' plugin in case Total is 0 (reported
  by Stefan Huelswitt).
- Added a copy constructor to cString and fixed its assignment operator
  (thanks to Holger Brunn).
- The new function Skins.QueueMessage() can be called from a background thread
  to queue a message for display. See VDR/skins.h for details.
- The SVDRP command MESG uses the new message queueing facility, so MESG
  commands may now be executed at any time, and the message will be displayed
  (no more "pending message").
2005-11-27 18:00:00 +01:00

195 lines
6.7 KiB
C

/*
* 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 1.70 2005/11/27 15:31:06 kls Exp $
*/
#include "interface.h"
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include "i18n.h"
#include "status.h"
cInterface *Interface = NULL;
cInterface::cInterface(int SVDRPport)
{
interrupted = false;
SVDRP = NULL;
if (SVDRPport)
SVDRP = new cSVDRP(SVDRPport);
}
cInterface::~cInterface()
{
delete SVDRP;
}
eKeys cInterface::GetKey(bool Wait)
{
if (!cRemote::HasKeys())
Skins.Flush();
if (SVDRP) {
if (SVDRP->Process())
Wait = false;
}
return cRemote::Get(Wait ? 1000 : 10);
}
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))
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();
sleep(3);
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) {
char *Prompt;
asprintf(&Prompt, tr("Press key for '%s'"), tr(cKey::ToString(NewKey)));
DisplayMenu->SetItem(Prompt, 4, false, false);
free(Prompt);
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) {
cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu();
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;
}
}
}
}
}