All cards write EIT info into the same data structure; free cards scan for EIT info

This commit is contained in:
Klaus Schmidinger 2000-11-18 13:57:32 +01:00
parent 5e272f9065
commit 6439a8e169
14 changed files with 169 additions and 41 deletions

14
HISTORY
View File

@ -266,7 +266,7 @@ Video Disk Recorder Revision History
are programmed via the "Schedules" menu) are now replaced by suitable are programmed via the "Schedules" menu) are now replaced by suitable
substitutes. substitutes.
2000-11-12: Version 0.68 2000-11-18: Version 0.68
- Date and time in the title of an event info page are now always right adjusted. - Date and time in the title of an event info page are now always right adjusted.
- The 'current channel' is now handled device specific (in case there is more - The 'current channel' is now handled device specific (in case there is more
@ -289,3 +289,15 @@ Video Disk Recorder Revision History
CAM module (and thus can continue recording on a different DVB card). CAM module (and thus can continue recording on a different DVB card).
- The "Yellow" button in the "What's on now/next?" menus now displays the - The "Yellow" button in the "What's on now/next?" menus now displays the
schedule of the current channel from that menu. schedule of the current channel from that menu.
- All DVB cards in a multi-card system now write their EIT information into the
same data structure.
- If there is more than one DVB card in the system, the non-primary cards are
now used to periodically scan through the channels in order to keep the
EPG info up-to-date. Scanning kicks in after 60 seconds of user inactivity
(timeout in order to keep user interactions instantaneously) and each channel
that has the 'pnr' parameter defined in 'channels.conf' is switched to for
20 seconds. If there is only one DVB card in the system, that card will start
scanning after 5 hours (configurable through the "Setup" menu) of user inactivity
and will switch back to the channel it originally displayed at the first sign of
user activity. Any scanning will only occur if that particular card is not
currently recording or replaying.

6
MANUAL
View File

@ -272,10 +272,16 @@ Video Disk Recorder User's Manual
1 = system time wil be set 1 = system time wil be set
Note that this works only if VDR is running under a user Note that this works only if VDR is running under a user
id that has permisson to set the system time. id that has permisson to set the system time.
MarginStart = 2 Defines how many minutes before the official start time MarginStart = 2 Defines how many minutes before the official start time
MarginStop = 10 of a broadcast VDR shall start recording, and how long MarginStop = 10 of a broadcast VDR shall start recording, and how long
after the official end time it shall stop recording. after the official end time it shall stop recording.
EPGScanTimeout = 5 The time (in hours) of user inactivity after which the
DVB card in a single card system starts scanning channels
to keep the EPG up-to-date.
A value of '0' turns off scanning on a single card system.
* Executing system commands * Executing system commands
The "Main" menu option "Commands" allows you to execute any system commands The "Main" menu option "Commands" allows you to execute any system commands

11
README
View File

@ -1,9 +1,8 @@
On Screen Menu for the Video Disk Recorder Video Disk Recorder ('VDR')
------------------------------------------ ---------------------------
These files contain the source code of an on screen These files contain the source code of the "Video Disk Recorder",
menu for a video disk recorder based on the DVB driver which is based on the DVB driver of the LinuxTV project (http://linuxtv.org).
of the LinuxTV project (http://linuxtv.org).
For details about the "Video Disk Recorder" project please For details about the "Video Disk Recorder" project please
refer to http://www.cadsoft.de/people/kls/vdr. refer to http://www.cadsoft.de/people/kls/vdr.
@ -13,6 +12,8 @@ Web pages, which can be used within this program.
Please see the INSTALL file for details on how to install Please see the INSTALL file for details on how to install
this program on your computer. this program on your computer.
The MANUAL file describes how to operate the VDR.
The author can be contacted at kls@cadsoft.de. The author can be contacted at kls@cadsoft.de.
Yet another "set-top-box"? Yet another "set-top-box"?

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.c 1.33 2000/11/12 12:22:40 kls Exp $ * $Id: config.c 1.34 2000/11/18 13:26:36 kls Exp $
*/ */
#include "config.h" #include "config.h"
@ -257,12 +257,14 @@ bool cChannel::Save(FILE *f)
return fprintf(f, ToText()) > 0; return fprintf(f, ToText()) > 0;
} }
bool cChannel::Switch(cDvbApi *DvbApi) bool cChannel::Switch(cDvbApi *DvbApi, bool Log)
{ {
if (!DvbApi) if (!DvbApi)
DvbApi = cDvbApi::PrimaryDvbApi; DvbApi = cDvbApi::PrimaryDvbApi;
if (!DvbApi->Recording() && !groupSep) { if (!DvbApi->Recording() && !groupSep) {
isyslog(LOG_INFO, "switching to channel %d", number); if (Log) {
isyslog(LOG_INFO, "switching to channel %d", number);
}
for (int i = 3; i--;) { for (int i = 3; i--;) {
if (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid, ca, pnr)) if (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid, ca, pnr))
return true; return true;
@ -720,6 +722,7 @@ cSetup::cSetup(void)
SetSystemTime = 0; SetSystemTime = 0;
MarginStart = 2; MarginStart = 2;
MarginStop = 10; MarginStop = 10;
EPGScanTimeout = 5;
} }
bool cSetup::Parse(char *s) bool cSetup::Parse(char *s)
@ -738,6 +741,7 @@ bool cSetup::Parse(char *s)
else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value); else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value); else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value); else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
else else
return false; return false;
return true; return true;
@ -788,7 +792,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi); fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
fprintf(f, "SetSystemTime = %d\n", SetSystemTime); fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
fprintf(f, "MarginStart = %d\n", MarginStart); fprintf(f, "MarginStart = %d\n", MarginStart);
fprintf(f, "MarginStop = %d\n", MarginStop); fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fclose(f); fclose(f);
isyslog(LOG_INFO, "saved setup to %s", FileName); isyslog(LOG_INFO, "saved setup to %s", FileName);
return true; return true;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.h 1.33 2000/11/12 12:22:24 kls Exp $ * $Id: config.h 1.34 2000/11/18 13:25:53 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -92,7 +92,7 @@ public:
const char *ToText(void); const char *ToText(void);
bool Parse(const char *s); bool Parse(const char *s);
bool Save(FILE *f); bool Save(FILE *f);
bool Switch(cDvbApi *DvbApi = NULL); bool Switch(cDvbApi *DvbApi = NULL, bool Log = true);
}; };
#define DEFAULTPRIORITY 99 #define DEFAULTPRIORITY 99
@ -257,6 +257,7 @@ public:
int LnbFrequHi; int LnbFrequHi;
int SetSystemTime; int SetSystemTime;
int MarginStart, MarginStop; int MarginStart, MarginStop;
int EPGScanTimeout;
cSetup(void); cSetup(void);
bool Load(const char *FileName); bool Load(const char *FileName);
bool Save(const char *FileName = NULL); bool Save(const char *FileName = NULL);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.c 1.37 2000/11/12 12:59:50 kls Exp $ * $Id: dvbapi.c 1.38 2000/11/18 13:46:46 kls Exp $
*/ */
#include "dvbapi.h" #include "dvbapi.h"
@ -1143,6 +1143,7 @@ cDvbApi::~cDvbApi()
Stop(); Stop();
StopRecord(); StopRecord();
OvlO(false); //Overlay off! OvlO(false); //Overlay off!
//XXX the following call sometimes causes a segfault - driver problem?
close(videoDev); close(videoDev);
} }
#if defined(DEBUG_OSD) || defined(REMOTE_KBD) #if defined(DEBUG_OSD) || defined(REMOTE_KBD)
@ -1727,7 +1728,7 @@ bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization,
front.AFC = 1; front.AFC = 1;
ioctl(videoDev, VIDIOCSFRONTEND, &front); ioctl(videoDev, VIDIOCSFRONTEND, &front);
if (front.sync & 0x1F == 0x1F) { if (front.sync & 0x1F == 0x1F) {
if (siProcessor) if (this == PrimaryDvbApi && siProcessor)
siProcessor->SetCurrentServiceID(Pnr); siProcessor->SetCurrentServiceID(Pnr);
currentChannel = ChannelNumber; currentChannel = ChannelNumber;
return true; return true;
@ -2107,3 +2108,55 @@ bool cDvbApi::GetIndex(int *Current, int *Total)
return false; return false;
} }
// --- cEITScanner -----------------------------------------------------------
cEITScanner::cEITScanner(void)
{
lastScan = lastActivity = time(NULL);
currentChannel = 0;
lastChannel = 1;
}
void cEITScanner::Activity(void)
{
if (currentChannel) {
Channels.SwitchTo(currentChannel);
currentChannel = 0;
}
lastActivity = time(NULL);
}
void cEITScanner::Process(void)
{
if (Channels.MaxNumber() > 1) {
time_t now = time(NULL);
if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) {
for (int i = 0; i < cDvbApi::NumDvbApis; i++) {
cDvbApi *DvbApi = cDvbApi::GetDvbApi(i, 0);
if (DvbApi) {
if (DvbApi != cDvbApi::PrimaryDvbApi || (cDvbApi::NumDvbApis == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) {
if (!(DvbApi->Recording() || DvbApi->Replaying())) {
int oldCh = lastChannel;
int ch = oldCh + 1;
while (ch != oldCh) {
if (ch > Channels.MaxNumber())
ch = 1;
cChannel *Channel = Channels.GetByNumber(ch);
if (Channel && Channel->pnr) {
if (DvbApi == cDvbApi::PrimaryDvbApi && !currentChannel)
currentChannel = DvbApi->Channel();
Channel->Switch(DvbApi, false);
lastChannel = ch;
break;
}
ch++;
}
}
}
}
}
lastScan = time(NULL);
}
}
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.h 1.23 2000/11/12 12:52:41 kls Exp $ * $Id: dvbapi.h 1.24 2000/11/18 13:46:10 kls Exp $
*/ */
#ifndef __DVBAPI_H #ifndef __DVBAPI_H
@ -45,7 +45,6 @@ public:
class cDvbApi { class cDvbApi {
private: private:
int videoDev; int videoDev;
cSIProcessor *siProcessor;
cDvbApi(const char *VideoFileName, const char *VbiFileName); cDvbApi(const char *VideoFileName, const char *VbiFileName);
public: public:
~cDvbApi(); ~cDvbApi();
@ -79,6 +78,9 @@ public:
// EIT facilities // EIT facilities
private:
cSIProcessor *siProcessor;
public:
const cSchedules *Schedules(cThreadLock *ThreadLock) const; const cSchedules *Schedules(cThreadLock *ThreadLock) const;
// Caller must provide a cThreadLock which has to survive the entire // Caller must provide a cThreadLock which has to survive the entire
// time the returned cSchedules is accessed. Once the cSchedules is no // time the returned cSchedules is accessed. Once the cSchedules is no
@ -147,6 +149,7 @@ private:
public: public:
bool SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Ca, int Pnr); bool SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Ca, int Pnr);
static int CurrentChannel(void) { return PrimaryDvbApi ? PrimaryDvbApi->currentChannel : 0; } static int CurrentChannel(void) { return PrimaryDvbApi ? PrimaryDvbApi->currentChannel : 0; }
int Channel(void) { return currentChannel; }
// Record/Replay facilities // Record/Replay facilities
@ -212,4 +215,18 @@ public:
bool GetIndex(int *Current, int *Total = NULL); bool GetIndex(int *Current, int *Total = NULL);
}; };
class cEITScanner {
private:
enum { ActivityTimeout = 60,
ScanTimeout = 20
};
time_t lastScan, lastActivity;
int currentChannel, lastChannel;
public:
cEITScanner(void);
bool Active(void) { return currentChannel; }
void Activity(void);
void Process(void);
};
#endif //__DVBAPI_H #endif //__DVBAPI_H

