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