add notifications
[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 Label
5 from Components.config import configfile, configsequencearg
6 from Components.config import config, configElement, ConfigSubsection, configSequence
7 from ChannelSelection import ChannelSelection
8
9 from Components.Pixmap import Pixmap, PixmapConditional
10 from Components.BlinkingPixmap import BlinkingPixmapConditional
11 from Components.ServiceName import ServiceName
12 from Components.EventInfo import EventInfo
13
14 from ServiceReference import ServiceReference
15 from EpgSelection import EPGSelection
16
17 from Screens.MessageBox import MessageBox
18 from Screens.Volume import Volume
19 from Screens.Mute import Mute
20 from Screens.Standby import Standby
21 from Screens.EventView import EventView
22
23 from Tools import Notifications
24
25 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
26 from enigma import *
27
28 import time
29 import os
30
31 # hack alert!
32 from Menu import MainMenu, mdom
33
34 class InfoBarVolumeControl:
35         """Volume control, handles volUp, volDown, volMute actions and display 
36         a corresponding dialog"""
37         def __init__(self):
38                 config.audio = ConfigSubsection()
39                 config.audio.volume = configElement("config.audio.volume", configSequence, [5], configsequencearg.get("INTEGER", (0, 100)))
40
41                 self["VolumeActions"] = ActionMap( ["InfobarVolumeActions"] ,
42                         {
43                                 "volumeUp": self.volUp,
44                                 "volumeDown": self.volDown,
45                                 "volumeMute": self.volMute,
46                         })
47
48                 self.volumeDialog = self.session.instantiateDialog(Volume)
49                 self.muteDialog = self.session.instantiateDialog(Mute)
50
51                 self.hideVolTimer = eTimer()
52                 self.hideVolTimer.timeout.get().append(self.volHide)
53
54                 vol = config.audio.volume.value[0]
55                 self.volumeDialog.setValue(vol)
56                 eDVBVolumecontrol.getInstance().setVolume(vol, vol)
57         
58         def volSave(self):
59                 config.audio.volume.value = eDVBVolumecontrol.getInstance().getVolume()
60                 config.audio.volume.save()
61                 
62         def     volUp(self):
63                 if (eDVBVolumecontrol.getInstance().isMuted()):
64                         self.volMute()
65                 eDVBVolumecontrol.getInstance().volumeUp()
66                 self.volumeDialog.instance.show()
67                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
68                 self.volSave()
69                 self.hideVolTimer.start(3000)
70
71         def     volDown(self):
72                 if (eDVBVolumecontrol.getInstance().isMuted()):
73                         self.volMute()
74                 eDVBVolumecontrol.getInstance().volumeDown()
75                 self.volumeDialog.instance.show()
76                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
77                 self.volSave()
78                 self.hideVolTimer.start(3000)
79                 
80         def volHide(self):
81                 self.volumeDialog.instance.hide()
82
83         def     volMute(self):
84                 eDVBVolumecontrol.getInstance().volumeToggleMute()
85                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
86                 
87                 if (eDVBVolumecontrol.getInstance().isMuted()):
88                         self.muteDialog.instance.show()
89                 else:
90                         self.muteDialog.instance.hide()
91
92 class InfoBarShowHide:
93         """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
94         fancy animations. """
95         STATE_HIDDEN = 0
96         STATE_HIDING = 1
97         STATE_SHOWING = 2
98         STATE_SHOWN = 3
99         
100         def __init__(self):
101                 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
102                         {
103                                 "toggleShow": self.toggleShow,
104                                 "hide": self.hide,
105                         })
106
107                 self.state = self.STATE_SHOWN
108                 
109                 self.onExecBegin.append(self.show)
110                 self.onClose.append(self.delHideTimer)
111                 
112                 self.hideTimer = eTimer()
113                 self.hideTimer.timeout.get().append(self.doTimerHide)
114                 self.hideTimer.start(5000)
115
116         def delHideTimer(self):
117                 del self.hideTimer
118
119         def hide(self): 
120                 self.instance.hide()
121                 
122         def show(self):
123                 self.state = self.STATE_SHOWN
124                 self.hideTimer.stop()
125                 self.hideTimer.start(5000)
126
127         def doTimerHide(self):
128                 self.hideTimer.stop()
129                 if self.state == self.STATE_SHOWN:
130                         self.instance.hide()
131                         self.state = self.STATE_HIDDEN
132
133         def toggleShow(self):
134                 if self.state == self.STATE_SHOWN:
135                         self.instance.hide()
136                         #pls check animation support, sorry
137 #                       self.startHide()
138                         self.hideTimer.stop()
139                         self.state = self.STATE_HIDDEN
140                 elif self.state == self.STATE_HIDDEN:
141                         self.instance.show()
142                         self.show()
143                         
144         def startShow(self):
145                 self.instance.m_animation.startMoveAnimation(ePoint(0, 600), ePoint(0, 380), 100)
146                 self.state = self.STATE_SHOWN
147         
148         def startHide(self):
149                 self.instance.m_animation.startMoveAnimation(ePoint(0, 380), ePoint(0, 600), 100)
150                 self.state = self.STATE_HIDDEN
151
152 class NumberZap(Screen):
153         def quit(self):
154                 self.Timer.stop()
155                 self.close(0)
156
157         def keyOK(self):
158                 self.Timer.stop()
159                 self.close(int(self["number"].getText()))
160
161         def keyNumberGlobal(self, number):
162                 self.Timer.start(3000)          #reset timer
163                 self.field = self.field + str(number)
164                 self["number"].setText(self.field)
165                 if len(self.field) >= 4:
166                         self.keyOK()
167
168         def __init__(self, session, number):
169                 Screen.__init__(self, session)
170                 self.field = str(number)
171
172                 self["channel"] = Label(_("Channel:"))
173
174                 self["number"] = Label(self.field)
175
176                 self["actions"] = NumberActionMap( [ "SetupActions" ], 
177                         {
178                                 "cancel": self.quit,
179                                 "ok": self.keyOK,
180                                 "1": self.keyNumberGlobal,
181                                 "2": self.keyNumberGlobal,
182                                 "3": self.keyNumberGlobal,
183                                 "4": self.keyNumberGlobal,
184                                 "5": self.keyNumberGlobal,
185                                 "6": self.keyNumberGlobal,
186                                 "7": self.keyNumberGlobal,
187                                 "8": self.keyNumberGlobal,
188                                 "9": self.keyNumberGlobal,
189                                 "0": self.keyNumberGlobal
190                         })
191
192                 self.Timer = eTimer()
193                 self.Timer.timeout.get().append(self.keyOK)
194                 self.Timer.start(3000)
195
196 class InfoBarPowerKey:
197         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
198         
199         def __init__(self):
200                 self.powerKeyTimer = eTimer()
201                 self.powerKeyTimer.timeout.get().append(self.powertimer)
202                 self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
203                         {
204                                 "powerdown": self.powerdown,
205                                 "powerup": self.powerup,
206                                 "discreteStandby": (self.standby, "Go standby"),
207                                 "discretePowerOff": (self.quit, "Go to deep standby"),
208                         })
209
210         def powertimer(self):   
211                 print "PowerOff - Now!"
212                 self.quit()
213         
214         def powerdown(self):
215                 self.standbyblocked = 0
216                 self.powerKeyTimer.start(3000)
217
218         def powerup(self):
219                 self.powerKeyTimer.stop()
220                 if self.standbyblocked == 0:
221                         self.standbyblocked = 1
222                         self.standby()
223
224         def standby(self):
225                 self.session.open(Standby, self)
226
227         def quit(self):
228                 # halt
229                 quitMainloop(1)
230
231 class InfoBarNumberZap:
232         """ Handles an initial number for NumberZapping """
233         def __init__(self):
234                 self["NumberZapActions"] = NumberActionMap( [ "NumberZapActions"],
235                         {
236                                 "1": self.keyNumberGlobal,
237                                 "2": self.keyNumberGlobal,
238                                 "3": self.keyNumberGlobal,
239                                 "4": self.keyNumberGlobal,
240                                 "5": self.keyNumberGlobal,
241                                 "6": self.keyNumberGlobal,
242                                 "7": self.keyNumberGlobal,
243                                 "8": self.keyNumberGlobal,
244                                 "9": self.keyNumberGlobal,
245                                 "0": self.keyNumberGlobal,
246                         })
247
248         def keyNumberGlobal(self, number):
249 #               print "You pressed number " + str(number)
250                 self.session.openWithCallback(self.numberEntered, NumberZap, number)
251
252         def numberEntered(self, retval):
253 #               print self.servicelist
254                 if retval > 0:
255                         self.zapToNumber(retval)
256
257         def searchNumberHelper(self, serviceHandler, num, bouquet):
258                 servicelist = serviceHandler.list(bouquet)
259                 if not servicelist is None:
260                         while num:
261                                 serviceIterator = servicelist.getNext()
262                                 if not serviceIterator.valid(): #check end of list
263                                         break
264                                 if serviceIterator.flags: #assume normal dvb service have no flags set
265                                         continue
266                                 num -= 1;
267                         if not num: #found service with searched number ?
268                                 return serviceIterator, 0
269                 return None, num
270
271         def zapToNumber(self, number):
272                 bouquet = self.servicelist.bouquet_root
273                 service = None
274                 serviceHandler = eServiceCenter.getInstance()
275                 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
276                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
277                 else:
278                         bouquetlist = serviceHandler.list(bouquet)
279                         if not bouquetlist is None:
280                                 while number:
281                                         bouquet = bouquetlist.getNext()
282                                         if not bouquet.valid(): #check end of list
283                                                 break
284                                         if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
285                                                 continue
286                                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
287                 if not service is None:
288                         self.session.nav.playService(service) #play service
289                         if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
290                                 self.servicelist.setRoot(bouquet)
291                         self.servicelist.setCurrentSelection(service) #select the service in servicelist
292
293 class InfoBarChannelSelection:
294         """ ChannelSelection - handles the channelSelection dialog and the initial 
295         channelChange actions which open the channelSelection dialog """
296         def __init__(self):
297                 #instantiate forever
298                 self.servicelist = self.session.instantiateDialog(ChannelSelection)
299
300                 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
301                         {
302                                 "switchChannelUp": self.switchChannelUp,
303                                 "switchChannelDown": self.switchChannelDown,
304                                 "zapUp": (self.zapUp, _("next channel")),
305                                 "zapDown": (self.zapDown, _("previous channel")),
306                         })
307                         
308         def switchChannelUp(self):      
309                 self.servicelist.moveUp()
310                 self.session.execDialog(self.servicelist)
311
312         def switchChannelDown(self):    
313                 self.servicelist.moveDown()
314                 self.session.execDialog(self.servicelist)
315
316         def     zapUp(self):
317                 self.servicelist.moveUp()
318                 self.servicelist.zap()
319                 self.instance.show()
320                 self.show()
321
322         def     zapDown(self):
323                 self.servicelist.moveDown()
324                 self.servicelist.zap()
325                 self.instance.show()
326                 self.show()
327                 
328 class InfoBarMenu:
329         """ Handles a menu action, to open the (main) menu """
330         def __init__(self):
331                 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions", 
332                         {
333                                 "mainMenu": (self.mainMenu, "Enter main menu..."),
334                         })
335
336         def mainMenu(self):
337                 print "loading mainmenu XML..."
338                 menu = mdom.childNodes[0]
339                 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
340                 self.session.open(MainMenu, menu, menu.childNodes)
341
342 class InfoBarEPG:
343         """ EPG - Opens an EPG list when the showEPGList action fires """
344         def __init__(self):
345                 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
346                         {
347                                 "showEPGList": (self.showEPGList, _("show EPG...")),
348                         })
349
350         def showEPGList(self):
351                 ref=self.session.nav.getCurrentlyPlayingServiceReference()
352                 ptr=eEPGCache.getInstance()
353                 if ptr.startTimeQuery(ref) != -1:
354                         self.session.open(EPGSelection, ref)
355                 else: # try to show now/next
356                         print 'no epg for service', ref.toString()
357                         try:
358                                 self.epglist = [ ]
359                                 service = self.session.nav.getCurrentService()
360                                 info = service.info()
361                                 ptr=info.getEvent(0)
362                                 if ptr:
363                                         self.epglist.append(ptr)
364                                 ptr=info.getEvent(1)
365                                 if ptr:
366                                         self.epglist.append(ptr)
367                                 if len(self.epglist) > 0:
368                                         self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
369                         except:
370                                 pass
371
372         def eventViewCallback(self, setEvent, val): #used for now/next displaying
373                 if len(self.epglist) > 1:
374                         tmp = self.epglist[0]
375                         self.epglist[0]=self.epglist[1]
376                         self.epglist[1]=tmp
377                         setEvent(self.epglist[0])
378
379 class InfoBarEvent:
380         """provides a current/next event info display"""
381         def __init__(self):
382                 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
383                 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
384                                 
385                 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
386                 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
387
388                 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
389                 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
390
391 class InfoBarServiceName:
392         def __init__(self):
393                 self["ServiceName"] = ServiceName(self.session.nav)
394
395 class InfoBarPVR:
396         """handles PVR specific actions like seeking, pause"""
397         def __init__(self):
398                 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions", 
399                         {
400                                 "pauseService": (self.pauseService, "pause"),
401                                 "unPauseService": (self.unPauseService, "continue"),
402                                 
403                                 "seekFwd": (self.seekFwd, "skip forward"),
404                                 "seekBack": (self.seekBack, "skip backward"),
405                         })
406                 
407         def pauseService(self):
408                 self.session.nav.pause(1)
409                 
410         def unPauseService(self):
411                 self.session.nav.pause(0)
412         
413         def doSeek(self, dir, seektime):
414                 service = self.session.nav.getCurrentService()
415                 if service is None:
416                         return
417                 
418                 seekable = service.seek()
419                 if seekable is None:
420                         return
421                 seekable.seekRelative(dir, 90 * seektime)
422
423         def seekFwd(self):
424                 self.doSeek(+1, 60000)
425         
426         def seekBack(self):
427                 self.doSeek(-1, 60000)
428
429 class InfoBarInstantRecord:
430         """Instant Record - handles the instantRecord action in order to 
431         start/stop instant records"""
432         def __init__(self):
433                 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
434                         {
435                                 "instantRecord": (self.instantRecord, "Instant Record..."),
436                         })
437                 self.recording = None
438                 
439                 self["BlinkingPoint"] = BlinkingPixmapConditional()
440                 self.onShown.append(self["BlinkingPoint"].hidePixmap)
441                 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
442                 
443         def stopCurrentRecording(self): 
444                 self.session.nav.RecordTimer.removeEntry(self.recording)
445                 self.recording = None
446                         
447         def startInstantRecording(self):
448                 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
449                         
450                 # try to get event info
451                 epg = None
452                 try:
453                         service = self.session.nav.getCurrentService()
454                         info = service.info()
455                         ev = info.getEvent(0)
456                         epg = ev
457                 except:
458                         pass
459                 
460                 # fix me, description. 
461                 self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600, serviceref, epg, "instant record")
462                 self.recording.dontSave = True
463                 
464                 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
465                 
466         def isInstantRecordRunning(self):
467                 if self.recording != None:
468                         if self.recording.isRunning():
469                                 return True
470                 return False
471
472         def recordQuestionCallback(self, answer):
473                 if answer == False:
474                         return
475                 
476                 if self.isInstantRecordRunning():
477                         self.stopCurrentRecording()
478                 else:
479                         self.startInstantRecording()
480
481         def instantRecord(self):
482                 try:
483                         stat = os.stat("/hdd/movies")
484                 except:
485                         self.session.open(MessageBox, "No HDD found!")
486                         return
487         
488                 if self.isInstantRecordRunning():
489                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
490                 else:
491                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
492
493 from Screens.AudioSelection import AudioSelection
494
495 class InfoBarAudioSelection:
496         def __init__(self):
497                 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions", 
498                         {
499                                 "audioSelection": (self.audioSelection, "Audio Options..."),
500                         })
501
502         def audioSelection(self):
503                 service = self.session.nav.getCurrentService()
504                 audio = service.audioTracks()
505                 n = audio.getNumberOfTracks()
506                 if n > 0:
507                         self.session.open(AudioSelection, audio)
508
509 class InfoBarAdditionalInfo:
510         def __init__(self):
511                 self["DolbyActive"] = PixmapConditional()
512                 # TODO: get the info from c++ somehow
513                 self["DolbyActive"].setConnect(lambda: False)
514                 
515                 self["CryptActive"] = PixmapConditional()
516                 # TODO: get the info from c++ somehow
517                 self["CryptActive"].setConnect(lambda: False)
518                 
519                 self["FormatActive"] = PixmapConditional()
520                 # TODO: get the info from c++ somehow
521                 self["FormatActive"].setConnect(lambda: False)
522                 
523                 self["ButtonRed"] = Pixmap()
524                 self["ButtonRedText"] = Label(_("Record"))
525                 self["ButtonGreen"] = Pixmap()
526                 self["ButtonYellow"] = Pixmap()
527                 self["ButtonBlue"] = Pixmap()
528
529 class InfoBarNotifications:
530         def __init__(self):
531                 self.onExecBegin.append(self.checkNotifications)
532                 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
533         
534         def checkNotificationsIfExecing(self):
535                 if self.execing:
536                         self.checkNotifications()
537
538         def checkNotifications(self):
539                 if len(Notifications.notifications):
540                         n = Notifications.notifications[0]
541                         Notifications.notifications = Notifications.notifications[1:]
542                         print "open",n
543                         cb = n[0]
544                         if cb is not None:
545                                 self.session.openWithCallback(cb, *n[1:])
546                         else:
547                                 self.session.open(*n[1:])