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