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["CurrentTime"] = Clock()
1047 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1049 "cancel": self.cancel,
1050 "ok": self.channelSelected,
1051 "keyRadio": self.setModeRadio,
1052 "keyTV": self.setModeTv,
1055 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1057 iPlayableService.evStart: self.__evServiceStart,
1058 iPlayableService.evEnd: self.__evServiceEnd
1061 self.lastChannelRootTimer = eTimer()
1062 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1063 self.lastChannelRootTimer.start(100,True)
1065 self.history_tv = [ ]
1066 self.history_radio = [ ]
1067 self.history = self.history_tv
1068 self.history_pos = 0
1070 self.lastservice = config.tv.lastservice
1071 self.lastroot = config.tv.lastroot
1072 self.revertMode = None
1073 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1074 self.new_service_played = False
1076 def multibouquet_config_changed(self, val):
1077 self.recallBouquetMode()
1079 def __evServiceStart(self):
1080 service = self.session.nav.getCurrentService()
1082 info = service.info()
1084 refstr = info.getInfoString(iServiceInformation.sServiceref)
1085 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1087 def __evServiceEnd(self):
1088 self.servicelist.setPlayableIgnoreService(eServiceReference())
1092 lastservice=eServiceReference(self.lastservice.value)
1093 if lastservice.valid():
1094 self.setCurrentSelection(lastservice)
1096 def setModeTv(self):
1097 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1098 self.revertMode = MODE_RADIO
1099 self.history = self.history_tv
1100 self.lastservice = config.tv.lastservice
1101 self.lastroot = config.tv.lastroot
1102 config.servicelist.lastmode.value = "tv"
1106 def setModeRadio(self):
1107 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1108 self.revertMode = MODE_TV
1109 if config.usage.e1like_radio_mode.value:
1110 self.history = self.history_radio
1111 self.lastservice = config.radio.lastservice
1112 self.lastroot = config.radio.lastroot
1113 config.servicelist.lastmode.value = "radio"
1117 def __onCreate(self):
1118 if config.usage.e1like_radio_mode.value:
1119 if config.servicelist.lastmode.value == "tv":
1125 lastservice=eServiceReference(self.lastservice.value)
1126 if lastservice.valid():
1129 def channelSelected(self):
1130 ref = self.getCurrentSelection()
1132 self.toggleMoveMarked()
1133 elif (ref.flags & 7) == 7:
1135 elif self.bouquet_mark_edit != OFF:
1136 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1138 elif not (ref.flags & eServiceReference.isMarker): # no marker
1139 root = self.getRoot()
1140 if not root or not (root.flags & eServiceReference.isGroup):
1144 #called from infoBar and channelSelected
1146 self.revertMode=None
1147 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1148 nref = self.getCurrentSelection()
1149 if ref is None or ref != nref:
1150 self.new_service_played = True
1151 self.session.nav.playService(nref)
1153 self.saveChannel(nref)
1154 config.servicelist.lastmode.save()
1155 self.addToHistory(nref)
1157 def newServicePlayed(self):
1158 ret = self.new_service_played
1159 self.new_service_played = False
1162 def addToHistory(self, ref):
1163 if self.servicePath is not None:
1164 tmp=self.servicePath[:]
1167 del self.history[self.history_pos+1:]
1170 self.history.append(tmp)
1171 hlen = len(self.history)
1172 if hlen > HISTORYSIZE:
1175 self.history_pos = hlen-1
1177 def historyBack(self):
1178 hlen = len(self.history)
1179 if hlen > 1 and self.history_pos > 0:
1180 self.history_pos -= 1
1181 self.setHistoryPath()
1183 def historyNext(self):
1184 hlen = len(self.history)
1185 if hlen > 1 and self.history_pos < (hlen-1):
1186 self.history_pos += 1
1187 self.setHistoryPath()
1189 def setHistoryPath(self):
1190 path = self.history[self.history_pos][:]
1192 del self.servicePath[:]
1193 self.servicePath += path
1197 cur_root = self.getRoot()
1198 if cur_root and cur_root != root:
1200 self.session.nav.playService(ref)
1201 self.setCurrentSelection(ref)
1202 self.saveChannel(ref)
1206 for i in self.servicePath:
1207 path += i.toString()
1209 if len(path) and path != self.lastroot.value:
1210 self.lastroot.value = path
1211 self.lastroot.save()
1213 def restoreRoot(self):
1215 re = compile('.+?;')
1216 tmp = re.findall(self.lastroot.value)
1219 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1222 path = self.servicePath.pop()
1223 self.enterPath(path)
1225 self.showFavourites()
1228 def preEnterPath(self, refstr):
1229 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1230 pathstr = self.lastroot.value
1231 if pathstr is not None and pathstr.find(refstr) == 0:
1233 lastservice=eServiceReference(self.lastservice.value)
1234 if lastservice.valid():
1235 self.setCurrentSelection(lastservice)
1239 def saveChannel(self, ref):
1241 refstr = ref.toString()
1244 if refstr != self.lastservice.value:
1245 self.lastservice.value = refstr
1246 self.lastservice.save()
1248 def setCurrentServicePath(self, path):
1249 hlen = len(self.history)
1251 self.history[self.history_pos] = path
1253 self.history.append(path)
1254 self.setHistoryPath()
1256 def getCurrentServicePath(self):
1257 hlen = len(self.history)
1259 return self.history[self.history_pos]
1262 def recallPrevService(self):
1263 hlen = len(self.history)
1265 if self.history_pos == hlen-1:
1266 tmp = self.history[self.history_pos]
1267 self.history[self.history_pos] = self.history[self.history_pos-1]
1268 self.history[self.history_pos-1] = tmp
1270 tmp = self.history[self.history_pos+1]
1271 self.history[self.history_pos+1] = self.history[self.history_pos]
1272 self.history[self.history_pos] = tmp
1273 self.setHistoryPath()
1276 if self.revertMode is None:
1278 lastservice=eServiceReference(self.lastservice.value)
1279 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1280 self.setCurrentSelection(lastservice)
1281 elif self.revertMode == MODE_TV:
1283 elif self.revertMode == MODE_RADIO:
1285 self.revertMode = None
1288 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1290 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1291 def __init__(self, session):
1292 Screen.__init__(self, session)
1293 InfoBarEvent.__init__(self)
1294 InfoBarServiceName.__init__(self)
1295 self["CurrentTime"] = Clock()
1296 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1297 self["BlinkingPoint"] = Pixmap()
1298 self["BlinkingPoint"].hide()
1300 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1301 ALLOW_SUSPEND = True
1303 def __init__(self, session, infobar):
1304 ChannelSelectionBase.__init__(self, session)
1305 ChannelSelectionEdit.__init__(self)
1306 ChannelSelectionEPG.__init__(self)
1307 self.infobar = infobar
1308 config.radio = ConfigSubsection();
1309 config.radio.lastservice = ConfigText()
1310 config.radio.lastroot = ConfigText()
1311 self.onLayoutFinish.append(self.onCreate)
1313 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1315 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1317 "keyTV": self.closeRadio,
1318 "keyRadio": self.closeRadio,
1319 "cancel": self.closeRadio,
1320 "ok": self.channelSelected,
1323 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1325 iPlayableService.evStart: self.__evServiceStart,
1326 iPlayableService.evEnd: self.__evServiceEnd
1329 ########## RDS Radiotext / Rass Support BEGIN
1330 self.infobar = infobar # reference to real infobar (the one and only)
1331 self["RdsDecoder"] = self.info["RdsDecoder"]
1332 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1334 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1336 self["RdsActions"].setEnabled(False)
1337 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1339 def startRassInteractive(self):
1341 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1343 def RassInteractiveClosed(self):
1345 self.infobar.rass_interactive = None
1346 self.infobar.RassSlidePicChanged()
1348 def RassInteractivePossibilityChanged(self, state):
1349 self["RdsActions"].setEnabled(state)
1350 ########## RDS Radiotext / Rass Support END
1352 def closeRadio(self):
1353 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1355 #set previous tv service
1356 lastservice=eServiceReference(config.tv.lastservice.value)
1357 self.session.nav.playService(lastservice)
1360 def __evServiceStart(self):
1361 service = self.session.nav.getCurrentService()
1363 info = service.info()
1365 refstr = info.getInfoString(iServiceInformation.sServiceref)
1366 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1368 def __evServiceEnd(self):
1369 self.servicelist.setPlayableIgnoreService(eServiceReference())
1373 for i in self.servicePathRadio:
1374 path += i.toString()
1376 if len(path) and path != config.radio.lastroot.value:
1377 config.radio.lastroot.value = path
1378 config.radio.lastroot.save()
1380 def restoreRoot(self):
1382 re = compile('.+?;')
1383 tmp = re.findall(config.radio.lastroot.value)
1386 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1389 path = self.servicePathRadio.pop()
1390 self.enterPath(path)
1392 self.showFavourites()
1395 def preEnterPath(self, refstr):
1396 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1397 pathstr = config.radio.lastroot.value
1398 if pathstr is not None and pathstr.find(refstr) == 0:
1400 lastservice=eServiceReference(config.radio.lastservice.value)
1401 if lastservice.valid():
1402 self.setCurrentSelection(lastservice)
1409 lastservice=eServiceReference(config.radio.lastservice.value)
1410 if lastservice.valid():
1411 self.servicelist.setCurrent(lastservice)
1412 self.session.nav.playService(lastservice)
1415 def channelSelected(self): # just return selected service
1416 ref = self.getCurrentSelection()
1418 self.toggleMoveMarked()
1419 elif (ref.flags & 7) == 7:
1421 elif self.bouquet_mark_edit != OFF:
1422 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1424 elif not (ref.flags & eServiceReference.isMarker): # no marker
1425 cur_root = self.getRoot()
1426 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1427 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1428 if playingref is None or playingref != ref:
1429 self.session.nav.playService(ref)
1430 config.radio.lastservice.value = ref.toString()
1431 config.radio.lastservice.save()
1434 class SimpleChannelSelection(ChannelSelectionBase):
1435 def __init__(self, session, title):
1436 ChannelSelectionBase.__init__(self, session)
1438 self.onShown.append(self.__onExecCallback)
1440 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1442 "cancel": self.close,
1443 "ok": self.channelSelected,
1444 "keyRadio": self.setModeRadio,
1445 "keyTV": self.setModeTv,
1448 def __onExecCallback(self):
1449 self.setTitle(self.title)
1452 def channelSelected(self): # just return selected service
1453 ref = self.getCurrentSelection()
1454 if (ref.flags & 7) == 7:
1456 elif not (ref.flags & eServiceReference.isMarker):
1457 ref = self.getCurrentSelection()
1460 def setModeTv(self):
1462 self.showFavourites()
1464 def setModeRadio(self):
1466 self.showFavourites()