Merge branch 'master' of https://github.com/OpenPLi/enigma2
[openblackhole/openblackhole-enigma2.git] / lib / python / Screens / InfoBar.py
1 from Tools.Profile import profile
2 from Tools.BoundFunction import boundFunction
3 from enigma import eServiceReference
4
5 # workaround for required config entry dependencies.
6 import Screens.MovieSelection
7
8 from Screen import Screen
9 from Screens.MessageBox import MessageBox
10
11 profile("LOAD:enigma")
12 import enigma
13
14 profile("LOAD:InfoBarGenerics")
15 from Screens.InfoBarGenerics import InfoBarShowHide, \
16         InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarRdsDecoder, \
17         InfoBarEPG, InfoBarSeek, InfoBarInstantRecord, InfoBarRedButton, InfoBarTimerButton, InfoBarVmodeButton, \
18         InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarUnhandledKey, \
19         InfoBarSubserviceSelection, InfoBarShowMovies, InfoBarTimeshift,  \
20         InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarBuffer, \
21         InfoBarSummarySupport, InfoBarMoviePlayerSummarySupport, InfoBarTimeshiftState, InfoBarTeletextPlugin, InfoBarExtensions, \
22         InfoBarSubtitleSupport, InfoBarPiP, InfoBarPlugins, InfoBarServiceErrorPopupSupport, InfoBarJobman, InfoBarPowersaver, \
23         InfoBarHDMI, setResumePoint, delResumePoint
24 from Screens.Hotkey import InfoBarHotkey
25
26 profile("LOAD:InitBar_Components")
27 from Components.ActionMap import HelpableActionMap
28 from Components.config import config
29 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
30
31 profile("LOAD:HelpableScreen")
32 from Screens.HelpMenu import HelpableScreen
33
34 from Screens.BpBlue import DeliteBp
35 from Screens.BpGreen import DeliteGp
36
37 class InfoBar(InfoBarBase, InfoBarShowHide,
38         InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRdsDecoder, DeliteBp, DeliteGp,
39         InfoBarInstantRecord, InfoBarAudioSelection, InfoBarRedButton, InfoBarTimerButton, InfoBarVmodeButton,
40         HelpableScreen, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarUnhandledKey,
41         InfoBarSubserviceSelection, InfoBarTimeshift, InfoBarSeek, InfoBarCueSheetSupport, InfoBarBuffer,
42         InfoBarSummarySupport, InfoBarTimeshiftState, InfoBarTeletextPlugin, InfoBarExtensions,
43         InfoBarPiP, InfoBarPlugins, InfoBarSubtitleSupport, InfoBarServiceErrorPopupSupport, InfoBarJobman, InfoBarPowersaver,
44         InfoBarHDMI, InfoBarHotkey, Screen):
45
46         ALLOW_SUSPEND = True
47         instance = None
48
49         def __init__(self, session):
50                 Screen.__init__(self, session)
51                 self["actions"] = HelpableActionMap(self, "InfobarActions",
52                         {
53                                 "showMovies": (self.showMovies, _("Play recorded movies...")),
54                                 "showRadio": (self.showRadio, _("Show the radio player...")),
55                                 "showTv": (self.showTv, _("Show the tv player...")),
56                         }, prio=2)
57
58                 self.allowPiP = True
59
60                 for x in HelpableScreen, \
61                                 InfoBarBase, InfoBarShowHide, \
62                                 InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRdsDecoder,  DeliteBp, DeliteGp, \
63                                 InfoBarInstantRecord, InfoBarAudioSelection, InfoBarRedButton, InfoBarTimerButton, InfoBarUnhandledKey, InfoBarVmodeButton,\
64                                 InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarSubserviceSelection, InfoBarBuffer, \
65                                 InfoBarTimeshift, InfoBarSeek, InfoBarCueSheetSupport, InfoBarSummarySupport, InfoBarTimeshiftState, \
66                                 InfoBarTeletextPlugin, InfoBarExtensions, InfoBarPiP, InfoBarSubtitleSupport, InfoBarJobman, InfoBarPowersaver, \
67                                 InfoBarPlugins, InfoBarServiceErrorPopupSupport, InfoBarHotkey:
68                         x.__init__(self)
69
70                 self.helpList.append((self["actions"], "InfobarActions", [("showMovies", _("Watch recordings..."))]))
71                 self.helpList.append((self["actions"], "InfobarActions", [("showRadio", _("Listen to the radio..."))]))
72
73                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
74                         {
75                                 enigma.iPlayableService.evUpdatedEventInfo: self.__eventInfoChanged
76                         })
77
78                 self.current_begin_time=0
79                 assert InfoBar.instance is None, "class InfoBar is a singleton class and just one instance of this class is allowed!"
80                 InfoBar.instance = self
81
82         def __onClose(self):
83                 InfoBar.instance = None
84
85         def __eventInfoChanged(self):
86                 if self.execing:
87                         service = self.session.nav.getCurrentService()
88                         old_begin_time = self.current_begin_time
89                         info = service and service.info()
90                         ptr = info and info.getEvent(0)
91                         self.current_begin_time = ptr and ptr.getBeginTime() or 0
92                         if config.usage.show_infobar_on_event_change.value:
93                                 if old_begin_time and old_begin_time != self.current_begin_time:
94                                         self.doShow()
95
96         def __checkServiceStarted(self):
97                 self.__serviceStarted(True)
98                 self.onExecBegin.remove(self.__checkServiceStarted)
99
100         def serviceStarted(self):  #override from InfoBarShowHide
101                 new = self.servicelist.newServicePlayed()
102                 if self.execing:
103                         InfoBarShowHide.serviceStarted(self)
104                         self.current_begin_time=0
105                 elif not self.__checkServiceStarted in self.onShown and new:
106                         self.onShown.append(self.__checkServiceStarted)
107
108         def __checkServiceStarted(self):
109                 self.serviceStarted()
110                 self.onShown.remove(self.__checkServiceStarted)
111
112         def showTv(self):
113                 self.showTvChannelList(True)
114
115         def showRadio(self):
116                 if config.usage.e1like_radio_mode.value:
117                         self.showRadioChannelList(True)
118                 else:
119                         self.rds_display.hide() # in InfoBarRdsDecoder
120                         from Screens.ChannelSelection import ChannelSelectionRadio
121                         self.session.openWithCallback(self.ChannelSelectionRadioClosed, ChannelSelectionRadio, self)
122
123         def ChannelSelectionRadioClosed(self, *arg):
124                 self.rds_display.show()  # in InfoBarRdsDecoder
125                 self.servicelist.correctChannelNumber()
126
127         def showMovies(self, defaultRef=None):
128                 self.lastservice = self.session.nav.getCurrentlyPlayingServiceOrGroup()
129                 self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, defaultRef or eServiceReference(config.usage.last_movie_played.value), timeshiftEnabled = self.timeshiftEnabled())
130
131         def movieSelected(self, service):
132                 ref = self.lastservice
133                 del self.lastservice
134                 if service is None:
135                         if ref and not self.session.nav.getCurrentlyPlayingServiceOrGroup():
136                                 self.session.nav.playService(ref)
137                 else:
138                         from Components.ParentalControl import parentalControl
139                         if parentalControl.isServicePlayable(service, self.openMoviePlayer):
140                                 self.openMoviePlayer(service)
141
142         def openMoviePlayer(self, ref):
143                 self.session.open(MoviePlayer, ref, slist=self.servicelist, lastservice=self.session.nav.getCurrentlyPlayingServiceOrGroup(), infobar=self)
144
145 class MoviePlayer(InfoBarBase, InfoBarShowHide, InfoBarMenu, InfoBarSeek, InfoBarShowMovies, InfoBarInstantRecord,
146                 InfoBarAudioSelection, HelpableScreen, InfoBarNotifications, InfoBarServiceNotifications, InfoBarPVRState,
147                 InfoBarCueSheetSupport, InfoBarMoviePlayerSummarySupport, InfoBarSubtitleSupport, Screen, InfoBarTeletextPlugin,
148                 InfoBarServiceErrorPopupSupport, InfoBarExtensions, InfoBarPlugins, InfoBarPiP, InfoBarHDMI, InfoBarHotkey):
149
150         ENABLE_RESUME_SUPPORT = True
151         ALLOW_SUSPEND = True
152
153         def __init__(self, session, service, slist=None, lastservice=None, infobar=None):
154                 Screen.__init__(self, session)
155
156                 self["actions"] = HelpableActionMap(self, "MoviePlayerActions",
157                         {
158                                 "leavePlayer": (self.leavePlayer, _("leave movie player...")),
159                                 "leavePlayerOnExit": (self.leavePlayerOnExit, _("leave movie player...")),
160                                 "channelUp": (self.channelUp, _("when PiPzap enabled zap channel up...")),
161                                 "channelDown": (self.channelDown, _("when PiPzap enabled zap channel down...")),
162                         })
163
164                 self["DirectionActions"] = HelpableActionMap(self, "DirectionActions",
165                         {
166                                 "left": self.left,
167                                 "right": self.right
168                         }, prio = -2)
169
170                 self.allowPiP = True
171
172                 for x in HelpableScreen, InfoBarShowHide, InfoBarMenu, \
173                                 InfoBarBase, InfoBarSeek, InfoBarShowMovies, InfoBarInstantRecord, \
174                                 InfoBarAudioSelection, InfoBarNotifications, \
175                                 InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, \
176                                 InfoBarMoviePlayerSummarySupport, InfoBarSubtitleSupport, \
177                                 InfoBarTeletextPlugin, InfoBarServiceErrorPopupSupport, InfoBarExtensions, \
178                                 InfoBarPlugins, InfoBarPiP, InfoBarHotkey:
179                         x.__init__(self)
180
181                 self.servicelist = slist
182                 self.infobar = infobar
183                 self.lastservice = lastservice or session.nav.getCurrentlyPlayingServiceOrGroup()
184                 session.nav.playService(service)
185                 self.cur_service = service
186                 self.returning = False
187                 self.onClose.append(self.__onClose)
188                 config.misc.standbyCounter.addNotifier(self.standbyCountChanged, initial_call=False)
189
190         def __onClose(self):
191                 config.misc.standbyCounter.removeNotifier(self.standbyCountChanged)
192                 from Screens.MovieSelection import playlist
193                 del playlist[:]
194                 if not config.movielist.stop_service.value:
195                         Screens.InfoBar.InfoBar.instance.callServiceStarted()
196                 self.session.nav.playService(self.lastservice)
197                 config.usage.last_movie_played.value = self.cur_service.toString()
198                 config.usage.last_movie_played.save()
199
200         def standbyCountChanged(self, value):
201                 if config.ParentalControl.servicepinactive.value:
202                         from Components.ParentalControl import parentalControl
203                         if parentalControl.isProtected(self.cur_service):
204                                 self.close()
205
206         def handleLeave(self, how):
207                 self.is_closing = True
208                 if how == "ask":
209                         if config.usage.setup_level.index < 2: # -expert
210                                 list = (
211                                         (_("Yes"), "quit"),
212                                         (_("No"), "continue")
213                                 )
214                         else:
215                                 list = (
216                                         (_("Yes"), "quit"),
217                                         (_("Yes, returning to movie list"), "movielist"),
218                                         (_("Yes, and delete this movie"), "quitanddelete"),
219                                         (_("Yes, delete this movie and return to movie list"), "deleteandmovielist"),
220                                         (_("No"), "continue"),
221                                         (_("No, but restart from begin"), "restart")
222                                 )
223
224                         from Screens.ChoiceBox import ChoiceBox
225                         self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Stop playing this movie?"), list = list)
226                 else:
227                         self.leavePlayerConfirmed([True, how])
228
229         def leavePlayer(self):
230                 setResumePoint(self.session)
231                 self.handleLeave(config.usage.on_movie_stop.value)
232
233         def leavePlayerOnExit(self):
234                 if self.shown:
235                         self.hide()
236                 elif self.session.pipshown and "popup" in config.usage.pip_hideOnExit.value:
237                         if config.usage.pip_hideOnExit.value == "popup":
238                                 self.session.openWithCallback(self.hidePipOnExitCallback, MessageBox, _("Disable Picture in Picture"), simple=True)
239                         else:
240                                 self.hidePipOnExitCallback(True)
241                 elif config.usage.leave_movieplayer_onExit.value == "movielist":
242                         self.leavePlayer()
243                 elif config.usage.leave_movieplayer_onExit.value == "popup":
244                         self.session.openWithCallback(self.leavePlayerOnExitCallback, MessageBox, _("Exit movie player?"), simple=True)
245                 elif config.usage.leave_movieplayer_onExit.value == "without popup":
246                         self.leavePlayerOnExitCallback(True)
247
248         def leavePlayerOnExitCallback(self, answer):
249                 if answer == True:
250                         setResumePoint(self.session)
251                         self.handleLeave("quit")
252
253         def hidePipOnExitCallback(self, answer):
254                 if answer == True:
255                         self.showPiP()
256
257         def deleteConfirmed(self, answer):
258                 if answer:
259                         self.leavePlayerConfirmed((True, "quitanddeleteconfirmed"))
260
261         def deleteAndMovielistConfirmed(self, answer):
262                 if answer:
263                         self.leavePlayerConfirmed((True, "deleteandmovielistconfirmed"))
264
265         def movielistAgain(self):
266                 from Screens.MovieSelection import playlist
267                 del playlist[:]
268                 self.leavePlayerConfirmed((True, "movielist"))
269
270         def leavePlayerConfirmed(self, answer):
271                 answer = answer and answer[1]
272                 if answer is None:
273                         return
274                 if answer in ("quitanddelete", "quitanddeleteconfirmed", "deleteandmovielist", "deleteandmovielistconfirmed"):
275                         ref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
276                         serviceHandler = enigma.eServiceCenter.getInstance()
277                         if answer in ("quitanddelete", "deleteandmovielist"):
278                                 msg = ''
279                                 if config.usage.movielist_trashcan.value:
280                                         import Tools.Trashcan
281                                         try:
282                                                 trash = Tools.Trashcan.createTrashFolder(ref.getPath())
283                                                 Screens.MovieSelection.moveServiceFiles(ref, trash)
284                                                 # Moved to trash, okay
285                                                 if answer == "quitanddelete":
286                                                         self.close()
287                                                 else:
288                                                         self.movielistAgain()
289                                                 return
290                                         except Exception, e:
291                                                 print "[InfoBar] Failed to move to .Trash folder:", e
292                                                 msg = _("Cannot move to trash can") + "\n" + str(e) + "\n"
293                                 info = serviceHandler.info(ref)
294                                 name = info and info.getName(ref) or _("this recording")
295                                 msg += _("Do you really want to delete %s?") % name
296                                 if answer == "quitanddelete":
297                                         self.session.openWithCallback(self.deleteConfirmed, MessageBox, msg)
298                                 elif answer == "deleteandmovielist":
299                                         self.session.openWithCallback(self.deleteAndMovielistConfirmed, MessageBox, msg)
300                                 return
301
302                         elif answer in ("quitanddeleteconfirmed", "deleteandmovielistconfirmed"):
303                                 offline = serviceHandler.offlineOperations(ref)
304                                 if offline.deleteFromDisk(0):
305                                         self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR)
306                                         if answer == "deleteandmovielistconfirmed":
307                                                 self.movielistAgain()
308                                         return
309
310                 if answer in ("quit", "quitanddeleteconfirmed"):
311                         self.close()
312                 elif answer in ("movielist", "deleteandmovielistconfirmed"):
313                         ref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
314                         self.returning = True
315                         self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, ref)
316                         self.session.nav.stopService()
317                         if not config.movielist.stop_service.value:
318                                 self.session.nav.playService(self.lastservice)
319                 elif answer == "restart":
320                         self.doSeek(0)
321                         self.setSeekState(self.SEEK_STATE_PLAY)
322                 elif answer in ("playlist","playlistquit","loop"):
323                         ( next_service, item , lenght ) = self.getPlaylistServiceInfo(self.cur_service)
324                         if next_service is not None:
325                                 if config.usage.next_movie_msg.value:
326                                         self.displayPlayedName(next_service, item, lenght)
327                                 self.session.nav.playService(next_service)
328                                 self.cur_service = next_service
329                         else:
330                                 if answer == "playlist":
331                                         self.leavePlayerConfirmed([True,"movielist"])
332                                 elif answer == "loop" and lenght > 0:
333                                         self.leavePlayerConfirmed([True,"loop"])
334                                 else:
335                                         self.leavePlayerConfirmed([True,"quit"])
336                 elif answer in ("repeatcurrent"):
337                         if config.usage.next_movie_msg.value:
338                                 (item, lenght) = self.getPlaylistServiceInfo(self.cur_service)
339                                 self.displayPlayedName(self.cur_service, item, lenght)
340                         self.session.nav.stopService()
341                         self.session.nav.playService(self.cur_service)
342
343         def doEofInternal(self, playing):
344                 if not self.execing:
345                         return
346                 if not playing :
347                         return
348                 ref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
349                 if ref:
350                         delResumePoint(ref)
351                 self.handleLeave(config.usage.on_movie_eof.value)
352
353         def up(self):
354                 if self.servicelist and self.servicelist.dopipzap:
355                         if config.usage.oldstyle_zap_controls.value:
356                                 self.zapDown()
357                         else:
358                                 self.switchChannelUp()
359                 else:
360                         self.showMovies()
361
362         def down(self):
363                 if self.servicelist and self.servicelist.dopipzap:
364                         if config.usage.oldstyle_zap_controls.value:
365                                 self.zapUp()
366                         else:
367                                 self.switchChannelDown()
368                 else:
369                         self.showMovies()
370
371         def right(self):
372                 if self.servicelist and self.servicelist.dopipzap:
373                         if config.usage.oldstyle_zap_controls.value:
374                                 self.switchChannelDown()
375                         else:
376                                 self.zapDown()
377                 else:
378                         InfoBarSeek.seekFwd(self)
379
380         def left(self):
381                 if self.servicelist and self.servicelist.dopipzap:
382                         if config.usage.oldstyle_zap_controls.value:
383                                 self.switchChannelUp()
384                         else:
385                                 self.zapUp()
386                 else:
387                         InfoBarSeek.seekBack(self)
388
389         def channelUp(self):
390                 if config.usage.zap_with_ch_buttons.value and self.servicelist and self.servicelist.dopipzap:
391                         self.zapDown()
392                 else:
393                         return 0
394
395         def channelDown(self):
396                 if config.usage.zap_with_ch_buttons.value and self.servicelist and self.servicelist.dopipzap:
397                         self.zapUp()
398                 else:
399                         return 0
400
401         def switchChannelDown(self):
402                 if self.servicelist:
403                         if "keep" not in config.usage.servicelist_cursor_behavior.value:
404                                 self.servicelist.moveDown()
405                         self.session.execDialog(self.servicelist)
406
407         def switchChannelUp(self):
408                 if self.servicelist:
409                         if "keep" not in config.usage.servicelist_cursor_behavior.value:
410                                 self.servicelist.moveUp()
411                         self.session.execDialog(self.servicelist)
412
413         def zapUp(self):
414                 slist = self.servicelist
415                 if slist:
416                         if slist.inBouquet():
417                                 prev = slist.getCurrentSelection()
418                                 if prev:
419                                         prev = prev.toString()
420                                         while True:
421                                                 if config.usage.quickzap_bouquet_change.value:
422                                                         if slist.atBegin():
423                                                                 slist.prevBouquet()
424                                                 slist.moveUp()
425                                                 cur = slist.getCurrentSelection()
426                                                 if cur:
427                                                         playable = not (cur.flags & (64|8)) and hasattr(self.session, "pip") and self.session.pip.isPlayableForPipService(cur)
428                                                         if cur.toString() == prev or playable:
429                                                                 break
430                         else:
431                                 slist.moveUp()
432                         slist.zap(enable_pipzap = True)
433
434         def zapDown(self):
435                 slist = self.servicelist
436                 if slist:
437                         if slist.inBouquet():
438                                 prev = slist.getCurrentSelection()
439                                 if prev:
440                                         prev = prev.toString()
441                                         while True:
442                                                 if config.usage.quickzap_bouquet_change.value and slist.atEnd():
443                                                         slist.nextBouquet()
444                                                 else:
445                                                         slist.moveDown()
446                                                 cur = slist.getCurrentSelection()
447                                                 if cur:
448                                                         playable = not (cur.flags & (64|8)) and hasattr(self.session, "pip") and self.session.pip.isPlayableForPipService(cur)
449                                                         if cur.toString() == prev or playable:
450                                                                 break
451                         else:
452                                 slist.moveDown()
453                         slist.zap(enable_pipzap = True)
454
455         def showPiP(self):
456                 slist = self.servicelist
457                 if self.session.pipshown:
458                         if slist and slist.dopipzap:
459                                 slist.togglePipzap()
460                         if self.session.pipshown:
461                                 del self.session.pip
462                                 self.session.pipshown = False
463                 elif slist:
464                         from Screens.PictureInPicture import PictureInPicture
465                         self.session.pip = self.session.instantiateDialog(PictureInPicture)
466                         self.session.pip.show()
467                         if self.session.pip.playService(slist.getCurrentSelection()):
468                                 self.session.pipshown = True
469                                 self.session.pip.servicePath = slist.getCurrentServicePath()
470                         else:
471                                 self.session.pipshown = False
472                                 del self.session.pip
473
474         def movePiP(self):
475                 if self.session.pipshown:
476                         InfoBarPiP.movePiP(self)
477
478         def swapPiP(self):
479                 pass
480
481         def showDefaultEPG(self):
482                 self.infobar and self.infobar.showMultiEPG()
483
484         def openEventView(self):
485                 self.infobar and self.infobar.showDefaultEPG()
486
487         def showEventInfoPlugins(self):
488                 self.infobar and self.infobar.showEventInfoPlugins()
489
490         def showEventGuidePlugins(self):
491                 self.infobar and self.infobar.showEventGuidePlugins()
492
493         def openSingleServiceEPG(self):
494                 self.infobar and self.infobar.openSingleServiceEPG()
495
496         def openMultiServiceEPG(self):
497                 self.infobar and self.infobar.openMultiServiceEPG()
498
499         def showMovies(self):
500                 ref = self.session.nav.getCurrentlyPlayingServiceOrGroup()
501                 self.playingservice = ref # movie list may change the currently playing
502                 self.session.openWithCallback(self.movieSelected, Screens.MovieSelection.MovieSelection, ref)
503
504         def movieSelected(self, service):
505                 if service is not None:
506                         self.cur_service = service
507                         self.is_closing = False
508                         self.session.nav.playService(service)
509                         self.returning = False
510                 elif self.returning:
511                         self.close()
512                 else:
513                         self.is_closing = False
514                         ref = self.playingservice
515                         del self.playingservice
516                         # no selection? Continue where we left off
517                         if ref and not self.session.nav.getCurrentlyPlayingServiceOrGroup():
518                                 self.session.nav.playService(ref)
519
520         def getPlaylistServiceInfo(self, service):
521                 from MovieSelection import playlist
522                 for i, item in enumerate(playlist):
523                         if item == service:
524                                 if config.usage.on_movie_eof.value == "repeatcurrent":
525                                         return (i+1, len(playlist))
526                                 i += 1
527                                 if i < len(playlist):
528                                         return (playlist[i], i+1, len(playlist))
529                                 elif config.usage.on_movie_eof.value == "loop":
530                                         return (playlist[0], 1, len(playlist))
531                 return ( None, 0, 0 )
532
533         def displayPlayedName(self, ref, index, n):
534                 from Tools import Notifications
535                 Notifications.AddPopup(text = _("%s/%s: %s") % (index, n, self.ref2HumanName(ref)), type = MessageBox.TYPE_INFO, timeout = 5)
536
537         def ref2HumanName(self, ref):
538                 return enigma.eServiceCenter.getInstance().info(ref).getName(ref)