remove info info
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
1 from Screen import Screen
2 from Components.ActionMap import ActionMap, HelpableActionMap
3 from Components.ActionMap import NumberActionMap
4 from Components.Label import *
5 from Components.ProgressBar import *
6 from Components.config import configfile, configsequencearg
7 from Components.config import config, configElement, ConfigSubsection, configSequence
8 from ChannelSelection import ChannelSelection, BouquetSelector
9
10 from Components.Pixmap import Pixmap, PixmapConditional
11 from Components.BlinkingPixmap import BlinkingPixmapConditional
12 from Components.ServiceName import ServiceName
13 from Components.EventInfo import EventInfo
14
15 from ServiceReference import ServiceReference
16 from EpgSelection import EPGSelection
17
18 from Screens.MessageBox import MessageBox
19 from Screens.Volume import Volume
20 from Screens.Mute import Mute
21 from Screens.Dish import Dish
22 from Screens.Standby import Standby
23 from Screens.EventView import EventView
24 from Screens.MinuteInput import MinuteInput
25 from Components.Harddisk import harddiskmanager
26
27 from Tools import Notifications
28 from Tools.Directories import *
29
30 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
31 from enigma import *
32
33 import time
34 import os
35
36 # hack alert!
37 from Menu import MainMenu, mdom
38
39 class InfoBarVolumeControl:
40         """Volume control, handles volUp, volDown, volMute actions and display 
41         a corresponding dialog"""
42         def __init__(self):
43                 config.audio = ConfigSubsection()
44                 config.audio.volume = configElement("config.audio.volume", configSequence, [100], configsequencearg.get("INTEGER", (0, 100)))
45
46                 self["VolumeActions"] = ActionMap( ["InfobarVolumeActions"] ,
47                         {
48                                 "volumeUp": self.volUp,
49                                 "volumeDown": self.volDown,
50                                 "volumeMute": self.volMute,
51                         })
52
53                 self.volumeDialog = self.session.instantiateDialog(Volume)
54                 self.muteDialog = self.session.instantiateDialog(Mute)
55
56                 self.hideVolTimer = eTimer()
57                 self.hideVolTimer.timeout.get().append(self.volHide)
58
59                 vol = config.audio.volume.value[0]
60                 self.volumeDialog.setValue(vol)
61                 eDVBVolumecontrol.getInstance().setVolume(vol, vol)
62         
63         def volSave(self):
64                 config.audio.volume.value = eDVBVolumecontrol.getInstance().getVolume()
65                 config.audio.volume.save()
66                 
67         def     volUp(self):
68                 if (eDVBVolumecontrol.getInstance().isMuted()):
69                         self.volMute()
70                 eDVBVolumecontrol.getInstance().volumeUp()
71                 self.volumeDialog.instance.show()
72                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
73                 self.volSave()
74                 self.hideVolTimer.start(3000, True)
75
76         def     volDown(self):
77                 if (eDVBVolumecontrol.getInstance().isMuted()):
78                         self.volMute()
79                 eDVBVolumecontrol.getInstance().volumeDown()
80                 self.volumeDialog.instance.show()
81                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
82                 self.volSave()
83                 self.hideVolTimer.start(3000, True)
84                 
85         def volHide(self):
86                 self.volumeDialog.instance.hide()
87
88         def     volMute(self):
89                 eDVBVolumecontrol.getInstance().volumeToggleMute()
90                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
91                 
92                 if (eDVBVolumecontrol.getInstance().isMuted()):
93                         self.muteDialog.instance.show()
94                 else:
95                         self.muteDialog.instance.hide()
96
97 class InfoBarDish:
98         def __init__(self):
99                 self.dishDialog = self.session.instantiateDialog(Dish)
100                 self.onShown.append(self.dishDialog.instance.hide)
101
102 class InfoBarShowHide:
103         """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
104         fancy animations. """
105         STATE_HIDDEN = 0
106         STATE_HIDING = 1
107         STATE_SHOWING = 2
108         STATE_SHOWN = 3
109         
110         def __init__(self):
111                 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
112                         {
113                                 "toggleShow": self.toggleShow,
114                                 "hide": self.hide,
115                         })
116
117                 self.state = self.STATE_SHOWN
118                 
119                 self.onExecBegin.append(self.show)
120                 self.onClose.append(self.delHideTimer)
121                 
122                 self.hideTimer = eTimer()
123                 self.hideTimer.timeout.get().append(self.doTimerHide)
124                 self.hideTimer.start(5000, True)
125
126         def delHideTimer(self):
127                 del self.hideTimer
128
129         def hide(self): 
130                 self.instance.hide()
131                 
132         def show(self):
133                 self.state = self.STATE_SHOWN
134                 self.hideTimer.start(5000, True)
135
136         def doTimerHide(self):
137                 self.hideTimer.stop()
138                 if self.state == self.STATE_SHOWN:
139                         self.instance.hide()
140                         self.state = self.STATE_HIDDEN
141
142         def toggleShow(self):
143                 if self.state == self.STATE_SHOWN:
144                         self.instance.hide()
145                         #pls check animation support, sorry
146 #                       self.startHide()
147                         self.hideTimer.stop()
148                         self.state = self.STATE_HIDDEN
149                 elif self.state == self.STATE_HIDDEN:
150                         self.instance.show()
151                         self.show()
152                         
153         def startShow(self):
154                 self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
155                 self.state = self.STATE_SHOWN
156         
157         def startHide(self):
158                 self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
159                 self.state = self.STATE_HIDDEN
160
161 class NumberZap(Screen):
162         def quit(self):
163                 self.Timer.stop()
164                 self.close(0)
165
166         def keyOK(self):
167                 self.Timer.stop()
168                 self.close(int(self["number"].getText()))
169
170         def keyNumberGlobal(self, number):
171                 self.Timer.start(3000, True)            #reset timer
172                 self.field = self.field + str(number)
173                 self["number"].setText(self.field)
174                 if len(self.field) >= 4:
175                         self.keyOK()
176
177         def __init__(self, session, number):
178                 Screen.__init__(self, session)
179                 self.field = str(number)
180
181                 self["channel"] = Label(_("Channel:"))
182
183                 self["number"] = Label(self.field)
184
185                 self["actions"] = NumberActionMap( [ "SetupActions" ], 
186                         {
187                                 "cancel": self.quit,
188                                 "ok": self.keyOK,
189                                 "1": self.keyNumberGlobal,
190                                 "2": self.keyNumberGlobal,
191                                 "3": self.keyNumberGlobal,
192                                 "4": self.keyNumberGlobal,
193                                 "5": self.keyNumberGlobal,
194                                 "6": self.keyNumberGlobal,
195                                 "7": self.keyNumberGlobal,
196                                 "8": self.keyNumberGlobal,
197                                 "9": self.keyNumberGlobal,
198                                 "0": self.keyNumberGlobal
199                         })
200
201                 self.Timer = eTimer()
202                 self.Timer.timeout.get().append(self.keyOK)
203                 self.Timer.start(3000, True)
204
205 class InfoBarPowerKey:
206         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
207         
208         def __init__(self):
209                 self.powerKeyTimer = eTimer()
210                 self.powerKeyTimer.timeout.get().append(self.powertimer)
211                 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
212                         {
213                                 "powerdown": self.powerdown,
214                                 "powerup": self.powerup,
215                                 "discreteStandby": (self.standby, "Go standby"),
216                                 "discretePowerOff": (self.quit, "Go to deep standby"),
217                         })
218
219         def powertimer(self):   
220                 print "PowerOff - Now!"
221                 self.quit()
222         
223         def powerdown(self):
224                 self.standbyblocked = 0
225                 self.powerKeyTimer.start(3000, True)
226
227         def powerup(self):
228                 self.powerKeyTimer.stop()
229                 if self.standbyblocked == 0:
230                         self.standbyblocked = 1
231                         self.standby()
232
233         def standby(self):
234                 self.session.open(Standby, self)
235
236         def quit(self):
237                 # halt
238                 quitMainloop(1)
239
240 class InfoBarNumberZap:
241         """ Handles an initial number for NumberZapping """
242         def __init__(self):
243                 self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
244                         {
245                                 "1": self.keyNumberGlobal,
246                                 "2": self.keyNumberGlobal,
247                                 "3": self.keyNumberGlobal,
248                                 "4": self.keyNumberGlobal,
249                                 "5": self.keyNumberGlobal,
250                                 "6": self.keyNumberGlobal,
251                                 "7": self.keyNumberGlobal,
252                                 "8": self.keyNumberGlobal,
253                                 "9": self.keyNumberGlobal,
254                                 "0": self.keyNumberGlobal,
255                         })
256
257         def keyNumberGlobal(self, number):
258 #               print "You pressed number " + str(number)
259                 if number == 0:
260                         self.session.nav.zapLast()
261                         self.instance.show()
262                         self.show()
263                 else:
264                         self.session.openWithCallback(self.numberEntered, NumberZap, number)
265
266         def numberEntered(self, retval):
267 #               print self.servicelist
268                 if retval > 0:
269                         self.zapToNumber(retval)
270
271         def searchNumberHelper(self, serviceHandler, num, bouquet):
272                 servicelist = serviceHandler.list(bouquet)
273                 if not servicelist is None:
274                         while num:
275                                 serviceIterator = servicelist.getNext()
276                                 if not serviceIterator.valid(): #check end of list
277                                         break
278                                 if serviceIterator.flags: #assume normal dvb service have no flags set
279                                         continue
280                                 num -= 1;
281                         if not num: #found service with searched number ?
282                                 return serviceIterator, 0
283                 return None, num
284
285         def zapToNumber(self, number):
286                 bouquet = self.servicelist.bouquet_root
287                 service = None
288                 serviceHandler = eServiceCenter.getInstance()
289                 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
290                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
291                 else:
292                         bouquetlist = serviceHandler.list(bouquet)
293                         if not bouquetlist is None:
294                                 while number:
295                                         bouquet = self.servicelist.appendDVBTypes(bouquetlist.getNext())
296                                         if not bouquet.valid(): #check end of list
297                                                 break
298                                         if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
299                                                 continue
300                                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
301                 if not service is None:
302                         self.session.nav.playService(service) #play service
303                         if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
304                                 self.servicelist.setRoot(bouquet)
305                         self.servicelist.setCurrentSelection(service) #select the service in servicelist
306
307 class InfoBarChannelSelection:
308         """ ChannelSelection - handles the channelSelection dialog and the initial 
309         channelChange actions which open the channelSelection dialog """
310         def __init__(self):
311                 #instantiate forever
312                 self.servicelist = self.session.instantiateDialog(ChannelSelection)
313
314                 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
315                         {
316                                 "switchChannelUp": self.switchChannelUp,
317                                 "switchChannelDown": self.switchChannelDown,
318                                 "zapUp": (self.zapUp, _("next channel")),
319                                 "zapDown": (self.zapDown, _("previous channel")),
320                         })
321                         
322         def switchChannelUp(self):      
323                 self.servicelist.moveUp()
324                 self.session.execDialog(self.servicelist)
325
326         def switchChannelDown(self):    
327                 self.servicelist.moveDown()
328                 self.session.execDialog(self.servicelist)
329
330         def     zapUp(self):
331                 self.servicelist.moveUp()
332                 self.servicelist.zap()
333                 self.instance.show()
334                 self.show()
335
336         def     zapDown(self):
337                 self.servicelist.moveDown()
338                 self.servicelist.zap()
339                 self.instance.show()
340                 self.show()
341                 
342 class InfoBarMenu:
343         """ Handles a menu action, to open the (main) menu """
344         def __init__(self):
345                 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions", 
346                         {
347                                 "mainMenu": (self.mainMenu, "Enter main menu..."),
348                         })
349
350         def mainMenu(self):
351                 print "loading mainmenu XML..."
352                 menu = mdom.childNodes[0]
353                 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
354                 self.session.open(MainMenu, menu, menu.childNodes)
355
356 class InfoBarEPG:
357         """ EPG - Opens an EPG list when the showEPGList action fires """
358         def __init__(self):
359                 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
360                         {
361                                 "showEPGList": (self.showEPGList, _("show EPG...")),
362                         })
363
364         def showEPGList(self):
365                 bouquets = self.servicelist.getBouquetList()
366                 if bouquets is None:
367                         cnt = 0
368                 else:
369                         cnt = len(bouquets)
370                 if cnt > 1: # show bouquet list
371                         self.session.open(BouquetSelector, bouquets, self.openBouquetEPG)
372                 elif cnt == 1: # add to only one existing bouquet
373                         self.openBouquetEPG(bouquets[0][1])
374                 else: #no bouquets so we open single epg
375                         self.openSingleEPGSelector(self.session.nav.getCurrentlyPlayingServiceReference())
376
377         def bouquetEPGCallback(self, info):
378                 if info:
379                         self.openSingleServiceEPG()
380         
381         def singleEPGCallback(self, info):
382                 if info:
383                         self.showEPGList()
384                         
385         def openEventView(self):
386                 try:
387                         self.epglist = [ ]
388                         service = self.session.nav.getCurrentService()
389                         info = service.info()
390                         ptr=info.getEvent(0)
391                         if ptr:
392                                 self.epglist.append(ptr)
393                         ptr=info.getEvent(1)
394                         if ptr:
395                                 self.epglist.append(ptr)
396                         if len(self.epglist) > 0:
397                                 self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
398                 except:
399                         pass
400                         
401         def openSingleServiceEPG(self):
402                 ref=self.session.nav.getCurrentlyPlayingServiceReference()
403                 ptr=eEPGCache.getInstance()
404                 if ptr.startTimeQuery(ref) != -1:
405                         self.session.openWithCallback(self.singleEPGCallback, EPGSelection, ref)
406                 else: # try to show now/next
407                         print 'no epg for service', ref.toString()
408
409         
410         def openBouquetEPG(self, bouquet):
411                 ptr=eEPGCache.getInstance()
412                 services = [ ]
413                 servicelist = eServiceCenter.getInstance().list(bouquet)
414                 if not servicelist is None:
415                         while True:
416                                 service = servicelist.getNext()
417                                 if not service.valid(): #check if end of list
418                                         break
419                                 if service.flags: #ignore non playable services
420                                         continue
421                                 services.append(ServiceReference(service))
422                 if len(services):
423                         self.session.openWithCallback(self.bouquetEPGCallback, EPGSelection, services)
424
425         def openSingleEPGSelector(self, ref):
426                 ptr=eEPGCache.getInstance()
427                 if ptr.startTimeQuery(ref) != -1:
428                         self.session.open(EPGSelection, ref)
429                 else: # try to show now/next
430                         print 'no epg for service', ref.toString()
431                         try:
432                                 self.epglist = [ ]
433                                 service = self.session.nav.getCurrentService()
434                                 info = service.info()
435                                 ptr=info.getEvent(0)
436                                 if ptr:
437                                         self.epglist.append(ptr)
438                                 ptr=info.getEvent(1)
439                                 if ptr:
440                                         self.epglist.append(ptr)
441                                 if len(self.epglist) > 0:
442                                         self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
443                         except:
444                                 pass
445
446         def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
447                 if len(self.epglist) > 1:
448                         tmp = self.epglist[0]
449                         self.epglist[0]=self.epglist[1]
450                         self.epglist[1]=tmp
451                         setEvent(self.epglist[0])
452
453 from math import log
454
455 class InfoBarTuner:
456         """provides a snr/agc/ber display"""
457         def __init__(self):
458                 self["snr"] = Label()
459                 self["agc"] = Label()
460                 self["ber"] = Label()
461                 self["snr_percent"] = Label()
462                 self["agc_percent"] = Label()
463                 self["ber_count"] = Label()
464                 self["snr_progress"] = ProgressBar()
465                 self["agc_progress"] = ProgressBar()
466                 self["ber_progress"] = ProgressBar()
467                 self.timer = eTimer()
468                 self.timer.timeout.get().append(self.updateTunerInfo)
469                 self.timer.start(1000)
470
471         def calc(self,val):
472                 if not val:
473                         return 0
474                 if val < 2500:
475                         return (long)(log(val)/log(2))
476                 return val*100/65535
477
478         def updateTunerInfo(self):
479                 if self.instance.isVisible():
480                         service = self.session.nav.getCurrentService()
481                         snr=0
482                         agc=0
483                         ber=0
484                         if service is not None:
485                                 feinfo = service.frontendStatusInfo()
486                                 if feinfo is not None:
487                                         ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
488                                         snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
489                                         agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
490                         self["snr_percent"].setText("%d%%"%(snr))
491                         self["agc_percent"].setText("%d%%"%(agc))
492                         self["ber_count"].setText("%d"%(ber))
493                         self["snr_progress"].setValue(snr)
494                         self["agc_progress"].setValue(agc)
495                         self["ber_progress"].setValue(self.calc(ber))
496
497 class InfoBarEvent:
498         """provides a current/next event info display"""
499         def __init__(self):
500                 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
501                 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
502                                 
503                 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
504                 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
505
506                 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
507                 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
508
509 class InfoBarServiceName:
510         def __init__(self):
511                 self["ServiceName"] = ServiceName(self.session.nav)
512
513 class InfoBarPVR:
514
515         # ispause, isff, issm, skip
516         SEEK_STATE_PLAY = (0, 0, 0, 0)
517         SEEK_STATE_PAUSE = (1, 0, 0, 0)
518         SEEK_STATE_FF_2X = (0, 2, 0, 0)
519         SEEK_STATE_FF_4X = (0, 4, 0, 0)
520         SEEK_STATE_FF_8X = (0, 8, 0, 0)
521         SEEK_STATE_FF_32X = (0, 4, 0, 32)
522         SEEK_STATE_FF_64X = (0, 4, 0, 64)
523         SEEK_STATE_FF_128X = (0, 4, 0, 128)
524         
525         SEEK_STATE_BACK_4X = (0, 0, 0, -4)
526         SEEK_STATE_BACK_32X = (0, 0, 0, -32)
527         SEEK_STATE_BACK_64X = (0, 0, 0, -64)
528         SEEK_STATE_BACK_128X = (0, 0, 0, -128)
529         
530         SEEK_STATE_SM_HALF = (0, 0, 2, 0)
531         SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
532         SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
533         
534         """handles PVR specific actions like seeking, pause"""
535         def __init__(self):
536                 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions", 
537                         {
538                                 "pauseService": (self.pauseService, "pause"),
539                                 "unPauseService": (self.unPauseService, "continue"),
540                                 
541                                 "seekFwd": (self.seekFwd, "skip forward"),
542                                 "seekFwdUp": (self.seekFwdUp, "skip forward"),
543                                 "seekBack": (self.seekBack, "skip backward"),
544                                 "seekBackUp": (self.seekBackUp, "skip backward"),
545                                                          
546                                 "up": (self.showMovies, "movie list"),
547                                 "down": (self.showMovies, "movie list")
548                         })
549
550                 self.seekstate = self.SEEK_STATE_PLAY
551                 self.seekTimer = eTimer()
552                 self.seekTimer.timeout.get().append(self.seekTimerFired)
553                 self.skipinterval = 500 # 500ms skip interval
554                 self.onClose.append(self.delSeekTimer)
555                 
556                 self.fwdtimer = False
557                 self.fwdKeyTimer = eTimer()
558                 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
559
560                 self.rwdtimer = False
561                 self.rwdKeyTimer = eTimer()
562                 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
563         
564         def up(self):
565                 pass
566         
567         def down(self):
568                 pass
569         
570         def delSeekTimer(self):
571                 del self.seekTimer
572         
573         def seekTimerFired(self):
574                 self.seekbase += self.skipmode * self.skipinterval
575                 
576                 # check if we bounced against the beginning of the file
577                 if self.seekbase < 0:
578                         self.seekbase = 0;
579                         self.setSeekState(self.SEEK_STATE_PLAY)
580                         
581                 self.doSeek(self.seekbase)
582
583         def setSeekState(self, state):
584                 oldstate = self.seekstate
585                 
586                 self.seekstate = state
587
588                 service = self.session.nav.getCurrentService()
589                 if service is None:
590                         return
591                 
592                 pauseable = service.pause()
593                 
594                 for i in range(4):
595                         if oldstate[i] != self.seekstate[i]:
596                                 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
597                 
598         def setSkipMode(self, skipmode):
599                 self.skipmode = skipmode
600                 if skipmode == 0:
601                         self.seekTimer.stop()
602                 else:
603                         self.seekTimer.start(500)
604                 
605                 service = self.session.nav.getCurrentService()
606                 if service is None:
607                         return
608                 
609                 seekable = service.seek()
610                 if seekable is None:
611                         return
612
613                 if skipmode:
614                         seekable.setTrickmode(1)
615                 else:
616                         seekable.setTrickmode(0)
617                 
618                 self.seekbase = seekable.getPlayPosition()[1] / 90
619         
620         def pauseService(self):
621                 if (self.seekstate == self.SEEK_STATE_PAUSE):
622                         self.unPauseService()
623                 else:
624                         self.setSeekState(self.SEEK_STATE_PAUSE);
625                 
626         def unPauseService(self):
627                 self.setSeekState(self.SEEK_STATE_PLAY);
628         
629         def doSeek(self, seektime):
630                 service = self.session.nav.getCurrentService()
631                 if service is None:
632                         return
633                 
634                 seekable = service.seek()
635                 if seekable is None:
636                         return
637                 seekable.seekTo(90 * seektime)
638
639         def seekFwd(self):
640                 print "start fwd timer"
641                 self.fwdtimer = True
642                 self.fwdKeyTimer.start(500)
643
644         def seekBack(self):
645                 print "start rewind timer"
646                 self.rwdtimer = True
647                 self.rwdKeyTimer.start(500)
648
649         def seekFwdUp(self):
650                 if self.fwdtimer:
651                         self.fwdKeyTimer.stop()
652                         self.fwdtimer = False
653                         lookup = {
654                                         self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
655                                         self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
656                                         self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
657                                         self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
658                                         self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
659                                         self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
660                                         self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
661                                         self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
662                                         self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
663                                         self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
664                                         self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
665                                         self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
666                                         self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
667                                         self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
668                                         self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
669                                 }
670                         self.setSeekState(lookup[self.seekstate]);
671         
672         def seekBackUp(self):
673                 if self.rwdtimer:
674                         self.rwdKeyTimer.stop()
675                         self.rwdtimer = False
676                 
677                         lookup = {
678                                         self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
679                                         self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
680                                         self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
681                                         self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
682                                         self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
683                                         self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
684                                         self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
685                                         self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
686                                         self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
687                                         self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
688                                         self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
689                                         self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
690                                         self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
691                                         self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
692                                         self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
693                                 }
694                         self.setSeekState(lookup[self.seekstate]);
695                 
696         def fwdTimerFire(self):
697                 print "Display seek fwd"
698                 self.fwdKeyTimer.stop()
699                 self.fwdtimer = False
700                 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
701                 
702         def fwdSeekTo(self, minutes):
703                 print "Seek", minutes, "minutes forward"
704                 if minutes != 0:
705                         service = self.session.nav.getCurrentService()
706                         if service is None:
707                                 return
708                         seekable = service.seek()
709                         if seekable is None:
710                                 return
711                         seekable.seekRelative(1, minutes * 60 * 90000)
712         
713         def rwdTimerFire(self):
714                 self.rwdKeyTimer.stop()
715                 self.rwdtimer = False
716                 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
717         
718         def rwdSeekTo(self, minutes):
719                 self.fwdSeekTo(0 - minutes)
720
721 from RecordTimer import parseEvent
722
723 class InfoBarInstantRecord:
724         """Instant Record - handles the instantRecord action in order to 
725         start/stop instant records"""
726         def __init__(self):
727                 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
728                         {
729                                 "instantRecord": (self.instantRecord, "Instant Record..."),
730                         })
731                 self.recording = None
732                 
733                 self["BlinkingPoint"] = BlinkingPixmapConditional()
734                 self.onShown.append(self["BlinkingPoint"].hideWidget)
735                 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
736                 
737         def stopCurrentRecording(self): 
738                 self.session.nav.RecordTimer.removeEntry(self.recording)
739                 self.recording = None
740                         
741         def startInstantRecording(self):
742                 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
743                 
744                 # try to get event info
745                 event = None
746                 try:
747                         service = self.session.nav.getCurrentService()
748                         info = service.info()
749                         ev = info.getEvent(0)
750                         event = ev
751                 except:
752                         pass
753                 
754                 if event is not None:
755                         data = parseEvent(event)
756                         data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
757                 else:
758                         data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
759                 
760                 # fix me, description. 
761                 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
762                 self.recording.dontSave = True
763                 
764                 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
765                 
766         def isInstantRecordRunning(self):
767                 if self.recording != None:
768                         if self.recording.isRunning():
769                                 return True
770                 return False
771
772         def recordQuestionCallback(self, answer):
773                 if answer == False:
774                         return
775                 
776                 if self.isInstantRecordRunning():
777                         self.stopCurrentRecording()
778                 else:
779                         self.startInstantRecording()
780
781         def instantRecord(self):
782                 try:
783                         stat = os.stat(resolveFilename(SCOPE_HDD))
784                 except:
785                         self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
786                         return
787         
788                 if self.isInstantRecordRunning():
789                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
790                 else:
791                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
792
793 from Screens.AudioSelection import AudioSelection
794
795 class InfoBarAudioSelection:
796         def __init__(self):
797                 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions", 
798                         {
799                                 "audioSelection": (self.audioSelection, "Audio Options..."),
800                         })
801
802         def audioSelection(self):
803                 service = self.session.nav.getCurrentService()
804                 audio = service.audioTracks()
805                 n = audio.getNumberOfTracks()
806                 if n > 0:
807                         self.session.open(AudioSelection, audio)
808
809 from Screens.SubserviceSelection import SubserviceSelection
810
811 class InfoBarSubserviceSelection:
812         def __init__(self):
813                 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
814                         {
815                                 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
816                         })
817
818         def subserviceSelection(self):
819                 service = self.session.nav.getCurrentService()
820                 subservices = service.subServices()
821                 n = subservices.getNumberOfSubservices()
822                 if n > 0:
823                         self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
824
825         def subserviceSelected(self, service):
826                 if not service is None:
827                         self.session.nav.playService(service)
828
829 class InfoBarAdditionalInfo:
830         def __init__(self):
831                 self["DolbyActive"] = Pixmap()
832                 self["CryptActive"] = Pixmap()
833                 self["FormatActive"] = Pixmap()
834                 
835                 self["ButtonRed"] = PixmapConditional(withTimer = False)
836                 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
837                 self.onShown.append(self["ButtonRed"].update)
838                 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
839                 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
840                 self.onShown.append(self["ButtonRedText"].update)
841
842                 self["ButtonGreen"] = Pixmap()
843                 self["ButtonGreenText"] = Label(_("Subservices"))
844
845                 self["ButtonYellow"] = PixmapConditional(withTimer = False)
846                 self["ButtonYellow"].setConnect(lambda: False)
847
848                 self["ButtonBlue"] = PixmapConditional(withTimer = False)
849                 self["ButtonBlue"].setConnect(lambda: False)
850
851                 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
852
853         def hideSubServiceIndication(self):
854                 self["ButtonGreen"].hideWidget()
855                 self["ButtonGreenText"].hide()
856
857         def showSubServiceIndication(self):
858                 self["ButtonGreen"].showWidget()
859                 self["ButtonGreenText"].show()
860
861         def checkFormat(self, service):
862                 info = service.info()
863                 if info is not None:
864                         aspect = info.getInfo(iServiceInformation.sAspect)
865                         if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
866                                 self["FormatActive"].showWidget()
867                         else:
868                                 self["FormatActive"].hideWidget()
869
870         def checkSubservices(self, service):
871                 if service.subServices().getNumberOfSubservices() > 0:
872                         self.showSubServiceIndication()
873                 else:
874                         self.hideSubServiceIndication()
875
876         def checkDolby(self, service):
877                 dolby = False
878                 audio = service.audioTracks()
879                 if audio is not None:
880                         n = audio.getNumberOfTracks()
881                         for x in range(n):
882                                 i = audio.getTrackInfo(x)
883                                 description = i.getDescription();
884                                 if description.find("AC3") != -1 or description.find("DTS") != -1:
885                                         dolby = True
886                                         break
887                 if dolby:
888                         self["DolbyActive"].showWidget()
889                 else:
890                         self["DolbyActive"].hideWidget()
891
892         def checkCrypted(self, service):
893                 info = service.info()
894                 if info is not None:
895                         if info.getInfo(iServiceInformation.sIsCrypted) > 0:
896                                 self["CryptActive"].showWidget()
897                         else:
898                                 self["CryptActive"].hideWidget()
899
900         def gotServiceEvent(self, ev):
901                 service = self.session.nav.getCurrentService()
902                 if ev == pNavigation.evUpdatedEventInfo:
903                         self.checkSubservices(service)
904                         self.checkFormat(service)
905                 elif ev == pNavigation.evUpdatedInfo:
906                         self.checkCrypted(service)
907                         self.checkDolby(service)
908                 elif ev == pNavigation.evStopService:
909                         self.hideSubServiceIndication()
910                         self["CryptActive"].hideWidget()
911                         self["DolbyActive"].hideWidget()
912                         self["FormatActive"].hideWidget()
913
914 class InfoBarNotifications:
915         def __init__(self):
916                 self.onExecBegin.append(self.checkNotifications)
917                 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
918         
919         def checkNotificationsIfExecing(self):
920                 if self.execing:
921                         self.checkNotifications()
922
923         def checkNotifications(self):
924                 if len(Notifications.notifications):
925                         n = Notifications.notifications[0]
926                         Notifications.notifications = Notifications.notifications[1:]
927                         print "open",n
928                         cb = n[0]
929                         if cb is not None:
930                                 self.session.openWithCallback(cb, *n[1:])
931                         else:
932                                 self.session.open(*n[1:])