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
41 entrys.append((x[0], x[1]))
42 self["menu"] = MenuList(entrys, enableWrapAround)
45 cur = self["menu"].getCurrent()
48 def okbuttonClick(self):
49 self.selectedFunc(self.getCurrent())
57 def cancelClick(self):
60 # csel.bouquet_mark_edit values
65 def apend_when_current_valid(current, menu, args):
66 if current and current.valid():
69 class ChannelContextMenu(Screen):
70 def __init__(self, session, csel):
71 Screen.__init__(self, session)
75 self["actions"] = ActionMap(["OkCancelActions"],
77 "ok": self.okbuttonClick,
78 "cancel": self.cancelClick
82 current = csel.getCurrentSelection()
83 current_root = csel.getRoot()
84 current_sel_path = current.getPath()
85 current_sel_flags = current.flags
86 inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
87 inBouquet = csel.getMutableList() is not None
88 haveBouquets = config.usage.multibouquet.value
90 if not (len(current_sel_path) or current_sel_flags & (eServiceReference.isDirectory|eServiceReference.isMarker)):
91 apend_when_current_valid(current, menu, (_("show transponder info"), self.showServiceInformations))
92 if csel.bouquet_mark_edit == OFF and not csel.movemode:
93 if not inBouquetRootList:
94 isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
96 if config.ParentalControl.configured.value:
97 if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
98 apend_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())))
100 apend_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())))
102 apend_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected))
104 apend_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected))
107 if not inBouquet and current_sel_path.find("PROVIDERS") == -1:
108 apend_when_current_valid(current, menu, (_("copy to bouquets"), self.copyCurrentToBouquetList))
109 if current_sel_path.find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
110 apend_when_current_valid(current, menu, (_("remove all new found flags"), self.removeAllNewFoundFlags))
112 apend_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService))
113 if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
114 apend_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag))
116 menu.append((_("add bouquet"), self.showBouquetInputBox))
117 apend_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet))
119 if inBouquet: # current list is editable?
120 if csel.bouquet_mark_edit == OFF:
121 if not csel.movemode:
122 apend_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode))
123 if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup):
124 menu.append((_("add marker"), self.showMarkerInputBox))
126 apend_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart))
128 apend_when_current_valid(current, menu, (_("enable favourite edit"), self.bouquetMarkStart))
129 if current_sel_flags & eServiceReference.isGroup:
130 apend_when_current_valid(current, menu, (_("edit alternatives"), self.editAlternativeServices))
131 apend_when_current_valid(current, menu, (_("show alternatives"), self.showAlternativeServices))
132 apend_when_current_valid(current, menu, (_("remove all alternatives"), self.removeAlternativeServices))
133 elif not current_sel_flags & eServiceReference.isMarker:
134 apend_when_current_valid(current, menu, (_("add alternatives"), self.addAlternativeServices))
136 apend_when_current_valid(current, menu, (_("disable move mode"), self.toggleMoveMode))
138 if csel.bouquet_mark_edit == EDIT_BOUQUET:
140 apend_when_current_valid(current, menu, (_("end bouquet edit"), self.bouquetMarkEnd))
141 apend_when_current_valid(current, menu, (_("abort bouquet edit"), self.bouquetMarkAbort))
143 apend_when_current_valid(current, menu, (_("end favourites edit"), self.bouquetMarkEnd))
144 apend_when_current_valid(current, menu, (_("abort favourites edit"), self.bouquetMarkAbort))
146 apend_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd))
147 apend_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort))
149 menu.append((_("back"), self.cancelClick))
150 self["menu"] = MenuList(menu)
152 def okbuttonClick(self):
153 self["menu"].getCurrent()[1]()
155 def cancelClick(self):
158 def showServiceInformations(self):
159 self.session.open( ServiceInfo, self.csel.getCurrentSelection() )
161 def showBouquetInputBox(self):
162 self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
164 def bouquetInputCallback(self, bouquet):
165 if bouquet is not None:
166 self.csel.addBouquet(bouquet, None)
169 def addParentalProtection(self, service):
170 parentalControl.protectService(service.toCompareString())
173 def removeParentalProtection(self, service):
174 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"))
176 def pinEntered(self, service, result):
178 parentalControl.unProtectService(service)
181 self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR)
183 def addServiceToBouquetSelected(self):
184 bouquets = self.csel.getBouquetList()
189 if cnt > 1: # show bouquet list
190 self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
191 elif cnt == 1: # add to only one existing bouquet
192 self.addCurrentServiceToBouquet(bouquets[0][1])
194 def bouquetSelClosed(self, recursive):
199 def copyCurrentToBouquetList(self):
200 self.csel.copyCurrentToBouquetList()
203 def removeBouquet(self):
204 self.csel.removeBouquet()
207 def showMarkerInputBox(self):
208 self.session.openWithCallback(self.markerInputCallback, InputBox, title=_("Please enter a name for the new marker"), text="markername", maxSize=False, type=Input.TEXT)
210 def markerInputCallback(self, marker):
211 if marker is not None:
212 self.csel.addMarker(marker)
215 def addCurrentServiceToBouquet(self, dest):
216 self.csel.addServiceToBouquet(dest)
217 if self.bsel is not None:
218 self.bsel.close(True)
220 self.close(True) # close bouquet selection
222 def removeCurrentService(self):
223 self.csel.removeCurrentService()
226 def toggleMoveMode(self):
227 self.csel.toggleMoveMode()
230 def bouquetMarkStart(self):
231 self.csel.startMarkedEdit(EDIT_BOUQUET)
234 def bouquetMarkEnd(self):
235 self.csel.endMarkedEdit(abort=False)
238 def bouquetMarkAbort(self):
239 self.csel.endMarkedEdit(abort=True)
242 def removeNewFoundFlag(self):
243 eDVBDB.getInstance().removeFlag(self.csel.getCurrentSelection(), FLAG_SERVICE_NEW_FOUND)
246 def removeAllNewFoundFlags(self):
247 curpath = self.csel.getCurrentSelection().getPath()
248 idx = curpath.find("satellitePosition == ")
250 tmp = curpath[idx+21:]
253 satpos = int(tmp[:idx])
254 eDVBDB.getInstance().removeFlags(FLAG_SERVICE_NEW_FOUND, -1, -1, -1, satpos)
257 def editAlternativeServices(self):
258 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
261 def showAlternativeServices(self):
262 self.csel.enterPath(self.csel.getCurrentSelection())
265 def removeAlternativeServices(self):
266 self.csel.removeAlternativeServices()
269 def addAlternativeServices(self):
270 self.csel.addAlternativeServices()
271 self.csel.startMarkedEdit(EDIT_ALTERNATIVES)
274 class ChannelSelectionEPG:
276 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
278 "showEPGList": self.showEPGList,
281 def showEPGList(self):
282 ref=self.getCurrentSelection()
283 ptr=eEPGCache.getInstance()
284 if ptr.startTimeQuery(ref) != -1:
285 self.session.open(EPGSelection, ref)
287 print 'no epg for service', ref.toString()
289 class ChannelSelectionEdit:
291 self.entry_marked = False
292 self.movemode = False
293 self.bouquet_mark_edit = OFF
294 self.mutableList = None
296 self.saved_title = None
297 self.saved_root = None
299 class ChannelSelectionEditActionMap(ActionMap):
300 def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
301 ActionMap.__init__(self, contexts, actions, prio)
304 def action(self, contexts, action):
305 if action == "cancel":
306 self.csel.handleEditCancel()
307 return 0 # fall-trough
309 return 0 # fall-trough
311 return ActionMap.action(self, contexts, action)
313 self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
315 "contextMenu": self.doContext,
318 def getMutableList(self, root=eServiceReference()):
319 if not self.mutableList is None:
320 return self.mutableList
321 serviceHandler = eServiceCenter.getInstance()
324 list = root and serviceHandler.list(root)
326 return list.startEdit()
329 def buildBouquetID(self, str):
333 if (c >= 'a' and c <= 'z') or (c >= '0' and c <= '9'):
339 def addMarker(self, name):
340 current = self.servicelist.getCurrent()
341 mutableList = self.getMutableList()
344 str = '1:64:%d:0:0:0:0:0:0:0::%s'%(cnt, name)
345 ref = eServiceReference(str)
346 if current and current.valid():
347 if not mutableList.addService(ref, current):
348 self.servicelist.addService(ref, True)
349 mutableList.flushChanges()
351 elif not mutableList.addService(ref):
352 self.servicelist.addService(ref, True)
353 mutableList.flushChanges()
357 def addAlternativeServices(self):
358 cur_service = ServiceReference(self.getCurrentSelection())
359 root = self.getRoot()
360 cur_root = root and ServiceReference(root)
361 mutableBouquet = cur_root.list().startEdit()
363 name = cur_service.getServiceName()
365 if self.mode == MODE_TV:
366 str = '1:134:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"alternatives.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(name))
368 str = '1:134:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"alternatives.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(name))
369 new_ref = ServiceReference(str)
370 if not mutableBouquet.addService(new_ref.ref, cur_service.ref):
371 mutableBouquet.removeService(cur_service.ref)
372 mutableBouquet.flushChanges()
373 eDVBDB.getInstance().reloadBouquets()
374 mutableAlternatives = new_ref.list().startEdit()
375 if mutableAlternatives:
376 mutableAlternatives.setListName(name)
377 if mutableAlternatives.addService(cur_service.ref):
378 print "add", cur_service.toString(), "to new alternatives failed"
379 mutableAlternatives.flushChanges()
380 self.servicelist.addService(new_ref.ref, True)
381 self.servicelist.removeCurrent()
382 self.servicelist.moveUp()
384 print "get mutable list for new created alternatives failed"
386 print "add", str, "to", cur_root.getServiceName(), "failed"
388 print "bouquetlist is not editable"
390 def addBouquet(self, bName, services):
391 serviceHandler = eServiceCenter.getInstance()
392 mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
393 if mutableBouquetList:
394 if self.mode == MODE_TV:
396 str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(bName))
399 str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(bName))
400 new_bouquet_ref = eServiceReference(str)
401 if not mutableBouquetList.addService(new_bouquet_ref):
402 mutableBouquetList.flushChanges()
403 eDVBDB.getInstance().reloadBouquets()
404 mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
406 mutableBouquet.setListName(bName)
407 if services is not None:
408 for service in services:
409 if mutableBouquet.addService(service):
410 print "add", service.toString(), "to new bouquet failed"
411 mutableBouquet.flushChanges()
413 print "get mutable list for new created bouquet failed"
414 # do some voodoo to check if current_root is equal to bouquet_root
415 cur_root = self.getRoot();
416 str1 = cur_root and cur_root.toString()
417 pos1 = str1 and str1.find("FROM BOUQUET") or -1
418 pos2 = self.bouquet_rootstr.find("FROM BOUQUET")
419 if pos1 != -1 and pos2 != -1 and str1[pos1:] == self.bouquet_rootstr[pos2:]:
420 self.servicelist.addService(new_bouquet_ref)
422 print "add", str, "to bouquets failed"
424 print "bouquetlist is not editable"
426 def copyCurrentToBouquetList(self):
427 provider = ServiceReference(self.getCurrentSelection())
428 providerName = provider.getServiceName()
429 serviceHandler = eServiceCenter.getInstance()
430 services = serviceHandler.list(provider.ref)
431 self.addBouquet(providerName, services and services.getContent('R', True))
433 def removeAlternativeServices(self):
434 cur_service = ServiceReference(self.getCurrentSelection())
435 root = self.getRoot()
436 cur_root = root and ServiceReference(root)
437 list = cur_service.list()
438 first_in_alternative = list and list.getNext()
439 if first_in_alternative:
440 edit_root = cur_root and cur_root.list().startEdit()
442 if not edit_root.addService(first_in_alternative, cur_service.ref):
443 self.servicelist.addService(first_in_alternative, True)
445 print "couldn't add first alternative service to current root"
447 print "couldn't edit current root!!"
449 print "remove empty alternative list !!"
451 self.servicelist.moveUp()
453 def removeBouquet(self):
454 refstr = self.getCurrentSelection().toString()
455 print "removeBouquet", refstr
456 self.bouquetNumOffsetCache = { }
457 pos = refstr.find('FROM BOUQUET "')
460 refstr = refstr[pos+14:]
461 pos = refstr.find('"')
463 filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
464 self.removeCurrentService()
466 if filename is not None:
469 print "error during remove of", filename
471 # multiple marked entry stuff ( edit mode, later multiepg selection )
472 def startMarkedEdit(self, type):
473 self.savedPath = self.servicePath[:]
474 if type == EDIT_ALTERNATIVES:
475 self.enterPath(self.getCurrentSelection())
476 self.mutableList = self.getMutableList()
477 # add all services from the current list to internal marked set in listboxservicecontent
478 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
479 self.saved_title = self.instance.getTitle()
480 pos = self.saved_title.find(')')
481 new_title = self.saved_title[:pos+1]
482 if type == EDIT_ALTERNATIVES:
483 self.bouquet_mark_edit = EDIT_ALTERNATIVES
484 new_title += ' ' + _("[alternative edit]")
486 self.bouquet_mark_edit = EDIT_BOUQUET
487 if config.usage.multibouquet.value:
488 new_title += ' ' + _("[bouquet edit]")
490 new_title += ' ' + _("[favourite edit]")
491 self.setTitle(new_title)
492 self.__marked = self.servicelist.getRootServices()
493 for x in self.__marked:
494 self.servicelist.addMarked(eServiceReference(x))
495 self.showAllServices()
497 def endMarkedEdit(self, abort):
498 if not abort and self.mutableList is not None:
499 self.bouquetNumOffsetCache = { }
500 new_marked = set(self.servicelist.getMarked())
501 old_marked = set(self.__marked)
502 removed = old_marked - new_marked
503 added = new_marked - old_marked
507 self.mutableList.removeService(eServiceReference(x))
510 self.mutableList.addService(eServiceReference(x))
512 self.mutableList.flushChanges()
515 self.bouquet_mark_edit = OFF
516 self.mutableList = None
517 self.setTitle(self.saved_title)
518 self.saved_title = None
519 # self.servicePath is just a reference to servicePathTv or Radio...
520 # so we never ever do use the asignment operator in self.servicePath
521 del self.servicePath[:] # remove all elements
522 self.servicePath += self.savedPath # add saved elements
524 self.setRoot(self.servicePath[len(self.servicePath)-1])
526 def clearMarks(self):
527 self.servicelist.clearMarks()
530 ref = self.servicelist.getCurrent()
531 if self.servicelist.isMarked(ref):
532 self.servicelist.removeMarked(ref)
534 self.servicelist.addMarked(ref)
536 def removeCurrentService(self):
537 ref = self.servicelist.getCurrent()
538 mutableList = self.getMutableList()
539 if ref.valid() and mutableList is not None:
540 if not mutableList.removeService(ref):
541 self.bouquetNumOffsetCache = { }
542 mutableList.flushChanges() #FIXME dont flush on each single removed service
543 self.servicelist.removeCurrent()
545 def addServiceToBouquet(self, dest, service=None):
546 mutableList = self.getMutableList(dest)
547 if not mutableList is None:
548 if service is None: #use current selected service
549 service = self.servicelist.getCurrent()
550 if not mutableList.addService(service):
551 self.bouquetNumOffsetCache = { }
552 mutableList.flushChanges()
553 # do some voodoo to check if current_root is equal to dest
554 cur_root = self.getRoot();
555 str1 = cur_root and cur_root.toString() or -1
556 str2 = dest.toString()
557 pos1 = str1.find("FROM BOUQUET")
558 pos2 = str2.find("FROM BOUQUET")
559 if pos1 != -1 and pos2 != -1 and str1[pos1:] == str2[pos2:]:
560 self.servicelist.addService(service)
562 def toggleMoveMode(self):
564 if self.entry_marked:
565 self.toggleMoveMarked() # unmark current entry
566 self.movemode = False
567 self.pathChangeDisabled = False # re-enable path change
568 self.mutableList.flushChanges() # FIXME add check if changes was made
569 self.mutableList = None
570 self.setTitle(self.saved_title)
571 self.saved_title = None
572 cur_root = self.getRoot()
573 if cur_root and cur_root == self.bouquet_root:
574 self.bouquetNumOffsetCache = { }
576 self.mutableList = self.getMutableList()
578 self.pathChangeDisabled = True # no path change allowed in movemode
579 self.saved_title = self.instance.getTitle()
580 new_title = self.saved_title
581 pos = self.saved_title.find(')')
582 new_title = self.saved_title[:pos+1] + ' ' + _("[move mode]") + self.saved_title[pos+1:]
583 self.setTitle(new_title);
585 def handleEditCancel(self):
586 if self.movemode: #movemode active?
587 self.channelSelected() # unmark
588 self.toggleMoveMode() # disable move mode
589 elif self.bouquet_mark_edit != OFF:
590 self.endMarkedEdit(True) # abort edit mode
592 def toggleMoveMarked(self):
593 if self.entry_marked:
594 self.servicelist.setCurrentMarked(False)
595 self.entry_marked = False
597 self.servicelist.setCurrentMarked(True)
598 self.entry_marked = True
601 self.session.open(ChannelContextMenu, self)
606 # this makes it much simple to implement a selectable radio or tv mode :)
607 service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25)'
608 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)'
610 class ChannelSelectionBase(Screen):
611 def __init__(self, session):
612 Screen.__init__(self, session)
614 self["key_red"] = Button(_("All"))
615 self["key_green"] = Button(_("Satellites"))
616 self["key_yellow"] = Button(_("Provider"))
617 self["key_blue"] = Button(_("Favourites"))
619 self["list"] = ServiceList()
620 self.servicelist = self["list"]
622 self.numericalTextInput = NumericalTextInput()
623 self.numericalTextInput.setUseableChars(u'1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
625 self.servicePathTV = [ ]
626 self.servicePathRadio = [ ]
627 self.servicePath = [ ]
631 self.pathChangeDisabled = False
633 self.bouquetNumOffsetCache = { }
635 self["ChannelSelectBaseActions"] = NumberActionMap(["ChannelSelectBaseActions", "NumberActions"],
637 "showFavourites": self.showFavourites,
638 "showAllServices": self.showAllServices,
639 "showProviders": self.showProviders,
640 "showSatellites": self.showSatellites,
641 "nextBouquet": self.nextBouquet,
642 "prevBouquet": self.prevBouquet,
643 "nextMarker": self.nextMarker,
644 "prevMarker": self.prevMarker,
645 "1": self.keyNumberGlobal,
646 "2": self.keyNumberGlobal,
647 "3": self.keyNumberGlobal,
648 "4": self.keyNumberGlobal,
649 "5": self.keyNumberGlobal,
650 "6": self.keyNumberGlobal,
651 "7": self.keyNumberGlobal,
652 "8": self.keyNumberGlobal,
653 "9": self.keyNumberGlobal,
656 self.recallBouquetMode()
658 def getBouquetNumOffset(self, bouquet):
659 if not config.usage.multibouquet.value:
661 str = bouquet.toString()
663 if not self.bouquetNumOffsetCache.has_key(str):
664 serviceHandler = eServiceCenter.getInstance()
665 bouquetlist = serviceHandler.list(self.bouquet_root)
666 if not bouquetlist is None:
668 bouquetIterator = bouquetlist.getNext()
669 if not bouquetIterator.valid(): #end of list
671 self.bouquetNumOffsetCache[bouquetIterator.toString()]=offsetCount
672 if not (bouquetIterator.flags & eServiceReference.isDirectory):
674 servicelist = serviceHandler.list(bouquetIterator)
675 if not servicelist is None:
677 serviceIterator = servicelist.getNext()
678 if not serviceIterator.valid(): #check if end of list
680 playable = not (serviceIterator.flags & (eServiceReference.isDirectory|eServiceReference.isMarker))
683 return self.bouquetNumOffsetCache.get(str, offsetCount)
685 def recallBouquetMode(self):
686 if self.mode == MODE_TV:
687 self.service_types = service_types_tv
688 if config.usage.multibouquet.value:
689 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
691 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types)
693 self.service_types = service_types_radio
694 if config.usage.multibouquet.value:
695 self.bouquet_rootstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.radio" ORDER BY bouquet'
697 self.bouquet_rootstr = '%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types)
698 self.bouquet_root = eServiceReference(self.bouquet_rootstr)
702 self.servicePath = self.servicePathTV
703 self.recallBouquetMode()
704 title = self.instance.getTitle()
705 pos = title.find(" (")
711 def setRadioMode(self):
712 self.mode = MODE_RADIO
713 self.servicePath = self.servicePathRadio
714 self.recallBouquetMode()
715 title = self.instance.getTitle()
716 pos = title.find(" (")
722 def setRoot(self, root, justSet=False):
723 path = root.getPath()
724 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
725 pos = path.find('FROM BOUQUET')
726 isBouquet = (pos != -1) and (root.flags & eServiceReference.isDirectory)
727 if not inBouquetRootList and isBouquet:
728 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
729 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
731 self.servicelist.setMode(ServiceList.MODE_NORMAL)
732 self.servicelist.setRoot(root, justSet)
733 self.buildTitleString()
735 def removeModeStr(self, str):
736 if self.mode == MODE_TV:
737 pos = str.find(' (TV)')
739 pos = str.find(' (Radio)')
744 def getServiceName(self, ref):
745 str = self.removeModeStr(ServiceReference(ref).getServiceName())
747 pathstr = ref.getPath()
748 if pathstr.find('FROM PROVIDERS') != -1:
750 if pathstr.find('FROM SATELLITES') != -1:
751 return _("Satellites")
752 if pathstr.find(') ORDER BY name') != -1:
756 def buildTitleString(self):
757 titleStr = self.instance.getTitle()
758 pos = titleStr.find(']')
760 pos = titleStr.find(')')
762 titleStr = titleStr[:pos+1]
763 Len = len(self.servicePath)
765 base_ref = self.servicePath[0]
767 end_ref = self.servicePath[Len-1]
770 nameStr = self.getServiceName(base_ref)
771 titleStr += ' ' + nameStr
772 if end_ref is not None:
777 nameStr = self.getServiceName(end_ref)
779 self.setTitle(titleStr)
782 self.servicelist.moveUp()
785 self.servicelist.moveDown()
788 del self.servicePath[:]
790 def enterPath(self, ref, justSet=False):
791 self.servicePath.append(ref)
792 self.setRoot(ref, justSet)
794 def pathUp(self, justSet=False):
795 prev = self.servicePath.pop()
796 length = len(self.servicePath)
798 current = self.servicePath[length-1]
799 self.setRoot(current, justSet)
801 self.setCurrentSelection(prev)
804 def isBasePathEqual(self, ref):
805 if len(self.servicePath) > 1 and self.servicePath[0] == ref:
809 def isPrevPathEqual(self, ref):
810 length = len(self.servicePath)
811 if length > 1 and self.servicePath[length-2] == ref:
815 def preEnterPath(self, refstr):
818 def showAllServices(self):
819 if not self.pathChangeDisabled:
820 refstr = '%s ORDER BY name'%(self.service_types)
821 if not self.preEnterPath(refstr):
822 ref = eServiceReference(refstr)
823 currentRoot = self.getRoot()
824 if currentRoot is None or currentRoot != ref:
828 def showSatellites(self):
829 if not self.pathChangeDisabled:
830 refstr = '%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types)
831 if not self.preEnterPath(refstr):
832 ref = eServiceReference(refstr)
836 if self.isBasePathEqual(ref):
837 if self.isPrevPathEqual(ref):
839 prev = self.pathUp(justSet)
841 currentRoot = self.getRoot()
842 if currentRoot is None or currentRoot != ref:
845 self.enterPath(ref, True)
847 serviceHandler = eServiceCenter.getInstance()
848 servicelist = serviceHandler.list(ref)
849 if not servicelist is None:
851 service = servicelist.getNext()
852 if not service.valid(): #check if end of list
854 orbpos = service.getUnsignedData(4) >> 16
855 if service.getPath().find("FROM PROVIDER") != -1:
856 service_name = _("Providers")
857 elif service.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1:
858 service_name = _("New")
860 service_name = _("Services")
862 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
863 service.setName(service_name) # why we need this cast?
865 if orbpos == 0xFFFF: #Cable
866 n = ("%s (%s)") % (service_name, _("Cable"))
867 elif orbpos == 0xEEEE: #Terrestrial
868 n = ("%s (%s)") % (service_name, _("Terrestrial"))
870 if orbpos > 1800: # west
871 orbpos = 3600 - orbpos
875 n = ("%s (%d.%d" + h + ")") % (service_name, orbpos / 10, orbpos % 10)
877 self.servicelist.addService(service)
878 self.servicelist.finishFill()
880 self.setCurrentSelection(prev)
882 def showProviders(self):
883 if not self.pathChangeDisabled:
884 refstr = '%s FROM PROVIDERS ORDER BY name'%(self.service_types)
885 if not self.preEnterPath(refstr):
886 ref = eServiceReference(refstr)
887 if self.isBasePathEqual(ref):
890 currentRoot = self.getRoot()
891 if currentRoot is None or currentRoot != ref:
895 def changeBouquet(self, direction):
896 if not self.pathChangeDisabled:
897 if len(self.servicePath) > 1:
898 #when enter satellite root list we must do some magic stuff..
899 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
900 if self.isBasePathEqual(ref):
901 self.showSatellites()
908 ref = self.getCurrentSelection()
912 return self.isBasePathEqual(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)
1055 def multibouquet_config_changed(self, val):
1056 self.recallBouquetMode()
1058 def __evServiceStart(self):
1059 service = self.session.nav.getCurrentService()
1061 info = service.info()
1063 refstr = info.getInfoString(iServiceInformation.sServiceref)
1064 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1066 def __evServiceEnd(self):
1067 self.servicelist.setPlayableIgnoreService(eServiceReference())
1071 lastservice=eServiceReference(self.lastservice.value)
1072 if lastservice.valid():
1073 self.setCurrentSelection(lastservice)
1075 def setModeTv(self):
1076 if self.revertMode is None and config.servicelist.lastmode.value == "radio":
1077 self.revertMode = MODE_RADIO
1078 self.history = self.history_tv
1079 self.lastservice = config.tv.lastservice
1080 self.lastroot = config.tv.lastroot
1081 config.servicelist.lastmode.value = "tv"
1085 def setModeRadio(self):
1086 if self.revertMode is None and config.servicelist.lastmode.value == "tv":
1087 self.revertMode = MODE_TV
1088 if config.usage.e1like_radio_mode.value:
1089 self.history = self.history_radio
1090 self.lastservice = config.radio.lastservice
1091 self.lastroot = config.radio.lastroot
1092 config.servicelist.lastmode.value = "radio"
1096 def __onCreate(self):
1097 if config.usage.e1like_radio_mode.value:
1098 if config.servicelist.lastmode.value == "tv":
1104 lastservice=eServiceReference(self.lastservice.value)
1105 if lastservice.valid():
1108 def channelSelected(self):
1109 ref = self.getCurrentSelection()
1111 self.toggleMoveMarked()
1112 elif (ref.flags & 7) == 7:
1114 elif self.bouquet_mark_edit != OFF:
1115 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1117 elif not (ref.flags & eServiceReference.isMarker): # no marker
1118 root = self.getRoot()
1119 if not root or not (root.flags & eServiceReference.isGroup):
1123 #called from infoBar and channelSelected
1125 self.revertMode=None
1126 ref = self.session.nav.getCurrentlyPlayingServiceReference()
1127 nref = self.getCurrentSelection()
1128 if ref is None or ref != nref:
1129 self.session.nav.playService(nref)
1131 self.saveChannel(nref)
1132 config.servicelist.lastmode.save()
1133 self.addToHistory(nref)
1135 def addToHistory(self, ref):
1136 if self.servicePath is not None:
1137 tmp=self.servicePath[:]
1140 del self.history[self.history_pos+1:]
1143 self.history.append(tmp)
1144 hlen = len(self.history)
1145 if hlen > HISTORYSIZE:
1148 self.history_pos = hlen-1
1150 def historyBack(self):
1151 hlen = len(self.history)
1152 if hlen > 1 and self.history_pos > 0:
1153 self.history_pos -= 1
1154 self.setHistoryPath()
1156 def historyNext(self):
1157 hlen = len(self.history)
1158 if hlen > 1 and self.history_pos < (hlen-1):
1159 self.history_pos += 1
1160 self.setHistoryPath()
1162 def setHistoryPath(self):
1163 path = self.history[self.history_pos][:]
1165 del self.servicePath[:]
1166 self.servicePath += path
1170 cur_root = self.getRoot()
1171 if cur_root and cur_root != root:
1173 self.session.nav.playService(ref)
1174 self.setCurrentSelection(ref)
1175 self.saveChannel(ref)
1179 for i in self.servicePath:
1180 path += i.toString()
1182 if len(path) and path != self.lastroot.value:
1183 self.lastroot.value = path
1184 self.lastroot.save()
1186 def restoreRoot(self):
1188 re = compile('.+?;')
1189 tmp = re.findall(self.lastroot.value)
1192 self.servicePath.append(eServiceReference(i[:len(i)-1]))
1195 path = self.servicePath.pop()
1196 self.enterPath(path)
1198 self.showFavourites()
1201 def preEnterPath(self, refstr):
1202 if len(self.servicePath) and self.servicePath[0] != eServiceReference(refstr):
1203 pathstr = self.lastroot.value
1204 if pathstr is not None and pathstr.find(refstr) == 0:
1206 lastservice=eServiceReference(self.lastservice.value)
1207 if lastservice.valid():
1208 self.setCurrentSelection(lastservice)
1212 def saveChannel(self, ref):
1214 refstr = ref.toString()
1217 if refstr != self.lastservice.value:
1218 self.lastservice.value = refstr
1219 self.lastservice.save()
1221 def setCurrentServicePath(self, path):
1222 hlen = len(self.history)
1224 self.history[self.history_pos] = path
1226 self.history.append(path)
1227 self.setHistoryPath()
1229 def getCurrentServicePath(self):
1230 hlen = len(self.history)
1232 return self.history[self.history_pos]
1235 def recallPrevService(self):
1236 hlen = len(self.history)
1238 if self.history_pos == hlen-1:
1239 tmp = self.history[self.history_pos]
1240 self.history[self.history_pos] = self.history[self.history_pos-1]
1241 self.history[self.history_pos-1] = tmp
1243 tmp = self.history[self.history_pos+1]
1244 self.history[self.history_pos+1] = self.history[self.history_pos]
1245 self.history[self.history_pos] = tmp
1246 self.setHistoryPath()
1249 if self.revertMode is None:
1251 lastservice=eServiceReference(self.lastservice.value)
1252 if lastservice.valid() and self.getCurrentSelection() != lastservice:
1253 self.setCurrentSelection(lastservice)
1254 elif self.revertMode == MODE_TV:
1256 elif self.revertMode == MODE_RADIO:
1258 self.revertMode = None
1261 from Screens.InfoBarGenerics import InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord, InfoBarRadioText
1263 class RadioInfoBar(Screen, InfoBarEvent, InfoBarServiceName, InfoBarInstantRecord):
1264 def __init__(self, session):
1265 Screen.__init__(self, session)
1266 InfoBarEvent.__init__(self)
1267 InfoBarServiceName.__init__(self)
1268 InfoBarInstantRecord.__init__(self)
1269 self["CurrentTime"] = Clock()
1271 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG, InfoBarRadioText):
1273 ALLOW_SUSPEND = True
1275 def __init__(self, session):
1276 ChannelSelectionBase.__init__(self, session)
1277 ChannelSelectionEdit.__init__(self)
1278 ChannelSelectionEPG.__init__(self)
1279 InfoBarRadioText.__init__(self)
1281 config.radio = ConfigSubsection();
1282 config.radio.lastservice = ConfigText()
1283 config.radio.lastroot = ConfigText()
1284 self.onLayoutFinish.append(self.onCreate)
1286 self.info = session.instantiateDialog(RadioInfoBar)
1288 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1290 "keyTV": self.closeRadio,
1291 "keyRadio": self.closeRadio,
1292 "cancel": self.closeRadio,
1293 "ok": self.channelSelected,
1296 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
1298 iPlayableService.evStart: self.__evServiceStart,
1299 iPlayableService.evEnd: self.__evServiceEnd
1302 def __evServiceStart(self):
1303 service = self.session.nav.getCurrentService()
1305 info = service.info()
1307 refstr = info.getInfoString(iServiceInformation.sServiceref)
1308 self.servicelist.setPlayableIgnoreService(eServiceReference(refstr))
1310 def __evServiceEnd(self):
1311 self.servicelist.setPlayableIgnoreService(eServiceReference())
1315 for i in self.servicePathRadio:
1316 path += i.toString()
1318 if len(path) and path != config.radio.lastroot.value:
1319 config.radio.lastroot.value = path
1320 config.radio.lastroot.save()
1322 def restoreRoot(self):
1324 re = compile('.+?;')
1325 tmp = re.findall(config.radio.lastroot.value)
1328 self.servicePathRadio.append(eServiceReference(i[:len(i)-1]))
1331 path = self.servicePathRadio.pop()
1332 self.enterPath(path)
1334 self.showFavourites()
1337 def preEnterPath(self, refstr):
1338 if len(self.servicePathRadio) and self.servicePathRadio[0] != eServiceReference(refstr):
1339 pathstr = config.radio.lastroot.value
1340 if pathstr is not None and pathstr.find(refstr) == 0:
1342 lastservice=eServiceReference(config.radio.lastservice.value)
1343 if lastservice.valid():
1344 self.setCurrentSelection(lastservice)
1351 lastservice=eServiceReference(config.radio.lastservice.value)
1352 if lastservice.valid():
1353 self.servicelist.setCurrent(lastservice)
1354 self.session.nav.playService(lastservice)
1357 def channelSelected(self): # just return selected service
1358 ref = self.getCurrentSelection()
1360 self.toggleMoveMarked()
1361 elif (ref.flags & 7) == 7:
1363 elif self.bouquet_mark_edit != OFF:
1364 if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
1366 elif not (ref.flags & eServiceReference.isMarker): # no marker
1367 cur_root = self.getRoot()
1368 if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
1369 playingref = self.session.nav.getCurrentlyPlayingServiceReference()
1370 if playingref is None or playingref != ref:
1371 self.session.nav.playService(ref)
1372 config.radio.lastservice.value = ref.toString()
1373 config.radio.lastservice.save()
1376 def closeRadio(self):
1378 #set previous tv service
1379 lastservice=eServiceReference(config.tv.lastservice.value)
1380 self.session.nav.playService(lastservice)
1383 class SimpleChannelSelection(ChannelSelectionBase):
1384 def __init__(self, session, title):
1385 ChannelSelectionBase.__init__(self, session)
1387 self.onShown.append(self.__onExecCallback)
1389 self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
1391 "cancel": self.close,
1392 "ok": self.channelSelected,
1393 "keyRadio": self.setModeRadio,
1394 "keyTV": self.setModeTv,
1397 def __onExecCallback(self):
1398 self.setTitle(self.title)
1401 def channelSelected(self): # just return selected service
1402 ref = self.getCurrentSelection()
1403 if (ref.flags & 7) == 7:
1405 elif not (ref.flags & eServiceReference.isMarker):
1406 ref = self.getCurrentSelection()
1409 def setModeTv(self):
1411 self.showFavourites()
1413 def setModeRadio(self):
1415 self.showFavourites()