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
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.

6
MANUAL
View File

@ -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

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
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"?

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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

37
eit.c
View File

@ -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");

7
eit.h
View File

@ -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;

5
i18n.c
View File

@ -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",

3
menu.c
View File

@ -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)

View File

@ -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();
}
}

View File

@ -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;

10
vdr.c
View File

@ -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;