AutTimer 4.1.6: Fixed invalid syntax
[enigma2-plugins.git] / autotimer / src / AutoPoller.py
1 from __future__ import print_function
2
3 # Core functionality
4 from enigma import eTimer, ePythonMessagePump
5
6 # Config
7 from Components.config import config
8
9 # Notifications
10 from Tools.FuzzyDate import FuzzyTime
11 from Tools.Notifications import AddPopup
12 from Screens.MessageBox import MessageBox
13
14 NOTIFICATIONID = 'AutoTimerConflictEncounteredNotification'
15 SIMILARNOTIFICATIONID = 'AutoTimerSimilarUsedNotification'
16
17 from threading import Thread, Semaphore
18 from collections import deque
19
20 from twisted.internet import reactor
21
22 from Logger import doLog
23
24 class AutoPollerThread(Thread):
25         """Background thread where the EPG is parsed (unless initiated by the user)."""
26         def __init__(self):
27                 Thread.__init__(self)
28                 self.__semaphore = Semaphore(0)
29                 self.__queue = deque(maxlen=1)
30                 self.__pump = ePythonMessagePump()
31                 self.__pump_recv_msg_conn = self.__pump.recv_msg.connect(self.gotThreadMsg)
32                 self.__timer = eTimer()
33                 self.__timer_conn = self.__timer.timeout.connect(self.timeout)
34                 self.running = False
35
36         def timeout(self):
37                 self.__semaphore.release()
38
39         def gotThreadMsg(self, msg):
40                 """Create Notifications if there is anything to display."""
41                 ret = self.__queue.pop()
42                 conflicts = ret[4]
43                 if conflicts and config.plugins.autotimer.notifconflict.value:
44                         AddPopup(
45                                 _("%(conflicts)d conflict(s) encountered when trying to add new timers:\n%(timers)s") % \
46                                 { "conflicts":len(conflicts), "timers":'\n'.join( [ _("%(tname)s: %(name)s at %(begin)s") % {"tname":x[4], "name":x[0], "begin":FuzzyTime(x[2])} for x in conflicts ] ) },
47                                 MessageBox.TYPE_INFO,
48                                 config.plugins.autotimer.popup_timeout.value,
49                                 NOTIFICATIONID
50                         )
51                 similars = ret[5]
52                 if similars and config.plugins.autotimer.notifsimilar.value:
53                         AddPopup(
54                                 _("%(similars)d conflict(s) solved with similar timer(s):\n%(timers)s") % \
55                                 { "similars":len(similars), "timers":'\n'.join( [ _("%(tname)s: %(name)s at %(begin)s") % {"tname":x[4], "name":x[0], "begin":FuzzyTime(x[2])} for x in similars ] ) },
56                                 MessageBox.TYPE_INFO,
57                                 config.plugins.autotimer.popup_timeout.value,
58                                 SIMILARNOTIFICATIONID
59                         )
60
61         def start(self, initial=True):
62                 # NOTE: we wait for several minutes on initial launch to not delay enigma2 startup time
63                 if initial: delay = config.plugins.autotimer.delay.value*60
64                 else: delay = config.plugins.autotimer.interval.value*3600
65
66                 self.__timer.startLongTimer(delay)
67                 if not self.isAlive():
68                         Thread.start(self)
69
70         def pause(self):
71                 self.__timer.stop()
72
73         def stop(self):
74                 self.__timer.stop()
75                 self.running = False
76                 self.__semaphore.release()
77                 self.__pump_recv_msg_conn = None
78                 self.__timer_conn = None
79
80         def run(self):
81                 sem = self.__semaphore
82                 queue = self.__queue
83                 pump = self.__pump
84                 timer = self.__timer
85
86                 self.running = True
87                 while 1:
88                         sem.acquire()
89                         # NOTE: we have to check this here and not using the while to prevent the parser to be started on shutdown
90                         if not self.running: break
91                         
92                         if config.plugins.autotimer.skip_during_records.value:
93                                 try:
94                                         import NavigationInstance
95                                         if NavigationInstance.instance.RecordTimer.isRecording():
96                                                 doLog("[AutoTimer]: Skip check during running records")
97                                                 reactor.callFromThread(timer.startLongTimer, config.plugins.autotimer.interval.value*3600)
98                                                 continue
99                                 except:
100                                         pass
101
102                         if config.plugins.autotimer.skip_during_epgrefresh.value:
103                                 try:
104                                         from Plugins.Extensions.EPGRefresh.EPGRefresh import epgrefresh
105                                         if epgrefresh.isrunning:
106                                                 doLog("[AutoTimer]: Skip check during EPGRefresh")
107                                                 reactor.callFromThread(timer.startLongTimer, config.plugins.autotimer.interval.value*3600)
108                                                 continue
109                                 except:
110                                         pass
111
112                         from plugin import autotimer
113                         # Ignore any program errors
114                         try:
115                                 queue.append(autotimer.parseEPG())
116                                 pump.send(0)
117                         except Exception:
118                                 # Dump error to stdout
119                                 import traceback, sys
120                                 traceback.print_exc(file=sys.stdout)
121                         #Keep that eTimer in the mainThread
122                         reactor.callFromThread(timer.startLongTimer, config.plugins.autotimer.interval.value*3600)
123
124 class AutoPoller:
125         """Manages actual thread which does the polling. Used for convenience."""
126
127         def __init__(self):
128                 self.thread = AutoPollerThread()
129
130         def start(self, initial=True):
131                 self.thread.start(initial=initial)
132
133         def pause(self):
134                 self.thread.pause()
135
136         def stop(self):
137                 self.thread.stop()
138                 # NOTE: while we don't need to join the thread, we should do so in case it's currently parsing
139                 self.thread.join()
140                 self.thread = None