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