make DieMade happy (show current path in Channellist titlebar)
[vuplus_dvbapp] / 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.bouquetRoot = self.getRoot()
268                 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
269                 self.saved_title = self.instance.getTitle()
270                 pos = self.saved_title.find(')')
271                 new_title = self.saved_title[:pos+1]
272                 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1:
273                         new_title += ' ' + _("[bouquet edit]")
274                 else:
275                         new_title += ' ' + _("[favourite edit]")
276                 self.instance.setTitle(new_title)
277                 print new_title
278                 self.bouquet_mark_edit = True
279                 self.__marked = self.servicelist.getRootServices()
280                 for x in self.__marked:
281                         self.servicelist.addMarked(eServiceReference(x))
282                 self.savedPath = self.servicePath[:]
283                 self.showAllServices()
284
285         def endMarkedEdit(self, abort):
286                 if not abort and self.mutableList is not None:
287                         self.bouquetNumOffsetCache = { }
288                         new_marked = set(self.servicelist.getMarked())
289                         old_marked = set(self.__marked)
290                         removed = old_marked - new_marked
291                         added = new_marked - old_marked
292                         changed = False
293                         for x in removed:
294                                 changed = True
295                                 self.mutableList.removeService(eServiceReference(x))
296                         for x in added:
297                                 changed = True
298                                 self.mutableList.addService(eServiceReference(x))
299                         if changed:
300                                 self.mutableList.flushChanges()
301                 self.__marked = []
302                 self.clearMarks()
303                 self.bouquet_mark_edit = False
304                 self.bouquetRoot = None
305                 self.mutableList = None
306                 self.instance.setTitle(self.saved_title)
307                 self.saved_title = None
308                 self.servicePath = self.savedPath[:]
309                 del self.savedPath
310                 self.setRoot(self.servicePath[len(self.servicePath)-1])
311
312         def clearMarks(self):
313                 self.servicelist.clearMarks()
314
315         def doMark(self):
316                 ref = self.servicelist.getCurrent()
317                 if self.servicelist.isMarked(ref):
318                         self.servicelist.removeMarked(ref)
319                 else:
320                         self.servicelist.addMarked(ref)
321
322         def removeCurrentService(self):
323                 ref = self.servicelist.getCurrent()
324                 mutableList = self.getMutableList()
325                 if ref.valid() and mutableList is not None:
326                         if not mutableList.removeService(ref):
327                                 self.bouquetNumOffsetCache = { }
328                                 currentIndex = self.servicelist.getCurrentIndex()
329                                 self.servicelist.moveDown()
330                                 if self.servicelist.getCurrentIndex() == currentIndex:
331                                         currentIndex -= 1
332                                 mutableList.flushChanges() #FIXME dont flush on each single removed service
333                                 self.setRoot(self.getRoot())
334                                 self.servicelist.moveToIndex(currentIndex)
335
336         def addCurrentServiceToBouquet(self, dest):
337                 mutableList = self.getMutableList(dest)
338                 if not mutableList is None:
339                         if not mutableList.addService(self.servicelist.getCurrent()):
340                                 self.bouquetNumOffsetCache = { }
341                                 mutableList.flushChanges()
342                 self.close()
343
344         def toggleMoveMode(self):
345                 if self.movemode:
346                         if self.entry_marked:
347                                 self.toggleMoveMarked() # unmark current entry
348                         self.movemode = False
349                         self.pathChangedDisabled = False # re-enable path change
350                         self.mutableList.flushChanges() # FIXME add check if changes was made
351                         self.mutableList = None
352                         self.instance.setTitle(self.saved_title)
353                         self.saved_title = None
354                         if self.getRoot() == self.bouquet_root:
355                                 self.bouquetNumOffsetCache = { }
356                 else:
357                         self.mutableList = self.getMutableList()
358                         self.movemode = True
359                         self.pathChangedDisabled = True # no path change allowed in movemode
360                         self.saved_title = self.instance.getTitle()
361                         new_title = self.saved_title
362                         pos = self.saved_title.find(')')
363                         new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
364                         self.instance.setTitle(new_title);
365
366         def handleEditCancel(self):
367                 if self.movemode: #movemode active?
368                         self.channelSelected() # unmark
369                         self.toggleMoveMode() # disable move mode
370                 elif self.bouquet_mark_edit:
371                         self.endMarkedEdit(True) # abort edit mode
372
373         def toggleMoveMarked(self):
374                 if self.entry_marked:
375                         self.servicelist.setCurrentMarked(False)
376                         self.entry_marked = False
377                 else:
378                         self.servicelist.setCurrentMarked(True)
379                         self.entry_marked = True
380
381         def doContext(self):
382                 self.session.open(ChannelContextMenu, self)
383
384 MODE_TV = 0
385 MODE_RADIO = 1
386
387 class ChannelSelectionBase(Screen):
388         def __init__(self, session):
389                 Screen.__init__(self, session)
390
391                 # this makes it much simple to implement a selectable radio or tv mode :)
392                 self.service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17)'
393                 self.service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
394
395                 self["key_red"] = Button(_("All"))
396                 self["key_green"] = Button(_("Satellites"))
397                 self["key_yellow"] = Button(_("Provider"))
398                 self["key_blue"] = Button(_("Favourites"))
399
400                 self["list"] = ServiceList()
401                 self.servicelist = self["list"]
402
403                 self.numericalTextInput = NumericalTextInput()
404
405                 self.servicePathTV = [ ]
406                 self.servicePathRadio = [ ]
407                 self.servicePath = None
408
409                 self.pathChangedDisabled = False
410
411                 self.bouquetNumOffsetCache = { }
412
413                 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
414                         {
415                                 "showFavourites": self.showFavourites,
416                                 "showAllServices": self.showAllServices,
417                                 "showProviders": self.showProviders,
418                                 "showSatellites": self.showSatellites,
419                                 "nextBouquet": self.nextBouquet,
420                                 "prevBouquet": self.prevBouquet,
421                                 "1": self.keyNumberGlobal,
422                                 "2": self.keyNumberGlobal,
423                                 "3": self.keyNumberGlobal,
424                                 "4": self.keyNumberGlobal,
425                                 "5": self.keyNumberGlobal,
426                                 "6": self.keyNumberGlobal,
427                                 "7": self.keyNumberGlobal,
428                                 "8": self.keyNumberGlobal,
429                                 "9": self.keyNumberGlobal,
430                                 "0": self.keyNumberGlobal
431                         })
432
433         def appendDVBTypes(self, ref):
434                 path = ref.getPath()
435                 pos = path.find(' FROM BOUQUET')
436                 if pos != -1:
437                         return eServiceReference(self.service_types + path[pos:])
438                 return ref
439
440         def getBouquetNumOffset(self, bouquet):
441                 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
442                         return 0
443                 bouquet = self.appendDVBTypes(bouquet)
444                 try:
445                         return self.bouquetNumOffsetCache[bouquet.toString()]
446                 except:
447                         offsetCount = 0
448                         serviceHandler = eServiceCenter.getInstance()
449                         bouquetlist = serviceHandler.list(self.bouquet_root)
450                         if not bouquetlist is None:
451                                 while True:
452                                         bouquetIterator = self.appendDVBTypes(bouquetlist.getNext())
453                                         if not bouquetIterator.valid(): #end of list
454                                                 break
455                                         self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
456                                         if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
457                                                 continue
458                                         servicelist = serviceHandler.list(bouquetIterator)
459                                         if not servicelist is None:
460                                                 while True:
461                                                         serviceIterator = servicelist.getNext()
462                                                         if not serviceIterator.valid(): #check if end of list
463                                                                 break
464                                                         if serviceIterator.flags: #playable services have no flags
465                                                                 continue
466                                                         offsetCount += 1
467                 return self.bouquetNumOffsetCache.get(bouquet.toString(), offsetCount)
468
469         def recallBouquetMode(self):
470                 if self.mode == MODE_TV:
471                         self.service_types = self.service_types_tv
472                         if currentConfigSelectionElement(config.usage.multibouquet) == "yes":
473                                 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
474                         else:
475                                 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
476                 else:
477                         self.service_types = self.service_types_radio
478                         if currentConfigSelectionElement(config.usage.multibouquet) == "yes":
479                                 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
480                         else:
481                                 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
482                 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
483
484         def setTvMode(self):
485                 self.mode = MODE_TV
486                 self.servicePath = self.servicePathTV
487                 self.recallBouquetMode()
488                 title = self.instance.getTitle()
489                 pos = title.find(" (")
490                 if pos != -1:
491                         title = title[:pos]
492                 title += " (TV)"
493                 self.instance.setTitle(title)
494
495         def setRadioMode(self):
496                 self.mode = MODE_RADIO
497                 self.servicePath = self.servicePathRadio
498                 self.recallBouquetMode()
499                 title = self.instance.getTitle()
500                 pos = title.find(" (")
501                 if pos != -1:
502                         title = title[:pos]
503                 title += " (Radio)"
504                 self.instance.setTitle(title)
505
506         def setRoot(self, root, justSet=False):
507                 path = root.getPath()
508                 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
509                 pos = path.find(' FROM BOUQUET')
510                 isBouquet = pos != -1
511                 if not inBouquetRootList and isBouquet:
512                         self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
513                         self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
514                         refstr = self.service_types + path[pos:]
515                         root = eServiceReference(refstr)
516                 else:
517                         self.servicelist.setMode(ServiceList.MODE_NORMAL)
518                 self.servicelist.setRoot(root, justSet)
519                 self.buildTitleString()
520
521         def removeModeStr(self, str):
522                 if self.mode == MODE_TV:
523                         pos = str.find(' (TV)')
524                 else:
525                         pos = str.find(' (Radio)')
526                 if pos != -1:
527                         return str[:pos]
528                 return str
529
530         def getServiceName(self, ref):
531                 str = self.removeModeStr(ServiceReference(ref).getServiceName())
532                 if not len(str):
533                         pathstr = ref.getPath()
534                         if pathstr.find('FROM PROVIDERS') != -1:
535                                 return _("Provider")
536                         if pathstr.find('FROM SATELLITES') != -1:
537                                 return _("Satellites")
538                         if pathstr.find(') ORDER BY name') != -1:
539                                 return _("All")
540                 return str
541
542         def buildTitleString(self):
543                 titleStr = self.instance.getTitle()
544                 pos = titleStr.find(']')
545                 if pos == -1:
546                         pos = titleStr.find(')')
547                 if pos != -1:
548                         titleStr = titleStr[:pos+1]
549                         Len = len(self.servicePath)
550                         if Len > 0:
551                                 base_ref = self.servicePath[0]
552                                 if Len > 1:
553                                         end_ref = self.servicePath[Len-1]
554                                 else:
555                                         end_ref = None
556                                 nameStr = self.getServiceName(base_ref)
557                                 titleStr += ' ' + nameStr
558                                 if end_ref is not None:
559                                         if Len > 2:
560                                                 titleStr += '/../'
561                                         else:
562                                                 titleStr += '/'
563                                         nameStr = self.getServiceName(end_ref)
564                                         titleStr += nameStr
565                                 self.instance.setTitle(titleStr)
566
567         def moveUp(self):
568                 self.servicelist.moveUp()
569
570         def moveDown(self):
571                 self.servicelist.moveDown()
572
573         def clearPath(self):
574                 del self.servicePath[:]
575
576         def enterPath(self, ref, justSet=False):
577                 self.servicePath.append(ref)
578                 self.setRoot(ref, justSet)
579
580         def pathUp(self, justSet=False):
581                 prev = self.servicePath.pop()
582                 length = len(self.servicePath)
583                 if length:
584                         current = self.servicePath[length-1]
585                 self.setRoot(current, justSet)
586                 if not justSet:
587                         self.setCurrentSelection(prev)
588                 return prev
589
590         def isBasePathEqual(self, ref):
591                 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
592                         return True
593                 return False
594
595         def isPrevPathEqual(self, ref):
596                 length = len(self.servicePath)
597                 if length > 1 and self.servicePath[length-2] == ref:
598                         return True
599                 return False
600
601         def preEnterPath(self, refstr):
602                 return False
603
604         def showAllServices(self):
605                 if not self.pathChangedDisabled:
606                         refstr = '%s ORDER BY name'%(self.service_types)
607                         if not self.preEnterPath(refstr):
608                                 ref = eServiceReference(refstr)
609                                 currentRoot = self.getRoot()
610                                 if currentRoot is None or currentRoot != ref:
611                                         self.clearPath()
612                                         self.enterPath(ref)
613
614         def showSatellites(self):
615                 if not self.pathChangedDisabled:
616                         refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
617                         if not self.preEnterPath(refstr):
618                                 ref = eServiceReference(refstr)
619                                 justSet=False
620                                 prev = None
621
622                                 if self.isBasePathEqual(ref):
623                                         if self.isPrevPathEqual(ref):
624                                                 justSet=True
625                                         prev = self.pathUp(justSet)
626                                 else:
627                                         currentRoot = self.getRoot()
628                                         if currentRoot is None or currentRoot != ref:
629                                                 justSet=True
630                                                 self.clearPath()
631                                                 self.enterPath(ref, True)
632                                 if justSet:
633                                         serviceHandler = eServiceCenter.getInstance()
634                                         servicelist = serviceHandler.list(ref)
635                                         if not servicelist is None:
636                                                 while True:
637                                                         service = servicelist.getNext()
638                                                         if not service.valid(): #check if end of list
639                                                                 break
640                                                         orbpos = service.getData(4) >> 16
641                                                         if service.getPath().find("FROM PROVIDER") != -1:
642                                                                 service_name = _("Providers")
643                                                         else:
644                                                                 service_name = _("Services")
645                                                         try:
646                                                                 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
647                                                                 service.setName(service_name) # why we need this cast?
648                                                         except:
649                                                                 if orbpos > 1800: # west
650                                                                         service.setName("%s (%3.1f" + _("W") + ")" %(str, (0 - (orbpos - 3600)) / 10.0))
651                                                                 else:
652                                                                         service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0))
653                                                         self.servicelist.addService(service)
654                                                         self.servicelist.finishFill()
655                                                         if prev is not None:
656                                                                 self.setCurrentSelection(prev)
657
658         def showProviders(self):
659                 if not self.pathChangedDisabled:
660                         refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
661                         if not self.preEnterPath(refstr):
662                                 ref = eServiceReference(refstr)
663                                 if self.isBasePathEqual(ref):
664                                         self.pathUp()
665                                 else:
666                                         currentRoot = self.getRoot()
667                                         if currentRoot is None or currentRoot != ref:
668                                                 self.clearPath()
669                                                 self.enterPath(ref)
670
671         def changeBouquet(self, direction):
672                 if not self.pathChangedDisabled:
673                         if self.isBasePathEqual(self.bouquet_root):
674                                 self.pathUp()
675                                 if direction < 0:
676                                         self.moveUp()
677                                 else:
678                                         self.moveDown()
679                                 ref = self.getCurrentSelection()
680                                 self.enterPath(ref)
681
682         def inBouquet(self):
683                 return self.isBasePathEqual(self.bouquet_root)
684
685         def atBegin(self):
686                 return self.servicelist.atBegin()
687
688         def atEnd(self):
689                 return self.servicelist.atEnd()
690
691         def nextBouquet(self):
692                 self.changeBouquet(+1)
693
694         def prevBouquet(self):
695                 self.changeBouquet(-1)
696
697         def showFavourites(self):
698                 if not self.pathChangedDisabled:
699                         if not self.preEnterPath(self.bouquet_rootstr):
700                                 if self.isBasePathEqual(self.bouquet_root):
701                                         self.pathUp()
702                                 else:
703                                         currentRoot = self.getRoot()
704                                         if currentRoot is None or currentRoot != self.bouquet_root:
705                                                 self.clearPath()
706                                                 self.enterPath(self.bouquet_root)
707
708         def keyNumberGlobal(self, number):
709                 char = self.numericalTextInput.getKey(number)
710                 self.servicelist.moveToChar(char)
711
712         def getRoot(self):
713                 return self.servicelist.getRoot()
714
715         def getCurrentSelection(self):
716                 return self.servicelist.getCurrent()
717
718         def setCurrentSelection(self, service):
719                 servicepath = service.getPath()
720                 pos = servicepath.find(" FROM BOUQUET")
721                 if pos != -1:
722                         if self.mode == MODE_TV:
723                                 servicepath = '(type == 1)' + servicepath[pos:]
724                         else:
725                                 servicepath = '(type == 2)' + servicepath[pos:]
726                         service.setPath(servicepath)
727                 self.servicelist.setCurrent(service)
728
729         def getBouquetList(self):
730                 serviceCount=0
731                 bouquets = [ ]
732                 serviceHandler = eServiceCenter.getInstance()
733                 list = serviceHandler.list(self.bouquet_root)
734                 if not list is None:
735                         while True:
736                                 s = list.getNext()
737                                 if not s.valid():
738                                         break
739                                 if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
740                                         info = serviceHandler.info(s)
741                                         if not info is None:
742                                                 bouquets.append((info.getName(s), s))
743                                 else:
744                                         serviceCount += 1
745                         if len(bouquets) == 0 and serviceCount > 0:
746                                 info = serviceHandler.info(self.bouquet_root)
747                                 if not info is None:
748                                         bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
749                         return bouquets
750                 return None
751
752 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
753         def __init__(self, session):
754                 ChannelSelectionBase.__init__(self,session)
755                 ChannelSelectionEdit.__init__(self)
756                 ChannelSelectionEPG.__init__(self)
757
758                 #config for lastservice
759                 config.tv = ConfigSubsection();
760                 config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
761                 config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
762                 config.tv.prevservice = configElement("config.tv.prevservice", configText, "", 0);
763                 config.tv.prevroot = configElement("config.tv.prevroot", configText, "", 0);
764
765                 self["actions"] = ActionMap(["OkCancelActions"],
766                         {
767                                 "cancel": self.cancel,
768                                 "ok": self.channelSelected,
769                         })
770                 self.onShown.append(self.__onShown)
771
772                 self.lastChannelRootTimer = eTimer()
773                 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
774                 self.lastChannelRootTimer.start(100,True)
775
776         def __onCreate(self):
777                 self.setTvMode()
778                 self.restoreRoot()
779                 lastservice=eServiceReference(config.tv.lastservice.value)
780                 if lastservice.valid():
781                         self.setCurrentSelection(lastservice)
782                         self.session.nav.playService(lastservice)
783
784         def __onShown(self):
785                 self.recallBouquetMode()
786                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
787                 if ref is not None and ref.valid() and ref.getPath() == "":
788                         self.servicelist.setPlayableIgnoreService(ref)
789                 else:
790                         self.servicelist.setPlayableIgnoreService(eServiceReference())
791
792         def channelSelected(self):
793                 ref = self.getCurrentSelection()
794                 if self.movemode:
795                         self.toggleMoveMarked()
796                 elif (ref.flags & 7) == 7:
797                         self.enterPath(ref)
798                 elif self.bouquet_mark_edit:
799                         self.doMark()
800                 else:
801                         self.zap()
802                         self.close(ref)
803
804         #called from infoBar and channelSelected
805         def zap(self):
806                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
807                 if ref is None or ref != self.getCurrentSelection():
808                         self.session.nav.playService(self.getCurrentSelection())
809                 self.saveRoot()
810                 self.saveChannel()
811
812         def saveRoot(self):
813                 path = ''
814                 for i in self.servicePathTV:
815                         path += i.toString()
816                         path += ';'
817                 if config.tv.prevroot.value != config.tv.lastroot.value:
818                         config.tv.prevroot.value = config.tv.lastroot.value
819                         config.tv.prevroot.save()
820                 if len(path) and path != config.tv.lastroot.value:
821                         config.tv.lastroot.value = path
822                         config.tv.lastroot.save()
823
824         def restoreRoot(self):
825                 self.clearPath()
826                 re = compile('.+?;')
827                 tmp = re.findall(config.tv.lastroot.value)
828                 cnt = 0
829                 for i in tmp:
830                         self.servicePathTV.append(eServiceReference(i[:len(i)-1]))
831                         cnt += 1
832                 if cnt:
833                         path = self.servicePathTV.pop()
834                         self.enterPath(path)
835                 else:
836                         self.showFavourites()
837                         self.saveRoot()
838
839         def preEnterPath(self, refstr):
840                 if len(self.servicePathTV) and self.servicePathTV[0] != eServiceReference(refstr):
841                         pathstr = config.tv.lastroot.value
842                         if pathstr is not None and pathstr.find(refstr) == 0:
843                                 self.restoreRoot()
844                                 lastservice=eServiceReference(config.tv.lastservice.value)
845                                 if lastservice is not None:
846                                         self.setCurrentSelection(lastservice)
847                                 return True
848                 return False
849
850         def saveChannel(self):
851                 ref = self.session.nav.getCurrentlyPlayingServiceReference()
852                 if ref is not None:
853                         refstr = ref.toString()
854                 else:
855                         refstr = ""
856                 if refstr != config.tv.lastservice.value:
857                         config.tv.prevservice.value = config.tv.lastservice.value
858                         config.tv.prevservice.save()
859                         config.tv.lastservice.value = refstr
860                         config.tv.lastservice.save()
861
862         def recallPrevService(self):
863                 if len(config.tv.prevservice.value) and len(config.tv.prevroot.value):
864                         if config.tv.lastroot.value != config.tv.prevroot.value:
865                                 tmp = config.tv.lastroot.value
866                                 config.tv.lastroot.value = config.tv.prevroot.value
867                                 config.tv.lastroot.save()
868                                 config.tv.prevroot.value = tmp
869                                 config.tv.prevroot.save()
870                                 self.restoreRoot()
871                         if config.tv.lastservice.value != config.tv.prevservice.value:
872                                 tmp = config.tv.lastservice.value
873                                 config.tv.lastservice.value = config.tv.prevservice.value
874                                 config.tv.lastservice.save()
875                                 config.tv.prevservice.value = tmp
876                                 config.tv.prevservice.save()
877                                 lastservice=eServiceReference(config.tv.lastservice.value)
878                                 self.session.nav.playService(lastservice)
879                                 self.setCurrentSelection(lastservice)
880
881         def cancel(self):
882                 self.close(None)
883                 self.restoreRoot()
884                 lastservice=eServiceReference(config.tv.lastservice.value)
885                 if lastservice.valid() and self.getCurrentSelection() != lastservice:
886                         self.setCurrentSelection(lastservice)
887
888 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord
889
890 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
891         def __init__(self, session):
892                 Screen.__init__(self, session)
893                 InfoBarEvent.__init__(self)
894                 InfoBarServiceName.__init__(self)
895                 InfoBarInstantRecord.__init__(self)
896                 self["Clock"] = Clock()
897
898 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
899         def __init__(self, session):
900                 ChannelSelectionBase.__init__(self, session)
901                 ChannelSelectionEdit.__init__(self)
902                 ChannelSelectionEPG.__init__(self)
903
904                 config.radio = ConfigSubsection();
905                 config.radio.lastservice = configElement("config.radio.lastservice", configText, "", 0);
906                 config.radio.lastroot = configElement("config.radio.lastroot", configText, "", 0);
907                 self.onLayoutFinish.append(self.onCreate)
908
909                 self.info = session.instantiateDialog(RadioInfoBar)
910
911                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
912                         {
913                                 "keyTV": self.closeRadio,
914                                 "keyRadio": self.closeRadio,
915                                 "cancel": self.closeRadio,
916                                 "ok": self.channelSelected,
917                         })
918
919         def saveRoot(self):
920                 path = ''
921                 for i in self.servicePathRadio:
922                         path += i.toString()
923                         path += ';'
924                 if len(path) and path != config.radio.lastroot.value:
925                         config.radio.lastroot.value = path
926                         config.radio.lastroot.save()
927
928         def restoreRoot(self):
929                 self.clearPath()
930                 re = compile('.+?;')
931                 tmp = re.findall(config.radio.lastroot.value)
932                 cnt = 0
933                 for i in tmp:
934                         self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
935                         cnt += 1
936                 if cnt:
937                         path = self.servicePathRadio.pop()
938                         self.enterPath(path)
939                 else:
940                         self.showFavourites()
941                         self.saveRoot()
942
943         def preEnterPath(self, refstr):
944                 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
945                         pathstr = config.radio.lastroot.value
946                         if pathstr is not None and pathstr.find(refstr) == 0:
947                                 self.restoreRoot()
948                                 lastservice=eServiceReference(config.radio.lastservice.value)
949                                 if lastservice is not None:
950                                         self.setCurrentSelection(lastservice)
951                                 return True
952                 return False
953
954         def onCreate(self):
955                 self.setRadioMode()
956                 self.restoreRoot()
957                 lastservice=eServiceReference(config.radio.lastservice.value)
958                 if lastservice.valid():
959                         self.servicelist.setCurrent(lastservice)
960                         self.session.nav.playService(lastservice)
961                         self.servicelist.setPlayableIgnoreService(lastservice)
962                 self.info.show()
963
964         def channelSelected(self): # just return selected service
965                 ref = self.getCurrentSelection()
966                 if self.movemode:
967                         self.toggleMoveMarked()
968                 elif (ref.flags & 7) == 7:
969                         self.enterPath(ref)
970                 elif self.bouquet_mark_edit:
971                         self.doMark()
972                 else:
973                         playingref = self.session.nav.getCurrentlyPlayingServiceReference()
974                         if playingref is None or playingref != ref:
975                                 self.session.nav.playService(ref)
976                                 self.servicelist.setPlayableIgnoreService(ref)
977                                 config.radio.lastservice.value = ref.toString()
978                                 config.radio.lastservice.save()
979                         self.saveRoot()
980
981         def closeRadio(self):
982                 self.info.hide()
983                 #set previous tv service
984                 lastservice=eServiceReference(config.tv.lastservice.value)
985                 self.session.nav.playService(lastservice)
986                 self.close(None)
987
988 class SimpleChannelSelection(ChannelSelectionBase):
989         def __init__(self, session, title):
990                 ChannelSelectionBase.__init__(self, session)
991                 self.title = title
992                 self.onShown.append(self.__onExecCallback)
993
994                 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
995                         {
996                                 "cancel": self.close,
997                                 "ok": self.channelSelected,
998                                 "keyRadio": self.setModeRadio,
999                                 "keyTV": self.setModeTv,
1000                         })
1001
1002         def __onExecCallback(self):
1003                 self.session.currentDialog.instance.setTitle(self.title)
1004                 self.setModeTv()
1005
1006         def channelSelected(self): # just return selected service
1007                 ref = self.getCurrentSelection()
1008                 if (ref.flags & 7) == 7:
1009                         self.enterPath(ref)
1010                 else:
1011                         ref = self.getCurrentSelection()
1012                         self.close(ref)
1013
1014         def setModeTv(self):
1015                 self.setTvMode()
1016                 self.showFavourites()
1017
1018         def setModeRadio(self):
1019                 self.setRadioMode()
1020                 self.showFavourites()