EPGRefresh:
[enigma2-plugins.git] / epgrefresh / src / EPGRefresh.py
1 # -*- coding: UTF-8 -*-
2 from __future__ import print_function
3
4 # To check if in Standby
5 import Screens.Standby
6
7 # eServiceReference
8 from enigma import eServiceReference, eServiceCenter, eEPGCache, cachestate
9
10 # ...
11 from ServiceReference import ServiceReference
12
13 from RecordTimer import RecordTimerEntry
14 from Components.ParentalControl import parentalControl
15
16 # Timer
17 from EPGRefreshTimer import epgrefreshtimer, EPGRefreshTimerEntry, checkTimespan
18
19 # To calculate next timer execution
20 from time import time
21
22 # Error-print
23 from traceback import print_exc
24 from sys import stdout
25
26 # Plugin Config
27 from xml.etree.cElementTree import parse as cet_parse
28 from Tools.XMLTools import stringToXML
29 from os import path as path
30
31 # We want a list of unique services
32 from EPGRefreshService import EPGRefreshService
33
34 from OrderedSet import OrderedSet
35
36 # Configuration
37 from Components.config import config
38
39 # MessageBox
40 from Screens.MessageBox import MessageBox
41 from Tools import Notifications
42 from Tools.BoundFunction import boundFunction
43
44 # ... II
45 from . import ENDNOTIFICATIONID, NOTIFICATIONDOMAIN
46 from MainPictureAdapter import MainPictureAdapter
47 from PipAdapter import PipAdapter
48 from RecordAdapter import RecordAdapter
49
50 # timeout timer for eEPGCache-signal based refresh
51 from enigma import eTimer
52 from enigma import eDVBSatelliteEquipmentControl
53
54 # Path to configuration
55 CONFIG = "/etc/enigma2/epgrefresh.xml"
56 XML_VERSION = "1"
57
58 class EPGRefresh:
59         """Simple Class to refresh EPGData"""
60
61         def __init__(self):
62                 # Initialize
63                 self.services = (OrderedSet(), OrderedSet())
64                 self.currentServiceRef = None
65                 self.forcedScan = False
66                 self.isrunning = False
67                 self.doStopRunningRefresh = False
68                 self.session = None
69                 self.beginOfTimespan = 0
70                 self.refreshAdapter = None
71                 # to call additional tasks (from other plugins)
72                 self.finishNotifiers = { }
73
74                 # Mtime of configuration files
75                 self.configMtime = -1
76                 
77                 # Todos after finish
78                 self._initFinishTodos()
79
80                 # Read in Configuration
81                 self.readConfiguration()
82
83                 # Initialise myEpgCacheInstance
84                 self.myEpgCacheInstance = None
85
86                 # timeout timer for eEPGCache-signal based refresh
87                 self.epgTimeoutTimer = eTimer()
88                 self.epgTimeoutTimer_conn = self.epgTimeoutTimer.timeout.connect(self.epgTimeout)
89                 
90                 # set state for pending services message box
91                 self.showPendingServicesMessageShown = False            
92
93         def epgTimeout(self):
94                 if eDVBSatelliteEquipmentControl.getInstance().isRotorMoving():
95                         # rotor is moving, timeout raised too early...check again in 5 seconds
96                         self.epgTimeoutTimer.start(5000, True)
97                 else:
98                         # epgcache-signal is not responding...maybe service/transponder is already running or cache was already updated...? step to next entry
99                         print("[EPGRefresh] - finished channel without epg update. Reason: epgTimeout")
100                         epgrefreshtimer.add(EPGRefreshTimerEntry(
101                                         time(),
102                                         self.refresh,
103                                         nocheck = True)
104                         )
105                         
106         # _onCacheStateChanged is called whenever an eEPGCache-signal is sent by enigma2
107         #  0 = started, 1 = stopped, 2 = aborted, 3 = deferred, 4 = load_finished, 5 = save_finished
108         def _onCacheStateChanged(self, cState):
109                 sref = self.currentServiceRef
110                 if sref is None:
111                         print("[EPGRefresh] - got EPG message but no epgrefresh running... ignore")
112                         return
113
114                 if cState.state in (cachestate.load_finished, cachestate.save_finished, cachestate.aborted):
115                         print("[EPGRefresh] - assuming the state is not relevant for EPGRefresh. State:" + str(cState.state))
116                         return
117
118                 sdata = sref.getUnsignedData
119                 tsid = sdata(2)
120                 onid = sdata(3)
121                 ns = sdata(4)
122
123                 if cState.tsid != tsid or cState.onid != onid or cState.dvbnamespace != ns:
124                         print("[EPGRefresh] - ignored EPG message for wrong transponder %04x:%04x:%08x <> %04x:%04x:%08x" %(cState.tsid, cState.onid, cState.dvbnamespace, tsid, onid, ns))
125                         return
126
127                 print("[EPGRefresh] - state is:" + str(cState.state))
128
129                 self.epgTimeoutTimer.stop()
130                 if cState.state == cachestate.started:
131                         print("[EPGRefresh] - EPG update started for transponder %04x:%04x:%08x" %(tsid, onid, ns))
132                 elif cState.state == cachestate.stopped or cState.state == cachestate.deferred:
133                         print("[EPGRefresh] - EPG update finished for transponder %04x:%04x:%08x" %(tsid, onid, ns))
134
135                         if self.refreshAdapter:
136                                 self.refreshAdapter.stop()
137
138                         epgrefreshtimer.add(EPGRefreshTimerEntry(
139                                         time(),
140                                         self.refresh,
141                                         nocheck = True)
142                         )
143
144         def _initFinishTodos(self):
145                 self.finishTodos = [self._ToDoCallAutotimer, self._ToDoAutotimerCalled, self._callFinishNotifiers, self.finish]
146         
147         def addFinishNotifier(self, notifier):
148                 if not callable(notifier):
149                         print("[EPGRefresh] notifier" + str(notifier) + " isn't callable")
150                         return
151                 self.finishNotifiers[str(notifier)] = notifier
152
153         def removeFinishNotifier(self, notifier):
154                 notifierKey = str(notifier)
155                 if self.finishNotifiers.has_key(notifierKey):
156                         self.finishNotifiers.pop(notifierKey)
157
158         def readConfiguration(self):
159                 # Check if file exists
160                 if not path.exists(CONFIG):
161                         return
162
163                 # Check if file did not change
164                 mtime = path.getmtime(CONFIG)
165                 if mtime == self.configMtime:
166                         return
167
168                 # Keep mtime
169                 self.configMtime = mtime
170
171                 # Empty out list
172                 self.services[0].clear()
173                 self.services[1].clear()
174
175                 # Open file
176                 configuration = cet_parse(CONFIG).getroot()
177                 version = configuration.get("version", None)
178                 if version is None:
179                         factor = 60
180                 else: #if version == "1"
181                         factor = 1
182
183                 # Add References
184                 for service in configuration.findall("service"):
185                         value = service.text
186                         if value:
187                                 # strip all after last : (custom name)
188                                 pos = value.rfind(':')
189                                 # don't split alternative service
190                                 if pos != -1 and not value.startswith('1:134:'):
191                                         value = value[:pos+1]
192
193                                 duration = service.get('duration', None)
194                                 duration = duration and int(duration)*factor
195
196                                 self.services[0].add(EPGRefreshService(value, duration))
197                 for bouquet in configuration.findall("bouquet"):
198                         value = bouquet.text
199                         if value:
200                                 duration = bouquet.get('duration', None)
201                                 duration = duration and int(duration)
202                                 self.services[1].add(EPGRefreshService(value, duration))
203
204         def buildConfiguration(self, webif = False):
205                 list = ['<?xml version="1.0" ?>\n<epgrefresh version="', XML_VERSION, '">\n\n']
206
207                 if webif:
208                         for serviceref in self.services[0].union(self.services[1]):
209                                 ref = ServiceReference(str(serviceref))
210                                 list.extend((
211                                         ' <e2service>\n',
212                                         '  <e2servicereference>', str(serviceref), '</e2servicereference>\n',
213                                         '  <e2servicename>', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '</e2servicename>\n',
214                                         ' </e2service>\n',
215                                 ))
216                 else:
217                         for service in self.services[0]:
218                                 ref = ServiceReference(service.sref)
219                                 list.extend((' <!--', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '-->\n', ' <service'))
220                                 if service.duration is not None:
221                                         list.extend((' duration="', str(service.duration), '"'))
222                                 list.extend(('>', stringToXML(service.sref), '</service>\n'))
223                         for bouquet in self.services[1]:
224                                 ref = ServiceReference(bouquet.sref)
225                                 list.extend((' <!--', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '-->\n', ' <bouquet'))
226                                 if bouquet.duration is not None:
227                                         list.extend((' duration="', str(bouquet.duration), '"'))
228                                 list.extend(('>', stringToXML(bouquet.sref), '</bouquet>\n'))
229
230                 list.append('\n</epgrefresh>')
231
232                 return list
233
234         def saveConfiguration(self):
235                 file = open(CONFIG, 'w')
236                 file.writelines(self.buildConfiguration())
237
238                 file.close()
239
240         def maybeStopAdapter(self):
241                 if self.refreshAdapter:
242                         self.refreshAdapter.stop()
243                         self.refreshAdapter = None
244
245         def forceRefresh(self, session = None):
246                 print("[EPGRefresh] Forcing start of EPGRefresh")
247                 if self.session is None:
248                         if session is not None:
249                                 self.session = session
250                         else:
251                                 return False
252
253                 self.forcedScan = True
254                 self.prepareRefresh()
255                 return True
256         
257         def stopRunningRefresh(self, session = None):
258                 print("[EPGRefresh] Forcing stop of EPGRefresh")
259                 if self.session is None:
260                         if session is not None:
261                                 self.session = session
262                         else:
263                                 return False
264                 self.doStopRunningRefresh = True
265                 # stopping the refresh only has an effect when nextService() is still called which is not necessarily happening when signal-based method is used. So, just call it
266                 if config.plugins.epgrefresh.usetimebased.value == False:
267                         self.nextService()
268
269         def start(self, session = None):
270                 if session is not None:
271                         self.session = session
272
273                 epgrefreshtimer.setRefreshTimer(self.createWaitTimer)
274
275         def stop(self):
276                 print("[EPGRefresh] Stopping Timer")
277                 self.maybeStopAdapter()
278                 epgrefreshtimer.clear()
279
280         def addServices(self, fromList, toList, channelIds):
281                 for scanservice in fromList:
282                         service = eServiceReference(scanservice.sref)
283                         if not service.valid() \
284                                 or (service.flags & (eServiceReference.isMarker|eServiceReference.isDirectory)):
285
286                                 continue
287
288                         channelID = '%08x%04x%04x' % (
289                                 service.getUnsignedData(4), # NAMESPACE
290                                 service.getUnsignedData(2), # TSID
291                                 service.getUnsignedData(3), # ONID
292                         )
293
294                         if channelID not in channelIds:
295                                 toList.append(scanservice)
296                                 channelIds.append(channelID)
297
298         def generateServicelist(self, services, bouquets):
299                 # This will hold services which are not explicitely in our list
300                 additionalServices = []
301                 additionalBouquets = []
302
303                 # See if we are supposed to read in autotimer services
304                 if config.plugins.epgrefresh.inherit_autotimer.value:
305                         try:
306                                 # Import Instance
307                                 from Plugins.Extensions.AutoTimer.plugin import autotimer
308
309                                 if autotimer is None:
310                                         # Create an instance
311                                         from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
312                                         autotimer = AutoTimer()
313
314                                 # Read in configuration
315                                 autotimer.readXml()
316                         except Exception as e:
317                                 print("[EPGRefresh] Could not inherit AutoTimer Services:", e)
318                         else:
319                                 # Fetch services
320                                 for timer in autotimer.getEnabledTimerList():
321                                         additionalServices.extend([EPGRefreshService(x, None) for x in timer.services])
322                                         additionalBouquets.extend([EPGRefreshService(x, None) for x in timer.bouquets])
323
324                 scanServices = []
325                 channelIdList = []
326                 self.addServices(services, scanServices, channelIdList)
327
328                 serviceHandler = eServiceCenter.getInstance()
329                 for bouquet in bouquets.union(additionalBouquets):
330                         myref = eServiceReference(bouquet.sref)
331                         list = serviceHandler.list(myref)
332                         if list is not None:
333                                 while 1:
334                                         s = list.getNext()
335                                         # TODO: I wonder if its sane to assume we get services here (and not just new lists)
336                                         if s.valid():
337                                                 additionalServices.append(EPGRefreshService(s.toString(), None))
338                                         else:
339                                                 break
340                 del additionalBouquets[:]
341
342                 self.addServices(additionalServices, scanServices, channelIdList)
343                 del additionalServices[:]
344
345                 return scanServices
346
347         def isRunning(self):
348                 return self.isrunning
349         
350         def isRefreshAllowed(self):
351                 if self.isRunning():
352                         message = _("There is still a refresh running. The Operation isn't allowed at this moment.")
353                         try:
354                                 if self.session != None:
355                                         self.session.open(MessageBox, message, \
356                                                  MessageBox.TYPE_INFO, timeout=10)
357                         except:
358                                 print("[EPGRefresh] Error while opening Messagebox!")
359                                 print_exc(file=stdout)
360                                 Notifications.AddPopup(message, MessageBox.TYPE_INFO, 10, domain = NOTIFICATIONDOMAIN)
361                         return False
362                 return True
363
364         def prepareRefresh(self):
365                 if not self.isRefreshAllowed():
366                         return
367                 self.isrunning = True
368                 print("[EPGRefresh] About to start refreshing EPG")
369
370                 self._initFinishTodos()
371                 # Maybe read in configuration
372                 try:
373                         self.readConfiguration()
374                 except Exception as e:
375                         print("[EPGRefresh] Error occured while reading in configuration:", e)
376
377                 self.scanServices = self.generateServicelist(self.services[0], self.services[1])
378
379                 # Debug
380                 print("[EPGRefresh] Services we're going to scan:", ', '.join([repr(x) for x in self.scanServices]))
381
382                 self.maybeStopAdapter()
383                 # NOTE: start notification is handled in adapter initializer
384                 if config.plugins.epgrefresh.adapter.value.startswith("pip"):
385                         hidden = config.plugins.epgrefresh.adapter.value == "pip_hidden"
386                         refreshAdapter = PipAdapter(self.session, hide=hidden)
387                 elif config.plugins.epgrefresh.adapter.value.startswith("record"):
388                         refreshAdapter = RecordAdapter(self.session)
389                 else:
390                         refreshAdapter = MainPictureAdapter(self.session)
391
392                 if (not refreshAdapter.backgroundCapable and Screens.Standby.inStandby) or not refreshAdapter.prepare():
393                         print("[EPGRefresh] Adapter is not able to run in background or not available, falling back to MainPictureAdapter")
394                         refreshAdapter = MainPictureAdapter(self.session)
395                         refreshAdapter.prepare()
396                 self.refreshAdapter = refreshAdapter
397
398                 try:
399                         from plugin import AdjustExtensionsmenu, extStopDescriptor, extPendingServDescriptor, extRunDescriptor
400                         AdjustExtensionsmenu(True, extPendingServDescriptor)
401                         AdjustExtensionsmenu(True, extStopDescriptor)
402                         AdjustExtensionsmenu(False, extRunDescriptor)
403                 except:
404                         print("[EPGRefresh] Error while adding 'Stop Running EPG-Refresh' to Extensionmenu")
405                         print_exc(file=stdout)
406                         
407                 self.refresh()
408
409         def cleanUp(self):
410                 print("[EPGRefresh] Debug: Cleanup")
411                 config.plugins.epgrefresh.lastscan.value = int(time())
412                 config.plugins.epgrefresh.lastscan.save()
413                 self.doStopRunningRefresh = False
414                 # stop the epgTimeoutTimer - just in case one is running
415                 self.epgTimeoutTimer.stop()
416                 
417                 try:
418                         from plugin import AdjustExtensionsmenu, housekeepingExtensionsmenu, extStopDescriptor, extPendingServDescriptor
419                         AdjustExtensionsmenu(False, extPendingServDescriptor)
420                         AdjustExtensionsmenu(False, extStopDescriptor)
421                         housekeepingExtensionsmenu(config.plugins.epgrefresh.show_run_in_extensionsmenu, force=True)
422                 except:
423                         print("[EPGRefresh] Error while removing 'Stop Running EPG-Refresh' to Extensionmenu:")
424                         print_exc(file=stdout)
425
426                 self.currentServiceRef = None
427                 # Start Todo-Chain
428                 self._nextTodo()
429
430         def _nextTodo(self, *args, **kwargs):
431                 print("[EPGRefresh] Debug: Calling nextTodo")
432                 if len(self.finishTodos) > 0:
433                         finishTodo = self.finishTodos.pop(0)
434                         print("[EPGRefresh] Debug: Call " + str(finishTodo))
435                         finishTodo(*args, **kwargs)
436
437         def _ToDoCallAutotimer(self):
438                 if config.plugins.epgrefresh.parse_autotimer.value != "never":
439                         if config.plugins.epgrefresh.parse_autotimer.value in ("ask_yes", "ask_no"):
440                                 defaultanswer = True if config.plugins.epgrefresh.parse_autotimer.value == "ask_yes" else False
441                                 if self.forcedScan:
442                                         # only if we are interactive
443                                         Notifications.AddNotificationWithCallback(self._ToDoCallAutotimerCB, MessageBox, \
444                                                 text = _("EPG refresh finished.\nShould AutoTimer be search for new matches?"), \
445                                                 type = MessageBox.TYPE_YESNO, default = defaultanswer, timeout = 10, domain = NOTIFICATIONDOMAIN)
446                                 else:
447                                         self._ToDoCallAutotimerCB(parseAT=defaultanswer)
448                         else:
449                                 if self.forcedScan\
450                                         and config.plugins.epgrefresh.parse_autotimer.value == "bg_only":
451                                         self._nextTodo()
452                                 else:
453                                         # config.parse_autotimer = always / bg_only
454                                         self._ToDoCallAutotimerCB(parseAT=True)
455                 else:
456                         self._nextTodo()
457
458         def _ToDoCallAutotimerCB(self, parseAT):
459                 print("[EPGRefresh] Debug: Call AutoTimer: " + str(parseAT))
460                 if parseAT:
461                         try:
462                                 # Import Instance
463                                 from Plugins.Extensions.AutoTimer.plugin import autotimer
464         
465                                 if autotimer is None:
466                                         # Create an instance
467                                         from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
468                                         autotimer = AutoTimer()
469         
470                                 # Parse EPG
471                                 autotimer.parseEPGAsync(simulateOnly=False).addCallback(self._nextTodo).addErrback(self._autotimerErrback)
472                         except:
473                                 from traceback import format_exc
474                                 print("[EPGRefresh] Could not start AutoTimer:" + str(format_exc()))
475                                 self._nextTodo()
476                 else:
477                         self._nextTodo()
478         
479         def _autotimerErrback(self, failure):
480                 print("[EPGRefresh] Debug: AutoTimer failed:" + str(failure))
481                 if config.plugins.epgrefresh.enablemessage.value:
482                         Notifications.AddPopup(_("AutoTimer failed with error %s") % (str(failure)), \
483                                 MessageBox.TYPE_ERROR, 10, domain = NOTIFICATIONDOMAIN)
484                 self._nextTodo()
485
486         def _ToDoAutotimerCalled(self, *args, **kwargs):
487                 if config.plugins.epgrefresh.enablemessage.value:
488                         if len(args):
489                                 # Autotimer has been started
490                                 ret=args[0]
491                                 Notifications.AddPopup(_("Found a total of %d matching Events.\n%d Timer were added and\n%d modified,\n%d conflicts encountered,\n%d similars added.") \
492                                         % (ret[0], ret[1], ret[2], len(ret[4]), len(ret[5])),
493                                         MessageBox.TYPE_INFO, 10, domain = NOTIFICATIONDOMAIN)
494                 self._nextTodo()
495         
496         def _callFinishNotifiers(self, *args, **kwargs):
497                 for notifier in self.finishNotifiers.keys():
498                         print("[EPGRefresh] Debug: call " + str(notifier))
499                         self.finishNotifiers[notifier]()
500                 self._nextTodo()
501         
502         def finish(self, *args, **kwargs):
503                 print("[EPGRefresh] Debug: Refresh finished!")
504                 if config.plugins.epgrefresh.enablemessage.value:
505                         Notifications.AddPopup(_("EPG refresh finished."), MessageBox.TYPE_INFO, 4, ENDNOTIFICATIONID, domain = NOTIFICATIONDOMAIN)
506                 epgrefreshtimer.cleanup()
507                 self.maybeStopAdapter()
508                 if config.plugins.epgrefresh.epgsave.value:
509                         Notifications.AddPopup(_("EPG refresh save."), MessageBox.TYPE_INFO, 4, ENDNOTIFICATIONID, domain = NOTIFICATIONDOMAIN)
510                         from enigma import eEPGCache
511                         myEpg = None
512                         myEpg = eEPGCache.getInstance()
513                         myEpg.save()
514                 
515                 # shutdown if we're supposed to go to deepstandby and not recording
516                 if not self.forcedScan and config.plugins.epgrefresh.afterevent.value \
517                         and not Screens.Standby.inTryQuitMainloop:
518                         self.forcedScan = False
519                         if Screens.Standby.inStandby:
520                                 RecordTimerEntry.TryQuitMainloop()
521                         else:
522                                 Notifications.AddNotificationWithID("Shutdown", Screens.Standby.TryQuitMainloop, 1, domain = NOTIFICATIONDOMAIN)
523                 self.forcedScan = False
524                 self.isrunning = False
525                 self._nextTodo()
526                 
527         def refresh(self):
528                 if self.doStopRunningRefresh:
529                         self.cleanUp()
530                         return
531                 
532                 if self.forcedScan:
533                         self.nextService()
534                 else:
535                         # Abort if a scan finished later than our begin of timespan
536                         if self.beginOfTimespan < config.plugins.epgrefresh.lastscan.value:
537                                 return
538                         if config.plugins.epgrefresh.force.value \
539                                 or (Screens.Standby.inStandby and \
540                                         not self.session.nav.RecordTimer.isRecording()):
541
542                                 self.nextService()
543                         # We don't follow our rules here - If the Box is still in Standby and not recording we won't reach this line
544                         else:
545                                 if not checkTimespan(
546                                         config.plugins.epgrefresh.begin.value,
547                                         config.plugins.epgrefresh.end.value):
548
549                                         print("[EPGRefresh] Gone out of timespan while refreshing, sorry!")
550                                         self.cleanUp()
551                                 else:
552                                         print("[EPGRefresh] Box no longer in Standby or Recording started, rescheduling")
553
554                                         # Recheck later
555                                         epgrefreshtimer.add(EPGRefreshTimerEntry(
556                                                         time() + config.plugins.epgrefresh.delay_standby.value*60,
557                                                         self.refresh,
558                                                         nocheck = True)
559                                         )
560
561         def createWaitTimer(self):
562                 self.beginOfTimespan = time()
563
564                 # Add wait timer to epgrefreshtimer
565                 epgrefreshtimer.add(EPGRefreshTimerEntry(time() + 30, self.prepareRefresh))
566
567         def isServiceProtected(self, service):
568                 if not config.ParentalControl.configured.value \
569                         or not config.ParentalControl.servicepinactive.value:
570                         print("[EPGRefresh] DEBUG: ParentalControl not configured")
571                         return False
572                 print("[EPGRefresh] DEBUG: ParentalControl ProtectionLevel:" + str(parentalControl.getProtectionLevel(str(service))))
573                 return parentalControl.getProtectionLevel(str(service)) != -1
574
575         def nextService(self):
576                 # Debug
577                 print("[EPGRefresh] Maybe zap to next service")
578
579                 # update pending services message box (if shown)
580                 if self.showPendingServicesMessageShown:
581                         print("[EPGRefresh] - MessageBox is shown. Update pending services")
582                         self.showPendingServices(self.session)                  
583
584                 try:
585                         # Get next reference
586                         service = self.scanServices.pop(0)
587                 except IndexError:
588                         # Debug
589                         print("[EPGRefresh] Done refreshing EPG")
590
591                         # Clean up
592                         self.cleanUp()
593                 else:
594                         if self.myEpgCacheInstance is None and config.plugins.epgrefresh.usetimebased.value == False:
595                                 # get eEPGCache instance if None and eEPGCache-signal based is used
596                                 print("[EPGRefresh] - myEpgCacheInstance is None. Get it")
597                                 self.myEpgCacheInstance = eEPGCache.getInstance()
598                                 self.EpgCacheStateChanged_conn = self.myEpgCacheInstance.cacheState.connect(self._onCacheStateChanged)
599
600                         if self.isServiceProtected(service):
601                                 if (not self.forcedScan) or config.plugins.epgrefresh.skipProtectedServices.value == "always":
602                                         print("[EPGRefresh] Service is protected, skipping!")
603                                         self.refresh()
604                                         return
605                         
606                         # If the current adapter is unable to run in background and we are in fact in background now,
607                         # fall back to main picture
608                         if (not self.refreshAdapter.backgroundCapable and Screens.Standby.inStandby):
609                                 print("[EPGRefresh] Adapter is not able to run in background or not available, falling back to MainPictureAdapter")
610                                 self.maybeStopAdapter()
611                                 self.refreshAdapter = MainPictureAdapter(self.session)
612                                 self.refreshAdapter.prepare()
613
614                         if config.plugins.epgrefresh.usetimebased.value == False:
615                                 # set timeout timer for eEPGCache-signal based refresh
616                                 self.epgTimeoutTimer.start(5000, True)
617                         # Play next service
618                         # XXX: we might want to check the return value
619                         self.currentServiceRef = eServiceReference(service.sref)
620                         self.refreshAdapter.play(self.currentServiceRef)
621                         ref = ServiceReference(service.sref)
622                         channelname = ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')
623                         print("[EPGRefresh] - Service is: %s" %(str(channelname)))
624                                         
625                         if config.plugins.epgrefresh.usetimebased.value:
626                                 # Start Timer
627                                 delay = service.duration or config.plugins.epgrefresh.interval_seconds.value
628                                 epgrefreshtimer.add(EPGRefreshTimerEntry(
629                                         time() + delay,
630                                         self.refresh,
631                                         nocheck = True)
632                                 )
633
634         def showPendingServices(self, session):
635                 LISTMAX = 10
636                 servcounter = 0
637                 try:
638                         servtxt = ""
639                         for service in self.scanServices:
640                                 if self.isServiceProtected(service):
641                                         if not self.forcedScan or config.plugins.epgrefresh.skipProtectedServices.value == "always":
642                                                 continue
643                                 if servcounter <= LISTMAX:
644                                         ref = ServiceReference(service.sref)
645                                         txt = ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')
646                                         servtxt = servtxt + str(txt) + "\n"
647                                 servcounter = servcounter + 1
648                         
649                         if servcounter > LISTMAX:
650                                 servtxt = servtxt + _("%d more services") % (servcounter)
651                         
652                         # open message box only if not already shown
653                         if self.showPendingServicesMessageShown == False:
654                                 self.msg = session.open(MessageBox, _("Following Services have to be scanned:") \
655                                         + "\n" + servtxt, MessageBox.TYPE_INFO)
656                                 # update state for pending services message box on close
657                                 self.msg.onClose.append(self.setMessageBoxState)
658                                 self.showPendingServicesMessageShown = True
659                         else:
660                                 self.msg["text"].setText(_("Following Services have to be scanned:") + "\n" + servtxt)
661                                 self.msg["Text"].setText(_("Following Services have to be scanned:") + "\n" + servtxt)
662                 except:
663                         print("[EPGRefresh] showPendingServices Error!")
664                         print_exc(file=stdout)
665                         
666         def setMessageBoxState(self):
667                 self.showPendingServicesMessageShown = False                            
668
669 epgrefresh = EPGRefresh()