vdr 2.6.8
eitscan.c
Go to the documentation of this file.
1/*
2 * eitscan.c: EIT scanner
3 *
4 * See the main source file 'vdr.c' for copyright information and
5 * how to reach the author.
6 *
7 * $Id: eitscan.c 5.6 2024/07/06 11:19:21 kls Exp $
8 */
9
10#include "eitscan.h"
11#include <stdlib.h>
12#include "channels.h"
13#include "dvbdevice.h"
14#include "skins.h"
15#include "transfer.h"
16
17// --- cScanData -------------------------------------------------------------
18
19class cScanData : public cListObject {
20private:
22public:
23 cScanData(const cChannel *Channel);
24 virtual int Compare(const cListObject &ListObject) const;
25 int Source(void) const { return channel.Source(); }
26 int Transponder(void) const { return channel.Transponder(); }
27 const cChannel *GetChannel(void) const { return &channel; }
28 };
29
31{
32 channel = *Channel;
33}
34
35int cScanData::Compare(const cListObject &ListObject) const
36{
37 const cScanData *sd = (const cScanData *)&ListObject;
38 int r = Source() - sd->Source();
39 if (r == 0)
40 r = Transponder() - sd->Transponder();
41 return r;
42}
43
44// --- cScanList -------------------------------------------------------------
45
46class cScanList : public cList<cScanData> {
47private:
48 bool HasDeviceForChannelEIT(const cChannel *Channel) const;
49public:
50 void AddTransponders(const cList<cChannel> *Channels);
51 void AddTransponder(const cChannel *Channel);
52 };
53
55{
56 for (int i = 0; i < cDevice::NumDevices(); i++) {
57 cDevice *Device = cDevice::GetDevice(i);
58 if (Device && Device->ProvidesEIT() && Device->ProvidesTransponder(Channel))
59 return true;
60 }
61 return false;
62}
63
65{
66 for (const cChannel *ch = Channels->First(); ch; ch = Channels->Next(ch))
68 Sort();
69}
70
72{
73 if (Channel->Source() && Channel->Transponder() && (Setup.EPGScanMaxChannel <= 0 || Channel->Number() < Setup.EPGScanMaxChannel)) {
74 if (!HasDeviceForChannelEIT(Channel))
75 return;
76 for (cScanData *sd = First(); sd; sd = Next(sd)) {
77 if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder()))
78 return;
79 }
80 Add(new cScanData(Channel));
81 }
82}
83
84// --- cTransponderList ------------------------------------------------------
85
86class cTransponderList : public cList<cChannel> {
87public:
88 void AddTransponder(cChannel *Channel);
89 };
90
92{
93 for (cChannel *ch = First(); ch; ch = Next(ch)) {
94 if (ch->Source() == Channel->Source() && ch->Transponder() == Channel->Transponder()) {
95 delete Channel;
96 return;
97 }
98 }
99 Add(Channel);
100}
101
102// --- cEITScanner -----------------------------------------------------------
103
105
107{
108 paused = false;
109 lastScan = 0;
110 lastActivity = time(NULL);
111 currentChannel = 0;
112 scanList = new cScanList;
113 transponderList = NULL;
114}
115
117{
118 delete scanList;
119 delete transponderList;
120}
121
128
130{
131 lastActivity = 0;
132}
133
135{
136 if (currentChannel) {
138 Channels->SwitchTo(currentChannel);
139 currentChannel = 0;
140 }
141 lastActivity = time(NULL);
142}
143
145{
146 if (Setup.EPGScanTimeout || !lastActivity) { // !lastActivity means a scan was forced
147 time_t now = time(NULL);
148 if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) {
149 if (Setup.EPGPauseAfterScan && scanList->Count() == 0 && lastActivity && lastScan && now - lastScan < Setup.EPGScanTimeout * 3600) {
150 if (!paused) {
151 dsyslog("pause EPG scan");
152 paused = true;
153 }
154 // Allow unused devices to go into power save mode:
155 for (int i = 0; i < cDevice::NumDevices(); i++) {
156 if (cDevice *Device = cDevice::GetDevice(i))
157 Device->SetPowerSaveIfUnused();
158 }
159 lastScan = time(NULL); // let's not do this too often
160 return; // pause for Setup.EPGScanTimeout hours
161 }
162 else if (paused) {
163 dsyslog("start EPG scan");
164 paused = false;
165 }
166 cStateKey StateKey;
167 if (const cChannels *Channels = cChannels::GetChannelsRead(StateKey, 10)) {
168 if (scanList->Count() == 0) {
169 if (transponderList) {
171 delete transponderList;
172 transponderList = NULL;
173 }
174 scanList->AddTransponders(Channels);
175 //dsyslog("EIT scan: %d scanList entries", scanList->Count());
176 }
177 for (int i = 0; i < cDevice::NumDevices(); i++) {
178 cDevice *Device = cDevice::GetDevice(i);
179 if (Device && Device->ProvidesEIT()) {
180 cScanData *Next = NULL;
181 for (cScanData *ScanData = scanList->First(); ScanData; ScanData = Next) {
182 Next = scanList->Next(ScanData);
183 const cChannel *Channel = ScanData->GetChannel();
184 if (Channel) {
185 if (Device->IsTunedToTransponder(Channel))
186 scanList->Del(ScanData);
187 else if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= CA_ENCRYPTED_MIN) {
188 if (Device->ProvidesTransponder(Channel)) {
189 if (Device->Priority() < 0) {
190 if (const cPositioner *Positioner = Device->Positioner()) {
191 if (Positioner->LastLongitude() != cSource::Position(Channel->Source()))
192 continue;
193 }
194 bool MaySwitchTransponder = Device->MaySwitchTransponder(Channel);
195 if (MaySwitchTransponder || Device->ProvidesTransponderExclusively(Channel) && now - lastActivity > Setup.EPGScanTimeout * 3600) {
196 if (!MaySwitchTransponder) {
197 if (Device == cDevice::ActualDevice() && !currentChannel) {
198 cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
199 currentChannel = Device->CurrentChannel();
200 Skins.Message(mtInfo, tr("Starting EPG scan"));
201 }
202 }
203 //dsyslog("EIT scan: %d device %d source %-8s tp %5d", scanList->Count(), Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
204 Device->SwitchChannel(Channel, false);
205 scanList->Del(ScanData);
206 break;
207 }
208 }
209 }
210 }
211 }
212 }
213 }
214 }
215 if (scanList->Count() == 0) {
216 if (lastActivity == 0) // this was a triggered scan
217 Activity();
218 }
219 StateKey.Remove();
220 }
221 lastScan = time(NULL);
222 }
223 }
224}
#define CA_ENCRYPTED_MIN
Definition channels.h:44
#define LOCK_CHANNELS_READ
Definition channels.h:270
#define ISTRANSPONDER(f1, f2)
Definition channels.h:18
int Source(void) const
Definition channels.h:152
int Number(void) const
Definition channels.h:179
int Ca(int Index=0) const
Definition channels.h:173
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition channels.c:154
static const cChannels * GetChannelsRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for read access.
Definition channels.c:856
int Priority(bool IgnoreOccupied=false) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY),...
Definition device.c:1695
virtual const cPositioner * Positioner(void) const
Returns a pointer to the positioner (if any) this device has used to move the satellite dish to the r...
Definition device.c:780
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise.
Definition device.c:222
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition device.h:148
virtual bool MaySwitchTransponder(const cChannel *Channel) const
Returns true if it is ok to switch to the Channel's transponder on this device, without disturbing an...
Definition device.c:810
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition device.c:230
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
Definition device.c:825
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition device.c:167
virtual bool ProvidesEIT(void) const
Returns true if this device provides EIT data and thus wants to be tuned to the channels it can recei...
Definition device.c:770
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
Definition device.h:371
void StopReplay(void)
Stops the current replay session (if any).
Definition device.c:1421
virtual bool ProvidesTransponderExclusively(const cChannel *Channel) const
Returns true if this is the only device that is able to provide the given channel's transponder.
Definition device.c:756
static int NumDevices(void)
Returns the total number of devices.
Definition device.h:129
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel's transponder.
Definition device.c:805
virtual bool ProvidesTransponder(const cChannel *Channel) const
Returns true if this device can provide the transponder of the given Channel (which implies that it c...
Definition device.c:751
int currentChannel
Definition eitscan.h:28
cEITScanner(void)
Definition eitscan.c:106
void AddTransponder(cChannel *Channel)
Definition eitscan.c:122
@ ScanTimeout
Definition eitscan.h:24
@ ActivityTimeout
Definition eitscan.h:23
bool paused
Definition eitscan.h:26
void ForceScan(void)
Definition eitscan.c:129
void Process(void)
Definition eitscan.c:144
cScanList * scanList
Definition eitscan.h:29
time_t lastActivity
Definition eitscan.h:27
cTransponderList * transponderList
Definition eitscan.h:30
void Activity(void)
Definition eitscan.c:134
time_t lastScan
Definition eitscan.h:27
void Del(cListObject *Object, bool DeleteObject=true)
Definition tools.c:2251
int Count(void) const
Definition tools.h:640
void Add(cListObject *Object, cListObject *After=NULL)
Definition tools.c:2219
void Sort(void)
Definition tools.c:2343
Definition tools.h:644
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
Definition tools.h:656
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
Definition tools.h:663
A steerable satellite dish generally points to the south on the northern hemisphere,...
Definition positioner.h:31
int Transponder(void) const
Definition eitscan.c:26
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater",...
Definition eitscan.c:35
int Source(void) const
Definition eitscan.c:25
const cChannel * GetChannel(void) const
Definition eitscan.c:27
cChannel channel
Definition eitscan.c:21
cScanData(const cChannel *Channel)
Definition eitscan.c:30
bool HasDeviceForChannelEIT(const cChannel *Channel) const
Definition eitscan.c:54
void AddTransponder(const cChannel *Channel)
Definition eitscan.c:71
void AddTransponders(const cList< cChannel > *Channels)
Definition eitscan.c:64
int EPGPauseAfterScan
Definition config.h:299
int EPGScanMaxChannel
Definition config.h:298
int EPGScanTimeout
Definition config.h:300
eKeys Message(eMessageType Type, const char *s, int Seconds=0)
Displays the given message, either through a currently visible display object that is capable of doin...
Definition skins.c:250
int Position(void)
Returns the orbital position of the satellite in case this is a DVB-S source (zero otherwise).
Definition sources.h:35
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
Definition thread.c:867
void AddTransponder(cChannel *Channel)
Definition eitscan.c:91
cSetup Setup
Definition config.c:372
cEITScanner EITScanner
Definition eitscan.c:104
#define tr(s)
Definition i18n.h:85
cSkins Skins
Definition skins.c:219
@ mtInfo
Definition skins.h:37
#define dsyslog(a...)
Definition tools.h:37