V 2.0b1-20140219: Check if refresh is still running to prevent multiple
[enigma2-plugins.git] / epgrefresh / src / plugin.py
1 from __future__ import print_function
2
3 # for localized messages
4 from . import _, NOTIFICATIONDOMAIN
5
6 # Config
7 from Components.config import config, ConfigYesNo, ConfigNumber, ConfigSelection, \
8         ConfigSubsection, ConfigClock, ConfigYesNo, ConfigInteger, ConfigDirectory, NoSave
9 from Screens.MessageBox import MessageBox
10 from Screens.Standby import TryQuitMainloop
11 from Tools.BoundFunction import boundFunction
12
13 # Error-print
14 from traceback import print_exc
15 from sys import stdout
16
17 # Calculate default begin/end
18 from time import time, localtime, mktime
19 now = localtime()
20 begin = mktime((
21         now.tm_year, now.tm_mon, now.tm_mday, 20, 15, \
22         0, now.tm_wday, now.tm_yday, now.tm_isdst)
23 )
24 end = mktime((
25         now.tm_year, now.tm_mon, now.tm_mday, 06, 30, \
26         0, now.tm_wday, now.tm_yday, now.tm_isdst)
27 )
28
29 #Configuration
30 config.plugins.epgrefresh = ConfigSubsection()
31 config.plugins.epgrefresh.enabled = ConfigYesNo(default = False)
32 config.plugins.epgrefresh.begin = ConfigClock(default = int(begin))
33 config.plugins.epgrefresh.end = ConfigClock(default = int(end))
34 config.plugins.epgrefresh.interval_seconds = ConfigNumber(default = 120)
35 config.plugins.epgrefresh.delay_standby = ConfigNumber(default = 10)
36 config.plugins.epgrefresh.inherit_autotimer = ConfigYesNo(default = False)
37 config.plugins.epgrefresh.afterevent = ConfigYesNo(default = False)
38 config.plugins.epgrefresh.force = ConfigYesNo(default = False)
39 config.plugins.epgrefresh.enablemessage = ConfigYesNo(default = True)
40 config.plugins.epgrefresh.wakeup = ConfigYesNo(default = False)
41 config.plugins.epgrefresh.lastscan = ConfigNumber(default = 0)
42 config.plugins.epgrefresh.parse_autotimer = ConfigSelection(choices = [
43                 ("always", _("Yes")),
44                 ("never", _("No")),
45                 ("bg_only", _("Background only")),
46                 ("ask_yes", _("Ask default Yes")),
47                 ("ask_no", _("Ask default No")),
48         ], default = "never"
49 )
50 config.plugins.epgrefresh.adapter = ConfigSelection(choices = [
51                 ("main", _("Main Picture")),
52                 ("pip", _("Picture in Picture")),
53                 ("pip_hidden", _("Picture in Picture (hidden)")),
54                 ("record", _("Fake recording")),
55         ], default = "main"
56 )
57 config.plugins.epgrefresh.show_in_extensionsmenu = ConfigYesNo(default = False)
58 config.plugins.epgrefresh.show_run_in_extensionsmenu = ConfigYesNo(default = True)
59 config.plugins.epgrefresh.show_backuprestore_in_extmenu = ConfigYesNo(default = False)
60 config.plugins.epgrefresh.show_help = ConfigYesNo(default = True)
61 config.plugins.epgrefresh.wakeup_time = ConfigInteger(default=-1)
62 config.plugins.epgrefresh.backup_enabled = ConfigYesNo(default = True)
63 config.plugins.epgrefresh.backup_filesize_valid = ConfigNumber(default=1024)
64 config.plugins.epgrefresh.backup_timespan_valid = ConfigNumber(default=7)
65 config.plugins.epgrefresh.showadvancedoptions = NoSave(ConfigYesNo(default = False))
66 config.plugins.epgrefresh.backup_epgwrite_wait = ConfigNumber(default=3)
67 config.plugins.epgrefresh.showin_usr_scripts = ConfigYesNo(default = True)
68 config.plugins.epgrefresh.backup_strategy = ConfigSelection(choices = [
69                 ("biggest", _("Biggest before Youngest")),
70                 ("youngest", _("Youngest before Biggest")),
71         ], default = "biggest"
72 )
73 config.plugins.epgrefresh.backup_enable_debug = ConfigYesNo(default = False)
74 config.plugins.epgrefresh.backup_log_dir = ConfigDirectory(default = "/hdd")
75 config.plugins.epgrefresh.backup_max_boot_count = ConfigNumber(default=3)
76
77 # convert previous parameters
78 config.plugins.epgrefresh.background = ConfigYesNo(default = False)
79 if config.plugins.epgrefresh.background.value:
80         config.plugins.epgrefresh.adapter.value = "pip_hidden"
81         config.plugins.epgrefresh.background.value = False
82         config.plugins.epgrefresh.save()
83 config.plugins.epgrefresh.interval = ConfigNumber(default = 2)
84 if config.plugins.epgrefresh.interval.value != 2:
85         config.plugins.epgrefresh.interval_seconds.value = config.plugins.epgrefresh.interval.value * 60
86         config.plugins.epgrefresh.interval.value = 2
87         config.plugins.epgrefresh.save()
88
89 #pragma mark - Help
90 try:
91         from Components.Language import language
92         from Plugins.SystemPlugins.MPHelp import registerHelp, XMLHelpReader
93         from Tools.Directories import resolveFilename, SCOPE_PLUGINS, fileExists
94         lang = language.getLanguage()[:2]
95         
96         HELPPATH = resolveFilename(SCOPE_PLUGINS, "Extensions/EPGRefresh")
97         if fileExists(HELPPATH + "/locale/" + str(lang) + "/mphelp.xml"):
98                 helpfile = HELPPATH + "/locale/" + str(lang) + "/mphelp.xml"
99         else:
100                 helpfile = HELPPATH + "/mphelp.xml"
101         reader = XMLHelpReader(helpfile)
102         epgrefreshHelp = registerHelp(*reader)
103 except Exception as e:
104         print("[EPGRefresh] Unable to initialize MPHelp:", e,"- Help not available!")
105         epgrefreshHelp = None
106 #pragma mark -
107
108 # Notification-Domain
109 from Tools import Notifications
110 try:
111         Notifications.notificationQueue.registerDomain(NOTIFICATIONDOMAIN, _("EPGREFRESH_NOTIFICATION_DOMAIN"), deferred_callable = True)
112 except Exception as e:
113         EPGRefreshNotificationKey = ""
114         print("[EPGRefresh] Error registering Notification-Domain:", e)
115         
116 # Plugin
117 from EPGRefresh import epgrefresh
118 from EPGRefreshService import EPGRefreshService
119 epgbackup = None
120 # Plugins
121 from Components.PluginComponent import plugins
122 from Plugins.Plugin import PluginDescriptor
123
124 #pragma mark - Workaround for unset clock
125 from enigma import eDVBLocalTimeHandler
126
127 def timeCallback(isCallback=True):
128         """Time Callback/Autostart management."""
129         thInstance = eDVBLocalTimeHandler.getInstance()
130         if isCallback:
131                 # NOTE: this assumes the clock is actually ready when called back
132                 # this may not be true, but we prefer silently dying to waiting forever
133                 thInstance.m_timeUpdated.get().remove(timeCallback)
134         elif not thInstance.ready():
135                 thInstance.m_timeUpdated.get().append(timeCallback)
136                 return
137         epgrefresh.start()
138
139 gUserScriptExists = False
140 # Autostart
141 def autostart(reason, **kwargs):
142         global epgbackup
143         global gUserScriptExists
144         
145         if reason == 0 and "session" in kwargs:
146                 session = kwargs["session"]
147                 epgrefresh.session = session
148
149                 from EPGBackupSupport import EPGBackupSupport
150                 try:
151                         epgbackup = EPGBackupSupport(session)
152                 except:
153                         print("[EPGRefresh] Error while initializing EPGBackupSupport")
154                         print_exc(file=stdout)
155         
156                 if config.plugins.epgrefresh.enabled.value:
157                         # check if box was woken up by a timer, if so, check if epgrefresh set this timer
158                         if session.nav.wasTimerWakeup() and config.misc.prev_wakeup_time.value == config.plugins.epgrefresh.wakeup_time.value:
159                                 # if box is not in idle mode, do that
160                                 from Screens.Standby import Standby, inStandby
161                                 if not inStandby:
162                                         from Tools import Notifications
163                                         Notifications.AddNotificationWithID("Standby", Standby)
164                         timeCallback(isCallback=False)
165                 
166                 try:
167                         from Plugins.Extensions.UserScripts.plugin import UserScriptsConfiguration
168                         gUserScriptExists = True
169                         del UserScriptsConfiguration
170                 except:
171                         pass
172
173         elif reason == 1:
174                 epgrefresh.stop()
175
176 def getNextWakeup():
177         # Return invalid time if not automatically refreshing
178         if not config.plugins.epgrefresh.enabled.value or \
179                 not config.plugins.epgrefresh.wakeup.value:
180
181                 setConfigWakeupTime(-1) 
182                 return -1
183
184         now = localtime()
185         begin = int(mktime(
186                 (now.tm_year, now.tm_mon, now.tm_mday,
187                 config.plugins.epgrefresh.begin.value[0],
188                 config.plugins.epgrefresh.begin.value[1],
189                 0, now.tm_wday, now.tm_yday, now.tm_isdst)
190         ))
191
192         # todays timespan has not yet begun
193         if begin > time():
194                 setConfigWakeupTime(begin)
195                 return begin
196
197         # otherwise add 1 day
198         setConfigWakeupTime(begin+86400)
199         return begin+86400
200
201 def setConfigWakeupTime(value):
202         config.plugins.epgrefresh.wakeup_time.value = value
203         config.plugins.epgrefresh.save()
204
205 # Mainfunction
206 def main(session, **kwargs):
207         try:
208                 from EPGRefreshConfiguration import EPGRefreshConfiguration
209                 session.openWithCallback(
210                         doneConfiguring,
211                         EPGRefreshConfiguration
212                 )
213         except:
214                 print("[EPGRefresh] Error while Opening EPGRefreshConfiguration")
215                 print_exc(file=stdout)
216
217 def forceRefresh(session, **kwargs):
218         epgrefresh.forceRefresh(session)
219
220 def stopRunningRefresh(session, **kwargs):
221         epgrefresh.stopRunningRefresh(session)
222
223 def restoreBackup(session, **kwargs):
224         epgbackup.forceBackup()
225
226 def showPendingServices(session, **kwargs):
227         epgrefresh.showPendingServices(session)
228
229 def doneConfiguring(session, needsRestart):
230         if needsRestart:
231                 session.openWithCallback(boundFunction(restartGUICB, session), MessageBox, \
232                                 _("To apply your Changes the GUI has to be restarted.\nDo you want to restart the GUI now?"), \
233                                 MessageBox.TYPE_YESNO, timeout =  30)
234         else:
235                 _startAfterConfig(session)
236
237 def restartGUICB(session, answer):
238         if answer is True:
239                 session.open(TryQuitMainloop, 3)
240         else:
241                 _startAfterConfig(session)
242
243 def _startAfterConfig(session):
244         if config.plugins.epgrefresh.enabled.value:
245                 if not epgrefresh.isRunning():
246                         epgrefresh.start(session)
247
248 # Eventinfo
249 def eventinfo(session, servicelist, **kwargs):
250         ref = session.nav.getCurrentlyPlayingServiceReference()
251         if not ref:
252                 return
253         sref = ref.toString()
254         # strip all after last :
255         pos = sref.rfind(':')
256         if pos != -1:
257                 sref = sref[:pos+1]
258
259         epgrefresh.services[0].add(EPGRefreshService(str(sref), None))
260
261 # XXX: we need this helper function to identify the descriptor
262 # Extensions menu
263 def extensionsmenu(session, **kwargs):
264         main(session, **kwargs)
265
266 extPrefix = _("EXTENSIONMENU_PREFIX")
267 extSetupDescriptor = PluginDescriptor(name = extPrefix + " " + _("EXTENSIONNAME_SETUP"), description = _("Automatically refresh EPG"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = extensionsmenu, needsRestart=False)
268 extRunDescriptor = PluginDescriptor(name = extPrefix + " " + _("Refresh now"), description = _("Start EPGrefresh immediately"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = forceRefresh, needsRestart = False)
269 extStopDescriptor = PluginDescriptor(name = extPrefix + " " + _("Stop Refresh"), description = _("Stop Running EPG-refresh"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = stopRunningRefresh, needsRestart = False)
270 extBackupDescriptor = PluginDescriptor(name = extPrefix + " " + _("Restore Backup"), description = _("Start a Restore of a Backup"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = restoreBackup, needsRestart = False)
271 extPendingServDescriptor = PluginDescriptor(name = extPrefix + " " + _("Pending Services"), description = _("Show the pending Services for refresh"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = showPendingServices, needsRestart = False)
272
273 def AdjustExtensionsmenu(enable, PlugDescriptor):
274         if enable:
275                 plugins.addPlugin(PlugDescriptor)
276         else:
277                 try:
278                         plugins.removePlugin(PlugDescriptor)
279                 except ValueError as ve:
280                         if PlugDescriptor != extRunDescriptor:
281                                 print("[EPGRefresh] AdjustExtensionsmenu got confused, tried to remove non-existant plugin entry... ignoring.")
282
283 def housekeepingExtensionsmenu(configentry, force=False):
284         if force or (epgrefresh != None and not epgrefresh.isRunning()):
285                 PlugDescriptor = None
286                 if configentry == config.plugins.epgrefresh.show_in_extensionsmenu:
287                         PlugDescriptor = extSetupDescriptor
288                 elif configentry == config.plugins.epgrefresh.show_run_in_extensionsmenu:
289                         PlugDescriptor = extRunDescriptor
290                 elif configentry == config.plugins.epgrefresh.show_backuprestore_in_extmenu:
291                         PlugDescriptor = extBackupDescriptor
292                 if PlugDescriptor != None:
293                         AdjustExtensionsmenu(configentry.value, PlugDescriptor)
294
295 config.plugins.epgrefresh.show_in_extensionsmenu.addNotifier(housekeepingExtensionsmenu, initial_call = False, immediate_feedback = True)
296 config.plugins.epgrefresh.show_run_in_extensionsmenu.addNotifier(housekeepingExtensionsmenu, initial_call = False, immediate_feedback = True)
297 config.plugins.epgrefresh.show_backuprestore_in_extmenu.addNotifier(housekeepingExtensionsmenu, initial_call = False, immediate_feedback = True)
298
299 def Plugins(**kwargs):
300         # NOTE: this might be a little odd to check this, but a user might expect
301         # the plugin to resume normal operation if installed during runtime, but
302         # this is not given if the plugin is supposed to run in background (as we
303         # won't be handed the session which we need to zap). So in turn we require
304         # a restart if-and only if-we're installed during runtime AND running in
305         # background. To improve the user experience in this situation, we hide
306         # all references to this plugin.
307         needsRestart = config.plugins.epgrefresh.enabled.value and not plugins.firstRun
308         list = [
309                 PluginDescriptor(
310                         name = "EPGRefresh",
311                         where = [
312                                 PluginDescriptor.WHERE_AUTOSTART,
313                                 PluginDescriptor.WHERE_SESSIONSTART
314                         ],
315                         fnc = autostart,
316                         wakeupfnc = getNextWakeup,
317                         needsRestart = needsRestart,
318                 ),
319                 PluginDescriptor(
320                         name = _("add to EPGRefresh"),
321                         where = PluginDescriptor.WHERE_EVENTINFO,
322                         fnc = eventinfo,
323                         needsRestart = needsRestart,
324                 ),
325                 PluginDescriptor(
326                         name = _("PLUGINNAME_EPGRefresh"),
327                         description = _("Automatically refresh EPG"),
328                         where = PluginDescriptor.WHERE_PLUGINMENU, 
329                         fnc = main,
330                         icon = "EPGRefresh.png",
331                         needsRestart = needsRestart,
332                 ),
333         ]
334         if config.plugins.epgrefresh.show_in_extensionsmenu.value:
335                 extSetupDescriptor.needsRestart = needsRestart
336                 list.append(extSetupDescriptor)
337         if config.plugins.epgrefresh.show_run_in_extensionsmenu.value:
338                 extRunDescriptor.needsRestart = needsRestart
339                 list.append(extRunDescriptor)
340         if config.plugins.epgrefresh.show_backuprestore_in_extmenu.value:
341                 extBackupDescriptor.needsRestart = needsRestart
342                 list.append(extBackupDescriptor)
343
344         return list