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 PixmapConditional
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_name = _("Providers")
858 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
859 service_name = _("New")
861 service_name = _("Services")
863 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
864 service.setName(service_name) # why we need this cast?
866 if orbpos == 0xFFFF: #Cable
867 n = ("%s (%s)") % (service_name, _("Cable"))
868 elif orbpos == 0xEEEE: #Terrestrial
869 n = ("%s (%s)") % (service_name, _("Terrestrial"))
871 if orbpos > 1800: # west
872 orbpos = 3600 - orbpos
876 n = ("%s (%d.%d" + h + ")") % (service_name, orbpos / 10, orbpos % 10)
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 return self.isBasePathEqual(self.bouquet_root)
916 return self.servicelist.atBegin()
919 return self.servicelist.atEnd()
921 def nextBouquet(self):
922 self.changeBouquet(+1)
924 def prevBouquet(self):
925 self.changeBouquet(-1)
927 def showFavourites(self):
928 if not self.pathChangeDisabled:
929 if not self.preEnterPath(self.bouquet_rootstr):
930 if self.isBasePathEqual(self.bouquet_root):
933 currentRoot = self.getRoot()
934 if currentRoot is None or currentRoot != self.bouquet_root:
936 self.enterPath(self.bouquet_root)
938 def keyNumberGlobal(self, number):
939 unichar = self.numericalTextInput.getKey(number)
940 charstr = unichar.encode("utf-8")
941 if len(charstr) == 1:
942 self.servicelist.moveToChar(charstr[0])
945 return self.servicelist.getRoot()
947 def getCurrentSelection(self):
948 return self.servicelist.getCurrent()
950 def setCurrentSelection(self, service):
951 servicepath = service.getPath()
952 pos = servicepath.find(" FROM BOUQUET")
954 if self.mode == MODE_TV:
955 servicepath = '(type == 1)' + servicepath[pos:]
957 servicepath = '(type == 2)' + servicepath[pos:]
958 service.setPath(servicepath)
959 self.servicelist.setCurrent(service)
961 def getBouquetList(self):
963 serviceHandler = eServiceCenter.getInstance()
964 if config.usage.multibouquet.value:
965 list = serviceHandler.list(self.bouquet_root)
971 if s.flags & eServiceReference.isDirectory:
972 info = serviceHandler.info(s)
974 bouquets.append((info.getName(s), s))
977 info = serviceHandler.info(self.bouquet_root)
979 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
983 def keyNumber0(self, num):
984 if len(self.servicePath) > 1:
987 self.keyNumberGlobal(num)
990 if len(self.servicePath) > 1:
991 if self.isBasePathEqual(self.bouquet_root):
992 self.showFavourites()
994 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
995 if self.isBasePathEqual(ref):
996 self.showSatellites()
998 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
999 if self.isBasePathEqual(ref):
1000 self.showProviders()
1002 self.showAllServices()
1004 def nextMarker(self):
1005 self.servicelist.moveToNextMarker()
1007 def prevMarker(self):
1008 self.servicelist.moveToPrevMarker()
1012 #config for lastservice
1013 config.tv = ConfigSubsection()
1014 config.tv.lastservice = ConfigText()
1015 config.tv.lastroot = ConfigText()
1016 config.radio = ConfigSubsection()
1017 config.radio.lastservice = ConfigText()
1018 config.radio.lastroot = ConfigText()
1019 config.servicelist = ConfigSubsection()
1020 config.servicelist.lastmode = ConfigText(default = "tv")
1022 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1023 def __init__(self, session):
1024 ChannelSelectionBase.__init__(self,session)
1025 ChannelSelectionEdit.__init__(self)
1026 ChannelSelectionEPG.__init__(self)
1028 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1030 "cancel": self.cancel,
1031 "ok": self.channelSelected,
1032 "keyRadio": self.setModeRadio,
1033 "keyTV": self.setModeTv,
1036 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1038 iPlayableService.evStart: self.__evServiceStart,
1039 iPlayableService.evEnd: self.__evServiceEnd
1042 self.lastChannelRootTimer = eTimer()
1043 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1044 self.lastChannelRootTimer.start(100,True)
1046 self.history_tv = [ ]
1047 self.history_radio = [ ]
1048 self.history = self.history_tv
1049 self.history_pos = 0
1051 self.lastservice = config.tv.lastservice
1052 self.lastroot = config.tv.lastroot
1053 self.revertMode = None
1054 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1056 def multibouquet_config_changed(self, val):
1057 self.recallBouquetMode()
1059 def __evServiceStart(self):
1060 service = self.session.nav.getCurrentService()
1062 info = service.info()
1064 refstr = info.getInfoString(iServiceInformation.sServiceref)
1065 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1067 def __evServiceEnd(self):
1068 self.servicelist.setPlayableIgnoreService(eServiceReference())
1072 lastservice=eServiceReference(self.lastservice.value)
1073 if lastservice.valid():
1074 self.setCurrentSelection(lastservice)
1076 def setModeTv(self):
1077 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1078 self.revertMode = MODE_RADIO
1079 self.history = self.history_tv
1080 self.lastservice = config.tv.lastservice
1081 self.lastroot = config.tv.lastroot
1082 config.servicelist.lastmode.value = "tv"
1086 def setModeRadio(self):
1087 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1088 self.revertMode = MODE_TV
1089 if config.usage.e1like_radio_mode.value:
1090 self.history = self.history_radio
1091 self.lastservice = config.radio.lastservice
1092 self.lastroot = config.radio.lastroot
1093 config.servicelist.lastmode.value = "radio"
1097 def __onCreate(self):
1098 if config.usage.e1like_radio_mode.value:
1099 if config.servicelist.lastmode.value == "tv":
1105 lastservice=eServiceReference(self.lastservice.value)
1106 if lastservice.valid():
1109 def channelSelected(self):
1110 ref = self.getCurrentSelection()
1112 self.toggleMoveMarked()
1113 elif (ref.flags & 7) == 7:
1115 elif self.bouquet_mark_edit != OFF:
1116 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1118 elif not (ref.flags & eServiceReference.isMarker): # no marker
1119 root = self.getRoot()
1120 if not root or not (root.flags & eServiceReference.isGroup):
1124 #called from infoBar and channelSelected
1126 self.revertMode=None
1127 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1128 nref = self.getCurrentSelection()
1129 if ref is None or ref != nref:
1130 self.session.nav.playService(nref)
1132 self.saveChannel(nref)
1133 config.servicelist.lastmode.save()
1134 self.addToHistory(nref)
1136 def addToHistory(self, ref):
1137 if self.servicePath is not None:
1138 tmp=self.servicePath[:]
1141 del self.history[self.history_pos+1:]
1144 self.history.append(tmp)
1145 hlen = len(self.history)
1146 if hlen > HISTORYSIZE:
1149 self.history_pos = hlen-1
1151 def historyBack(self):
1152 hlen = len(self.history)
1153 if hlen > 1 and self.history_pos > 0:
1154 self.history_pos -= 1
1155 self.setHistoryPath()
1157 def historyNext(self):
1158 hlen = len(self.history)
1159 if hlen > 1 and self.history_pos < (hlen-1):
1160 self.history_pos += 1
1161 self.setHistoryPath()
1163 def setHistoryPath(self):
1164 path = self.history[self.history_pos][:]
1166 del self.servicePath[:]
1167 self.servicePath += path
1171 cur_root = self.getRoot()
1172 if cur_root and cur_root != root:
1174 self.session.nav.playService(ref)
1175 self.setCurrentSelection(ref)
1176 self.saveChannel(ref)
1180 for i in self.servicePath:
1181 path += i.toString()
1183 if len(path) and path != self.lastroot.value:
1184 self.lastroot.value = path
1185 self.lastroot.save()
1187 def restoreRoot(self):
1189 re = compile('.+?;')
1190 tmp = re.findall(self.lastroot.value)
1193 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1196 path = self.servicePath.pop()
1197 self.enterPath(path)
1199 self.showFavourites()
1202 def preEnterPath(self, refstr):
1203 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1204 pathstr = self.lastroot.value
1205 if pathstr is not None and pathstr.find(refstr) == 0:
1207 lastservice=eServiceReference(self.lastservice.value)
1208 if lastservice.valid():
1209 self.setCurrentSelection(lastservice)
1213 def saveChannel(self, ref):
1215 refstr = ref.toString()
1218 if refstr != self.lastservice.value:
1219 self.lastservice.value = refstr
1220 self.lastservice.save()
1222 def setCurrentServicePath(self, path):
1223 hlen = len(self.history)
1225 self.history[self.history_pos] = path
1227 self.history.append(path)
1228 self.setHistoryPath()
1230 def getCurrentServicePath(self):
1231 hlen = len(self.history)
1233 return self.history[self.history_pos]
1236 def recallPrevService(self):
1237 hlen = len(self.history)
1239 if self.history_pos == hlen-1:
1240 tmp = self.history[self.history_pos]
1241 self.history[self.history_pos] = self.history[self.history_pos-1]
1242 self.history[self.history_pos-1] = tmp
1244 tmp = self.history[self.history_pos+1]
1245 self.history[self.history_pos+1] = self.history[self.history_pos]
1246 self.history[self.history_pos] = tmp
1247 self.setHistoryPath()
1250 if self.revertMode is None:
1252 lastservice=eServiceReference(self.lastservice.value)
1253 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1254 self.setCurrentSelection(lastservice)
1255 elif self.revertMode == MODE_TV:
1257 elif self.revertMode == MODE_RADIO:
1259 self.revertMode = None
1262 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1264 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1265 def __init__(self, session):
1266 Screen.__init__(self, session)
1267 InfoBarEvent.__init__(self)
1268 InfoBarServiceName.__init__(self)
1269 self["CurrentTime"] = Clock()
1270 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1271 self["BlinkingPoint"] = PixmapConditional()
1272 self["BlinkingPoint"].hide()
1274 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1275 ALLOW_SUSPEND = True
1277 def __init__(self, session, infobar):
1278 ChannelSelectionBase.__init__(self, session)
1279 ChannelSelectionEdit.__init__(self)
1280 ChannelSelectionEPG.__init__(self)
1281 self.infobar = infobar
1282 config.radio = ConfigSubsection();
1283 config.radio.lastservice = ConfigText()
1284 config.radio.lastroot = ConfigText()
1285 self.onLayoutFinish.append(self.onCreate)
1287 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1289 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1291 "keyTV": self.closeRadio,
1292 "keyRadio": self.closeRadio,
1293 "cancel": self.closeRadio,
1294 "ok": self.channelSelected,
1297 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1299 iPlayableService.evStart: self.__evServiceStart,
1300 iPlayableService.evEnd: self.__evServiceEnd
1303 ########## RDS Radiotext / Rass Support BEGIN
1304 self.infobar = infobar # reference to real infobar (the one and only)
1305 self["RdsDecoder"] = self.info["RdsDecoder"]
1306 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1308 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1310 self["RdsActions"].setEnabled(False)
1311 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1313 def startRassInteractive(self):
1315 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1317 def RassInteractiveClosed(self):
1319 self.infobar.rass_interactive = None
1320 self.infobar.RassSlidePicChanged()
1322 def RassInteractivePossibilityChanged(self, state):
1323 self["RdsActions"].setEnabled(state)
1324 ########## RDS Radiotext / Rass Support END
1326 def closeRadio(self):
1327 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1329 #set previous tv service
1330 lastservice=eServiceReference(config.tv.lastservice.value)
1331 self.session.nav.playService(lastservice)
1334 def __evServiceStart(self):
1335 service = self.session.nav.getCurrentService()
1337 info = service.info()
1339 refstr = info.getInfoString(iServiceInformation.sServiceref)
1340 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1342 def __evServiceEnd(self):
1343 self.servicelist.setPlayableIgnoreService(eServiceReference())
1347 for i in self.servicePathRadio:
1348 path += i.toString()
1350 if len(path) and path != config.radio.lastroot.value:
1351 config.radio.lastroot.value = path
1352 config.radio.lastroot.save()
1354 def restoreRoot(self):
1356 re = compile('.+?;')
1357 tmp = re.findall(config.radio.lastroot.value)
1360 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1363 path = self.servicePathRadio.pop()
1364 self.enterPath(path)
1366 self.showFavourites()
1369 def preEnterPath(self, refstr):
1370 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1371 pathstr = config.radio.lastroot.value
1372 if pathstr is not None and pathstr.find(refstr) == 0:
1374 lastservice=eServiceReference(config.radio.lastservice.value)
1375 if lastservice.valid():
1376 self.setCurrentSelection(lastservice)
1383 lastservice=eServiceReference(config.radio.lastservice.value)
1384 if lastservice.valid():
1385 self.servicelist.setCurrent(lastservice)
1386 self.session.nav.playService(lastservice)
1389 def channelSelected(self): # just return selected service
1390 ref = self.getCurrentSelection()
1392 self.toggleMoveMarked()
1393 elif (ref.flags & 7) == 7:
1395 elif self.bouquet_mark_edit != OFF:
1396 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1398 elif not (ref.flags & eServiceReference.isMarker): # no marker
1399 cur_root = self.getRoot()
1400 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1401 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1402 if playingref is None or playingref != ref:
1403 self.session.nav.playService(ref)
1404 config.radio.lastservice.value = ref.toString()
1405 config.radio.lastservice.save()
1408 class SimpleChannelSelection(ChannelSelectionBase):
1409 def __init__(self, session, title):
1410 ChannelSelectionBase.__init__(self, session)
1412 self.onShown.append(self.__onExecCallback)
1414 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1416 "cancel": self.close,
1417 "ok": self.channelSelected,
1418 "keyRadio": self.setModeRadio,
1419 "keyTV": self.setModeTv,
1422 def __onExecCallback(self):
1423 self.setTitle(self.title)
1426 def channelSelected(self): # just return selected service
1427 ref = self.getCurrentSelection()
1428 if (ref.flags & 7) == 7:
1430 elif not (ref.flags & eServiceReference.isMarker):
1431 ref = self.getCurrentSelection()
1434 def setModeTv(self):
1436 self.showFavourites()
1438 def setModeRadio(self):
1440 self.showFavourites()