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