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