summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2000-11-18 13:57:32 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2000-11-18 13:57:32 +0100
commit6439a8e169167e116efd9630564b5629efcd657b (patch)
tree93cfaaccc5fcad64a4e9f0d63ef8094f347f6274
parent5e272f90653736e6bc115660fa39cbe6d2ab0403 (diff)
downloadvdr-6439a8e169167e116efd9630564b5629efcd657b.tar.gz
vdr-6439a8e169167e116efd9630564b5629efcd657b.tar.bz2
All cards write EIT info into the same data structure; free cards scan for EIT info
-rw-r--r--HISTORY14
-rw-r--r--MANUAL6
-rw-r--r--README11
-rw-r--r--config.c12
-rw-r--r--config.h5
-rw-r--r--dvbapi.c57
-rw-r--r--dvbapi.h21
-rw-r--r--eit.c37
-rw-r--r--eit.h7
-rw-r--r--i18n.c5
-rw-r--r--menu.c3
-rw-r--r--thread.c8
-rw-r--r--thread.h14
-rw-r--r--vdr.c10
14 files changed, 169 insertions, 41 deletions
diff --git a/HISTORY b/HISTORY
index f1d5bad6..1d2d1cb5 100644
--- a/HISTORY
+++ b/HISTORY
@@ -266,7 +266,7 @@ Video Disk Recorder Revision History
are programmed via the "Schedules" menu) are now replaced by suitable
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.
- 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).
- The "Yellow" button in the "What's on now/next?" menus now displays the
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.
diff --git a/MANUAL b/MANUAL
index 4de0af22..490b689d 100644
--- a/MANUAL
+++ b/MANUAL
@@ -272,10 +272,16 @@ Video Disk Recorder User's Manual
1 = system time wil be set
Note that this works only if VDR is running under a user
id that has permisson to set the system time.
+
MarginStart = 2 Defines how many minutes before the official start time
MarginStop = 10 of a broadcast VDR shall start recording, and how long
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
The "Main" menu option "Commands" allows you to execute any system commands
diff --git a/README b/README
index cfc10a76..b1e071ee 100644
--- a/README
+++ b/README
@@ -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
-menu for a video disk recorder based on the DVB driver
-of the LinuxTV project (http://linuxtv.org).
+These files contain the source code of the "Video Disk Recorder",
+which is based on the DVB driver of the LinuxTV project (http://linuxtv.org).
For details about the "Video Disk Recorder" project please
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
this program on your computer.
+The MANUAL file describes how to operate the VDR.
+
The author can be contacted at kls@cadsoft.de.
Yet another "set-top-box"?
diff --git a/config.c b/config.c
index f7344169..8964e5a0 100644
--- a/config.c
+++ b/config.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@@ -257,12 +257,14 @@ bool cChannel::Save(FILE *f)
return fprintf(f, ToText()) > 0;
}
-bool cChannel::Switch(cDvbApi *DvbApi)
+bool cChannel::Switch(cDvbApi *DvbApi, bool Log)
{
if (!DvbApi)
DvbApi = cDvbApi::PrimaryDvbApi;
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--;) {
if (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid, ca, pnr))
return true;
@@ -720,6 +722,7 @@ cSetup::cSetup(void)
SetSystemTime = 0;
MarginStart = 2;
MarginStop = 10;
+ EPGScanTimeout = 5;
}
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, "MarginStart")) MarginStart = atoi(Value);
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
+ else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
else
return false;
return true;
@@ -788,7 +792,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
fprintf(f, "MarginStart = %d\n", MarginStart);
- fprintf(f, "MarginStop = %d\n", MarginStop);
+ fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fclose(f);
isyslog(LOG_INFO, "saved setup to %s", FileName);
return true;
diff --git a/config.h b/config.h
index dd6b5f88..db3f1edc 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@@ -92,7 +92,7 @@ public:
const char *ToText(void);
bool Parse(const char *s);
bool Save(FILE *f);
- bool Switch(cDvbApi *DvbApi = NULL);
+ bool Switch(cDvbApi *DvbApi = NULL, bool Log = true);
};
#define DEFAULTPRIORITY 99
@@ -257,6 +257,7 @@ public:
int LnbFrequHi;
int SetSystemTime;
int MarginStart, MarginStop;
+ int EPGScanTimeout;
cSetup(void);
bool Load(const char *FileName);
bool Save(const char *FileName = NULL);
diff --git a/dvbapi.c b/dvbapi.c
index 886348d7..dda8ae98 100644
--- a/dvbapi.c
+++ b/dvbapi.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@@ -1143,6 +1143,7 @@ cDvbApi::~cDvbApi()
Stop();
StopRecord();
OvlO(false); //Overlay off!
+ //XXX the following call sometimes causes a segfault - driver problem?
close(videoDev);
}
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
@@ -1727,7 +1728,7 @@ bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization,
front.AFC = 1;
ioctl(videoDev, VIDIOCSFRONTEND, &front);
if (front.sync & 0x1F == 0x1F) {
- if (siProcessor)
+ if (this == PrimaryDvbApi && siProcessor)
siProcessor->SetCurrentServiceID(Pnr);
currentChannel = ChannelNumber;
return true;
@@ -2107,3 +2108,55 @@ bool cDvbApi::GetIndex(int *Current, int *Total)
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);
+ }
+ }
+}
+
diff --git a/dvbapi.h b/dvbapi.h
index 7e237379..1f5e1a7d 100644
--- a/dvbapi.h
+++ b/dvbapi.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@@ -45,7 +45,6 @@ public:
class cDvbApi {
private:
int videoDev;
- cSIProcessor *siProcessor;
cDvbApi(const char *VideoFileName, const char *VbiFileName);
public:
~cDvbApi();
@@ -79,6 +78,9 @@ public:
// EIT facilities
+private:
+ cSIProcessor *siProcessor;
+public:
const cSchedules *Schedules(cThreadLock *ThreadLock) const;
// Caller must provide a cThreadLock which has to survive the entire
// time the returned cSchedules is accessed. Once the cSchedules is no
@@ -147,6 +149,7 @@ private:
public:
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; }
+ int Channel(void) { return currentChannel; }
// Record/Replay facilities
@@ -212,4 +215,18 @@ public:
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
diff --git a/eit.c b/eit.c
index edc3d7b8..79855282 100644
--- a/eit.c
+++ b/eit.c
@@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (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"
@@ -1056,15 +1056,20 @@ bool cEIT::WriteExtEventDescriptor(unsigned short service, eit_loop_t *eitloop,
#define MAX_FILTERS 20
+int cSIProcessor::numSIProcessors = 0;
+cSchedules *cSIProcessor::schedules = NULL;
+cMutex cSIProcessor::schedulesMutex;
+
/** */
cSIProcessor::cSIProcessor(const char *FileName)
{
+ masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
useTStime = false;
filters = NULL;
- schedules = NULL;
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));
}
else
@@ -1078,7 +1083,8 @@ cSIProcessor::~cSIProcessor()
Stop();
ShutDownFilters();
delete filters;
- delete schedules;
+ if (!--numSIProcessors) // the last one deletes it
+ delete schedules;
close(fsvbi);
}
}
@@ -1093,7 +1099,7 @@ void cSIProcessor::Action()
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 int seclen;
@@ -1103,15 +1109,20 @@ void cSIProcessor::Action()
while(true)
{
- time_t now = time(NULL);
- struct tm *ptm = localtime(&now);
- if (now - lastCleanup > 3600 && ptm->tm_hour == 5)
+ if (masterSIProcessor)
{
- 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");
- schedules->Cleanup();
- lastCleanup = now;
+ schedulesMutex.Lock();
+ isyslog(LOG_INFO, "cleaning up schedules data");
+ schedules->Cleanup();
+ schedulesMutex.Unlock();
+ lastCleanup = now;
+ }
}
/* wait data become ready from the bitfilter */
@@ -1150,8 +1161,10 @@ void cSIProcessor::Action()
{
LOCK_THREAD;
+ schedulesMutex.Lock();
cEIT ceit(buf, seclen, schedules);
ceit.ProcessEIT();
+ schedulesMutex.Unlock();
}
else
dsyslog(LOG_INFO, "Received stuffing section in EIT\n");
diff --git a/eit.h b/eit.h
index fec498ba..d5c4ebdc 100644
--- a/eit.h
+++ b/eit.h
@@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (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
@@ -120,7 +120,10 @@ typedef struct sip_filter {
class cSIProcessor : public cThread {
private:
- cSchedules *schedules;
+ static int numSIProcessors;
+ static cSchedules *schedules;
+ static cMutex schedulesMutex;
+ bool masterSIProcessor;
bool useTStime;
SIP_FILTER *filters;
int fsvbi;
diff --git a/i18n.c b/i18n.c
index 94009cb1..94002302 100644
--- a/i18n.c
+++ b/i18n.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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",
"Zeitpuffer bei Ende",
},
+ { "EPGScanTimeout",
+ "Zeit bis EPG Scan",
+ },
// The days of the week:
{ "MTWTFSS",
"MDMDFSS",
diff --git a/menu.c b/menu.c
index 08350ea3..3d4b241e 100644
--- a/menu.c
+++ b/menu.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@@ -1527,6 +1527,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditBoolItem(tr("SetSystemTime"), &data.SetSystemTime));
Add(new cMenuEditIntItem( tr("MarginStart"), &data.MarginStart));
Add(new cMenuEditIntItem( tr("MarginStop"), &data.MarginStop));
+ Add(new cMenuEditIntItem( tr("EPGScanTimeout"), &data.EPGScanTimeout));
}
eOSState cMenuSetup::ProcessKey(eKeys Key)
diff --git a/thread.c b/thread.c
index b124581f..67b5ab96 100644
--- a/thread.c
+++ b/thread.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@@ -24,7 +24,6 @@ cThread::cThread(void)
signal(SIGIO, SignalHandler);
signalHandlerInstalled = true;
}
- pthread_mutex_init(&mutex, NULL);
running = false;
parentPid = lockingPid = 0;
locked = 0;
@@ -32,7 +31,6 @@ cThread::cThread(void)
cThread::~cThread()
{
- pthread_mutex_destroy(&mutex);
}
void cThread::SignalHandler(int signum)
@@ -64,7 +62,7 @@ void cThread::Stop(void)
bool cThread::Lock(void)
{
if (!lockingPid || lockingPid != getpid()) {
- pthread_mutex_lock(&mutex);
+ Mutex.Lock();
lockingPid = getpid();
}
locked++;
@@ -75,7 +73,7 @@ void cThread::Unlock(void)
{
if (!--locked) {
lockingPid = 0;
- pthread_mutex_unlock(&mutex);
+ Mutex.Unlock();
}
}
diff --git a/thread.h b/thread.h
index b47f6d71..c85c51e2 100644
--- a/thread.h
+++ b/thread.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@@ -13,11 +13,21 @@
#include <pthread.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 {
friend class cThreadLock;
private:
pthread_t thread;
- pthread_mutex_t mutex;
+ cMutex Mutex;
pid_t parentPid, lockingPid;
int locked;
bool running;
diff --git a/vdr.c b/vdr.c
index 060a9d00..8a842003 100644
--- a/vdr.c
+++ b/vdr.c
@@ -22,7 +22,7 @@
*
* 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>
@@ -181,6 +181,8 @@ int main(int argc, char *argv[])
Channels.SwitchTo(1);
+ cEITScanner EITScanner;
+
// User interface:
Interface = new cInterface(SVDRPport);
@@ -205,7 +207,7 @@ int main(int argc, char *argv[])
while (!Interrupted) {
// Channel display:
- if (cDvbApi::CurrentChannel() != LastChannel) {
+ if (!EITScanner.Active() && cDvbApi::CurrentChannel() != LastChannel) {
if (!Menu)
Menu = new cDisplayChannel(cDvbApi::CurrentChannel(), LastChannel > 0);
PreviousChannel = LastChannel;
@@ -224,6 +226,8 @@ int main(int argc, char *argv[])
// User Input:
cOsdBase **Interact = Menu ? &Menu : (cOsdBase **)&ReplayControl;
eKeys key = Interface->GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
+ if (NORMALKEY(key) != kNone)
+ EITScanner.Activity();
if (*Interact) {
switch ((*Interact)->ProcessKey(key)) {
case osMenu: DELETENULL(Menu);
@@ -302,6 +306,8 @@ int main(int argc, char *argv[])
default: break;
}
}
+ if (!Menu)
+ EITScanner.Process();
}
isyslog(LOG_INFO, "caught signal %d", Interrupted);
delete Menu;