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