Functionality:
[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 # Autostart
140 def autostart(reason, **kwargs):
141         global epgbackup
142         
143         if reason == 0 and "session" in kwargs:
144                 session = kwargs["session"]
145                 epgrefresh.session = session
146
147                 from EPGBackupSupport import EPGBackupSupport
148                 try:
149                         epgbackup = EPGBackupSupport(session)
150                 except:
151                         print("[EPGRefresh] Error while initializing EPGBackupSupport")
152                         print_exc(file=stdout)
153         
154                 if config.plugins.epgrefresh.enabled.value:
155                         # check if box was woken up by a timer, if so, check if epgrefresh set this timer
156                         if session.nav.wasTimerWakeup() and config.misc.prev_wakeup_time.value == config.plugins.epgrefresh.wakeup_time.value:
157                                 # if box is not in idle mode, do that
158                                 from Screens.Standby import Standby, inStandby
159                                 if not inStandby:
160                                         from Tools import Notifications
161                                         Notifications.AddNotificationWithID("Standby", Standby)
162                         timeCallback(isCallback=False)
163
164         elif reason == 1:
165                 epgrefresh.stop()
166
167 def getNextWakeup():
168         # Return invalid time if not automatically refreshing
169         if not config.plugins.epgrefresh.enabled.value or \
170                 not config.plugins.epgrefresh.wakeup.value:
171
172                 setConfigWakeupTime(-1) 
173                 return -1
174
175         now = localtime()
176         begin = int(mktime(
177                 (now.tm_year, now.tm_mon, now.tm_mday,
178                 config.plugins.epgrefresh.begin.value[0],
179                 config.plugins.epgrefresh.begin.value[1],
180                 0, now.tm_wday, now.tm_yday, now.tm_isdst)
181         ))
182
183         # todays timespan has not yet begun
184         if begin > time():
185                 setConfigWakeupTime(begin)
186                 return begin
187
188         # otherwise add 1 day
189         setConfigWakeupTime(begin+86400)
190         return begin+86400
191
192 def setConfigWakeupTime(value):
193         config.plugins.epgrefresh.wakeup_time.value = value
194         config.plugins.epgrefresh.save()
195
196 # Mainfunction
197 def main(session, **kwargs):
198         epgrefresh.stop()
199         try:
200                 from EPGRefreshConfiguration import EPGRefreshConfiguration
201                 session.openWithCallback(
202                         doneConfiguring,
203                         EPGRefreshConfiguration
204                 )
205         except:
206                 print("[EPGRefresh] Error while Opening EPGRefreshConfiguration")
207                 print_exc(file=stdout)
208
209 def forceRefresh(session, **kwargs):
210         epgrefresh.forceRefresh(session)
211
212 def stopRunningRefresh(session, **kwargs):
213         epgrefresh.stopRunningRefresh(session)
214
215 def restoreBackup(session, **kwargs):
216         epgbackup.forceBackup()
217
218 def showPendingServices(session, **kwargs):
219         epgrefresh.showPendingServices(session)
220
221 def doneConfiguring(session, needsRestart):
222         if needsRestart:
223                 session.openWithCallback(boundFunction(restartGUICB, session), MessageBox, \
224                                 _("To apply your Changes the GUI has to be restarted.\nDo you want to restart the GUI now?"), \
225                                 MessageBox.TYPE_YESNO, timeout =  30)
226         else:
227                 _startAfterConfig(session)
228
229 def restartGUICB(session, answer):
230         if answer is True:
231                 session.open(TryQuitMainloop, 3)
232         else:
233                 _startAfterConfig(session)
234
235 def _startAfterConfig(session):
236         if config.plugins.epgrefresh.enabled.value:
237                         epgrefresh.start(session)
238
239 # Eventinfo
240 def eventinfo(session, servicelist, **kwargs):
241         ref = session.nav.getCurrentlyPlayingServiceReference()
242         if not ref:
243                 return
244         sref = ref.toString()
245         # strip all after last :
246         pos = sref.rfind(':')
247         if pos != -1:
248                 sref = sref[:pos+1]
249
250         epgrefresh.services[0].add(EPGRefreshService(str(sref), None))
251
252 # XXX: we need this helper function to identify the descriptor
253 # Extensions menu
254 def extensionsmenu(session, **kwargs):
255         main(session, **kwargs)
256
257 extSetupDescriptor = PluginDescriptor(name=_("EXTENSIONNAME_SETUP"), description = _("Automatically refresh EPG"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = extensionsmenu, needsRestart=False)
258 extRunDescriptor = PluginDescriptor(name = _("EPGRefresh Start now"), description = _("Start EPGrefresh immediately"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = forceRefresh, needsRestart = False)
259 extStopDescriptor = PluginDescriptor(name=_("EPGRefresh Stop"), description = _("Stop Running EPG-refresh"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = stopRunningRefresh, needsRestart = False)
260 extBackupDescriptor = PluginDescriptor(name = _("EPGRefresh Restore Backup"), description = _("Start a Restore of a Backup"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = restoreBackup, needsRestart = False)
261 extPendingServDescriptor = PluginDescriptor(name = _("EPGRefresh Pending Services"), description = _("Show the pending Services for refresh"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = showPendingServices, needsRestart = False)
262
263 def AdjustExtensionsmenu(enable, PlugDescriptor):
264         if enable:
265                 plugins.addPlugin(PlugDescriptor)
266         else:
267                 try:
268                         plugins.removePlugin(PlugDescriptor)
269                 except ValueError as ve:
270                         print("[EPGRefresh] AdjustExtensionsmenu got confused, tried to remove non-existant plugin entry... ignoring.")
271
272 def housekeepingExtensionsmenu(configentry):
273         PlugDescriptor = None
274         if configentry == config.plugins.epgrefresh.show_in_extensionsmenu:
275                 PlugDescriptor = extSetupDescriptor
276         elif configentry == config.plugins.epgrefresh.show_run_in_extensionsmenu:
277                 PlugDescriptor = extRunDescriptor
278         elif configentry == config.plugins.epgrefresh.show_backuprestore_in_extmenu:
279                 PlugDescriptor = extBackupDescriptor
280         if PlugDescriptor != None:
281                 AdjustExtensionsmenu(configentry.value, PlugDescriptor)
282
283 config.plugins.epgrefresh.show_in_extensionsmenu.addNotifier(housekeepingExtensionsmenu, initial_call = False, immediate_feedback = True)
284 config.plugins.epgrefresh.show_run_in_extensionsmenu.addNotifier(housekeepingExtensionsmenu, initial_call = False, immediate_feedback = True)
285 config.plugins.epgrefresh.show_backuprestore_in_extmenu.addNotifier(housekeepingExtensionsmenu, initial_call = False, immediate_feedback = True)
286
287 def Plugins(**kwargs):
288         # NOTE: this might be a little odd to check this, but a user might expect
289         # the plugin to resume normal operation if installed during runtime, but
290         # this is not given if the plugin is supposed to run in background (as we
291         # won't be handed the session which we need to zap). So in turn we require
292         # a restart if-and only if-we're installed during runtime AND running in
293         # background. To improve the user experience in this situation, we hide
294         # all references to this plugin.
295         needsRestart = config.plugins.epgrefresh.enabled.value and not plugins.firstRun
296         list = [
297                 PluginDescriptor(
298                         name = "EPGRefresh",
299                         where = [
300                                 PluginDescriptor.WHERE_AUTOSTART,
301                                 PluginDescriptor.WHERE_SESSIONSTART
302                         ],
303                         fnc = autostart,
304                         wakeupfnc = getNextWakeup,
305                         needsRestart = needsRestart,
306                 ),
307                 PluginDescriptor(
308                         name = _("add to EPGRefresh"),
309                         where = PluginDescriptor.WHERE_EVENTINFO,
310                         fnc = eventinfo,
311                         needsRestart = needsRestart,
312                 ),
313                 PluginDescriptor(
314                         name = _("PLUGINNAME_EPGRefresh"),
315                         description = _("Automatically refresh EPG"),
316                         where = PluginDescriptor.WHERE_PLUGINMENU, 
317                         fnc = main,
318                         needsRestart = needsRestart,
319                 ),
320         ]
321         if config.plugins.epgrefresh.show_in_extensionsmenu.value:
322                 extSetupDescriptor.needsRestart = needsRestart
323                 list.append(extSetupDescriptor)
324         if config.plugins.epgrefresh.show_run_in_extensionsmenu.value:
325                 extRunDescriptor.needsRestart = needsRestart
326                 list.append(extRunDescriptor)
327         if config.plugins.epgrefresh.show_backuprestore_in_extmenu.value:
328                 extBackupDescriptor.needsRestart = needsRestart
329                 list.append(extBackupDescriptor)
330
331         return list