1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ServiceList import ServiceList
4 from Components.ActionMap import NumberActionMap
5 from EpgSelection import EPGSelection
6 from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer
7 from Components.config import config, configElement, ConfigSubsection, configText
8 from Screens.FixedMenu import FixedMenu
9 from Tools.NumericalTextInput import NumericalTextInput
10 from Components.NimManager import nimmanager
11 from Components.EventInfo import EventInfo
13 import xml.dom.minidom
15 class BouquetSelector(FixedMenu):
16 def __init__(self, session, bouquets, selectedFunc):
17 self.selectedFunc=selectedFunc
20 entrys.append((x[0], self.bouquetSelected, x[1]))
21 FixedMenu.__init__(self, session, "Bouquetlist", entrys)
22 self.skinName = "Menu"
24 def bouquetSelected(self):
25 self.selectedFunc(self["menu"].getCurrent()[2])
27 class ChannelContextMenu(FixedMenu):
28 def __init__(self, session, csel):
33 inBouquetRootList = csel.servicelist.getRoot().getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
34 inBouquet = csel.getMutableList() is not None
35 haveBouquets = csel.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1
37 if not csel.bouquet_mark_edit and not csel.movemode and not inBouquetRootList:
38 if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
40 menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected))
42 menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
44 menu.append((_("remove service"), self.removeCurrentService))
46 if inBouquet: # current list is editable?
47 if not csel.bouquet_mark_edit:
49 menu.append((_("enable move mode"), self.toggleMoveMode))
50 if not inBouquetRootList:
52 menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
54 menu.append((_("enable favourite edit"), self.bouquetMarkStart))
56 menu.append((_("disable move mode"), self.toggleMoveMode))
57 elif not inBouquetRootList:
59 menu.append((_("end bouquet edit"), self.bouquetMarkEnd))
60 menu.append((_("abort bouquet edit"), self.bouquetMarkAbort))
62 menu.append((_("end favourites edit"), self.bouquetMarkEnd))
63 menu.append((_("abort favourites edit"), self.bouquetMarkAbort))
65 menu.append((_("back"), self.close))
67 FixedMenu.__init__(self, session, _("Channel Selection"), menu)
68 self.skinName = "Menu"
70 def addServiceToBouquetSelected(self):
71 bouquets = self.csel.getBouquetList()
76 if cnt > 1: # show bouquet list
77 self.session.open(BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
78 elif cnt == 1: # add to only one existing bouquet
79 self.addCurrentServiceToBouquet(bouquets[0][1])
80 else: #no bouquets in root.. so assume only one favourite list is used
81 self.addCurrentServiceToBouquet(self.csel.bouquet_root)
83 def addCurrentServiceToBouquet(self, dest):
84 self.csel.addCurrentServiceToBouquet(dest)
87 def removeCurrentService(self):
88 self.csel.removeCurrentService()
91 def toggleMoveMode(self):
92 self.csel.toggleMoveMode()
95 def bouquetMarkStart(self):
96 self.csel.startMarkedEdit()
99 def bouquetMarkEnd(self):
100 self.csel.endMarkedEdit(abort=False)
103 def bouquetMarkAbort(self):
104 self.csel.endMarkedEdit(abort=True)
107 class ChannelSelectionEdit:
109 self.entry_marked = False
110 self.movemode = False
111 self.bouquet_mark_edit = False
112 self.mutableList = None
114 self.saved_title = None
115 self.saved_root = None
117 def getMutableList(self, root=eServiceReference()):
118 if not self.mutableList is None:
119 return self.mutableList
120 serviceHandler = eServiceCenter.getInstance()
122 root=self.servicelist.getRoot()
123 list = serviceHandler.list(root)
125 return list.startEdit()
128 # multiple marked entry stuff ( edit mode, later multiepg selection )
129 def startMarkedEdit(self):
130 self.mutableList = self.getMutableList()
131 # add all services from the current list to internal marked set in listboxservicecontent
132 self.bouquetRoot = self.servicelist.getRoot()
133 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
134 self.saved_title = self.instance.getTitle()
135 new_title = self.saved_title
136 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1:
137 new_title += ' ' + _("[bouquet edit]")
139 new_title += ' ' + _("[favourite edit]")
140 self.instance.setTitle(new_title)
141 self.bouquet_mark_edit = True
142 self.__marked = self.servicelist.getRootServices()
143 for x in self.__marked:
144 self.servicelist.addMarked(eServiceReference(x))
145 self.saved_root = self.getRoot()
146 self.showAllServices()
148 def endMarkedEdit(self, abort):
149 if not abort and self.mutableList is not None:
150 new_marked = set(self.servicelist.getMarked())
151 old_marked = set(self.__marked)
152 removed = old_marked - new_marked
153 added = new_marked - old_marked
157 self.mutableList.removeService(eServiceReference(x))
160 self.mutableList.addService(eServiceReference(x))
162 self.mutableList.flushChanges()
165 self.bouquet_mark_edit = False
166 self.bouquetRoot = None
167 self.mutableList = None
168 self.instance.setTitle(self.saved_title)
169 self.saved_title = None
170 self.setRoot(self.saved_root)
172 def clearMarks(self):
173 self.servicelist.clearMarks()
176 ref = self.servicelist.getCurrent()
177 if self.servicelist.isMarked(ref):
178 self.servicelist.removeMarked(ref)
180 self.servicelist.addMarked(ref)
182 def removeCurrentService(self):
183 ref = self.servicelist.getCurrent()
184 mutableList = self.getMutableList()
185 if ref.valid() and mutableList is not None:
186 if not mutableList.removeService(ref):
187 currentIndex = self.servicelist.getCurrentIndex()
188 self.servicelist.moveDown()
189 if self.servicelist.getCurrentIndex() == currentIndex:
191 mutableList.flushChanges() #FIXME dont flush on each single removed service
192 self.setRoot(self.servicelist.getRoot())
193 self.servicelist.moveToIndex(currentIndex)
195 def addCurrentServiceToBouquet(self, dest):
196 mutableList = self.getMutableList(dest)
197 if not mutableList is None:
198 if not mutableList.addService(self.servicelist.getCurrent()):
199 mutableList.flushChanges()
202 def toggleMoveMode(self):
204 if self.entry_marked:
205 self.toggleMoveMarked() # unmark current entry
206 self.movemode = False
207 self.mutableList.flushChanges() # FIXME add check if changes was made
208 self.mutableList = None
209 self.instance.setTitle(self.saved_title)
210 self.saved_title = None
212 self.mutableList = self.getMutableList()
214 self.saved_title = self.instance.getTitle()
215 new_title = self.saved_title
216 new_title += ' ' + _("[move mode]");
217 self.instance.setTitle(new_title);
219 def handleEditCancel(self):
220 if self.movemode: #movemode active?
221 self.channelSelected() # unmark
222 self.toggleMoveMode() # disable move mode
223 elif self.bouquet_mark_edit:
224 self.endMarkedEdit(True) # abort edit mode
226 def toggleMoveMarked(self):
227 if self.entry_marked:
228 self.servicelist.setCurrentMarked(False)
229 self.entry_marked = False
231 self.servicelist.setCurrentMarked(True)
232 self.entry_marked = True
235 self.session.open(ChannelContextMenu, self)
237 USE_MULTIBOUQUETS = True
242 class ChannelSelectionBase(Screen):
243 def __init__(self, session):
244 Screen.__init__(self, session)
246 # this makes it much simple to implement a selectable radio or tv mode :)
247 self.service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17)'
248 self.service_types_radio = '1:7:1:0:0:0:0:0:0:0:(type == 2)'
250 self["key_red"] = Button(_("All"))
251 self["key_green"] = Button(_("Satellites"))
252 self["key_yellow"] = Button(_("Provider"))
253 self["key_blue"] = Button(_("Favourites"))
255 self["list"] = ServiceList()
256 self.servicelist = self["list"]
258 self.numericalTextInput = NumericalTextInput()
260 def appendDVBTypes(self, ref):
262 pos = path.find(' FROM BOUQUET')
264 return eServiceReference(self.service_types + path[pos:])
267 def getBouquetNumOffset(self, bouquet):
268 bouquet = self.appendDVBTypes(bouquet)
269 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
272 serviceHandler = eServiceCenter.getInstance()
273 bouquetlist = serviceHandler.list(self.bouquet_root)
274 if not bouquetlist is None:
276 bouquetIterator = self.appendDVBTypes(bouquetlist.getNext())
277 if not bouquetIterator.valid() or bouquetIterator == bouquet: #end of list or bouquet found
279 if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
281 servicelist = serviceHandler.list(bouquetIterator)
282 if not servicelist is None:
284 serviceIterator = servicelist.getNext()
285 if not serviceIterator.valid(): #check if end of list
287 if serviceIterator.flags: #playable services have no flags
293 self.service_types = self.service_types_tv
294 if USE_MULTIBOUQUETS:
295 self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
297 self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types))
298 title = self.instance.getTitle()
299 pos = title.find(" (")
303 self.instance.setTitle(title)
306 def setRadioMode(self):
307 self.service_types = self.service_types_radio
308 if USE_MULTIBOUQUETS:
309 self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet')
311 self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types))
312 title = self.instance.getTitle()
313 pos = title.find(" (")
317 self.instance.setTitle(title)
318 self.mode = MODE_RADIO
320 def setRootBase(self, root, justSet=False):
321 path = root.getPath()
322 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
323 pos = path.find(' FROM BOUQUET')
324 isBouquet = pos != -1
325 if not inBouquetRootList and isBouquet:
326 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
327 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
328 refstr = self.service_types + path[pos:]
329 root = eServiceReference(refstr)
331 self.servicelist.setMode(ServiceList.MODE_NORMAL)
332 self.servicelist.setRoot(root, justSet)
335 self.servicelist.moveUp()
338 self.servicelist.moveDown()
340 def showAllServices(self):
341 ref = eServiceReference('%s ORDER BY name'%(self.service_types))
344 def showSatellites(self):
345 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
346 self.setRoot(ref, True)
347 serviceHandler = eServiceCenter.getInstance()
348 servicelist = serviceHandler.list(ref)
349 if not servicelist is None:
351 service = servicelist.getNext()
352 if not service.valid(): #check if end of list
354 orbpos = service.getData(4) >> 16
355 if service.getPath().find("FROM PROVIDER") != -1:
356 service_name = _("Providers")
358 service_name = _("Services")
360 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
361 service.setName(service_name) # why we need this cast?
363 if orbpos > 1800: # west
364 service.setName("%s (%3.1f" + _("W") + ")" %(str, (0 - (orbpos - 3600)) / 10.0))
366 service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0))
367 self.servicelist.addService(service)
368 self.servicelist.finishFill()
370 def showProviders(self):
371 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
374 def showFavourites(self):
375 self.setRoot(self.bouquet_root)
377 def keyNumberGlobal(self, number):
378 char = self.numericalTextInput.getKey(number)
379 print "You pressed number " + str(number)
380 print "You would go to character " + str(char)
381 self.servicelist.moveToChar(char)
383 def enterBouquet(self, action):
384 if action[:7] == "bouquet":
385 if action.find("FROM BOUQUET") != -1:
386 self.setRoot(eServiceReference("1:7:1:0:0:0:0:0:0:0:" + action[8:]))
388 self.setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:]))
393 return self.servicelist.getRoot()
395 def getCurrentSelection(self):
396 return self.servicelist.getCurrent()
398 def setCurrentSelection(self, service):
399 self.servicelist.setCurrent(service)
404 def getBouquetList(self):
407 serviceHandler = eServiceCenter.getInstance()
408 list = serviceHandler.list(self.bouquet_root)
414 if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
415 info = serviceHandler.info(s)
417 bouquets.append((info.getName(s), s))
420 if len(bouquets) == 0 and serviceCount > 0:
421 info = serviceHandler.info(self.bouquet_root)
423 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
427 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
428 def __init__(self, session):
429 ChannelSelectionBase.__init__(self,session)
430 ChannelSelectionEdit.__init__(self)
432 #config for lastservice
433 config.tv = ConfigSubsection();
434 config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
435 config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
437 class ChannelActionMap(NumberActionMap):
438 def action(self, contexts, action):
439 if not self.csel.enterBouquet(action):
440 if action == "cancel":
441 self.csel.handleEditCancel()
442 NumberActionMap.action(self, contexts, action)
443 self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions"],
445 "cancel": self.cancel,
446 "ok": self.channelSelected,
448 "contextMenu": self.doContext,
449 "showFavourites": self.showFavourites,
450 "showAllServices": self.showAllServices,
451 "showProviders": self.showProviders,
452 "showSatellites": self.showSatellites,
453 "showEPGList": self.showEPGList,
454 "1": self.keyNumberGlobal,
455 "2": self.keyNumberGlobal,
456 "3": self.keyNumberGlobal,
457 "4": self.keyNumberGlobal,
458 "5": self.keyNumberGlobal,
459 "6": self.keyNumberGlobal,
460 "7": self.keyNumberGlobal,
461 "8": self.keyNumberGlobal,
462 "9": self.keyNumberGlobal,
463 "0": self.keyNumberGlobal
465 self["actions"].csel = self
466 self.onShown.append(self.onShow)
468 self.lastChannelRootTimer = eTimer()
469 self.lastChannelRootTimer.timeout.get().append(self.onCreate)
470 self.lastChannelRootTimer.start(100,True)
474 lastroot=eServiceReference(config.tv.lastroot.value)
476 self.setRoot(lastroot)
478 self.showFavourites()
479 self.saveRoot(self.getRoot())
481 lastservice=eServiceReference(config.tv.lastservice.value)
482 if lastservice.valid():
483 self.servicelist.setCurrent(lastservice)
484 self.session.nav.playService(lastservice)
487 ref = self.session.nav.getCurrentlyPlayingServiceReference()
488 if ref is not None and ref.valid() and ref.getPath() == "":
489 self.servicelist.setPlayableIgnoreService(ref)
491 self.servicelist.setPlayableIgnoreService(eServiceReference())
493 def showEPGList(self):
494 ref=self.getCurrentSelection()
495 ptr=eEPGCache.getInstance()
496 if ptr.startTimeQuery(ref) != -1:
497 self.session.open(EPGSelection, ref)
499 print 'no epg for service', ref.toString()
501 def channelSelected(self):
502 ref = self.getCurrentSelection()
504 self.toggleMoveMarked()
505 elif (ref.flags & 7) == 7:
507 elif self.bouquet_mark_edit:
513 def setRoot(self, root, justSet=False):
514 if not self.movemode:
515 self.setRootBase(root, justSet)
517 #called from infoBar and channelSelected
519 self.session.nav.playService(self.getCurrentSelection())
520 self.saveRoot(self.getRoot())
523 def saveRoot(self, root):
525 config.tv.lastroot.value = root.toString()
526 config.tv.lastroot.save()
528 def saveChannel(self):
529 ref = self.session.nav.getCurrentlyPlayingServiceReference()
531 refstr = ref.toString()
534 config.tv.lastservice.value = refstr
535 config.tv.lastservice.save()
539 lastroot=eServiceReference(config.tv.lastroot.value)
540 lastservice=eServiceReference(config.tv.lastservice.value)
541 if lastroot.valid() and self.getRoot() != lastroot:
542 self.setRoot(lastroot)
543 if lastservice.valid() and self.getCurrentSelection() != lastservice:
544 self.servicelist.setCurrent(lastservice)
546 class ServiceInfoWindow(Screen):
547 def __init__(self, session):
548 Screen.__init__(self, session)
549 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
550 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
551 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
552 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
553 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
554 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
556 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit):
557 def __init__(self, session):
558 ChannelSelectionBase.__init__(self, session)
559 ChannelSelectionEdit.__init__(self)
561 config.radio = ConfigSubsection();
562 config.radio.lastservice = configElement("config.radio.lastservice", configText, "", 0);
563 config.radio.lastroot = configElement("config.radio.lastroot", configText, "", 0);
564 self.onLayoutFinish.append(self.onCreate)
566 self.info = session.instantiateDialog(ServiceInfoWindow)
568 class ChannelActionMap(NumberActionMap):
569 def action(self, contexts, action):
570 if not self.csel.enterBouquet(action):
571 NumberActionMap.action(self, contexts, action)
572 self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions", "TvRadioActions"],
574 "keyTV": self.closeRadio,
575 "keyRadio": self.closeRadio,
576 "contextMenu": self.doContext,
577 "cancel": self.closeRadio,
578 "ok": self.channelSelected,
579 "showFavourites": self.showFavourites,
580 "showAllServices": self.showAllServices,
581 "showProviders": self.showProviders,
582 "showSatellites": self.showSatellites,
583 "1": self.keyNumberGlobal,
584 "2": self.keyNumberGlobal,
585 "3": self.keyNumberGlobal,
586 "4": self.keyNumberGlobal,
587 "5": self.keyNumberGlobal,
588 "6": self.keyNumberGlobal,
589 "7": self.keyNumberGlobal,
590 "8": self.keyNumberGlobal,
591 "9": self.keyNumberGlobal,
592 "0": self.keyNumberGlobal
594 self["actions"].csel = self
598 lastroot=eServiceReference(config.radio.lastroot.value)
600 self.setRoot(lastroot)
602 self.showFavourites()
603 self.saveRoot(self.getRoot())
604 lastservice=eServiceReference(config.radio.lastservice.value)
605 if lastservice.valid():
606 self.servicelist.setCurrent(lastservice)
607 self.session.nav.playService(lastservice)
608 self.servicelist.setPlayableIgnoreService(lastservice)
609 self.info.instance.show()
611 def channelSelected(self): # just return selected service
612 ref = self.getCurrentSelection()
614 self.toggleMoveMarked()
615 elif (ref.flags & 7) == 7:
617 elif self.bouquet_mark_edit:
620 self.session.nav.playService(ref)
621 self.servicelist.setPlayableIgnoreService(ref)
622 config.radio.lastservice.value = ref.toString()
623 config.radio.lastservice.save()
625 def setRoot(self, root, justSet=False):
626 self.setRootBase(root, justSet)
628 def closeRadio(self):
629 self.info.instance.hide()
630 lastroot=eServiceReference(config.radio.lastroot.value)
631 lastservice=eServiceReference(config.radio.lastservice.value)
632 if lastroot.valid() and self.getRoot() != lastroot:
633 self.setRoot(lastroot)
634 if lastservice.valid() and self.getCurrentSelection() != lastservice:
635 self.servicelist.setCurrent(lastservice)
636 #set previous tv service
637 lastservice=eServiceReference(config.tv.lastservice.value)
638 self.session.nav.playService(lastservice)
641 class SimpleChannelSelection(ChannelSelectionBase):
642 def __init__(self, session, title):
643 ChannelSelectionBase.__init__(self, session)
645 self.onShown.append(self.onExecCallback)
647 class ChannelActionMap(NumberActionMap):
648 def action(self, contexts, action):
649 if not self.csel.enterBouquet(action):
650 NumberActionMap.action(self, contexts, action)
651 self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions", "TvRadioActions"],
653 "cancel": self.cancel,
654 "ok": self.channelSelected,
655 "showFavourites": self.showFavourites,
656 "showAllServices": self.showAllServices,
657 "showProviders": self.showProviders,
658 "showSatellites": self.showSatellites,
659 "keyRadio": self.setModeRadio,
660 "keyTV": self.setModeTv,
661 "1": self.keyNumberGlobal,
662 "2": self.keyNumberGlobal,
663 "3": self.keyNumberGlobal,
664 "4": self.keyNumberGlobal,
665 "5": self.keyNumberGlobal,
666 "6": self.keyNumberGlobal,
667 "7": self.keyNumberGlobal,
668 "8": self.keyNumberGlobal,
669 "9": self.keyNumberGlobal,
670 "0": self.keyNumberGlobal
672 self["actions"].csel = self
674 def onExecCallback(self):
675 self.session.currentDialog.instance.setTitle(self.title)
678 def channelSelected(self): # just return selected service
679 ref = self.getCurrentSelection()
680 if (ref.flags & 7) == 7:
683 ref = self.getCurrentSelection()
686 def setRoot(self, root, justSet=False):
687 self.setRootBase(root, justSet)
691 self.showFavourites()
693 def setModeRadio(self):
695 self.showFavourites()