Added EIT support for current/next display

This commit is contained in:
Klaus Schmidinger 2000-09-03 11:40:00 +02:00
parent 97ada9e025
commit d4eb96f725
10 changed files with 683 additions and 14 deletions

View File

@ -16,3 +16,6 @@ Heino Goldenstein <heino.goldenstein@microplex.de>
Guido Fiala <gfiala@s.netic.de>
for implementing slow forward/back
Robert Schneider <Robert.Schneider@lotus.com>
for implementing EIT support for displaying the current/next info

15
HISTORY
View File

@ -123,3 +123,18 @@ Video Disk Recorder Revision History
doesn't yet exist).
- New version of the 'epg2timers' tool (with a modified channel list).
- Bugfix in closing window in DEBUG_OSD mode.
2000-09-03: Version 0.62
- The Makefile now defines DVBDIR to easily point to where the DVB driver
source is located.
- When switching channels the current/next information is now displayed if
available (thanks to Robert Schneider). Since there is now more information
to read when switching channels, the timeout for displaying it has been
increased from 2 to 5 seconds (remember that this info can always be recalled
by pressing the "Ok" button).
For this feature to work it is necessary that the 'Pnr' parameter in the
channel setup ('channels.conf') is set to the proper value. This has been
done for some of the channels in the default 'channels.conf'. Some other
parameters in the default 'channels.conf' have also been updated, so please
make sure your timers still use the correct channels!

View File

@ -11,6 +11,9 @@ http://linuxtv.org/dvb/siemens_dvb.html for more information
about that driver). For example, if the DVB driver was
extracted into the directory /home/kls/vdr/DVB, then this
package should be extracted into /home/kls/vdr/VDR.
If you have the DVB driver source in a different location
you will have to change the definition of DVBDIR in the
Makefile.
This program requires the card driver version 0.05 or higher
to work properly.

View File

@ -4,9 +4,12 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 1.6 2000/07/28 14:37:44 kls Exp $
# $Id: Makefile 1.7 2000/09/03 09:26:24 kls Exp $
OBJS = config.o dvbapi.o interface.o menu.o osd.o recording.o remote.o svdrp.o tools.o vdr.o videodir.o
DVBDIR = ../DVB
INCLUDES = -I$(DVBDIR)/driver
OBJS = config.o dvbapi.o eit.o interface.o menu.o osd.o recording.o remote.o svdrp.o tools.o vdr.o videodir.o
ifndef REMOTE
REMOTE = KBD
@ -19,13 +22,14 @@ DEFINES += -DDEBUG_OSD
endif
%.o: %.c
g++ -g -O2 -Wall -c $(DEFINES) $<
g++ -g -O2 -Wall -c $(DEFINES) $(INCLUDES) $<
all: vdr
config.o : config.c config.h dvbapi.h interface.h tools.h
config.o : config.c config.h dvbapi.h eit.h interface.h tools.h
dvbapi.o : dvbapi.c config.h dvbapi.h interface.h tools.h videodir.h
interface.o: interface.c config.h dvbapi.h interface.h remote.h tools.h
eit.o : eit.c eit.h
interface.o: interface.c config.h dvbapi.h eit.h interface.h remote.h tools.h
menu.o : menu.c config.h dvbapi.h interface.h menu.h osd.h recording.h tools.h
osd.o : osd.c config.h dvbapi.h interface.h osd.h tools.h
vdr.o : vdr.c config.h dvbapi.h interface.h menu.h osd.h recording.h svdrp.h tools.h videodir.h

View File

