fix more very stupid bugs... someone must have had too much drinks while writing...
[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                 service = self.session.nav.getCurrentService()
644                 if service is None:
645                         return
646                 seekable = service.seek()
647                 if seekable is None:
648                         return
649                 seekable.seekRelative(1, minutes * 60 * 90000)
650         
651         def rwdTimerFire(self):
652                 self.rwdKeyTimer.stop()
653                 self.rwdtimer = False
654                 self.session.openWithCallback(self.rwdSeekTo, MinuteInput)
655         
656         def rwdSeekTo(self, minutes):
657                 self.fwdSeekTo(0 - minutes)
658
659 from RecordTimer import parseEvent
660
661 class InfoBarInstantRecord:
662         """Instant Record - handles the instantRecord action in order to 
663         start/stop instant records"""
664         def __init__(self):
665                 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
666                         {
667                                 "instantRecord": (self.instantRecord, "Instant Record..."),
668                         })
669                 self.recording = None
670                 
671                 self["BlinkingPoint"] = BlinkingPixmapConditional()
672                 self.onShown.append(self["BlinkingPoint"].hideWidget)
673                 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
674                 
675         def stopCurrentRecording(self): 
676                 self.session.nav.RecordTimer.removeEntry(self.recording)
677                 self.recording = None
678                         
679         def startInstantRecording(self):
680                 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
681                 
682                 # try to get event info
683                 event = None
684                 try:
685                         service = self.session.nav.getCurrentService()
686                         info = service.info()
687                         ev = info.getEvent(0)
688                         event = ev
689                 except:
690                         pass
691                 
692                 if event is not None:
693                         data = parseEvent(event)
694                         data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
695                 else:
696                         data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
697                 
698                 # fix me, description. 
699                 self.recording = self.session.nav.recordWithTimer(serviceref, *data)
700                 self.recording.dontSave = True
701                 
702                 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
703                 
704         def isInstantRecordRunning(self):
705                 if self.recording != None:
706                         if self.recording.isRunning():
707                                 return True
708                 return False
709
710         def recordQuestionCallback(self, answer):
711                 if answer == False:
712                         return
713                 
714                 if self.isInstantRecordRunning():
715                         self.stopCurrentRecording()
716                 else:
717                         self.startInstantRecording()
718
719         def instantRecord(self):
720                 try:
721                         stat = os.stat("/hdd/movies")
722                 except:
723                         self.session.open(MessageBox, "No HDD found!", MessageBox.TYPE_ERROR)
724                         return
725         
726                 if self.isInstantRecordRunning():
727                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
728                 else:
729                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
730
731 from Screens.AudioSelection import AudioSelection
732
733 class InfoBarAudioSelection:
734         def __init__(self):
735                 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions", 
736                         {
737                                 "audioSelection": (self.audioSelection, "Audio Options..."),
738                         })
739
740         def audioSelection(self):
741                 service = self.session.nav.getCurrentService()
742                 audio = service.audioTracks()
743                 n = audio.getNumberOfTracks()
744                 if n > 0:
745                         self.session.open(AudioSelection, audio)
746
747 from Screens.SubserviceSelection import SubserviceSelection
748
749 class InfoBarSubserviceSelection:
750         def __init__(self):
751                 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
752                         {
753                                 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
754                         })
755
756         def subserviceSelection(self):
757                 service = self.session.nav.getCurrentService()
758                 subservices = service.subServices()
759                 n = subservices.getNumberOfSubservices()
760                 if n > 0:
761                         self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
762
763         def subserviceSelected(self, service):
764                 if not service is None:
765                         self.session.nav.playService(service)
766
767 class InfoBarAdditionalInfo:
768         def __init__(self):
769                 self["DolbyActive"] = Pixmap()
770                 self["CryptActive"] = Pixmap()
771                 self["FormatActive"] = Pixmap()
772                 
773                 self["ButtonRed"] = PixmapConditional(withTimer = False)
774                 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
775                 self.onShown.append(self["ButtonRed"].update)
776                 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
777                 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
778                 self.onShown.append(self["ButtonRedText"].update)
779
780                 self["ButtonGreen"] = Pixmap()
781                 self["ButtonGreenText"] = Label(_("Subservices"))
782
783                 self["ButtonYellow"] = PixmapConditional(withTimer = False)
784                 self["ButtonYellow"].setConnect(lambda: False)
785
786                 self["ButtonBlue"] = PixmapConditional(withTimer = False)
787                 self["ButtonBlue"].setConnect(lambda: False)
788
789                 self.session.nav.event.append(self.gotServiceEvent) # we like to get service events
790
791         def hideSubServiceIndication(self):
792                 self["ButtonGreen"].hideWidget()
793                 self["ButtonGreenText"].hide()
794
795         def showSubServiceIndication(self):
796                 self["ButtonGreen"].showWidget()
797                 self["ButtonGreenText"].show()
798
799         def checkFormat(self, service):
800                 info = service.info()
801                 if info is not None:
802                         aspect = info.getInfo(iServiceInformation.sAspect)
803                         if aspect in [ 3, 4, 7, 8, 0xB, 0xC, 0xF, 0x10 ]:
804                                 self["FormatActive"].showWidget()
805                         else:
806                                 self["FormatActive"].hideWidget()
807
808         def checkSubservices(self, service):
809                 if service.subServices().getNumberOfSubservices() > 0:
810                         self.showSubServiceIndication()
811                 else:
812                         self.hideSubServiceIndication()
813
814         def checkDolby(self, service):
815                 dolby = False
816                 audio = service.audioTracks()
817                 if audio is not None:
818                         n = audio.getNumberOfTracks()
819                         for x in range(n):
820                                 i = audio.getTrackInfo(x)
821                                 description = i.getDescription();
822                                 if description.find("AC3") != -1 or description.find("DTS") != -1:
823                                         dolby = True
824                                         break
825                 if dolby:
826                         self["DolbyActive"].showWidget()
827                 else:
828                         self["DolbyActive"].hideWidget()
829
830         def checkCrypted(self, service):
831                 info = service.info()
832                 if info is not None:
833                         if info.getInfo(iServiceInformation.sIsCrypted) > 0:
834                                 self["CryptActive"].showWidget()
835                         else:
836                                 self["CryptActive"].hideWidget()
837
838         def gotServiceEvent(self, ev):
839                 service = self.session.nav.getCurrentService()
840                 if ev == pNavigation.evUpdatedEventInfo:
841                         self.checkSubservices(service)
842                         self.checkFormat(service)
843                 elif ev == pNavigation.evUpdatedInfo:
844                         self.checkCrypted(service)
845                         self.checkDolby(service)
846                 elif ev == pNavigation.evStopService:
847                         self.hideSubServiceIndication()
848                         self["CryptActive"].hideWidget()
849                         self["DolbyActive"].hideWidget()
850                         self["FormatActive"].hideWidget()
851
852 class InfoBarNotifications:
853         def __init__(self):
854                 self.onExecBegin.append(self.checkNotifications)
855                 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
856         
857         def checkNotificationsIfExecing(self):
858                 if self.execing:
859                         self.checkNotifications()
860
861         def checkNotifications(self):
862                 if len(Notifications.notifications):
863                         n = Notifications.notifications[0]
864                         Notifications.notifications = Notifications.notifications[1:]
865                         print "open",n
866                         cb = n[0]
867                         if cb is not None:
868                                 self.session.openWithCallback(cb, *n[1:])
869                         else:
870                                 self.session.open(*n[1:])