configSelection is now saved to config file in a human readable style
[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 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 = 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                 ref=self.session.nav.getCurrentlyPlayingServiceReference()
366                 ptr=eEPGCache.getInstance()
367                 if ptr.startTimeQuery(ref) != -1:
368                         self.session.open(EPGSelection, ref)
369                 else: # try to show now/next
370                         print 'no epg for service', ref.toString()
371                         try:
372                                 self.epglist = [ ]
373                                 service = self.session.nav.getCurrentService()
374                                 info = service.info()
375                                 ptr=info.getEvent(0)
376                                 if ptr:
377                                         self.epglist.append(ptr)
378                                 ptr=info.getEvent(1)
379                                 if ptr:
380                                         self.epglist.append(ptr)
381                                 if len(self.epglist) > 0:
382                                         self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
383                         except:
384                                 pass
385
386         def eventViewCallback(self, setEvent, val): #used for now/next displaying
387                 if len(self.epglist) > 1:
388                         tmp = self.epglist[0]
389                         self.epglist[0]=self.epglist[1]
390                         self.epglist[1]=tmp
391                         setEvent(self.epglist[0])
392
393 from math import log
394
395 class InfoBarTuner:
396         """provides a snr/agc/ber display"""
397         def __init__(self):
398                 self["snr"] = Label()
399                 self["agc"] = Label()
400                 self["ber"] = Label()
401                 self["snr_percent"] = Label()
402                 self["agc_percent"] = Label()
403                 self["ber_count"] = Label()
404                 self["snr_progress"] = ProgressBar()
405                 self["agc_progress"] = ProgressBar()
406                 self["ber_progress"] = ProgressBar()
407                 self.timer = eTimer()
408                 self.timer.timeout.get().append(self.updateTunerInfo)
409                 self.timer.start(1000)
410
411         def calc(self,val):
412                 if not val:
413                         return 0
414                 if val < 2500:
415                         return (long)(log(val)/log(2))
416                 return val*100/65535
417
418         def updateTunerInfo(self):
419                 if self.instance.isVisible():
420                         service = self.session.nav.getCurrentService()
421                         snr=0
422                         agc=0
423                         ber=0
424                         if service is not None:
425                                 feinfo = service.frontendStatusInfo()
426                                 if feinfo is not None:
427                                         ber=feinfo.getFrontendInfo(iFrontendStatusInformation.bitErrorRate)
428                                         snr=feinfo.getFrontendInfo(iFrontendStatusInformation.signalPower)*100/65536
429                                         agc=feinfo.getFrontendInfo(iFrontendStatusInformation.signalQuality)*100/65536
430                         self["snr_percent"].setText("%d%%"%(snr))
431                         self["agc_percent"].setText("%d%%"%(agc))
432                         self["ber_count"].setText("%d"%(ber))
433                         self["snr_progress"].setValue(snr)
434                         self["agc_progress"].setValue(agc)
435                         self["ber_progress"].setValue(self.calc(ber))
436
437 class InfoBarEvent:
438         """provides a current/next event info display"""
439         def __init__(self):
440                 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
441                 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
442                                 
443                 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
444                 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
445
446                 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
447                 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
448
449 class InfoBarServiceName:
450         def __init__(self):
451                 self["ServiceName"] = ServiceName(self.session.nav)
452
453 class InfoBarPVR:
454
455         # ispause, isff, issm, skip
456         SEEK_STATE_PLAY = (0, 0, 0, 0)
457         SEEK_STATE_PAUSE = (1, 0, 0, 0)
458         SEEK_STATE_FF_2X = (0, 2, 0, 0)
459         SEEK_STATE_FF_4X = (0, 4, 0, 0)
460         SEEK_STATE_FF_8X = (0, 8, 0, 0)
461         SEEK_STATE_FF_32X = (0, 4, 0, 32)
462         SEEK_STATE_FF_64X = (0, 4, 0, 64)
463         SEEK_STATE_FF_128X = (0, 4, 0, 128)
464         
465         SEEK_STATE_BACK_4X = (0, 0, 0, -4)
466         SEEK_STATE_BACK_32X = (0, 0, 0, -32)
467         SEEK_STATE_BACK_64X = (0, 0, 0, -64)
468         SEEK_STATE_BACK_128X = (0, 0, 0, -128)
469         
470         SEEK_STATE_SM_HALF = (0, 0, 2, 0)
471         SEEK_STATE_SM_QUARTER = (0, 0, 4, 0)
472         SEEK_STATE_SM_EIGHTH = (0, 0, 8, 0)
473         
474         """handles PVR specific actions like seeking, pause"""
475         def __init__(self):
476                 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions", 
477                         {
478                                 "pauseService": (self.pauseService, "pause"),
479                                 "unPauseService": (self.unPauseService, "continue"),
480                                 
481                                 "seekFwd": (self.seekFwd, "skip forward"),
482                                 "seekFwdUp": (self.seekFwdUp, "skip forward"),
483                                 "seekBack": (self.seekBack, "skip backward"),
484                                 "seekBackUp": (self.seekBackUp, "skip backward"),
485                                                          
486                                 "up": (self.showMovies, "movie list"),
487                                 "down": (self.showMovies, "movie list")
488                         })
489
490                 self.seekstate = self.SEEK_STATE_PLAY
491                 self.seekTimer = eTimer()
492                 self.seekTimer.timeout.get().append(self.seekTimerFired)
493                 self.skipinterval = 500 # 500ms skip interval
494                 self.onClose.append(self.delSeekTimer)
495                 
496                 self.fwdtimer = False
497                 self.fwdKeyTimer = eTimer()
498                 self.fwdKeyTimer.timeout.get().append(self.fwdTimerFire)
499
500                 self.rwdtimer = False
501                 self.rwdKeyTimer = eTimer()
502                 self.rwdKeyTimer.timeout.get().append(self.rwdTimerFire)
503         
504         def up(self):
505                 pass
506         
507         def down(self):
508                 pass
509         
510         def delSeekTimer(self):
511                 del self.seekTimer
512         
513         def seekTimerFired(self):
514                 self.seekbase += self.skipmode * self.skipinterval
515                 
516                 # check if we bounced against the beginning of the file
517                 if self.seekbase < 0:
518                         self.seekbase = 0;
519                         self.setSeekState(self.SEEK_STATE_PLAY)
520                         
521                 self.doSeek(self.seekbase)
522
523         def setSeekState(self, state):
524                 oldstate = self.seekstate
525                 
526                 self.seekstate = state
527
528                 service = self.session.nav.getCurrentService()
529                 if service is None:
530                         return
531                 
532                 pauseable = service.pause()
533                 
534                 for i in range(4):
535                         if oldstate[i] != self.seekstate[i]:
536                                 (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion, self.setSkipMode)[i](self.seekstate[i])
537                 
538         def setSkipMode(self, skipmode):
539                 self.skipmode = skipmode
540                 if skipmode == 0:
541                         self.seekTimer.stop()
542                 else:
543                         self.seekTimer.start(500)
544                 
545                 service = self.session.nav.getCurrentService()
546                 if service is None:
547                         return
548                 
549                 seekable = service.seek()
550                 if seekable is None:
551                         return
552
553                 if skipmode:
554                         seekable.setTrickmode(1)
555                 else:
556                         seekable.setTrickmode(0)
557                 
558                 self.seekbase = seekable.getPlayPosition()[1] / 90
559         
560         def pauseService(self):
561                 if (self.seekstate == self.SEEK_STATE_PAUSE):
562                         self.unPauseService()
563                 else:
564                         self.setSeekState(self.SEEK_STATE_PAUSE);
565                 
566         def unPauseService(self):
567                 self.setSeekState(self.SEEK_STATE_PLAY);
568         
569         def doSeek(self, seektime):
570                 service = self.session.nav.getCurrentService()
571                 if service is None:
572                         return
573                 
574                 seekable = service.seek()
575                 if seekable is None:
576                         return
577                 seekable.seekTo(90 * seektime)
578
579         def seekFwd(self):
580                 print "start fwd timer"
581                 self.fwdtimer = True
582                 self.fwdKeyTimer.start(500)
583
584         def seekBack(self):
585                 print "start rewind timer"
586                 self.rwdtimer = True
587                 self.rwdKeyTimer.start(500)
588
589         def seekFwdUp(self):
590                 if self.fwdtimer:
591                         self.fwdKeyTimer.stop()
592                         self.fwdtimer = False
593                         lookup = {
594                                         self.SEEK_STATE_PLAY: self.SEEK_STATE_FF_2X,
595                                         self.SEEK_STATE_PAUSE: self.SEEK_STATE_SM_EIGHTH,
596                                         self.SEEK_STATE_FF_2X: self.SEEK_STATE_FF_4X,
597                                         self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_8X,
598                                         self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_32X,
599                                         self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_64X,
600                                         self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_128X,
601                                         self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_128X,
602                                         self.SEEK_STATE_BACK_4X: self.SEEK_STATE_PLAY,
603                                         self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_4X,
604                                         self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_32X,
605                                         self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_64X,
606                                         self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_HALF,
607                                         self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_HALF,
608                                         self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_SM_QUARTER
609                                 }
610                         self.setSeekState(lookup[self.seekstate]);
611         
612         def seekBackUp(self):
613                 if self.rwdtimer:
614                         self.rwdKeyTimer.stop()
615                         self.rwdtimer = False
616                 
617                         lookup = {
618                                         self.SEEK_STATE_PLAY: self.SEEK_STATE_BACK_4X,
619                                         self.SEEK_STATE_PAUSE: self.SEEK_STATE_PAUSE,
620                                         self.SEEK_STATE_FF_2X: self.SEEK_STATE_PLAY,
621                                         self.SEEK_STATE_FF_4X: self.SEEK_STATE_FF_2X,
622                                         self.SEEK_STATE_FF_8X: self.SEEK_STATE_FF_4X,
623                                         self.SEEK_STATE_FF_32X: self.SEEK_STATE_FF_8X,
624                                         self.SEEK_STATE_FF_64X: self.SEEK_STATE_FF_32X,
625                                         self.SEEK_STATE_FF_128X: self.SEEK_STATE_FF_64X,
626                                         self.SEEK_STATE_BACK_4X: self.SEEK_STATE_BACK_32X,
627                                         self.SEEK_STATE_BACK_32X: self.SEEK_STATE_BACK_64X,
628                                         self.SEEK_STATE_BACK_64X: self.SEEK_STATE_BACK_128X,
629                                         self.SEEK_STATE_BACK_128X: self.SEEK_STATE_BACK_128X,
630                                         self.SEEK_STATE_SM_HALF: self.SEEK_STATE_SM_QUARTER,
631                                         self.SEEK_STATE_SM_QUARTER: self.SEEK_STATE_SM_EIGHTH,
632                                         self.SEEK_STATE_SM_EIGHTH: self.SEEK_STATE_PAUSE
633                                 }
634                         self.setSeekState(lookup[self.seekstate]);
635                 
636         def fwdTimerFire(self):
637                 print "Display seek fwd"
638                 self.fwdKeyTimer.stop()
639                 self.fwdtimer = False
640                 self.session.openWithCallback(self.fwdSeekTo, MinuteInput)
641                 
642         def fwdSeekTo(self, minutes):
643                 print "Seek", minutes, "minutes forward"
644                 if minutes != 0:
645                         service = self.session.nav.getCurrentService()
646                         if service is None:
647                                 return
648                         seekable = service.seek()
649                         if seekable is None:
650                                 return
651                         seekable.seekRelative(1, minutes * 60 * 90000)
652         
653         def rwdTimerFire(self):
654                 self.rwdKeyTimer.stop()
655                 self.rwdtimer = False
656                 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
657         
658         def rwdSeekTo(self, minutes):
659                 self.fwdSeekTo(0 - minutes)
660
661 from RecordTimer import parseEvent
662
663 class InfoBarInstantRecord:
664         """Instant Record - handles the instantRecord action in order to 
665         start/stop instant records"""
666         def __init__(self):
667                 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
668                         {
669                                 "instantRecord": (self.instantRecord, "Instant Record..."),
670                         })
671                 self.recording = None
672                 
673                 self["BlinkingPoint"] = BlinkingPixmapConditional()
674                 self.onShown.append(self["BlinkingPoint"].hideWidget)
675                 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
676                 
677         def stopCurrentRecording(self): 
678                 self.session.nav.RecordTimer.removeEntry(self.recording)
679                 self.recording = None
680                         
681         def startInstantRecording(self):
682                 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
683                 
684                 # try to get event info
685                 event = None
686                 try:
687                         service = self.session.nav.getCurrentService()
688                         info = service.info()
689                         ev = info.getEvent(0)
690                         event = ev
691                 except:
692                         pass
693                 
694                 if event is not None:
695                         data = parseEvent(event)
696                         data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
697                 else:
698                         data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
699                 
700                 # fix me, description. 
701                 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
702                 self.recording.dontSave = True
703                 
704                 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
705                 
706         def isInstantRecordRunning(self):
707                 if self.recording != None:
708                         if self.recording.isRunning():
709                                 return True
710                 return False
711
712         def recordQuestionCallback(self, answer):
713                 if answer == False:
714                         return
715                 
716                 if self.isInstantRecordRunning():
717                         self.stopCurrentRecording()
718                 else:
719                         self.startInstantRecording()
720
721         def instantRecord(self):
722                 try:
723                         stat = os.stat(resolveFilename(SCOPE_HDD))
724                 except:
725                         self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
726                         return
727         
728                 if self.isInstantRecordRunning():
729                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
730                 else:
731                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
732
733 from Screens.AudioSelection import AudioSelection
734
735 class InfoBarAudioSelection:
736         def __init__(self):
737                 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions", 
738                         {
739                                 "audioSelection": (self.audioSelection, "Audio Options..."),
740                         })
741
742         def audioSelection(self):
743                 service = self.session.nav.getCurrentService()
744                 audio = service.audioTracks()
745                 n = audio.getNumberOfTracks()
746                 if n > 0:
747                         self.session.open(AudioSelection, audio)
748
749 from Screens.SubserviceSelection import SubserviceSelection
750
751 class InfoBarSubserviceSelection:
752         def __init__(self):
753                 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
754                         {
755                                 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
756                         })
757
758         def subserviceSelection(self):
759                 service = self.session.nav.getCurrentService()
760                 subservices = service.subServices()
761                 n = subservices.getNumberOfSubservices()
762                 if n > 0:
763                         self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
764
765         def subserviceSelected(self, service):
766                 if not service is None:
767                         self.session.nav.playService(service)
768
769 class InfoBarAdditionalInfo:
770         def __init__(self):
771                 self["DolbyActive"] = Pixmap()
772                 self["CryptActive"] = Pixmap()
773                 self["FormatActive"] = Pixmap()
774                 
775                 self["ButtonRed"] = PixmapConditional(withTimer = False)
776                 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
777                 self.onShown.append(self["ButtonRed"].update)
778                 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
779                 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
780                 self.onShown.append(self["ButtonRedText"].update)
781
782                 self["ButtonGreen"] = Pixmap()
783                 self["ButtonGreenText"] = Label(_("Subservices"))
784
785                 self["ButtonYellow"] = PixmapConditional(withTimer = False)
786                 self["ButtonYellow"].setConnect(lambda: False)
787
788                 self["ButtonBlue"] = PixmapConditional(withTimer = False)
789                 self["ButtonBlue"].setConnect(lambda: False)
790
791                 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
792
793         def hideSubServiceIndication(self):
794                 self["ButtonGreen"].hideWidget()
795                 self["ButtonGreenText"].hide()
796
797         def showSubServiceIndication(self):
798                 self["ButtonGreen"].showWidget()
799                 self["ButtonGreenText"].show()
800
801         def checkFormat(self, service):
802                 info = service.info()
803                 if info is not None:
804                         aspect = info.getInfo(iServiceInformation.sAspect)
805                         if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
806                                 self["FormatActive"].showWidget()
807                         else:
808                                 self["FormatActive"].hideWidget()
809
810         def checkSubservices(self, service):
811                 if service.subServices().getNumberOfSubservices() > 0:
812                         self.showSubServiceIndication()
813                 else:
814                         self.hideSubServiceIndication()
815
816         def checkDolby(self, service):
817                 dolby = False
818                 audio = service.audioTracks()
819                 if audio is not None:
820                         n = audio.getNumberOfTracks()
821                         for x in range(n):
822                                 i = audio.getTrackInfo(x)
823                                 description = i.getDescription();
824                                 if description.find("AC3") != -1 or description.find("DTS") != -1:
825                                         dolby = True
826                                         break
827                 if dolby:
828                         self["DolbyActive"].showWidget()
829                 else:
830                         self["DolbyActive"].hideWidget()
831
832         def checkCrypted(self, service):
833                 info = service.info()
834                 if info is not None:
835                         if info.getInfo(iServiceInformation.sIsCrypted) > 0:
836                                 self["CryptActive"].showWidget()
837                         else:
838                                 self["CryptActive"].hideWidget()
839
840         def gotServiceEvent(self, ev):
841                 service = self.session.nav.getCurrentService()
842                 if ev == pNavigation.evUpdatedEventInfo:
843                         self.checkSubservices(service)
844                         self.checkFormat(service)
845                 elif ev == pNavigation.evUpdatedInfo:
846                         self.checkCrypted(service)
847                         self.checkDolby(service)
848                 elif ev == pNavigation.evStopService:
849                         self.hideSubServiceIndication()
850                         self["CryptActive"].hideWidget()
851                         self["DolbyActive"].hideWidget()
852                         self["FormatActive"].hideWidget()
853
854 class InfoBarNotifications:
855         def __init__(self):
856                 self.onExecBegin.append(self.checkNotifications)
857                 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
858         
859         def checkNotificationsIfExecing(self):
860                 if self.execing:
861                         self.checkNotifications()
862
863         def checkNotifications(self):
864                 if len(Notifications.notifications):
865                         n = Notifications.notifications[0]
866                         Notifications.notifications = Notifications.notifications[1:]
867                         print "open",n
868                         cb = n[0]
869                         if cb is not None:
870                                 self.session.openWithCallback(cb, *n[1:])
871                         else:
872                                 self.session.open(*n[1:])