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 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 cur_ref = self.session.nav.getCurrentlyPlayingServiceReference()
895 pos = self.service_types.rfind(':')
896 refstr = '%s (channelID == %08x%04x%04x) && %s ORDER BY name' %(self.service_types[:pos+1],
897 cur_ref.getUnsignedData(4), # NAMESPACE
898 cur_ref.getUnsignedData(2), # TSID
899 cur_ref.getUnsignedData(3), # ONID
900 self.service_types[pos+1:])
901 ref = eServiceReference(refstr)
902 ref.setName(_("Current Transponder"))
903 self.servicelist.addService(ref)
904 self.servicelist.finishFill()
906 self.setCurrentSelection(prev)
908 def showProviders(self):
909 if not self.pathChangeDisabled:
910 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
911 if not self.preEnterPath(refstr):
912 ref = eServiceReference(refstr)
913 if self.isBasePathEqual(ref):
916 currentRoot = self.getRoot()
917 if currentRoot is None or currentRoot != ref:
921 def changeBouquet(self, direction):
922 if not self.pathChangeDisabled:
923 if len(self.servicePath) > 1:
924 #when enter satellite root list we must do some magic stuff..
925 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
926 if self.isBasePathEqual(ref):
927 self.showSatellites()
934 ref = self.getCurrentSelection()
938 if len(self.servicePath) > 0 and self.servicePath[0] == self.bouquet_root:
943 return self.servicelist.atBegin()
946 return self.servicelist.atEnd()
948 def nextBouquet(self):
949 self.changeBouquet(+1)
951 def prevBouquet(self):
952 self.changeBouquet(-1)
954 def showFavourites(self):
955 if not self.pathChangeDisabled:
956 if not self.preEnterPath(self.bouquet_rootstr):
957 if self.isBasePathEqual(self.bouquet_root):
960 currentRoot = self.getRoot()
961 if currentRoot is None or currentRoot != self.bouquet_root:
963 self.enterPath(self.bouquet_root)
965 def keyNumberGlobal(self, number):
966 unichar = self.numericalTextInput.getKey(number)
967 charstr = unichar.encode("utf-8")
968 if len(charstr) == 1:
969 self.servicelist.moveToChar(charstr[0])
972 return self.servicelist.getRoot()
974 def getCurrentSelection(self):
975 return self.servicelist.getCurrent()
977 def setCurrentSelection(self, service):
978 servicepath = service.getPath()
979 pos = servicepath.find(" FROM BOUQUET")
981 if self.mode == MODE_TV:
982 servicepath = '(type == 1)' + servicepath[pos:]
984 servicepath = '(type == 2)' + servicepath[pos:]
985 service.setPath(servicepath)
986 self.servicelist.setCurrent(service)
988 def getBouquetList(self):
990 serviceHandler = eServiceCenter.getInstance()
991 if config.usage.multibouquet.value:
992 list = serviceHandler.list(self.bouquet_root)
998 if s.flags & eServiceReference.isDirectory:
999 info = serviceHandler.info(s)
1001 bouquets.append((info.getName(s), s))
1004 info = serviceHandler.info(self.bouquet_root)
1006 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
1010 def keyNumber0(self, num):
1011 if len(self.servicePath) > 1:
1014 self.keyNumberGlobal(num)
1017 if len(self.servicePath) > 1:
1018 if self.isBasePathEqual(self.bouquet_root):
1019 self.showFavourites()
1021 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
1022 if self.isBasePathEqual(ref):
1023 self.showSatellites()
1025 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1026 if self.isBasePathEqual(ref):
1027 self.showProviders()
1029 self.showAllServices()
1031 def nextMarker(self):
1032 self.servicelist.moveToNextMarker()
1034 def prevMarker(self):
1035 self.servicelist.moveToPrevMarker()
1039 #config for lastservice
1040 config.tv = ConfigSubsection()
1041 config.tv.lastservice = ConfigText()
1042 config.tv.lastroot = ConfigText()
1043 config.radio = ConfigSubsection()
1044 config.radio.lastservice = ConfigText()
1045 config.radio.lastroot = ConfigText()
1046 config.servicelist = ConfigSubsection()
1047 config.servicelist.lastmode = ConfigText(default = "tv")
1049 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, SelectionEventInfo):
1050 def __init__(self, session):
1051 ChannelSelectionBase.__init__(self,session)
1052 ChannelSelectionEdit.__init__(self)
1053 ChannelSelectionEPG.__init__(self)
1054 SelectionEventInfo.__init__(self)
1056 self["CurrentTime"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
1058 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1060 "cancel": self.cancel,
1061 "ok": self.channelSelected,
1062 "keyRadio": self.setModeRadio,
1063 "keyTV": self.setModeTv,
1066 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1068 iPlayableService.evStart: self.__evServiceStart,
1069 iPlayableService.evEnd: self.__evServiceEnd
1072 self.lastChannelRootTimer = eTimer()
1073 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1074 self.lastChannelRootTimer.start(100,True)
1076 self.history_tv = [ ]
1077 self.history_radio = [ ]
1078 self.history = self.history_tv
1079 self.history_pos = 0
1081 self.lastservice = config.tv.lastservice
1082 self.lastroot = config.tv.lastroot
1083 self.revertMode = None
1084 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1085 self.new_service_played = False
1087 def multibouquet_config_changed(self, val):
1088 self.recallBouquetMode()
1090 def __evServiceStart(self):
1091 service = self.session.nav.getCurrentService()
1093 info = service.info()
1095 refstr = info.getInfoString(iServiceInformation.sServiceref)
1096 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1098 def __evServiceEnd(self):
1099 self.servicelist.setPlayableIgnoreService(eServiceReference())
1103 lastservice=eServiceReference(self.lastservice.value)
1104 if lastservice.valid():
1105 self.setCurrentSelection(lastservice)
1107 def setModeTv(self):
1108 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1109 self.revertMode = MODE_RADIO
1110 self.history = self.history_tv
1111 self.lastservice = config.tv.lastservice
1112 self.lastroot = config.tv.lastroot
1113 config.servicelist.lastmode.value = "tv"
1117 def setModeRadio(self):
1118 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1119 self.revertMode = MODE_TV
1120 if config.usage.e1like_radio_mode.value:
1121 self.history = self.history_radio
1122 self.lastservice = config.radio.lastservice
1123 self.lastroot = config.radio.lastroot
1124 config.servicelist.lastmode.value = "radio"
1128 def __onCreate(self):
1129 if config.usage.e1like_radio_mode.value:
1130 if config.servicelist.lastmode.value == "tv":
1136 lastservice=eServiceReference(self.lastservice.value)
1137 if lastservice.valid():
1140 def channelSelected(self):
1141 ref = self.getCurrentSelection()
1143 self.toggleMoveMarked()
1144 elif (ref.flags & 7) == 7:
1146 elif self.bouquet_mark_edit != OFF:
1147 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1149 elif not (ref.flags & eServiceReference.isMarker): # no marker
1150 root = self.getRoot()
1151 if not root or not (root.flags & eServiceReference.isGroup):
1155 #called from infoBar and channelSelected
1157 self.revertMode=None
1158 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1159 nref = self.getCurrentSelection()
1160 if ref is None or ref != nref:
1161 self.new_service_played = True
1162 self.session.nav.playService(nref)
1164 self.saveChannel(nref)
1165 config.servicelist.lastmode.save()
1166 self.addToHistory(nref)
1168 def newServicePlayed(self):
1169 ret = self.new_service_played
1170 self.new_service_played = False
1173 def addToHistory(self, ref):
1174 if self.servicePath is not None:
1175 tmp=self.servicePath[:]
1178 del self.history[self.history_pos+1:]
1181 self.history.append(tmp)
1182 hlen = len(self.history)
1183 if hlen > HISTORYSIZE:
1186 self.history_pos = hlen-1
1188 def historyBack(self):
1189 hlen = len(self.history)
1190 if hlen > 1 and self.history_pos > 0:
1191 self.history_pos -= 1
1192 self.setHistoryPath()
1194 def historyNext(self):
1195 hlen = len(self.history)
1196 if hlen > 1 and self.history_pos < (hlen-1):
1197 self.history_pos += 1
1198 self.setHistoryPath()
1200 def setHistoryPath(self):
1201 path = self.history[self.history_pos][:]
1203 del self.servicePath[:]
1204 self.servicePath += path
1208 cur_root = self.getRoot()
1209 if cur_root and cur_root != root:
1211 self.session.nav.playService(ref)
1212 self.setCurrentSelection(ref)
1213 self.saveChannel(ref)
1217 for i in self.servicePath:
1218 path += i.toString()
1220 if len(path) and path != self.lastroot.value:
1221 self.lastroot.value = path
1222 self.lastroot.save()
1224 def restoreRoot(self):
1226 re = compile('.+?;')
1227 tmp = re.findall(self.lastroot.value)
1230 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1233 path = self.servicePath.pop()
1234 self.enterPath(path)
1236 self.showFavourites()
1239 def preEnterPath(self, refstr):
1240 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1241 pathstr = self.lastroot.value
1242 if pathstr is not None and pathstr.find(refstr) == 0:
1244 lastservice=eServiceReference(self.lastservice.value)
1245 if lastservice.valid():
1246 self.setCurrentSelection(lastservice)
1250 def saveChannel(self, ref):
1252 refstr = ref.toString()
1255 if refstr != self.lastservice.value:
1256 self.lastservice.value = refstr
1257 self.lastservice.save()
1259 def setCurrentServicePath(self, path):
1260 hlen = len(self.history)
1262 self.history[self.history_pos] = path
1264 self.history.append(path)
1265 self.setHistoryPath()
1267 def getCurrentServicePath(self):
1268 hlen = len(self.history)
1270 return self.history[self.history_pos]
1273 def recallPrevService(self):
1274 hlen = len(self.history)
1276 if self.history_pos == hlen-1:
1277 tmp = self.history[self.history_pos]
1278 self.history[self.history_pos] = self.history[self.history_pos-1]
1279 self.history[self.history_pos-1] = tmp
1281 tmp = self.history[self.history_pos+1]
1282 self.history[self.history_pos+1] = self.history[self.history_pos]
1283 self.history[self.history_pos] = tmp
1284 self.setHistoryPath()
1287 if self.revertMode is None:
1289 lastservice=eServiceReference(self.lastservice.value)
1290 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1291 self.setCurrentSelection(lastservice)
1292 elif self.revertMode == MODE_TV:
1294 elif self.revertMode == MODE_RADIO:
1296 self.revertMode = None
1299 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1301 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1302 def __init__(self, session):
1303 Screen.__init__(self, session)
1304 InfoBarEvent.__init__(self)
1305 InfoBarServiceName.__init__(self)
1306 self["CurrentTime"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
1307 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1308 self["BlinkingPoint"] = Pixmap()
1309 self["BlinkingPoint"].hide()
1311 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1312 ALLOW_SUSPEND = True
1314 def __init__(self, session, infobar):
1315 ChannelSelectionBase.__init__(self, session)
1316 ChannelSelectionEdit.__init__(self)
1317 ChannelSelectionEPG.__init__(self)
1318 self.infobar = infobar
1319 config.radio = ConfigSubsection();
1320 config.radio.lastservice = ConfigText()
1321 config.radio.lastroot = ConfigText()
1322 self.onLayoutFinish.append(self.onCreate)
1324 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1326 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1328 "keyTV": self.closeRadio,
1329 "keyRadio": self.closeRadio,
1330 "cancel": self.closeRadio,
1331 "ok": self.channelSelected,
1334 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1336 iPlayableService.evStart: self.__evServiceStart,
1337 iPlayableService.evEnd: self.__evServiceEnd
1340 ########## RDS Radiotext / Rass Support BEGIN
1341 self.infobar = infobar # reference to real infobar (the one and only)
1342 self["RdsDecoder"] = self.info["RdsDecoder"]
1343 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1345 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1347 self["RdsActions"].setEnabled(False)
1348 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1350 def startRassInteractive(self):
1352 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1354 def RassInteractiveClosed(self):
1356 self.infobar.rass_interactive = None
1357 self.infobar.RassSlidePicChanged()
1359 def RassInteractivePossibilityChanged(self, state):
1360 self["RdsActions"].setEnabled(state)
1361 ########## RDS Radiotext / Rass Support END
1363 def closeRadio(self):
1364 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1366 #set previous tv service
1367 lastservice=eServiceReference(config.tv.lastservice.value)
1368 self.session.nav.playService(lastservice)
1371 def __evServiceStart(self):
1372 service = self.session.nav.getCurrentService()
1374 info = service.info()
1376 refstr = info.getInfoString(iServiceInformation.sServiceref)
1377 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1379 def __evServiceEnd(self):
1380 self.servicelist.setPlayableIgnoreService(eServiceReference())
1384 for i in self.servicePathRadio:
1385 path += i.toString()
1387 if len(path) and path != config.radio.lastroot.value:
1388 config.radio.lastroot.value = path
1389 config.radio.lastroot.save()
1391 def restoreRoot(self):
1393 re = compile('.+?;')
1394 tmp = re.findall(config.radio.lastroot.value)
1397 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1400 path = self.servicePathRadio.pop()
1401 self.enterPath(path)
1403 self.showFavourites()
1406 def preEnterPath(self, refstr):
1407 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1408 pathstr = config.radio.lastroot.value
1409 if pathstr is not None and pathstr.find(refstr) == 0:
1411 lastservice=eServiceReference(config.radio.lastservice.value)
1412 if lastservice.valid():
1413 self.setCurrentSelection(lastservice)
1420 lastservice=eServiceReference(config.radio.lastservice.value)
1421 if lastservice.valid():
1422 self.servicelist.setCurrent(lastservice)
1423 self.session.nav.playService(lastservice)
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()