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