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 Screens.FixedMenu import FixedMenu
11 from Tools.NumericalTextInput import NumericalTextInput
12 from Components.NimManager import nimmanager
13 from Components.Sources.Clock import Clock
14 from Components.Sources.RdsDecoder import RdsDecoder
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
27 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
29 import xml.dom.minidom
31 class BouquetSelector(Screen):
32 def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
33 Screen.__init__(self, session)
35 self.selectedFunc=selectedFunc
37 self["actions"] = ActionMap(["OkCancelActions"],
39 "ok": self.okbuttonClick,
40 "cancel": self.cancelClick
42 entrys = [ (x[0], x[1]) for x in bouquets ]
43 self["menu"] = MenuList(entrys, enableWrapAround)
46 cur = self["menu"].getCurrent()
49 def okbuttonClick(self):
50 self.selectedFunc(self.getCurrent())
58 def cancelClick(self):
61 # csel.bouquet_mark_edit values
66 def apend_when_current_valid(current, menu, args):
67 if current and current.valid():
70 class ChannelContextMenu(Screen):
71 def __init__(self, session, csel):
72 Screen.__init__(self, session)
76 self["actions"] = ActionMap(["OkCancelActions"],
78 "ok": self.okbuttonClick,
79 "cancel": self.cancelClick
83 current = csel.getCurrentSelection()
84 current_root = csel.getRoot()
85 current_sel_path = current.getPath()
86 current_sel_flags = current.flags
87 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
88 inBouquet = csel.getMutableList() is not None
89 haveBouquets = config.usage.multibouquet.value
91 if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
92 apend_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations))
93 if csel.bouquet_mark_edit == OFF and not csel.movemode:
94 if not inBouquetRootList:
95 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
97 if config.ParentalControl.configured.value:
98 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
99 apend_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
101 apend_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
103 apend_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected))
105 apend_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected))
108 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
109 apend_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList))
110 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
111 apend_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags))
113 apend_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService))
114 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
115 apend_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag))
117 menu.append((_("add bouquet"), self.showBouquetInputBox))
118 apend_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet))
120 if inBouquet: # current list is editable?
121 if csel.bouquet_mark_edit == OFF:
122 if not csel.movemode:
123 apend_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode))
124 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
125 menu.append((_("add marker"), self.showMarkerInputBox))
127 apend_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart))
129 apend_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart))
130 if current_sel_flags & eServiceReference.isGroup:
131 apend_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices))
132 apend_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices))
133 apend_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices))
134 elif not current_sel_flags & eServiceReference.isMarker:
135 apend_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices))
137 apend_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode))
139 if csel.bouquet_mark_edit == EDIT_BOUQUET:
141 apend_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd))
142 apend_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort))
144 apend_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd))
145 apend_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort))
147 apend_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd))
148 apend_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort))
150 menu.append((_("back"), self.cancelClick))
151 self["menu"] = MenuList(menu)
153 def okbuttonClick(self):
154 self["menu"].getCurrent()[1]()
156 def cancelClick(self):
159 def showServiceInformations(self):
160 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
162 def showBouquetInputBox(self):
163 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
165 def bouquetInputCallback(self, bouquet):
166 if bouquet is not None:
167 self.csel.addBouquet(bouquet, None)
170 def addParentalProtection(self, service):
171 parentalControl.protectService(service.toCompareString())
174 def removeParentalProtection(self, service):
175 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"))
177 def pinEntered(self, service, result):
179 parentalControl.unProtectService(service)
182 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
184 def addServiceToBouquetSelected(self):
185 bouquets = self.csel.getBouquetList()
190 if cnt > 1: # show bouquet list
191 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
192 elif cnt == 1: # add to only one existing bouquet
193 self.addCurrentServiceToBouquet(bouquets[0][1])
195 def bouquetSelClosed(self, recursive):
200 def copyCurrentToBouquetList(self):
201 self.csel.copyCurrentToBouquetList()
204 def removeBouquet(self):
205 self.csel.removeBouquet()
208 def showMarkerInputBox(self):
209 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, type=Input.TEXT)
211 def markerInputCallback(self, marker):
212 if marker is not None:
213 self.csel.addMarker(marker)
216 def addCurrentServiceToBouquet(self, dest):
217 self.csel.addServiceToBouquet(dest)
218 if self.bsel is not None:
219 self.bsel.close(True)
221 self.close(True) # close bouquet selection
223 def removeCurrentService(self):
224 self.csel.removeCurrentService()
227 def toggleMoveMode(self):
228 self.csel.toggleMoveMode()
231 def bouquetMarkStart(self):
232 self.csel.startMarkedEdit(EDIT_BOUQUET)
235 def bouquetMarkEnd(self):
236 self.csel.endMarkedEdit(abort=False)
239 def bouquetMarkAbort(self):
240 self.csel.endMarkedEdit(abort=True)
243 def removeNewFoundFlag(self):
244 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
247 def removeAllNewFoundFlags(self):
248 curpath = self.csel.getCurrentSelection().getPath()
249 idx = curpath.find("satellitePosition == ")
251 tmp = curpath[idx+21:]
254 satpos = int(tmp[:idx])
255 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
258 def editAlternativeServices(self):
259 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
262 def showAlternativeServices(self):
263 self.csel.enterPath(self.csel.getCurrentSelection())
266 def removeAlternativeServices(self):
267 self.csel.removeAlternativeServices()
270 def addAlternativeServices(self):
271 self.csel.addAlternativeServices()
272 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
275 class ChannelSelectionEPG:
277 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
279 "showEPGList": self.showEPGList,
282 def showEPGList(self):
283 ref=self.getCurrentSelection()
284 ptr=eEPGCache.getInstance()
285 if ptr.startTimeQuery(ref) != -1:
286 self.session.open(EPGSelection, ref)
288 print 'no epg for service', ref.toString()
290 class ChannelSelectionEdit:
292 self.entry_marked = False
293 self.movemode = False
294 self.bouquet_mark_edit = OFF
295 self.mutableList = None
297 self.saved_title = None
298 self.saved_root = None
300 class ChannelSelectionEditActionMap(ActionMap):
301 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
302 ActionMap.__init__(self, contexts, actions, prio)
305 def action(self, contexts, action):
306 if action == "cancel":
307 self.csel.handleEditCancel()
308 return 0 # fall-trough
310 return 0 # fall-trough
312 return ActionMap.action(self, contexts, action)
314 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
316 "contextMenu": self.doContext,
319 def getMutableList(self, root=eServiceReference()):
320 if not self.mutableList is None:
321 return self.mutableList
322 serviceHandler = eServiceCenter.getInstance()
325 list = root and serviceHandler.list(root)
327 return list.startEdit()
330 def buildBouquetID(self, str):
334 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
340 def addMarker(self, name):
341 current = self.servicelist.getCurrent()
342 mutableList = self.getMutableList()
345 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
346 ref = eServiceReference(str)
347 if current and current.valid():
348 if not mutableList.addService(ref, current):
349 self.servicelist.addService(ref, True)
350 mutableList.flushChanges()
352 elif not mutableList.addService(ref):
353 self.servicelist.addService(ref, True)
354 mutableList.flushChanges()
358 def addAlternativeServices(self):
359 cur_service = ServiceReference(self.getCurrentSelection())
360 root = self.getRoot()
361 cur_root = root and ServiceReference(root)
362 mutableBouquet = cur_root.list().startEdit()
364 name = cur_service.getServiceName()
366 if self.mode == MODE_TV:
367 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
369 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
370 new_ref = ServiceReference(str)
371 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
372 mutableBouquet.removeService(cur_service.ref)
373 mutableBouquet.flushChanges()
374 eDVBDB.getInstance().reloadBouquets()
375 mutableAlternatives = new_ref.list().startEdit()
376 if mutableAlternatives:
377 mutableAlternatives.setListName(name)
378 if mutableAlternatives.addService(cur_service.ref):
379 print "add", cur_service.toString(), "to new alternatives failed"
380 mutableAlternatives.flushChanges()
381 self.servicelist.addService(new_ref.ref, True)
382 self.servicelist.removeCurrent()
383 self.servicelist.moveUp()
385 print "get mutable list for new created alternatives failed"
387 print "add", str, "to", cur_root.getServiceName(), "failed"
389 print "bouquetlist is not editable"
391 def addBouquet(self, bName, services):
392 serviceHandler = eServiceCenter.getInstance()
393 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
394 if mutableBouquetList:
395 if self.mode == MODE_TV:
397 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
400 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
401 new_bouquet_ref = eServiceReference(str)
402 if not mutableBouquetList.addService(new_bouquet_ref):
403 mutableBouquetList.flushChanges()
404 eDVBDB.getInstance().reloadBouquets()
405 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
407 mutableBouquet.setListName(bName)
408 if services is not None:
409 for service in services:
410 if mutableBouquet.addService(service):
411 print "add", service.toString(), "to new bouquet failed"
412 mutableBouquet.flushChanges()
414 print "get mutable list for new created bouquet failed"
415 # do some voodoo to check if current_root is equal to bouquet_root
416 cur_root = self.getRoot();
417 str1 = cur_root and cur_root.toString()
418 pos1 = str1 and str1.find("FROM BOUQUET") or -1
419 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
420 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
421 self.servicelist.addService(new_bouquet_ref)
423 print "add", str, "to bouquets failed"
425 print "bouquetlist is not editable"
427 def copyCurrentToBouquetList(self):
428 provider = ServiceReference(self.getCurrentSelection())
429 providerName = provider.getServiceName()
430 serviceHandler = eServiceCenter.getInstance()
431 services = serviceHandler.list(provider.ref)
432 self.addBouquet(providerName, services and services.getContent('R', True))
434 def removeAlternativeServices(self):
435 cur_service = ServiceReference(self.getCurrentSelection())
436 root = self.getRoot()
437 cur_root = root and ServiceReference(root)
438 list = cur_service.list()
439 first_in_alternative = list and list.getNext()
440 if first_in_alternative:
441 edit_root = cur_root and cur_root.list().startEdit()
443 if not edit_root.addService(first_in_alternative, cur_service.ref):
444 self.servicelist.addService(first_in_alternative, True)
446 print "couldn't add first alternative service to current root"
448 print "couldn't edit current root!!"
450 print "remove empty alternative list !!"
452 self.servicelist.moveUp()
454 def removeBouquet(self):
455 refstr = self.getCurrentSelection().toString()
456 print "removeBouquet", refstr
457 self.bouquetNumOffsetCache = { }
458 pos = refstr.find('FROM BOUQUET "')
461 refstr = refstr[pos+14:]
462 pos = refstr.find('"')
464 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
465 self.removeCurrentService()
467 if filename is not None:
470 print "error during remove of", filename
472 # multiple marked entry stuff ( edit mode, later multiepg selection )
473 def startMarkedEdit(self, type):
474 self.savedPath = self.servicePath[:]
475 if type == EDIT_ALTERNATIVES:
476 self.enterPath(self.getCurrentSelection())
477 self.mutableList = self.getMutableList()
478 # add all services from the current list to internal marked set in listboxservicecontent
479 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
480 self.saved_title = self.instance.getTitle()
481 pos = self.saved_title.find(')')
482 new_title = self.saved_title[:pos+1]
483 if type == EDIT_ALTERNATIVES:
484 self.bouquet_mark_edit = EDIT_ALTERNATIVES
485 new_title += ' ' + _("[alternative edit]")
487 self.bouquet_mark_edit = EDIT_BOUQUET
488 if config.usage.multibouquet.value:
489 new_title += ' ' + _("[bouquet edit]")
491 new_title += ' ' + _("[favourite edit]")
492 self.setTitle(new_title)
493 self.__marked = self.servicelist.getRootServices()
494 for x in self.__marked:
495 self.servicelist.addMarked(eServiceReference(x))
496 self.showAllServices()
498 def endMarkedEdit(self, abort):
499 if not abort and self.mutableList is not None:
500 self.bouquetNumOffsetCache = { }
501 new_marked = set(self.servicelist.getMarked())
502 old_marked = set(self.__marked)
503 removed = old_marked - new_marked
504 added = new_marked - old_marked
508 self.mutableList.removeService(eServiceReference(x))
511 self.mutableList.addService(eServiceReference(x))
513 self.mutableList.flushChanges()
516 self.bouquet_mark_edit = OFF
517 self.mutableList = None
518 self.setTitle(self.saved_title)
519 self.saved_title = None
520 # self.servicePath is just a reference to servicePathTv or Radio...
521 # so we never ever do use the asignment operator in self.servicePath
522 del self.servicePath[:] # remove all elements
523 self.servicePath += self.savedPath # add saved elements
525 self.setRoot(self.servicePath[len(self.servicePath)-1])
527 def clearMarks(self):
528 self.servicelist.clearMarks()
531 ref = self.servicelist.getCurrent()
532 if self.servicelist.isMarked(ref):
533 self.servicelist.removeMarked(ref)
535 self.servicelist.addMarked(ref)
537 def removeCurrentService(self):
538 ref = self.servicelist.getCurrent()
539 mutableList = self.getMutableList()
540 if ref.valid() and mutableList is not None:
541 if not mutableList.removeService(ref):
542 self.bouquetNumOffsetCache = { }
543 mutableList.flushChanges() #FIXME dont flush on each single removed service
544 self.servicelist.removeCurrent()
546 def addServiceToBouquet(self, dest, service=None):
547 mutableList = self.getMutableList(dest)
548 if not mutableList is None:
549 if service is None: #use current selected service
550 service = self.servicelist.getCurrent()
551 if not mutableList.addService(service):
552 self.bouquetNumOffsetCache = { }
553 mutableList.flushChanges()
554 # do some voodoo to check if current_root is equal to dest
555 cur_root = self.getRoot();
556 str1 = cur_root and cur_root.toString() or -1
557 str2 = dest.toString()
558 pos1 = str1.find("FROM BOUQUET")
559 pos2 = str2.find("FROM BOUQUET")
560 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
561 self.servicelist.addService(service)
563 def toggleMoveMode(self):
565 if self.entry_marked:
566 self.toggleMoveMarked() # unmark current entry
567 self.movemode = False
568 self.pathChangeDisabled = False # re-enable path change
569 self.mutableList.flushChanges() # FIXME add check if changes was made
570 self.mutableList = None
571 self.setTitle(self.saved_title)
572 self.saved_title = None
573 cur_root = self.getRoot()
574 if cur_root and cur_root == self.bouquet_root:
575 self.bouquetNumOffsetCache = { }
577 self.mutableList = self.getMutableList()
579 self.pathChangeDisabled = True # no path change allowed in movemode
580 self.saved_title = self.instance.getTitle()
581 new_title = self.saved_title
582 pos = self.saved_title.find(')')
583 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
584 self.setTitle(new_title);
586 def handleEditCancel(self):
587 if self.movemode: #movemode active?
588 self.channelSelected() # unmark
589 self.toggleMoveMode() # disable move mode
590 elif self.bouquet_mark_edit != OFF:
591 self.endMarkedEdit(True) # abort edit mode
593 def toggleMoveMarked(self):
594 if self.entry_marked:
595 self.servicelist.setCurrentMarked(False)
596 self.entry_marked = False
598 self.servicelist.setCurrentMarked(True)
599 self.entry_marked = True
602 self.session.open(ChannelContextMenu, self)
607 # this makes it much simple to implement a selectable radio or tv mode :)
608 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
609 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
611 class ChannelSelectionBase(Screen):
612 def __init__(self, session):
613 Screen.__init__(self, session)
615 self["key_red"] = Button(_("All"))
616 self["key_green"] = Button(_("Satellites"))
617 self["key_yellow"] = Button(_("Provider"))
618 self["key_blue"] = Button(_("Favourites"))
620 self["list"] = ServiceList()
621 self.servicelist = self["list"]
623 self.numericalTextInput = NumericalTextInput()
624 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
626 self.servicePathTV = [ ]
627 self.servicePathRadio = [ ]
628 self.servicePath = [ ]
632 self.pathChangeDisabled = False
634 self.bouquetNumOffsetCache = { }
636 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
638 "showFavourites": self.showFavourites,
639 "showAllServices": self.showAllServices,
640 "showProviders": self.showProviders,
641 "showSatellites": self.showSatellites,
642 "nextBouquet": self.nextBouquet,
643 "prevBouquet": self.prevBouquet,
644 "nextMarker": self.nextMarker,
645 "prevMarker": self.prevMarker,
646 "1": self.keyNumberGlobal,
647 "2": self.keyNumberGlobal,
648 "3": self.keyNumberGlobal,
649 "4": self.keyNumberGlobal,
650 "5": self.keyNumberGlobal,
651 "6": self.keyNumberGlobal,
652 "7": self.keyNumberGlobal,
653 "8": self.keyNumberGlobal,
654 "9": self.keyNumberGlobal,
657 self.recallBouquetMode()
659 def getBouquetNumOffset(self, bouquet):
660 if not config.usage.multibouquet.value:
662 str = bouquet.toString()
664 if not self.bouquetNumOffsetCache.has_key(str):
665 serviceHandler = eServiceCenter.getInstance()
666 bouquetlist = serviceHandler.list(self.bouquet_root)
667 if not bouquetlist is None:
669 bouquetIterator = bouquetlist.getNext()
670 if not bouquetIterator.valid(): #end of list
672 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
673 if not (bouquetIterator.flags & eServiceReference.isDirectory):
675 servicelist = serviceHandler.list(bouquetIterator)
676 if not servicelist is None:
678 serviceIterator = servicelist.getNext()
679 if not serviceIterator.valid(): #check if end of list
681 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
684 return self.bouquetNumOffsetCache.get(str, offsetCount)
686 def recallBouquetMode(self):
687 if self.mode == MODE_TV:
688 self.service_types = service_types_tv
689 if config.usage.multibouquet.value:
690 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
692 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
694 self.service_types = service_types_radio
695 if config.usage.multibouquet.value:
696 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
698 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
699 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
703 self.servicePath = self.servicePathTV
704 self.recallBouquetMode()
705 title = self.instance.getTitle()
706 pos = title.find(" (")
712 def setRadioMode(self):
713 self.mode = MODE_RADIO
714 self.servicePath = self.servicePathRadio
715 self.recallBouquetMode()
716 title = self.instance.getTitle()
717 pos = title.find(" (")
723 def setRoot(self, root, justSet=False):
724 path = root.getPath()
725 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
726 pos = path.find('FROM BOUQUET')
727 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
728 if not inBouquetRootList and isBouquet:
729 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
730 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
732 self.servicelist.setMode(ServiceList.MODE_NORMAL)
733 self.servicelist.setRoot(root, justSet)
734 self.buildTitleString()
736 def removeModeStr(self, str):
737 if self.mode == MODE_TV:
738 pos = str.find(' (TV)')
740 pos = str.find(' (Radio)')
745 def getServiceName(self, ref):
746 str = self.removeModeStr(ServiceReference(ref).getServiceName())
748 pathstr = ref.getPath()
749 if pathstr.find('FROM PROVIDERS') != -1:
751 if pathstr.find('FROM SATELLITES') != -1:
752 return _("Satellites")
753 if pathstr.find(') ORDER BY name') != -1:
757 def buildTitleString(self):
758 titleStr = self.instance.getTitle()
759 pos = titleStr.find(']')
761 pos = titleStr.find(')')
763 titleStr = titleStr[:pos+1]
764 Len = len(self.servicePath)
766 base_ref = self.servicePath[0]
768 end_ref = self.servicePath[Len-1]
771 nameStr = self.getServiceName(base_ref)
772 titleStr += ' ' + nameStr
773 if end_ref is not None:
778 nameStr = self.getServiceName(end_ref)
780 self.setTitle(titleStr)
783 self.servicelist.moveUp()
786 self.servicelist.moveDown()
789 del self.servicePath[:]
791 def enterPath(self, ref, justSet=False):
792 self.servicePath.append(ref)
793 self.setRoot(ref, justSet)
795 def pathUp(self, justSet=False):
796 prev = self.servicePath.pop()
797 length = len(self.servicePath)
799 current = self.servicePath[length-1]
800 self.setRoot(current, justSet)
802 self.setCurrentSelection(prev)
805 def isBasePathEqual(self, ref):
806 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
810 def isPrevPathEqual(self, ref):
811 length = len(self.servicePath)
812 if length > 1 and self.servicePath[length-2] == ref:
816 def preEnterPath(self, refstr):
819 def showAllServices(self):
820 if not self.pathChangeDisabled:
821 refstr = '%s ORDER BY name'%(self.service_types)
822 if not self.preEnterPath(refstr):
823 ref = eServiceReference(refstr)
824 currentRoot = self.getRoot()
825 if currentRoot is None or currentRoot != ref:
829 def showSatellites(self):
830 if not self.pathChangeDisabled:
831 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
832 if not self.preEnterPath(refstr):
833 ref = eServiceReference(refstr)
837 if self.isBasePathEqual(ref):
838 if self.isPrevPathEqual(ref):
840 prev = self.pathUp(justSet)
842 currentRoot = self.getRoot()
843 if currentRoot is None or currentRoot != ref:
846 self.enterPath(ref, True)
848 serviceHandler = eServiceCenter.getInstance()
849 servicelist = serviceHandler.list(ref)
850 if not servicelist is None:
852 service = servicelist.getNext()
853 if not service.valid(): #check if end of list
855 orbpos = service.getUnsignedData(4) >> 16
856 if service.getPath().find("FROM PROVIDER") != -1:
857 service_type = _("Providers")
858 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
859 service_type = _("New")
861 service_type = _("Services")
863 # why we need this cast?
864 service_name = str(nimmanager.getSatDescription(orbpos))
866 if orbpos == 0xFFFF: #Cable
867 service_name = _("Cable")
868 elif orbpos == 0xEEEE: #Terrestrial
869 service_name = _("Terrestrial")
871 if orbpos > 1800: # west
872 orbpos = 3600 - orbpos
876 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
877 service.setName("%s - %s" % (service_name, service_type))
878 self.servicelist.addService(service)
879 self.servicelist.finishFill()
881 self.setCurrentSelection(prev)
883 def showProviders(self):
884 if not self.pathChangeDisabled:
885 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
886 if not self.preEnterPath(refstr):
887 ref = eServiceReference(refstr)
888 if self.isBasePathEqual(ref):
891 currentRoot = self.getRoot()
892 if currentRoot is None or currentRoot != ref:
896 def changeBouquet(self, direction):
897 if not self.pathChangeDisabled:
898 if len(self.servicePath) > 1:
899 #when enter satellite root list we must do some magic stuff..
900 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
901 if self.isBasePathEqual(ref):
902 self.showSatellites()
909 ref = self.getCurrentSelection()
913 if len(self.servicePath) > 0 and self.servicePath[0] == self.bouquet_root:
918 return self.servicelist.atBegin()
921 return self.servicelist.atEnd()
923 def nextBouquet(self):
924 self.changeBouquet(+1)
926 def prevBouquet(self):
927 self.changeBouquet(-1)
929 def showFavourites(self):
930 if not self.pathChangeDisabled:
931 if not self.preEnterPath(self.bouquet_rootstr):
932 if self.isBasePathEqual(self.bouquet_root):
935 currentRoot = self.getRoot()
936 if currentRoot is None or currentRoot != self.bouquet_root:
938 self.enterPath(self.bouquet_root)
940 def keyNumberGlobal(self, number):
941 unichar = self.numericalTextInput.getKey(number)
942 charstr = unichar.encode("utf-8")
943 if len(charstr) == 1:
944 self.servicelist.moveToChar(charstr[0])
947 return self.servicelist.getRoot()
949 def getCurrentSelection(self):
950 return self.servicelist.getCurrent()
952 def setCurrentSelection(self, service):
953 servicepath = service.getPath()
954 pos = servicepath.find(" FROM BOUQUET")
956 if self.mode == MODE_TV:
957 servicepath = '(type == 1)' + servicepath[pos:]
959 servicepath = '(type == 2)' + servicepath[pos:]
960 service.setPath(servicepath)
961 self.servicelist.setCurrent(service)
963 def getBouquetList(self):
965 serviceHandler = eServiceCenter.getInstance()
966 if config.usage.multibouquet.value:
967 list = serviceHandler.list(self.bouquet_root)
973 if s.flags & eServiceReference.isDirectory:
974 info = serviceHandler.info(s)
976 bouquets.append((info.getName(s), s))
979 info = serviceHandler.info(self.bouquet_root)
981 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
985 def keyNumber0(self, num):
986 if len(self.servicePath) > 1:
989 self.keyNumberGlobal(num)
992 if len(self.servicePath) > 1:
993 if self.isBasePathEqual(self.bouquet_root):
994 self.showFavourites()
996 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
997 if self.isBasePathEqual(ref):
998 self.showSatellites()
1000 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
1001 if self.isBasePathEqual(ref):
1002 self.showProviders()
1004 self.showAllServices()
1006 def nextMarker(self):
1007 self.servicelist.moveToNextMarker()
1009 def prevMarker(self):
1010 self.servicelist.moveToPrevMarker()
1014 #config for lastservice
1015 config.tv = ConfigSubsection()
1016 config.tv.lastservice = ConfigText()
1017 config.tv.lastroot = ConfigText()
1018 config.radio = ConfigSubsection()
1019 config.radio.lastservice = ConfigText()
1020 config.radio.lastroot = ConfigText()
1021 config.servicelist = ConfigSubsection()
1022 config.servicelist.lastmode = ConfigText(default = "tv")
1024 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1025 def __init__(self, session):
1026 ChannelSelectionBase.__init__(self,session)
1027 ChannelSelectionEdit.__init__(self)
1028 ChannelSelectionEPG.__init__(self)
1030 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1032 "cancel": self.cancel,
1033 "ok": self.channelSelected,
1034 "keyRadio": self.setModeRadio,
1035 "keyTV": self.setModeTv,
1038 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1040 iPlayableService.evStart: self.__evServiceStart,
1041 iPlayableService.evEnd: self.__evServiceEnd
1044 self.lastChannelRootTimer = eTimer()
1045 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1046 self.lastChannelRootTimer.start(100,True)
1048 self.history_tv = [ ]
1049 self.history_radio = [ ]
1050 self.history = self.history_tv
1051 self.history_pos = 0
1053 self.lastservice = config.tv.lastservice
1054 self.lastroot = config.tv.lastroot
1055 self.revertMode = None
1056 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1057 self.new_service_played = False
1059 def multibouquet_config_changed(self, val):
1060 self.recallBouquetMode()
1062 def __evServiceStart(self):
1063 service = self.session.nav.getCurrentService()
1065 info = service.info()
1067 refstr = info.getInfoString(iServiceInformation.sServiceref)
1068 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1070 def __evServiceEnd(self):
1071 self.servicelist.setPlayableIgnoreService(eServiceReference())
1075 lastservice=eServiceReference(self.lastservice.value)
1076 if lastservice.valid():
1077 self.setCurrentSelection(lastservice)
1079 def setModeTv(self):
1080 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1081 self.revertMode = MODE_RADIO
1082 self.history = self.history_tv
1083 self.lastservice = config.tv.lastservice
1084 self.lastroot = config.tv.lastroot
1085 config.servicelist.lastmode.value = "tv"
1089 def setModeRadio(self):
1090 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1091 self.revertMode = MODE_TV
1092 if config.usage.e1like_radio_mode.value:
1093 self.history = self.history_radio
1094 self.lastservice = config.radio.lastservice
1095 self.lastroot = config.radio.lastroot
1096 config.servicelist.lastmode.value = "radio"
1100 def __onCreate(self):
1101 if config.usage.e1like_radio_mode.value:
1102 if config.servicelist.lastmode.value == "tv":
1108 lastservice=eServiceReference(self.lastservice.value)
1109 if lastservice.valid():
1112 def channelSelected(self):
1113 ref = self.getCurrentSelection()
1115 self.toggleMoveMarked()
1116 elif (ref.flags & 7) == 7:
1118 elif self.bouquet_mark_edit != OFF:
1119 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1121 elif not (ref.flags & eServiceReference.isMarker): # no marker
1122 root = self.getRoot()
1123 if not root or not (root.flags & eServiceReference.isGroup):
1127 #called from infoBar and channelSelected
1129 self.revertMode=None
1130 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1131 nref = self.getCurrentSelection()
1132 if ref is None or ref != nref:
1133 self.new_service_played = True
1134 self.session.nav.playService(nref)
1136 self.saveChannel(nref)
1137 config.servicelist.lastmode.save()
1138 self.addToHistory(nref)
1140 def newServicePlayed(self):
1141 ret = self.new_service_played
1142 self.new_service_played = False
1145 def addToHistory(self, ref):
1146 if self.servicePath is not None:
1147 tmp=self.servicePath[:]
1150 del self.history[self.history_pos+1:]
1153 self.history.append(tmp)
1154 hlen = len(self.history)
1155 if hlen > HISTORYSIZE:
1158 self.history_pos = hlen-1
1160 def historyBack(self):
1161 hlen = len(self.history)
1162 if hlen > 1 and self.history_pos > 0:
1163 self.history_pos -= 1
1164 self.setHistoryPath()
1166 def historyNext(self):
1167 hlen = len(self.history)
1168 if hlen > 1 and self.history_pos < (hlen-1):
1169 self.history_pos += 1
1170 self.setHistoryPath()
1172 def setHistoryPath(self):
1173 path = self.history[self.history_pos][:]
1175 del self.servicePath[:]
1176 self.servicePath += path
1180 cur_root = self.getRoot()
1181 if cur_root and cur_root != root:
1183 self.session.nav.playService(ref)
1184 self.setCurrentSelection(ref)
1185 self.saveChannel(ref)
1189 for i in self.servicePath:
1190 path += i.toString()
1192 if len(path) and path != self.lastroot.value:
1193 self.lastroot.value = path
1194 self.lastroot.save()
1196 def restoreRoot(self):
1198 re = compile('.+?;')
1199 tmp = re.findall(self.lastroot.value)
1202 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1205 path = self.servicePath.pop()
1206 self.enterPath(path)
1208 self.showFavourites()
1211 def preEnterPath(self, refstr):
1212 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1213 pathstr = self.lastroot.value
1214 if pathstr is not None and pathstr.find(refstr) == 0:
1216 lastservice=eServiceReference(self.lastservice.value)
1217 if lastservice.valid():
1218 self.setCurrentSelection(lastservice)
1222 def saveChannel(self, ref):
1224 refstr = ref.toString()
1227 if refstr != self.lastservice.value:
1228 self.lastservice.value = refstr
1229 self.lastservice.save()
1231 def setCurrentServicePath(self, path):
1232 hlen = len(self.history)
1234 self.history[self.history_pos] = path
1236 self.history.append(path)
1237 self.setHistoryPath()
1239 def getCurrentServicePath(self):
1240 hlen = len(self.history)
1242 return self.history[self.history_pos]
1245 def recallPrevService(self):
1246 hlen = len(self.history)
1248 if self.history_pos == hlen-1:
1249 tmp = self.history[self.history_pos]
1250 self.history[self.history_pos] = self.history[self.history_pos-1]
1251 self.history[self.history_pos-1] = tmp
1253 tmp = self.history[self.history_pos+1]
1254 self.history[self.history_pos+1] = self.history[self.history_pos]
1255 self.history[self.history_pos] = tmp
1256 self.setHistoryPath()
1259 if self.revertMode is None:
1261 lastservice=eServiceReference(self.lastservice.value)
1262 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1263 self.setCurrentSelection(lastservice)
1264 elif self.revertMode == MODE_TV:
1266 elif self.revertMode == MODE_RADIO:
1268 self.revertMode = None
1271 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1273 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1274 def __init__(self, session):
1275 Screen.__init__(self, session)
1276 InfoBarEvent.__init__(self)
1277 InfoBarServiceName.__init__(self)
1278 self["CurrentTime"] = Clock()
1279 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1280 self["BlinkingPoint"] = Pixmap()
1281 self["BlinkingPoint"].hide()
1283 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1284 ALLOW_SUSPEND = True
1286 def __init__(self, session, infobar):
1287 ChannelSelectionBase.__init__(self, session)
1288 ChannelSelectionEdit.__init__(self)
1289 ChannelSelectionEPG.__init__(self)
1290 self.infobar = infobar
1291 config.radio = ConfigSubsection();
1292 config.radio.lastservice = ConfigText()
1293 config.radio.lastroot = ConfigText()
1294 self.onLayoutFinish.append(self.onCreate)
1296 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1298 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1300 "keyTV": self.closeRadio,
1301 "keyRadio": self.closeRadio,
1302 "cancel": self.closeRadio,
1303 "ok": self.channelSelected,
1306 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1308 iPlayableService.evStart: self.__evServiceStart,
1309 iPlayableService.evEnd: self.__evServiceEnd
1312 ########## RDS Radiotext / Rass Support BEGIN
1313 self.infobar = infobar # reference to real infobar (the one and only)
1314 self["RdsDecoder"] = self.info["RdsDecoder"]
1315 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1317 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1319 self["RdsActions"].setEnabled(False)
1320 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1322 def startRassInteractive(self):
1324 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1326 def RassInteractiveClosed(self):
1328 self.infobar.rass_interactive = None
1329 self.infobar.RassSlidePicChanged()
1331 def RassInteractivePossibilityChanged(self, state):
1332 self["RdsActions"].setEnabled(state)
1333 ########## RDS Radiotext / Rass Support END
1335 def closeRadio(self):
1336 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1338 #set previous tv service
1339 lastservice=eServiceReference(config.tv.lastservice.value)
1340 self.session.nav.playService(lastservice)
1343 def __evServiceStart(self):
1344 service = self.session.nav.getCurrentService()
1346 info = service.info()
1348 refstr = info.getInfoString(iServiceInformation.sServiceref)
1349 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1351 def __evServiceEnd(self):
1352 self.servicelist.setPlayableIgnoreService(eServiceReference())
1356 for i in self.servicePathRadio:
1357 path += i.toString()
1359 if len(path) and path != config.radio.lastroot.value:
1360 config.radio.lastroot.value = path
1361 config.radio.lastroot.save()
1363 def restoreRoot(self):
1365 re = compile('.+?;')
1366 tmp = re.findall(config.radio.lastroot.value)
1369 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1372 path = self.servicePathRadio.pop()
1373 self.enterPath(path)
1375 self.showFavourites()
1378 def preEnterPath(self, refstr):
1379 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1380 pathstr = config.radio.lastroot.value
1381 if pathstr is not None and pathstr.find(refstr) == 0:
1383 lastservice=eServiceReference(config.radio.lastservice.value)
1384 if lastservice.valid():
1385 self.setCurrentSelection(lastservice)
1392 lastservice=eServiceReference(config.radio.lastservice.value)
1393 if lastservice.valid():
1394 self.servicelist.setCurrent(lastservice)
1395 self.session.nav.playService(lastservice)
1398 def channelSelected(self): # just return selected service
1399 ref = self.getCurrentSelection()
1401 self.toggleMoveMarked()
1402 elif (ref.flags & 7) == 7:
1404 elif self.bouquet_mark_edit != OFF:
1405 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1407 elif not (ref.flags & eServiceReference.isMarker): # no marker
1408 cur_root = self.getRoot()
1409 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1410 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1411 if playingref is None or playingref != ref:
1412 self.session.nav.playService(ref)
1413 config.radio.lastservice.value = ref.toString()
1414 config.radio.lastservice.save()
1417 class SimpleChannelSelection(ChannelSelectionBase):
1418 def __init__(self, session, title):
1419 ChannelSelectionBase.__init__(self, session)
1421 self.onShown.append(self.__onExecCallback)
1423 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1425 "cancel": self.close,
1426 "ok": self.channelSelected,
1427 "keyRadio": self.setModeRadio,
1428 "keyTV": self.setModeTv,
1431 def __onExecCallback(self):
1432 self.setTitle(self.title)
1435 def channelSelected(self): # just return selected service
1436 ref = self.getCurrentSelection()
1437 if (ref.flags & 7) == 7:
1439 elif not (ref.flags & eServiceReference.isMarker):
1440 ref = self.getCurrentSelection()
1443 def setModeTv(self):
1445 self.showFavourites()
1447 def setModeRadio(self):
1449 self.showFavourites()