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