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