1 from enigma import eTimer
2 from Components.config import config, ConfigSelection, ConfigSubDict, ConfigYesNo
4 from Tools.CList import CList
5 from Tools.HardwareInfo import HardwareInfo
7 # The "VideoHardware" is the interface to /proc/stb/video.
8 # It generates hotplug events, and gives you the list of
9 # available and preferred modes, as well as handling the currently
10 # selected mode. No other strict checking is done.
12 rates = { } # high-level, use selectable modes.
14 modes = { } # a list of (high-level) modes for a certain port.
16 rates["PAL"] = { "50Hz": { 50: "pal" },
17 "60Hz": { 60: "pal60" },
18 "multi": { 50: "pal", 60: "pal60" } }
20 rates["NTSC"] = { "60Hz": { 60: "ntsc" } }
22 rates["Multi"] = { "multi": { 50: "pal", 60: "ntsc" } }
24 rates["480i"] = { "60Hz": { 60: "480i" } }
26 rates["576i"] = { "50Hz": { 50: "576i" } }
28 rates["480p"] = { "60Hz": { 60: "480p" } }
30 rates["576p"] = { "50Hz": { 50: "576p" } }
32 rates["720p"] = { "50Hz": { 50: "720p50" },
33 "60Hz": { 60: "720p" },
34 "multi": { 50: "720p50", 60: "720p" } }
36 rates["1080i"] = { "50Hz": { 50: "1080i50" },
37 "60Hz": { 60: "1080i" },
38 "multi": { 50: "1080i50", 60: "1080i" } }
41 "1024x768": { 60: "1024x768" }, # not possible on DM7025
42 "800x600" : { 60: "800x600" }, # also not possible
43 "720x480" : { 60: "720x480" },
44 "720x576" : { 60: "720x576" },
45 "1280x720": { 60: "1280x720" },
46 "1280x720 multi": { 50: "1280x720_50", 60: "1280x720" },
47 "1920x1080": { 60: "1920x1080"},
48 "1920x1080 multi": { 50: "1920x1080", 60: "1920x1080_50" },
49 "1280x1024" : { 60: "1280x1024"},
50 "1366x768" : { 60: "1366x768"},
51 "1366x768 multi" : { 50: "1366x768", 60: "1366x768_50" },
52 "1280x768": { 60: "1280x768" },
53 "640x480" : { 60: "640x480" }
56 modes["Scart"] = ["PAL", "NTSC", "Multi"]
57 modes["YPbPr"] = ["720p", "1080i", "576p", "480p", "576i", "480i"]
58 modes["DVI"] = ["720p", "1080i", "576p", "480p", "576i", "480i"]
59 modes["DVI-PC"] = ["PC"]
61 widescreen_modes = set(["720p", "1080i"])
63 def getOutputAspect(self):
65 port = config.av.videoport.value
66 if port not in config.av.videomode:
67 print "current port not available in getOutputAspect!!! force 16:9"
69 mode = config.av.videomode[port].value
70 force_widescreen = self.isWidescreenMode(port, mode)
71 is_widescreen = force_widescreen or config.av.aspect.value in ("16_9", "16_10")
72 is_auto = config.av.aspect.value == "auto"
77 aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value]
82 aspect_str = open("/proc/stb/vmpeg/0/aspect", "r").read()
83 if aspect_str == "1": # 4:3
92 self.last_modes_preferred = [ ]
93 self.on_hotplug = CList()
94 self.current_mode = None
95 self.current_port = None
97 self.readAvailableModes()
99 if self.modes.has_key("DVI-PC") and not self.getModeList("DVI-PC"):
100 print "remove DVI-PC because of not existing modes"
101 del self.modes["DVI-PC"]
104 # self.on_hotplug.append(self.createConfig)
106 self.readPreferredModes()
108 # take over old AVSwitch component :)
109 from Components.AVSwitch import AVSwitch
110 # config.av.colorformat.notifiers = [ ]
111 config.av.aspectratio.notifiers = [ ]
112 config.av.tvsystem.notifiers = [ ]
113 config.av.wss.notifiers = [ ]
114 AVSwitch.getOutputAspect = self.getOutputAspect
116 config.av.aspect.addNotifier(self.updateAspect)
117 config.av.wss.addNotifier(self.updateAspect)
118 config.av.policy_169.addNotifier(self.updateAspect)
119 config.av.policy_43.addNotifier(self.updateAspect)
121 # until we have the hotplug poll socket
122 # self.timer = eTimer()
123 # self.timer.callback.append(self.readPreferredModes)
124 # self.timer.start(1000)
126 def readAvailableModes(self):
128 modes = open("/proc/stb/video/videomode_choices").read()[:-1]
130 print "couldn't read available videomodes."
131 self.modes_available = [ ]
133 self.modes_available = modes.split(' ')
135 def readPreferredModes(self):
137 modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
138 self.modes_preferred = modes.split(' ')
140 print "reading preferred modes failed, using all modes"
141 self.modes_preferred = self.modes_available
143 if self.modes_preferred != self.last_modes_preferred:
144 self.last_modes_preferred = self.modes_preferred
145 print "hotplug on dvi"
146 self.on_hotplug("DVI") # must be DVI
148 # check if a high-level mode with a given rate is available.
149 def isModeAvailable(self, port, mode, rate):
150 rate = self.rates[mode][rate]
151 for mode in rate.values():
152 # DVI modes must be in "modes_preferred"
154 # if mode not in self.modes_preferred and not config.av.edid_override.value:
155 # print "no, not preferred"
157 if mode not in self.modes_available:
161 def isWidescreenMode(self, port, mode):
162 return mode in self.widescreen_modes
164 def setMode(self, port, mode, rate, force = None):
165 print "setMode - port:", port, "mode:", mode, "rate:", rate
166 # we can ignore "port"
167 self.current_mode = mode
168 self.current_port = port
169 modes = self.rates[mode][rate]
171 mode_50 = modes.get(50)
172 mode_60 = modes.get(60)
173 if mode_50 is None or force == 60:
175 if mode_60 is None or force == 50:
179 open("/proc/stb/video/videomode_50hz", "w").write(mode_50)
180 open("/proc/stb/video/videomode_60hz", "w").write(mode_60)
183 # fallback if no possibility to setup 50/60 hz mode
184 open("/proc/stb/video/videomode", "w").write(mode_50)
186 print "setting videomode failed."
189 open("/etc/videomode", "w").write(mode_50) # use 50Hz mode (if available) for booting
191 print "writing initial videomode to /etc/videomode failed."
193 self.updateAspect(None)
195 def saveMode(self, port, mode, rate):
196 print "saveMode", port, mode, rate
197 config.av.videoport.value = port
198 config.av.videoport.save()
199 config.av.videomode[port].value = mode
200 config.av.videomode[port].save()
201 config.av.videorate[mode].value = rate
202 config.av.videorate[mode].save()
204 def isPortAvailable(self, port):
208 def isPortUsed(self, port):
210 self.readPreferredModes()
211 return len(self.modes_preferred) != 0
215 def getPortList(self):
216 return [port for port in self.modes if self.isPortAvailable(port)]
218 # get a list with all modes, with all rates, for a given port.
219 def getModeList(self, port):
220 print "getModeList for port", port
222 for mode in self.modes[port]:
223 # list all rates which are completely valid
224 rates = [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
226 # if at least one rate is ok, add this mode
228 res.append( (mode, rates) )
231 def createConfig(self, *args):
232 hw_type = HardwareInfo().get_device_name()
235 config.av.videomode = ConfigSubDict()
236 config.av.videorate = ConfigSubDict()
238 # create list of output ports
239 portlist = self.getPortList()
240 for port in portlist:
242 if descr == 'DVI' and hw_type in ('dm500hd', 'dm800se', 'dm7020hd'):
244 elif descr == 'DVI-PC' and hw_type in ('dm500hd', 'dm800se', 'dm7020hd'):
246 lst.append((port, descr))
248 # create list of available modes
249 modes = self.getModeList(port)
251 config.av.videomode[port] = ConfigSelection(choices = [mode for (mode, rates) in modes])
252 for (mode, rates) in modes:
253 config.av.videorate[mode] = ConfigSelection(choices = rates)
254 config.av.videoport = ConfigSelection(choices = lst)
256 def setConfiguredMode(self):
257 port = config.av.videoport.value
258 if port not in config.av.videomode:
259 print "current port not available, not setting videomode"
262 mode = config.av.videomode[port].value
264 if mode not in config.av.videorate:
265 print "current mode not available, not setting videomode"
268 rate = config.av.videorate[mode].value
269 self.setMode(port, mode, rate)
271 def updateAspect(self, cfgelement):
272 # determine aspect = {any,4:3,16:9,16:10}
273 # determine policy = {bestfit,letterbox,panscan,nonlinear}
276 # config.av.videoport.value: current video output device
279 # 4_3: use policy_169
280 # 16_9,16_10: use policy_43
281 # auto always "bestfit"
282 # config.av.policy_169
283 # letterbox use letterbox
284 # panscan use panscan
286 # config.av.policy_43
287 # pillarbox use panscan
288 # panscan use letterbox ("panscan" is just a bad term, it's inverse-panscan)
289 # nonlinear use nonlinear
292 port = config.av.videoport.value
293 if port not in config.av.videomode:
294 print "current port not available, not setting videomode"
296 mode = config.av.videomode[port].value
298 force_widescreen = self.isWidescreenMode(port, mode)
300 is_widescreen = force_widescreen or config.av.aspect.value in ("16_9", "16_10")
301 is_auto = config.av.aspect.value == "auto"
302 policy2 = "policy" # use main policy
308 aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value]
309 policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value]
310 policy2 = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
316 policy = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
318 if not config.av.wss.value:
319 wss = "auto(4:3_off)"
323 print "-> setting aspect, policy, policy2, wss", aspect, policy, policy2, wss
324 open("/proc/stb/video/aspect", "w").write(aspect)
325 open("/proc/stb/video/policy", "w").write(policy)
326 open("/proc/stb/denc/0/wss", "w").write(wss)
328 open("/proc/stb/video/policy2", "w").write(policy2)
332 config.av.edid_override = ConfigYesNo(default = False)
333 video_hw = VideoHardware()
334 video_hw.setConfiguredMode()