@ -4,15 +4,18 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.17 2000/08/06 12:27:38 kls Exp $
* $Id: config.c 1.18 2000/09/03 09:20:22 kls Exp $
*/
#include "config.h"
#include <ctype.h>
#include <stdlib.h>
#include "dvbapi.h"
#include "eit.h"
#include "interface.h"
extern cEIT EIT;
// -- cKeys ------------------------------------------------------------------
tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
@ -231,8 +234,10 @@ bool cChannel::Switch(cDvbApi *DvbApi)
isyslog(LOG_INFO, "switching to channel %d", Index() + 1);
CurrentChannel = Index();
for (int i = 3; i--;) {
if (DvbApi->SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr))
if (DvbApi->SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr)) {
EIT.SetProgramNumber(pnr);
return true;
}
esyslog(LOG_ERR, "retrying");
}
return false;

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.14 2000/08/06 12:22:52 kls Exp $
* $Id: config.h 1.15 2000/09/03 09:37:30 kls Exp $
*/
#ifndef __CONFIG_H
@ -17,7 +17,7 @@
#include "dvbapi.h"
#include "tools.h"
#define VDRVERSION "0.61"
#define VDRVERSION "0.62"
#define MaxBuffer 10000

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.12 2000/07/30 15:01:01 kls Exp $
* $Id: dvbapi.h 1.13 2000/09/03 09:25:53 kls Exp $
*/
#ifndef __DVBAPI_H
@ -19,7 +19,7 @@ typedef unsigned char __u8;
#include <ncurses.h>
#endif
#include <stdio.h>
#include "../DVB/driver/dvb.h"
#include <dvb.h>
#define MenuLines 15
#define MenuColumns 40

530
eit.c Normal file
View File

