1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ServiceList import ServiceList
4 from Components.ActionMap import NumberActionMap, ActionMap
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.Input import Input
15 from Components.ParentalControl import parentalControl
16 from Screens.InputBox import InputBox, PinInput
17 from Screens.MessageBox import MessageBox
18 from Screens.ServiceInfo import ServiceInfo
19 from ServiceReference import ServiceReference
20 from Tools.BoundFunction import boundFunction
24 FLAG_SERVICE_NEW_FOUND = 64 #define in lib/dvb/idvb.h as dxNewFound = 64
26 import xml.dom.minidom
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_name = _("Providers")
855 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
856 service_name = _("New")
858 service_name = _("Services")
860 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
861 service.setName(service_name) # why we need this cast?
863 if orbpos == 0xFFFF: #Cable
864 n = ("%s (%s)") % (service_name, _("Cable"))
865 elif orbpos == 0xEEEE: #Terrestrial
866 n = ("%s (%s)") % (service_name, _("Terrestrial"))
868 if orbpos > 1800: # west
869 orbpos = 3600 - orbpos
873 n = ("%s (%d.%d" + h + ")") % (service_name, orbpos / 10, orbpos % 10)
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 return self.isBasePathEqual(self.bouquet_root)
913 return self.servicelist.atBegin()
916 return self.servicelist.atEnd()
918 def nextBouquet(self):
919 self.changeBouquet(+1)
921 def prevBouquet(self):
922 self.changeBouquet(-1)
924 def showFavourites(self):
925 if not self.pathChangeDisabled:
926 if not self.preEnterPath(self.bouquet_rootstr):
927 if self.isBasePathEqual(self.bouquet_root):
930 currentRoot = self.getRoot()
931 if currentRoot is None or currentRoot != self.bouquet_root:
933 self.enterPath(self.bouquet_root)
935 def keyNumberGlobal(self, number):
936 unichar = self.numericalTextInput.getKey(number)
937 charstr = unichar.encode("utf-8")
938 if len(charstr) == 1:
939 self.servicelist.moveToChar(charstr[0])
942 return self.servicelist.getRoot()
944 def getCurrentSelection(self):
945 return self.servicelist.getCurrent()
947 def setCurrentSelection(self, service):
948 servicepath = service.getPath()
949 pos = servicepath.find(" FROM BOUQUET")
951 if self.mode == MODE_TV:
952 servicepath = '(type == 1)' + servicepath[pos:]
954 servicepath = '(type == 2)' + servicepath[pos:]
955 service.setPath(servicepath)
956 self.servicelist.setCurrent(service)
958 def getBouquetList(self):
960 serviceHandler = eServiceCenter.getInstance()
961 if config.usage.multibouquet.value:
962 list = serviceHandler.list(self.bouquet_root)
968 if s.flags & eServiceReference.isDirectory:
969 info = serviceHandler.info(s)
971 bouquets.append((info.getName(s), s))
974 info = serviceHandler.info(self.bouquet_root)
976 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
980 def keyNumber0(self, num):
981 if len(self.servicePath) > 1:
984 self.keyNumberGlobal(num)
987 if len(self.servicePath) > 1:
988 if self.isBasePathEqual(self.bouquet_root):
989 self.showFavourites()
991 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
992 if self.isBasePathEqual(ref):
993 self.showSatellites()
995 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
996 if self.isBasePathEqual(ref):
999 self.showAllServices()
1001 def nextMarker(self):
1002 self.servicelist.moveToNextMarker()
1004 def prevMarker(self):
1005 self.servicelist.moveToPrevMarker()
1009 #config for lastservice
1010 config.tv = ConfigSubsection()
1011 config.tv.lastservice = ConfigText()
1012 config.tv.lastroot = ConfigText()
1013 config.radio = ConfigSubsection()
1014 config.radio.lastservice = ConfigText()
1015 config.radio.lastroot = ConfigText()
1016 config.servicelist = ConfigSubsection()
1017 config.servicelist.lastmode = ConfigText(default = "tv")
1019 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
1020 def __init__(self, session):
1021 ChannelSelectionBase.__init__(self,session)
1022 ChannelSelectionEdit.__init__(self)
1023 ChannelSelectionEPG.__init__(self)
1025 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1027 "cancel": self.cancel,
1028 "ok": self.channelSelected,
1029 "keyRadio": self.setModeRadio,
1030 "keyTV": self.setModeTv,
1033 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1035 iPlayableService.evStart: self.__evServiceStart,
1036 iPlayableService.evEnd: self.__evServiceEnd
1039 self.lastChannelRootTimer = eTimer()
1040 self.lastChannelRootTimer.timeout.get().append(self.__onCreate)
1041 self.lastChannelRootTimer.start(100,True)
1043 self.history_tv = [ ]
1044 self.history_radio = [ ]
1045 self.history = self.history_tv
1046 self.history_pos = 0
1048 self.lastservice = config.tv.lastservice
1049 self.lastroot = config.tv.lastroot
1050 self.revertMode = None
1051 config.usage.multibouquet.addNotifier(self.multibouquet_config_changed)
1053 def multibouquet_config_changed(self, val):
1054 self.recallBouquetMode()
1056 def __evServiceStart(self):
1057 service = self.session.nav.getCurrentService()
1059 info = service.info()
1061 refstr = info.getInfoString(iServiceInformation.sServiceref)
1062 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1064 def __evServiceEnd(self):
1065 self.servicelist.setPlayableIgnoreService(eServiceReference())
1069 lastservice=eServiceReference(self.lastservice.value)
1070 if lastservice.valid():
1071 self.setCurrentSelection(lastservice)
1073 def setModeTv(self):
1074 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1075 self.revertMode = MODE_RADIO
1076 self.history = self.history_tv
1077 self.lastservice = config.tv.lastservice
1078 self.lastroot = config.tv.lastroot
1079 config.servicelist.lastmode.value = "tv"
1083 def setModeRadio(self):
1084 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1085 self.revertMode = MODE_TV
1086 if config.usage.e1like_radio_mode.value:
1087 self.history = self.history_radio
1088 self.lastservice = config.radio.lastservice
1089 self.lastroot = config.radio.lastroot
1090 config.servicelist.lastmode.value = "radio"
1094 def __onCreate(self):
1095 if config.usage.e1like_radio_mode.value:
1096 if config.servicelist.lastmode.value == "tv":
1102 lastservice=eServiceReference(self.lastservice.value)
1103 if lastservice.valid():
1106 def channelSelected(self):
1107 ref = self.getCurrentSelection()
1109 self.toggleMoveMarked()
1110 elif (ref.flags & 7) == 7:
1112 elif self.bouquet_mark_edit != OFF:
1113 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1115 elif not (ref.flags & eServiceReference.isMarker): # no marker
1116 root = self.getRoot()
1117 if not root or not (root.flags & eServiceReference.isGroup):
1121 #called from infoBar and channelSelected
1123 self.revertMode=None
1124 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1125 nref = self.getCurrentSelection()
1126 if ref is None or ref != nref:
1127 self.session.nav.playService(nref)
1129 self.saveChannel(nref)
1130 config.servicelist.lastmode.save()
1131 self.addToHistory(nref)
1133 def addToHistory(self, ref):
1134 if self.servicePath is not None:
1135 tmp=self.servicePath[:]
1138 del self.history[self.history_pos+1:]
1141 self.history.append(tmp)
1142 hlen = len(self.history)
1143 if hlen > HISTORYSIZE:
1146 self.history_pos = hlen-1
1148 def historyBack(self):
1149 hlen = len(self.history)
1150 if hlen > 1 and self.history_pos > 0:
1151 self.history_pos -= 1
1152 self.setHistoryPath()
1154 def historyNext(self):
1155 hlen = len(self.history)
1156 if hlen > 1 and self.history_pos < (hlen-1):
1157 self.history_pos += 1
1158 self.setHistoryPath()
1160 def setHistoryPath(self):
1161 path = self.history[self.history_pos][:]
1163 del self.servicePath[:]
1164 self.servicePath += path
1168 cur_root = self.getRoot()
1169 if cur_root and cur_root != root:
1171 self.session.nav.playService(ref)
1172 self.setCurrentSelection(ref)
1173 self.saveChannel(ref)
1177 for i in self.servicePath:
1178 path += i.toString()
1180 if len(path) and path != self.lastroot.value:
1181 self.lastroot.value = path
1182 self.lastroot.save()
1184 def restoreRoot(self):
1186 re = compile('.+?;')
1187 tmp = re.findall(self.lastroot.value)
1190 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1193 path = self.servicePath.pop()
1194 self.enterPath(path)
1196 self.showFavourites()
1199 def preEnterPath(self, refstr):
1200 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1201 pathstr = self.lastroot.value
1202 if pathstr is not None and pathstr.find(refstr) == 0:
1204 lastservice=eServiceReference(self.lastservice.value)
1205 if lastservice.valid():
1206 self.setCurrentSelection(lastservice)
1210 def saveChannel(self, ref):
1212 refstr = ref.toString()
1215 if refstr != self.lastservice.value:
1216 self.lastservice.value = refstr
1217 self.lastservice.save()
1219 def setCurrentServicePath(self, path):
1220 hlen = len(self.history)
1222 self.history[self.history_pos] = path
1224 self.history.append(path)
1225 self.setHistoryPath()
1227 def getCurrentServicePath(self):
1228 hlen = len(self.history)
1230 return self.history[self.history_pos]
1233 def recallPrevService(self):
1234 hlen = len(self.history)
1236 if self.history_pos == hlen-1:
1237 tmp = self.history[self.history_pos]
1238 self.history[self.history_pos] = self.history[self.history_pos-1]
1239 self.history[self.history_pos-1] = tmp
1241 tmp = self.history[self.history_pos+1]
1242 self.history[self.history_pos+1] = self.history[self.history_pos]
1243 self.history[self.history_pos] = tmp
1244 self.setHistoryPath()
1247 if self.revertMode is None:
1249 lastservice=eServiceReference(self.lastservice.value)
1250 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1251 self.setCurrentSelection(lastservice)
1252 elif self.revertMode == MODE_TV:
1254 elif self.revertMode == MODE_RADIO:
1256 self.revertMode = None
1259 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarRadioText
1261 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
1262 def __init__(self, session):
1263 Screen.__init__(self, session)
1264 InfoBarEvent.__init__(self)
1265 InfoBarServiceName.__init__(self)
1266 InfoBarInstantRecord.__init__(self)
1267 self["CurrentTime"] = Clock()
1269 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarRadioText):
1271 ALLOW_SUSPEND = True
1273 def __init__(self, session):
1274 ChannelSelectionBase.__init__(self, session)
1275 ChannelSelectionEdit.__init__(self)
1276 ChannelSelectionEPG.__init__(self)
1277 InfoBarRadioText.__init__(self)
1279 config.radio = ConfigSubsection();
1280 config.radio.lastservice = ConfigText()
1281 config.radio.lastroot = ConfigText()
1282 self.onLayoutFinish.append(self.onCreate)
1284 self.info = session.instantiateDialog(RadioInfoBar)
1286 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1288 "keyTV": self.closeRadio,
1289 "keyRadio": self.closeRadio,
1290 "cancel": self.closeRadio,
1291 "ok": self.channelSelected,
1294 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1296 iPlayableService.evStart: self.__evServiceStart,
1297 iPlayableService.evEnd: self.__evServiceEnd
1300 def __evServiceStart(self):
1301 service = self.session.nav.getCurrentService()
1303 info = service.info()
1305 refstr = info.getInfoString(iServiceInformation.sServiceref)
1306 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1308 def __evServiceEnd(self):
1309 self.servicelist.setPlayableIgnoreService(eServiceReference())
1313 for i in self.servicePathRadio:
1314 path += i.toString()
1316 if len(path) and path != config.radio.lastroot.value:
1317 config.radio.lastroot.value = path
1318 config.radio.lastroot.save()
1320 def restoreRoot(self):
1322 re = compile('.+?;')
1323 tmp = re.findall(config.radio.lastroot.value)
1326 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1329 path = self.servicePathRadio.pop()
1330 self.enterPath(path)
1332 self.showFavourites()
1335 def preEnterPath(self, refstr):
1336 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1337 pathstr = config.radio.lastroot.value
1338 if pathstr is not None and pathstr.find(refstr) == 0:
1340 lastservice=eServiceReference(config.radio.lastservice.value)
1341 if lastservice.valid():
1342 self.setCurrentSelection(lastservice)
1349 lastservice=eServiceReference(config.radio.lastservice.value)
1350 if lastservice.valid():
1351 self.servicelist.setCurrent(lastservice)
1352 self.session.nav.playService(lastservice)
1355 def channelSelected(self): # just return selected service
1356 ref = self.getCurrentSelection()
1358 self.toggleMoveMarked()
1359 elif (ref.flags & 7) == 7:
1361 elif self.bouquet_mark_edit != OFF:
1362 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1364 elif not (ref.flags & eServiceReference.isMarker): # no marker
1365 cur_root = self.getRoot()
1366 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1367 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1368 if playingref is None or playingref != ref:
1369 self.session.nav.playService(ref)
1370 config.radio.lastservice.value = ref.toString()
1371 config.radio.lastservice.save()
1374 def closeRadio(self):
1376 #set previous tv service
1377 lastservice=eServiceReference(config.tv.lastservice.value)
1378 self.session.nav.playService(lastservice)
1381 class SimpleChannelSelection(ChannelSelectionBase):
1382 def __init__(self, session, title):
1383 ChannelSelectionBase.__init__(self, session)
1385 self.onShown.append(self.__onExecCallback)
1387 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1389 "cancel": self.close,
1390 "ok": self.channelSelected,
1391 "keyRadio": self.setModeRadio,
1392 "keyTV": self.setModeTv,
1395 def __onExecCallback(self):
1396 self.setTitle(self.title)
1399 def channelSelected(self): # just return selected service
1400 ref = self.getCurrentSelection()
1401 if (ref.flags & 7) == 7:
1403 elif not (ref.flags & eServiceReference.isMarker):
1404 ref = self.getCurrentSelection()
1407 def setModeTv(self):
1409 self.showFavourites()
1411 def setModeRadio(self):
1413 self.showFavourites()