replaced deprecated ConfigEnableDisable by ConfigOnOff
[enigma2-plugins.git] / seriesplugin / src / plugin.py
1 # -*- coding: utf-8 -*-
2 import os, sys, traceback
3
4 # Localization
5 from . import _
6
7 from time import time
8
9 # GUI (Screens)
10 from Screens.MessageBox import MessageBox
11 from Tools.Notifications import AddPopup
12
13 # Config
14 from Components.config import config, ConfigSubsection, ConfigOnOff, ConfigNumber, ConfigSelection, ConfigYesNo, ConfigText, ConfigSelectionNumber
15
16 # Plugin
17 from Components.PluginComponent import plugins
18 from Plugins.Plugin import PluginDescriptor
19
20 # Plugin internal
21 from SeriesPluginTimer import SeriesPluginTimer
22 from SeriesPluginInfoScreen import SeriesPluginInfoScreen
23 from SeriesPluginRenamer import SeriesPluginRenamer
24 from SeriesPluginIndependent import startIndependent, runIndependent
25 from SeriesPluginConfiguration import SeriesPluginConfiguration
26 from Logger import splog
27
28
29 #######################################################
30 # Constants
31 NAME = "SeriesPlugin"
32 VERSION = "3.3.1"
33 DESCRIPTION = _("SeriesPlugin")
34 SHOWINFO = _("Show series info (SP)")
35 RENAMESERIES = _("Rename serie(s) (SP)")
36 CHECKTIMERS = _("Check timer list for series (SP)")
37 SUPPORT = "http://bit.ly/seriespluginihad"
38 DONATE = "http://bit.ly/seriespluginpaypal"
39 TERMS = "TBD"
40 ABOUT = "\n  " + NAME + " " + VERSION + "\n\n" \
41                                 + _("  (C) 2012 by betonme @ IHAD \n\n") \
42                                 + _("  Terms: ") + TERMS + "\n\n" \
43                                 + _("  {lookups:d} successful lookups.\n") \
44                                 + _("  How much time have You saved?\n\n") \
45                                 + _("  Support: ") + SUPPORT + "\n" \
46                                 + _("  Feel free to donate. \n") \
47                                 + _("  PayPal: ") + DONATE
48
49 PROXY = "http://serienrecorder.lima-city.de/proxy.php"
50 USER_AGENT = "Enigma2-"+NAME
51
52 try:
53         from Tools.HardwareInfo import HardwareInfo
54         DEVICE = HardwareInfo().get_device_name().strip()
55         
56         # Get Box Info
57         #from Components.Network import iNetwork
58         #self.BoxID = iNetwork.getAdapterAttribute("eth0", "mac")
59         #self.DeviceName = HardwareInfo().get_device_name()
60         #from Components.About import about
61         #self.EnigmaVersion = about.getEnigmaVersionString()
62         #self.ImageVersion = about.getVersionString()
63 except:
64         DEVICE = ''
65
66 WHERE_EPGMENU     = 'WHERE_EPGMENU'
67 WHERE_CHANNELMENU = 'WHERE_CHANNELMENU'
68
69
70 def buildURL(url):
71         return PROXY + "?device=" + DEVICE + "&version=" + VERSION + "&url=" + url
72
73
74 #######################################################
75 # Initialize Configuration
76 config.plugins.seriesplugin = ConfigSubsection()
77
78 config.plugins.seriesplugin.enabled                   = ConfigOnOff(default = False)
79
80 config.plugins.seriesplugin.menu_info                 = ConfigYesNo(default = True)
81 config.plugins.seriesplugin.menu_extensions           = ConfigYesNo(default = False)
82 config.plugins.seriesplugin.menu_epg                  = ConfigYesNo(default = False)
83 config.plugins.seriesplugin.menu_channel              = ConfigYesNo(default = True)
84 config.plugins.seriesplugin.menu_movie_info           = ConfigYesNo(default = True)
85 config.plugins.seriesplugin.menu_movie_rename         = ConfigYesNo(default = True)
86
87 #TODO config.plugins.seriesplugin.open MessageBox or TheTVDB  ConfigSelection if hasTheTVDB
88
89 config.plugins.seriesplugin.identifier_elapsed        = ConfigText(default = "", fixed_size = False)
90 config.plugins.seriesplugin.identifier_today          = ConfigText(default = "", fixed_size = False)
91 config.plugins.seriesplugin.identifier_future         = ConfigText(default = "", fixed_size = False)
92
93 #config.plugins.seriesplugin.manager                   = ConfigSelection(choices = [("", "")], default = "")
94 #config.plugins.seriesplugin.guide                     = ConfigSelection(choices = [("", "")], default = "")
95
96 config.plugins.seriesplugin.pattern_file              = ConfigText(default = "/etc/enigma2/seriesplugin_patterns.json", fixed_size = False)
97 config.plugins.seriesplugin.pattern_title             = ConfigText(default = "{org:s} S{season:02d}E{episode:02d} {title:s}", fixed_size = False)
98 config.plugins.seriesplugin.pattern_description       = ConfigText(default = "S{season:02d}E{episode:02d} {title:s} {org:s}", fixed_size = False)
99 #config.plugins.seriesplugin.pattern_record            = ConfigText(default = "{org:s} S{season:02d}E{episode:02d} {title:s}", fixed_size = False)
100 config.plugins.seriesplugin.pattern_file_directories  = ConfigText(default = "/etc/enigma2/seriesplugin_patterns_directories.json", fixed_size = False)
101 config.plugins.seriesplugin.pattern_directory         = ConfigText(default = "Disabled", fixed_size = False)
102
103 config.plugins.seriesplugin.default_season            = ConfigSelectionNumber(0, 1, 1, default = 1)
104 config.plugins.seriesplugin.default_episode           = ConfigSelectionNumber(0, 1, 1, default = 1)
105
106 config.plugins.seriesplugin.replace_chars             = ConfigText(default = ":\!/\\,\(\)'\?", fixed_size = False)
107
108 config.plugins.seriesplugin.channel_file              = ConfigText(default = "/etc/enigma2/seriesplugin_channels.xml", fixed_size = False)
109
110 config.plugins.seriesplugin.bouquet_main              = ConfigText(default = "", fixed_size = False)
111
112 config.plugins.seriesplugin.rename_file               = ConfigYesNo(default = True)
113 config.plugins.seriesplugin.rename_tidy               = ConfigYesNo(default = False)
114 config.plugins.seriesplugin.rename_legacy             = ConfigYesNo(default = False)
115 config.plugins.seriesplugin.rename_existing_files     = ConfigYesNo(default = False)
116 config.plugins.seriesplugin.rename_popups             = ConfigYesNo(default = True)
117 config.plugins.seriesplugin.rename_popups_success     = ConfigYesNo(default = False)
118 config.plugins.seriesplugin.rename_popups_timeout     = ConfigSelectionNumber(-1, 20, 1, default = 3)
119
120 config.plugins.seriesplugin.max_time_drift            = ConfigSelectionNumber(0, 600, 1, default = 15)
121 config.plugins.seriesplugin.search_depths             = ConfigSelectionNumber(0, 10, 1, default = 0)
122
123 config.plugins.seriesplugin.skip_during_records       = ConfigYesNo(default=False)
124 config.plugins.seriesplugin.skip_pattern_match        = ConfigYesNo(default=True)
125
126 config.plugins.seriesplugin.autotimer_independent     = ConfigYesNo(default = False)
127 config.plugins.seriesplugin.independent_cycle         = ConfigSelectionNumber(5, 24*60, 5, default = 60)
128 config.plugins.seriesplugin.independent_retry         = ConfigYesNo(default = False)
129
130 config.plugins.seriesplugin.check_timer_list          = ConfigYesNo(default = False)
131
132 config.plugins.seriesplugin.timer_popups              = ConfigYesNo(default = True)
133 config.plugins.seriesplugin.timer_popups_success      = ConfigYesNo(default = False)
134 config.plugins.seriesplugin.timer_popups_timeout      = ConfigSelectionNumber(-1, 20, 1, default = 3)
135
136 config.plugins.seriesplugin.socket_timeout            = ConfigSelectionNumber(0, 600, 1, default = 30)
137
138 config.plugins.seriesplugin.caching                   = ConfigYesNo(default = True)
139 config.plugins.seriesplugin.caching_expiration        = ConfigSelectionNumber(0, 48, 1, default = 6)
140
141 config.plugins.seriesplugin.debug_prints              = ConfigYesNo(default = False)
142 config.plugins.seriesplugin.write_log                 = ConfigYesNo(default = False)
143 config.plugins.seriesplugin.log_file                  = ConfigText(default = "/tmp/seriesplugin.log", fixed_size = False)
144 config.plugins.seriesplugin.log_reply_user            = ConfigText(default = "Dreambox User", fixed_size = False)
145 config.plugins.seriesplugin.log_reply_mail            = ConfigText(default = "myemail@home.com", fixed_size = False)
146
147 # Internal
148 config.plugins.seriesplugin.lookup_counter            = ConfigNumber(default = 0)
149 #config.plugins.seriesplugin.uid                       = ConfigText(default = str(time()), fixed_size = False)
150
151
152 #######################################################
153 # Start
154 def start(reason, **kwargs):
155         if config.plugins.seriesplugin.enabled.value:
156                 # Startup
157                 if reason == 0:
158                         # Start on demand if it is requested
159                         if config.plugins.seriesplugin.autotimer_independent.value:
160                                 startIndependent()
161                         
162                 # Shutdown
163                 elif reason == 1:
164                         from SeriesPlugin import resetInstance
165                         resetInstance()
166
167
168 #######################################################
169 # Plugin configuration
170 def setup(session, *args, **kwargs):
171         try:
172                 session.open(SeriesPluginConfiguration)
173         except Exception as e:
174                 splog(_("SeriesPlugin setup exception ") + str(e))
175                 #exc_type, exc_value, exc_traceback = sys.exc_info()
176                 #splog( exc_type, exc_value, exc_traceback )
177
178
179 #######################################################
180 # Event Info
181 def info(session, service=None, event=None, *args, **kwargs):
182         if config.plugins.seriesplugin.enabled.value:
183                 try:
184                         session.open(SeriesPluginInfoScreen, service, event)
185                 except Exception as e:
186                         splog(_("SeriesPlugin info exception ") + str(e))
187                         #exc_type, exc_value, exc_traceback = sys.exc_info()
188                         #splog( exc_type, exc_value, exc_traceback )
189
190
191 #######################################################
192 # Extensions menu
193 def sp_extension(session, *args, **kwargs):
194         if config.plugins.seriesplugin.enabled.value:
195                 try:
196                         if session:
197                                 session.open(SeriesPluginInfoScreen)
198                 except Exception as e:
199                         splog(_("SeriesPlugin extension exception ") + str(e))
200
201
202 #######################################################
203 # Channel menu
204 def channel(session, service=None, *args, **kwargs):
205         if config.plugins.seriesplugin.enabled.value:
206                 try:
207                         from enigma import eServiceCenter
208                         info = eServiceCenter.getInstance().info(service)
209                         event = info.getEvent(service)
210                         session.open(SeriesPluginInfoScreen, service, event)
211                 except Exception as e:
212                         splog(_("SeriesPlugin extension exception ") + str(e))
213
214
215 #######################################################
216 # Timer
217 def checkTimers(session, *args, **kwargs):
218         runIndependent()
219
220
221 #######################################################
222 # Movielist menu rename
223 def movielist_rename(session, service, services=None, *args, **kwargs):
224         if config.plugins.seriesplugin.enabled.value:
225                 try:
226                         if services:
227                                 if not isinstance(services, list):
228                                         services = [services]   
229                         else:
230                                 services = [service]
231                         SeriesPluginRenamer(session, services)
232                 except Exception as e:
233                         splog(_("SeriesPlugin renamer exception ") + str(e))
234
235
236 #######################################################
237 # Movielist menu info
238 def movielist_info(session, service, *args, **kwargs):
239         if config.plugins.seriesplugin.enabled.value:
240                 try:
241                         session.open(SeriesPluginInfoScreen, service)
242                 except Exception as e:
243                         splog(_("SeriesPlugin extension exception ") + str(e))
244
245
246 #######################################################
247 # Timer renaming
248
249 # Synchronous call, blocks until we have the information
250 def getSeasonAndEpisode(timer, name, begin, end, *args, **kwargs):
251         result = None
252         if config.plugins.seriesplugin.enabled.value:
253                 try:
254                         spt = SeriesPluginTimer(timer, name, begin, end, True)
255                         result = spt.getSeasonAndEpisode(timer, name, begin, end)
256                 except Exception as e:
257                         splog(_("SeriesPlugin label exception ") + str(e))
258         return result
259
260 # Synchronous call, blocks until we have the information
261 loop_data = []
262 loop_counter = 0
263 def getSeasonEpisode(service_ref, name, begin, end, description, path, *args, **kwargs):
264         result = None
265         if config.plugins.seriesplugin.enabled.value:
266                 try:
267                         from SeriesPlugin import getInstance, refactorTitle, refactorDescription, refactorDirectory
268                         seriesPlugin = getInstance()
269                         data = seriesPlugin.getEpisodeBlocking(
270                                 name, begin, end, service_ref, future=True
271                         )
272                         global loop_counter
273                         loop_counter += 1
274                         if data and len(data) == 4:
275                                 name = str(refactorTitle(name, data))
276                                 description = str(refactorDescription(description, data))
277                                 path = refactorDirectory(path, data)
278                                 return (name, description, path)
279                         elif data:
280                                 global loop_data
281                                 loop_data.append( str(data) )
282                         return str(data)
283                 except Exception as e:
284                         splog(_("SeriesPlugin label exception ") + str(e))
285         return result
286
287 def showResult(*args, **kwargs):
288         global loop_data, loop_counter
289         if not loop_data and config.plugins.seriesplugin.timer_popups_success.value:
290                 AddPopup(
291                         "SeriesPlugin:\n" + _("%d timer renamed successfully") % (loop_counter),
292                         MessageBox.TYPE_ERROR,
293                         int(config.plugins.seriesplugin.timer_popups_timeout.value),
294                         'SP_PopUp_ID_Finished'
295                 )
296         elif loop_data and config.plugins.seriesplugin.timer_popups.value:
297                 AddPopup(
298                         "SeriesPlugin:\n" + _("SP has been finished with errors:\n") +"\n" +"\n".join(loop_data),
299                         MessageBox.TYPE_ERROR,
300                         int(config.plugins.seriesplugin.timer_popups_timeout.value),
301                         'SP_PopUp_ID_Finished'
302                 )
303         loop_data = []
304         loop_counter = 0
305
306 # Call asynchronous
307 def renameTimer(timer, name, begin, end, *args, **kwargs):
308         if config.plugins.seriesplugin.enabled.value:
309                 try:
310                         SeriesPluginTimer(timer, name, begin, end)
311                 except Exception as e:
312                         splog(_("SeriesPlugin label exception ") + str(e))
313
314
315 # For compatibility reasons
316 def modifyTimer(timer, name, *args, **kwargs):
317         if config.plugins.seriesplugin.enabled.value:
318                 splog("SeriesPlugin modifyTimer is deprecated - Update Your AutoTimer!")
319                 try:
320                         SeriesPluginTimer(timer, name or timer.name, timer.begin, timer.end)
321                 except Exception as e:
322                         splog(_("SeriesPlugin label exception ") + str(e))
323
324
325 # For compatibility reasons
326 def labelTimer(timer, begin=None, end=None, *args, **kwargs):
327         if config.plugins.seriesplugin.enabled.value:
328                 splog("SeriesPlugin labelTimer is deprecated - Update Your AutoTimer!")
329                 try:
330                         SeriesPluginTimer(timer, timer.name, timer.begin, timer.end)
331                 except Exception as e:
332                         splog(_("SeriesPlugin label exception ") + str(e))
333
334
335 #######################################################
336 # Plugin main function
337 def Plugins(**kwargs):
338         descriptors = []
339         
340         #TODO icon
341         descriptors.append( PluginDescriptor(
342                                                                                         name = NAME + " " + _("Setup"),
343                                                                                         description = NAME + " " + _("Setup"),
344                                                                                         where = PluginDescriptor.WHERE_PLUGINMENU,
345                                                                                         fnc = setup,
346                                                                                         needsRestart = False) )
347         
348         if config.plugins.seriesplugin.enabled.value:
349                 
350                 overwriteAutoTimer()
351                 
352                 descriptors.append( PluginDescriptor(
353                                                                                                         #where = PluginDescriptor.WHERE_SESSIONSTART,
354                                                                                                         where = PluginDescriptor.WHERE_AUTOSTART,
355                                                                                                         needsRestart = False,
356                                                                                                         fnc = start) )
357
358                 if config.plugins.seriesplugin.menu_info.value:
359                         descriptors.append( PluginDescriptor(
360                                                                                                         name = SHOWINFO,
361                                                                                                         description = SHOWINFO,
362                                                                                                         where = PluginDescriptor.WHERE_EVENTINFO,
363                                                                                                         needsRestart = False,
364                                                                                                         fnc = info) )
365
366                 if config.plugins.seriesplugin.menu_extensions.value:
367                         descriptors.append(PluginDescriptor(
368                                                                                                         name = SHOWINFO,
369                                                                                                         description = SHOWINFO,
370                                                                                                         where = PluginDescriptor.WHERE_EXTENSIONSMENU,
371                                                                                                         fnc = sp_extension,
372                                                                                                         needsRestart = False) )
373                 
374                 if config.plugins.seriesplugin.check_timer_list.value:
375                         descriptors.append(PluginDescriptor(
376                                                                                                         name = CHECKTIMERS,
377                                                                                                         description = CHECKTIMERS,
378                                                                                                         where = PluginDescriptor.WHERE_EXTENSIONSMENU,
379                                                                                                         fnc = checkTimers,
380                                                                                                         needsRestart = False) )
381                 
382                 if config.plugins.seriesplugin.menu_movie_info.value:
383                         descriptors.append( PluginDescriptor(
384                                                                                                         name = SHOWINFO,
385                                                                                                         description = SHOWINFO,
386                                                                                                         where = PluginDescriptor.WHERE_MOVIELIST,
387                                                                                                         fnc = movielist_info,
388                                                                                                         needsRestart = False) )
389                 
390                 if config.plugins.seriesplugin.menu_movie_rename.value:
391                         descriptors.append( PluginDescriptor(
392                                                                                                         name = RENAMESERIES,
393                                                                                                         description = RENAMESERIES,
394                                                                                                         where = PluginDescriptor.WHERE_MOVIELIST,
395                                                                                                         fnc = movielist_rename,
396                                                                                                         needsRestart = False) )
397                 
398                 if config.plugins.seriesplugin.menu_channel.value:
399                         try:
400                                 descriptors.append( PluginDescriptor(
401                                                                                                         name = SHOWINFO,
402                                                                                                         description = SHOWINFO,
403                                                                                                         where = PluginDescriptor.WHERE_CHANNEL_CONTEXT_MENU,
404                                                                                                         fnc = channel,
405                                                                                                         needsRestart = False) )
406                         except:
407                                 addSeriesPlugin(WHERE_CHANNELMENU, SHOWINFO)
408                 
409                 if config.plugins.seriesplugin.menu_epg.value:
410                         addSeriesPlugin(WHERE_EPGMENU, SHOWINFO)
411
412         return descriptors
413
414
415 #######################################################
416 # Override EPGSelection enterDateTime
417 EPGSelection_enterDateTime = None
418 #EPGSelection_openOutdatedEPGSelection = None
419 def SPEPGSelectionInit():
420         print "SeriesPlugin override EPGSelection"
421         global EPGSelection_enterDateTime #, EPGSelection_openOutdatedEPGSelection
422         if EPGSelection_enterDateTime is None: # and EPGSelection_openOutdatedEPGSelection is None:
423                 from Screens.EpgSelection import EPGSelection
424                 EPGSelection_enterDateTime = EPGSelection.enterDateTime
425                 EPGSelection.enterDateTime = enterDateTime
426                 #EPGSelection_openOutdatedEPGSelection = EPGSelection.openOutdatedEPGSelection
427                 #EPGSelection.openOutdatedEPGSelection = openOutdatedEPGSelection
428                 EPGSelection.SPcloseafterfinish = closeafterfinish
429
430 def SPEPGSelectionUndo():
431         print "SeriesPlugin undo override EPGSelection"
432         global EPGSelection_enterDateTime #, EPGSelection_openOutdatedEPGSelection
433         if EPGSelection_enterDateTime: # and EPGSelection_openOutdatedEPGSelection:
434                 from Screens.EpgSelection import EPGSelection
435                 EPGSelection.enterDateTime = EPGSelection_enterDateTime
436                 EPGSelection_enterDateTime = None
437                 #EPGSelection.openOutdatedEPGSelection = EPGSelection_openOutdatedEPGSelection
438                 #EPGSelection_openOutdatedEPGSelection = None
439
440 def enterDateTime(self):
441         from Screens.EpgSelection import EPG_TYPE_SINGLE,EPG_TYPE_MULTI,EPG_TYPE_SIMILAR
442         event = self["Event"].event
443         if self.type == EPG_TYPE_SINGLE:
444                 service = self.currentService
445         elif self.type == EPG_TYPE_MULTI:       
446                 service = self.services
447         elif self.type == EPG_TYPE_SIMILAR:
448                 service = self.currentService
449         if service and event:
450                 self.session.openWithCallback(self.SPcloseafterfinish, SeriesPluginInfoScreen, service, event) 
451                 return
452         EPGSelection_enterDateTime(self)
453
454 #def openOutdatedEPGSelection(self, reason=None):
455 #       if reason == 1:
456 #               EPGSelection_enterDateTime(self)
457
458
459 #######################################################
460 # Override ChannelContextMenu
461 ChannelContextMenu__init__ = None
462 def SPChannelContextMenuInit():
463         print "[SeriesPlugin] override ChannelContextMenu.__init__"
464         global ChannelContextMenu__init__
465         if ChannelContextMenu__init__ is None:
466                 from Screens.ChannelSelection import ChannelContextMenu
467                 ChannelContextMenu__init__ = ChannelContextMenu.__init__
468                 ChannelContextMenu.__init__ = SPChannelContextMenu__init__
469                 ChannelContextMenu.SPchannelShowSeriesInfo = channelShowSeriesInfo
470                 ChannelContextMenu.SPcloseafterfinish = closeafterfinish
471
472 def SPChannelContextMenuUndo():
473         print "[SeriesPlugin] override ChannelContextMenu.__init__"
474         global ChannelContextMenu__init__
475         if ChannelContextMenu__init__:
476                 from Screens.ChannelSelection import ChannelContextMenu
477                 ChannelContextMenu.__init__ = ChannelContextMenu__init__
478                 ChannelContextMenu__init__ = None
479
480 def SPChannelContextMenu__init__(self, session, csel):
481         from Components.ChoiceList import ChoiceEntryComponent
482         from Screens.ChannelSelection import MODE_TV
483         from Tools.BoundFunction import boundFunction
484         from enigma import eServiceReference
485         ChannelContextMenu__init__(self, session, csel)
486         current = csel.getCurrentSelection()
487         current_sel_path = current.getPath()
488         current_sel_flags = current.flags
489         if csel.mode == MODE_TV and not (current_sel_path or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
490                 self["menu"].list.insert(0, ChoiceEntryComponent(text=(SHOWINFO, boundFunction(self.SPchannelShowSeriesInfo))))
491
492 def channelShowSeriesInfo(self):
493         splog( "[SeriesPlugin] channelShowSeriesInfo ")
494         if config.plugins.seriesplugin.enabled.value:
495                 try:
496                         from enigma import eServiceCenter
497                         service = self.csel.servicelist.getCurrent()
498                         info = eServiceCenter.getInstance().info(service)
499                         event = info.getEvent(service)
500                         self.session.openWithCallback(self.SPcloseafterfinish, SeriesPluginInfoScreen, service, event)
501                 except Exception as e:
502                         splog(_("SeriesPlugin info exception ") + str(e))
503
504 def closeafterfinish(self, retval=None):
505         self.close()
506
507
508 #######################################################
509 # Add / Remove menu functions
510 def addSeriesPlugin(menu, title, fnc=None):
511         # Add to menu
512         if( menu == WHERE_EPGMENU ):
513                 SPEPGSelectionInit()
514         elif( menu == WHERE_CHANNELMENU ):
515                 try:
516                         addSeriesPlugin(PluginDescriptor.WHERE_CHANNEL_CONTEXT_MENU, SHOWINFO, fnc)
517                 except:
518                         SPChannelContextMenuInit()
519         else:
520                 from Components.PluginComponent import plugins
521                 if plugins:
522                         for p in plugins.getPlugins( where = menu ):
523                                 if p.name == title:
524                                         # Plugin is already in menu
525                                         break
526                         else:
527                                 # Plugin not in menu - add it
528                                 plugin = PluginDescriptor(
529                                                                                                                                 name = title,
530                                                                                                                                 description = title,
531                                                                                                                                 where = menu,
532                                                                                                                                 needsRestart = False,
533                                                                                                                                 fnc = fnc)
534                                 if menu in plugins.plugins:
535                                         plugins.plugins[ menu ].append(plugin)
536
537
538 def removeSeriesPlugin(menu, title):
539         # Remove from menu
540         if( menu == WHERE_EPGMENU ):
541                 SPEPGSelectionUndo()
542         elif( menu == WHERE_CHANNELMENU ):
543                 try:
544                         removeSeriesPlugin(PluginDescriptor.WHERE_CHANNEL_CONTEXT_MENU, SHOWINFO)
545                 except:
546                         SPChannelContextMenuUndo()
547         else:
548                 from Components.PluginComponent import plugins
549                 if plugins:
550                         for p in plugins.getPlugins( where = menu ):
551                                 if p.name == title:
552                                         plugins.plugins[ menu ].remove(p)
553                                         break
554
555
556 #######################################################
557 # Overwrite AutoTimer support functions
558
559 try:
560         from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
561         #from Plugins.Extensions.AutoTimer.plugin import autotimer as AutoTimer
562 except:
563         AutoTimer = None
564
565 ATmodifyTimer = None
566
567
568 def overwriteAutoTimer():
569         try:
570                 global ATmodifyTimer
571                 if AutoTimer:
572                         if ATmodifyTimer is None:
573                                 # Backup original function
574                                 ATmodifyTimer = AutoTimer.modifyTimer
575                                 # Overwrite function
576                                 AutoTimer.modifyTimer = SPmodifyTimer
577         except:
578                 splog("SeriesPlugin found old AutoTimer")
579
580
581 def recoverAutoTimer():
582         try:
583                 global ATmodifyTimer
584                 if AutoTimer:
585                         if ATmodifyTimer:
586                                 AutoTimer.modifyTimer = ATmodifyTimer
587                                 ATmodifyTimer = None
588         except:
589                 splog("SeriesPlugin found old AutoTimer")
590
591
592 #######################################################
593 # Customized support functions
594
595 from difflib import SequenceMatcher
596 from ServiceReference import ServiceReference
597
598 def SPmodifyTimer(self, timer, name, shortdesc, begin, end, serviceref, eit=None):
599         # Never overwrite existing names, You will lose Your series informations
600         #timer.name = name
601         # Only overwrite non existing descriptions
602         #timer.description = timer.description or shortdesc
603         timer.begin = int(begin)
604         timer.end = int(end)
605         timer.service_ref = ServiceReference(serviceref)
606         if eit:
607                 timer.eit = eit