@ -0,0 +1,530 @@
/***************************************************************************
eit.c - description
-------------------
begin : Fri Aug 25 2000
copyright : (C) 2000 by Robert Schneider
email : Robert.Schneider@web.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.1 2000/09/03 10:22:25 kls Exp $
***************************************************************************/
#include "eit.h"
#include <iostream.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <dvb_comcode.h>
#include "tools.h"
typedef struct {
u_char table_id : 8;
#if BYTE_ORDER == BIG_ENDIAN
u_char section_syntax_indicator : 1;
u_char : 3;
u_char section_length_hi : 4;
#else
u_char section_length_hi : 4;
u_char : 3;
u_char section_syntax_indicator : 1;
#endif
u_char section_length_lo : 8;
u_char service_id_hi : 8;
u_char service_id_lo : 8;
#if BYTE_ORDER == BIG_ENDIAN
u_char : 2;
u_char version_number : 5;
u_char current_next_indicator : 1;
#else
u_char current_next_indicator : 1;
u_char version_number : 5;
u_char : 2;
#endif
u_char section_number : 8;
u_char last_section_number : 8;
u_char transport_stream_id_hi : 8;
u_char transport_stream_id_lo : 8;
u_char original_network_id_hi : 8;
u_char original_network_id_lo : 8;
u_char segment_last_section_number : 8;
u_char segment_last_table_id : 8;
} eit_t;
#define EIT_SIZE 14
struct eit_loop_struct1 {
u_char event_id_hi : 8;
u_char event_id_lo : 8;
u_char date_hi : 8;
u_char date_lo : 8;
u_char time_hour : 4;
u_char time_hour_ten : 4;
u_char time_minute : 4;
u_char time_minute_ten : 4;
u_char time_second : 4;
u_char time_second_ten : 4;
u_char dur_hour_ten : 4;
u_char dur_hour : 4;
u_char dur_minute_ten : 4;
u_char dur_minute : 4;
u_char dur_second_ten : 4;
u_char dur_second : 4;
#if BYTE_ORDER == BIG_ENDIAN
u_char running_status : 3;
u_char free_ca_mode : 1;
u_char descriptors_loop_length_hi : 4;
#else
u_char descriptors_loop_length_hi : 4;
u_char free_ca_mode : 1;
u_char running_status : 3;
#endif
u_char descriptors_loop_length_lo : 8;
};
#define EIT_SHORT_EVENT_DESCRIPTOR 0x4d
#define EIT_SHORT_EVENT_DESCRIPTOR_SIZE 6
struct eit_short_event_descriptor_struct {
u_char descriptor_tag : 8;
u_char descriptor_length : 8;
u_char language_code_1 : 8;
u_char language_code_2 : 8;
u_char language_code_3 : 8;
u_char event_name_length : 8;
};
#define EIT_EXTENDED_EVENT_DESCRIPOR 0x4e
#define EIT_DESCRIPTOR_SIZE
typedef struct eit_event_struct {
u_char event_id_hi : 8;
u_char event_id_lo : 8;
u_char start_time_1 : 8;
u_char start_time_2 : 8;
u_char start_time_3 : 8;
u_char start_time_4 : 8;
u_char start_time_5 : 8;
u_char duration_1 : 8;
u_char duration_2 : 8;
u_char duration_3 : 8;
#if BYTE_ORDER == BIG_ENDIAN
u_char running_status : 3;
u_char free_CA_mode : 1;
u_char descriptors_loop_length_hi : 4;
#else
u_char descriptors_loop_length_hi : 4;
u_char free_CA_mode : 1;
u_char running_status : 3;
#endif
u_char descriptors_loop_length_lo : 8;
} eit_event_t;
#define EIT_LOOP_SIZE 12
typedef struct tot_t {
u_char table_id : 8;
#if BYTE_ORDER == BIG_ENDIAN
u_char section_syntax_indicator : 1;
u_char : 3;
u_char section_length_hi : 4;
#else
u_char section_length_hi : 4;
u_char : 3;
u_char section_syntax_indicator : 1;
#endif
u_char date_hi : 8;
u_char date_lo : 8;
u_char time_hour : 4;
u_char time_hour_ten : 4;
u_char time_minute : 4;
u_char time_minute_ten : 4;
u_char time_second : 4;
u_char time_second_ten : 4;
#if BYTE_ORDER == BIG_ENDIAN
u_char : 4;
u_char descriptor_loop_length_hi : 4;
#else
u_char descriptor_loop_length_hi : 4;
u_char : 4;
#endif
u_char descriptor_loop_length_lo : 8;
} tot_t;
typedef struct local_time_offset {
u_char descriptor_tag : 8;
u_char descriptor_length : 8;
u_char language_code_1 : 8;
u_char language_code_2 : 8;
u_char language_code_3 : 8;
u_char : 8;
u_char offset_hour : 4;
u_char offset_hour_ten : 4;
u_char offset_minute : 4;
u_char offset_minute_ten : 4;
u_char change_date_hi : 8;
u_char change_date_lo : 8;
u_char change_time_hour : 4;
u_char change_time_hour_ten : 4;
u_char change_time_minute : 4;
u_char change_time_minute_ten : 4;
u_char change_time_second : 4;
u_char change_time_second_ten : 4;
u_char next_offset_hour : 4;
u_char next_offset_hour_ten : 4;
u_char next_offset_minute : 4;
u_char next_offset_minute_ten : 4;
} local_time_offset;
cEIT::cEIT()
{
cszBitFilter = "/dev/vbi";
if((fsvbi = open(cszBitFilter, O_RDWR))<0)
{
fsvbi = 0;
esyslog(LOG_ERR, "Failed to open DVB bitfilter device: %s", cszBitFilter);
return;
}
}
cEIT::~cEIT()
{
if (fsvbi != 0)
close(fsvbi);
fsvbi = 0;
}
/** Set the bitfilter in vbi device to return
correct tables */
int cEIT::SetBitFilter(unsigned short pid, unsigned short section, unsigned short mode)
{
struct bitfilter filt = {
pid,
{ section, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
mode,0,
FILTER_MEM,
{},
};
if (ioctl(fsvbi, VIDIOCSBITFILTER, &filt) < 0)
return 0xffff;
return 0;
}
/** */
int cEIT::GetSection(unsigned char *buf, ushort PID, unsigned char sec)
{
int seclen=0;
unsigned short handle, pid;
unsigned char section, sectionnum=0xff, maxsec=0;
struct pollfd pfd;
if ((handle = SetBitFilter(PID, (sec<<8)|0x00ff, SECTION_CONTINUOS))==0xffff)
return -1;
seclen=0;
pfd.fd=fsvbi;
pfd.events=POLLIN;
if (poll(&pfd, 1, 20000)==0)
{
//cerr << "Timeout\n";
return -1;
}
read(fsvbi, buf, 8);
seclen=(buf[6]<<8)|buf[7];
pid=(buf[4]<<8)|buf[5];
read(fsvbi, buf, seclen);
section=buf[0];
sectionnum=buf[6];
maxsec=buf[7];
//cerr << "secnum: " << HEX(2) << (int)sectionnum
// << ", secmax: " << HEX(2) << (int) msecnum << "\n";
CloseFilter(handle);
return seclen;
}
/** */
int cEIT::CloseFilter(unsigned short handle)
{
if (ioctl(fsvbi, VIDIOCSSHUTDOWNFILTER, &handle)<0)
return -1;
return 0;
}
/** */
char * cEIT::mjd2string(unsigned short mjd)
{
int y, m, d, k;
static char buf[20];
y = (int) ((mjd - 15078.2) / 365.25);
m = (int) ((mjd - 14956.1 - (int)(y * 365.25)) / 30.6001);
d = (int) (mjd - 14956 - (int)(y * 365.25) - (int)(m * 30.6001));
k = (m == 14 || m == 15) ? 1 : 0;
y = y + k;
m = m - 1 - k * 12;
sprintf(buf, "%d.%d.%4d", d, m, y + 1900);
return(buf);
}
/** */
int cEIT::GetEIT()
{
unsigned char buf[1024];
eit_t *eit;
struct eit_loop_struct1 *eitloop;
struct eit_short_event_descriptor_struct *eitevt;
int seclen;
unsigned short handle, pid;
struct pollfd pfd;
eit_event * pevt = (eit_event *)0;
time_t tstart;
if ((handle = SetBitFilter(0x12, (0x4e << 8) | 0x00ff, SECTION_CONTINUOS))==0xffff)
{
return -1;
}
/*
pid_t process = fork();
if (process < 0)
{
cerr << "GetEIT -1" << endl;
return -1;
}
if (process != 0)
{
cerr << "GetEIT 0" << endl;
return 0;
}
*/
int nReceivedEITs = 0;
tstart = time(NULL);
while ((!evtRunning.bIsValid || !evtNext.bIsValid) && nReceivedEITs < 20 && difftime(time(NULL), tstart) < 4)
{
pfd.fd=fsvbi;
pfd.events=POLLIN;
if (poll(&pfd, 1, 5000)==0)
{
//cerr << "Timeout\n";
CloseFilter(handle);
return -1;
}
read(fsvbi, buf, 8);
seclen=(buf[6]<<8)|buf[7];
pid=(buf[4]<<8)|buf[5];
read(fsvbi, buf, seclen);
if (seclen < (int)(sizeof(eit_t)
+ sizeof(struct eit_loop_struct1)
+ sizeof(struct eit_short_event_descriptor_struct)))
continue;
eit = (eit_t *)buf;
eitloop = (struct eit_loop_struct1 *)&eit[1];
eitevt = (struct eit_short_event_descriptor_struct *)&eitloop[1];
if (eitevt->descriptor_tag != EIT_SHORT_EVENT_DESCRIPTOR)
{
// printf("Tag = '%c'\n", eitevt->descriptor_tag);
continue;
}
if (((eit->service_id_hi << 8) | eit->service_id_lo) != uProgramNumber)
{
// printf("Wrong program %04x need %04x\n", (eit->service_id_hi << 8) | eit->service_id_lo, uProgramNumber);
continue;
}
nReceivedEITs++;
pevt = (eit_event *)0;
if (eitloop->running_status == 4 | eitloop->running_status == 3)
pevt = (eit_event *)&evtRunning;
else if (eitloop->running_status == 1 || eitloop->running_status == 2 || eitloop->running_status == 0)
pevt = (eit_event *)&evtNext;
if (pevt)
{
unsigned char *p = (unsigned char *)&eitevt[1];
strdvbcpy((unsigned char *)pevt->szTitle, p, eitevt->event_name_length);
pevt->szSubTitle[0] = 0;
strdvbcpy((unsigned char *)pevt->szSubTitle, &p[eitevt->event_name_length+1], (int)p[eitevt->event_name_length]);
strcpy(pevt->szDate, mjd2string((eitloop->date_hi << 8) + eitloop->date_lo));
int hr = eitloop->time_hour + (eitloop->time_hour_ten * 10);
hr += 2;
if (hr >=24)
{
hr -= 24;
// need to switch date one day ahead here
}
sprintf(pevt->szTime, "%d:%c%c", hr,
eitloop->time_minute_ten + '0',
eitloop->time_minute + '0');
pevt->bIsValid = true;
}
}
CloseFilter(handle);
return 1;
}
/** */
int cEIT::SetProgramNumber(unsigned short pnr)
{
if (pnr == 0)
{
evtRunning.bIsValid = false;
evtNext.bIsValid = false;
return -1;
}
if (pnr != uProgramNumber)
{
evtRunning.bIsValid = false;
evtNext.bIsValid = false;
uProgramNumber = pnr;
return GetEIT();
}
return (IsValid() ? 1 : -1);
}
/** retrieves the string for the running title */
char * cEIT::GetRunningTitle()
{
if (evtRunning.bIsValid)
return evtRunning.szTitle;
else
return "---";
}
/** Retrieves the string for the running subtitle */
char * cEIT::GetRunningSubtitle()
{
if (evtRunning.bIsValid)
return evtRunning.szSubTitle;
else
return "---";
}
/** Retrieves the string representing the
date of the current event
*/
char * cEIT::GetRunningDate()
{
if (evtRunning.bIsValid)
return evtRunning.szDate;
else
return "---";
}
/** Retrieves the string representing the
time of the current event */
char * cEIT::GetRunningTime()
{
if (evtRunning.bIsValid)
return evtRunning.szTime;
else
return "---";
}
/** retrieves the string for the running title */
char * cEIT::GetNextTitle()
{
if (evtNext.bIsValid)
return evtNext.szTitle;
else
return "---";
}
/** Retrieves the string for the running subtitle */
char * cEIT::GetNextSubtitle()
{
if (evtNext.bIsValid)
return evtNext.szSubTitle;
else
return "---";
}
/** Retrieves the string representing the
date of the current event
*/
char * cEIT::GetNextDate()
{
if (evtNext.bIsValid)
return evtNext.szDate;
else
return "---";
}
/** Retrieves the string representing the
time of the current event */
char * cEIT::GetNextTime()
{
if (evtNext.bIsValid)
return evtNext.szTime;
else
return "---";
}
/** */
bool cEIT::IsValid()
{
return (evtRunning.bIsValid && evtNext.bIsValid);
}
/** */
int cEIT::strdvbcpy(unsigned char *dst, unsigned char *src, int max)
{
int a;
for (a = 0; a < max; a++)
{
if (*src == 0)
break;
if ((*src >= ' ' && *src <= '~') || (*src >= 0xa0 && *src <= 0xff))
*dst++ = *src++;
else
src++;
}
*dst = 0;
return a;
}

92
eit.h Normal file
View File

@ -0,0 +1,92 @@
/***************************************************************************
eit.h - description
-------------------
begin : Fri Aug 25 2000
copyright : (C) 2000 by Robert Schneider
email : Robert.Schneider@web.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.h 1.1 2000/09/03 10:23:24 kls Exp $
***************************************************************************/
#ifndef __EIT_H
#define __EIT_H
#include <dvb_v4l.h>
typedef struct eit_event {
bool bIsValid;
char szTitle[512];
char szSubTitle[512];
char szDate[12];
char szTime[12];
}eit_event;
/**
*@author Robert Schneider
*/
class cEIT {
public:
cEIT();
~cEIT();
/** */
int GetEIT();
/** */
int SetProgramNumber(unsigned short pnr);
/** Retrieves the string representing the time of the current event */
char * GetRunningTime();
/** Retrieves the string representing the date of the current event */
char * GetRunningDate();
/** Retrieves the string for the running subtitle */
char * GetRunningSubtitle();
/** retrieves the string for the running title */
char * GetRunningTitle();
/** Retrieves the string representing the time of the next event */
char * GetNextTime();
/** Retrieves the string representing the date of the next event */
char * GetNextDate();
/** Retrieves the string for the next subtitle */
char * GetNextSubtitle();
/** retrieves the string for the next title */
char * GetNextTitle();
/** */
bool IsValid();
protected: // Protected attributes
/** Device name of VBI device */
const char * cszBitFilter;
protected: // Protected attributes
/** handle to VBI device (usually /dev/vbi) */
int fsvbi;
/** Describes the event next on */
eit_event evtNext;
/** Describes the running event */
eit_event evtRunning;
protected: // Protected methods
/** Set the bitfilter in vbi device to return
correct tables */
int SetBitFilter(unsigned short pid, unsigned short section, unsigned short mode);
/** */
int GetSection(unsigned char *buf, ushort PID, unsigned char sec);
/** */
int CloseFilter(unsigned short handle);
/** */
char * mjd2string(unsigned short mjd);
/** */
int strdvbcpy(unsigned char *dst, unsigned char *src, int max);
public: // Public attributes
/** */
unsigned short uProgramNumber;
};
#endif

View File

@ -4,13 +4,16 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.c 1.10 2000/07/15 12:39:20 kls Exp $
* $Id: interface.c 1.11 2000/09/03 10:17:21 kls Exp $
*/
#include "interface.h"
#include <unistd.h>
#include "eit.h"
#include "remote.h"
cEIT EIT;
#if defined(REMOTE_RCU)
cRcIoRCU RcIo("/dev/ttyS1");
#elif defined(REMOTE_LIRC)
@ -316,7 +319,7 @@ void cInterface::DisplayChannel(int Number, const char *Name)
{
RcIo.Number(Number);
if (Name && !Recording()) {
Open(MenuColumns, 1);
Open(MenuColumns, EIT.IsValid() ? 5 : 1);
char buffer[MenuColumns + 1];
snprintf(buffer, sizeof(buffer), "%d %s", Number, Name ? Name : "");
Write(0, 0, buffer);
@ -324,7 +327,21 @@ void cInterface::DisplayChannel(int Number, const char *Name)
struct tm *now = localtime(&t);
snprintf(buffer, sizeof(buffer), "%02d:%02d", now->tm_hour, now->tm_min);
Write(-5, 0, buffer);
if (Wait(2, true) == kOk)
if (EIT.IsValid()) {
const int t = 7;
int w = MenuColumns - t;
Write(0, 1, EIT.GetRunningTime(), clrYellow, clrBackground);
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetRunningTitle());
Write(t, 1, buffer, clrCyan, clrBackground);
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetRunningSubtitle());
Write(t, 2, buffer, clrCyan, clrBackground);
Write(0, 3, EIT.GetNextTime(), clrYellow, clrBackground);
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetNextTitle());
Write(t, 3, buffer, clrCyan, clrBackground);
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetNextSubtitle());
Write(t, 4, buffer, clrCyan, clrBackground);
}
if (Wait(5, true) == kOk)
GetKey();
Close();
}