mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
235 lines
5.4 KiB
C
235 lines
5.4 KiB
C
/*
|
|
* filter.c: Section filter
|
|
*
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
* how to reach the author.
|
|
*
|
|
* $Id: filter.c 5.1 2021/03/16 15:10:54 kls Exp $
|
|
*/
|
|
|
|
#include "filter.h"
|
|
#include "sections.h"
|
|
|
|
// --- cSectionSyncer --------------------------------------------------------
|
|
|
|
cSectionSyncer::cSectionSyncer(bool Random)
|
|
{
|
|
random = Random;
|
|
Reset();
|
|
}
|
|
|
|
void cSectionSyncer::Reset(void)
|
|
{
|
|
currentVersion = -1;
|
|
currentSection = -1;
|
|
synced = false;
|
|
complete = false;
|
|
segments = 0;
|
|
memset(sections, 0x00, sizeof(sections));
|
|
}
|
|
|
|
bool cSectionSyncer::Check(uchar Version, int SectionNumber)
|
|
{
|
|
if (Version != currentVersion) {
|
|
Reset();
|
|
currentVersion = Version;
|
|
}
|
|
if (complete)
|
|
return false;
|
|
if (!random) {
|
|
if (!synced) {
|
|
if (SectionNumber == 0) {
|
|
currentSection = 0;
|
|
synced = true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
if (SectionNumber != currentSection)
|
|
return false;
|
|
}
|
|
return !GetSectionFlag(SectionNumber);
|
|
}
|
|
|
|
bool cSectionSyncer::Processed(int SectionNumber, int LastSectionNumber, int SegmentLastSectionNumber)
|
|
{
|
|
SetSectionFlag(SectionNumber, true); // the flag for this section
|
|
if (!random)
|
|
currentSection++; // expect the next section
|
|
int Index = SectionNumber / 8; // the segment (byte) in which this section lies
|
|
uchar b = 0xFF; // all sections in this segment
|
|
if (SegmentLastSectionNumber < 0 && Index == LastSectionNumber / 8)
|
|
SegmentLastSectionNumber = LastSectionNumber;
|
|
if (SegmentLastSectionNumber >= 0) {
|
|
b >>= 7 - (SegmentLastSectionNumber & 0x07); // limits them up to the last section in this segment
|
|
if (!random && SectionNumber == SegmentLastSectionNumber)
|
|
currentSection = (SectionNumber + 8) & ~0x07; // expect first section of next segment
|
|
}
|
|
if (sections[Index] == b) // all expected sections in this segment have been received
|
|
segments |= 1 << Index; // so we set the respective bit in the segments flags
|
|
uint32_t s = 0xFFFFFFFF; // all segments
|
|
s >>= 31 - (LastSectionNumber / 8); // limits them up to the last expected segment
|
|
complete = segments == s;
|
|
return complete;
|
|
}
|
|
|
|
#if DEPRECATED_SECTIONSYNCER_SYNC_REPEAT
|
|
void cSectionSyncer::Repeat(void)
|
|
{
|
|
SetSectionFlag(currentSection, false);
|
|
synced = false;
|
|
complete = false;
|
|
}
|
|
|
|
bool cSectionSyncer::Sync(uchar Version, int Number, int LastNumber)
|
|
{
|
|
if (Version != currentVersion) {
|
|
Reset();
|
|
currentVersion = Version;
|
|
}
|
|
if (!synced) {
|
|
if (Number != 0)
|
|
return false;
|
|
else
|
|
synced = true;
|
|
}
|
|
currentSection = Number;
|
|
bool Result = !GetSectionFlag(Number);
|
|
SetSectionFlag(Number, true);
|
|
if (Number == LastNumber)
|
|
complete = true;
|
|
return Result;
|
|
}
|
|
#endif
|
|
|
|
// --- cFilterData -----------------------------------------------------------
|
|
|
|
cFilterData::cFilterData(void)
|
|
{
|
|
pid = 0;
|
|
tid = 0;
|
|
mask = 0;
|
|
sticky = false;
|
|
}
|
|
|
|
cFilterData::cFilterData(u_short Pid, u_char Tid, u_char Mask, bool Sticky)
|
|
{
|
|
pid = Pid;
|
|
tid = Tid;
|
|
mask = Mask;
|
|
sticky = Sticky;
|
|
}
|
|
|
|
cFilterData& cFilterData::operator= (const cFilterData &FilterData)
|
|
{
|
|
pid = FilterData.pid;
|
|
tid = FilterData.tid;
|
|
mask = FilterData.mask;
|
|
sticky = FilterData.sticky;
|
|
return *this;
|
|
}
|
|
|
|
bool cFilterData::Is(u_short Pid, u_char Tid, u_char Mask)
|
|
{
|
|
return pid == Pid && tid == Tid && mask == Mask;
|
|
}
|
|
|
|
bool cFilterData::Matches(u_short Pid, u_char Tid)
|
|
{
|
|
return pid == Pid && tid == (Tid & mask);
|
|
}
|
|
|
|
// --- cFilter ---------------------------------------------------------------
|
|
|
|
cFilter::cFilter(void)
|
|
{
|
|
sectionHandler = NULL;
|
|
on = false;
|
|
}
|
|
|
|
cFilter::cFilter(u_short Pid, u_char Tid, u_char Mask)
|
|
{
|
|
sectionHandler = NULL;
|
|
on = false;
|
|
Set(Pid, Tid, Mask);
|
|
}
|
|
|
|
cFilter::~cFilter()
|
|
{
|
|
if (sectionHandler)
|
|
sectionHandler->Detach(this);
|
|
}
|
|
|
|
int cFilter::Source(void)
|
|
{
|
|
return sectionHandler ? sectionHandler->Source() : 0;
|
|
}
|
|
|
|
int cFilter::Transponder(void)
|
|
{
|
|
return sectionHandler ? sectionHandler->Transponder() : 0;
|
|
}
|
|
|
|
const cChannel *cFilter::Channel(void)
|
|
{
|
|
return sectionHandler ? sectionHandler->Channel() : NULL;
|
|
}
|
|
|
|
void cFilter::SetStatus(bool On)
|
|
{
|
|
if (sectionHandler && on != On) {
|
|
cFilterData *fd = data.First();
|
|
while (fd) {
|
|
if (On)
|
|
sectionHandler->Add(fd);
|
|
else {
|
|
sectionHandler->Del(fd);
|
|
if (!fd->sticky) {
|
|
cFilterData *next = data.Next(fd);
|
|
data.Del(fd);
|
|
fd = next;
|
|
continue;
|
|
}
|
|
}
|
|
fd = data.Next(fd);
|
|
}
|
|
on = On;
|
|
}
|
|
}
|
|
|
|
bool cFilter::Matches(u_short Pid, u_char Tid)
|
|
{
|
|
if (on) {
|
|
for (cFilterData *fd = data.First(); fd; fd = data.Next(fd)) {
|
|
if (fd->Matches(Pid, Tid))
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void cFilter::Set(u_short Pid, u_char Tid, u_char Mask)
|
|
{
|
|
Add(Pid, Tid, Mask, true);
|
|
}
|
|
|
|
void cFilter::Add(u_short Pid, u_char Tid, u_char Mask, bool Sticky)
|
|
{
|
|
cFilterData *fd = new cFilterData(Pid, Tid, Mask, Sticky);
|
|
data.Add(fd);
|
|
if (sectionHandler && on)
|
|
sectionHandler->Add(fd);
|
|
}
|
|
|
|
void cFilter::Del(u_short Pid, u_char Tid, u_char Mask)
|
|
{
|
|
for (cFilterData *fd = data.First(); fd; fd = data.Next(fd)) {
|
|
if (fd->Is(Pid, Tid, Mask)) {
|
|
if (sectionHandler && on)
|
|
sectionHandler->Del(fd);
|
|
data.Del(fd);
|
|
return;
|
|
}
|
|
}
|
|
}
|