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.Input import Input
15 from Components.ParentalControl import parentalControl
16 from Components.Pixmap import Pixmap
17 from Screens.InputBox import InputBox, PinInput
18 from Screens.MessageBox import MessageBox
19 from Screens.ServiceInfo import ServiceInfo
20 from Screens.RdsDisplay import RassInteractive
21 from ServiceReference import ServiceReference
22 from Tools.BoundFunction import boundFunction
23 from re import compile
26 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
28 class BouquetSelector(Screen):
29 def __init__(self, session, bouquets, selectedFunc, enableWrapAround=False):
30 Screen.__init__(self, session)
32 self.selectedFunc=selectedFunc
34 self["actions"] = ActionMap(["OkCancelActions"],
36 "ok": self.okbuttonClick,
37 "cancel": self.cancelClick
39 entrys = [ (x[0], x[1]) for x in bouquets ]
40 self["menu"] = MenuList(entrys, enableWrapAround)
43 cur = self["menu"].getCurrent()
46 def okbuttonClick(self):
47 self.selectedFunc(self.getCurrent())
55 def cancelClick(self):
58 # csel.bouquet_mark_edit values
63 def apend_when_current_valid(current, menu, args):
64 if current and current.valid():
67 class ChannelContextMenu(Screen):
68 def __init__(self, session, csel):
69 Screen.__init__(self, session)
73 self["actions"] = ActionMap(["OkCancelActions"],
75 "ok": self.okbuttonClick,
76 "cancel": self.cancelClick
80 current = csel.getCurrentSelection()
81 current_root = csel.getRoot()
82 current_sel_path = current.getPath()
83 current_sel_flags = current.flags
84 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
85 inBouquet = csel.getMutableList() is not None
86 haveBouquets = config.usage.multibouquet.value
88 if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
89 apend_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations))
90 if csel.bouquet_mark_edit == OFF and not csel.movemode:
91 if not inBouquetRootList:
92 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
94 if config.ParentalControl.configured.value:
95 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
96 apend_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
98 apend_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
100 apend_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected))
102 apend_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected))
105 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
106 apend_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList))
107 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
108 apend_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags))
110 apend_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService))
111 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
112 apend_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag))
114 menu.append((_("add bouquet"), self.showBouquetInputBox))
115 apend_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet))
117 if inBouquet: # current list is editable?
118 if csel.bouquet_mark_edit == OFF:
119 if not csel.movemode:
120 apend_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode))
121 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
122 menu.append((_("add marker"), self.showMarkerInputBox))
124 apend_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart))
126 apend_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart))
127 if current_sel_flags & eServiceReference.isGroup:
128 apend_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices))
129 apend_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices))
130 apend_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices))
131 elif not current_sel_flags & eServiceReference.isMarker:
132 apend_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices))
134 apend_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode))
136 if csel.bouquet_mark_edit == EDIT_BOUQUET:
138 apend_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd))
139 apend_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort))
141 apend_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd))
142 apend_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort))
144 apend_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd))
145 apend_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort))
147 menu.append((_("back"), self.cancelClick))
148 self["menu"] = MenuList(menu)
150 def okbuttonClick(self):
151 self["menu"].getCurrent()[1]()
153 def cancelClick(self):
156 def showServiceInformations(self):
157 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
159 def showBouquetInputBox(self):
160 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
162 def bouquetInputCallback(self, bouquet):
163 if bouquet is not None:
164 self.csel.addBouquet(bouquet, None)
167 def addParentalProtection(self, service):
168 parentalControl.protectService(service.toCompareString())
171 def removeParentalProtection(self, service):
172 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"))
174 def pinEntered(self, service, result):
176 parentalControl.unProtectService(service)
179 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
181 def addServiceToBouquetSelected(self):
182 bouquets = self.csel.getBouquetList()
187 if cnt > 1: # show bouquet list
188 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
189 elif cnt == 1: # add to only one existing bouquet
190 self.addCurrentServiceToBouquet(bouquets[0][1])
192 def bouquetSelClosed(self, recursive):
197 def copyCurrentToBouquetList(self):
198 self.csel.copyCurrentToBouquetList()
201 def removeBouquet(self):
202 self.csel.removeBouquet()
205 def showMarkerInputBox(self):
206 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, type=Input.TEXT)
208 def markerInputCallback(self, marker):
209 if marker is not None:
210 self.csel.addMarker(marker)
213 def addCurrentServiceToBouquet(self, dest):
214 self.csel.addServiceToBouquet(dest)
215 if self.bsel is not None:
216 self.bsel.close(True)
218 self.close(True) # close bouquet selection
220 def removeCurrentService(self):
221 self.csel.removeCurrentService()
224 def toggleMoveMode(self):
225 self.csel.toggleMoveMode()
228 def bouquetMarkStart(self):
229 self.csel.startMarkedEdit(EDIT_BOUQUET)
232 def bouquetMarkEnd(self):
233 self.csel.endMarkedEdit(abort=False)
236 def bouquetMarkAbort(self):
237 self.csel.endMarkedEdit(abort=True)
240 def removeNewFoundFlag(self):
241 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
244 def removeAllNewFoundFlags(self):
245 curpath = self.csel.getCurrentSelection().getPath()
246 idx = curpath.find("satellitePosition == ")
248 tmp = curpath[idx+21:]
251 satpos = int(tmp[:idx])
252 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
255 def editAlternativeServices(self):
256 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
259 def showAlternativeServices(self):
260 self.csel.enterPath(self.csel.getCurrentSelection())
263 def removeAlternativeServices(self):
264 self.csel.removeAlternativeServices()
267 def addAlternativeServices(self):
268 self.csel.addAlternativeServices()
269 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
272 class ChannelSelectionEPG:
274 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
276 "showEPGList": self.showEPGList,
279 def showEPGList(self):
280 ref=self.getCurrentSelection()
281 ptr=eEPGCache.getInstance()
282 if ptr.startTimeQuery(ref) != -1:
283 self.session.open(EPGSelection, ref)
285 print 'no epg for service', ref.toString()
287 class ChannelSelectionEdit:
289 self.entry_marked = False
290 self.movemode = False
291 self.bouquet_mark_edit = OFF
292 self.mutableList = None
294 self.saved_title = None
295 self.saved_root = None
297 class ChannelSelectionEditActionMap(ActionMap):
298 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
299 ActionMap.__init__(self, contexts, actions, prio)
302 def action(self, contexts, action):
303 if action == "cancel":
304 self.csel.handleEditCancel()
305 return 0 # fall-trough
307 return 0 # fall-trough
309 return ActionMap.action(self, contexts, action)
311 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
313 "contextMenu": self.doContext,
316 def getMutableList(self, root=eServiceReference()):
317 if not self.mutableList is None:
318 return self.mutableList
319 serviceHandler = eServiceCenter.getInstance()
322 list = root and serviceHandler.list(root)
324 return list.startEdit()
327 def buildBouquetID(self, str):
331 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
337 def addMarker(self, name):
338 current = self.servicelist.getCurrent()
339 mutableList = self.getMutableList()
342 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
343 ref = eServiceReference(str)
344 if current and current.valid():
345 if not mutableList.addService(ref, current):
346 self.servicelist.addService(ref, True)
347 mutableList.flushChanges()
349 elif not mutableList.addService(ref):
350 self.servicelist.addService(ref, True)
351 mutableList.flushChanges()
355 def addAlternativeServices(self):
356 cur_service = ServiceReference(self.getCurrentSelection())
357 root = self.getRoot()
358 cur_root = root and ServiceReference(root)
359 mutableBouquet = cur_root.list().startEdit()
361 name = cur_service.getServiceName()
363 if self.mode == MODE_TV:
364 str = '1:134:1:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
366 str = '1:134:2:0:0:0:0:0:0:0:FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
367 new_ref = ServiceReference(str)
368 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
369 mutableBouquet.removeService(cur_service.ref)
370 mutableBouquet.flushChanges()
371 eDVBDB.getInstance().reloadBouquets()
372 mutableAlternatives = new_ref.list().startEdit()
373 if mutableAlternatives:
374 mutableAlternatives.setListName(name)
375 if mutableAlternatives.addService(cur_service.ref):
376 print "add", cur_service.toString(), "to new alternatives failed"
377 mutableAlternatives.flushChanges()
378 self.servicelist.addService(new_ref.ref, True)
379 self.servicelist.removeCurrent()
380 self.servicelist.moveUp()
382 print "get mutable list for new created alternatives failed"
384 print "add", str, "to", cur_root.getServiceName(), "failed"
386 print "bouquetlist is not editable"
388 def addBouquet(self, bName, services):
389 serviceHandler = eServiceCenter.getInstance()
390 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
391 if mutableBouquetList:
392 if self.mode == MODE_TV:
394 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
397 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
398 new_bouquet_ref = eServiceReference(str)
399 if not mutableBouquetList.addService(new_bouquet_ref):
400 mutableBouquetList.flushChanges()
401 eDVBDB.getInstance().reloadBouquets()
402 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
404 mutableBouquet.setListName(bName)
405 if services is not None:
406 for service in services:
407 if mutableBouquet.addService(service):
408 print "add", service.toString(), "to new bouquet failed"
409 mutableBouquet.flushChanges()
411 print "get mutable list for new created bouquet failed"
412 # do some voodoo to check if current_root is equal to bouquet_root
413 cur_root = self.getRoot();
414 str1 = cur_root and cur_root.toString()
415 pos1 = str1 and str1.find("FROM BOUQUET") or -1
416 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
417 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
418 self.servicelist.addService(new_bouquet_ref)
420 print "add", str, "to bouquets failed"
422 print "bouquetlist is not editable"
424 def copyCurrentToBouquetList(self):
425 provider = ServiceReference(self.getCurrentSelection())
426 providerName = provider.getServiceName()
427 serviceHandler = eServiceCenter.getInstance()
428 services = serviceHandler.list(provider.ref)
429 self.addBouquet(providerName, services and services.getContent('R', True))
431 def removeAlternativeServices(self):
432 cur_service = ServiceReference(self.getCurrentSelection())
433 root = self.getRoot()
434 cur_root = root and ServiceReference(root)
435 list = cur_service.list()
436 first_in_alternative = list and list.getNext()
437 if first_in_alternative:
438 edit_root = cur_root and cur_root.list().startEdit()
440 if not edit_root.addService(first_in_alternative, cur_service.ref):
441 self.servicelist.addService(first_in_alternative, True)
443 print "couldn't add first alternative service to current root"
445 print "couldn't edit current root!!"
447 print "remove empty alternative list !!"
449 self.servicelist.moveUp()
451 def removeBouquet(self):
452 refstr = self.getCurrentSelection().toString()
453 print "removeBouquet", refstr
454 self.bouquetNumOffsetCache = { }
455 pos = refstr.find('FROM BOUQUET "')
458 refstr = refstr[pos+14:]
459 pos = refstr.find('"')
461 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
462 self.removeCurrentService()
464 if filename is not None:
467 print "error during remove of", filename
469 # multiple marked entry stuff ( edit mode, later multiepg selection )
470 def startMarkedEdit(self, type):
471 self.savedPath = self.servicePath[:]
472 if type == EDIT_ALTERNATIVES:
473 self.enterPath(self.getCurrentSelection())
474 self.mutableList = self.getMutableList()
475 # add all services from the current list to internal marked set in listboxservicecontent
476 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
477 self.saved_title = self.instance.getTitle()
478 pos = self.saved_title.find(')')
479 new_title = self.saved_title[:pos+1]
480 if type == EDIT_ALTERNATIVES:
481 self.bouquet_mark_edit = EDIT_ALTERNATIVES
482 new_title += ' ' + _("[alternative edit]")
484 self.bouquet_mark_edit = EDIT_BOUQUET
485 if config.usage.multibouquet.value:
486 new_title += ' ' + _("[bouquet edit]")
488 new_title += ' ' + _("[favourite edit]")
489 self.setTitle(new_title)
490 self.__marked = self.servicelist.getRootServices()
491 for x in self.__marked:
492 self.servicelist.addMarked(eServiceReference(x))
493 self.showAllServices()
495 def endMarkedEdit(self, abort):
496 if not abort and self.mutableList is not None:
497 self.bouquetNumOffsetCache = { }
498 new_marked = set(self.servicelist.getMarked())
499 old_marked = set(self.__marked)
500 removed = old_marked - new_marked
501 added = new_marked - old_marked
505 self.mutableList.removeService(eServiceReference(x))
508 self.mutableList.addService(eServiceReference(x))
510 self.mutableList.flushChanges()
513 self.bouquet_mark_edit = OFF
514 self.mutableList = None
515 self.setTitle(self.saved_title)
516 self.saved_title = None
517 # self.servicePath is just a reference to servicePathTv or Radio...
518 # so we never ever do use the asignment operator in self.servicePath
519 del self.servicePath[:] # remove all elements
520 self.servicePath += self.savedPath # add saved elements
522 self.setRoot(self.servicePath[len(self.servicePath)-1])
524 def clearMarks(self):
525 self.servicelist.clearMarks()
528 ref = self.servicelist.getCurrent()
529 if self.servicelist.isMarked(ref):
530 self.servicelist.removeMarked(ref)
532 self.servicelist.addMarked(ref)
534 def removeCurrentService(self):
535 ref = self.servicelist.getCurrent()
536 mutableList = self.getMutableList()
537 if ref.valid() and mutableList is not None:
538 if not mutableList.removeService(ref):
539 self.bouquetNumOffsetCache = { }
540 mutableList.flushChanges() #FIXME dont flush on each single removed service
541 self.servicelist.removeCurrent()
543 def addServiceToBouquet(self, dest, service=None):
544 mutableList = self.getMutableList(dest)
545 if not mutableList is None:
546 if service is None: #use current selected service
547 service = self.servicelist.getCurrent()
548 if not mutableList.addService(service):
549 self.bouquetNumOffsetCache = { }
550 mutableList.flushChanges()
551 # do some voodoo to check if current_root is equal to dest
552 cur_root = self.getRoot();
553 str1 = cur_root and cur_root.toString() or -1
554 str2 = dest.toString()
555 pos1 = str1.find("FROM BOUQUET")
556 pos2 = str2.find("FROM BOUQUET")
557 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
558 self.servicelist.addService(service)
560 def toggleMoveMode(self):
562 if self.entry_marked:
563 self.toggleMoveMarked() # unmark current entry
564 self.movemode = False
565 self.pathChangeDisabled = False # re-enable path change
566 self.mutableList.flushChanges() # FIXME add check if changes was made
567 self.mutableList = None
568 self.setTitle(self.saved_title)
569 self.saved_title = None
570 cur_root = self.getRoot()
571 if cur_root and cur_root == self.bouquet_root:
572 self.bouquetNumOffsetCache = { }
574 self.mutableList = self.getMutableList()
576 self.pathChangeDisabled = True # no path change allowed in movemode
577 self.saved_title = self.instance.getTitle()
578 new_title = self.saved_title
579 pos = self.saved_title.find(')')
580 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
581 self.setTitle(new_title);
583 def handleEditCancel(self):
584 if self.movemode: #movemode active?
585 self.channelSelected() # unmark
586 self.toggleMoveMode() # disable move mode
587 elif self.bouquet_mark_edit != OFF:
588 self.endMarkedEdit(True) # abort edit mode
590 def toggleMoveMarked(self):
591 if self.entry_marked:
592 self.servicelist.setCurrentMarked(False)
593 self.entry_marked = False
595 self.servicelist.setCurrentMarked(True)
596 self.entry_marked = True
599 self.session.open(ChannelContextMenu, self)
604 # this makes it much simple to implement a selectable radio or tv mode :)
605 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
606 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
608 class ChannelSelectionBase(Screen):
609 def __init__(self, session):
610 Screen.__init__(self, session)
612 self["key_red"] = Button(_("All"))
613 self["key_green"] = Button(_("Satellites"))
614 self["key_yellow"] = Button(_("Provider"))
615 self["key_blue"] = Button(_("Favourites"))
617 self["list"] = ServiceList()
618 self.servicelist = self["list"]
620 self.numericalTextInput = NumericalTextInput()
621 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
623 self.servicePathTV = [ ]
624 self.servicePathRadio = [ ]
625 self.servicePath = [ ]
629 self.pathChangeDisabled = False
631 self.bouquetNumOffsetCache = { }
633 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
635 "showFavourites": self.showFavourites,
636 "showAllServices": self.showAllServices,
637 "showProviders": self.showProviders,
638 "showSatellites": self.showSatellites,
639 "nextBouquet": self.nextBouquet,
640 "prevBouquet": self.prevBouquet,
641 "nextMarker": self.nextMarker,
642 "prevMarker": self.prevMarker,
643 "1": self.keyNumberGlobal,
644 "2": self.keyNumberGlobal,
645 "3": self.keyNumberGlobal,
646 "4": self.keyNumberGlobal,
647 "5": self.keyNumberGlobal,
648 "6": self.keyNumberGlobal,
649 "7": self.keyNumberGlobal,
650 "8": self.keyNumberGlobal,
651 "9": self.keyNumberGlobal,
654 self.recallBouquetMode()
656 def getBouquetNumOffset(self, bouquet):
657 if not config.usage.multibouquet.value:
659 str = bouquet.toString()
661 if not self.bouquetNumOffsetCache.has_key(str):
662 serviceHandler = eServiceCenter.getInstance()
663 bouquetlist = serviceHandler.list(self.bouquet_root)
664 if not bouquetlist is None:
666 bouquetIterator = bouquetlist.getNext()
667 if not bouquetIterator.valid(): #end of list
669 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
670 if not (bouquetIterator.flags & eServiceReference.isDirectory):
672 servicelist = serviceHandler.list(bouquetIterator)
673 if not servicelist is None:
675 serviceIterator = servicelist.getNext()
676 if not serviceIterator.valid(): #check if end of list
678 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
681 return self.bouquetNumOffsetCache.get(str, offsetCount)
683 def recallBouquetMode(self):
684 if self.mode == MODE_TV:
685 self.service_types = service_types_tv
686 if config.usage.multibouquet.value:
687 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
689 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
691 self.service_types = service_types_radio
692 if config.usage.multibouquet.value:
693 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
695 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
696 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
700 self.servicePath = self.servicePathTV
701 self.recallBouquetMode()
702 title = self.instance.getTitle()
703 pos = title.find(" (")
709 def setRadioMode(self):
710 self.mode = MODE_RADIO
711 self.servicePath = self.servicePathRadio
712 self.recallBouquetMode()
713 title = self.instance.getTitle()
714 pos = title.find(" (")
720 def setRoot(self, root, justSet=False):
721 path = root.getPath()
722 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
723 pos = path.find('FROM BOUQUET')
724 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
725 if not inBouquetRootList and isBouquet:
726 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
727 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
729 self.servicelist.setMode(ServiceList.MODE_NORMAL)
730 self.servicelist.setRoot(root, justSet)
731 self.buildTitleString()
733 def removeModeStr(self, str):
734 if self.mode == MODE_TV:
735 pos = str.find(' (TV)')
737 pos = str.find(' (Radio)')
742 def getServiceName(self, ref):
743 str = self.removeModeStr(ServiceReference(ref).getServiceName())
745 pathstr = ref.getPath()
746 if pathstr.find('FROM PROVIDERS') != -1:
748 if pathstr.find('FROM SATELLITES') != -1:
749 return _("Satellites")
750 if pathstr.find(') ORDER BY name') != -1:
754 def buildTitleString(self):
755 titleStr = self.instance.getTitle()
756 pos = titleStr.find(']')
758 pos = titleStr.find(')')
760 titleStr = titleStr[:pos+1]
761 Len = len(self.servicePath)
763 base_ref = self.servicePath[0]
765 end_ref = self.servicePath[Len-1]
768 nameStr = self.getServiceName(base_ref)
769 titleStr += ' ' + nameStr
770 if end_ref is not None:
775 nameStr = self.getServiceName(end_ref)
777 self.setTitle(titleStr)
780 self.servicelist.moveUp()
783 self.servicelist.moveDown()
786 del self.servicePath[:]
788 def enterPath(self, ref, justSet=False):
789 self.servicePath.append(ref)
790 self.setRoot(ref, justSet)
792 def pathUp(self, justSet=False):
793 prev = self.servicePath.pop()
794 length = len(self.servicePath)
796 current = self.servicePath[length-1]
797 self.setRoot(current, justSet)
799 self.setCurrentSelection(prev)
802 def isBasePathEqual(self, ref):
803 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
807 def isPrevPathEqual(self, ref):
808 length = len(self.servicePath)
809 if length > 1 and self.servicePath[length-2] == ref:
813 def preEnterPath(self, refstr):
816 def showAllServices(self):
817 if not self.pathChangeDisabled:
818 refstr = '%s ORDER BY name'%(self.service_types)
819 if not self.preEnterPath(refstr):
820 ref = eServiceReference(refstr)
821 currentRoot = self.getRoot()
822 if currentRoot is None or currentRoot != ref:
826 def showSatellites(self):
827 if not self.pathChangeDisabled:
828 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
829 if not self.preEnterPath(refstr):
830 ref = eServiceReference(refstr)
834 if self.isBasePathEqual(ref):
835 if self.isPrevPathEqual(ref):
837 prev = self.pathUp(justSet)
839 currentRoot = self.getRoot()
840 if currentRoot is None or currentRoot != ref:
843 self.enterPath(ref, True)
845 serviceHandler = eServiceCenter.getInstance()
846 servicelist = serviceHandler.list(ref)
847 if not servicelist is None:
849 service = servicelist.getNext()
850 if not service.valid(): #check if end of list
852 orbpos = service.getUnsignedData(4) >> 16
853 if service.getPath().find("FROM PROVIDER") != -1:
854 service_type = _("Providers")
855 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
856 service_type = _("New")
858 service_type = _("Services")
860 # why we need this cast?
861 service_name = str(nimmanager.getSatDescription(orbpos))
863 if orbpos == 0xFFFF: #Cable
864 service_name = _("Cable")
865 elif orbpos == 0xEEEE: #Terrestrial
866 service_name = _("Terrestrial")
868 if orbpos > 1800: # west
869 orbpos = 3600 - orbpos
873 service_name = ("%d.%d" + h) % (orbpos / 10, orbpos % 10)
874 service.setName("%s - %s" % (service_name, service_type))
875 self.servicelist.addService(service)
876 self.servicelist.finishFill()
878 self.setCurrentSelection(prev)
880 def showProviders(self):
881 if not self.pathChangeDisabled:
882 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
883 if not self.preEnterPath(refstr):
884 ref = eServiceReference(refstr)
885 if self.isBasePathEqual(ref):
888 currentRoot = self.getRoot()
889 if currentRoot is None or currentRoot != ref:
893 def changeBouquet(self, direction):
894 if not self.pathChangeDisabled:
895 if len(self.servicePath) > 1:
896 #when enter satellite root list we must do some magic stuff..
897 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
898 if self.isBasePathEqual(ref):
899 self.showSatellites()
906 ref = self.getCurrentSelection()
910 if len(self.servicePath) > 0 and self.servicePath[0] == self.bouquet_root:
915 return self.servicelist.atBegin()
918 return self.servicelist.atEnd()
920 def nextBouquet(self):
921 self.changeBouquet(+1)
923 def prevBouquet(self):
924 self.changeBouquet(-1)
926 def showFavourites(self):
927 if not self.pathChangeDisabled:
928 if not self.preEnterPath(self.bouquet_rootstr):
929 if self.isBasePathEqual(self.bouquet_root):
932 currentRoot = self.getRoot()
933 if currentRoot is None or currentRoot != self.bouquet_root:
935 self.enterPath(self.bouquet_root)
937 def keyNumberGlobal(self, number):
938 unichar = self.numericalTextInput.getKey(number)
939 charstr = unichar.encode("utf-8")
940 if len(charstr) == 1:
941 self.servicelist.moveToChar(charstr[0])
944 return self.servicelist.getRoot()
946 def getCurrentSelection(self):
947 return self.servicelist.getCurrent()
949 def setCurrentSelection(self, service):
950 servicepath = service.getPath()
951 pos = servicepath.find(" FROM BOUQUET")
953 if self.mode == MODE_TV:
954 servicepath = '(type == 1)' + servicepath[pos:]
956 servicepath = '(type == 2)' + servicepath[pos:]
957 service.setPath(servicepath)
958 self.servicelist.setCurrent(service)
960 def getBouquetList(self):
962 serviceHandler = eServiceCenter.getInstance()
963 if config.usage.multibouquet.value:
964 list = serviceHandler.list(self.bouquet_root)
970 if s.flags & eServiceReference.isDirectory:
971 info = serviceHandler.info(s)
973 bouquets.append((info.getName(s), s))
976 info = serviceHandler.info(self.bouquet_root)
978 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
982 def keyNumber0(self, num):
983 if len(self.servicePath) > 1:
986 self.keyNumberGlobal(num)
989 if len(self.servicePath) > 1:
990 if self.isBasePathEqual(self.bouquet_root):
991 self.showFavourites()
993 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
994 if self.isBasePathEqual(ref):
995 self.showSatellites()
997 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
998 if self.isBasePathEqual(ref):
1001 self.showAllServices()
1003 def nextMarker(self):
1004 self.servicelist.moveToNextMarker()
1006 def prevMarker(self):
1007 self.servicelist.moveToPrevMarker()
1011 #config for lastservice
1012 config.tv = ConfigSubsection()
1013 config.tv.lastservice = ConfigText()
1014 config.tv.lastroot = ConfigText()
1015 config.radio = ConfigSubsection()
1016 config.radio.lastservice = ConfigText()
1017 config.radio.lastroot = ConfigText()
1018 config.servicelist = ConfigSubsection()
1019 config.servicelist.lastmode = ConfigText(default = "tv")
1021 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1022 def __init__(self, session):
1023 ChannelSelectionBase.__init__(self,session)
1024 ChannelSelectionEdit.__init__(self)
1025 ChannelSelectionEPG.__init__(self)
1027 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1029 "cancel": self.cancel,
1030 "ok": self.channelSelected,
1031 "keyRadio": self.setModeRadio,
1032 "keyTV": self.setModeTv,
1035 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1037 iPlayableService.evStart: self.__evServiceStart,
1038 iPlayableService.evEnd: self.__evServiceEnd
1041 self.lastChannelRootTimer = eTimer()
1042 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1043 self.lastChannelRootTimer.start(100,True)
1045 self.history_tv = [ ]
1046 self.history_radio = [ ]
1047 self.history = self.history_tv
1048 self.history_pos = 0
1050 self.lastservice = config.tv.lastservice
1051 self.lastroot = config.tv.lastroot
1052 self.revertMode = None
1053 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1054 self.new_service_played = False
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.new_service_played = True
1131 self.session.nav.playService(nref)
1133 self.saveChannel(nref)
1134 config.servicelist.lastmode.save()
1135 self.addToHistory(nref)
1137 def newServicePlayed(self):
1138 ret = self.new_service_played
1139 self.new_service_played = False
1142 def addToHistory(self, ref):
1143 if self.servicePath is not None:
1144 tmp=self.servicePath[:]
1147 del self.history[self.history_pos+1:]
1150 self.history.append(tmp)
1151 hlen = len(self.history)
1152 if hlen > HISTORYSIZE:
1155 self.history_pos = hlen-1
1157 def historyBack(self):
1158 hlen = len(self.history)
1159 if hlen > 1 and self.history_pos > 0:
1160 self.history_pos -= 1
1161 self.setHistoryPath()
1163 def historyNext(self):
1164 hlen = len(self.history)
1165 if hlen > 1 and self.history_pos < (hlen-1):
1166 self.history_pos += 1
1167 self.setHistoryPath()
1169 def setHistoryPath(self):
1170 path = self.history[self.history_pos][:]
1172 del self.servicePath[:]
1173 self.servicePath += path
1177 cur_root = self.getRoot()
1178 if cur_root and cur_root != root:
1180 self.session.nav.playService(ref)
1181 self.setCurrentSelection(ref)
1182 self.saveChannel(ref)
1186 for i in self.servicePath:
1187 path += i.toString()
1189 if len(path) and path != self.lastroot.value:
1190 self.lastroot.value = path
1191 self.lastroot.save()
1193 def restoreRoot(self):
1195 re = compile('.+?;')
1196 tmp = re.findall(self.lastroot.value)
1199 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1202 path = self.servicePath.pop()
1203 self.enterPath(path)
1205 self.showFavourites()
1208 def preEnterPath(self, refstr):
1209 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1210 pathstr = self.lastroot.value
1211 if pathstr is not None and pathstr.find(refstr) == 0:
1213 lastservice=eServiceReference(self.lastservice.value)
1214 if lastservice.valid():
1215 self.setCurrentSelection(lastservice)
1219 def saveChannel(self, ref):
1221 refstr = ref.toString()
1224 if refstr != self.lastservice.value:
1225 self.lastservice.value = refstr
1226 self.lastservice.save()
1228 def setCurrentServicePath(self, path):
1229 hlen = len(self.history)
1231 self.history[self.history_pos] = path
1233 self.history.append(path)
1234 self.setHistoryPath()
1236 def getCurrentServicePath(self):
1237 hlen = len(self.history)
1239 return self.history[self.history_pos]
1242 def recallPrevService(self):
1243 hlen = len(self.history)
1245 if self.history_pos == hlen-1:
1246 tmp = self.history[self.history_pos]
1247 self.history[self.history_pos] = self.history[self.history_pos-1]
1248 self.history[self.history_pos-1] = tmp
1250 tmp = self.history[self.history_pos+1]
1251 self.history[self.history_pos+1] = self.history[self.history_pos]
1252 self.history[self.history_pos] = tmp
1253 self.setHistoryPath()
1256 if self.revertMode is None:
1258 lastservice=eServiceReference(self.lastservice.value)
1259 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1260 self.setCurrentSelection(lastservice)
1261 elif self.revertMode == MODE_TV:
1263 elif self.revertMode == MODE_RADIO:
1265 self.revertMode = None
1268 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName
1270 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName):
1271 def __init__(self, session):
1272 Screen.__init__(self, session)
1273 InfoBarEvent.__init__(self)
1274 InfoBarServiceName.__init__(self)
1275 self["CurrentTime"] = Clock()
1276 self["RdsDecoder"] = RdsDecoder(self.session.nav)
1277 self["BlinkingPoint"] = Pixmap()
1278 self["BlinkingPoint"].hide()
1280 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1281 ALLOW_SUSPEND = True
1283 def __init__(self, session, infobar):
1284 ChannelSelectionBase.__init__(self, session)
1285 ChannelSelectionEdit.__init__(self)
1286 ChannelSelectionEPG.__init__(self)
1287 self.infobar = infobar
1288 config.radio = ConfigSubsection();
1289 config.radio.lastservice = ConfigText()
1290 config.radio.lastroot = ConfigText()
1291 self.onLayoutFinish.append(self.onCreate)
1293 self.info = session.instantiateDialog(RadioInfoBar) # our simple infobar
1295 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1297 "keyTV": self.closeRadio,
1298 "keyRadio": self.closeRadio,
1299 "cancel": self.closeRadio,
1300 "ok": self.channelSelected,
1303 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1305 iPlayableService.evStart: self.__evServiceStart,
1306 iPlayableService.evEnd: self.__evServiceEnd
1309 ########## RDS Radiotext / Rass Support BEGIN
1310 self.infobar = infobar # reference to real infobar (the one and only)
1311 self["RdsDecoder"] = self.info["RdsDecoder"]
1312 self["RdsActions"] = HelpableActionMap(self, "InfobarRdsActions",
1314 "startRassInteractive": (self.startRassInteractive, _("View Rass interactive..."))
1316 self["RdsActions"].setEnabled(False)
1317 infobar.rds_display.onRassInteractivePossibilityChanged.append(self.RassInteractivePossibilityChanged)
1319 def startRassInteractive(self):
1321 self.infobar.rass_interactive = self.session.openWithCallback(self.RassInteractiveClosed, RassInteractive)
1323 def RassInteractiveClosed(self):
1325 self.infobar.rass_interactive = None
1326 self.infobar.RassSlidePicChanged()
1328 def RassInteractivePossibilityChanged(self, state):
1329 self["RdsActions"].setEnabled(state)
1330 ########## RDS Radiotext / Rass Support END
1332 def closeRadio(self):
1333 self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
1335 #set previous tv service
1336 lastservice=eServiceReference(config.tv.lastservice.value)
1337 self.session.nav.playService(lastservice)
1340 def __evServiceStart(self):
1341 service = self.session.nav.getCurrentService()
1343 info = service.info()
1345 refstr = info.getInfoString(iServiceInformation.sServiceref)
1346 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1348 def __evServiceEnd(self):
1349 self.servicelist.setPlayableIgnoreService(eServiceReference())
1353 for i in self.servicePathRadio:
1354 path += i.toString()
1356 if len(path) and path != config.radio.lastroot.value:
1357 config.radio.lastroot.value = path
1358 config.radio.lastroot.save()
1360 def restoreRoot(self):
1362 re = compile('.+?;')
1363 tmp = re.findall(config.radio.lastroot.value)
1366 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1369 path = self.servicePathRadio.pop()
1370 self.enterPath(path)
1372 self.showFavourites()
1375 def preEnterPath(self, refstr):
1376 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1377 pathstr = config.radio.lastroot.value
1378 if pathstr is not None and pathstr.find(refstr) == 0:
1380 lastservice=eServiceReference(config.radio.lastservice.value)
1381 if lastservice.valid():
1382 self.setCurrentSelection(lastservice)
1389 lastservice=eServiceReference(config.radio.lastservice.value)
1390 if lastservice.valid():
1391 self.servicelist.setCurrent(lastservice)
1392 self.session.nav.playService(lastservice)
1395 def channelSelected(self): # just return selected service
1396 ref = self.getCurrentSelection()
1398 self.toggleMoveMarked()
1399 elif (ref.flags & 7) == 7:
1401 elif self.bouquet_mark_edit != OFF:
1402 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1404 elif not (ref.flags & eServiceReference.isMarker): # no marker
1405 cur_root = self.getRoot()
1406 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1407 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1408 if playingref is None or playingref != ref:
1409 self.session.nav.playService(ref)
1410 config.radio.lastservice.value = ref.toString()
1411 config.radio.lastservice.save()
1414 class SimpleChannelSelection(ChannelSelectionBase):
1415 def __init__(self, session, title):
1416 ChannelSelectionBase.__init__(self, session)
1418 self.onShown.append(self.__onExecCallback)
1420 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1422 "cancel": self.close,
1423 "ok": self.channelSelected,
1424 "keyRadio": self.setModeRadio,
1425 "keyTV": self.setModeTv,
1428 def __onExecCallback(self):
1429 self.setTitle(self.title)
1432 def channelSelected(self): # just return selected service
1433 ref = self.getCurrentSelection()
1434 if (ref.flags & 7) == 7:
1436 elif not (ref.flags & eServiceReference.isMarker):
1437 ref = self.getCurrentSelection()
1440 def setModeTv(self):
1442 self.showFavourites()
1444 def setModeRadio(self):
1446 self.showFavourites()