vdr
1.7.27
|
00001 /* 00002 * eitscan.c: EIT scanner 00003 * 00004 * See the main source file 'vdr.c' for copyright information and 00005 * how to reach the author. 00006 * 00007 * $Id: eitscan.c 2.6 2012/03/07 13:54:34 kls Exp $ 00008 */ 00009 00010 #include "eitscan.h" 00011 #include <stdlib.h> 00012 #include "channels.h" 00013 #include "dvbdevice.h" 00014 #include "skins.h" 00015 #include "transfer.h" 00016 00017 // --- cScanData ------------------------------------------------------------- 00018 00019 class cScanData : public cListObject { 00020 private: 00021 cChannel channel; 00022 public: 00023 cScanData(const cChannel *Channel); 00024 virtual int Compare(const cListObject &ListObject) const; 00025 int Source(void) const { return channel.Source(); } 00026 int Transponder(void) const { return channel.Transponder(); } 00027 const cChannel *GetChannel(void) const { return &channel; } 00028 }; 00029 00030 cScanData::cScanData(const cChannel *Channel) 00031 { 00032 channel = *Channel; 00033 } 00034 00035 int cScanData::Compare(const cListObject &ListObject) const 00036 { 00037 const cScanData *sd = (const cScanData *)&ListObject; 00038 int r = Source() - sd->Source(); 00039 if (r == 0) 00040 r = Transponder() - sd->Transponder(); 00041 return r; 00042 } 00043 00044 // --- cScanList ------------------------------------------------------------- 00045 00046 class cScanList : public cList<cScanData> { 00047 public: 00048 void AddTransponders(cList<cChannel> *Channels); 00049 void AddTransponder(const cChannel *Channel); 00050 }; 00051 00052 void cScanList::AddTransponders(cList<cChannel> *Channels) 00053 { 00054 for (cChannel *ch = Channels->First(); ch; ch = Channels->Next(ch)) 00055 AddTransponder(ch); 00056 Sort(); 00057 } 00058 00059 void cScanList::AddTransponder(const cChannel *Channel) 00060 { 00061 if (Channel->Source() && Channel->Transponder()) { 00062 for (cScanData *sd = First(); sd; sd = Next(sd)) { 00063 if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder())) 00064 return; 00065 } 00066 Add(new cScanData(Channel)); 00067 } 00068 } 00069 00070 // --- cTransponderList ------------------------------------------------------ 00071 00072 class cTransponderList : public cList<cChannel> { 00073 public: 00074 void AddTransponder(cChannel *Channel); 00075 }; 00076 00077 void cTransponderList::AddTransponder(cChannel *Channel) 00078 { 00079 for (cChannel *ch = First(); ch; ch = Next(ch)) { 00080 if (ch->Source() == Channel->Source() && ch->Transponder() == Channel->Transponder()) { 00081 delete Channel; 00082 return; 00083 } 00084 } 00085 Add(Channel); 00086 } 00087 00088 // --- cEITScanner ----------------------------------------------------------- 00089 00090 cEITScanner EITScanner; 00091 00092 cEITScanner::cEITScanner(void) 00093 { 00094 lastScan = lastActivity = time(NULL); 00095 currentChannel = 0; 00096 scanList = NULL; 00097 transponderList = NULL; 00098 } 00099 00100 cEITScanner::~cEITScanner() 00101 { 00102 delete scanList; 00103 delete transponderList; 00104 } 00105 00106 void cEITScanner::AddTransponder(cChannel *Channel) 00107 { 00108 if (!transponderList) 00109 transponderList = new cTransponderList; 00110 transponderList->AddTransponder(Channel); 00111 } 00112 00113 void cEITScanner::ForceScan(void) 00114 { 00115 lastActivity = 0; 00116 } 00117 00118 void cEITScanner::Activity(void) 00119 { 00120 if (currentChannel) { 00121 Channels.SwitchTo(currentChannel); 00122 currentChannel = 0; 00123 } 00124 lastActivity = time(NULL); 00125 } 00126 00127 void cEITScanner::Process(void) 00128 { 00129 if (Setup.EPGScanTimeout || !lastActivity) { // !lastActivity means a scan was forced 00130 time_t now = time(NULL); 00131 if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) { 00132 if (Channels.Lock(false, 10)) { 00133 if (!scanList) { 00134 scanList = new cScanList; 00135 if (transponderList) { 00136 scanList->AddTransponders(transponderList); 00137 delete transponderList; 00138 transponderList = NULL; 00139 } 00140 scanList->AddTransponders(&Channels); 00141 } 00142 bool AnyDeviceSwitched = false; 00143 for (int i = 0; i < cDevice::NumDevices(); i++) { 00144 cDevice *Device = cDevice::GetDevice(i); 00145 if (Device && Device->ProvidesEIT()) { 00146 for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) { 00147 const cChannel *Channel = ScanData->GetChannel(); 00148 if (Channel) { 00149 if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= CA_ENCRYPTED_MIN) { 00150 if (Device->ProvidesTransponder(Channel)) { 00151 if (!Device->Receiving()) { 00152 bool MaySwitchTransponder = Device->MaySwitchTransponder(Channel); 00153 if (MaySwitchTransponder || Device->ProvidesTransponderExclusively(Channel) && now - lastActivity > Setup.EPGScanTimeout * 3600) { 00154 if (!MaySwitchTransponder) { 00155 if (Device == cDevice::ActualDevice() && !currentChannel) { 00156 cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode 00157 currentChannel = Device->CurrentChannel(); 00158 Skins.Message(mtInfo, tr("Starting EPG scan")); 00159 } 00160 } 00161 //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); 00162 Device->SwitchChannel(Channel, false); 00163 scanList->Del(ScanData); 00164 AnyDeviceSwitched = true; 00165 break; 00166 } 00167 } 00168 } 00169 } 00170 } 00171 } 00172 } 00173 } 00174 if (!scanList->Count() || !AnyDeviceSwitched) { 00175 delete scanList; 00176 scanList = NULL; 00177 if (lastActivity == 0) // this was a triggered scan 00178 Activity(); 00179 } 00180 Channels.Unlock(); 00181 } 00182 lastScan = time(NULL); 00183 } 00184 } 00185 }