-add option to delay videomode switch x seconds after service started
[enigma2-plugins.git] / autoresolution / src / plugin.py
1 from Screens.Screen import Screen
2 from Screens.Setup import SetupSummary
3 from Screens.MessageBox import MessageBox
4 from Components.ConfigList import ConfigList, ConfigListScreen
5 from Components.config import config, getConfigListEntry, ConfigSelection, ConfigSubsection, ConfigYesNo, ConfigSubDict
6 from Components.ServiceEventTracker import ServiceEventTracker
7 from Components.ActionMap import ActionMap
8 from Components.Label import Label
9 from Components.Pixmap import Pixmap
10 from enigma import iPlayableService, iServiceInformation, eTimer
11 from Plugins.Plugin import PluginDescriptor
12 from Plugins.SystemPlugins.Videomode.VideoHardware import video_hw # depends on Videomode Plugin
13
14 session = [ ]
15
16 default = (config.av.videomode[config.av.videoport.value].value, _("default"))
17 preferedmodes = [mode[0] for mode in video_hw.getModeList(config.av.videoport.value) if mode[0] != default[0]]
18 preferedmodes.append(default)
19 resolutions = (('sd_i_50', (_("SD 25/50HZ Interlace Mode"))), ('sd_i_60', (_("SD 30/60HZ Interlace Mode"))), \
20                         ('sd_p_50', (_("SD 25/50HZ Progressive Mode"))), ('sd_p_60', (_("SD 30/60HZ Progressive Mode"))), \
21                         ('hd_i', (_("HD Interlace Mode"))), ('hd_p', (_("HD Progressive Mode"))), \
22                         ('p720_24', (_("Enable 720p24 Mode"))), ('p1080_24', (_("Enable 1080p24 Mode"))), \
23                         ('p1080_25', (_("Enable 1080p25 Mode"))), ('p1080_30', (_("Enable 1080p30 Mode"))))
24
25 config.plugins.autoresolution = ConfigSubsection()
26 config.plugins.autoresolution.enable = ConfigYesNo(default = False)
27 config.plugins.autoresolution.videoresolution = ConfigSubDict()
28 videoresolution_dictionary = {}
29 for mode in resolutions:
30         if mode[0].startswith('p1080'):
31                 choices = ['1080p24', '1080p25', '1080p30'] + preferedmodes
32         elif mode[0] == 'p720_24':
33                 choices = ['720p24', '1080p24'] + preferedmodes
34         else:
35                 choices = preferedmodes
36         config.plugins.autoresolution.videoresolution[mode[0]] = ConfigSelection(default = default[0], choices = choices)
37         videoresolution_dictionary[mode[0]] = (config.plugins.autoresolution.videoresolution[mode[0]])
38 config.plugins.autoresolution.showinfo = ConfigYesNo(default = True)
39 config.plugins.autoresolution.testmode = ConfigYesNo(default = False)
40 config.plugins.autoresolution.deinterlacer = ConfigSelection(default = "auto", choices =
41                 [("auto", _("auto")), ("off", _("off")), ("on", _("on"))])
42 config.plugins.autoresolution.delay_switch_mode = ConfigSelection(default = "500", choices = [
43                 ("500", _("immeadetly")), ("1000", "1 " + _("second")), ("2000", "2 " + _("seconds")), ("3000", "3 " + _("seconds")),
44                 ("4000", "4 " + _("seconds")), ("5000", "5 " + _("seconds")), ("6000", "6 " + _("seconds")), ("7000", "7 " + _("seconds")),
45                 ("8000", "8 " + _("seconds")), ("9000", "9 " + _("seconds")), ("10000", "10 " + _("seconds"))])
46
47 def setDeinterlacer(configElement):
48         mode = config.plugins.autoresolution.deinterlacer.value
49         print "[AutoRes] switch deinterlacer mode to %s" % mode
50         f = open('/proc/stb/vmpeg/deinterlace' , "w")
51         f.write("%s\n" % mode)
52         f.close()
53 config.plugins.autoresolution.deinterlacer.addNotifier(setDeinterlacer)
54
55 frqdic = { 23976: '24', \
56                 24000: '24', \
57                 25000: '25', \
58                 29970: '30', \
59                 30000: '30', \
60                 50000: '50', \
61                 59940: '60', \
62                 60000: '60'}
63
64 class AutoRes(Screen):
65         def __init__(self, session):
66                 Screen.__init__(self, session)
67                 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
68                         {
69                                 iPlayableService.evVideoSizeChanged: self.__evVideoSizeChanged,
70                                 iPlayableService.evVideoProgressiveChanged: self.__evVideoProgressiveChanged,
71                                 iPlayableService.evVideoFramerateChanged: self.__evVideoFramerateChanged,
72                                 iPlayableService.evStart: self.__evStart
73                         })
74                 self.timer = eTimer()
75                 self.timer.callback.append(self.determineContent)
76                 self.lastmode = config.av.videomode[config.av.videoport.value].value
77         
78         def __evStart(self):
79                 if self.timer.isActive():
80                         self.timer.stop()
81                 if config.plugins.autoresolution.enable.value:
82                         self.timer.start(int(config.plugins.autoresolution.delay_switch_mode.value))
83
84         def __evVideoFramerateChanged(self):
85                 print "[AutoRes] got event evFramerateChanged"
86                 if self.timer.isActive():
87                         self.timer.stop()
88                 if config.plugins.autoresolution.enable.value:
89                         self.timer.start(int(config.plugins.autoresolution.delay_switch_mode.value))
90
91         def __evVideoSizeChanged(self):
92                 print "[AutoRes] got event evVideoSizeChanged"
93                 if self.timer.isActive():
94                         self.timer.stop()
95                 if config.plugins.autoresolution.enable.value:
96                         self.timer.start(int(config.plugins.autoresolution.delay_switch_mode.value))
97
98         def __evVideoProgressiveChanged(self):
99                 print "[AutoRes] got event evVideoProgressiveChanged"
100                 if self.timer.isActive():
101                         self.timer.stop()
102                 if config.plugins.autoresolution.enable.value:
103                         self.timer.start(int(config.plugins.autoresolution.delay_switch_mode.value))
104
105         def determineContent(self):
106                 self.timer.stop()
107                 service = session.nav.getCurrentService()
108                 info = service and service.info()
109                 height = info and info.getInfo(iServiceInformation.sVideoHeight)
110                 width = info and info.getInfo(iServiceInformation.sVideoWidth)
111                 framerate = info and info.getInfo(iServiceInformation.sFrameRate)
112                 frate = str(framerate)[:2] #fallback?
113                 if frqdic.has_key(framerate):
114                         frate = frqdic[framerate]
115                 progressive = info and info.getInfo(iServiceInformation.sProgressive)
116                 if progressive == 1:
117                         prog = 'p'
118                 else:
119                         prog = 'i'
120                 print "[AutoRes] new content is %sx%s%s%s" %(width, height, prog, frate)
121                 self.determineVideoMode(width, height, prog, frate)
122
123         def determineVideoMode(self, width, height, prog, frate):
124                 if (height >= 900 or width >= 1600) and frate in ('24', '25', '30') and prog == 'p':    # 1080p content
125                         new_mode = 'p1080_%s' % frate
126                 elif (height >= 576 or width >= 720) and frate == '24' and prog == 'p':                 # 720p24 detection
127                         new_mode = 'p720_24'
128                 elif height > 576 or width > 720:                                                       #asume higher then 576 or greater then 720 is hd content
129                         new_mode = 'hd_%s' % prog
130                 else:                                                                                   # SD Content
131                         if frate in ('25', '50'):
132                                 new_mode = 'sd_%s_50' % prog
133                         else:
134                                 new_mode = 'sd_%s_60' % prog
135                 if videoresolution_dictionary.has_key(new_mode):
136                         new_mode = videoresolution_dictionary[new_mode].value
137                         print '[AutoRes] determined videomode', new_mode
138                         if new_mode != self.lastmode:
139                                 self.lastmode = new_mode
140                                 self.contentlabeltxt = "Videocontent: %sx%s%s %sHZ" % (width, height, prog, frate)
141                                 self.changeVideomode(new_mode)
142
143         def changeVideomode(self, mode):
144                 if mode.find("1080p") != -1 or mode.find("720p24") != -1:
145                         print "[AutoRes] switching to", mode
146                         v = open('/proc/stb/video/videomode' , "w")
147                         v.write("%s\n" % mode)
148                         v.close()
149                         resolutionlabeltxt = "Videomode: %s" % mode
150                 else:
151                         port = config.av.videoport.value
152                         rate = config.av.videorate[mode].value
153                         print "[AutoRes] switching to %s %s %s" % (port, mode, rate)
154                         video_hw.setMode(port, mode, rate)
155                         resolutionlabeltxt = 'Videomode: %s %s %s' % (port, mode, rate)
156                 if config.plugins.autoresolution.showinfo.value:
157                         resolutionlabel["restxt"].setText(resolutionlabeltxt)
158                         resolutionlabel["content"].setText(self.contentlabeltxt)
159                         resolutionlabel.show()
160                 if config.plugins.autoresolution.testmode.value:
161                         self.session.openWithCallback(
162                                 self.confirm,
163                                 MessageBox,
164                                 _("Autoresolution Plugin Testmode:\nIs %s ok?") % (resolutionlabeltxt),
165                                 MessageBox.TYPE_YESNO,
166                                 timeout = 15,
167                                 default = False
168                         )
169
170         def confirm(self, confirmed):
171                 if not confirmed:
172                         port = config.av.videoport.value
173                         mode = config.av.videomode[port].value
174                         rate = config.av.videorate[mode].value
175                         if config.plugins.autoresolution.showinfo.value:
176                                 resolutionlabel["restxt"].setText("Videomode: %s %s %s" % (port, mode, rate))
177                                 resolutionlabel.show()
178                         video_hw.setMode(port, mode, rate)
179
180 class ResolutionLabel(Screen):
181         skin = """
182                 <screen position="50,40" size="250,36" flags="wfNoBorder" >
183                         <widget name="content" position="0,0" size="250,18" font="Regular;16" />
184                         <widget name="restxt" position="0,18" size="250,18" font="Regular;16" />
185                 </screen>"""
186         def __init__(self, session):
187                 Screen.__init__(self, session)
188
189                 self["content"] = Label()
190                 self["restxt"] = Label()
191
192                 self.hideTimer = eTimer()
193                 self.hideTimer.callback.append(self.hide)
194
195                 self.onShow.append(self.hide_me)
196                 self.onHide.append(self.clean_me)
197
198         def hide_me(self):
199                 self.hideTimer.start(config.usage.infobar_timeout.index * 1500, True)
200
201         def clean_me(self):
202                 self["restxt"].setText("")
203                 self["content"].setText("")
204
205
206 class AutoResSetupMenu(Screen, ConfigListScreen):
207         def __init__(self, session):
208                 Screen.__init__(self, session)
209                 self.skinName = "Setup"
210                 self.setup_title = _("Autoresolution videomode setup")
211
212                 self.onChangedEntry = [ ]
213                 self.list = [ ]
214                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changedEntry)
215
216                 self["actions"] = ActionMap(["SetupActions"],
217                         {
218                                 "cancel": self.keyCancel,
219                                 "save": self.apply,
220                         }, -2)
221
222                 self["title"] = Label(_("Autoresolution settings"))
223
224                 self["oktext"] = Label(_("OK"))
225                 self["canceltext"] = Label(_("Cancel"))
226
227                 self["ok"] = Pixmap()
228                 self["cancel"] = Pixmap()
229
230                 self.createSetup()
231
232         def createSetup(self):
233                 self.list = [
234                         getConfigListEntry(_("Enable Autoresolution"), config.plugins.autoresolution.enable)
235                 ]
236                 if config.plugins.autoresolution.enable.value:
237                         for mode, label in resolutions:
238                                 self.list.append(getConfigListEntry(label, videoresolution_dictionary[mode]))
239                         self.list.extend((
240                                 getConfigListEntry(_("Show info screen"), config.plugins.autoresolution.showinfo),
241                                 getConfigListEntry(_("Delay x seconds after service started"), config.plugins.autoresolution.delay_switch_mode),
242                                 getConfigListEntry(_("Running in testmode"), config.plugins.autoresolution.testmode),
243                                 getConfigListEntry(_("Deinterlacer mode"), config.plugins.autoresolution.deinterlacer)
244                         ))
245                 self["config"].list = self.list
246                 self["config"].setList(self.list)
247
248         def apply(self):
249                 for x in self["config"].list:
250                         x[1].save()
251                 self.close()
252
253         def keyLeft(self):
254                 ConfigListScreen.keyLeft(self)
255                 self.createSetup()
256
257         def keyRight(self):
258                 ConfigListScreen.keyRight(self)
259                 self.createSetup()
260
261         # for summary:
262         def changedEntry(self):
263                 for x in self.onChangedEntry:
264                         x()
265
266         def getCurrentEntry(self):
267                 return self["config"].getCurrent()[0]
268
269         def getCurrentValue(self):
270                 return str(self["config"].getCurrent()[1].getText())
271
272         def createSummary(self):
273                 return SetupSummary
274
275
276 def autostart(reason, **kwargs):
277         global session, resolutionlabel
278         if "session" in kwargs:
279                 session = kwargs["session"]
280                 resolutionlabel = session.instantiateDialog(ResolutionLabel)
281                 AutoRes(session)
282
283 def startSetup(menuid):
284         if menuid != "system":
285                 return [ ]
286         return [("Autoresolution...", autoresSetup, "autores_setup", 45)]
287
288 def autoresSetup(session, **kwargs):
289         session.open(AutoResSetupMenu)
290
291 def Plugins(path, **kwargs):
292         return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART], fnc = autostart), \
293                 PluginDescriptor(name="Autoresolution", description=_("Autoresolution Switch"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup) ]