37
eit.c
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: eit.c 1.8 2000/11/02 19:19:06 kls Exp $ * $Id: eit.c 1.9 2000/11/18 13:42:28 kls Exp $
***************************************************************************/ ***************************************************************************/
#include "eit.h" #include "eit.h"
@ -1056,15 +1056,20 @@ bool cEIT::WriteExtEventDescriptor(unsigned short service, eit_loop_t *eitloop,
#define MAX_FILTERS 20 #define MAX_FILTERS 20
int cSIProcessor::numSIProcessors = 0;
cSchedules *cSIProcessor::schedules = NULL;
cMutex cSIProcessor::schedulesMutex;
/** */ /** */
cSIProcessor::cSIProcessor(const char *FileName) cSIProcessor::cSIProcessor(const char *FileName)
{ {
masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
useTStime = false; useTStime = false;
filters = NULL; filters = NULL;
schedules = NULL;
if ((fsvbi = open(FileName, O_RDONLY)) >= 0) if ((fsvbi = open(FileName, O_RDONLY)) >= 0)
{ {
schedules = new cSchedules; if (!numSIProcessors++) // the first one creates it
schedules = new cSchedules;
filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER)); filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
} }
else else
@ -1078,7 +1083,8 @@ cSIProcessor::~cSIProcessor()
Stop(); Stop();
ShutDownFilters(); ShutDownFilters();
delete filters; delete filters;
delete schedules; if (!--numSIProcessors) // the last one deletes it
delete schedules;
close(fsvbi); close(fsvbi);
} }
} }
@ -1093,7 +1099,7 @@ void cSIProcessor::Action()
return; return;
} }
dsyslog(LOG_INFO, "EIT processing thread started (pid=%d)", getpid()); dsyslog(LOG_INFO, "EIT processing thread started (pid=%d)%s", getpid(), masterSIProcessor ? " - master" : "");
unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-) unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-)
unsigned int seclen; unsigned int seclen;
@ -1103,15 +1109,20 @@ void cSIProcessor::Action()
while(true) while(true)
{ {
time_t now = time(NULL); if (masterSIProcessor)
struct tm *ptm = localtime(&now);
if (now - lastCleanup > 3600 && ptm->tm_hour == 5)
{ {
LOCK_THREAD; time_t now = time(NULL);
struct tm *ptm = localtime(&now);
if (now - lastCleanup > 3600 && ptm->tm_hour == 5)
{
LOCK_THREAD;
isyslog(LOG_INFO, "Now cleaning up things"); schedulesMutex.Lock();
schedules->Cleanup(); isyslog(LOG_INFO, "cleaning up schedules data");
lastCleanup = now; schedules->Cleanup();
schedulesMutex.Unlock();
lastCleanup = now;
}
} }
/* wait data become ready from the bitfilter */ /* wait data become ready from the bitfilter */
@ -1150,8 +1161,10 @@ void cSIProcessor::Action()
{ {
LOCK_THREAD; LOCK_THREAD;
schedulesMutex.Lock();
cEIT ceit(buf, seclen, schedules); cEIT ceit(buf, seclen, schedules);
ceit.ProcessEIT(); ceit.ProcessEIT();
schedulesMutex.Unlock();
} }
else else
dsyslog(LOG_INFO, "Received stuffing section in EIT\n"); dsyslog(LOG_INFO, "Received stuffing section in EIT\n");

7
eit.h
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: eit.h 1.2 2000/10/29 10:21:56 kls Exp $ * $Id: eit.h 1.3 2000/11/17 16:14:27 kls Exp $
***************************************************************************/ ***************************************************************************/
#ifndef __EIT_H #ifndef __EIT_H
@ -120,7 +120,10 @@ typedef struct sip_filter {
class cSIProcessor : public cThread { class cSIProcessor : public cThread {
private: private:
cSchedules *schedules; static int numSIProcessors;
static cSchedules *schedules;
static cMutex schedulesMutex;
bool masterSIProcessor;
bool useTStime; bool useTStime;
SIP_FILTER *filters; SIP_FILTER *filters;
int fsvbi; int fsvbi;

5
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: i18n.c 1.2 2000/11/11 16:20:47 kls Exp $ * $Id: i18n.c 1.3 2000/11/18 13:28:19 kls Exp $
*/ */
/* /*
@ -250,6 +250,9 @@ const tPhrase Phrases[] = {
{ "MarginStop", { "MarginStop",
"Zeitpuffer bei Ende", "Zeitpuffer bei Ende",
}, },
{ "EPGScanTimeout",
"Zeit bis EPG Scan",
},
// The days of the week: // The days of the week:
{ "MTWTFSS", { "MTWTFSS",
"MDMDFSS", "MDMDFSS",

3
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.48 2000/11/12 16:46:19 kls Exp $ * $Id: menu.c 1.49 2000/11/18 13:42:52 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -1527,6 +1527,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditBoolItem(tr("SetSystemTime"), &data.SetSystemTime)); Add(new cMenuEditBoolItem(tr("SetSystemTime"), &data.SetSystemTime));
Add(new cMenuEditIntItem( tr("MarginStart"), &data.MarginStart)); Add(new cMenuEditIntItem( tr("MarginStart"), &data.MarginStart));
Add(new cMenuEditIntItem( tr("MarginStop"), &data.MarginStop)); Add(new cMenuEditIntItem( tr("MarginStop"), &data.MarginStop));
Add(new cMenuEditIntItem( tr("EPGScanTimeout"), &data.EPGScanTimeout));
} }
eOSState cMenuSetup::ProcessKey(eKeys Key) eOSState cMenuSetup::ProcessKey(eKeys Key)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.c 1.3 2000/10/28 15:26:02 kls Exp $ * $Id: thread.c 1.4 2000/11/14 18:38:25 kls Exp $
*/ */
#include "thread.h" #include "thread.h"
@ -24,7 +24,6 @@ cThread::cThread(void)
signal(SIGIO, SignalHandler); signal(SIGIO, SignalHandler);
signalHandlerInstalled = true; signalHandlerInstalled = true;
} }
pthread_mutex_init(&mutex, NULL);
running = false; running = false;
parentPid = lockingPid = 0; parentPid = lockingPid = 0;
locked = 0; locked = 0;
@ -32,7 +31,6 @@ cThread::cThread(void)
cThread::~cThread() cThread::~cThread()
{ {
pthread_mutex_destroy(&mutex);
} }
void cThread::SignalHandler(int signum) void cThread::SignalHandler(int signum)
@ -64,7 +62,7 @@ void cThread::Stop(void)
bool cThread::Lock(void) bool cThread::Lock(void)
{ {
if (!lockingPid || lockingPid != getpid()) { if (!lockingPid || lockingPid != getpid()) {
pthread_mutex_lock(&mutex); Mutex.Lock();
lockingPid = getpid(); lockingPid = getpid();
} }
locked++; locked++;
@ -75,7 +73,7 @@ void cThread::Unlock(void)
{ {
if (!--locked) { if (!--locked) {
lockingPid = 0; lockingPid = 0;
pthread_mutex_unlock(&mutex); Mutex.Unlock();
} }
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.h 1.2 2000/10/28 15:08:09 kls Exp $ * $Id: thread.h 1.3 2000/11/14 18:38:11 kls Exp $
*/ */
#ifndef __THREAD_H #ifndef __THREAD_H
@ -13,11 +13,21 @@
#include <pthread.h> #include <pthread.h>
#include <sys/types.h> #include <sys/types.h>
class cMutex {
private:
pthread_mutex_t mutex;
public:
cMutex(void) { pthread_mutex_init(&mutex, NULL); }
~cMutex() { pthread_mutex_destroy(&mutex); }
void Lock(void) { pthread_mutex_lock(&mutex); }
void Unlock(void) { pthread_mutex_unlock(&mutex); }
};
class cThread { class cThread {
friend class cThreadLock; friend class cThreadLock;
private: private:
pthread_t thread; pthread_t thread;
pthread_mutex_t mutex; cMutex Mutex;
pid_t parentPid, lockingPid; pid_t parentPid, lockingPid;
int locked; int locked;
bool running; bool running;

10
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/people/kls/vdr * The project's page is at http://www.cadsoft.de/people/kls/vdr
* *
* $Id: vdr.c 1.45 2000/11/11 14:40:11 kls Exp $ * $Id: vdr.c 1.46 2000/11/18 13:46:56 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -181,6 +181,8 @@ int main(int argc, char *argv[])
Channels.SwitchTo(1); Channels.SwitchTo(1);
cEITScanner EITScanner;
// User interface: // User interface:
Interface = new cInterface(SVDRPport); Interface = new cInterface(SVDRPport);
@ -205,7 +207,7 @@ int main(int argc, char *argv[])
while (!Interrupted) { while (!Interrupted) {
// Channel display: // Channel display:
if (cDvbApi::CurrentChannel() != LastChannel) { if (!EITScanner.Active() && cDvbApi::CurrentChannel() != LastChannel) {
if (!Menu) if (!Menu)
Menu = new cDisplayChannel(cDvbApi::CurrentChannel(), LastChannel > 0); Menu = new cDisplayChannel(cDvbApi::CurrentChannel(), LastChannel > 0);
PreviousChannel = LastChannel; PreviousChannel = LastChannel;
@ -224,6 +226,8 @@ int main(int argc, char *argv[])
// User Input: // User Input:
cOsdBase **Interact = Menu ? &Menu : (cOsdBase **)&ReplayControl; cOsdBase **Interact = Menu ? &Menu : (cOsdBase **)&ReplayControl;
eKeys key = Interface->GetKey(!*Interact || !(*Interact)->NeedsFastResponse()); eKeys key = Interface->GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
if (NORMALKEY(key) != kNone)
EITScanner.Activity();
if (*Interact) { if (*Interact) {
switch ((*Interact)->ProcessKey(key)) { switch ((*Interact)->ProcessKey(key)) {
case osMenu: DELETENULL(Menu); case osMenu: DELETENULL(Menu);
@ -302,6 +306,8 @@ int main(int argc, char *argv[])
default: break; default: break;
} }
} }
if (!Menu)
EITScanner.Process();
} }
isyslog(LOG_INFO, "caught signal %d", Interrupted); isyslog(LOG_INFO, "caught signal %d", Interrupted);
delete Menu; delete Menu;