1 from enigma import eTimer
2 from Components.config import config, ConfigSelection, ConfigSubDict, ConfigYesNo
4 from Tools.CList import CList
6 # The "VideoHardware" is the interface to /proc/stb/video.
7 # It generates hotplug events, and gives you the list of
8 # available and preferred modes, as well as handling the currently
9 # selected mode. No other strict checking is done.
11 rates = { } # high-level, use selectable modes.
13 modes = { } # a list of (high-level) modes for a certain port.
15 rates["PAL"] = { "50Hz": { 50: "pal" },
16 "60Hz": { 60: "pal60" },
17 "multi": { 50: "pal", 60: "pal60" } }
19 rates["NTSC"] = { "60Hz": { 60: "ntsc" } }
21 rates["Multi"] = { "multi": { 50: "pal", 60: "ntsc" } }
23 rates["480i"] = { "60Hz": { 60: "480i" } }
25 rates["576i"] = { "50Hz": { 50: "576i" } }
27 rates["480p"] = { "60Hz": { 60: "480p" } }
29 rates["576p"] = { "50Hz": { 50: "576p" } }
31 rates["720p"] = { "50Hz": { 50: "720p50" },
32 "60Hz": { 60: "720p" },
33 "multi": { 50: "720p50", 60: "720p" } }
35 rates["1080i"] = { "50Hz": { 50: "1080i50" },
36 "60Hz": { 60: "1080i" },
37 "multi": { 50: "1080i50", 60: "1080i" } }
40 "1024x768": { 60: "1024x768" }, # not possible on DM7025
41 "800x600" : { 60: "800x600" }, # also not possible
42 "720x480" : { 60: "720x480" },
43 "720x576" : { 60: "720x576" },
44 "1280x720": { 60: "1280x720" },
45 "1280x720 multi": { 50: "1280x720_50", 60: "1280x720" },
46 "1920x1080": { 60: "1920x1080"},
47 "1920x1080 multi": { 50: "1920x1080", 60: "1920x1080_50" },
48 "1280x1024" : { 60: "1280x1024"},
49 "1366x768" : { 60: "1366x768"},
50 "1366x768 multi" : { 50: "1366x768", 60: "1366x768_50" },
51 "1280x768": { 60: "1280x768" },
52 "640x480" : { 60: "640x480" }
55 modes["Scart"] = ["PAL", "NTSC", "Multi"]
56 modes["YPbPr"] = ["720p", "1080i", "576p", "480p", "576i", "480i"]
57 modes["DVI"] = ["720p", "1080i", "576p", "480p", "576i", "480i"]
58 modes["DVI-PC"] = ["PC"]
60 widescreen_modes = set(["720p", "1080i"])
63 self.last_modes_preferred = [ ]
64 self.on_hotplug = CList()
66 self.current_mode = None
67 self.current_port = None
69 self.readAvailableModes()
72 # self.on_hotplug.append(self.createConfig)
74 self.readPreferredModes()
76 # take over old AVSwitch component :)
77 from Components.AVSwitch import AVSwitch
78 # config.av.colorformat.notifiers = [ ]
79 config.av.aspectratio.notifiers = [ ]
80 config.av.tvsystem.notifiers = [ ]
81 config.av.wss.notifiers = [ ]
82 AVSwitch.setInput = self.AVSwitchSetInput
84 config.av.aspect.addNotifier(self.updateAspect)
85 config.av.wss.addNotifier(self.updateAspect)
86 config.av.policy_169.addNotifier(self.updateAspect)
87 config.av.policy_43.addNotifier(self.updateAspect)
89 # until we have the hotplug poll socket
90 # self.timer = eTimer()
91 # self.timer.callback.append(self.readPreferredModes)
92 # self.timer.start(1000)
94 config.av.colorformat.addNotifier(self.updateFastblank)
96 def AVSwitchSetInput(self, mode):
97 self.standby = mode == "SCART"
100 def readAvailableModes(self):
102 modes = open("/proc/stb/video/videomode_choices").read()[:-1]
104 print "couldn't read available videomodes."
105 self.modes_available = [ ]
107 self.modes_available = modes.split(' ')
109 def readPreferredModes(self):
111 modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
112 self.modes_preferred = modes.split(' ')
114 print "reading preferred modes failed, using all modes"
115 self.modes_preferred = self.modes_available
117 if self.modes_preferred != self.last_modes_preferred:
118 self.last_modes_preferred = self.modes_preferred
119 print "hotplug on dvi"
120 self.on_hotplug("DVI") # must be DVI
122 # check if a high-level mode with a given rate is available.
123 def isModeAvailable(self, port, mode, rate):
124 rate = self.rates[mode][rate]
125 for mode in rate.values():
126 # DVI modes must be in "modes_preferred"
128 # if mode not in self.modes_preferred and not config.av.edid_override.value:
129 # print "no, not preferred"
131 if mode not in self.modes_available:
135 def isWidescreenMode(self, port, mode):
136 return mode in self.widescreen_modes
138 def setMode(self, port, mode, rate, force = None):
139 print "setMode - port:", port, "mode:", mode, "rate:", rate
140 # we can ignore "port"
141 self.current_mode = mode
142 self.current_port = port
143 modes = self.rates[mode][rate]
145 mode_50 = modes.get(50)
146 mode_60 = modes.get(60)
147 if mode_50 is None or force == 60:
149 if mode_60 is None or force == 50:
153 open("/proc/stb/video/videomode_50hz", "w").write(mode_50)
154 open("/proc/stb/video/videomode_60hz", "w").write(mode_60)
157 # fallback if no possibility to setup 50/60 hz mode
158 open("/proc/stb/video/videomode", "w").write(mode_50)
160 print "setting videomode failed."
163 open("/etc/videomode", "w").write(mode_50) # use 50Hz mode (if available) for booting
165 print "writing initial videomode to /etc/videomode failed."
167 self.updateAspect(None)
169 def saveMode(self, port, mode, rate):
170 config.av.videoport.value = port
171 config.av.videoport.save()
172 config.av.videomode[port].value = mode
173 config.av.videomode[port].save()
174 config.av.videorate[mode].value = rate
175 config.av.videorate[mode].save()
177 def isPortAvailable(self, port):
181 def isPortUsed(self, port):
183 self.readPreferredModes()
184 return len(self.modes_preferred) != 0
188 def getPortList(self):
189 return [port for port in self.modes if self.isPortAvailable(port)]
191 # get a list with all modes, with all rates, for a given port.
192 def getModeList(self, port):
193 print "getModeList for port", port
195 for mode in self.modes[port]:
196 # list all rates which are completely valid
197 rates = [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
199 # if at least one rate is ok, add this mode
201 res.append( (mode, rates) )
204 def createConfig(self, *args):
205 # create list of output ports
206 portlist = self.getPortList()
208 # create list of available modes
209 config.av.videoport = ConfigSelection(choices = [(port, _(port)) for port in portlist])
210 config.av.videomode = ConfigSubDict()
211 config.av.videorate = ConfigSubDict()
213 for port in portlist:
214 modes = self.getModeList(port)
216 config.av.videomode[port] = ConfigSelection(choices = [mode for (mode, rates) in modes])
217 for (mode, rates) in modes:
218 config.av.videorate[mode] = ConfigSelection(choices = rates)
220 def setConfiguredMode(self):
221 port = config.av.videoport.value
222 if port not in config.av.videomode:
223 print "current port not available, not setting videomode"
226 mode = config.av.videomode[port].value
228 if mode not in config.av.videorate:
229 print "current mode not available, not setting videomode"
232 rate = config.av.videorate[mode].value
233 self.setMode(port, mode, rate)
235 def updateAspect(self, cfgelement):
236 # determine aspect = {any,4:3,16:9,16:10}
237 # determine policy = {bestfit,letterbox,panscan,nonlinear}
240 # config.av.videoport.value: current video output device
243 # 4_3: use policy_169
244 # 16_9,16_10: use policy_43
245 # auto always "bestfit"
246 # config.av.policy_169
247 # letterbox use letterbox
248 # panscan use panscan
250 # config.av.policy_43
251 # pillarbox use panscan
252 # panscan use letterbox ("panscan" is just a bad term, it's inverse-panscan)
253 # nonlinear use nonlinear
256 port = config.av.videoport.value
257 if port not in config.av.videomode:
258 print "current port not available, not setting videomode"
260 mode = config.av.videomode[port].value
262 force_widescreen = self.isWidescreenMode(port, mode)
264 is_widescreen = force_widescreen or config.av.aspect.value in ["16_9", "16_10"]
265 is_auto = config.av.aspect.value == "auto"
271 aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value]
272 policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value]
278 policy = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
280 if not config.av.wss.value:
281 wss = "auto(4:3_off)"
285 print "-> setting aspect, policy, wss", aspect, policy, wss
286 open("/proc/stb/video/aspect", "w").write(aspect)
287 open("/proc/stb/video/policy", "w").write(policy)
288 open("/proc/stb/denc/0/wss", "w").write(wss)
289 self.updateSlowblank()
290 self.updateFastblank()
292 def updateSlowblank(self):
294 from Components.SystemInfo import SystemInfo
295 if SystemInfo["ScartSwitch"]:
305 open("/proc/stb/avs/0/sb", "w").write(sb)
306 open("/proc/stb/avs/0/input", "w").write(input)
308 def updateStandby(self):
309 self.updateSlowblank()
310 self.updateFastblank()
312 def updateFastblank(self, *args):
314 from Components.SystemInfo import SystemInfo
315 if SystemInfo["ScartSwitch"]:
320 if self.current_port == "Scart" and config.av.colorformat.value == "rgb":
324 open("/proc/stb/avs/0/fb", "w").write(fb)
326 config.av.edid_override = ConfigYesNo(default = False)
327 video_hw = VideoHardware()
328 video_hw.setConfiguredMode()