vdr  2.2.0
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 3.0 2012/04/07 14:39:28 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 
19 class cScanData : public cListObject {
20 private:
22 public:
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 
35 int 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 
46 class cScanList : public cList<cScanData> {
47 public:
48  void AddTransponders(cList<cChannel> *Channels);
49  void AddTransponder(const cChannel *Channel);
50  };
51 
53 {
54  for (cChannel *ch = Channels->First(); ch; ch = Channels->Next(ch))
55  AddTransponder(ch);
56  Sort();
57 }
58 
59 void cScanList::AddTransponder(const cChannel *Channel)
60 {
61  if (Channel->Source() && Channel->Transponder()) {
62  for (cScanData *sd = First(); sd; sd = Next(sd)) {
63  if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder()))
64  return;
65  }
66  Add(new cScanData(Channel));
67  }
68 }
69 
70 // --- cTransponderList ------------------------------------------------------
71 
72 class cTransponderList : public cList<cChannel> {
73 public:
74  void AddTransponder(cChannel *Channel);
75  };
76 
78 {
79  for (cChannel *ch = First(); ch; ch = Next(ch)) {
80  if (ch->Source() == Channel->Source() && ch->Transponder() == Channel->Transponder()) {
81  delete Channel;
82  return;
83  }
84  }
85  Add(Channel);
86 }
87 
88 // --- cEITScanner -----------------------------------------------------------
89 
91 
93 {
94  lastScan = lastActivity = time(NULL);
95  currentChannel = 0;
96  scanList = NULL;
97  transponderList = NULL;
98 }
99 
101 {
102  delete scanList;
103  delete transponderList;
104 }
105 
107 {
108  if (!transponderList)
109  transponderList = new cTransponderList;
110  transponderList->AddTransponder(Channel);
111 }
112 
114 {
115  lastActivity = 0;
116 }
117 
119 {
120  if (currentChannel) {
121  Channels.SwitchTo(currentChannel);
122  currentChannel = 0;
123  }
124  lastActivity = time(NULL);
125 }
126 
128 {
129  if (Setup.EPGScanTimeout || !lastActivity) { // !lastActivity means a scan was forced
130  time_t now = time(NULL);
131  if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) {
132  if (Channels.Lock(false, 10)) {
133  if (!scanList) {
134  scanList = new cScanList;
135  if (transponderList) {
136  scanList->AddTransponders(transponderList);
137  delete transponderList;
138  transponderList = NULL;
139  }
140  scanList->AddTransponders(&Channels);
141  }
142  bool AnyDeviceSwitched = false;
143  for (int i = 0; i < cDevice::NumDevices(); i++) {
144  cDevice *Device = cDevice::GetDevice(i);
145  if (Device && Device->ProvidesEIT()) {
146  for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) {
147  const cChannel *Channel = ScanData->GetChannel();
148  if (Channel) {
149  if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= CA_ENCRYPTED_MIN) {
150  if (Device->ProvidesTransponder(Channel)) {
151  if (Device->Priority() < 0) {
152  bool MaySwitchTransponder = Device->MaySwitchTransponder(Channel);
153  if (MaySwitchTransponder || Device->ProvidesTransponderExclusively(Channel) && now - lastActivity > Setup.EPGScanTimeout * 3600) {
154  if (!MaySwitchTransponder) {
155  if (Device == cDevice::ActualDevice() && !currentChannel) {
156  cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
157  currentChannel = Device->CurrentChannel();
158  Skins.Message(mtInfo, tr("Starting EPG scan"));
159  }
160  }
161  //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
162  Device->SwitchChannel(Channel, false);
163  scanList->Del(ScanData);
164  AnyDeviceSwitched = true;
165  break;
166  }
167  }
168  }
169  }
170  }
171  }
172  }
173  }
174  if (!scanList->Count() || !AnyDeviceSwitched) {
175  delete scanList;
176  scanList = NULL;
177  if (lastActivity == 0) // this was a triggered scan
178  Activity();
179  }
180  Channels.Unlock();
181  }
182  lastScan = time(NULL);
183  }
184  }
185 }
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:161
int Transponder(void) const
Definition: eitscan.c:26
cChannels Channels
Definition: channels.c:864
#define CA_ENCRYPTED_MIN
Definition: channels.h:49
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:657
int Source(void) const
Definition: eitscan.c:25
cEITScanner EITScanner
Definition: eitscan.c:90
int Ca(int Index=0) const
Definition: channels.h:191
~cEITScanner()
Definition: eitscan.c:100
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition: device.c:223
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater", and a negative value if it is "smaller".
Definition: eitscan.c:35
Definition: tools.h:489
void AddTransponders(cList< cChannel > *Channels)
Definition: eitscan.c:52
static int NumDevices(void)
Returns the total number of devices.
Definition: device.h:118
void ForceScan(void)
Definition: eitscan.c:113
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:158
cScanData(const cChannel *Channel)
Definition: eitscan.c:30
void Unlock(void)
Definition: thread.c:170
virtual bool MaySwitchTransponder(const cChannel *Channel) const
Returns true if it is ok to switch to the Channel&#39;s transponder on this device, without disturbing an...
Definition: device.c:692
const cChannel * GetChannel(void) const
Definition: eitscan.c:27
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
Definition: device.h:323
void AddTransponder(const cChannel *Channel)
Definition: eitscan.c:59
T * Next(const T *object) const
Definition: tools.h:495
void Activity(void)
Definition: eitscan.c:118
int Source(void) const
Definition: channels.h:168
#define ISTRANSPONDER(f1, f2)
Definition: channels.h:18
cListObject * Next(void) const
Definition: tools.h:468
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
Definition: device.c:697
void Process(void)
Definition: eitscan.c:127
Definition: skins.h:24
int EPGScanTimeout
Definition: config.h:293
cSetup Setup
Definition: config.c:373
bool Lock(bool Write, int TimeoutMs=0)
Definition: thread.c:155
cChannel channel
Definition: eitscan.c:21
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:638
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 Priority(void) const
Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY), or IDLEPRIORITY if no receiver is currently active.
Definition: device.c:1564
cEITScanner(void)
Definition: eitscan.c:92
T * First(void) const
Definition: tools.h:492
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:137
void StopReplay(void)
Stops the current replay session (if any).
Definition: device.c:1265
#define tr(s)
Definition: i18n.h:85
virtual bool ProvidesTransponderExclusively(const cChannel *Channel) const
Returns true if this is the only device that is able to provide the given channel&#39;s transponder...
Definition: device.c:643
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise...
Definition: device.c:215
bool SwitchTo(int Number)
Definition: channels.c:1074
void AddTransponder(cChannel *Channel)
Definition: eitscan.c:106
void AddTransponder(cChannel *Channel)
Definition: eitscan.c:77
The cDevice class is the base from which actual devices can be derived.
Definition: device.h:109
cSkins Skins
Definition: skins.c:219