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.ServiceName import ServiceName
12 from Components.Clock import Clock
13 from Components.EventInfo import EventInfo
15 import xml.dom.minidom
17 class BouquetSelector(FixedMenu):
18 def __init__(self, session, bouquets, selectedFunc):
19 self.selectedFunc=selectedFunc
22 entrys.append((x[0], self.bouquetSelected, x[1]))
23 FixedMenu.__init__(self, session, "Bouquetlist", entrys)
24 self.skinName = "Menu"
26 def bouquetSelected(self):
27 self.selectedFunc(self["menu"].getCurrent()[2])
29 class ChannelContextMenu(FixedMenu):
30 def __init__(self, session, csel):
35 inBouquetRootList = csel.servicelist.getRoot().getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
36 inBouquet = csel.getMutableList() is not None
37 haveBouquets = csel.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1
39 if not csel.bouquet_mark_edit and not csel.movemode and not inBouquetRootList:
40 if (csel.getCurrentSelection().flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory:
42 menu.append((_("add service to bouquet"), self.addServiceToBouquetSelected))
44 menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
46 menu.append((_("remove service"), self.removeCurrentService))
48 if inBouquet: # current list is editable?
49 if not csel.bouquet_mark_edit:
51 menu.append((_("enable move mode"), self.toggleMoveMode))
52 if not inBouquetRootList:
54 menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
56 menu.append((_("enable favourite edit"), self.bouquetMarkStart))
58 menu.append((_("disable move mode"), self.toggleMoveMode))
59 elif not inBouquetRootList:
61 menu.append((_("end bouquet edit"), self.bouquetMarkEnd))
62 menu.append((_("abort bouquet edit"), self.bouquetMarkAbort))
64 menu.append((_("end favourites edit"), self.bouquetMarkEnd))
65 menu.append((_("abort favourites edit"), self.bouquetMarkAbort))
67 menu.append((_("back"), self.close))
69 FixedMenu.__init__(self, session, _("Channel Selection"), menu)
70 self.skinName = "Menu"
72 def addServiceToBouquetSelected(self):
73 bouquets = self.csel.getBouquetList()
78 if cnt > 1: # show bouquet list
79 self.session.open(BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
80 elif cnt == 1: # add to only one existing bouquet
81 self.addCurrentServiceToBouquet(bouquets[0][1])
82 else: #no bouquets in root.. so assume only one favourite list is used
83 self.addCurrentServiceToBouquet(self.csel.bouquet_root)
85 def addCurrentServiceToBouquet(self, dest):
86 self.csel.addCurrentServiceToBouquet(dest)
89 def removeCurrentService(self):
90 self.csel.removeCurrentService()
93 def toggleMoveMode(self):
94 self.csel.toggleMoveMode()
97 def bouquetMarkStart(self):
98 self.csel.startMarkedEdit()
101 def bouquetMarkEnd(self):
102 self.csel.endMarkedEdit(abort=False)
105 def bouquetMarkAbort(self):
106 self.csel.endMarkedEdit(abort=True)
109 class ChannelSelectionEdit:
111 self.entry_marked = False
112 self.movemode = False
113 self.bouquet_mark_edit = False
114 self.mutableList = None
116 self.saved_title = None
117 self.saved_root = None
119 def getMutableList(self, root=eServiceReference()):
120 if not self.mutableList is None:
121 return self.mutableList
122 serviceHandler = eServiceCenter.getInstance()
124 root=self.servicelist.getRoot()
125 list = serviceHandler.list(root)
127 return list.startEdit()
130 # multiple marked entry stuff ( edit mode, later multiepg selection )
131 def startMarkedEdit(self):
132 self.mutableList = self.getMutableList()
133 # add all services from the current list to internal marked set in listboxservicecontent
134 self.bouquetRoot = self.servicelist.getRoot()
135 self.clearMarks() # this clears the internal marked set in the listboxservicecontent
136 self.saved_title = self.instance.getTitle()
137 new_title = self.saved_title
138 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1:
139 new_title += ' ' + _("[bouquet edit]")
141 new_title += ' ' + _("[favourite edit]")
142 self.instance.setTitle(new_title)
143 self.bouquet_mark_edit = True
144 self.__marked = self.servicelist.getRootServices()
145 for x in self.__marked:
146 self.servicelist.addMarked(eServiceReference(x))
147 self.saved_root = self.getRoot()
148 self.showAllServices()
150 def endMarkedEdit(self, abort):
151 if not abort and self.mutableList is not None:
152 new_marked = set(self.servicelist.getMarked())
153 old_marked = set(self.__marked)
154 removed = old_marked - new_marked
155 added = new_marked - old_marked
159 self.mutableList.removeService(eServiceReference(x))
162 self.mutableList.addService(eServiceReference(x))
164 self.mutableList.flushChanges()
167 self.bouquet_mark_edit = False
168 self.bouquetRoot = None
169 self.mutableList = None
170 self.instance.setTitle(self.saved_title)
171 self.saved_title = None
172 self.setRoot(self.saved_root)
174 def clearMarks(self):
175 self.servicelist.clearMarks()
178 ref = self.servicelist.getCurrent()
179 if self.servicelist.isMarked(ref):
180 self.servicelist.removeMarked(ref)
182 self.servicelist.addMarked(ref)
184 def removeCurrentService(self):
185 ref = self.servicelist.getCurrent()
186 mutableList = self.getMutableList()
187 if ref.valid() and mutableList is not None:
188 if not mutableList.removeService(ref):
189 currentIndex = self.servicelist.getCurrentIndex()
190 self.servicelist.moveDown()
191 if self.servicelist.getCurrentIndex() == currentIndex:
193 mutableList.flushChanges() #FIXME dont flush on each single removed service
194 self.setRoot(self.servicelist.getRoot())
195 self.servicelist.moveToIndex(currentIndex)
197 def addCurrentServiceToBouquet(self, dest):
198 mutableList = self.getMutableList(dest)
199 if not mutableList is None:
200 if not mutableList.addService(self.servicelist.getCurrent()):
201 mutableList.flushChanges()
204 def toggleMoveMode(self):
206 if self.entry_marked:
207 self.toggleMoveMarked() # unmark current entry
208 self.movemode = False
209 self.mutableList.flushChanges() # FIXME add check if changes was made
210 self.mutableList = None
211 self.instance.setTitle(self.saved_title)
212 self.saved_title = None
214 self.mutableList = self.getMutableList()
216 self.saved_title = self.instance.getTitle()
217 new_title = self.saved_title
218 new_title += ' ' + _("[move mode]");
219 self.instance.setTitle(new_title);
221 def handleEditCancel(self):
222 if self.movemode: #movemode active?
223 self.channelSelected() # unmark
224 self.toggleMoveMode() # disable move mode
225 elif self.bouquet_mark_edit:
226 self.endMarkedEdit(True) # abort edit mode
228 def toggleMoveMarked(self):
229 if self.entry_marked:
230 self.servicelist.setCurrentMarked(False)
231 self.entry_marked = False
233 self.servicelist.setCurrentMarked(True)
234 self.entry_marked = True
237 self.session.open(ChannelContextMenu, self)
239 USE_MULTIBOUQUETS = False
244 class ChannelSelectionBase(Screen):
245 def __init__(self, session):
246 Screen.__init__(self, session)
248 # this makes it much simple to implement a selectable radio or tv mode :)
249 self.service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17)'
250 self.service_types_radio = '1:7:1:0:0:0:0:0:0:0:(type == 2)'
252 self["key_red"] = Button(_("All"))
253 self["key_green"] = Button(_("Satellites"))
254 self["key_yellow"] = Button(_("Provider"))
255 self["key_blue"] = Button(_("Favourites"))
257 self["list"] = ServiceList()
258 self.servicelist = self["list"]
260 self.numericalTextInput = NumericalTextInput()
262 def appendDVBTypes(self, ref):
264 pos = path.find(' FROM BOUQUET')
266 return eServiceReference(self.service_types + path[pos:])
269 def getBouquetNumOffset(self, bouquet):
270 bouquet = self.appendDVBTypes(bouquet)
271 if self.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
274 serviceHandler = eServiceCenter.getInstance()
275 bouquetlist = serviceHandler.list(self.bouquet_root)
276 if not bouquetlist is None:
278 bouquetIterator = self.appendDVBTypes(bouquetlist.getNext())
279 if not bouquetIterator.valid() or bouquetIterator == bouquet: #end of list or bouquet found
281 if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
283 servicelist = serviceHandler.list(bouquetIterator)
284 if not servicelist is None:
286 serviceIterator = servicelist.getNext()
287 if not serviceIterator.valid(): #check if end of list
289 if serviceIterator.flags: #playable services have no flags
295 self.service_types = self.service_types_tv
296 if USE_MULTIBOUQUETS:
297 self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
299 self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(self.service_types))
300 title = self.instance.getTitle()
301 pos = title.find(" (")
305 self.instance.setTitle(title)
308 def setRadioMode(self):
309 self.service_types = self.service_types_radio
310 if USE_MULTIBOUQUETS:
311 self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.radio" ORDER BY bouquet')
313 self.bouquet_root = eServiceReference('%s FROM BOUQUET "userbouquet.favourites.radio" ORDER BY bouquet'%(self.service_types))
314 title = self.instance.getTitle()
315 pos = title.find(" (")
319 self.instance.setTitle(title)
320 self.mode = MODE_RADIO
322 def setRootBase(self, root, justSet=False):
323 path = root.getPath()
324 inBouquetRootList = path.find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
325 pos = path.find(' FROM BOUQUET')
326 isBouquet = pos != -1
327 if not inBouquetRootList and isBouquet:
328 self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
329 self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
330 refstr = self.service_types + path[pos:]
331 root = eServiceReference(refstr)
333 self.servicelist.setMode(ServiceList.MODE_NORMAL)
334 self.servicelist.setRoot(root, justSet)
337 self.servicelist.moveUp()
340 self.servicelist.moveDown()
342 def showAllServices(self):
343 ref = eServiceReference('%s ORDER BY name'%(self.service_types))
346 def showSatellites(self):
347 ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
348 self.setRoot(ref, True)
349 serviceHandler = eServiceCenter.getInstance()
350 servicelist = serviceHandler.list(ref)
351 if not servicelist is None:
353 service = servicelist.getNext()
354 if not service.valid(): #check if end of list
356 orbpos = service.getData(4) >> 16
357 if service.getPath().find("FROM PROVIDER") != -1:
358 service_name = _("Providers")
360 service_name = _("Services")
362 service_name += str(' - %s'%(nimmanager.getSatDescription(orbpos)))
363 service.setName(service_name) # why we need this cast?
365 if orbpos > 1800: # west
366 service.setName("%s (%3.1f" + _("W") + ")" %(str, (0 - (orbpos - 3600)) / 10.0))
368 service.setName("%s (%3.1f" + _("E") + ")" % (str, orbpos / 10.0))
369 self.servicelist.addService(service)
370 self.servicelist.finishFill()
372 def showProviders(self):
373 ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
376 def showFavourites(self):
377 self.setRoot(self.bouquet_root)
379 def keyNumberGlobal(self, number):
380 char = self.numericalTextInput.getKey(number)
381 print "You pressed number " + str(number)
382 print "You would go to character " + str(char)
383 self.servicelist.moveToChar(char)
385 def enterBouquet(self, action):
386 if action[:7] == "bouquet":
387 if action.find("FROM BOUQUET") != -1:
388 self.setRoot(eServiceReference("1:7:1:0:0:0:0:0:0:0:" + action[8:]))
390 self.setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:]))
395 return self.servicelist.getRoot()
397 def getCurrentSelection(self):
398 return self.servicelist.getCurrent()
400 def setCurrentSelection(self, service):
401 self.servicelist.setCurrent(service)
406 def getBouquetList(self):
409 serviceHandler = eServiceCenter.getInstance()
410 list = serviceHandler.list(self.bouquet_root)
416 if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
417 info = serviceHandler.info(s)
419 bouquets.append((info.getName(s), s))
422 if len(bouquets) == 0 and serviceCount > 0:
423 info = serviceHandler.info(self.bouquet_root)
425 bouquets.append((info.getName(self.bouquet_root), self.bouquet_root))
429 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
430 def __init__(self, session):
431 ChannelSelectionBase.__init__(self,session)
432 ChannelSelectionEdit.__init__(self)
434 #config for lastservice
435 config.tv = ConfigSubsection();
436 config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
437 config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
439 class ChannelActionMap(NumberActionMap):
440 def action(self, contexts, action):
441 if not self.csel.enterBouquet(action):
442 if action == "cancel":
443 self.csel.handleEditCancel()
444 NumberActionMap.action(self, contexts, action)
445 self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions"],
447 "cancel": self.cancel,
448 "ok": self.channelSelected,
450 "contextMenu": self.doContext,
451 "showFavourites": self.showFavourites,
452 "showAllServices": self.showAllServices,
453 "showProviders": self.showProviders,
454 "showSatellites": self.showSatellites,
455 "showEPGList": self.showEPGList,
456 "1": self.keyNumberGlobal,
457 "2": self.keyNumberGlobal,
458 "3": self.keyNumberGlobal,
459 "4": self.keyNumberGlobal,
460 "5": self.keyNumberGlobal,
461 "6": self.keyNumberGlobal,
462 "7": self.keyNumberGlobal,
463 "8": self.keyNumberGlobal,
464 "9": self.keyNumberGlobal,
465 "0": self.keyNumberGlobal
467 self["actions"].csel = self
468 self.onShown.append(self.onShow)
470 self.lastChannelRootTimer = eTimer()
471 self.lastChannelRootTimer.timeout.get().append(self.onCreate)
472 self.lastChannelRootTimer.start(100,True)
476 lastroot=eServiceReference(config.tv.lastroot.value)
478 self.setRoot(lastroot)
480 self.showFavourites()
481 self.saveRoot(self.getRoot())
483 lastservice=eServiceReference(config.tv.lastservice.value)
484 if lastservice.valid():
485 self.servicelist.setCurrent(lastservice)
486 self.session.nav.playService(lastservice)
489 ref = self.session.nav.getCurrentlyPlayingServiceReference()
490 if ref is not None and ref.valid() and ref.getPath() == "":
491 self.servicelist.setPlayableIgnoreService(ref)
493 self.servicelist.setPlayableIgnoreService(eServiceReference())
495 def showEPGList(self):
496 ref=self.getCurrentSelection()
497 ptr=eEPGCache.getInstance()
498 if ptr.startTimeQuery(ref) != -1:
499 self.session.open(EPGSelection, ref)
501 print 'no epg for service', ref.toString()
503 def channelSelected(self):
504 ref = self.getCurrentSelection()
506 self.toggleMoveMarked()
507 elif (ref.flags & 7) == 7:
509 elif self.bouquet_mark_edit:
515 def setRoot(self, root, justSet=False):
516 if not self.movemode:
517 self.setRootBase(root, justSet)
519 #called from infoBar and channelSelected
521 self.session.nav.playService(self.getCurrentSelection())
522 self.saveRoot(self.getRoot())
525 def saveRoot(self, root):
527 config.tv.lastroot.value = root.toString()
528 config.tv.lastroot.save()
530 def saveChannel(self):
531 ref = self.session.nav.getCurrentlyPlayingServiceReference()
533 refstr = ref.toString()
536 config.tv.lastservice.value = refstr
537 config.tv.lastservice.save()
541 lastroot=eServiceReference(config.tv.lastroot.value)
542 lastservice=eServiceReference(config.tv.lastservice.value)
543 if lastroot.valid() and self.getRoot() != lastroot:
544 self.setRoot(lastroot)
545 if lastservice.valid() and self.getCurrentSelection() != lastservice:
546 self.servicelist.setCurrent(lastservice)
548 class ServiceInfoWindow(Screen):
549 def __init__(self, session):
550 Screen.__init__(self, session)
551 self["Service_Name"] = ServiceName(self.session.nav)
552 self["Clock"] = Clock()
553 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
554 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
555 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
556 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
557 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
558 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
560 class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit):
561 def __init__(self, session):
562 ChannelSelectionBase.__init__(self, session)
563 ChannelSelectionEdit.__init__(self)
565 config.radio = ConfigSubsection();
566 config.radio.lastservice = configElement("config.radio.lastservice", configText, "", 0);
567 config.radio.lastroot = configElement("config.radio.lastroot", configText, "", 0);
568 self.onLayoutFinish.append(self.onCreate)
570 self.info = session.instantiateDialog(ServiceInfoWindow)
572 class ChannelActionMap(NumberActionMap):
573 def action(self, contexts, action):
574 if not self.csel.enterBouquet(action):
575 NumberActionMap.action(self, contexts, action)
576 self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions", "TvRadioActions"],
578 "keyTV": self.closeRadio,
579 "keyRadio": self.closeRadio,
580 "contextMenu": self.doContext,
581 "cancel": self.closeRadio,
582 "ok": self.channelSelected,
583 "showFavourites": self.showFavourites,
584 "showAllServices": self.showAllServices,
585 "showProviders": self.showProviders,
586 "showSatellites": self.showSatellites,
587 "1": self.keyNumberGlobal,
588 "2": self.keyNumberGlobal,
589 "3": self.keyNumberGlobal,
590 "4": self.keyNumberGlobal,
591 "5": self.keyNumberGlobal,
592 "6": self.keyNumberGlobal,
593 "7": self.keyNumberGlobal,
594 "8": self.keyNumberGlobal,
595 "9": self.keyNumberGlobal,
596 "0": self.keyNumberGlobal
598 self["actions"].csel = self
602 lastroot=eServiceReference(config.radio.lastroot.value)
604 self.setRoot(lastroot)
606 self.showFavourites()
607 self.saveRoot(self.getRoot())
608 lastservice=eServiceReference(config.radio.lastservice.value)
609 if lastservice.valid():
610 self.servicelist.setCurrent(lastservice)
611 self.session.nav.playService(lastservice)
612 self.servicelist.setPlayableIgnoreService(lastservice)
613 self.info.instance.show()
615 def channelSelected(self): # just return selected service
616 ref = self.getCurrentSelection()
618 self.toggleMoveMarked()
619 elif (ref.flags & 7) == 7:
621 elif self.bouquet_mark_edit:
624 self.session.nav.playService(ref)
625 self.servicelist.setPlayableIgnoreService(ref)
626 config.radio.lastservice.value = ref.toString()
627 config.radio.lastservice.save()
628 config.radio.lastroot.value = self.getRoot().toString()
629 config.radio.lastroot.save()
631 def setRoot(self, root, justSet=False):
632 self.setRootBase(root, justSet)
634 def closeRadio(self):
635 self.info.instance.hide()
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()