04c3c4480ade20811c3ab8cd138d880e5d276b2c
[enigma2.git] / lib / python / Screens / ChannelSelection.py
1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ServiceList import ServiceList
4 from Components.ActionMap import NumberActionMap, ActionMap
5 from EpgSelection import EPGSelection
6 from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer
7 from Components.config import config, configElement, ConfigSubsection, configText, currentConfigSelectionElement
8 from Screens.FixedMenu import FixedMenu
9 from Tools.NumericalTextInput import NumericalTextInput
10 from Components.NimManager import nimmanager
11 from Components.ServiceName import ServiceName
12 from Components.Clock import Clock
13 from Components.EventInfo import EventInfo
14 from re import *
15
16 import xml.dom.minidom
17
18 class BouquetSelector(FixedMenu):
19         def __init__(self, session, bouquets, selectedFunc):
20                 self.selectedFunc=selectedFunc
21                 entrys = [ ]
22                 for x in bouquets:
23                         entrys.append((x[0], self.bouquetSelected, x[1]))
24                 FixedMenu.__init__(self, session, "Bouquetlist", entrys)
25                 self.skinName = "Menu"
26
27         def bouquetSelected(self):
28                 self.selectedFunc(self["menu"].getCurrent()[2])
29
30 class ChannelContextMenu(FixedMenu):
31         def __init__(self, session, csel):
32                 self.csel = csel
33
34                 menu = [ ]
35
36                 inBouquetRootList = csel.getRoot().getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
37                 inBouquet = csel.getMutableList() is not None
38                 haveBouquets = csel.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1
39
40                 if not csel.bouquet_mark_edit and not csel.movemode and not inBouquetRootList:
41                         if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
42                                 if haveBouquets:
43                                         menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected))
44                                 else:
45                                         menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
46                         if inBouquet:
47                                 menu.append((_("remove service"), self.removeCurrentService))
48
49                 if inBouquet: # current list is editable?
50                         if not csel.bouquet_mark_edit:
51                                 if not csel.movemode:
52                                         menu.append((_("enable move mode"), self.toggleMoveMode))
53                                         if not inBouquetRootList:
54                                                 if haveBouquets:
55                                                         menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
56                                                 else:
57                                                         menu.append((_("enable favourite edit"), self.bouquetMarkStart))
58                                 else:
59                                         menu.append((_("disable move mode"), self.toggleMoveMode))
60                         elif not inBouquetRootList:
61                                 if haveBouquets:
62                                         menu.append((_("end bouquet edit"), self.bouquetMarkEnd))
63                                         menu.append((_("abort bouquet edit"), self.bouquetMarkAbort))
64                                 else:
65                                         menu.append((_("end favourites edit"), self.bouquetMarkEnd))
66                                         menu.append((_("abort favourites edit"), self.bouquetMarkAbort))
67
68                 menu.append((_("back"), self.close))
69
70                 FixedMenu.__init__(self, session, _("Channel Selection"), menu)
71                 self.skinName = "Menu"
72
73         def addServiceToBouquetSelected(self):
74                 bouquets = self.csel.getBouquetList()
75                 if bouquets is None:
76                         cnt = 0
77                 else:
78                         cnt = len(bouquets)
79                 if cnt > 1: # show bouquet list
80                         self.session.open(BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
81                 elif cnt == 1: # add to only one existing bouquet
82                         self.addCurrentServiceToBouquet(bouquets[0][1])
83                 else: #no bouquets in root.. so assume only one favourite list is used
84                         self.addCurrentServiceToBouquet(self.csel.bouquet_root)
85
86         def addCurrentServiceToBouquet(self, dest):
87                 self.csel.addCurrentServiceToBouquet(dest)
88                 self.close()
89
90         def removeCurrentService(self):
91                 self.csel.removeCurrentService()
92                 self.close()
93
94         def toggleMoveMode(self):
95                 self.csel.toggleMoveMode()
96                 self.close()
97
98         def bouquetMarkStart(self):
99                 self.csel.startMarkedEdit()
100                 self.close()
101
102         def bouquetMarkEnd(self):
103                 self.csel.endMarkedEdit(abort=False)
104                 self.close()
105
106         def bouquetMarkAbort(self):
107                 self.csel.endMarkedEdit(abort=True)
108                 self.close()
109
110 class ChannelSelectionEPG:
111         def __init__(self):
112                 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
113                         {
114                                 "showEPGList": self.showEPGList,
115                         })
116
117         def showEPGList(self):
118                 ref=self.getCurrentSelection()
119                 ptr=eEPGCache.getInstance()
120                 if ptr.startTimeQuery(ref) != -1:
121                         self.session.open(EPGSelection, ref)
122                 else:
123                         print 'no epg for service', ref.toString()
124
125 class ChannelSelectionEdit:
126         def __init__(self):
127                 self.entry_marked = False
128                 self.movemode = False
129                 self.bouquet_mark_edit = False
130                 self.mutableList = None
131                 self.__marked = [ ]
132                 self.saved_title = None
133                 self.saved_root = None
134
135                 class ChannelSelectionEditActionMap(ActionMap):
136                         def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
137                                 ActionMap.__init__(self, contexts, actions, prio)
138                                 self.csel = csel
139                         def action(self, contexts, action):
140                                 if action == "cancel":
141                                         self.csel.handleEditCancel()
142                                 ActionMap.action(self, contexts, action)
143                 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions"],
144                         {
145                                 "contextMenu": self.doContext,
146                         })
147
148         def getMutableList(self, root=eServiceReference()):
149                 if not self.mutableList is None:
150                         return self.mutableList
151                 serviceHandler = eServiceCenter.getInstance()
152                 if not root.valid():
153                         root=self.getRoot()
154                 list = serviceHandler.list(root)
155                 if list is not None:
156                         return list.startEdit()
157                 return None
158
159 #  multiple marked entry stuff ( edit mode, later multiepg selection )
160         def startMarkedEdit(self):
161                 self.mutableList = self.getMutableList()
162                 # add all services from the current list to internal marked set in listboxservicecontent
163                 self.bouquetRoot = self.getRoot()
164                 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
165                 self.saved_title = self.instance.getTitle()
166                 new_title = self.saved_title
167                 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1:
168                         new_title += ' ' + _("[bouquet edit]")
169                 else:
170                         new_title += ' ' + _("[favourite edit]")
171                 self.instance.setTitle(new_title)
172                 self.bouquet_mark_edit = True
173                 self.__marked = self.servicelist.getRootServices()
174                 for x in self.__marked:
175                         self.servicelist.addMarked(eServiceReference(x))
176                 self.saved_root = self.getRoot()
177                 self.showAllServices()
178
179         def endMarkedEdit(self, abort):
180                 if not abort and self.mutableList is not None:
181                         new_marked = set(self.servicelist.getMarked())
182                         old_marked = set(self.__marked)
183                         removed = old_marked - new_marked
184                         added = new_marked - old_marked
185                         changed = False
186                         for x in removed:
187                                 changed = True
188                                 self.mutableList.removeService(eServiceReference(x))
189                         for x in added:
190                                 changed = True
191                                 self.mutableList.addService(eServiceReference(x))
192                         if changed:
193                                 self.mutableList.flushChanges()
194                 self.__marked = []
195                 self.clearMarks()
196                 self.bouquet_mark_edit = False
197                 self.bouquetRoot = None
198                 self.mutableList = None
199                 self.instance.setTitle(self.saved_title)
200                 self.saved_title = None
201                 self.setRoot(self.saved_root)
202
203         def clearMarks(self):
204                 self.servicelist.clearMarks()
205
206         def doMark(self):
207                 ref = self.servicelist.getCurrent()
208                 if self.servicelist.isMarked(ref):
209                         self.servicelist.removeMarked(ref)
210                 else:
211                         self.servicelist.addMarked(ref)
212
213         def removeCurrentService(self):
214                 ref = self.servicelist.getCurrent()
215                 mutableList = self.getMutableList()
216                 if ref.valid() and mutableList is not None:
217                         if not mutableList.removeService(ref):
218                                 currentIndex = self.servicelist.getCurrentIndex()
219                                 self.servicelist.moveDown()
220                                 if self.servicelist.getCurrentIndex() == currentIndex:
221                                         currentIndex -= 1
222                                 mutableList.flushChanges() #FIXME dont flush on each single removed service
223                                 self.setRoot(self.getRoot())
224                                 self.servicelist.moveToIndex(currentIndex)
225
226         def addCurrentServiceToBouquet(self, dest):
227                 mutableList = self.getMutableList(dest)
228                 if not mutableList is None:
229                         if not mutableList.addService(self.servicelist.getCurrent()):
230                                 mutableList.flushChanges()
231                 self.close()
232
233         def toggleMoveMode(self):
234                 if self.movemode:
235                         if self.entry_marked:
236                                 self.toggleMoveMarked() # unmark current entry
237                         self.movemode = False
238                         self.mutableList.flushChanges() # FIXME add check if changes was made
239                         self.mutableList = None
240                         self.instance.setTitle(self.saved_title)
241                         self.saved_title = None
242                 else:
243                         self.mutableList = self.getMutableList()
244                         self.movemode = True
245                         self.saved_title = self.instance.getTitle()
246                         new_title = self.saved_title
247                         new_title += ' ' + _("[move mode]");
248                         self.instance.setTitle(new_title);
249
250         def handleEditCancel(self):
251                 if self.movemode: #movemode active?
252                         self.channelSelected() # unmark
253                         self.toggleMoveMode() # disable move mode
254                 elif self.bouquet_mark_edit:
255                         self.endMarkedEdit(True) # abort edit mode
256
257         def toggleMoveMarked(self):
258                 if self.entry_marked:
259                         self.servicelist.setCurrentMarked(False)
260                         self.entry_marked = False
261                 else:
262                         self.servicelist.setCurrentMarked(True)
263                         self.entry_marked = True
264
265         def doContext(self):
266                 self.session.open(ChannelContextMenu, self)
267
268 MODE_TV = 0
269 MODE_RADIO = 1
270
271 class ChannelSelectionBase(Screen):
272         def __init__(self, session):
273                 Screen.__init__(self, session)
274
275                 # this makes it much simple to implement a selectable radio or tv mode :)
276                 self.service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17)'
277                 self.service_types_radio = '1:7:1:0:0:0:0:0:0:0:(type == 2)'
278
279                 self["key_red"] = Button(_("All"))
280                 self["key_green"] = Button(_("Satellites"))
281                 self["key_yellow"] = Button(_("Provider"))
282                 self["key_blue"] = Button(_("Favourites"))
283
284                 self["list"] = ServiceList()
285                 self.servicelist = self["list"]
286
287                 self.numericalTextInput = NumericalTextInput()
288
289                 self.servicePathTV = [ ]
290                 self.servicePathRadio = [ ]
291
292                 class ChannelBaseActionMap(NumberActionMap):
293                         def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
294                                 NumberActionMap.__init__(self, contexts, actions, prio)
295                                 self.csel = csel
296                         def action(self, contexts, action):
297                                 if not self.csel.enterBouquet(action):
298                                         NumberActionMap.action(self, contexts, action)
299                 self["ChannelSelectBaseActions"] = ChannelBaseActionMap(self, ["ChannelSelectBaseActions"],
300                         {
301                                 "showFavourites": self.showFavourites,
302                                 "showAllServices": self.showAllServices,
303                                 "showProviders": self.showProviders,
304                                 "showSatellites": self.showSatellites,
305                                 "1": self.keyNumberGlobal,
306                                 "2": self.keyNumberGlobal,
307                                 "3": self.keyNumberGlobal,
308                                 "4": self.keyNumberGlobal,
309                                 "5": self.keyNumberGlobal,
310                                 "6": self.keyNumberGlobal,
311                                 "7": self.keyNumberGlobal,
312                                 "8": self.keyNumberGlobal,
313                                 "9": self.keyNumberGlobal,
314                                 "0": self.keyNumberGlobal
315                         })
316
317         def appendDVBTypes(self, ref):
318                 path = ref.getPath()
319                 pos = path.find(' FROM BOUQUET')
320                 if pos != -1:
321                         return eServiceReference(self.service_types + path[pos:])
322                 return ref
323
324         def getBouquetNumOffset(self, bouquet):
325                 bouquet = self.appendDVBTypes(bouquet)
326                 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
327                         return 0
328                 offsetCount = 0
329                 serviceHandler = eServiceCenter.getInstance()
330                 bouquetlist = serviceHandler.list(self.bouquet_root)
331                 if not bouquetlist is None:
332                         while True:
333                                 bouquetIterator = self.appendDVBTypes(bouquetlist.getNext())
334                                 if not bouquetIterator.valid() or bouquetIterator == bouquet: #end of list or bouquet found
335                                         break
336                                 if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
337                                         continue
338                                 servicelist = serviceHandler.list(bouquetIterator)
339                                 if not servicelist is None:
340                                         while True:
341                                                 serviceIterator = servicelist.getNext()
342                                                 if not serviceIterator.valid(): #check if end of list
343                                                         break
344                                                 if serviceIterator.flags: #playable services have no flags
345                                                         continue
346                                                 offsetCount += 1
347                 return offsetCount
348
349         def recallBouquetMode(self):
350                 if self.mode == MODE_TV:
351                         self.service_types = self.service_types_tv
352                         if currentConfigSelectionElement(config.usage.multibouquet) == "yes":
353                                 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
354                         else:
355                                 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
356                 else:
357                         self.service_types = self.service_types_radio
358                         if currentConfigSelectionElement(config.usage.multibouquet) == "yes":
359                                 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
360                         else:
361                                 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
362                 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
363
364         def setTvMode(self):
365                 title = self.instance.getTitle()
366                 pos = title.find(" (")
367                 if pos != -1:
368                         title = title[:pos]
369                 title += " (TV)"
370                 self.instance.setTitle(title)
371                 self.mode = MODE_TV
372                 self.recallBouquetMode()
373
374         def setRadioMode(self):
375                 title = self.instance.getTitle()
376                 pos = title.find(" (")
377                 if pos != -1:
378                         title = title[:pos]
379                 title += " (Radio)"
380                 self.instance.setTitle(title)
381                 self.mode = MODE_RADIO
382                 self.recallBouquetMode()
383
384         def setRootBase(self, root, justSet=False):
385                 path = root.getPath()
386                 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
387                 pos = path.find(' FROM BOUQUET')
388                 isBouquet = pos != -1
389                 if not inBouquetRootList and isBouquet:
390                         self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
391                         self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
392                         refstr = self.service_types + path[pos:]
393                         root = eServiceReference(refstr)
394                 else:
395                         self.servicelist.setMode(ServiceList.MODE_NORMAL)
396                 self.servicelist.setRoot(root, justSet)
397
398         def moveUp(self):
399                 self.servicelist.moveUp()
400
401         def moveDown(self):
402                 self.servicelist.moveDown()
403
404         def clearPath(self):
405                 if self.mode == MODE_RADIO:
406                         self.servicePathRadio = [ ]
407                 else:
408                         self.servicePathTV = [ ]
409
410         def enterPath(self, ref, justSet=False):
411                 if self.mode == MODE_RADIO:
412                         self.servicePathRadio.append(ref)
413                 else:
414                         self.servicePathTV.append(ref)
415                 self.setRoot(ref, justSet)
416
417         def pathUp(self, justSet=False):
418                 if self.mode == MODE_TV:
419                         prev = self.servicePathTV.pop()
420                         length = len(self.servicePathTV)
421                         if length:
422                                 current = self.servicePathTV[length-1]
423                 else:
424                         prev = self.servicePathRadio.pop()
425                         length = len(self.servicePathRadio)
426                         if length:
427                                 current = self.servicePathRadio[length-1]
428                 self.setRoot(current, justSet)
429                 if not justSet:
430                         self.setCurrentSelection(prev)
431                 return prev
432
433         def isBasePathEqual(self, ref):
434                 if self.mode == MODE_RADIO and len(self.servicePathRadio) > 1 and self.servicePathRadio[0] == ref:
435                         return True
436                 elif self.mode == MODE_TV and len(self.servicePathTV) > 1 and self.servicePathTV[0] == ref:
437                         return True
438                 return False
439
440         def isPrevPathEqual(self, ref):
441                 path = self.servicePathRadio
442                 if self.mode == MODE_TV:
443                         path = self.servicePathTV
444                 length = len(path)
445                 if length > 1 and path[length-2] == ref:
446                         return True
447                 return False
448
449         def preEnterPath(self, refstr):
450                 return False
451
452         def showAllServices(self):
453                 refstr = '%s ORDER BY name'%(self.service_types)
454                 if not self.preEnterPath(refstr):
455                         ref = eServiceReference(refstr)
456                         currentRoot = self.getRoot()
457                         if currentRoot is None or currentRoot != ref:
458                                 self.clearPath()
459                                 self.enterPath(ref)
460
461         def showSatellites(self):
462                 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
463                 if not self.preEnterPath(refstr):
464                         ref = eServiceReference(refstr)
465                         justSet=False
466                         prev = None
467
468                         if self.isBasePathEqual(ref):
469                                 if self.isPrevPathEqual(ref):
470                                         justSet=True
471                                 prev = self.pathUp(justSet)
472                         else:
473                                 currentRoot = self.getRoot()
474                                 if currentRoot is None or currentRoot != ref:
475                                         justSet=True
476                                         self.clearPath()
477                                         self.enterPath(ref, True)
478                         if justSet:
479                                 serviceHandler = eServiceCenter.getInstance()
480                                 servicelist = serviceHandler.list(ref)
481                                 if not servicelist is None:
482                                         while True:
483                                                 service = servicelist.getNext()
484                                                 if not service.valid(): #check if end of list
485                                                         break
486                                                 orbpos = service.getData(4) >> 16
487                                                 if service.getPath().find("FROM PROVIDER") != -1:
488                                                         service_name = _("Providers")
489                                                 else:
490                                                         service_name = _("Services")
491                                                 try:
492                                                         service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
493                                                         service.setName(service_name) # why we need this cast?
494                                                 except:
495                                                         if orbpos > 1800: # west
496                                                                 service.setName("%s (%3.1f" + _("W") + ")" %(str, (0 - (orbpos - 3600)) / 10.0))
497                                                         else:
498                                                                 service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0))
499         #                                       print service.toString()
500                                                 self.servicelist.addService(service)
501                                                 self.servicelist.finishFill()
502                                                 if prev is not None:
503         #                                       print "-->", prev.toString()
504                                                         self.setCurrentSelection(prev)
505
506         def showProviders(self):
507                 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
508                 if not self.preEnterPath(refstr):
509                         ref = eServiceReference(refstr)
510                         if self.isBasePathEqual(ref):
511                                 self.pathUp()
512                         else:
513                                 currentRoot = self.getRoot()
514                                 if currentRoot is None or currentRoot != ref:
515                                         self.clearPath()
516                                         self.enterPath(ref)
517
518         def showFavourites(self):
519                 if not self.preEnterPath(self.bouquet_rootstr):
520                         if self.isBasePathEqual(self.bouquet_root):
521                                 self.pathUp()
522                         else:
523                                 currentRoot = self.getRoot()
524                                 if currentRoot is None or currentRoot != self.bouquet_root:
525                                         self.clearPath()
526                                         self.enterPath(self.bouquet_root)
527
528         def keyNumberGlobal(self, number):
529                 char = self.numericalTextInput.getKey(number)
530                 print "You pressed number " + str(number)
531                 print "You would go to character " + str(char)
532                 self.servicelist.moveToChar(char)
533
534         def enterBouquet(self, action):
535                 if action[:7] == "bouquet":
536                         if action.find("FROM BOUQUET") != -1:
537                                 self.setRoot(eServiceReference("1:7:1:0:0:0:0:0:0:0:" + action[8:]))
538                         else:
539                                 self.setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:]))
540                         return True
541                 return False
542
543         def getRoot(self):
544                 return self.servicelist.getRoot()
545
546         def getCurrentSelection(self):
547                 return self.servicelist.getCurrent()
548
549         def setCurrentSelection(self, service):
550                 servicepath = service.getPath()
551                 pos = servicepath.find(" FROM BOUQUET")
552                 if pos != -1:
553                         servicepath = '(type == 1)' + servicepath[pos:]
554                         service.setPath(servicepath)
555                 self.servicelist.setCurrent(service)
556
557         def cancel(self):
558                 self.close(None)
559
560         def getBouquetList(self):
561                 serviceCount=0
562                 bouquets = [ ]
563                 serviceHandler = eServiceCenter.getInstance()
564                 list = serviceHandler.list(self.bouquet_root)
565                 if not list is None:
566                         while True:
567                                 s = list.getNext()
568                                 if not s.valid():
569                                         break
570                                 if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
571                                         info = serviceHandler.info(s)
572                                         if not info is None:
573                                                 bouquets.append((info.getName(s), s))
574                                 else:
575                                         serviceCount += 1
576                         if len(bouquets) == 0 and serviceCount > 0:
577                                 info = serviceHandler.info(self.bouquet_root)
578                                 if not info is None:
579                                         bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
580                         return bouquets
581                 return None
582
583 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
584         def __init__(self, session):
585                 ChannelSelectionBase.__init__(self,session)
586                 ChannelSelectionEdit.__init__(self)
587                 ChannelSelectionEPG.__init__(self)
588
589                 #config for lastservice
590                 config.tv = ConfigSubsection();
591                 config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
592                 config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
593                 config.tv.prevservice = configElement("config.tv.prevservice", configText, "", 0);
594                 config.tv.prevroot = configElement("config.tv.prevroot", configText, "", 0);
595
596                 self["actions"] = ActionMap(["OkCancelActions"],
597                         {
598                                 "cancel": self.cancel,
599                                 "ok": self.channelSelected,
600                         })
601                 self.onShown.append(self.onShow)
602
603                 self.lastChannelRootTimer = eTimer()
604                 self.lastChannelRootTimer.timeout.get().append(self.onCreate)
605                 self.lastChannelRootTimer.start(100,True)
606
607         def onCreate(self):
608                 self.setTvMode()
609                 self.servicePathTV = [ ]
610                 self.restoreRoot()
611                 lastservice=eServiceReference(config.tv.lastservice.value)
612                 if lastservice.valid():
613                         self.setCurrentSelection(lastservice)
614                         self.session.nav.playService(lastservice)
615
616         def onShow(self):
617                 self.recallBouquetMode()
618                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
619                 if ref is not None and ref.valid() and ref.getPath() == "":
620                         self.servicelist.setPlayableIgnoreService(ref)
621                 else:
622                         self.servicelist.setPlayableIgnoreService(eServiceReference())
623
624         def channelSelected(self):
625                 ref = self.getCurrentSelection()
626                 if self.movemode:
627                         self.toggleMoveMarked()
628                 elif (ref.flags & 7) == 7:
629                         self.enterPath(ref)
630                 elif self.bouquet_mark_edit:
631                         self.doMark()
632                 else:
633                         self.zap()
634                         self.close(ref)
635
636         def setRoot(self, root, justSet=False):
637                 if not self.movemode:
638                         self.setRootBase(root, justSet)
639
640         #called from infoBar and channelSelected
641         def zap(self):
642                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
643                 if ref is None or ref != self.getCurrentSelection():
644                         self.session.nav.playService(self.getCurrentSelection())
645                 self.saveRoot()
646                 self.saveChannel()
647
648         def saveRoot(self):
649                 path = ''
650                 for i in self.servicePathTV:
651                         path += i.toString()
652                         path += ';'
653                 if config.tv.prevroot.value != config.tv.lastroot.value:
654                         config.tv.prevroot.value = config.tv.lastroot.value
655                         config.tv.prevroot.save()
656                 if len(path) and path != config.tv.lastroot.value:
657                         config.tv.lastroot.value = path
658                         config.tv.lastroot.save()
659
660         def restoreRoot(self):
661                 self.servicePathTV = [ ]
662                 re = compile('.+?;')
663                 tmp = re.findall(config.tv.lastroot.value)
664                 cnt = 0
665                 for i in tmp:
666                         self.servicePathTV.append(eServiceReference(i[:len(i)-1]))
667                         cnt += 1
668                 if cnt:
669                         path = self.servicePathTV.pop()
670                         self.enterPath(path)
671                 else:
672                         self.showFavourites()
673                         self.saveRoot()
674
675         def preEnterPath(self, refstr):
676                 if len(self.servicePathTV) and self.servicePathTV[0] != eServiceReference(refstr):
677                         pathstr = config.tv.lastroot.value
678                         if pathstr is not None and pathstr.find(refstr) == 0:
679                                 self.restoreRoot()
680                                 lastservice=eServiceReference(config.tv.lastservice.value)
681                                 if lastservice is not None:
682                                         self.setCurrentSelection(lastservice)
683                                 return True
684                 return False
685
686         def saveChannel(self):
687                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
688                 if ref is not None:
689                         refstr = ref.toString()
690                 else:
691                         refstr = ""
692                 if refstr != config.tv.lastservice.value:
693                         config.tv.prevservice.value = config.tv.lastservice.value
694                         config.tv.prevservice.save()
695                         config.tv.lastservice.value = refstr
696                         config.tv.lastservice.save()
697
698         def recallPrevService(self):
699                 if len(config.tv.prevservice.value) and len(config.tv.prevroot.value):
700                         if config.tv.lastroot.value != config.tv.prevroot.value:
701                                 tmp = config.tv.lastroot.value
702                                 config.tv.lastroot.value = config.tv.prevroot.value
703                                 config.tv.lastroot.save()
704                                 config.tv.prevroot.value = tmp
705                                 config.tv.prevroot.save()
706                                 self.restoreRoot()
707                         if config.tv.lastservice.value != config.tv.prevservice.value:
708                                 tmp = config.tv.lastservice.value
709                                 config.tv.lastservice.value = config.tv.prevservice.value
710                                 config.tv.lastservice.save()
711                                 config.tv.prevservice.value = tmp
712                                 config.tv.prevservice.save()
713                                 lastservice=eServiceReference(config.tv.lastservice.value)
714                                 self.session.nav.playService(lastservice)
715                                 self.setCurrentSelection(lastservice)
716
717         def cancel(self):
718                 self.close(None)
719                 self.restoreRoot()
720                 lastservice=eServiceReference(config.tv.lastservice.value)
721                 if lastservice.valid() and self.getCurrentSelection() != lastservice:
722                         self.setCurrentSelection(lastservice)
723
724 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord
725
726 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
727         def __init__(self, session):
728                 Screen.__init__(self, session)
729                 InfoBarEvent.__init__(self)
730                 InfoBarServiceName.__init__(self)
731                 InfoBarInstantRecord.__init__(self)
732                 self["Clock"] = Clock()
733
734 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
735         def __init__(self, session):
736                 ChannelSelectionBase.__init__(self, session)
737                 ChannelSelectionEdit.__init__(self)
738                 ChannelSelectionEPG.__init__(self)
739
740                 config.radio = ConfigSubsection();
741                 config.radio.lastservice = configElement("config.radio.lastservice", configText, "", 0);
742                 config.radio.lastroot = configElement("config.radio.lastroot", configText, "", 0);
743                 self.onLayoutFinish.append(self.onCreate)
744
745                 self.info = session.instantiateDialog(RadioInfoBar)
746
747                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
748                         {
749                                 "keyTV": self.closeRadio,
750                                 "keyRadio": self.closeRadio,
751                                 "cancel": self.closeRadio,
752                                 "ok": self.channelSelected,
753                         })
754
755         def saveRoot(self):
756                 path = ''
757                 for i in self.servicePathRadio:
758                         path += i.toString()
759                         path += ';'
760                 if len(path) and path != config.radio.lastroot.value:
761                         config.radio.lastroot.value = path
762                         config.radio.lastroot.save()
763
764         def restoreRoot(self):
765                 self.servicePathRadio = [ ]
766                 re = compile('.+?;')
767                 tmp = re.findall(config.radio.lastroot.value)
768                 cnt = 0
769                 for i in tmp:
770                         self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
771                         cnt += 1
772                 if cnt:
773                         path = self.servicePathRadio.pop()
774                         self.enterPath(path)
775                 else:
776                         self.showFavourites()
777                         self.saveRoot()
778
779         def preEnterPath(self, refstr):
780                 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
781                         pathstr = config.radio.lastroot.value
782                         if pathstr is not None and pathstr.find(refstr) == 0:
783                                 self.restoreRoot()
784                                 lastservice=eServiceReference(config.radio.lastservice.value)
785                                 if lastservice is not None:
786                                         self.setCurrentSelection(lastservice)
787                                 return True
788                 return False
789
790         def onCreate(self):
791                 self.setRadioMode()
792                 self.restoreRoot()
793                 lastservice=eServiceReference(config.radio.lastservice.value)
794                 if lastservice.valid():
795                         self.servicelist.setCurrent(lastservice)
796                         self.session.nav.playService(lastservice)
797                         self.servicelist.setPlayableIgnoreService(lastservice)
798                 self.info.instance.show()
799
800         def channelSelected(self): # just return selected service
801                 ref = self.getCurrentSelection()
802                 if self.movemode:
803                         self.toggleMoveMarked()
804                 elif (ref.flags & 7) == 7:
805                         self.enterPath(ref)
806                 elif self.bouquet_mark_edit:
807                         self.doMark()
808                 else:
809                         playingref = self.session.nav.getCurrentlyPlayingServiceReference()
810                         if playingref is None or playingref != ref:
811                                 self.session.nav.playService(ref)
812                                 self.servicelist.setPlayableIgnoreService(ref)
813                                 config.radio.lastservice.value = ref.toString()
814                                 config.radio.lastservice.save()
815                         self.saveRoot()
816
817         def setRoot(self, root, justSet=False):
818                 self.setRootBase(root, justSet)
819
820         def closeRadio(self):
821                 self.info.instance.hide()
822                 #set previous tv service
823                 lastservice=eServiceReference(config.tv.lastservice.value)
824                 self.session.nav.playService(lastservice)
825                 self.close(None)
826
827 class SimpleChannelSelection(ChannelSelectionBase):
828         def __init__(self, session, title):
829                 ChannelSelectionBase.__init__(self, session)
830                 self.title = title
831                 self.onShown.append(self.onExecCallback)
832
833                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
834                         {
835                                 "cancel": self.cancel,
836                                 "ok": self.channelSelected,
837                                 "keyRadio": self.setModeRadio,
838                                 "keyTV": self.setModeTv,
839                         })
840
841         def onExecCallback(self):
842                 self.session.currentDialog.instance.setTitle(self.title)
843                 self.setModeTv()
844
845         def channelSelected(self): # just return selected service
846                 ref = self.getCurrentSelection()
847                 if (ref.flags & 7) == 7:
848                         self.enterPath(ref)
849                 else:
850                         ref = self.getCurrentSelection()
851                         self.close(ref)
852
853         def setRoot(self, root, justSet=False):
854                 self.setRootBase(root, justSet)
855
856         def setModeTv(self):
857                 self.setTvMode()
858                 self.showFavourites()
859
860         def setModeRadio(self):
861                 self.setRadioMode()
862                 self.showFavourites()