1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ServiceList import ServiceList
4 from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
5 from Components.MenuList import MenuList
6 from Components.ServiceEventTracker import ServiceEventTracker
7 from EpgSelection import EPGSelection
8 from enigma import eServiceReference, eEPGCache, eServiceCenter, eTimer, eDVBDB, iPlayableService, iServiceInformation
9 from Components.config import config, ConfigSubsection, ConfigText
10 from Tools.NumericalTextInput import NumericalTextInput
11 from Components.NimManager import nimmanager
12 from Components.Sources.Source import ObsoleteSource
13 from Components.Sources.RdsDecoder import RdsDecoder
14 from Components.Sources.ServiceEvent import ServiceEvent
15 from Components.Input import Input
16 from Components.ParentalControl import parentalControl
17 from Components.Pixmap import Pixmap
18 from Screens.InputBox import InputBox, PinInput
19 from Screens.MessageBox import MessageBox
20 from Screens.ServiceInfo import ServiceInfo
21 from Screens.RdsDisplay import RassInteractive
22 from ServiceReference import ServiceReference
23 from Tools.BoundFunction import boundFunction
24 from re import compile
27 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
29 class BouquetSelector(Screen):
30 def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
31 Screen.__init__(self, session)
33 self.selectedFunc=selectedFunc
35 self["actions"] = ActionMap(["OkCancelActions"],
37 "ok": self.okbuttonClick,
38 "cancel": self.cancelClick
40 entrys = [ (x[0], x[1]) for x in bouquets ]
41 self["menu"] = MenuList(entrys, enableWrapAround)
44 cur = self["menu"].getCurrent()
47 def okbuttonClick(self):
48 self.selectedFunc(self.getCurrent())
56 def cancelClick(self):
59 # csel.bouquet_mark_edit values
64 def append_when_current_valid(current, menu, args):
65 if current and current.valid():
68 class ChannelContextMenu(Screen):
69 def __init__(self, session, csel):
70 Screen.__init__(self, session)
71 #raise "we need a better summary screen here"
75 self["actions"] = ActionMap(["OkCancelActions"],
77 "ok": self.okbuttonClick,
78 "cancel": self.cancelClick
82 current = csel.getCurrentSelection()
83 current_root = csel.getRoot()
84 current_sel_path = current.getPath()
85 current_sel_flags = current.flags
86 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
87 inBouquet = csel.getMutableList() is not None
88 haveBouquets = config.usage.multibouquet.value
90 if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
91 append_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations))
92 if csel.bouquet_mark_edit == OFF and not csel.movemode:
93 if not inBouquetRootList:
94 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
96 if config.ParentalControl.configured.value:
97 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
98 append_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
100 append_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
102 append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected))
104 append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected))
107 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
108 append_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList))
109 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
110 append_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags))
112 append_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService))
113 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
114 append_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag))
116 menu.append((_("add bouquet"), self.showBouquetInputBox))
117 append_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet))
119 if inBouquet: # current list is editable?
120 if csel.bouquet_mark_edit == OFF:
121 if not csel.movemode:
122 append_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode))
123 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
124 menu.append((_("add marker"), self.showMarkerInputBox))
126 append_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart))
128 append_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart))
129 if current_sel_flags & eServiceReference.isGroup:
130 append_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices))
131 append_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices))
132 append_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices))
133 elif not current_sel_flags & eServiceReference.isMarker:
134 append_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices))
136 append_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode))
138 if csel.bouquet_mark_edit == EDIT_BOUQUET:
140 append_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd))
141 append_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort))
143 append_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd))
144 append_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort))
146 append_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd))
147 append_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort))
149 menu.append((_("back"), self.cancelClick))
150 self["menu"] = MenuList(menu)
152 def okbuttonClick(self):
153 self["menu"].getCurrent()[1]()
155 def cancelClick(self):
158 def showServiceInformations(self):
159 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
161 def showBouquetInputBox(self):
162 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
164 def bouquetInputCallback(self, bouquet):
165 if bouquet is not None:
166 self.csel.addBouquet(bouquet, None)
169 def addParentalProtection(self, service):
170 parentalControl.protectService(service.toCompareString())
173 def removeParentalProtection(self, service):
174 self.session.openWithCallback(boundFunction(self.pinEntered, service.toCompareString()), PinInput, pinList = [config.ParentalControl.servicepin[0].value], triesEntry = config.ParentalControl.retries.servicepin, title = _("Enter the service pin"), windowTitle = _("Change pin code"))
176 def pinEntered(self, service, result):
178 parentalControl.unProtectService(service)
181 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
183 def addServiceToBouquetSelected(self):
184 bouquets = self.csel.getBouquetList()
189 if cnt > 1: # show bouquet list
190 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
191 elif cnt == 1: # add to only one existing bouquet
192 self.addCurrentServiceToBouquet(bouquets[0][1])
194 def bouquetSelClosed(self, recursive):
199 def copyCurrentToBouquetList(self):
200 self.csel.copyCurrentToBouquetList()
203 def removeBouquet(self):
204 self.csel.removeBouquet()
207 def showMarkerInputBox(self):
208 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, type=Input.TEXT)
210 def markerInputCallback(self, marker):
211 if marker is not None:
212 self.csel.addMarker(marker)
215 def addCurrentServiceToBouquet(self, dest):
216 self.csel.addServiceToBouquet(dest)
217 if self.bsel is not None:
218 self.bsel.close(True)
220 self.close(True) # close bouquet selection
222 def removeCurrentService(self):
223 self.csel.removeCurrentService()
226 def toggleMoveMode(self):
227 self.csel.toggleMoveMode()
230 def bouquetMarkStart(self):
231 self.csel.startMarkedEdit(EDIT_BOUQUET)
234 def bouquetMarkEnd(self):
235 self.csel.endMarkedEdit(abort=False)
238 def bouquetMarkAbort(self):
239 self.csel.endMarkedEdit(abort=True)
242 def removeNewFoundFlag(self):
243 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
246 def removeAllNewFoundFlags(self):
247 curpath = self.csel.getCurrentSelection().getPath()
248 idx = curpath.find("satellitePosition == ")
250 tmp = curpath[idx+21:]
253 satpos = int(tmp[:idx])
254 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
257 def editAlternativeServices(self):
258 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
261 def showAlternativeServices(self):
262 self.csel.enterPath(self.csel.getCurrentSelection())
265 def removeAlternativeServices(self):
266 self.csel.removeAlternativeServices()
269 def addAlternativeServices(self):
270 self.csel.addAlternativeServices()
271 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
274 class SelectionEventInfo:
276 self["ServiceEvent"] = ServiceEvent()
277 self.servicelist.connectSelChanged(self.__selectionChanged)
278 self.timer = eTimer()
279 self.timer.timeout.get().append(self.updateEventInfo)
280 self.onShown.append(self.__selectionChanged)
282 def __selectionChanged(self):
284 self.timer.start(100, True)
286 def updateEventInfo(self):
287 cur = self.getCurrentSelection()
288 self["ServiceEvent"].newService(cur)
290 class ChannelSelectionEPG:
292 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
294 "showEPGList": self.showEPGList,
297 def showEPGList(self):
298 ref=self.getCurrentSelection()
299 ptr=eEPGCache.getInstance()
300 if ptr.startTimeQuery(ref) != -1:
301 self.session.open(EPGSelection, ref)
303 print 'no epg for service', ref.toString()
305 class ChannelSelectionEdit:
307 self.entry_marked = False
308 self.movemode = False
309 self.bouquet_mark_edit = OFF
310 self.mutableList = None
312 self.saved_title = None
313 self.saved_root = None
315 class ChannelSelectionEditActionMap(ActionMap):
316 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
317 ActionMap.__init__(self, contexts, actions, prio)
320 def action(self, contexts, action):
321 if action == "cancel":
322 self.csel.handleEditCancel()
323 return 0 # fall-trough
325 return 0 # fall-trough
327 return ActionMap.action(self, contexts, action)
329 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
331 "contextMenu": self.doContext,
334 def getMutableList(self, root=eServiceReference()):
335 if not self.mutableList is None:
336 return self.mutableList
337 serviceHandler = eServiceCenter.getInstance()
340 list = root and serviceHandler.list(root)
342 return list.startEdit()
345 def buildBouquetID(self, str):
349 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
355 def addMarker(self, name):
356 current = self.servicelist.getCurrent()
357 mutableList = self.getMutableList()
360 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
361 ref = eServiceReference(str)
362 if current and current.valid():
363 if not mutableList.addService(ref, current):
364 self.servicelist.addService(ref, True)
365 mutableList.flushChanges()
367 elif not mutableList.addService(ref):
368 self.servicelist.addService(ref, True)
369 mutableList.flushChanges()
373 def addAlternativeServices(self):
374 cur_service = ServiceReference(self.getCurrentSelection())
375 root = self.getRoot()
376 cur_root = root and ServiceReference(root)
377 mutableBouquet = cur_root.list().startEdit()
379 name = cur_service.getServiceName()
381 if self.mode == MODE_TV:
382 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
384 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
385 new_ref = ServiceReference(str)
386 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
387 mutableBouquet.removeService(cur_service.ref)
388 mutableBouquet.flushChanges()
389 eDVBDB.getInstance().reloadBouquets()
390 mutableAlternatives = new_ref.list().startEdit()
391 if mutableAlternatives:
392 mutableAlternatives.setListName(name)
393 if mutableAlternatives.addService(cur_service.ref):
394 print "add", cur_service.toString(), "to new alternatives failed"
395 mutableAlternatives.flushChanges()
396 self.servicelist.addService(new_ref.ref, True)
397 self.servicelist.removeCurrent()
398 self.servicelist.moveUp()
400 print "get mutable list for new created alternatives failed"
402 print "add", str, "to", cur_root.getServiceName(), "failed"
404 print "bouquetlist is not editable"
406 def addBouquet(self, bName, services):
407 serviceHandler = eServiceCenter.getInstance()
408 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
409 if mutableBouquetList:
410 if self.mode == MODE_TV:
412 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
415 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
416 new_bouquet_ref = eServiceReference(str)
417 if not mutableBouquetList.addService(new_bouquet_ref):
418 mutableBouquetList.flushChanges()
419 eDVBDB.getInstance().reloadBouquets()
420 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
422 mutableBouquet.setListName(bName)
423 if services is not None:
424 for service in services:
425 if mutableBouquet.addService(service):
426 print "add", service.toString(), "to new bouquet failed"
427 mutableBouquet.flushChanges()
429 print "get mutable list for new created bouquet failed"
430 # do some voodoo to check if current_root is equal to bouquet_root
431 cur_root = self.getRoot();
432 str1 = cur_root and cur_root.toString()
433 pos1 = str1 and str1.find("FROM BOUQUET") or -1
434 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
435 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
436 self.servicelist.addService(new_bouquet_ref)
438 print "add", str, "to bouquets failed"
440 print "bouquetlist is not editable"
442 def copyCurrentToBouquetList(self):
443 provider = ServiceReference(self.getCurrentSelection())
444 providerName = provider.getServiceName()
445 serviceHandler = eServiceCenter.getInstance()
446 services = serviceHandler.list(provider.ref)
447 self.addBouquet(providerName, services and services.getContent('R', True))
449 def removeAlternativeServices(self):
450 cur_service = ServiceReference(self.getCurrentSelection())
451 root = self.getRoot()
452 cur_root = root and ServiceReference(root)
453 list = cur_service.list()
454 first_in_alternative = list and list.getNext()
455 if first_in_alternative:
456 edit_root = cur_root and cur_root.list().startEdit()
458 if not edit_root.addService(first_in_alternative, cur_service.ref):
459 self.servicelist.addService(first_in_alternative, True)
461 print "couldn't add first alternative service to current root"
463 print "couldn't edit current root!!"
465 print "remove empty alternative list !!"
467 self.servicelist.moveUp()
469 def removeBouquet(self):
470 refstr = self.getCurrentSelection().toString()
471 print "removeBouquet", refstr
472 self.bouquetNumOffsetCache = { }
473 pos = refstr.find('FROM BOUQUET "')
476 refstr = refstr[pos+14:]
477 pos = refstr.find('"')
479 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
480 self.removeCurrentService()
482 if filename is not None:
485 print "error during remove of", filename
487 # multiple marked entry stuff ( edit mode, later multiepg selection )
488 def startMarkedEdit(self, type):
489 self.savedPath = self.servicePath[:]
490 if type == EDIT_ALTERNATIVES:
491 self.enterPath(self.getCurrentSelection())
492 self.mutableList = self.getMutableList()
493 # add all services from the current list to internal marked set in listboxservicecontent
494 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
495 self.saved_title = self.instance.getTitle()
496 pos = self.saved_title.find(')')
497 new_title = self.saved_title[:pos+1]
498 if type == EDIT_ALTERNATIVES:
499 self.bouquet_mark_edit = EDIT_ALTERNATIVES
500 new_title += ' ' + _("[alternative edit]")
502 self.bouquet_mark_edit = EDIT_BOUQUET
503 if config.usage.multibouquet.value:
504 new_title += ' ' + _("[bouquet edit]")
506 new_title += ' ' + _("[favourite edit]")
507 self.setTitle(new_title)
508 self.__marked = self.servicelist.getRootServices()
509 for x in self.__marked:
510 self.servicelist.addMarked(eServiceReference(x))
511 self.showAllServices()
513 def endMarkedEdit(self, abort):
514 if not abort and self.mutableList is not None:
515 self.bouquetNumOffsetCache = { }
516 new_marked = set(self.servicelist.getMarked())
517 old_marked = set(self.__marked)
518 removed = old_marked - new_marked
519 added = new_marked - old_marked
523 self.mutableList.removeService(eServiceReference(x))
526 self.mutableList.addService(eServiceReference(x))
528 self.mutableList.flushChanges()
531 self.bouquet_mark_edit = OFF
532 self.mutableList = None
533 self.setTitle(self.saved_title)
534 self.saved_title = None
535 # self.servicePath is just a reference to servicePathTv or Radio...
536 # so we never ever do use the asignment operator in self.servicePath
537 del self.servicePath[:] # remove all elements
538 self.servicePath += self.savedPath # add saved elements
540 self.setRoot(self.servicePath[len(self.servicePath)-1])
542 def clearMarks(self):
543 self.servicelist.clearMarks()
546 ref = self.servicelist.getCurrent()
547 if self.servicelist.isMarked(ref):
548 self.servicelist.removeMarked(ref)
550 self.servicelist.addMarked(ref)
552 def removeCurrentService(self):
553 ref = self.servicelist.getCurrent()
554 mutableList = self.getMutableList()
555 if ref.valid() and mutableList is not None:
556 if not mutableList.removeService(ref):
557 self.bouquetNumOffsetCache = { }
558 mutableList.flushChanges() #FIXME dont flush on each single removed service
559 self.servicelist.removeCurrent()
561 def addServiceToBouquet(self, dest, service=None):
562 mutableList = self.getMutableList(dest)
563 if not mutableList is None:
564 if service is None: #use current selected service
565 service = self.servicelist.getCurrent()
566 if not mutableList.addService(service):
567 self.bouquetNumOffsetCache = { }
568 mutableList.flushChanges()
569 # do some voodoo to check if current_root is equal to dest
570 cur_root = self.getRoot();
571 str1 = cur_root and cur_root.toString() or -1
572 str2 = dest.toString()
573 pos1 = str1.find("FROM BOUQUET")
574 pos2 = str2.find("FROM BOUQUET")
575 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
576 self.servicelist.addService(service)
578 def toggleMoveMode(self):
580 if self.entry_marked:
581 self.toggleMoveMarked() # unmark current entry
582 self.movemode = False
583 self.pathChangeDisabled = False # re-enable path change
584 self.mutableList.flushChanges() # FIXME add check if changes was made
585 self.mutableList = None
586 self.setTitle(self.saved_title)
587 self.saved_title = None
588 cur_root = self.getRoot()
589 if cur_root and cur_root == self.bouquet_root:
590 self.bouquetNumOffsetCache = { }
592 self.mutableList = self.getMutableList()
594 self.pathChangeDisabled = True # no path change allowed in movemode
595 self.saved_title = self.instance.getTitle()
596 new_title = self.saved_title
597 pos = self.saved_title.find(')')
598 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
599 self.setTitle(new_title);
601 def handleEditCancel(self):
602 if self.movemode: #movemode active?
603 self.channelSelected() # unmark
604 self.toggleMoveMode() # disable move mode
605 elif self.bouquet_mark_edit != OFF:
606 self.endMarkedEdit(True) # abort edit mode
608 def toggleMoveMarked(self):
609 if self.entry_marked:
610 self.servicelist.setCurrentMarked(False)
611 self.entry_marked = False
613 self.servicelist.setCurrentMarked(True)
614 self.entry_marked = True
617 self.session.open(ChannelContextMenu, self)
622 # this makes it much simple to implement a selectable radio or tv mode :)
623 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
624 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
626 class ChannelSelectionBase(Screen):
627 def __init__(self, session):
628 Screen.__init__(self, session)
630 self["key_red"] = Button(_("All"))
631 self["key_green"] = Button(_("Satellites"))
632 self["key_yellow"] = Button(_("Provider"))
633 self["key_blue"] = Button(_("Favourites"))
635 self["list"] = ServiceList()
636 self.servicelist = self["list"]
638 self.numericalTextInput = NumericalTextInput()
639 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
641 self.servicePathTV = [ ]
642 self.servicePathRadio = [ ]
643 self.servicePath = [ ]
647 self.pathChangeDisabled = False
649 self.bouquetNumOffsetCache = { }
651 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
653 "showFavourites": self.showFavourites,
654 "showAllServices": self.showAllServices,
655 "showProviders": self.showProviders,
656 "showSatellites": self.showSatellites,
657 "nextBouquet": self.nextBouquet,
658 "prevBouquet": self.prevBouquet,
659 "nextMarker": self.nextMarker,
660 "prevMarker": self.prevMarker,
661 "1": self.keyNumberGlobal,
662 "2": self.keyNumberGlobal,
663 "3": self.keyNumberGlobal,
664 "4": self.keyNumberGlobal,
665 "5": self.keyNumberGlobal,
666 "6": self.keyNumberGlobal,
667 "7": self.keyNumberGlobal,
668 "8": self.keyNumberGlobal,
669 "9": self.keyNumberGlobal,
672 self.recallBouquetMode()
674 def getBouquetNumOffset(self, bouquet):
675 if not config.usage.multibouquet.value:
677 str = bouquet.toString()
679 if not self.bouquetNumOffsetCache.has_key(str):
680 serviceHandler = eServiceCenter.getInstance()
681 bouquetlist = serviceHandler.list(self.bouquet_root)
682 if not bouquetlist is None:
684 bouquetIterator = bouquetlist.getNext()
685 if not bouquetIterator.valid(): #end of list
687 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
688 if not (bouquetIterator.flags & eServiceReference.isDirectory):
690 servicelist = serviceHandler.list(bouquetIterator)
691 if not servicelist is None:
693 serviceIterator = servicelist.getNext()
694 if not serviceIterator.valid(): #check if end of list
696 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
699 return self.bouquetNumOffsetCache.get(str, offsetCount)
701 def recallBouquetMode(self):
702 if self.mode == MODE_TV:
703 self.service_types = service_types_tv
704 if config.usage.multibouquet.value:
705 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
707 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
709 self.service_types = service_types_radio
710 if config.usage.multibouquet.value:
711 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
713 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
714 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
718 self.servicePath = self.servicePathTV
719 self.recallBouquetMode()
720 title = self.instance.getTitle()
721 pos = title.find(" (")
727 def setRadioMode(self):
728 self.mode = MODE_RADIO
729 self.servicePath = self.servicePathRadio
730 self.recallBouquetMode()
731 title = self.instance.getTitle()
732 pos = title.find(" (")
738 def setRoot(self, root, justSet=False):
739 path = root.getPath()
740 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
741 pos = path.find('FROM BOUQUET')
742 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
743 if not inBouquetRootList and isBouquet:
744 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
745 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
747 self.servicelist.setMode(ServiceList.MODE_NORMAL)
748 self.servicelist.setRoot(root, justSet)
749 self.buildTitleString()
751 def removeModeStr(self, str):
752 if self.mode == MODE_TV:
753 pos = str.find(' (TV)')
755 pos = str.find(' (Radio)')
760 def getServiceName(self, ref):
761 str = self.removeModeStr(ServiceReference(ref).getServiceName())
763 pathstr = ref.getPath()
764 if pathstr.find('FROM PROVIDERS') != -1:
766 if pathstr.find('FROM SATELLITES') != -1:
767 return _("Satellites")
768 if pathstr.find(') ORDER BY name') != -1:
772 def buildTitleString(self):
773 titleStr = self.instance.getTitle()
774 pos = titleStr.find(']')
776 pos = titleStr.find(')')
778 titleStr = titleStr[:pos+1]
779 Len = len(self.servicePath)
781 base_ref = self.servicePath[0]
783 end_ref = self.servicePath[Len-1]
786 nameStr = self.getServiceName(base_ref)
787 titleStr += ' ' + nameStr
788 if end_ref is not None:
793 nameStr = self.getServiceName(end_ref)
795 self.setTitle(titleStr)
798 self.servicelist.moveUp()
801 self.servicelist.moveDown()
804 del self.servicePath[:]
806 def enterPath(self, ref, justSet=False):
807 self.servicePath.append(ref)
808 self.setRoot(ref, justSet)
810 def pathUp(self, justSet=False):
811 prev = self.servicePath.pop()
812 length = len(self.servicePath)
814 current = self.servicePath[length-1]
815 self.setRoot(current, justSet)
817 self.setCurrentSelection(prev)
820 def isBasePathEqual(self, ref):
821 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
825 def isPrevPathEqual(self, ref):
826 length = len(self.servicePath)
827 if length > 1 and self.servicePath[length-2] == ref:
831 def preEnterPath(self, refstr):
834 def showAllServices(self):
835 if not self.pathChangeDisabled:
836 refstr = '%s ORDER BY name'%(self.service_types)
837 if not self.preEnterPath(refstr):
838 ref = eServiceReference(refstr)
839 currentRoot = self.getRoot()
840 if currentRoot is None or currentRoot != ref:
844 def showSatellites(self):
845 if not self.pathChangeDisabled:
846 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
847 if not self.preEnterPath(refstr):
848 ref = eServiceReference(refstr)
852 if self.isBasePathEqual(ref):
853 if self.isPrevPathEqual(ref):
855 prev = self.pathUp(justSet)
857 currentRoot = self.getRoot()
858 if currentRoot is None or currentRoot != ref:
861 self.enterPath(ref, True)
863 serviceHandler = eServiceCenter.getInstance()
864 servicelist = serviceHandler.list(ref)
865 if not servicelist is None:
867 service = servicelist.getNext()
868 if not service.valid(): #check if end of list
870 orbpos = service.getUnsignedData(4) >> 16
871 if service.getPath().find("FROM PROVIDER") != -1:
872 service_type = _("Providers")
873 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
874 service_type = _("New")
876 service_type = _("Services")
878 # why we need this cast?
879 service_name = str(nimmanager.getSatDescription(orbpos))
881 if orbpos == 0xFFFF: #Cable
882 service_name = _("Cable")
883 elif orbpos == 0xEEEE: #Terrestrial
884 service_name = _("Terrestrial")
886 if orbpos > 1800: # west
887 orbpos = 3600 - orbpos
891 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
892 service.setName("%s - %s" % (service_name, service_type))
893 self.servicelist.addService(service)
894 cur_ref = self.session.nav.getCurrentlyPlayingServiceReference()
896 pos = self.service_types.rfind(':')
897 refstr = '%s (channelID == %08x%04x%04x) && %s ORDER BY name' %(self.service_types[:pos+1],
898 cur_ref.getUnsignedData(4), # NAMESPACE
899 cur_ref.getUnsignedData(2), # TSID
900 cur_ref.getUnsignedData(3), # ONID
901 self.service_types[pos+1:])
902 ref = eServiceReference(refstr)
903 ref.setName(_("Current Transponder"))
904 self.servicelist.addService(ref)
905 self.servicelist.finishFill()
907 self.setCurrentSelection(prev)
909 def showProviders(self):
910 if not self.pathChangeDisabled:
911 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
912 if not self.preEnterPath(refstr):
913 ref = eServiceReference(refstr)
914 if self.isBasePathEqual(ref):
917 currentRoot = self.getRoot()
918 if currentRoot is None or currentRoot != ref:
922 def changeBouquet(self, direction):
923 if not self.pathChangeDisabled:
924 if len(self.servicePath) > 1:
925 #when enter satellite root list we must do some magic stuff..
926 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
927 if self.isBasePathEqual(ref):
928 self.showSatellites()
935 ref = self.getCurrentSelection()
939 if len(self.servicePath) > 0 and self.servicePath[0] == self.bouquet_root:
944 return self.servicelist.atBegin()
947 return self.servicelist.atEnd()
949 def nextBouquet(self):
950 self.changeBouquet(+1)
952 def prevBouquet(self):
953 self.changeBouquet(-1)
955 def showFavourites(self):
956 if not self.pathChangeDisabled:
957 if not self.preEnterPath(self.bouquet_rootstr):
958 if self.isBasePathEqual(self.bouquet_root):
961 currentRoot = self.getRoot()
962 if currentRoot is None or currentRoot != self.bouquet_root:
964 self.enterPath(self.bouquet_root)
966 def keyNumberGlobal(self, number):
967 unichar = self.numericalTextInput.getKey(number)
968 charstr = unichar.encode("utf-8")
969 if len(charstr) == 1:
970 self.servicelist.moveToChar(charstr[0])
973 return self.servicelist.getRoot()
975 def getCurrentSelection(self):
976 return self.servicelist.getCurrent()
978 def setCurrentSelection(self, service):
979 servicepath = service.getPath()
980 pos = servicepath.find(" FROM BOUQUET")
982 if self.mode == MODE_TV:
983 servicepath = '(type == 1)' + servicepath[pos:]
985 servicepath = '(type == 2)' + servicepath[pos:]
986 service.setPath(servicepath)
987 self.servicelist.setCurrent(service)
989 def getBouquetList(self):
991 serviceHandler = eServiceCenter.getInstance()
992 if config.usage.multibouquet.value:
993 list = serviceHandler.list(self.bouquet_root)
999 if s.flags & eServiceReference.isDirectory:
1000 info = serviceHandler.info(s)
1002 bouquets.append((info.getName(s), s))
1005 info = serviceHandler.info(self.bouquet_root)
1007 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
1011 def keyNumber0(self, num):
1012 if len(self.servicePath) > 1:
1015 self.keyNumberGlobal(num)
1018 if len(self.servicePath) > 1:
1019 if self.isBasePathEqual(self.bouquet_root):
1020 self.showFavourites()
1022 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1023 if self.isBasePathEqual(ref):
1024 self.showSatellites()
1026 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1027 if self.isBasePathEqual(ref):
1028 self.showProviders()
1030 self.showAllServices()
1032 def nextMarker(self):
1033 self.servicelist.moveToNextMarker()
1035 def prevMarker(self):
1036 self.servicelist.moveToPrevMarker()
1040 #config for lastservice
1041 config.tv = ConfigSubsection()
1042 config.tv.lastservice = ConfigText()
1043 config.tv.lastroot = ConfigText()
1044 config.radio = ConfigSubsection()
1045 config.radio.lastservice = ConfigText()
1046 config.radio.lastroot = ConfigText()
1047 config.servicelist = ConfigSubsection()
1048 config.servicelist.lastmode = ConfigText(default = "tv")
1050 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, SelectionEventInfo):
1051 def __init__(self, session):
1052 ChannelSelectionBase.__init__(self,session)
1053 ChannelSelectionEdit.__init__(self)
1054 ChannelSelectionEPG.__init__(self)
1055 SelectionEventInfo.__init__(self)
1057 self["CurrentTime"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
1059 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1061 "cancel": self.cancel,
1062 "ok": self.channelSelected,
1063 "keyRadio": self.setModeRadio,
1064 "keyTV": self.setModeTv,
1067 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1069 iPlayableService.evStart: self.__evServiceStart,
1070 iPlayableService.evEnd: self.__evServiceEnd
1073 self.lastChannelRootTimer = eTimer()
1074 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1075 self.lastChannelRootTimer.start(100,True)
1077 self.history_tv = [ ]
1078 self.history_radio = [ ]
1079 self.history = self.history_tv
1080 self.history_pos = 0
1082 self.lastservice = config.tv.lastservice
1083 self.lastroot = config.tv.lastroot
1084 self.revertMode = None
1085 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1086 self.new_service_played = False
1088 def multibouquet_config_changed(self, val):
1089 self.recallBouquetMode()
1091 def __evServiceStart(self):
1092 service = self.session.nav.getCurrentService()
1094 info = service.info()
1096 refstr = info.getInfoString(iServiceInformation.sServiceref)
1097 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1099 def __evServiceEnd(self):
1100 self.servicelist.setPlayableIgnoreService(eServiceReference())
1104 lastservice=eServiceReference(self.lastservice.value)
1105 if lastservice.valid():
1106 self.setCurrentSelection(lastservice)
1108 def setModeTv(self):
1109 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1110 self.revertMode = MODE_RADIO
1111 self.history = self.history_tv
1112 self.lastservice = config.tv.lastservice
1113 self.lastroot = config.tv.lastroot
1114 config.servicelist.lastmode.value = "tv"
1118 def setModeRadio(self):
1119 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1120 self.revertMode = MODE_TV
1121 if config.usage.e1like_radio_mode.value:
1122 self.history = self.history_radio
1123 self.lastservice = config.radio.lastservice
1124 self.lastroot = config.radio.lastroot
1125 config.servicelist.lastmode.value = "radio"
1129 def __onCreate(self):
1130 if config.usage.e1like_radio_mode.value:
1131 if config.servicelist.lastmode.value == "tv":
1137 lastservice=eServiceReference(self.lastservice.value)
1138 if lastservice.valid():
1141 def channelSelected(self):
1142 ref = self.getCurrentSelection()
1144 self.toggleMoveMarked()
1145 elif (ref.flags & 7) == 7:
1147 elif self.bouquet_mark_edit != OFF:
1148 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1150 elif not (ref.flags & eServiceReference.isMarker): # no marker
1151 root = self.getRoot()
1152 if not root or not (root.flags & eServiceReference.isGroup):
1156 #called from infoBar and channelSelected
1158 self.revertMode=None
1159 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1160 nref = self.getCurrentSelection()
1161 if ref is None or ref != nref:
1162 self.new_service_played = True
1163 self.session.nav.playService(nref)
1165 self.saveChannel(nref)
1166 config.servicelist.lastmode.save()
1167 self.addToHistory(nref)
1169 def newServicePlayed(self):
1170 ret = self.new_service_played
1171 self.new_service_played = False
1174 def addToHistory(self, ref):
1175 if self.servicePath is not None:
1176 tmp=self.servicePath[:]
1179 del self.history[self.history_pos+1:]
1182 self.history.append(tmp)
1183 hlen = len(self.history)
1184 if hlen > HISTORYSIZE:
1187 self.history_pos = hlen-1
1189 def historyBack(self):
1190 hlen = len(self.history)
1191 if hlen > 1 and self.history_pos > 0:
1192 self.history_pos -= 1
1193 self.setHistoryPath()
1195 def historyNext(self):
1196 hlen = len(self.history)
1197 if hlen > 1 and self.history_pos < (hlen-1):
1198 self.history_pos += 1
1199 self.setHistoryPath()
1201 def setHistoryPath(self):
1202 path = self.history[self.history_pos][:]
1204 del self.servicePath[:]
1205 self.servicePath += path
1209 cur_root = self.getRoot()
1210 if cur_root and cur_root != root:
1212 self.session.nav.playService(ref)
1213 self.setCurrentSelection(ref)
1214 self.saveChannel(ref)
1218 for i in self.servicePath:
1219 path += i.toString()
1221 if len(path) and path != self.lastroot.value:
1222 self.lastroot.value = path
1223 self.lastroot.save()
1225 def restoreRoot(self):
1227 re = compile('.+?;')
1228 tmp = re.findall(self.lastroot.value)
1231 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1234 path = self.servicePath.pop()
1235 self.enterPath(path)
1237 self.showFavourites()
1240 def preEnterPath(self, refstr):
1241 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1242 pathstr = self.lastroot.value
1243 if pathstr is not None and pathstr.find(refstr) == 0:
1245 lastservice=eServiceReference(self.lastservice.value)
1246 if lastservice.valid():
1247 self.setCurrentSelection(lastservice)
1251 def saveChannel(self, ref):
1253 refstr = ref.toString()
1256 if refstr != self.lastservice.value:
1257 self.lastservice.value = refstr
1258 self.lastservice.save()
1260 def setCurrentServicePath(self, path):
1261 hlen = len(self.history)
1263 self.history[self.history_pos] = path
1265 self.history.append(path)
1266 self.setHistoryPath()
1268 def getCurrentServicePath(self):
1269 hlen = len(self.history)
1271 return self.history[self.history_pos]
1274 def recallPrevService(self):
1275 hlen = len(self.history)
1277 if self.history_pos == hlen-1:
1278 tmp = self.history[self.history_pos]
1279 self.history[self.history_pos] = self.history[self.history_pos-1]
1280 self.history[self.history_pos-1] = tmp
1282 tmp = self.history[self.history_pos+1]
1283 self.history[self.history_pos+1] = self.history[self.history_pos]
1284 self.history[self.history_pos] = tmp
1285 self.setHistoryPath()
1288 if self.revertMode is None:
1290 lastservice=eServiceReference(self.lastservice.value)
1291 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1292 self.setCurrentSelection(lastservice)
1293 elif self.revertMode == MODE_TV:
1295 elif self.revertMode == MODE_RADIO:
1297 self.revertMode = None
1300 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1302 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1303 def __init__(self, session):
1304 Screen.__init__(self, session)
1305 InfoBarEvent.__init__(self)
1306 InfoBarServiceName.__init__(self)
1307 self["CurrentTime"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
1308 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1309 self["BlinkingPoint"] = Pixmap()
1310 self["BlinkingPoint"].hide()
1312 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1313 ALLOW_SUSPEND = True
1315 def __init__(self, session, infobar):
1316 ChannelSelectionBase.__init__(self, session)
1317 ChannelSelectionEdit.__init__(self)
1318 ChannelSelectionEPG.__init__(self)
1319 self.infobar = infobar
1320 self.onLayoutFinish.append(self.onCreate)
1322 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1324 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1326 "keyTV": self.closeRadio,
1327 "keyRadio": self.closeRadio,
1328 "cancel": self.closeRadio,
1329 "ok": self.channelSelected,
1332 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1334 iPlayableService.evStart: self.__evServiceStart,
1335 iPlayableService.evEnd: self.__evServiceEnd
1338 ########## RDS Radiotext / Rass Support BEGIN
1339 self.infobar = infobar # reference to real infobar (the one and only)
1340 self["RdsDecoder"] = self.info["RdsDecoder"]
1341 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1343 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1345 self["RdsActions"].setEnabled(False)
1346 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1348 def startRassInteractive(self):
1350 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1352 def RassInteractiveClosed(self):
1354 self.infobar.rass_interactive = None
1355 self.infobar.RassSlidePicChanged()
1357 def RassInteractivePossibilityChanged(self, state):
1358 self["RdsActions"].setEnabled(state)
1359 ########## RDS Radiotext / Rass Support END
1361 def closeRadio(self):
1362 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1364 #set previous tv service
1365 lastservice=eServiceReference(config.tv.lastservice.value)
1366 self.session.nav.playService(lastservice)
1369 def __evServiceStart(self):
1370 service = self.session.nav.getCurrentService()
1372 info = service.info()
1374 refstr = info.getInfoString(iServiceInformation.sServiceref)
1375 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1377 def __evServiceEnd(self):
1378 self.servicelist.setPlayableIgnoreService(eServiceReference())
1382 for i in self.servicePathRadio:
1383 path += i.toString()
1385 if len(path) and path != config.radio.lastroot.value:
1386 config.radio.lastroot.value = path
1387 config.radio.lastroot.save()
1389 def restoreRoot(self):
1391 re = compile('.+?;')
1392 tmp = re.findall(config.radio.lastroot.value)
1395 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1398 path = self.servicePathRadio.pop()
1399 self.enterPath(path)
1401 self.showFavourites()
1404 def preEnterPath(self, refstr):
1405 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1406 pathstr = config.radio.lastroot.value
1407 if pathstr is not None and pathstr.find(refstr) == 0:
1409 lastservice=eServiceReference(config.radio.lastservice.value)
1410 if lastservice.valid():
1411 self.setCurrentSelection(lastservice)
1418 lastservice=eServiceReference(config.radio.lastservice.value)
1419 if lastservice.valid():
1420 self.servicelist.setCurrent(lastservice)
1421 self.session.nav.playService(lastservice)
1423 self.session.nav.stopService()
1426 def channelSelected(self): # just return selected service
1427 ref = self.getCurrentSelection()
1429 self.toggleMoveMarked()
1430 elif (ref.flags & 7) == 7:
1432 elif self.bouquet_mark_edit != OFF:
1433 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1435 elif not (ref.flags & eServiceReference.isMarker): # no marker
1436 cur_root = self.getRoot()
1437 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1438 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1439 if playingref is None or playingref != ref:
1440 self.session.nav.playService(ref)
1441 config.radio.lastservice.value = ref.toString()
1442 config.radio.lastservice.save()
1445 class SimpleChannelSelection(ChannelSelectionBase):
1446 def __init__(self, session, title):
1447 ChannelSelectionBase.__init__(self, session)
1449 self.onShown.append(self.__onExecCallback)
1451 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1453 "cancel": self.close,
1454 "ok": self.channelSelected,
1455 "keyRadio": self.setModeRadio,
1456 "keyTV": self.setModeTv,
1459 def __onExecCallback(self):
1460 self.setTitle(self.title)
1463 def channelSelected(self): # just return selected service
1464 ref = self.getCurrentSelection()
1465 if (ref.flags & 7) == 7:
1467 elif not (ref.flags & eServiceReference.isMarker):
1468 ref = self.getCurrentSelection()
1471 def setModeTv(self):
1473 self.showFavourites()
1475 def setModeRadio(self):
1477 self.showFavourites()