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.Clock import Clock
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 apend_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)
74 self["actions"] = ActionMap(["OkCancelActions"],
76 "ok": self.okbuttonClick,
77 "cancel": self.cancelClick
81 current = csel.getCurrentSelection()
82 current_root = csel.getRoot()
83 current_sel_path = current.getPath()
84 current_sel_flags = current.flags
85 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
86 inBouquet = csel.getMutableList() is not None
87 haveBouquets = config.usage.multibouquet.value
89 if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
90 apend_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations))
91 if csel.bouquet_mark_edit == OFF and not csel.movemode:
92 if not inBouquetRootList:
93 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
95 if config.ParentalControl.configured.value:
96 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
97 apend_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
99 apend_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
101 apend_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected))
103 apend_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected))
106 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
107 apend_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList))
108 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
109 apend_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags))
111 apend_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService))
112 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
113 apend_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag))
115 menu.append((_("add bouquet"), self.showBouquetInputBox))
116 apend_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet))
118 if inBouquet: # current list is editable?
119 if csel.bouquet_mark_edit == OFF:
120 if not csel.movemode:
121 apend_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode))
122 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
123 menu.append((_("add marker"), self.showMarkerInputBox))
125 apend_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart))
127 apend_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart))
128 if current_sel_flags & eServiceReference.isGroup:
129 apend_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices))
130 apend_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices))
131 apend_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices))
132 elif not current_sel_flags & eServiceReference.isMarker:
133 apend_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices))
135 apend_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode))
137 if csel.bouquet_mark_edit == EDIT_BOUQUET:
139 apend_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd))
140 apend_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort))
142 apend_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd))
143 apend_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort))
145 apend_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd))
146 apend_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort))
148 menu.append((_("back"), self.cancelClick))
149 self["menu"] = MenuList(menu)
151 def okbuttonClick(self):
152 self["menu"].getCurrent()[1]()
154 def cancelClick(self):
157 def showServiceInformations(self):
158 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
160 def showBouquetInputBox(self):
161 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
163 def bouquetInputCallback(self, bouquet):
164 if bouquet is not None:
165 self.csel.addBouquet(bouquet, None)
168 def addParentalProtection(self, service):
169 parentalControl.protectService(service.toCompareString())
172 def removeParentalProtection(self, service):
173 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"))
175 def pinEntered(self, service, result):
177 parentalControl.unProtectService(service)
180 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
182 def addServiceToBouquetSelected(self):
183 bouquets = self.csel.getBouquetList()
188 if cnt > 1: # show bouquet list
189 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
190 elif cnt == 1: # add to only one existing bouquet
191 self.addCurrentServiceToBouquet(bouquets[0][1])
193 def bouquetSelClosed(self, recursive):
198 def copyCurrentToBouquetList(self):
199 self.csel.copyCurrentToBouquetList()
202 def removeBouquet(self):
203 self.csel.removeBouquet()
206 def showMarkerInputBox(self):
207 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, type=Input.TEXT)
209 def markerInputCallback(self, marker):
210 if marker is not None:
211 self.csel.addMarker(marker)
214 def addCurrentServiceToBouquet(self, dest):
215 self.csel.addServiceToBouquet(dest)
216 if self.bsel is not None:
217 self.bsel.close(True)
219 self.close(True) # close bouquet selection
221 def removeCurrentService(self):
222 self.csel.removeCurrentService()
225 def toggleMoveMode(self):
226 self.csel.toggleMoveMode()
229 def bouquetMarkStart(self):
230 self.csel.startMarkedEdit(EDIT_BOUQUET)
233 def bouquetMarkEnd(self):
234 self.csel.endMarkedEdit(abort=False)
237 def bouquetMarkAbort(self):
238 self.csel.endMarkedEdit(abort=True)
241 def removeNewFoundFlag(self):
242 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
245 def removeAllNewFoundFlags(self):
246 curpath = self.csel.getCurrentSelection().getPath()
247 idx = curpath.find("satellitePosition == ")
249 tmp = curpath[idx+21:]
252 satpos = int(tmp[:idx])
253 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
256 def editAlternativeServices(self):
257 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
260 def showAlternativeServices(self):
261 self.csel.enterPath(self.csel.getCurrentSelection())
264 def removeAlternativeServices(self):
265 self.csel.removeAlternativeServices()
268 def addAlternativeServices(self):
269 self.csel.addAlternativeServices()
270 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
273 class SelectionEventInfo:
275 self["ServiceEvent"] = ServiceEvent()
276 self.servicelist.connectSelChanged(self.__selectionChanged)
277 self.timer = eTimer()
278 self.timer.timeout.get().append(self.updateEventInfo)
279 self.onShown.append(self.__selectionChanged)
281 def __selectionChanged(self):
283 self.timer.start(100, True)
285 def updateEventInfo(self):
286 cur = self.getCurrentSelection()
287 self["ServiceEvent"].newService(cur)
289 class ChannelSelectionEPG:
291 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
293 "showEPGList": self.showEPGList,
296 def showEPGList(self):
297 ref=self.getCurrentSelection()
298 ptr=eEPGCache.getInstance()
299 if ptr.startTimeQuery(ref) != -1:
300 self.session.open(EPGSelection, ref)
302 print 'no epg for service', ref.toString()
304 class ChannelSelectionEdit:
306 self.entry_marked = False
307 self.movemode = False
308 self.bouquet_mark_edit = OFF
309 self.mutableList = None
311 self.saved_title = None
312 self.saved_root = None
314 class ChannelSelectionEditActionMap(ActionMap):
315 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
316 ActionMap.__init__(self, contexts, actions, prio)
319 def action(self, contexts, action):
320 if action == "cancel":
321 self.csel.handleEditCancel()
322 return 0 # fall-trough
324 return 0 # fall-trough
326 return ActionMap.action(self, contexts, action)
328 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
330 "contextMenu": self.doContext,
333 def getMutableList(self, root=eServiceReference()):
334 if not self.mutableList is None:
335 return self.mutableList
336 serviceHandler = eServiceCenter.getInstance()
339 list = root and serviceHandler.list(root)
341 return list.startEdit()
344 def buildBouquetID(self, str):
348 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
354 def addMarker(self, name):
355 current = self.servicelist.getCurrent()
356 mutableList = self.getMutableList()
359 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
360 ref = eServiceReference(str)
361 if current and current.valid():
362 if not mutableList.addService(ref, current):
363 self.servicelist.addService(ref, True)
364 mutableList.flushChanges()
366 elif not mutableList.addService(ref):
367 self.servicelist.addService(ref, True)
368 mutableList.flushChanges()
372 def addAlternativeServices(self):
373 cur_service = ServiceReference(self.getCurrentSelection())
374 root = self.getRoot()
375 cur_root = root and ServiceReference(root)
376 mutableBouquet = cur_root.list().startEdit()
378 name = cur_service.getServiceName()
380 if self.mode == MODE_TV:
381 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
383 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
384 new_ref = ServiceReference(str)
385 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
386 mutableBouquet.removeService(cur_service.ref)
387 mutableBouquet.flushChanges()
388 eDVBDB.getInstance().reloadBouquets()
389 mutableAlternatives = new_ref.list().startEdit()
390 if mutableAlternatives:
391 mutableAlternatives.setListName(name)
392 if mutableAlternatives.addService(cur_service.ref):
393 print "add", cur_service.toString(), "to new alternatives failed"
394 mutableAlternatives.flushChanges()
395 self.servicelist.addService(new_ref.ref, True)
396 self.servicelist.removeCurrent()
397 self.servicelist.moveUp()
399 print "get mutable list for new created alternatives failed"
401 print "add", str, "to", cur_root.getServiceName(), "failed"
403 print "bouquetlist is not editable"
405 def addBouquet(self, bName, services):
406 serviceHandler = eServiceCenter.getInstance()
407 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
408 if mutableBouquetList:
409 if self.mode == MODE_TV:
411 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
414 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
415 new_bouquet_ref = eServiceReference(str)
416 if not mutableBouquetList.addService(new_bouquet_ref):
417 mutableBouquetList.flushChanges()
418 eDVBDB.getInstance().reloadBouquets()
419 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
421 mutableBouquet.setListName(bName)
422 if services is not None:
423 for service in services:
424 if mutableBouquet.addService(service):
425 print "add", service.toString(), "to new bouquet failed"
426 mutableBouquet.flushChanges()
428 print "get mutable list for new created bouquet failed"
429 # do some voodoo to check if current_root is equal to bouquet_root
430 cur_root = self.getRoot();
431 str1 = cur_root and cur_root.toString()
432 pos1 = str1 and str1.find("FROM BOUQUET") or -1
433 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
434 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
435 self.servicelist.addService(new_bouquet_ref)
437 print "add", str, "to bouquets failed"
439 print "bouquetlist is not editable"
441 def copyCurrentToBouquetList(self):
442 provider = ServiceReference(self.getCurrentSelection())
443 providerName = provider.getServiceName()
444 serviceHandler = eServiceCenter.getInstance()
445 services = serviceHandler.list(provider.ref)
446 self.addBouquet(providerName, services and services.getContent('R', True))
448 def removeAlternativeServices(self):
449 cur_service = ServiceReference(self.getCurrentSelection())
450 root = self.getRoot()
451 cur_root = root and ServiceReference(root)
452 list = cur_service.list()
453 first_in_alternative = list and list.getNext()
454 if first_in_alternative:
455 edit_root = cur_root and cur_root.list().startEdit()
457 if not edit_root.addService(first_in_alternative, cur_service.ref):
458 self.servicelist.addService(first_in_alternative, True)
460 print "couldn't add first alternative service to current root"
462 print "couldn't edit current root!!"
464 print "remove empty alternative list !!"
466 self.servicelist.moveUp()
468 def removeBouquet(self):
469 refstr = self.getCurrentSelection().toString()
470 print "removeBouquet", refstr
471 self.bouquetNumOffsetCache = { }
472 pos = refstr.find('FROM BOUQUET "')
475 refstr = refstr[pos+14:]
476 pos = refstr.find('"')
478 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
479 self.removeCurrentService()
481 if filename is not None:
484 print "error during remove of", filename
486 # multiple marked entry stuff ( edit mode, later multiepg selection )
487 def startMarkedEdit(self, type):
488 self.savedPath = self.servicePath[:]
489 if type == EDIT_ALTERNATIVES:
490 self.enterPath(self.getCurrentSelection())
491 self.mutableList = self.getMutableList()
492 # add all services from the current list to internal marked set in listboxservicecontent
493 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
494 self.saved_title = self.instance.getTitle()
495 pos = self.saved_title.find(')')
496 new_title = self.saved_title[:pos+1]
497 if type == EDIT_ALTERNATIVES:
498 self.bouquet_mark_edit = EDIT_ALTERNATIVES
499 new_title += ' ' + _("[alternative edit]")
501 self.bouquet_mark_edit = EDIT_BOUQUET
502 if config.usage.multibouquet.value:
503 new_title += ' ' + _("[bouquet edit]")
505 new_title += ' ' + _("[favourite edit]")
506 self.setTitle(new_title)
507 self.__marked = self.servicelist.getRootServices()
508 for x in self.__marked:
509 self.servicelist.addMarked(eServiceReference(x))
510 self.showAllServices()
512 def endMarkedEdit(self, abort):
513 if not abort and self.mutableList is not None:
514 self.bouquetNumOffsetCache = { }
515 new_marked = set(self.servicelist.getMarked())
516 old_marked = set(self.__marked)
517 removed = old_marked - new_marked
518 added = new_marked - old_marked
522 self.mutableList.removeService(eServiceReference(x))
525 self.mutableList.addService(eServiceReference(x))
527 self.mutableList.flushChanges()
530 self.bouquet_mark_edit = OFF
531 self.mutableList = None
532 self.setTitle(self.saved_title)
533 self.saved_title = None
534 # self.servicePath is just a reference to servicePathTv or Radio...
535 # so we never ever do use the asignment operator in self.servicePath
536 del self.servicePath[:] # remove all elements
537 self.servicePath += self.savedPath # add saved elements
539 self.setRoot(self.servicePath[len(self.servicePath)-1])
541 def clearMarks(self):
542 self.servicelist.clearMarks()
545 ref = self.servicelist.getCurrent()
546 if self.servicelist.isMarked(ref):
547 self.servicelist.removeMarked(ref)
549 self.servicelist.addMarked(ref)
551 def removeCurrentService(self):
552 ref = self.servicelist.getCurrent()
553 mutableList = self.getMutableList()
554 if ref.valid() and mutableList is not None:
555 if not mutableList.removeService(ref):
556 self.bouquetNumOffsetCache = { }
557 mutableList.flushChanges() #FIXME dont flush on each single removed service
558 self.servicelist.removeCurrent()
560 def addServiceToBouquet(self, dest, service=None):
561 mutableList = self.getMutableList(dest)
562 if not mutableList is None:
563 if service is None: #use current selected service
564 service = self.servicelist.getCurrent()
565 if not mutableList.addService(service):
566 self.bouquetNumOffsetCache = { }
567 mutableList.flushChanges()
568 # do some voodoo to check if current_root is equal to dest
569 cur_root = self.getRoot();
570 str1 = cur_root and cur_root.toString() or -1
571 str2 = dest.toString()
572 pos1 = str1.find("FROM BOUQUET")
573 pos2 = str2.find("FROM BOUQUET")
574 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
575 self.servicelist.addService(service)
577 def toggleMoveMode(self):
579 if self.entry_marked:
580 self.toggleMoveMarked() # unmark current entry
581 self.movemode = False
582 self.pathChangeDisabled = False # re-enable path change
583 self.mutableList.flushChanges() # FIXME add check if changes was made
584 self.mutableList = None
585 self.setTitle(self.saved_title)
586 self.saved_title = None
587 cur_root = self.getRoot()
588 if cur_root and cur_root == self.bouquet_root:
589 self.bouquetNumOffsetCache = { }
591 self.mutableList = self.getMutableList()
593 self.pathChangeDisabled = True # no path change allowed in movemode
594 self.saved_title = self.instance.getTitle()
595 new_title = self.saved_title
596 pos = self.saved_title.find(')')
597 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
598 self.setTitle(new_title);
600 def handleEditCancel(self):
601 if self.movemode: #movemode active?
602 self.channelSelected() # unmark
603 self.toggleMoveMode() # disable move mode
604 elif self.bouquet_mark_edit != OFF:
605 self.endMarkedEdit(True) # abort edit mode
607 def toggleMoveMarked(self):
608 if self.entry_marked:
609 self.servicelist.setCurrentMarked(False)
610 self.entry_marked = False
612 self.servicelist.setCurrentMarked(True)
613 self.entry_marked = True
616 self.session.open(ChannelContextMenu, self)
621 # this makes it much simple to implement a selectable radio or tv mode :)
622 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
623 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
625 class ChannelSelectionBase(Screen):
626 def __init__(self, session):
627 Screen.__init__(self, session)
629 self["key_red"] = Button(_("All"))
630 self["key_green"] = Button(_("Satellites"))
631 self["key_yellow"] = Button(_("Provider"))
632 self["key_blue"] = Button(_("Favourites"))
634 self["list"] = ServiceList()
635 self.servicelist = self["list"]
637 self.numericalTextInput = NumericalTextInput()
638 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
640 self.servicePathTV = [ ]
641 self.servicePathRadio = [ ]
642 self.servicePath = [ ]
646 self.pathChangeDisabled = False
648 self.bouquetNumOffsetCache = { }
650 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
652 "showFavourites": self.showFavourites,
653 "showAllServices": self.showAllServices,
654 "showProviders": self.showProviders,
655 "showSatellites": self.showSatellites,
656 "nextBouquet": self.nextBouquet,
657 "prevBouquet": self.prevBouquet,
658 "nextMarker": self.nextMarker,
659 "prevMarker": self.prevMarker,
660 "1": self.keyNumberGlobal,
661 "2": self.keyNumberGlobal,
662 "3": self.keyNumberGlobal,
663 "4": self.keyNumberGlobal,
664 "5": self.keyNumberGlobal,
665 "6": self.keyNumberGlobal,
666 "7": self.keyNumberGlobal,
667 "8": self.keyNumberGlobal,
668 "9": self.keyNumberGlobal,
671 self.recallBouquetMode()
673 def getBouquetNumOffset(self, bouquet):
674 if not config.usage.multibouquet.value:
676 str = bouquet.toString()
678 if not self.bouquetNumOffsetCache.has_key(str):
679 serviceHandler = eServiceCenter.getInstance()
680 bouquetlist = serviceHandler.list(self.bouquet_root)
681 if not bouquetlist is None:
683 bouquetIterator = bouquetlist.getNext()
684 if not bouquetIterator.valid(): #end of list
686 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
687 if not (bouquetIterator.flags & eServiceReference.isDirectory):
689 servicelist = serviceHandler.list(bouquetIterator)
690 if not servicelist is None:
692 serviceIterator = servicelist.getNext()
693 if not serviceIterator.valid(): #check if end of list
695 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
698 return self.bouquetNumOffsetCache.get(str, offsetCount)
700 def recallBouquetMode(self):
701 if self.mode == MODE_TV:
702 self.service_types = service_types_tv
703 if config.usage.multibouquet.value:
704 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
706 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
708 self.service_types = service_types_radio
709 if config.usage.multibouquet.value:
710 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
712 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
713 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
717 self.servicePath = self.servicePathTV
718 self.recallBouquetMode()
719 title = self.instance.getTitle()
720 pos = title.find(" (")
726 def setRadioMode(self):
727 self.mode = MODE_RADIO
728 self.servicePath = self.servicePathRadio
729 self.recallBouquetMode()
730 title = self.instance.getTitle()
731 pos = title.find(" (")
737 def setRoot(self, root, justSet=False):
738 path = root.getPath()
739 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
740 pos = path.find('FROM BOUQUET')
741 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
742 if not inBouquetRootList and isBouquet:
743 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
744 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
746 self.servicelist.setMode(ServiceList.MODE_NORMAL)
747 self.servicelist.setRoot(root, justSet)
748 self.buildTitleString()
750 def removeModeStr(self, str):
751 if self.mode == MODE_TV:
752 pos = str.find(' (TV)')
754 pos = str.find(' (Radio)')
759 def getServiceName(self, ref):
760 str = self.removeModeStr(ServiceReference(ref).getServiceName())
762 pathstr = ref.getPath()
763 if pathstr.find('FROM PROVIDERS') != -1:
765 if pathstr.find('FROM SATELLITES') != -1:
766 return _("Satellites")
767 if pathstr.find(') ORDER BY name') != -1:
771 def buildTitleString(self):
772 titleStr = self.instance.getTitle()
773 pos = titleStr.find(']')
775 pos = titleStr.find(')')
777 titleStr = titleStr[:pos+1]
778 Len = len(self.servicePath)
780 base_ref = self.servicePath[0]
782 end_ref = self.servicePath[Len-1]
785 nameStr = self.getServiceName(base_ref)
786 titleStr += ' ' + nameStr
787 if end_ref is not None:
792 nameStr = self.getServiceName(end_ref)
794 self.setTitle(titleStr)
797 self.servicelist.moveUp()
800 self.servicelist.moveDown()
803 del self.servicePath[:]
805 def enterPath(self, ref, justSet=False):
806 self.servicePath.append(ref)
807 self.setRoot(ref, justSet)
809 def pathUp(self, justSet=False):
810 prev = self.servicePath.pop()
811 length = len(self.servicePath)
813 current = self.servicePath[length-1]
814 self.setRoot(current, justSet)
816 self.setCurrentSelection(prev)
819 def isBasePathEqual(self, ref):
820 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
824 def isPrevPathEqual(self, ref):
825 length = len(self.servicePath)
826 if length > 1 and self.servicePath[length-2] == ref:
830 def preEnterPath(self, refstr):
833 def showAllServices(self):
834 if not self.pathChangeDisabled:
835 refstr = '%s ORDER BY name'%(self.service_types)
836 if not self.preEnterPath(refstr):
837 ref = eServiceReference(refstr)
838 currentRoot = self.getRoot()
839 if currentRoot is None or currentRoot != ref:
843 def showSatellites(self):
844 if not self.pathChangeDisabled:
845 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
846 if not self.preEnterPath(refstr):
847 ref = eServiceReference(refstr)
851 if self.isBasePathEqual(ref):
852 if self.isPrevPathEqual(ref):
854 prev = self.pathUp(justSet)
856 currentRoot = self.getRoot()
857 if currentRoot is None or currentRoot != ref:
860 self.enterPath(ref, True)
862 serviceHandler = eServiceCenter.getInstance()
863 servicelist = serviceHandler.list(ref)
864 if not servicelist is None:
866 service = servicelist.getNext()
867 if not service.valid(): #check if end of list
869 orbpos = service.getUnsignedData(4) >> 16
870 if service.getPath().find("FROM PROVIDER") != -1:
871 service_type = _("Providers")
872 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
873 service_type = _("New")
875 service_type = _("Services")
877 # why we need this cast?
878 service_name = str(nimmanager.getSatDescription(orbpos))
880 if orbpos == 0xFFFF: #Cable
881 service_name = _("Cable")
882 elif orbpos == 0xEEEE: #Terrestrial
883 service_name = _("Terrestrial")
885 if orbpos > 1800: # west
886 orbpos = 3600 - orbpos
890 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
891 service.setName("%s - %s" % (service_name, service_type))
892 self.servicelist.addService(service)
893 self.servicelist.finishFill()
895 self.setCurrentSelection(prev)
897 def showProviders(self):
898 if not self.pathChangeDisabled:
899 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
900 if not self.preEnterPath(refstr):
901 ref = eServiceReference(refstr)
902 if self.isBasePathEqual(ref):
905 currentRoot = self.getRoot()
906 if currentRoot is None or currentRoot != ref:
910 def changeBouquet(self, direction):
911 if not self.pathChangeDisabled:
912 if len(self.servicePath) > 1:
913 #when enter satellite root list we must do some magic stuff..
914 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
915 if self.isBasePathEqual(ref):
916 self.showSatellites()
923 ref = self.getCurrentSelection()
927 if len(self.servicePath) > 0 and self.servicePath[0] == self.bouquet_root:
932 return self.servicelist.atBegin()
935 return self.servicelist.atEnd()
937 def nextBouquet(self):
938 self.changeBouquet(+1)
940 def prevBouquet(self):
941 self.changeBouquet(-1)
943 def showFavourites(self):
944 if not self.pathChangeDisabled:
945 if not self.preEnterPath(self.bouquet_rootstr):
946 if self.isBasePathEqual(self.bouquet_root):
949 currentRoot = self.getRoot()
950 if currentRoot is None or currentRoot != self.bouquet_root:
952 self.enterPath(self.bouquet_root)
954 def keyNumberGlobal(self, number):
955 unichar = self.numericalTextInput.getKey(number)
956 charstr = unichar.encode("utf-8")
957 if len(charstr) == 1:
958 self.servicelist.moveToChar(charstr[0])
961 return self.servicelist.getRoot()
963 def getCurrentSelection(self):
964 return self.servicelist.getCurrent()
966 def setCurrentSelection(self, service):
967 servicepath = service.getPath()
968 pos = servicepath.find(" FROM BOUQUET")
970 if self.mode == MODE_TV:
971 servicepath = '(type == 1)' + servicepath[pos:]
973 servicepath = '(type == 2)' + servicepath[pos:]
974 service.setPath(servicepath)
975 self.servicelist.setCurrent(service)
977 def getBouquetList(self):
979 serviceHandler = eServiceCenter.getInstance()
980 if config.usage.multibouquet.value:
981 list = serviceHandler.list(self.bouquet_root)
987 if s.flags & eServiceReference.isDirectory:
988 info = serviceHandler.info(s)
990 bouquets.append((info.getName(s), s))
993 info = serviceHandler.info(self.bouquet_root)
995 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
999 def keyNumber0(self, num):
1000 if len(self.servicePath) > 1:
1003 self.keyNumberGlobal(num)
1006 if len(self.servicePath) > 1:
1007 if self.isBasePathEqual(self.bouquet_root):
1008 self.showFavourites()
1010 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1011 if self.isBasePathEqual(ref):
1012 self.showSatellites()
1014 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1015 if self.isBasePathEqual(ref):
1016 self.showProviders()
1018 self.showAllServices()
1020 def nextMarker(self):
1021 self.servicelist.moveToNextMarker()
1023 def prevMarker(self):
1024 self.servicelist.moveToPrevMarker()
1028 #config for lastservice
1029 config.tv = ConfigSubsection()
1030 config.tv.lastservice = ConfigText()
1031 config.tv.lastroot = ConfigText()
1032 config.radio = ConfigSubsection()
1033 config.radio.lastservice = ConfigText()
1034 config.radio.lastroot = ConfigText()
1035 config.servicelist = ConfigSubsection()
1036 config.servicelist.lastmode = ConfigText(default = "tv")
1038 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, SelectionEventInfo):
1039 def __init__(self, session):
1040 ChannelSelectionBase.__init__(self,session)
1041 ChannelSelectionEdit.__init__(self)
1042 ChannelSelectionEPG.__init__(self)
1043 SelectionEventInfo.__init__(self)
1045 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1047 "cancel": self.cancel,
1048 "ok": self.channelSelected,
1049 "keyRadio": self.setModeRadio,
1050 "keyTV": self.setModeTv,
1053 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1055 iPlayableService.evStart: self.__evServiceStart,
1056 iPlayableService.evEnd: self.__evServiceEnd
1059 self.lastChannelRootTimer = eTimer()
1060 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1061 self.lastChannelRootTimer.start(100,True)
1063 self.history_tv = [ ]
1064 self.history_radio = [ ]
1065 self.history = self.history_tv
1066 self.history_pos = 0
1068 self.lastservice = config.tv.lastservice
1069 self.lastroot = config.tv.lastroot
1070 self.revertMode = None
1071 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1072 self.new_service_played = False
1074 def multibouquet_config_changed(self, val):
1075 self.recallBouquetMode()
1077 def __evServiceStart(self):
1078 service = self.session.nav.getCurrentService()
1080 info = service.info()
1082 refstr = info.getInfoString(iServiceInformation.sServiceref)
1083 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1085 def __evServiceEnd(self):
1086 self.servicelist.setPlayableIgnoreService(eServiceReference())
1090 lastservice=eServiceReference(self.lastservice.value)
1091 if lastservice.valid():
1092 self.setCurrentSelection(lastservice)
1094 def setModeTv(self):
1095 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1096 self.revertMode = MODE_RADIO
1097 self.history = self.history_tv
1098 self.lastservice = config.tv.lastservice
1099 self.lastroot = config.tv.lastroot
1100 config.servicelist.lastmode.value = "tv"
1104 def setModeRadio(self):
1105 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1106 self.revertMode = MODE_TV
1107 if config.usage.e1like_radio_mode.value:
1108 self.history = self.history_radio
1109 self.lastservice = config.radio.lastservice
1110 self.lastroot = config.radio.lastroot
1111 config.servicelist.lastmode.value = "radio"
1115 def __onCreate(self):
1116 if config.usage.e1like_radio_mode.value:
1117 if config.servicelist.lastmode.value == "tv":
1123 lastservice=eServiceReference(self.lastservice.value)
1124 if lastservice.valid():
1127 def channelSelected(self):
1128 ref = self.getCurrentSelection()
1130 self.toggleMoveMarked()
1131 elif (ref.flags & 7) == 7:
1133 elif self.bouquet_mark_edit != OFF:
1134 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1136 elif not (ref.flags & eServiceReference.isMarker): # no marker
1137 root = self.getRoot()
1138 if not root or not (root.flags & eServiceReference.isGroup):
1142 #called from infoBar and channelSelected
1144 self.revertMode=None
1145 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1146 nref = self.getCurrentSelection()
1147 if ref is None or ref != nref:
1148 self.new_service_played = True
1149 self.session.nav.playService(nref)
1151 self.saveChannel(nref)
1152 config.servicelist.lastmode.save()
1153 self.addToHistory(nref)
1155 def newServicePlayed(self):
1156 ret = self.new_service_played
1157 self.new_service_played = False
1160 def addToHistory(self, ref):
1161 if self.servicePath is not None:
1162 tmp=self.servicePath[:]
1165 del self.history[self.history_pos+1:]
1168 self.history.append(tmp)
1169 hlen = len(self.history)
1170 if hlen > HISTORYSIZE:
1173 self.history_pos = hlen-1
1175 def historyBack(self):
1176 hlen = len(self.history)
1177 if hlen > 1 and self.history_pos > 0:
1178 self.history_pos -= 1
1179 self.setHistoryPath()
1181 def historyNext(self):
1182 hlen = len(self.history)
1183 if hlen > 1 and self.history_pos < (hlen-1):
1184 self.history_pos += 1
1185 self.setHistoryPath()
1187 def setHistoryPath(self):
1188 path = self.history[self.history_pos][:]
1190 del self.servicePath[:]
1191 self.servicePath += path
1195 cur_root = self.getRoot()
1196 if cur_root and cur_root != root:
1198 self.session.nav.playService(ref)
1199 self.setCurrentSelection(ref)
1200 self.saveChannel(ref)
1204 for i in self.servicePath:
1205 path += i.toString()
1207 if len(path) and path != self.lastroot.value:
1208 self.lastroot.value = path
1209 self.lastroot.save()
1211 def restoreRoot(self):
1213 re = compile('.+?;')
1214 tmp = re.findall(self.lastroot.value)
1217 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1220 path = self.servicePath.pop()
1221 self.enterPath(path)
1223 self.showFavourites()
1226 def preEnterPath(self, refstr):
1227 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1228 pathstr = self.lastroot.value
1229 if pathstr is not None and pathstr.find(refstr) == 0:
1231 lastservice=eServiceReference(self.lastservice.value)
1232 if lastservice.valid():
1233 self.setCurrentSelection(lastservice)
1237 def saveChannel(self, ref):
1239 refstr = ref.toString()
1242 if refstr != self.lastservice.value:
1243 self.lastservice.value = refstr
1244 self.lastservice.save()
1246 def setCurrentServicePath(self, path):
1247 hlen = len(self.history)
1249 self.history[self.history_pos] = path
1251 self.history.append(path)
1252 self.setHistoryPath()
1254 def getCurrentServicePath(self):
1255 hlen = len(self.history)
1257 return self.history[self.history_pos]
1260 def recallPrevService(self):
1261 hlen = len(self.history)
1263 if self.history_pos == hlen-1:
1264 tmp = self.history[self.history_pos]
1265 self.history[self.history_pos] = self.history[self.history_pos-1]
1266 self.history[self.history_pos-1] = tmp
1268 tmp = self.history[self.history_pos+1]
1269 self.history[self.history_pos+1] = self.history[self.history_pos]
1270 self.history[self.history_pos] = tmp
1271 self.setHistoryPath()
1274 if self.revertMode is None:
1276 lastservice=eServiceReference(self.lastservice.value)
1277 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1278 self.setCurrentSelection(lastservice)
1279 elif self.revertMode == MODE_TV:
1281 elif self.revertMode == MODE_RADIO:
1283 self.revertMode = None
1286 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1288 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1289 def __init__(self, session):
1290 Screen.__init__(self, session)
1291 InfoBarEvent.__init__(self)
1292 InfoBarServiceName.__init__(self)
1293 self["CurrentTime"] = Clock()
1294 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1295 self["BlinkingPoint"] = Pixmap()
1296 self["BlinkingPoint"].hide()
1298 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1299 ALLOW_SUSPEND = True
1301 def __init__(self, session, infobar):
1302 ChannelSelectionBase.__init__(self, session)
1303 ChannelSelectionEdit.__init__(self)
1304 ChannelSelectionEPG.__init__(self)
1305 self.infobar = infobar
1306 config.radio = ConfigSubsection();
1307 config.radio.lastservice = ConfigText()
1308 config.radio.lastroot = ConfigText()
1309 self.onLayoutFinish.append(self.onCreate)
1311 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1313 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1315 "keyTV": self.closeRadio,
1316 "keyRadio": self.closeRadio,
1317 "cancel": self.closeRadio,
1318 "ok": self.channelSelected,
1321 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1323 iPlayableService.evStart: self.__evServiceStart,
1324 iPlayableService.evEnd: self.__evServiceEnd
1327 ########## RDS Radiotext / Rass Support BEGIN
1328 self.infobar = infobar # reference to real infobar (the one and only)
1329 self["RdsDecoder"] = self.info["RdsDecoder"]
1330 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1332 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1334 self["RdsActions"].setEnabled(False)
1335 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1337 def startRassInteractive(self):
1339 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1341 def RassInteractiveClosed(self):
1343 self.infobar.rass_interactive = None
1344 self.infobar.RassSlidePicChanged()
1346 def RassInteractivePossibilityChanged(self, state):
1347 self["RdsActions"].setEnabled(state)
1348 ########## RDS Radiotext / Rass Support END
1350 def closeRadio(self):
1351 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1353 #set previous tv service
1354 lastservice=eServiceReference(config.tv.lastservice.value)
1355 self.session.nav.playService(lastservice)
1358 def __evServiceStart(self):
1359 service = self.session.nav.getCurrentService()
1361 info = service.info()
1363 refstr = info.getInfoString(iServiceInformation.sServiceref)
1364 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1366 def __evServiceEnd(self):
1367 self.servicelist.setPlayableIgnoreService(eServiceReference())
1371 for i in self.servicePathRadio:
1372 path += i.toString()
1374 if len(path) and path != config.radio.lastroot.value:
1375 config.radio.lastroot.value = path
1376 config.radio.lastroot.save()
1378 def restoreRoot(self):
1380 re = compile('.+?;')
1381 tmp = re.findall(config.radio.lastroot.value)
1384 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1387 path = self.servicePathRadio.pop()
1388 self.enterPath(path)
1390 self.showFavourites()
1393 def preEnterPath(self, refstr):
1394 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1395 pathstr = config.radio.lastroot.value
1396 if pathstr is not None and pathstr.find(refstr) == 0:
1398 lastservice=eServiceReference(config.radio.lastservice.value)
1399 if lastservice.valid():
1400 self.setCurrentSelection(lastservice)
1407 lastservice=eServiceReference(config.radio.lastservice.value)
1408 if lastservice.valid():
1409 self.servicelist.setCurrent(lastservice)
1410 self.session.nav.playService(lastservice)
1413 def channelSelected(self): # just return selected service
1414 ref = self.getCurrentSelection()
1416 self.toggleMoveMarked()
1417 elif (ref.flags & 7) == 7:
1419 elif self.bouquet_mark_edit != OFF:
1420 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1422 elif not (ref.flags & eServiceReference.isMarker): # no marker
1423 cur_root = self.getRoot()
1424 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1425 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1426 if playingref is None or playingref != ref:
1427 self.session.nav.playService(ref)
1428 config.radio.lastservice.value = ref.toString()
1429 config.radio.lastservice.save()
1432 class SimpleChannelSelection(ChannelSelectionBase):
1433 def __init__(self, session, title):
1434 ChannelSelectionBase.__init__(self, session)
1436 self.onShown.append(self.__onExecCallback)
1438 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1440 "cancel": self.close,
1441 "ok": self.channelSelected,
1442 "keyRadio": self.setModeRadio,
1443 "keyTV": self.setModeTv,
1446 def __onExecCallback(self):
1447 self.setTitle(self.title)
1450 def channelSelected(self): # just return selected service
1451 ref = self.getCurrentSelection()
1452 if (ref.flags & 7) == 7:
1454 elif not (ref.flags & eServiceReference.isMarker):
1455 ref = self.getCurrentSelection()
1458 def setModeTv(self):
1460 self.showFavourites()
1462 def setModeRadio(self):
1464 self.showFavourites()