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