1b080d9bbc4bfcbc4cfdd24c1621899936ae2d1e
[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.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.Dish import Dish
21 from Screens.Standby import Standby
22 from Screens.EventView import EventView
23 from Components.Harddisk import harddiskmanager
24
25 from Tools import Notifications
26
27 #from enigma import eTimer, eDVBVolumecontrol, quitMainloop
28 from enigma import *
29
30 import time
31 import os
32
33 # hack alert!
34 from Menu import MainMenu, mdom
35
36 class InfoBarVolumeControl:
37         """Volume control, handles volUp, volDown, volMute actions and display 
38         a corresponding dialog"""
39         def __init__(self):
40                 config.audio = ConfigSubsection()
41                 config.audio.volume = configElement("config.audio.volume", configSequence, [5], configsequencearg.get("INTEGER", (0, 100)))
42
43                 self["VolumeActions"] = ActionMap( ["InfobarVolumeActions"] ,
44                         {
45                                 "volumeUp": self.volUp,
46                                 "volumeDown": self.volDown,
47                                 "volumeMute": self.volMute,
48                         })
49
50                 self.volumeDialog = self.session.instantiateDialog(Volume)
51                 self.muteDialog = self.session.instantiateDialog(Mute)
52
53                 self.hideVolTimer = eTimer()
54                 self.hideVolTimer.timeout.get().append(self.volHide)
55
56                 vol = config.audio.volume.value[0]
57                 self.volumeDialog.setValue(vol)
58                 eDVBVolumecontrol.getInstance().setVolume(vol, vol)
59         
60         def volSave(self):
61                 config.audio.volume.value = eDVBVolumecontrol.getInstance().getVolume()
62                 config.audio.volume.save()
63                 
64         def     volUp(self):
65                 if (eDVBVolumecontrol.getInstance().isMuted()):
66                         self.volMute()
67                 eDVBVolumecontrol.getInstance().volumeUp()
68                 self.volumeDialog.instance.show()
69                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
70                 self.volSave()
71                 self.hideVolTimer.start(3000)
72
73         def     volDown(self):
74                 if (eDVBVolumecontrol.getInstance().isMuted()):
75                         self.volMute()
76                 eDVBVolumecontrol.getInstance().volumeDown()
77                 self.volumeDialog.instance.show()
78                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
79                 self.volSave()
80                 self.hideVolTimer.start(3000)
81                 
82         def volHide(self):
83                 self.volumeDialog.instance.hide()
84
85         def     volMute(self):
86                 eDVBVolumecontrol.getInstance().volumeToggleMute()
87                 self.volumeDialog.setValue(eDVBVolumecontrol.getInstance().getVolume())
88                 
89                 if (eDVBVolumecontrol.getInstance().isMuted()):
90                         self.muteDialog.instance.show()
91                 else:
92                         self.muteDialog.instance.hide()
93
94 class InfoBarDish:
95         def __init__(self):
96                 self.dishDialog = self.session.instantiateDialog(Dish)
97                 self.onShown.append(self.dishDialog.instance.hide)
98
99 class InfoBarShowHide:
100         """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
101         fancy animations. """
102         STATE_HIDDEN = 0
103         STATE_HIDING = 1
104         STATE_SHOWING = 2
105         STATE_SHOWN = 3
106         
107         def __init__(self):
108                 self["ShowHideActions"] = ActionMap( ["InfobarShowHideActions"] ,
109                         {
110                                 "toggleShow": self.toggleShow,
111                                 "hide": self.hide,
112                         })
113
114                 self.state = self.STATE_SHOWN
115                 
116                 self.onExecBegin.append(self.show)
117                 self.onClose.append(self.delHideTimer)
118                 
119                 self.hideTimer = eTimer()
120                 self.hideTimer.timeout.get().append(self.doTimerHide)
121                 self.hideTimer.start(5000)
122
123         def delHideTimer(self):
124                 del self.hideTimer
125
126         def hide(self): 
127                 self.instance.hide()
128                 
129         def show(self):
130                 self.state = self.STATE_SHOWN
131                 self.hideTimer.stop()
132                 self.hideTimer.start(5000)
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)          #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)
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)
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                 self.session.openWithCallback(self.numberEntered, NumberZap, number)
258
259         def numberEntered(self, retval):
260 #               print self.servicelist
261                 if retval > 0:
262                         self.zapToNumber(retval)
263
264         def searchNumberHelper(self, serviceHandler, num, bouquet):
265                 servicelist = serviceHandler.list(bouquet)
266                 if not servicelist is None:
267                         while num:
268                                 serviceIterator = servicelist.getNext()
269                                 if not serviceIterator.valid(): #check end of list
270                                         break
271                                 if serviceIterator.flags: #assume normal dvb service have no flags set
272                                         continue
273                                 num -= 1;
274                         if not num: #found service with searched number ?
275                                 return serviceIterator, 0
276                 return None, num
277
278         def zapToNumber(self, number):
279                 bouquet = self.servicelist.bouquet_root
280                 service = None
281                 serviceHandler = eServiceCenter.getInstance()
282                 if bouquet.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
283                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
284                 else:
285                         bouquetlist = serviceHandler.list(bouquet)
286                         if not bouquetlist is None:
287                                 while number:
288                                         bouquet = bouquetlist.getNext()
289                                         if not bouquet.valid(): #check end of list
290                                                 break
291                                         if ((bouquet.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
292                                                 continue
293                                         service, number = self.searchNumberHelper(serviceHandler, number, bouquet)
294                 if not service is None:
295                         self.session.nav.playService(service) #play service
296                         if self.servicelist.getRoot() != bouquet: #already in correct bouquet?
297                                 self.servicelist.setRoot(bouquet)
298                         self.servicelist.setCurrentSelection(service) #select the service in servicelist
299
300 class InfoBarChannelSelection:
301         """ ChannelSelection - handles the channelSelection dialog and the initial 
302         channelChange actions which open the channelSelection dialog """
303         def __init__(self):
304                 #instantiate forever
305                 self.servicelist = self.session.instantiateDialog(ChannelSelection)
306
307                 self["ChannelSelectActions"] = HelpableActionMap(self, "InfobarChannelSelection",
308                         {
309                                 "switchChannelUp": self.switchChannelUp,
310                                 "switchChannelDown": self.switchChannelDown,
311                                 "zapUp": (self.zapUp, _("next channel")),
312                                 "zapDown": (self.zapDown, _("previous channel")),
313                         })
314                         
315         def switchChannelUp(self):      
316                 self.servicelist.moveUp()
317                 self.session.execDialog(self.servicelist)
318
319         def switchChannelDown(self):    
320                 self.servicelist.moveDown()
321                 self.session.execDialog(self.servicelist)
322
323         def     zapUp(self):
324                 self.servicelist.moveUp()
325                 self.servicelist.zap()
326                 self.instance.show()
327                 self.show()
328
329         def     zapDown(self):
330                 self.servicelist.moveDown()
331                 self.servicelist.zap()
332                 self.instance.show()
333                 self.show()
334                 
335 class InfoBarMenu:
336         """ Handles a menu action, to open the (main) menu """
337         def __init__(self):
338                 self["MenuActions"] = HelpableActionMap(self, "InfobarMenuActions", 
339                         {
340                                 "mainMenu": (self.mainMenu, "Enter main menu..."),
341                         })
342
343         def mainMenu(self):
344                 print "loading mainmenu XML..."
345                 menu = mdom.childNodes[0]
346                 assert menu.tagName == "menu", "root element in menu must be 'menu'!"
347                 self.session.open(MainMenu, menu, menu.childNodes)
348
349 class InfoBarEPG:
350         """ EPG - Opens an EPG list when the showEPGList action fires """
351         def __init__(self):
352                 self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", 
353                         {
354                                 "showEPGList": (self.showEPGList, _("show EPG...")),
355                         })
356
357         def showEPGList(self):
358                 ref=self.session.nav.getCurrentlyPlayingServiceReference()
359                 ptr=eEPGCache.getInstance()
360                 if ptr.startTimeQuery(ref) != -1:
361                         self.session.open(EPGSelection, ref)
362                 else: # try to show now/next
363                         print 'no epg for service', ref.toString()
364                         try:
365                                 self.epglist = [ ]
366                                 service = self.session.nav.getCurrentService()
367                                 info = service.info()
368                                 ptr=info.getEvent(0)
369                                 if ptr:
370                                         self.epglist.append(ptr)
371                                 ptr=info.getEvent(1)
372                                 if ptr:
373                                         self.epglist.append(ptr)
374                                 if len(self.epglist) > 0:
375                                         self.session.open(EventView, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
376                         except:
377                                 pass
378
379         def eventViewCallback(self, setEvent, val): #used for now/next displaying
380                 if len(self.epglist) > 1:
381                         tmp = self.epglist[0]
382                         self.epglist[0]=self.epglist[1]
383                         self.epglist[1]=tmp
384                         setEvent(self.epglist[0])
385
386 class InfoBarEvent:
387         """provides a current/next event info display"""
388         def __init__(self):
389                 self["Event_Now_StartTime"] = EventInfo(self.session.nav, EventInfo.Now_StartTime)
390                 self["Event_Next_StartTime"] = EventInfo(self.session.nav, EventInfo.Next_StartTime)
391                                 
392                 self["Event_Now"] = EventInfo(self.session.nav, EventInfo.Now)
393                 self["Event_Next"] = EventInfo(self.session.nav, EventInfo.Next)
394
395                 self["Event_Now_Duration"] = EventInfo(self.session.nav, EventInfo.Now_Duration)
396                 self["Event_Next_Duration"] = EventInfo(self.session.nav, EventInfo.Next_Duration)
397
398 class InfoBarServiceName:
399         def __init__(self):
400                 self["ServiceName"] = ServiceName(self.session.nav)
401
402 class InfoBarPVR:
403         """handles PVR specific actions like seeking, pause"""
404         def __init__(self):
405                 self["PVRActions"] = HelpableActionMap(self, "InfobarPVRActions", 
406                         {
407                                 "pauseService": (self.pauseService, "pause"),
408                                 "unPauseService": (self.unPauseService, "continue"),
409                                 
410                                 "seekFwd": (self.seekFwd, "skip forward"),
411                                 "seekBack": (self.seekBack, "skip backward"),
412                         })
413                 
414         def pauseService(self):
415                 self.session.nav.pause(1)
416                 
417         def unPauseService(self):
418                 self.session.nav.pause(0)
419         
420         def doSeek(self, dir, seektime):
421                 service = self.session.nav.getCurrentService()
422                 if service is None:
423                         return
424                 
425                 seekable = service.seek()
426                 if seekable is None:
427                         return
428                 seekable.seekRelative(dir, 90 * seektime)
429
430         def seekFwd(self):
431                 self.doSeek(+1, 60000)
432         
433         def seekBack(self):
434                 self.doSeek(-1, 60000)
435
436 class InfoBarInstantRecord:
437         """Instant Record - handles the instantRecord action in order to 
438         start/stop instant records"""
439         def __init__(self):
440                 self["InstantRecordActions"] = HelpableActionMap(self, "InfobarInstantRecord",
441                         {
442                                 "instantRecord": (self.instantRecord, "Instant Record..."),
443                         })
444                 self.recording = None
445                 
446                 self["BlinkingPoint"] = BlinkingPixmapConditional()
447                 self.onShown.append(self["BlinkingPoint"].hideWidget)
448                 self["BlinkingPoint"].setConnect(self.session.nav.RecordTimer.isRecording)
449                 
450         def stopCurrentRecording(self): 
451                 self.session.nav.RecordTimer.removeEntry(self.recording)
452                 self.recording = None
453                         
454         def startInstantRecording(self):
455                 serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
456                         
457                 # try to get event info
458                 epg = None
459                 try:
460                         service = self.session.nav.getCurrentService()
461                         info = service.info()
462                         ev = info.getEvent(0)
463                         epg = ev
464                 except:
465                         pass
466                 
467                 # fix me, description. 
468                 self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600, serviceref, epg, "instant record")
469                 self.recording.dontSave = True
470                 
471                 #self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
472                 
473         def isInstantRecordRunning(self):
474                 if self.recording != None:
475                         if self.recording.isRunning():
476                                 return True
477                 return False
478
479         def recordQuestionCallback(self, answer):
480                 if answer == False:
481                         return
482                 
483                 if self.isInstantRecordRunning():
484                         self.stopCurrentRecording()
485                 else:
486                         self.startInstantRecording()
487
488         def instantRecord(self):
489                 try:
490                         stat = os.stat("/hdd/movies")
491                 except:
492                         self.session.open(MessageBox, "No HDD found!")
493                         return
494         
495                 if self.isInstantRecordRunning():
496                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Do you want to stop the current\n(instant) recording?"))
497                 else:
498                         self.session.openWithCallback(self.recordQuestionCallback, MessageBox, _("Start recording?"))
499
500 from Screens.AudioSelection import AudioSelection
501
502 class InfoBarAudioSelection:
503         def __init__(self):
504                 self["AudioSelectionAction"] = HelpableActionMap(self, "InfobarAudioSelectionActions", 
505                         {
506                                 "audioSelection": (self.audioSelection, "Audio Options..."),
507                         })
508
509         def audioSelection(self):
510                 service = self.session.nav.getCurrentService()
511                 audio = service.audioTracks()
512                 n = audio.getNumberOfTracks()
513                 if n > 0:
514                         self.session.open(AudioSelection, audio)
515
516 from Screens.SubserviceSelection import SubserviceSelection
517
518 class InfoBarSubserviceSelection:
519         def __init__(self):
520                 self["SubserviceSelectionAction"] = HelpableActionMap(self, "InfobarSubserviceSelectionActions",
521                         {
522                                 "subserviceSelection": (self.subserviceSelection, "Subservice list..."),
523                         })
524
525         def subserviceSelection(self):
526                 service = self.session.nav.getCurrentService()
527                 subservices = service.subServices()
528                 n = subservices.getNumberOfSubservices()
529                 if n > 0:
530                         self.session.openWithCallback(self.subserviceSelected, SubserviceSelection, subservices)
531
532         def subserviceSelected(self, service):
533                 if not service is None:
534                         self.session.nav.playService(service)
535
536 class InfoBarAdditionalInfo:
537         def __init__(self):
538                 self["DolbyActive"] = PixmapConditional()
539                 # TODO: get the info from c++ somehow
540                 self["DolbyActive"].setConnect(lambda: False)
541                 
542                 self["CryptActive"] = PixmapConditional()
543                 # TODO: get the info from c++ somehow
544                 self["CryptActive"].setConnect(lambda: False)
545                 
546                 self["FormatActive"] = PixmapConditional()
547                 # TODO: get the info from c++ somehow
548                 self["FormatActive"].setConnect(lambda: False)
549                 
550                 self["ButtonRed"] = PixmapConditional(withTimer = False)
551                 self["ButtonRed"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
552                 self.onShown.append(self["ButtonRed"].update)
553                 self["ButtonRedText"] = LabelConditional(text = _("Record"), withTimer = False)
554                 self["ButtonRedText"].setConnect(lambda: harddiskmanager.HDDCount() > 0)
555                 self.onShown.append(self["ButtonRedText"].update)
556                                 
557                 self["ButtonGreen"] = PixmapConditional()
558                 self["ButtonGreen"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
559                 self["ButtonGreenText"] = LabelConditional(text = _("Subservices"))
560                 self["ButtonGreenText"].setConnect(lambda: self.session.nav.getCurrentService().subServices().getNumberOfSubservices() > 0)
561
562                 self["ButtonYellow"] = PixmapConditional()
563                 self["ButtonYellow"].setConnect(lambda: False)
564
565                 self["ButtonBlue"] = PixmapConditional()
566                 self["ButtonBlue"].setConnect(lambda: False)
567
568 class InfoBarNotifications:
569         def __init__(self):
570                 self.onExecBegin.append(self.checkNotifications)
571                 Notifications.notificationAdded.append(self.checkNotificationsIfExecing)
572         
573         def checkNotificationsIfExecing(self):
574                 if self.execing:
575                         self.checkNotifications()
576
577         def checkNotifications(self):
578                 if len(Notifications.notifications):
579                         n = Notifications.notifications[0]
580                         Notifications.notifications = Notifications.notifications[1:]
581                         print "open",n
582                         cb = n[0]
583                         if cb is not None:
584                                 self.session.openWithCallback(cb, *n[1:])
585                         else:
586                                 self.session.open(*n[1:])