summaryrefslogtreecommitdiff
path: root/eit.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-11-01 18:00:00 +0100
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-11-01 18:00:00 +0100
commita69b3211dc4f9b34eef440067d5ba304fbfbad94 (patch)
tree7701ccce8cef832eb5ab56293a7ae99aca40b78e /eit.c
parenta379eb714f7f5ef9a12efbe7588bb3509faba056 (diff)
downloadvdr-patch-lnbsharing-a69b3211dc4f9b34eef440067d5ba304fbfbad94.tar.gz
vdr-patch-lnbsharing-a69b3211dc4f9b34eef440067d5ba304fbfbad94.tar.bz2
Version 0.67vdr-0.67
- The EIT information is now gathered in a separate thread. - The sytem time can now be synchronized to the time broadcast in the DVB data stream. This can be enabled in the "Setup" menu by setting "SetSystemTime" to 1. Note that this works only if VDR is running under a user id that has permisson to set the system time. - The new item "Schedule" in the "Main" menu opens VDR's EPG (thanks to Robert Schneider). See the MANUAL file for a detailed description. - The new setup parameters MarginStart and MarginStop define how long (in minutes) before the official start time of a broadcast VDR shall begin recording, and how long after the official end time it shall stop recording. These are used when a recording is programmed from the "Schedules" menu. - The delay value in the dvb.c.071.diff patch to the driver has been increased to '3', because on some systems the OSD was not displayed correctly. If you are running an already patched version 0.71 driver and encounter problems with the OSD, please make sure the parameter in the ddelay call is '3', not '2'. - Fixed initializing the RCU remote control code (didn't work after switching on the system). - Problematic characters in recording names (which can come from timers that are programmed via the "Schedules" menu) are now replaced by suitable substitutes.
Diffstat (limited to 'eit.c')
-rw-r--r--eit.c1443
1 files changed, 1096 insertions, 347 deletions
diff --git a/eit.c b/eit.c
index 44c873b..65856e6 100644
--- a/eit.c
+++ b/eit.c
@@ -13,20 +13,606 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
- * $Id: eit.c 1.4 2000/10/01 14:09:05 kls Exp $
+ * $Id: eit.c 1.7 2000/11/02 17:06:19 kls Exp $
***************************************************************************/
#include "eit.h"
+#include <ctype.h>
+#include <dvb_comcode.h>
+#include <dvb_v4l.h>
+#include <fcntl.h>
+#include <fstream.h>
+#include <iomanip.h>
#include <iostream.h>
+#include <minmax.h>
#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/ioctl.h>
-#include <dvb_comcode.h>
-#include "tools.h"
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+// --- cMJD ------------------------------------------------------------------
+
+class cMJD {
+public:
+ cMJD();
+ cMJD(u_char date_hi, u_char date_lo);
+ cMJD(u_char date_hi, u_char date_lo, u_char timehr, u_char timemi, u_char timese);
+ ~cMJD();
+ /** */
+ void ConvertToTime();
+ /** */
+ bool SetSystemTime();
+ /** */
+ time_t GetTime_t();
+protected: // Protected attributes
+ /** */
+ time_t mjdtime;
+protected: // Protected attributes
+ /** */
+ u_char time_second;
+protected: // Protected attributes
+ /** */
+ u_char time_minute;
+protected: // Protected attributes
+ /** */
+ u_char time_hour;
+protected: // Protected attributes
+ /** */
+ u_short mjd;
+};
+
+cMJD::cMJD()
+{
+}
+
+cMJD::cMJD(u_char date_hi, u_char date_lo)
+{
+ mjd = date_hi << 8 | date_lo;
+ time_hour = time_minute = time_second = 0;
+ ConvertToTime();
+}
+
+cMJD::cMJD(u_char date_hi, u_char date_lo, u_char timehr, u_char timemi, u_char timese)
+{
+ mjd = date_hi << 8 | date_lo;
+ time_hour = timehr;
+ time_minute = timemi;
+ time_second = timese;
+ ConvertToTime();
+}
+
+cMJD::~cMJD()
+{
+}
+
+/** */
+void cMJD::ConvertToTime()
+{
+ struct tm t;
+
+ t.tm_sec = time_second;
+ t.tm_min = time_minute;
+ t.tm_hour = time_hour;
+ int k;
+
+ t.tm_year = (int) ((mjd - 15078.2) / 365.25);
+ t.tm_mon = (int) ((mjd - 14956.1 - (int)(t.tm_year * 365.25)) / 30.6001);
+ t.tm_mday = (int) (mjd - 14956 - (int)(t.tm_year * 365.25) - (int)(t.tm_mon * 30.6001));
+ k = (t.tm_mon == 14 || t.tm_mon == 15) ? 1 : 0;
+ t.tm_year = t.tm_year + k;
+ t.tm_mon = t.tm_mon - 1 - k * 12;
+ t.tm_mon--;
+
+ t.tm_isdst = -1;
+ t.tm_gmtoff = 0;
+
+ mjdtime = timegm(&t);
+
+ //isyslog(LOG_INFO, "Time parsed = %s\n", ctime(&mjdtime));
+}
+
+/** */
+bool cMJD::SetSystemTime()
+{
+ struct tm *ptm;
+ time_t loctim;
+
+ ptm = localtime(&mjdtime);
+ loctim = time(NULL);
+
+ if (abs(mjdtime - loctim) > 2)
+ {
+ isyslog(LOG_INFO, "System Time = %s (%ld)\n", ctime(&loctim), loctim);
+ isyslog(LOG_INFO, "Local Time = %s (%ld)\n", ctime(&mjdtime), mjdtime);
+ if (stime(&mjdtime) < 0)
+ esyslog(LOG_ERR, "ERROR while setting system time: %s", strerror(errno));
+ return true;
+ }
+
+ return false;
+}
+/** */
+time_t cMJD::GetTime_t()
+{
+ return mjdtime;
+}
+
+// --- cTDT ------------------------------------------------------------------
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 utc_date_hi : 8;
+ u_char utc_date_lo : 8;
+ u_char utc_hour : 4;
+ u_char utc_hour_ten : 4;
+ u_char utc_min : 4;
+ u_char utc_min_ten : 4;
+ u_char utc_sec : 4;
+ u_char utc_sec_ten : 4;
+} tdt_t;
+
+class cTDT {
+public:
+ cTDT(tdt_t *ptdt);
+ ~cTDT();
+ /** */
+ bool SetSystemTime();
+protected: // Protected attributes
+ /** */
+ tdt_t tdt;
+ /** */
+ cMJD * mjd;
+};
+
+cTDT::cTDT(tdt_t *ptdt)
+{
+ tdt = *ptdt;
+ mjd = new cMJD(tdt.utc_date_hi, tdt.utc_date_lo,
+ tdt.utc_hour_ten * 10 + tdt.utc_hour,
+ tdt.utc_min_ten * 10 + tdt.utc_min,
+ tdt.utc_sec_ten * 10 + tdt.utc_sec);
+}
+
+cTDT::~cTDT()
+{
+}
+/** */
+bool cTDT::SetSystemTime()
+{
+ return mjd->SetSystemTime();
+}
+
+// --- cEventInfo ------------------------------------------------------------
+
+cEventInfo::cEventInfo(unsigned short serviceid, unsigned short eventid)
+{
+ pTitle = NULL;
+ pSubtitle = NULL;
+ pExtendedDescription = NULL;
+ bIsPresent = bIsFollowing = false;
+ lDuration = 0;
+ tTime = 0;
+ uEventID = eventid;
+ uServiceID = serviceid;
+ cExtendedDescriptorNumber = 0;
+ nChannelNumber = 0;
+}
+
+cEventInfo::~cEventInfo()
+{
+ delete pTitle;
+ delete pSubtitle;
+ delete pExtendedDescription;
+}
+
+/** */
+const char * cEventInfo::GetTitle() const
+{
+ return pTitle;
+}
+/** */
+const char * cEventInfo::GetSubtitle() const
+{
+ return pSubtitle;
+}
+/** */
+const char * cEventInfo::GetExtendedDescription() const
+{
+ return pExtendedDescription;
+}
+/** */
+bool cEventInfo::IsPresent() const
+{
+ return bIsPresent;
+}
+/** */
+void cEventInfo::SetPresent(bool pres)
+{
+ bIsPresent = pres;
+}
+/** */
+bool cEventInfo::IsFollowing() const
+{
+ return bIsFollowing;
+}
+/** */
+void cEventInfo::SetFollowing(bool foll)
+{
+ bIsFollowing = foll;
+}
+/** */
+const char * cEventInfo::GetDate() const
+{
+ static char szDate[25];
+
+ strftime(szDate, sizeof(szDate), "%d.%m.%Y", localtime(&tTime));
+
+ return szDate;
+}
+/** */
+const char * cEventInfo::GetTimeString() const
+{
+ static char szTime[25];
+
+ strftime(szTime, sizeof(szTime), "%R", localtime(&tTime));
+
+ return szTime;
+}
+/** */
+const char * cEventInfo::GetEndTimeString() const
+{
+ static char szEndTime[25];
+ time_t tEndTime = tTime + lDuration;
+
+ strftime(szEndTime, sizeof(szEndTime), "%R", localtime(&tEndTime));
+
+ return szEndTime;
+}
+/** */
+time_t cEventInfo::GetTime() const
+{
+ return tTime;
+}
+/** */
+long cEventInfo::GetDuration() const
+{
+ return lDuration;
+}
+/** */
+unsigned short cEventInfo::GetEventID() const
+{
+ return uEventID;
+}
+/** */
+bool cEventInfo::SetTitle(char *string)
+{
+ if (string == NULL)
+ return false;
+
+ pTitle = strdup(string);
+ if (pTitle == NULL)
+ return false;
+
+ return true;
+}
+/** */
+bool cEventInfo::SetSubtitle(char *string)
+{
+ if (string == NULL)
+ return false;
+
+ pSubtitle = strdup(string);
+ if (pSubtitle == NULL)
+ return false;
+
+ return true;
+}
+/** */
+bool cEventInfo::AddExtendedDescription(char *string)
+{
+ int size = 0;
+ bool first = true;
+ char *p;
+
+ if (string == NULL)
+ return false;
+
+ if (pExtendedDescription)
+ {
+ first = false;
+ size += strlen(pExtendedDescription);
+ }
+
+ size += (strlen(string) + 1);
+
+ p = (char *)realloc(pExtendedDescription, size);
+ if (p == NULL)
+ return false;
+
+ if (first)
+ *p = 0;
+
+ strcat(p, string);
+
+ pExtendedDescription = p;
+
+ return true;
+}
+/** */
+void cEventInfo::SetTime(time_t t)
+{
+ tTime = t;
+}
+/** */
+void cEventInfo::SetDuration(long l)
+{
+ lDuration = l;
+}
+/** */
+void cEventInfo::SetEventID(unsigned short evid)
+{
+ uEventID = evid;
+}
+/** */
+void cEventInfo::SetServiceID(unsigned short servid)
+{
+ uServiceID = servid;
+}
+/** */
+u_char cEventInfo::GetExtendedDescriptorNumber() const
+{
+ return cExtendedDescriptorNumber;
+}
+/** */
+void cEventInfo::IncreaseExtendedDescriptorNumber()
+{
+ cExtendedDescriptorNumber++;
+}
+
+/** */
+unsigned short cEventInfo::GetServiceID() const
+{
+ return uServiceID;
+}
+
+// --- cSchedule -------------------------------------------------------------
+
+cSchedule::cSchedule(unsigned short servid)
+{
+ pPresent = pFollowing = NULL;
+ uServiceID = servid;
+}
+
+
+cSchedule::~cSchedule()
+{
+}
+/** */
+const cEventInfo * cSchedule::GetPresentEvent() const
+{
+ // checking temporal sanity of present event (kls 2000-11-01)
+ time_t now = time(NULL);
+ if (pPresent && !(pPresent->GetTime() <= now && now <= pPresent->GetTime() + pPresent->GetDuration()))
+ {
+ cEventInfo *pe = Events.First();
+ while (pe != NULL)
+ {
+ if (pe->GetTime() <= now && now <= pe->GetTime() + pe->GetDuration())
+ return pe;
+ pe = Events.Next(pe);
+ }
+ }
+ return pPresent;
+}
+/** */
+const cEventInfo * cSchedule::GetFollowingEvent() const
+{
+ // checking temporal sanity of following event (kls 2000-11-01)
+ time_t now = time(NULL);
+ const cEventInfo *pr = GetPresentEvent(); // must have it verified!
+ if (pFollowing && !(pr && pr->GetTime() + pr->GetDuration() <= pFollowing->GetTime()))
+ {
+ int minDt = INT_MAX;
+ cEventInfo *pe = Events.First(), *pf = NULL;
+ while (pe != NULL)
+ {
+ int dt = pe->GetTime() - now;
+ if (dt > 0 && dt < minDt)
+ {
+ minDt = dt;
+ pf = pe;
+ }
+ pe = Events.Next(pe);
+ }
+ return pf;
+ }
+ return pFollowing;
+}
+/** */
+void cSchedule::SetServiceID(unsigned short servid)
+{
+ uServiceID = servid;
+}
+/** */
+unsigned short cSchedule::GetServiceID() const
+{
+ return uServiceID;
+}
+/** */
+const cEventInfo * cSchedule::GetEvent(unsigned short uEventID) const
+{
+ cEventInfo *pe = Events.First();
+ while (pe != NULL)
+ {
+ if (pe->GetEventID() == uEventID)
+ return pe;
+
+ pe = Events.Next(pe);
+ }
+
+ return NULL;
+}
+/** */
+const cEventInfo * cSchedule::GetEvent(time_t tTime) const
+{
+ cEventInfo *pe = Events.First();
+ while (pe != NULL)
+ {
+ if (pe->GetTime() == tTime)
+ return pe;
+
+ pe = Events.Next(pe);
+ }
+
+ return NULL;
+}
+/** */
+bool cSchedule::SetPresentEvent(cEventInfo *pEvent)
+{
+ if (pPresent != NULL)
+ pPresent->SetPresent(false);
+ pPresent = pEvent;
+ pPresent->SetPresent(true);
+
+ return true;
+}
+
+/** */
+bool cSchedule::SetFollowingEvent(cEventInfo *pEvent)
+{
+ if (pFollowing != NULL)
+ pFollowing->SetFollowing(false);
+ pFollowing = pEvent;
+ pFollowing->SetFollowing(true);
+
+ return true;
+}
+
+/** */
+void cSchedule::Cleanup()
+{
+ Cleanup(time(NULL));
+}
+
+/** */
+void cSchedule::Cleanup(time_t tTime)
+{
+ cEventInfo *pEvent;
+ for (int a = 0; true ; a++)
+ {
+ pEvent = Events.Get(a);
+ if (pEvent == NULL)
+ break;
+ if (pEvent->GetTime() + pEvent->GetDuration() < tTime)
+ {
+ Events.Del(pEvent);
+ a--;
+ }
+ }
+}
+
+// --- cSchedules ------------------------------------------------------------
+
+cSchedules::cSchedules()
+{
+ pCurrentSchedule = NULL;
+ uCurrentServiceID = 0;
+}
+
+cSchedules::~cSchedules()
+{
+}
+/** */
+bool cSchedules::SetCurrentServiceID(unsigned short servid)
+{
+ pCurrentSchedule = GetSchedule(servid);
+ if (pCurrentSchedule == NULL)
+ {
+ Add(new cSchedule(servid));
+ pCurrentSchedule = GetSchedule(servid);
+ if (pCurrentSchedule == NULL)
+ return false;
+ }
+
+ uCurrentServiceID = servid;
+
+ return true;
+}
+/** */
+const cSchedule * cSchedules::GetSchedule() const
+{
+ return pCurrentSchedule;
+}
+/** */
+const cSchedule * cSchedules::GetSchedule(unsigned short servid) const
+{
+ cSchedule *p;
+
+ p = First();
+ while (p != NULL)
+ {
+ if (p->GetServiceID() == servid)
+ return p;
+ p = Next(p);
+ }
+
+ return NULL;
+}
+
+/** */
+void cSchedules::Cleanup()
+{
+ cSchedule *p;
+
+ p = First();
+ while (p != NULL)
+ {
+ p->Cleanup(time(NULL));
+ p = Next(p);
+ }
+}
+
+// --- cEIT ------------------------------------------------------------------
+
+#define DEC(N) dec << setw(N) << setfill(int('0'))
+#define HEX(N) hex << setw(N) << setfill(int('0'))
+
+#define EIT_STUFFING_DESCRIPTOR 0x42
+#define EIT_LINKAGE_DESCRIPTOR 0x4a
+#define EIT_SHORT_EVENT_DESCRIPTOR 0x4d
+#define EIT_EXTENDED_EVENT_DESCRIPTOR 0x4e
+#define EIT_TIME_SHIFTED_EVENT_DESCRIPTOR 0x4f
+#define EIT_COMPONENT_DESCRIPTOR 0x50
+#define EIT_CA_IDENTIFIER_DESCRIPTOR 0x53
+#define EIT_CONTENT_DESCRIPTOR 0x54
+#define EIT_PARENTAL_RATING_DESCRIPTOR 0x55
+#define EIT_TELEPHONE_DESCRIPTOR 0x57
+#define EIT_MULTILINGUAL_COMPONENT_DESCRIPTOR 0x5e
+#define EIT_PRIVATE_DATE_SPECIFIER_DESCRIPTOR 0x5f
+#define EIT_SHORT_SMOOTHING_BUFFER_DESCRIPTOR 0x61
+#define EIT_DATA_BROADCAST_DESCRIPTOR 0x64
+#define EIT_PDC_DESCRIPTOR 0x69
+
+typedef struct eit_struct {
u_char table_id : 8;
#if BYTE_ORDER == BIG_ENDIAN
@@ -64,9 +650,7 @@ typedef struct {
u_char segment_last_table_id : 8;
} eit_t;
-#define EIT_SIZE 14
-
-struct eit_loop_struct1 {
+typedef struct eit_loop_struct {
u_char event_id_hi : 8;
u_char event_id_lo : 8;
@@ -79,12 +663,12 @@ struct eit_loop_struct1 {
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_hour_ten : 4;
u_char dur_minute : 4;
- u_char dur_second_ten : 4;
+ u_char dur_minute_ten : 4;
u_char dur_second : 4;
+ u_char dur_second_ten : 4;
#if BYTE_ORDER == BIG_ENDIAN
u_char running_status : 3;
@@ -97,12 +681,9 @@ struct eit_loop_struct1 {
#endif
u_char descriptors_loop_length_lo : 8;
-};
+} eit_loop_t;
-#define EIT_SHORT_EVENT_DESCRIPTOR 0x4d
-#define EIT_SHORT_EVENT_DESCRIPTOR_SIZE 6
-
-struct eit_short_event_descriptor_struct {
+typedef struct eit_short_event_struct {
u_char descriptor_tag : 8;
u_char descriptor_length : 8;
@@ -111,415 +692,583 @@ struct eit_short_event_descriptor_struct {
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 {
+} eit_short_event_t;
+typedef struct eit_extended_event_struct {
u_char descriptor_tag : 8;
u_char descriptor_length : 8;
+ u_char last_descriptor_number : 4;
+ u_char descriptor_number : 4;
+
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 length_of_items : 8;
+} eit_extended_event_t;
+
+typedef struct eit_content_descriptor {
+ u_char descriptor_tag : 8;
+ u_char descriptor_length : 8;
+} eit_content_descriptor_t;
- 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;
+typedef struct eit_content_loop {
+ u_char content_nibble_level_2 : 4;
+ u_char content_nibble_level_1 : 4;
+ u_char user_nibble_2 : 4;
+ u_char user_nibble_1 : 4;
+} eit_content_loop_t;
- 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;
+class cEIT {
+private:
+ cSchedules *schedules;
+public:
+ cEIT(void *buf, int length, cSchedules *Schedules);
+ ~cEIT();
+ /** */
+ int ProcessEIT();
-cEIT::cEIT()
+protected: // Protected methods
+ /** */
+ int strdvbcpy(unsigned char *dst, unsigned char *src, int max);
+ /** returns true if this EIT covers a
+present/following information, false if it's
+schedule information */
+ bool IsPresentFollowing();
+ /** */
+ bool WriteShortEventDescriptor(unsigned short service, eit_loop_t *eitloop, u_char *buf);
+ /** */
+ bool WriteExtEventDescriptor(unsigned short service, eit_loop_t *eitloop, u_char *buf);
+protected: // Protected attributes
+ int buflen;
+protected: // Protected attributes
+ /** */
+ u_char buffer[4097];
+ /** Table ID of this EIT struct */
+ u_char tid;
+ /** EITs service id (program number) */
+ u_short pid;
+};
+
+cEIT::cEIT(void * buf, int length, cSchedules *Schedules)
{
- cszBitFilter = "/dev/vbi";
- if((fsvbi = open(cszBitFilter, O_RDWR))<0)
- {
- fsvbi = 0;
- esyslog(LOG_ERR, "Failed to open DVB bitfilter device: %s", cszBitFilter);
- return;
- }
+ buflen = min((unsigned int)length, sizeof(buffer));
+ memset(buffer, 0, sizeof(buffer));
+ memcpy(buffer, buf, buflen);
+ tid = buffer[0];
+ schedules = Schedules;
}
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 cEIT::ProcessEIT()
{
- int seclen=0;
- unsigned short handle, pid;
- unsigned char section, sectionnum=0xff, maxsec=0;
-
- if ((handle = SetBitFilter(PID, (sec<<8)|0x00ff, SECTION_CONTINUOS))==0xffff)
- return -1;
+ int bufact = 0;
+ eit_t *eit;
+ eit_loop_t *eitloop;
+ u_char tmp[256];
+
+ if (bufact + (int)sizeof(eit_t) > buflen)
+ return 0;
+ eit = (eit_t *)buffer;
+ bufact += sizeof(eit_t);
+
+ unsigned int service = (eit->service_id_hi << 8) | eit->service_id_lo;
+
+ while(bufact + (int)sizeof(eit_loop_t) <= buflen)
+ {
+ eitloop = (eit_loop_t *)&buffer[bufact];
+ bufact += sizeof(eit_loop_t);
+
+ int descdatalen = (eitloop->descriptors_loop_length_hi << 8) + eitloop->descriptors_loop_length_lo;
+ int descdataact = 0;
+
+ while (descdataact < descdatalen && bufact < buflen)
+ {
+ switch (buffer[bufact])
+ {
+ eit_content_descriptor_t *cont;
+ eit_content_loop_t *contloop;
+
+ case EIT_STUFFING_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_STUFFING_DESCRIPTOR");
+ break;
+
+ case EIT_LINKAGE_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_LINKAGE_DESCRIPTOR");
+ break;
+
+ case EIT_SHORT_EVENT_DESCRIPTOR:
+ WriteShortEventDescriptor(service, eitloop, &buffer[bufact]);
+ break;
- seclen=0;
- if (!cFile::AnyFileReady(fsvbi, 20000))
- {
- //cerr << "Timeout\n";
- return -1;
- }
+ case EIT_EXTENDED_EVENT_DESCRIPTOR:
+ WriteExtEventDescriptor(service, eitloop, &buffer[bufact]);
+ break;
+
+ case EIT_TIME_SHIFTED_EVENT_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_TIME_SHIFTED_EVENT_DESCRIPTOR");
+ break;
- read(fsvbi, buf, 8);
- seclen=(buf[6]<<8)|buf[7];
- pid=(buf[4]<<8)|buf[5];
+ case EIT_COMPONENT_DESCRIPTOR :
+ strdvbcpy(tmp, &buffer[bufact + 8], buffer[bufact + 1] - 6);
+ //dsyslog(LOG_INFO, "Found EIT_COMPONENT_DESCRIPTOR %c%c%c 0x%02x/0x%02x/0x%02x '%s'\n", buffer[bufact + 5], buffer[bufact + 6], buffer[bufact + 7], buffer[2], buffer[3], buffer[4], tmp);
+ break;
- read(fsvbi, buf, seclen);
- section=buf[0];
- sectionnum=buf[6];
- maxsec=buf[7];
+ case EIT_CA_IDENTIFIER_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_CA_IDENTIFIER_DESCRIPTOR");
+ break;
- //cerr << "secnum: " << HEX(2) << (int)sectionnum
- // << ", secmax: " << HEX(2) << (int) msecnum << "\n";
+ case EIT_CONTENT_DESCRIPTOR :
+ cont = (eit_content_descriptor_t *)buffer;
+ contloop = (eit_content_loop_t *)&buffer[sizeof(eit_content_descriptor_t)];
+ //dsyslog(LOG_INFO, "Found EIT_CONTENT_DESCRIPTOR 0x%02x/0x%02x\n", contloop->content_nibble_level_1, contloop->content_nibble_level_2);
+ break;
- CloseFilter(handle);
+ case EIT_PARENTAL_RATING_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_PARENTAL_RATING_DESCRIPTOR");
+ break;
- return seclen;
-}
+ case EIT_TELEPHONE_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_TELEPHONE_DESCRIPTOR");
+ break;
+
+ case EIT_MULTILINGUAL_COMPONENT_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_MULTILINGUAL_COMPONENT_DESCRIPTOR");
+ break;
+
+ case EIT_PRIVATE_DATE_SPECIFIER_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_PRIVATE_DATE_SPECIFIER_DESCRIPTOR");
+ break;
+
+ case EIT_SHORT_SMOOTHING_BUFFER_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_SHORT_SMOOTHING_BUFFER_DESCRIPTOR");
+ break;
+
+ case EIT_DATA_BROADCAST_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_DATA_BROADCAST_DESCRIPTOR");
+ break;
+
+ case EIT_PDC_DESCRIPTOR :
+ //dsyslog(LOG_INFO, "Found EIT_PDC_DESCRIPTOR");
+ break;
+
+ default:
+ //dsyslog(LOG_INFO, "Found unhandled descriptor 0x%02x with length of %04d\n", (int)buffer[bufact], (int)buffer[bufact + 1]);
+ break;
+ }
+ descdataact += (buffer[bufact + 1] + 2);
+ bufact += (buffer[bufact + 1] + 2);
+ }
+ }
-/** */
-int cEIT::CloseFilter(unsigned short handle)
-{
- if (ioctl(fsvbi, VIDIOCSSHUTDOWNFILTER, &handle)<0)
- return -1;
return 0;
}
/** */
-char * cEIT::mjd2string(unsigned short mjd)
+int cEIT::strdvbcpy(unsigned char *dst, unsigned char *src, int max)
{
- int y, m, d, k;
- static char buf[20];
+ int a = 0;
- 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);
+ if (*src == 0x05 || (*src >= 0x20 && *src <= 0xff))
+ {
+ for (a = 0; a < max; a++)
+ {
+ if (*src == 0)
+ break;
+
+ if ((*src >= ' ' && *src <= '~') || (*src >= 0xa0 && *src <= 0xff))
+ *dst++ = *src++;
+ else
+ {
+ // if ((*src > '~' && *src < 0xa0) || *src == 0xff)
+ // cerr << "found special character 0x" << HEX(2) << (int)*src << endl;
+ src++;
+ }
+ }
+ *dst = 0;
+ }
+ else
+ {
+ const char *ret;
+
+ switch (*src)
+ {
+ case 0x01: ret = "Coding according to character table 1"; break;
+ case 0x02: ret = "Coding according to character table 2"; break;
+ case 0x03: ret = "Coding according to character table 3"; break;
+ case 0x04: ret = "Coding according to character table 4"; break;
+ case 0x10: ret = "Coding according to ISO/IEC 8859"; break;
+ case 0x11: ret = "Coding according to ISO/IEC 10646"; break;
+ case 0x12: ret = "Coding according to KSC 5601"; break;
+ default: ret = "Unknown coding"; break;
+ }
+ strncpy((char *)dst, ret, max);
+ }
+ return a;
+}
+
+/** returns true if this EIT covers a
+present/following information, false if it's
+schedule information */
+bool cEIT::IsPresentFollowing()
+{
+ if (tid == 0x4e || tid == 0x4f)
+ return true;
- return(buf);
+ return false;
}
/** */
-int cEIT::GetEIT()
+bool cEIT::WriteShortEventDescriptor(unsigned short service, eit_loop_t *eitloop, u_char *buf)
{
- unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-)
- eit_t *eit;
- struct eit_loop_struct1 *eitloop;
- struct eit_short_event_descriptor_struct *eitevt;
- unsigned int seclen;
- unsigned short handle, pid;
- eit_event * pevt = (eit_event *)0;
- time_t tstart;
+ u_char tmp[256];
+ eit_short_event_t *evt = (eit_short_event_t *)buf;
+ unsigned short eventid = (unsigned short)((eitloop->event_id_hi << 8) | eitloop->event_id_lo);
+ cEventInfo *pEvent;
+
+ //isyslog(LOG_INFO, "Found Short Event Descriptor");
- if ((handle = SetBitFilter(0x12, (0x4e << 8) | 0x00ff, SECTION_CONTINUOS))==0xffff)
+ cSchedule *pSchedule = (cSchedule *)schedules->GetSchedule(service);
+ if (pSchedule == NULL)
{
- return -1;
+ schedules->Add(new cSchedule(service));
+ pSchedule = (cSchedule *)schedules->GetSchedule(service);
+ if (pSchedule == NULL)
+ return false;
}
-/*
- pid_t process = fork();
- if (process < 0)
+
+ /* cSchedule::GetPresentEvent() and cSchedule::GetFollowingEvent() verify
+ the temporal sanity of these events, so calling them here appears to
+ be a bad idea... (kls 2000-11-01)
+ //
+ // if we are working on a present/following info, let's see whether
+ // we already have present/following info for this service and if yes
+ // check whether it's the same eventid, if yes, just return, nothing
+ // left to do.
+ //
+ if (IsPresentFollowing())
{
- cerr << "GetEIT -1" << endl;
- return -1;
+ if (eitloop->running_status == 4 || eitloop->running_status == 3)
+ pEvent = (cEventInfo *)pSchedule->GetPresentEvent();
+ else
+ pEvent = (cEventInfo *)pSchedule->GetFollowingEvent();
+
+ if (pEvent != NULL)
+ if (pEvent->GetEventID() == eventid)
+ return true;
}
-
- if (process != 0)
+ */
+
+ //
+ // let's see whether we have that eventid already
+ // in case not, we have to create a new cEventInfo for it
+ //
+ pEvent = (cEventInfo *)pSchedule->GetEvent(eventid);
+ if (pEvent == NULL)
{
- cerr << "GetEIT 0" << endl;
- return 0;
+ pSchedule->Events.Add(new cEventInfo(service, eventid));
+ pEvent = (cEventInfo *)pSchedule->GetEvent(eventid);
+ if (pEvent == NULL)
+ return false;
+
+ strdvbcpy(tmp, &buf[sizeof(eit_short_event_t)], evt->event_name_length);
+ pEvent->SetTitle((char *)tmp);
+ strdvbcpy(tmp, &buf[sizeof(eit_short_event_t) + evt->event_name_length + 1],
+ (int)buf[sizeof(eit_short_event_t) + evt->event_name_length]);
+ pEvent->SetSubtitle((char *)tmp);
+ cMJD mjd(eitloop->date_hi, eitloop->date_lo,
+ eitloop->time_hour_ten * 10 + eitloop->time_hour,
+ eitloop->time_minute_ten * 10 + eitloop->time_minute,
+ eitloop->time_second_ten * 10 + eitloop->time_second);
+ pEvent->SetTime(mjd.GetTime_t());
+ pEvent->SetDuration((long)((long)((eitloop->dur_hour_ten * 10 + eitloop->dur_hour) * 60l * 60l) +
+ (long)((eitloop->dur_minute_ten * 10 + eitloop->dur_minute) * 60l) +
+ (long)(eitloop->dur_second_ten * 10 + eitloop->dur_second)));
}
-*/
- int nReceivedEITs = 0;
- tstart = time(NULL);
- while ((!evtRunning.bIsValid || !evtNext.bIsValid) && nReceivedEITs < 20 && difftime(time(NULL), tstart) < 4)
+
+ if (IsPresentFollowing())
{
- if (!cFile::AnyFileReady(fsvbi, 5000))
- {
- //cerr << "Timeout\n";
- CloseFilter(handle);
- return -1;
- }
+ if (eitloop->running_status == 4 || eitloop->running_status == 3)
+ pSchedule->SetPresentEvent(pEvent);
+ else if (eitloop->running_status == 1 || eitloop->running_status == 2 || eitloop->running_status == 0)
+ pSchedule->SetFollowingEvent(pEvent);
+ }
+
+ return true;
+}
+
+/** */
+bool cEIT::WriteExtEventDescriptor(unsigned short service, eit_loop_t *eitloop, u_char *buf)
+{
+ u_char tmp[256];
+ eit_extended_event_t *evt = (eit_extended_event_t *)buf;
+ int bufact, buflen;
+ unsigned short eventid = (unsigned short)((eitloop->event_id_hi << 8) | eitloop->event_id_lo);
+ cEventInfo *pEvent;
- read(fsvbi, buf, 8);
- seclen=(buf[6]<<8)|buf[7];
- pid=(buf[4]<<8)|buf[5];
+ //isyslog(LOG_INFO, "Found Extended Event Descriptor");
- if (seclen >= sizeof(buf))
- seclen = sizeof(buf) - 1;
- read(fsvbi, buf, seclen);
+ cSchedule *pSchedule = (cSchedule *)schedules->GetSchedule(service);
+ if (pSchedule == NULL)
+ {
+ schedules->Add(new cSchedule(service));
+ pSchedule = (cSchedule *)schedules->GetSchedule(service);
+ if (pSchedule == NULL)
+ return false;
+ }
+
+ pEvent = (cEventInfo *)pSchedule->GetEvent(eventid);
+ if (pEvent == NULL)
+ return false;
- if (seclen < (int)(sizeof(eit_t)
- + sizeof(struct eit_loop_struct1)
- + sizeof(struct eit_short_event_descriptor_struct)))
- continue;
+ if (evt->descriptor_number != pEvent->GetExtendedDescriptorNumber())
+ return false;
- eit = (eit_t *)buf;
- eitloop = (struct eit_loop_struct1 *)&eit[1];
- eitevt = (struct eit_short_event_descriptor_struct *)&eitloop[1];
+ bufact = sizeof(eit_extended_event_t);
+ buflen = buf[1] + 2;
- if (eitevt->descriptor_tag != EIT_SHORT_EVENT_DESCRIPTOR)
+ if (evt->length_of_items > 0)
+ {
+ while (bufact - sizeof(eit_extended_event_t) < evt->length_of_items)
{
- // printf("Tag = '%c'\n", eitevt->descriptor_tag);
- continue;
+ strdvbcpy(tmp, &buf[bufact + 1], (int)buf[bufact]);
+ // could use value in tmp now to do something,
+ // haven't seen any items as of yet transmitted from satellite
+ bufact += (buf[bufact] + 1);
}
+ }
- 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++;
+ strdvbcpy(tmp, &buf[bufact + 1], (int)buf[bufact]);
+ if (pEvent->AddExtendedDescription((char *)tmp))
+ {
+ pEvent->IncreaseExtendedDescriptorNumber();
+ return true;
+ }
- 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;
+ return false;
+}
+
+// --- cSIProcessor ----------------------------------------------------------
+
+#define MAX_FILTERS 20
+
+/** */
+cSIProcessor::cSIProcessor(const char *FileName)
+{
+ useTStime = false;
+ filters = NULL;
+ schedules = NULL;
+ if ((fsvbi = open(FileName, O_RDONLY)) >= 0)
+ {
+ schedules = new cSchedules;
+ filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
+ }
+ else
+ LOG_ERROR_STR(FileName);
+}
+
+cSIProcessor::~cSIProcessor()
+{
+ if (fsvbi >= 0)
+ {
+ Stop();
+ ShutDownFilters();
+ delete filters;
+ delete schedules;
+ close(fsvbi);
+ }
+}
+
+/** use the vbi device to parse all relevant SI
+information and let the classes corresponding
+to the tables write their information to the disk */
+void cSIProcessor::Action()
+{
+ if (fsvbi < 0) {
+ esyslog(LOG_ERR, "cSIProcessor::Action() called without open file - returning");
+ return;
+ }
+
+ dsyslog(LOG_INFO, "EIT processing thread started (pid=%d)", getpid());
+
+ unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-)
+ unsigned int seclen;
+ unsigned int pid;
+ time_t lastCleanup = time(NULL);
+ struct pollfd pfd;
+
+ while(true)
+ {
+ time_t now = time(NULL);
+ struct tm *ptm = localtime(&now);
+ if (now - lastCleanup > 3600 && ptm->tm_hour == 5)
+ {
+ LOCK_THREAD;
- if (pevt)
+ isyslog(LOG_INFO, "Now cleaning up things");
+ schedules->Cleanup();
+ lastCleanup = now;
+ }
+
+ /* wait data become ready from the bitfilter */
+ pfd.fd = fsvbi;
+ pfd.events = POLLIN;
+ if(poll(&pfd, 1, 1000) != 0) /* timeout is 5 secs */
{
- 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)
+ // fprintf(stderr, "<data>\n");
+ /* read section */
+ read(fsvbi, buf, 8);
+ seclen = (buf[6] << 8) | buf[7];
+ pid = (buf[4] << 8) | buf[5];
+ read(fsvbi, buf, seclen);
+
+ //dsyslog(LOG_INFO, "Received pid 0x%02x with table ID 0x%02x and length of %04d\n", pid, buf[0], seclen);
+
+ switch (pid)
{
- hr -= 24;
- // need to switch date one day ahead here
+ case 0x14:
+ if (buf[0] == 0x70)
+ {
+ if (useTStime)
+ {
+ cTDT ctdt((tdt_t *)buf);
+ ctdt.SetSystemTime();
+ }
+ }
+ /*XXX this comes pretty often:
+ else
+ dsyslog(LOG_INFO, "Time packet was not 0x70 but 0x%02x\n", (int)buf[0]);
+ XXX*/
+ break;
+
+ case 0x12:
+ if (buf[0] != 0x72)
+ {
+ LOCK_THREAD;
+
+ cEIT ceit(buf, seclen, schedules);
+ ceit.ProcessEIT();
+ }
+ else
+ dsyslog(LOG_INFO, "Received stuffing section in EIT\n");
+ break;
+
+ default:
+ break;
}
- sprintf(pevt->szTime, "%d:%c%c", hr,
- eitloop->time_minute_ten + '0',
- eitloop->time_minute + '0');
- pevt->bIsValid = true;
}
- }
-
- CloseFilter(handle);
+ else
+ {
+ LOCK_THREAD;
- return 1;
+ //XXX this comes pretty often
+ //isyslog(LOG_INFO, "Received timeout from poll, refreshing filters\n");
+ RefreshFilters();
+ }
+// WakeUp();
+ }
}
-/** */
-int cEIT::SetProgramNumber(unsigned short pnr)
+/** Add a filter with packet identifier pid and
+table identifer tid */
+bool cSIProcessor::AddFilter(u_char pid, u_char tid)
{
- if (pnr == 0)
- {
- evtRunning.bIsValid = false;
- evtNext.bIsValid = false;
- return -1;
- }
+ if (fsvbi < 0)
+ return false;
+
+ int section = ((int)tid << 8) | 0x00ff;
+
+ struct bitfilter filt = {
+ pid,
+ { section, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+ SECTION_CONTINUOS, 0,
+ FILTER_MEM,
+ {},
+ };
- if (pnr != uProgramNumber)
+ if (ioctl(fsvbi, VIDIOCSBITFILTER, &filt) < 0)
+ return false;
+
+ for (int a = 0; a < MAX_FILTERS; a++)
{
- evtRunning.bIsValid = false;
- evtNext.bIsValid = false;
- uProgramNumber = pnr;
+ if (filters[a].inuse == false)
+ {
+ filters[a].pid = pid;
+ filters[a].tid = tid;
+ filters[a].handle = filt.handle;
+ filters[a].inuse = true;
+ // dsyslog(LOG_INFO, " Registered filter handle %04x, pid = %02d, tid = %02d", filters[a].handle, filters[a].pid, filters[a].tid);
+ return true;
+ }
}
- return 1;
+
+ return false;
}
-/** 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()
+/** set whether local systems time should be
+set by the received TDT or TOT packets */
+bool cSIProcessor::SetUseTSTime(bool use)
{
- 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 "---";
+ useTStime = use;
+ return useTStime;
}
-/** 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()
+
+/** */
+bool cSIProcessor::ShutDownFilters()
{
- if (evtNext.bIsValid)
- return evtNext.szTime;
- else
- return "---";
+ if (fsvbi < 0)
+ return false;
+
+ bool ret = true;
+
+ for (int a = 0; a < MAX_FILTERS; a++)
+ {
+ if (filters[a].inuse == true)
+ {
+ if (ioctl(fsvbi, VIDIOCSSHUTDOWNFILTER, &filters[a].handle) < 0)
+ ret = false;
+
+ // dsyslog(LOG_INFO, "Deregistered filter handle %04x, pid = %02d, tid = %02d", filters[a].handle, filters[a].pid, filters[a].tid);
+
+ filters[a].inuse = false;
+ }
+ }
+
+ return ret;
}
-/** */
-bool cEIT::IsValid()
+/** */
+bool cSIProcessor::SetCurrentServiceID(unsigned short servid)
{
- GetEIT();
- return (evtRunning.bIsValid && evtNext.bIsValid);
+ LOCK_THREAD;
+ return schedules ? schedules->SetCurrentServiceID(servid) : false;
}
/** */
-int cEIT::strdvbcpy(unsigned char *dst, unsigned char *src, int max)
+bool cSIProcessor::RefreshFilters()
{
- int a;
- for (a = 0; a < max; a++)
+ if (fsvbi < 0)
+ return false;
+
+ bool ret = true;
+
+ ret = ShutDownFilters();
+
+ for (int a = 0; a < MAX_FILTERS; a++)
{
- if (*src == 0)
- break;
-
- if ((*src >= ' ' && *src <= '~') || (*src >= 0xa0 && *src <= 0xff))
- *dst++ = *src++;
- else
- src++;
+ if (filters[a].inuse == false && filters[a].pid != 0 && filters[a].tid != 0)
+ {
+ if (!AddFilter(filters[a].pid, filters[a].tid))
+ ret = false;
+ }
}
- *dst = 0;
- return a;
+
+ return ret;
}
+