@@ -219,13 +219,49 @@ public:
void SetRefChannel(cChannel *RefChannel);
};
+class cIteratorImpl {
+private:
+ int refCount;
+ cIteratorImpl(const cIteratorImpl &);
+ const cIteratorImpl &operator =(const cIteratorImpl &);
+public:
+ cIteratorImpl(void) { refCount = 0; }
+ virtual ~cIteratorImpl() {}
+ virtual int AddRef(void) { return ++refCount; }
+ virtual int DelRef(void) { int RefCount = --refCount; if (RefCount <= 0) delete this; return RefCount; }
+ virtual void *First(void) = 0;
+ virtual void *Last(void) = 0;
+ virtual void *Prev(void) = 0;
+ virtual void *Next(void) = 0;
+ virtual void *Current(void) const = 0;
+ };
+
+template <class T> class cIterator
+{
+private:
+ cIteratorImpl *impl;
+public:
+ cIterator(cIteratorImpl *Impl) { impl = Impl; impl->AddRef(); }
+ cIterator(const cIterator &rhs) { impl = rhs.impl; impl->AddRef(); }
+ ~cIterator() { impl->DelRef(); }
+ const cIterator &operator =(const cIterator &rhs) { rhs.impl->AddRef(); impl->DelRef(); impl = rhs.impl; return *this; }
+ T *First(void) const { return (T *)impl->First(); }
+ T *Last(void) const { return (T *)impl->Last(); }
+ T *Prev(void) const { return (T *)impl->Prev(); }
+ T *Next(void) const { return (T *)impl->Next(); }
+ T *Current(void) const { return (T *)impl->Current(); }
+ };
+
class cChannels : public cRwLock, public cConfig<cChannel> {
private:
int maxNumber;
int modified;
int beingEdited;
cHash<cChannel> channelsHashSid;
+ cHash<cChannel> channelsHashNidTid;
void DeleteDuplicateChannels(void);
+ void ClearChannelHashes(void);
+ static unsigned int HashKeyNidTid(unsigned short Nid, unsigned short Tid);
public:
cChannels(void);
bool Load(const char *FileName, bool AllowComments = false, bool MustExist = false);
@@ -240,6 +276,7 @@ public:
cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID);
cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false);
cChannel *GetByTransponderID(tChannelID ChannelID);
+ cIterator<cChannel> GetChannelsBySourceNidTid(int Source, unsigned short Nid, unsigned short Tid);
int BeingEdited(void) { return beingEdited; }
void IncBeingEdited(void) { beingEdited++; }
void DecBeingEdited(void) { beingEdited--; }
@@ -905,14 +905,72 @@ bool cChannels::Load(const char *FileNam
return false;
}
+void cChannels::ClearChannelHashes(void)
+{
+ channelsHashSid.Clear();
+ channelsHashNidTid.Clear();
+}
+
void cChannels::HashChannel(cChannel *Channel)
{
channelsHashSid.Add(Channel, Channel->Sid());
+ channelsHashNidTid.Add(Channel, HashKeyNidTid(Channel->Nid(), Channel->Tid()));
}
void cChannels::UnhashChannel(cChannel *Channel)
{
channelsHashSid.Del(Channel, Channel->Sid());
+ channelsHashNidTid.Del(Channel, HashKeyNidTid(Channel->Nid(), Channel->Tid()));
+}
+
+unsigned int cChannels::HashKeyNidTid(unsigned short Nid, unsigned short Tid)
+{
+ return Nid << 16 | Tid;
+}
+
+cIterator<cChannel> cChannels::GetChannelsBySourceNidTid(int Source, unsigned short Nid, unsigned short Tid)
+{
+ class cIteratorImplSourceNidTid : public cIteratorImpl {
+ private:
+ cList<cHashObject> *hashList;
+ cHashObject *current;
+ int source;
+ unsigned short nid;
+ unsigned short tid;
+ cChannel *FindMatchingChannel(bool reverse, bool reset = false) {
+ if (!hashList || (!current && !reset))
+ return NULL;
+ while (true) {
+ if (reset) {
+ reset = false;
+ current = reverse ? hashList->Last() : hashList->First();
+ }
+ else
+ current = reverse ? hashList->Prev(current) : hashList->Next(current);
+ if (!current)
+ break;
+ cChannel *Channel = (cChannel *)current->Object();
+ if (Channel->Source() == source && Channel->Nid() == nid && Channel->Tid() == tid)
+ return Channel;
+ }
+ return NULL;
+ }
+ public:
+ cIteratorImplSourceNidTid(cList<cHashObject> *HashList, int Source, unsigned short Nid, unsigned short Tid) {
+ hashList = HashList;
+ source = Source;
+ nid = Nid;
+ tid = Tid;
+ current = NULL;
+ }
+ virtual void *First(void) { return FindMatchingChannel(false, true); }
+ virtual void *Last(void) { return FindMatchingChannel(true, true); }
+ virtual void *Prev(void) { return FindMatchingChannel(false); }
+ virtual void *Next(void) { return FindMatchingChannel(true); }
+ virtual void *Current(void) const { return current ? (cChannel *)current->Object() : NULL; }
+ };
+
+ return cIterator<cChannel>(new cIteratorImplSourceNidTid(channelsHashNidTid.GetList(HashKeyNidTid(Nid, Tid)), Source, Nid, Tid));
}
int cChannels::GetNextGroup(int Idx)
@@ -949,7 +1007,7 @@ int cChannels::GetPrevNormal(int Idx)
void cChannels::ReNumber( void )
{
- channelsHashSid.Clear();
+ ClearChannelHashes();
int Number = 1;
for (cChannel *channel = First(); channel; channel = Next(channel)) {
if (channel->GroupSep()) {
@@ -142,20 +142,19 @@ void cNitFilter::Process(u_short Pid, u_
}
if (Setup.UpdateChannels >= 5) {
bool found = false;
- for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
- if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
- int transponder = Channel->Transponder();
- if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), transponder)) {
- for (int n = 0; n < NumFrequencies; n++) {
- if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), transponder)) {
- Frequency = Frequencies[n];
- break;
- }
+ cIterator<cChannel> ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId());
+ for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) {
+ int transponder = Channel->Transponder();
+ if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), transponder)) {
+ for (int n = 0; n < NumFrequencies; n++) {
+ if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), transponder)) {
+ Frequency = Frequencies[n];
+ break;
}
- }
- if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder
- Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate);
+ }
}
+ if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder
+ Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate);
found = true;
}
if (!found) {
@@ -193,20 +192,19 @@ void cNitFilter::Process(u_short Pid, u_
}
if (Setup.UpdateChannels >= 5) {
bool found = false;
- for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
- if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
- int transponder = Channel->Transponder();
- if (!ISTRANSPONDER(Frequency / 1000, transponder)) {
- for (int n = 0; n < NumFrequencies; n++) {
- if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) {
- Frequency = Frequencies[n];
- break;
- }
+ cIterator<cChannel> ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId());
+ for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) {
+ int transponder = Channel->Transponder();
+ if (!ISTRANSPONDER(Frequency / 1000, transponder)) {
+ for (int n = 0; n < NumFrequencies; n++) {
+ if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) {
+ Frequency = Frequencies[n];
+ break;
}
- }
- if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder
- Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate);
+ }
}
+ if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder
+ Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate);
found = true;
}
if (!found) {
@@ -251,20 +249,19 @@ void cNitFilter::Process(u_short Pid, u_
}
if (Setup.UpdateChannels >= 5) {
bool found = false;
- for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
- if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
- int transponder = Channel->Transponder();
- if (!ISTRANSPONDER(Frequency / 1000000, transponder)) {
- for (int n = 0; n < NumFrequencies; n++) {
- if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) {
- Frequency = Frequencies[n];
- break;
- }
+ cIterator<cChannel> ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId());
+ for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) {
+ int transponder = Channel->Transponder();
+ if (!ISTRANSPONDER(Frequency / 1000000, transponder)) {
+ for (int n = 0; n < NumFrequencies; n++) {
+ if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) {
+ Frequency = Frequencies[n];
+ break;
}
- }
- if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder
- Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode);
+ }
}
+ if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder
+ Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode);
found = true;
}
if (!found) {
@@ -276,7 +273,7 @@ void cNitFilter::Process(u_short Pid, u_
else
delete Channel;
}
- }
+ }
}
}
break;