EPGSearch: the last change was not acceptable, we will NOT modify default behaviour...
[enigma2-plugins.git] / epgsearch / src / EPGSearch.py
1 # for localized messages
2 from enigma import eEPGCache, eServiceCenter, eServiceReference, RT_HALIGN_LEFT, \
3                 RT_HALIGN_RIGHT, RT_VALIGN_CENTER, eListboxPythonMultiContent
4
5 from Tools.LoadPixmap import LoadPixmap
6 from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS
7 from ServiceReference import ServiceReference
8
9 from EPGSearchSetup import EPGSearchSetup
10 from Screens.ChannelSelection import SimpleChannelSelection
11 from Screens.ChoiceBox import ChoiceBox
12 from Screens.EpgSelection import EPGSelection
13 from Screens.ChannelSelection import ChannelSelectionBase
14 from Screens.EventView import EventViewEPGSelect, EventViewBase
15 from Screens.MessageBox import MessageBox
16 from Screens.InfoBar import InfoBar
17 from Screens.Screen import Screen
18 from Plugins.SystemPlugins.Toolkit.NTIVirtualKeyBoard import NTIVirtualKeyBoard
19 from Plugins.Plugin import PluginDescriptor
20
21 from Components.ActionMap import ActionMap, HelpableActionMap
22 from Components.Button import Button
23 from Components.config import config
24 from Components.EpgList import EPGList, EPG_TYPE_SINGLE, EPG_TYPE_MULTI
25 from Components.TimerList import TimerList
26 from Components.Sources.ServiceEvent import ServiceEvent
27 from Components.Sources.Event import Event
28 from Components.ServiceList import ServiceList, PiconLoader
29 from Components.PluginComponent import plugins
30
31 from . import SearchType
32 from time import localtime, time
33 from operator import itemgetter
34 from Tools.BoundFunction import boundFunction
35 from skin import componentSizes
36
37 # Partnerbox installed and icons in epglist enabled?
38 try:
39         from Plugins.Extensions.Partnerbox.PartnerboxEPGList import \
40                         isInRemoteTimer, getRemoteClockPixmap
41         from Plugins.Extensions.Partnerbox.plugin import \
42                         showPartnerboxIconsinEPGList
43         PartnerBoxIconsEnabled = showPartnerboxIconsinEPGList()
44 except ImportError:
45         PartnerBoxIconsEnabled = False
46
47 # AutoTimer installed?
48 try:
49         from Plugins.Extensions.AutoTimer.AutoTimerEditor import \
50                         addAutotimerFromEvent, addAutotimerFromSearchString
51         autoTimerAvailable = True
52 except ImportError:
53         autoTimerAvailable = False
54
55 def searchEvent(session, event, service):
56         if not event:
57                 return
58         session.open(EPGSearch, event.getEventName())
59
60 # Overwrite pzyP4T.__init__ with our modified one
61 basePzyP4T__init__ = None
62 def pzyP4TInit():
63         global basePzyP4T__init__
64         try:
65                 from Plugins.Extensions.pzyP4T.plugin import PzyP4T
66                 if basePzyP4T__init__ is None:
67                         basePzyP4T__init__ = PzyP4T.__init__
68                 PzyP4T.__init__ = PzyP4T__init__
69         except:
70                 basepzyP4T__init__ = None
71
72 # Modified PzyP4T__init__ for audio-key
73 def PzyP4T__init__(self, session):
74         basePzyP4T__init__(self, session)
75
76         def openEPGSearch():
77                 event = event = self["Event"].getCurrentEvent()
78                 if event:
79                         eventName = event.getEventName()
80                         self.session.open(EPGSearch, eventName)
81
82         self["InfobarAudioSelectionActions"] = ActionMap(["InfobarAudioSelectionActions"],
83                         {
84                                 "audioSelection": openEPGSearch,
85                         })
86
87 # Modified EPGSearchList with support for PartnerBox
88 class EPGSearchList(EPGList):
89         def __init__(self, type=EPG_TYPE_SINGLE, selChangedCB=None, timer=None):
90                 EPGList.__init__(self, type, selChangedCB, timer)
91                 self.l.setBuildFunc(self.buildEPGSearchEntry)
92
93                 self.piconLoader = PiconLoader()
94
95                 sizes = componentSizes[EPGList.SKIN_COMPONENT_KEY]
96                 self._iconWidth = sizes.get(EPGList.SKIN_COMPONENT_ICON_WIDTH, 21)
97                 self._iconHeight = sizes.get(EPGList.SKIN_COMPONENT_ICON_HEIGHT, 21)
98                 self._iconHPos = sizes.get(EPGList.SKIN_COMPONENT_ICON_HPOS, 4)
99                 self._itemMargin = sizes.get(EPGList.SKIN_COMPONENT_ITEM_MARGIN, 10)
100
101                 servicelist_sizes = componentSizes["ServiceList"]
102                 self._picon_width = servicelist_sizes.get(ServiceList.KEY_PICON_WIDTH, 58)
103
104                 if PartnerBoxIconsEnabled:
105                         # Partnerbox Clock Icons
106                         self.remote_clock_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock.png')
107                         self.remote_clock_add_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_add.png')
108                         self.remote_clock_pre_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_pre.png')
109                         self.remote_clock_post_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_post.png')
110                         self.remote_clock_prepost_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_prepost.png')
111
112         def buildEPGSearchEntry(self, service, eventId, beginTime, duration, EventName):
113                 rec1 = beginTime and self.timer.isInTimer(eventId, beginTime, duration, service)
114                 # Partnerbox
115                 if PartnerBoxIconsEnabled:
116                         rec2 = beginTime and isInRemoteTimer(self,beginTime, duration, service)
117                 else:
118                         rec2 = False
119                 r1 = self.weekday_rect
120                 r2 = self.datetime_rect
121                 r3 = self.descr_rect
122                 t = localtime(beginTime)
123                 serviceref = ServiceReference(service) # for Servicename
124                 serviceName = serviceref.getServiceName() + ": "
125
126                 #delete serviceName if set it in setup and it is most matched service
127                 if config.plugins.epgsearch.show_sname_in_title.value and service == self.mostSearchService:
128                         serviceName = ""
129
130                 res = [
131                         None, # no private data needed
132                         (eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, self.days[t[6]]),
133                         (eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, "%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4]))
134                 ]
135
136                 #add picon if set this option in setup
137                 picon = None
138                 if config.plugins.epgsearch.show_picon.value:
139                         picon = self.piconLoader.getPicon(service)
140                 left_pos = r3.left()
141                 if picon is not None:
142                         res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, left_pos, 2, self._picon_width, r3.height()-3, picon))
143                         left_pos = r3.left() + self._picon_width + self._itemMargin
144                         serviceName = "" #if load picon delete servicename
145
146                 if rec1 or rec2:
147                         if rec1:
148                                 clock_pic = self.getClockPixmap(service, beginTime, duration, eventId)
149                                 # maybe Partnerbox too
150                                 if rec2:
151                                         clock_pic_partnerbox = getRemoteClockPixmap(self,service, beginTime, duration, eventId)
152                         else:
153                                 clock_pic = getRemoteClockPixmap(self,service, beginTime, duration, eventId)
154                         if rec1 and rec2:
155                                 # Partnerbox and local
156                                 res.extend((
157                                         (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, left_pos, self._iconHPos, self._iconWidth, self._iconHeight, clock_pic),
158                                         (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, left_pos + self._iconWidth + self._itemMargin, self._iconHPos, self._iconWidth, self._iconHeight, clock_pic_partnerbox),
159                                         (eListboxPythonMultiContent.TYPE_TEXT, left_pos + self._iconWidth*2 + self._itemMargin*2, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName + EventName)))
160                         else:
161                                 res.extend((
162                                         (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, left_pos, self._iconHPos, self._iconWidth, self._iconHeight, clock_pic),
163                                         (eListboxPythonMultiContent.TYPE_TEXT, left_pos + self._iconWidth + self._itemMargin, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName + EventName)))
164                 else:
165                         res.append((eListboxPythonMultiContent.TYPE_TEXT, left_pos, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName + EventName))
166                 return res
167
168 # main class of plugin
169 class EPGSearch(EPGSelection):
170         def __init__(self, session, *args):
171                 Screen.__init__(self, session)
172                 self.skinName = ["EPGSearch", "EPGSelection"]
173
174                 self.searchargs = args
175                 self.currSearch = ""
176
177                 # XXX: we lose sort begin/end here
178                 self["key_yellow"] = Button(_("New Search"))
179                 self["key_blue"] = Button(_("History"))
180
181 # begin stripped copy of EPGSelection.__init__
182                 self.bouquetChangeCB = None
183                 self.serviceChangeCB = None
184                 self.ask_time = -1 #now
185                 self["key_red"] = Button("")
186                 self.closeRecursive = False
187                 self.saved_title = None
188                 self["Service"] = ServiceEvent()
189                 self["Event"] = Event()
190                 self.type = EPG_TYPE_SINGLE
191                 self.currentService=None
192                 self.zapFunc = None
193                 self.sort_type = 0
194                 self["key_green"] = Button(_("Add timer"))
195                 self.key_green_choice = self.ADD_TIMER
196                 self.key_red_choice = self.EMPTY
197                 self["list"] = EPGSearchList(type = self.type, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
198                 self["actions"] = ActionMap(["EPGSelectActions", "OkCancelActions", "MenuActions", "InputActions", "InfobarAudioSelectionActions"],
199                         {
200                                 "menu": self.menu,
201                                 "cancel": self.closeScreen,
202                                 "ok": self.eventSelected,
203                                 "timerAdd": self.timerAdd,
204                                 "yellow": self.yellowButtonPressed,
205                                 "blue": self.blueButtonPressed,
206                                 "info": self.infoKeyPressed,
207                                 "red": self.zapTo, # needed --> Partnerbox
208                                 "nextBouquet": self.nextBouquet, # just used in multi epg yet
209                                 "prevBouquet": self.prevBouquet, # just used in multi epg yet
210                                 "nextService": self.nextService, # just used in single epg yet
211                                 "prevService": self.prevService, # just used in single epg yet
212                                 "1": self.importFromTimer,
213                                 "2": self.importFromEPG,
214                                 "3": self.importFromAutoTimer,
215                                 "4": self.addAutoTimer,
216                                 "5": self.exportAutoTimer,
217                                 "6": self.openSPInfoScreen,
218                                 "7": self.openImdb,
219                                 "8": self.openTMDb,
220                                 "9": self.openTMDbSerie,
221                                 "0": self.setup,
222                                 "audioSelection": self.searchNoNumber,
223                         })
224
225                 self["actions"].csel = self
226                 self["list"].mostSearchService = ""
227                 self.onLayoutFinish.append(self.onCreate)
228 # end stripped copy of EPGSelection.__init__
229
230                 # Partnerbox
231                 if PartnerBoxIconsEnabled:
232                         EPGSelection.PartnerboxInit(self, False)
233
234                 self.pluginList = [(p.name, p) for p in plugins.getPlugins(where = [PluginDescriptor.WHERE_EPG_SELECTION_SINGLE_BLUE])]
235
236         def onCreate(self):
237                 self.setTitle(_("EPG Search"))
238
239                 if self.searchargs:
240                         self.doSearchEPG(*self.searchargs)
241                 else:
242                         l = self["list"]
243                         l.recalcEntrySize()
244                         l.list = []
245                         l.l.setList(l.list)
246                 del self.searchargs
247
248                 # Partnerbox
249                 if PartnerBoxIconsEnabled:
250                         EPGSelection.GetPartnerboxTimerlist(self)
251
252         def closeScreen(self):
253                 # Save our history
254                 config.plugins.epgsearch.save()
255                 EPGSelection.closeScreen(self)
256
257         def yellowButtonPressed(self):
258                 self.session.openWithCallback(
259                         self.searchEPG,
260                         NTIVirtualKeyBoard,
261                         title = _("Enter text to search for"),
262                         text = self.currSearch
263                 )
264
265         def infoKeyPressed(self):
266                 cur = self["list"].getCurrent()
267                 event = cur[0]
268                 service = cur[1]
269                 if event is not None:
270                         self.session.open(EventViewEPGSelect, event, service, self.eventViewCallback, self.openSingleServiceEPG, InfoBar.instance.openMultiServiceEPG, self.openSimilarList)
271
272         def openSimilarList(self, eventid, refstr):
273                 self.session.open(EPGSelection, refstr, None, eventid)
274
275         def openSingleServiceEPG(self):
276                 cur = self["list"].getCurrent()
277                 event = cur[0]
278                 service = cur[1]
279                 if event is not None:
280                         self.session.open(EPGSelection, cur[1].ref)
281
282         def menu(self):
283                 options = [
284                         (_("Import from Timer"), self.importFromTimer),
285                         (_("Import from EPG"), self.importFromEPG),
286                 ]
287                 keys = ["1","2"]
288
289                 if autoTimerAvailable:
290                         options.extend((
291                                 (_("Import from AutoTimer"), self.importFromAutoTimer),
292                                 (_("Save search as AutoTimer"), self.addAutoTimer),
293                                 (_("Export selected as AutoTimer"), self.exportAutoTimer),
294                         ))
295                         keys.extend(("3","4","5"))
296                 if fileExists(resolveFilename(SCOPE_PLUGINS, "Extensions/SeriesPlugin/plugin.py")):
297                         options.append((_("Show series info (SP)"), self.openSPInfoScreen))
298                         keys.append("6")
299
300                 if fileExists(resolveFilename(SCOPE_PLUGINS, "Extensions/IMDb/plugin.py")):
301                         options.append((_("Open selected in IMDb"), self.openImdb))
302                         keys.append("7")
303
304                 if fileExists(resolveFilename(SCOPE_PLUGINS, "Extensions/AdvancedMovieSelection/plugin.py")):
305                         options.append((_("Open selected in TMDB Info (AMS)"), self.openTMDb))
306                         options.append((_("Open selected in TMDB Serie Info (AMS)"), self.openTMDbSerie))
307                         keys.extend(("8","9"))
308
309                 options.append((_("Setup"), self.setup))
310                 keys.append("0")
311
312                 for p in self.pluginList:
313                         if not p in options and p[0] != _("Search EPG"):
314                                 options.append(p)
315
316                 self.session.openWithCallback(
317                         self.menuCallback,
318                         ChoiceBox,
319                         list = options,
320                         keys = keys,
321                         title = _("EPGSearch menu")
322                 )
323
324         def menuCallback(self, ret):
325                 if ret in self.pluginList:
326                         cur = self['list'].getCurrent()
327                         event = cur and cur[0]
328                         service = cur and cur[1]
329                         if event:
330                                 ret[1](self.session, event, service)
331                 else:
332                         ret and ret[1]()
333
334         def importFromTimer(self):
335                 self.session.openWithCallback(
336                         self.searchEPG,
337                         EPGSearchTimerImport
338                 )
339
340         def importFromEPG(self):
341                 self.session.openWithCallback(
342                         self.searchEPG,
343                         EPGSearchChannelSelection
344                 )
345
346         def importFromAutoTimer(self):
347                 removeInstance = False
348                 try:
349                         # Import Instance
350                         from Plugins.Extensions.AutoTimer.plugin import autotimer
351
352                         if autotimer is None:
353                                 removeInstance = True
354                                 # Create an instance
355                                 from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
356                                 autotimer = AutoTimer()
357
358                         # Read in configuration
359                         autotimer.readXml()
360                 except Exception as e:
361                         self.session.open(
362                                 MessageBox,
363                                 _("Could not read AutoTimer timer list: %s") % e,
364                                 type = MessageBox.TYPE_ERROR
365                         )
366                 else:
367                         # Fetch match strings
368                         # XXX: we could use the timer title as description
369                         options = [(x.match, x.match) for x in autotimer.getTimerList()]
370
371                         self.session.openWithCallback(
372                                 self.searchEPGWrapper,
373                                 ChoiceBox,
374                                 title = _("Select text to search for"),
375                                 list = options
376                         )
377                 finally:
378                         # Remove instance if there wasn't one before
379                         if removeInstance:
380                                 autotimer = None
381
382         def addAutoTimer(self):
383                 if autoTimerAvailable:
384                         addAutotimerFromSearchString(self.session, self.currSearch)
385
386         def exportAutoTimer(self):
387                 cur = self['list'].getCurrent()
388                 if cur is None:
389                         return
390                 if autoTimerAvailable:
391                         addAutotimerFromEvent(self.session, cur[0], cur[1])
392
393         def openSPInfoScreen(self):
394                 cur = self['list'].getCurrent()
395                 if cur is None:
396                         return
397                 try:
398                         from Plugins.Extensions.SeriesPlugin.SeriesPluginInfoScreen import SeriesPluginInfoScreen
399                         service=cur[1]
400                         event = cur[0]
401                         self.session.open(SeriesPluginInfoScreen, service, event)
402                 except ImportError as ie:
403                         pass
404
405         def openImdb(self):
406                 cur = self['list'].getCurrent()
407                 if cur is None:
408                         return
409                 try:
410                         from Plugins.Extensions.IMDb.plugin import IMDB
411                         self.session.open(IMDB, cur[0].getEventName())
412                 except ImportError as ie:
413                         pass
414
415         def openTMDb(self):
416                 cur = self['list'].getCurrent()
417                 if cur is None:
418                         return
419                 try:
420                         from Plugins.Extensions.AdvancedMovieSelection.plugin import tmdbInfo
421                         tmdbInfo(self.session, cur[0].getEventName())
422                 except ImportError as ie:
423                         pass
424
425         def openTMDbSerie(self):
426                 cur = self['list'].getCurrent()
427                 if cur is None:
428                         return
429                 try:
430                         from Plugins.Extensions.AdvancedMovieSelection.plugin import tmdbSeriesInfo
431                         tmdbSeriesInfo(self.session, cur[0].getEventName())
432                 except ImportError as ie:
433                         pass
434
435         def setup(self):
436                 self.session.openWithCallback(self.closeSetupCallback, EPGSearchSetup)
437
438         def closeSetupCallback(self):
439                 self.doSearchEPG(self.currSearch, self.currSearchSave, self.currSearchDescription)
440
441         def searchNoNumber(self):
442                 search_txt = self.currSearch
443                 search_txt = search_txt.translate(None, "1234567890(/)").strip()
444
445                 self.doSearchEPG(search_txt, self.currSearchSave, self.currSearchDescription)
446
447         def blueButtonPressed(self):
448                 options = [(x, x) for x in config.plugins.epgsearch.history.value]
449
450                 if options:
451                         self.session.openWithCallback(
452                                 self.searchEPGWrapper,
453                                 ChoiceBox,
454                                 title = _("Select text to search for"),
455                                 list = options
456                         )
457                 else:
458                         self.session.open(
459                                 MessageBox,
460                                 _("No history"),
461                                 type = MessageBox.TYPE_INFO
462                         )
463
464         def searchEPGWrapper(self, ret):
465                 if ret:
466                         self.searchEPG(ret[1])
467
468         def searchEPG(self, searchString = None, searchSave = True):
469                 if not searchString:
470                         return
471                 searchType = config.plugins.epgsearch.search_type.value
472                 if  searchType == SearchType.ASK:
473                         boundCallback = boundFunction(self.onSearchEPGCallback, searchString=searchString, searchSave=searchSave)
474                         choices = [ (_("Title only"), False),
475                                                 (_("Title and Description"), True) ]
476                         self.session.openWithCallback(boundCallback, ChoiceBox, list=choices, title=_("Where to search for '%s'?") %(searchString), windowTitle=_("EPG Search"))
477                 else:
478                         searchDescription = searchType == SearchType.TITLE_DESCRIPTION
479                         self.doSearchEPG(searchString, searchSave, searchDescription)
480
481         def onSearchEPGCallback(self, answer, searchString=None, searchSave=True):
482                 searchDescription = answer and answer[1]
483                 self.doSearchEPG(searchString, searchSave, searchDescription)
484
485         def doSearchEPG(self, searchString = None, searchSave = True, searchDescription=False):
486                 self.currSearchSave = searchSave
487                 self.currSearchDescription = searchDescription
488                 if searchString:
489                         self.currSearch = searchString
490                         if searchSave:
491                                 # Maintain history
492                                 history = config.plugins.epgsearch.history.value
493                                 if searchString not in history:
494                                         history.insert(0, searchString)
495                                         maxLen = config.plugins.epgsearch.history_length.value
496                                         if len(history) > maxLen:
497                                                 del history[maxLen:]
498                                 else:
499                                         history.remove(searchString)
500                                         history.insert(0, searchString)
501
502                         # Search EPG, default to empty list
503                         searchType = eEPGCache.PARTIAL_TITLE_SEARCH
504                         if config.plugins.epgsearch.search_type.value == "exact_title":
505                                 searchType = eEPGCache.EXACT_TITLE_SEARCH
506                         epgcache = eEPGCache.getInstance() # XXX: the EPGList also keeps an instance of the cache but we better make sure that we get what we want :-)
507                         ret = epgcache.search(('RIBDT', 1000, searchType, searchString, eEPGCache.NO_CASE_CHECK)) or []
508                         if searchDescription:
509                                 ret += epgcache.search(('RIBDT', 1000, eEPGCache.PARTIAL_DESCRIPTION_SEARCH, searchString, eEPGCache.NO_CASE_CHECK)) or []
510                                 #condense by eventids
511                                 condensed = {}
512                                 for item in ret:
513                                         condensed[item[1]] = item
514                                 ret = condensed.values()
515                         ret.sort(key=itemgetter(2)) # sort by time
516
517                         #filter epg-matches for selected bouquet from settings
518                         if config.plugins.epgsearch.search_scope.value != "all" and len(ret):
519                                 ret = self.filterEPGmatches(ret)
520
521                         #add short description to search result
522                         if config.plugins.epgsearch.show_shortdesc.value and len(ret):
523                                 ret = self.addShortDescription(epgcache, ret)
524
525                         #get most searched service
526                         mostSearchService = ""
527                         if not config.plugins.epgsearch.show_picon.value and config.plugins.epgsearch.show_sname_in_title.value and len(ret):
528                                 mostSearchService = self.getMostSearchService(ret)
529
530                         # Update List
531                         l = self["list"]
532
533                         #set mostsearchservice to screen-title
534                         title = _("EPG Search")
535                         l.mostSearchService = mostSearchService #save the value also to EPGList-Class
536                         if not config.plugins.epgsearch.show_picon.value and mostSearchService != "":
537                                 serviceref = ServiceReference(mostSearchService) # for Servicename
538                                 serviceName = serviceref.getServiceName()
539                                 title += " - " + serviceName
540                         self.setTitle(title)
541                         l.recalcEntrySize()
542                         l.list = ret
543                         l.l.setList(ret)
544
545         def getMostSearchService(self, matches):
546                 services = [x[0]for x in matches]
547                 mostSearchService = max(services, key = services.count)
548                 return mostSearchService
549
550         def filterEPGmatches(self, matches):
551                 services = self.getBouquetServiceList(config.plugins.epgsearch.search_scope.value)
552                 if len(services): #only if return services to check
553                         ret1 = []
554                         for event in matches:
555                                 timecheck=True
556                                 if config.plugins.epgsearch.show_events.value == "current_future" and int(event[2])+int(event[3]) < time():
557                                         timecheck = False #if is an old event
558                                 elif config.plugins.epgsearch.show_events.value == "future" and int(event[2]) < time():
559                                         timecheck = False #if is a current or old event
560                                 if config.plugins.epgsearch.show_events.value == "current" and (int(event[2]) > time() or int(event[2])+int(event[3]) < time()):
561                                         timecheck = False #if is a future or an old event
562                                 if str(event[0]) in services and timecheck:
563                                         ret1.append(event)
564                         matches = ret1
565                 return matches
566
567         def addShortDescription(self, epgcache, events):
568                 new_events=[]
569                 for event in events:
570                         epgEvent = epgcache.lookupEventId(eServiceReference(event[0]), int(event[1]))
571                         if epgEvent:
572                                 shortdesc = str(epgEvent.getShortDescription())
573                                 if len(shortdesc) > 0:
574                                         event_lst = list(event)
575                                         event_lst[4] = event_lst[4] + "  |  " + shortdesc
576                                         event = tuple(event_lst)
577                         new_events.append(event)
578
579                 return new_events
580
581         def getBouquetServiceList(self, bouquet="current"):
582                 infoBarInstance = InfoBar.instance
583                 if infoBarInstance is not None:
584                         servicelist = infoBarInstance.servicelist
585                         if bouquet == "current":
586                                 bouquet = servicelist.getRoot().toString()
587                         services = infoBarInstance.getBouquetServices(eServiceReference(bouquet))
588
589                         service_list = []
590                         for service in services:
591                                 service_ref = service.ref.toString()
592
593                                 serviceref_split = service_ref.split(":")
594                                 if len(serviceref_split)>10: #perhaps on ip-tv or renamed service
595                                         serviceref_split[0]="1"
596                                         serviceref_split[1]="0"
597                                         #cut the service_ref
598                                         service_ref = ":".join(serviceref_split[:10]) + ":"
599
600                                 service_list.append(service_ref)
601
602                         return service_list
603
604 class EPGSearchTimerImport(Screen):
605         def __init__(self, session):
606                 Screen.__init__(self, session)
607                 self.skinName = ["EPGSearchTimerImport", "TimerEditList"]
608
609                 self.list = []
610                 self.fillTimerList()
611
612                 self["timerlist"] = TimerList(self.list)
613
614                 self["key_red"] = Button(_("Cancel"))
615                 self["key_green"] = Button(_("OK"))
616                 self["key_yellow"] = Button("")
617                 self["key_blue"] = Button("")
618
619                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
620                 {
621                         "ok": self.search,
622                         "cancel": self.cancel,
623                         "green": self.search,
624                         "red": self.cancel
625                 }, -1)
626                 self.onLayoutFinish.append(self.setCustomTitle)
627
628         def setCustomTitle(self):
629                 self.setTitle(_("Select a timer to search"))
630
631         def fillTimerList(self):
632                 l = self.list
633                 del l[:]
634
635                 for timer in self.session.nav.RecordTimer.timer_list:
636                         l.append((timer, False))
637
638                 for timer in self.session.nav.RecordTimer.processed_timers:
639                         l.append((timer, True))
640                 l.sort(key = lambda x: x[0].begin)
641
642         def search(self):
643                 cur = self["timerlist"].getCurrent()
644                 if cur:
645                         self.close(cur.name)
646
647         def cancel(self):
648                 self.close(None)
649
650 class EPGSearchChannelSelection(SimpleChannelSelection):
651         def __init__(self, session):
652                 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
653                 self.skinName = ["EPGSearchChannelSelection", "SimpleChannelSelection"]
654
655                 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
656                 {
657                                 "showEPGList": self.channelSelected
658                 })
659
660         def channelSelected(self):
661                 ref = self.getCurrentSelection()
662                 if (ref.flags & 7) == 7:
663                         self.enterPath(ref)
664                 elif not (ref.flags & eServiceReference.isMarker):
665                         self.session.openWithCallback(
666                                 self.epgClosed,
667                                 EPGSearchEPGSelection,
668                                 ref,
669                                 False
670                         )
671
672         def epgClosed(self, ret = None):
673                 if ret:
674                         self.close(ret)
675
676 class EPGSearchEPGSelection(EPGSelection):
677         def __init__(self, session, ref, openPlugin):
678                 EPGSelection.__init__(self, session, ref)
679                 self.skinName = ["EPGSearchEPGSelection", "EPGSelection"]
680                 self["key_green"].text = _("Search")
681                 self.openPlugin = openPlugin
682
683         def infoKeyPressed(self):
684                 self.timerAdd()
685
686         def timerAdd(self):
687                 cur = self["list"].getCurrent()
688                 evt = cur[0]
689                 sref = cur[1]
690                 if not evt:
691                         return
692
693                 if self.openPlugin:
694                         self.session.open(EPGSearch,evt.getEventName())
695                 else:
696                         self.close(evt.getEventName())
697