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