use celementtree to parse config,
[enigma2-plugins.git] / epgrefresh / src / EPGRefresh.py
1 # To check if in Standby
2 import Screens.Standby
3
4 # eServiceReference
5 from enigma import eServiceReference, eServiceCenter
6
7 # ...
8 from ServiceReference import ServiceReference
9
10 # Timer
11 from EPGRefreshTimer import epgrefreshtimer, EPGRefreshTimerEntry, checkTimespan
12
13 # To calculate next timer execution
14 from time import time
15
16 # Plugin Config
17 from xml.etree.cElementTree import parse as cet_parse
18 from os import path as path
19
20 # We want a list of unique services
21 from sets import Set
22
23 # Configuration
24 from Components.config import config
25
26 # Path to configuration
27 CONFIG = "/etc/enigma2/epgrefresh.xml"
28
29 class EPGRefresh:
30         """Simple Class to refresh EPGData"""
31
32         def __init__(self):
33                 # Initialize 
34                 self.services = (Set(), Set())
35                 self.previousService = None
36                 self.forcedScan = False
37                 self.session = None
38                 self.beginOfTimespan = 0
39
40                 # Mtime of configuration files
41                 self.configMtime = -1
42
43                 # Read in Configuration
44                 self.readConfiguration()
45
46         def readConfiguration(self):
47                 # Check if file exists
48                 if not path.exists(CONFIG):
49                         return
50
51                 # Check if file did not change
52                 mtime = path.getmtime(CONFIG)
53                 if mtime == self.configMtime:
54                         return
55
56                 # Keep mtime
57                 self.configMtime = mtime
58
59                 # Empty out list
60                 self.services[0].clear()
61                 self.services[1].clear()
62
63                 # Open file
64                 configuration= cet_parse(CONFIG).getroot()
65
66                 # Add References
67                 for service in configuration.findall("service"):
68                         value = service.text
69                         if value:
70                                 # strip all after last : (custom name)
71                                 pos = value.rfind(':')
72                                 if pos != -1:
73                                         value = value[:pos+1]
74
75                                 self.services[0].add(value)
76                 for bouquet in configuration.findall("bouquet"):
77                         value = bouquet.text
78                         if value:
79                                 self.services[1].add(value)
80
81         def saveConfiguration(self):
82                 # Generate List in RAM
83                 list = ['<?xml version="1.0" ?>\n<epgrefresh>\n\n']
84
85                 for service in self.services[0]:
86                         ref = ServiceReference(str(service))
87                         list.extend([' <!-- ', ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''), ' -->\n'])
88                         list.extend([' <service>', service, '</service>\n'])
89                 for bouquet in self.services[1]:
90                         ref = ServiceReference(str(bouquet))
91                         list.extend([' <!-- ', ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''), ' -->\n'])
92                         list.extend([' <bouquet>', bouquet, '</bouquet>\n'])
93
94                 list.append('\n</epgrefresh>')
95
96                 # Save to Flash
97                 file = open(CONFIG, 'w')
98                 file.writelines(list)
99
100                 file.close()
101
102         def forceRefresh(self, session = None):
103                 print "[EPGRefresh] Forcing start of EPGRefresh"
104                 if session is not None:
105                         self.session = session
106
107                 self.forcedScan = True
108                 self.prepareRefresh()
109
110         def start(self, session = None):
111                 if session is not None:
112                         self.session = session
113
114                 epgrefreshtimer.setRefreshTimer(self.createWaitTimer)
115
116         def stop(self):
117                 print "[EPGRefresh] Stopping Timer"
118                 epgrefreshtimer.clear()
119
120         def prepareRefresh(self):
121                 print "[EPGRefresh] About to start refreshing EPG"
122
123                 # Keep service
124                 self.previousService =  self.session.nav.getCurrentlyPlayingServiceReference()
125
126                 # Maybe read in configuration
127                 try:
128                         self.readConfiguration()
129                 except Exception, e:
130                         print "[EPGRefresh] Error occured while reading in configuration:", e
131
132                 # Save Services in a dict <transponder data> => serviceref
133                 self.scanServices = []
134                 channelIdList = []
135
136                 # This will hold services which are not explicitely in our list
137                 additionalServices = []
138                 additionalBouquets = []
139
140                 # See if we are supposed to read in autotimer services
141                 if config.plugins.epgrefresh.inherit_autotimer.value:
142                         try:
143                                 # Import Instance
144                                 from Plugins.Extensions.AutoTimer.plugin import autotimer
145
146                                 # See if instance is empty
147                                 removeInstance = False
148                                 if autotimer is None:
149                                         removeInstance = True
150                                         # Create an instance
151                                         from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
152                                         autotimer = AutoTimer()
153
154                                 # Read in configuration
155                                 autotimer.readXml()
156
157                                 # Fetch services
158                                 for timer in autotimer.getEnabledTimerList():
159                                         additionalServices.extend(timer.getServices())
160                                         additionalBouquets.extend(timer.getBouquets())
161
162                                 # Remove instance if there wasn't one before
163                                 # we might go into the exception before we reach this line, but we don't care then...
164                                 if removeInstance:
165                                         autotimer = None
166
167                         except Exception, e:
168                                 print "[EPGRefresh] Could not inherit AutoTimer Services:", e
169
170                 serviceHandler = eServiceCenter.getInstance()
171                 for bouquet in self.services[1].union(additionalBouquets):
172                         myref = eServiceReference(str(bouquet))
173                         list = serviceHandler.list(myref)
174                         if list is not None:
175                                 while 1:
176                                         s = list.getNext()
177                                         # TODO: I wonder if its sane to assume we get services here (and not just new lists)
178                                         if s.valid():
179                                                 additionalServices.append(s.toString())
180                                         else:
181                                                 break
182
183                 for serviceref in self.services[0].union(additionalServices):
184                         service = eServiceReference(str(serviceref))
185                         if not service.valid() \
186                                 or (service.flags & (eServiceReference.isMarker|eServiceReference.isDirectory)):
187                                 
188                                 continue
189
190                         channelID = '%08x%04x%04x' % (
191                                 service.getUnsignedData(4), # NAMESPACE
192                                 service.getUnsignedData(2), # TSID
193                                 service.getUnsignedData(3), # ONID
194                         )
195
196                         if channelID not in channelIdList:
197                                 self.scanServices.append(service)
198                                 channelIdList.append(channelID)
199
200                 # Debug
201                 print "[EPGRefresh] Services we're going to scan:", ', '.join([ServiceReference(x).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '') for x in self.scanServices])
202
203                 self.refresh()
204
205         def cleanUp(self):
206                 config.plugins.epgrefresh.lastscan.value = int(time())
207                 config.plugins.epgrefresh.lastscan.save()
208
209                 # shutdown if we're supposed to go to deepstandby and not recording
210                 if not self.forcedScan and config.plugins.epgrefresh.afterevent.value \
211                         and not Screens.Standby.inTryQuitMainloop:
212
213                         self.session.open(
214                                 Screens.Standby.TryQuitMainloop,
215                                 1
216                         )
217
218                 self.forcedScan = False
219                 epgrefreshtimer.cleanup()
220
221                 # Zap back
222                 if self.previousService is not None or Screens.Standby.inStandby:
223                         self.session.nav.playService(self.previousService)
224
225         def refresh(self):
226                 if self.forcedScan:
227                         self.nextService()
228                 else:
229                         # Abort if a scan finished later than our begin of timespan
230                         if self.beginOfTimespan < config.plugins.epgrefresh.lastscan.value:
231                                 return
232                         if config.plugins.epgrefresh.force.value \
233                                 or (Screens.Standby.inStandby and \
234                                         not self.session.nav.RecordTimer.isRecording()):
235
236                                 self.nextService()
237                         # We don't follow our rules here - If the Box is still in Standby and not recording we won't reach this line 
238                         else:
239                                 if not checkTimespan(
240                                         config.plugins.epgrefresh.begin.value,
241                                         config.plugins.epgrefresh.end.value):
242
243                                         print "[EPGRefresh] Gone out of timespan while refreshing, sorry!"
244                                         self.cleanUp()
245                                 else:
246                                         print "[EPGRefresh] Box no longer in Standby or Recording started, rescheduling"
247
248                                         # Recheck later
249                                         epgrefreshtimer.add(EPGRefreshTimerEntry(
250                                                         time() + config.plugins.epgrefresh.delay_standby.value*60,
251                                                         self.refresh,
252                                                         nocheck = True)
253                                         )
254
255         def createWaitTimer(self):
256                 self.beginOfTimespan = time()
257
258                 # Add wait timer to epgrefreshtimer
259                 epgrefreshtimer.add(EPGRefreshTimerEntry(time() + 30, self.prepareRefresh))
260
261         def nextService(self):
262                 # DEBUG
263                 print "[EPGRefresh] Maybe zap to next service"
264
265                 try:
266                         # Get next reference
267                         service = self.scanServices.pop(0)
268
269                         # Play next service
270                         self.session.nav.playService(service)
271
272                         # Start Timer
273                         epgrefreshtimer.add(EPGRefreshTimerEntry(
274                                 time() + config.plugins.epgrefresh.interval.value*60,
275                                 self.refresh,
276                                 nocheck = True)
277                         )
278                 except IndexError:
279                         # Debug
280                         print "[EPGRefresh] Done refreshing EPG"
281
282                         # Clean up
283                         self.cleanUp()
284
285 epgrefresh = EPGRefresh()