1 from Components.config import config, ConfigSubDict, ConfigSelection, ConfigNothing, NoSave
2 from Tools.CList import CList
3 from Tools.HardwareInfo import HardwareInfo
6 # VideoHardware is the interface to /proc/stb/video.
10 modes = { # a list of modes for available port
11 "Scart" : ["PAL", "NTSC", "Multi"],
12 "YPbPr" : ["720p", "1080i", "576p", "480p", "576i", "480i"],
13 "DVI" : ["720p", "1080i", "576p", "480p", "576i", "480i"],
16 rates = { # list of rates for available mode
17 "PAL": { "50Hz" : {50: "pal"},
18 "60Hz" : {60: "pal60"},
19 "multi": {50: "pal", 60: "pal60"}
21 "NTSC": { "60Hz" : {60: "ntsc"} },
22 "Multi": { "multi": {50: "pal", 60: "ntsc"} },
23 "480i": { "60Hz" : {60: "480i"} },
24 "576i": { "50Hz" : {50: "576i"} },
25 "480p": { "60Hz" : {60: "480p"} },
26 "576p": { "50Hz" : {50: "576p"} },
28 "50Hz" : {50: "720p50"},
29 "60Hz" : {60: "720p"},
30 "multi": {50: "720p50", 60: "720p"}
33 "50Hz" : {50: "1080i50"},
34 "60Hz" : {60: "1080i"},
35 "multi": {50: "1080i50", 60: "1080i"}
38 "50Hz" : {50: "1080p50"},
39 "60Hz" : {60: "1080p"},
40 "multi": {50: "1080p50", 60: "1080p"}
43 "50Hz" : {50: "2160p50"},
44 "60Hz" : {60: "2160p"},
45 "multi": {50: "2160p50", 60: "2160p"}
48 "1024x768": {60: "1024x768"},
49 "800x600" : {60: "800x600"},
50 "720x480" : {60: "720x480"},
51 "720x576" : {60: "720x576"},
52 "1280x720": {60: "1280x720"},
53 "1280x720 multi": {50: "1280x720_50", 60: "1280x720"},
54 "1920x1080": {60: "1920x1080"},
55 "1920x1080 multi": {50: "1920x1080", 60: "1920x1080_50"},
56 "1280x1024": {60: "1280x1024"},
57 "1366x768": {60: "1366x768"},
58 "1366x768 multi": {50: "1366x768", 60: "1366x768_50"},
59 "1280x768": {60: "1280x768"},
60 "640x480" : {60: "640x480"}
64 widescreen_modes = set(["720p", "1080i", "1080p", "2160p"])
65 hdmi_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k", "ultimo4k", "uno4k", "uno4kse", "zero4k", "duo4k", "duo4kse"])
66 hdmi_pc_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k", "ultimo4k", "uno4k", "uno4kse", "zero4k", "duo4k", "duo4kse"])
67 noscart_hw_types = set(["zero", "solo4k", "ultimo4k", "uno4k", "uno4kse", "zero4k", "duo4k", "duo4kse"])
68 noypbpr_hw_types = set(["solose", "zero", "solo4k", "ultimo4k", "uno4k", "uno4kse", "zero4k", "duo4k", "duo4kse"])
70 def getDeviceName(self):
71 device_name = "unknown"
73 file = open("/proc/stb/info/vumodel", "r")
74 device_name = file.readline().strip()
77 from Tools.HardwareInfo import HardwareInfo
78 device_name = HardwareInfo.get_device_name()
82 def isVumodel(self, hw_type):
83 return hw_type in set(["bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k", "ultimo4k", "uno4k", "uno4kse", "zero4k", "duo4k", "duo4kse"])
85 def isVumodel4K(self, hw_type):
86 return hw_type in set(["solo4k", "ultimo4k", "uno4k", "uno4kse", "zero4k", "duo4k", "duo4kse"])
88 # re-define AVSwitch.getOutputAspect
89 def getOutputAspect(self):
91 port = config.av.videoport.value
92 if port not in config.av.videomode:
93 print "current port is not available. force 16:9"
95 mode = config.av.videomode[port].value
96 force_wide = self.isWidescreenMode(mode)
97 valstr = config.av.aspect.value
101 elif valstr == "16_10":
103 elif valstr == "auto":
105 aspect_str = open("/proc/stb/vmpeg/0/aspect", "r").read()
106 if aspect_str == "1": # 4:3
110 elif valstr == "4_3":
115 self.last_modes_preferred = [ ]
116 self.on_hotplug = CList()
118 self.readAvailableModes()
120 if self.modes.has_key("DVI-PC") and not self.getModeList("DVI-PC"):
121 print "remove DVI-PC because it does not exist."
122 del self.modes["DVI-PC"]
124 if self.isNoScart(self.getDeviceName()):
125 if self.modes.has_key("Scart"):
126 print "remove Scart because it does not exist."
127 del self.modes["Scart"]
129 if self.isNoYPbPr(self.getDeviceName()):
130 if self.modes.has_key("YPbPr"):
131 print "remove YPbPr because it does not exist."
132 del self.modes["YPbPr"]
136 self.readPreferredModes()
138 # re-define AVSwitch components
139 from Components.AVSwitch import AVSwitch
140 config.av.aspectratio.notifiers = [ ]
141 config.av.tvsystem.notifiers = [ ]
142 config.av.wss.notifiers = [ ]
143 AVSwitch.getOutputAspect = self.getOutputAspect
145 config.av.aspect.addNotifier(self.changedAspect)
146 config.av.wss.addNotifier(self.changedAspect)
147 config.av.policy_169.addNotifier(self.changedAspect)
148 config.av.policy_43.addNotifier(self.changedAspect)
150 # addNotifiers for port, mode, rate
151 config.av.videoport.addNotifier(self.changedVideomode)
152 for port in self.getPortList():
153 config.av.videomode[port].addNotifier(self.changedVideomode)
154 for mode in self.getModeList(port):
155 config.av.videorate[mode[0]].addNotifier(self.changedVideomode)
159 def readAvailableModes(self):
161 modes = open("/proc/stb/video/videomode_choices").read()[:-1]
162 self.modes_available = modes.split(' ')
164 print "failed to read video_choices."
165 self.modes_available = [ ]
167 def readPreferredModes(self):
169 modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
170 self.modes_preferred = modes.split(' ')
172 print "failed to read video_preferred."
173 self.modes_preferred = self.modes_available
175 if self.modes_preferred != self.last_modes_preferred:
176 self.last_modes_preferred = self.modes_preferred
177 print "hotplug on DVI"
178 self.on_hotplug("DVI") # must be DVI
180 # check if HDMI is available
181 def isHDMIAvailable(self, hw_type):
182 return hw_type in self.hdmi_hw_types
184 # check if HDMI-PC is available
185 def isHDMI_PCAvailable(self, hw_type):
186 return hw_type in self.hdmi_pc_hw_types
188 # check if mode is always widescreen
189 def isWidescreenMode(self, mode):
190 return mode in self.widescreen_modes
192 # check if Scart is not available
193 def isNoScart(self, hw_type):
194 return hw_type in self.noscart_hw_types
196 # check if YPbPr is not available
197 def isNoYPbPr(self, hw_type):
198 return hw_type in self.noypbpr_hw_types
200 # check if rate is available for mode
201 def isModeAvailable(self, port, mode, rate):
202 rate = self.rates[mode][rate]
203 for mode in rate.values():
204 if mode not in self.modes_available:
209 # check isModeAvailable in this port
210 def isPortAvailable(self, port):
211 for mode in self.getModeList(port):
212 if len(self.getRateList(port, mode[0])):
217 # get a list of all available port
218 def getPortList(self):
219 return [port for port in self.modes if self.isPortAvailable(port)]
221 # get a list of all available mode for a given port
222 def getModeList(self, port):
224 for mode in self.modes[port]:
225 rates = self.getRateList(port, mode)
228 modelist.append( (mode, rates))
232 # get a list of all available rate for a given port, mode
233 def getRateList(self, port, mode):
234 return [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
236 def createConfig(self):
237 config.av.videomode = ConfigSubDict()
238 config.av.videorate = ConfigSubDict()
240 hw_type = self.getDeviceName()
242 if self.isVumodel(hw_type):
243 self.modes["DVI"].insert(self.modes["DVI"].index("1080i")+1, "1080p")
245 if self.isVumodel4K(hw_type):
246 self.modes["DVI"].insert(self.modes["DVI"].index("1080p")+1, "2160p")
249 port_choices = self.getPortList()
251 for port in port_choices:
253 if desc == 'DVI' and self.isHDMIAvailable(hw_type):
255 if desc == 'DVI-PC' and self.isHDMI_PCAvailable(hw_type):
257 portlist.append( (port, desc))
259 # create list of available modes
261 mode_choices = self.getModeList(port)
263 for mode in mode_choices:
264 modelist.append( (mode[0], mode[0]))
266 # create list of available rates
268 rate_choices = self.getRateList(port, mode[0])
270 for rate in rate_choices:
271 ratelist.append( (rate, rate))
273 config.av.videorate[mode[0]] = ConfigSelection(choices = ratelist)
274 config.av.videomode[port] = ConfigSelection(choices = modelist)
275 config.av.videoport = ConfigSelection(choices = portlist)
277 if os.path.exists("/proc/stb/video/hdmi_colorspace"):
278 def setHdmiColorspace(config):
280 print "set HDMI Colorspace : ",config.value
281 f = open("/proc/stb/video/hdmi_colorspace", "w")
282 f.write(config.value)
285 print "set HDMI Colorspace failed!"
286 hdmicolorspace_choices = {}
287 hdmicolorspace_choices["Edid(Auto)"] = _("Auto")
288 hdmicolorspace_choices["Hdmi_Rgb"] = _("RGB")
289 hdmicolorspace_choices["444"] = _("YCbCr444")
290 hdmicolorspace_choices["422"] = _("YCbCr422")
291 hdmicolorspace_choices["420"] = _("YCbCr420")
292 config.av.hdmicolorspace = ConfigSelection(choices = hdmicolorspace_choices, default = "Edid(Auto)")
293 config.av.hdmicolorspace.addNotifier(setHdmiColorspace)
295 config.av.hdmicolorspace = NoSave(ConfigNothing())
297 if os.path.exists("/proc/stb/video/hdmi_colordepth"):
298 def setHdmiColordepth(config):
300 print "set HDMI Colordepth : ",config.value
301 f = open("/proc/stb/video/hdmi_colordepth", "w")
302 f.write(config.value)
305 print "set HDMI Colordepth failed!"
306 hdmicolordepth_choices = {}
307 hdmicolordepth_choices["auto"] = _("Auto")
308 hdmicolordepth_choices["8bit"] = _("8bit")
309 hdmicolordepth_choices["10bit"] = _("10bit")
310 hdmicolordepth_choices["12bit"] = _("12bit")
311 config.av.hdmicolordepth = ConfigSelection(choices = hdmicolordepth_choices, default = "auto")
312 config.av.hdmicolordepth.addNotifier(setHdmiColordepth)
314 config.av.hdmicolordepth = NoSave(ConfigNothing())
316 def changedVideomode(self, configElement):
320 self.setConfiguredMode()
322 def setConfiguredMode(self):
323 port = config.av.videoport.value
324 mode = config.av.videomode[port].value
325 rate = config.av.videorate[mode].value
327 self.setVideomode(port, mode, rate)
329 def setVideomode(self, port, mode, rate):
330 if port is None or port not in config.av.videomode:
331 print "current port not available. couldn't set videomode"
334 if mode not in config.av.videorate:
335 print "current mode not available. couldn't set videomode"
339 modelist = self.getModeList(port)
340 mode = modelist[0][0]
342 ratelist = self.getRateList(port, mode)
346 ratelist = self.getRateList(port, mode)
349 print "set Videomode", port, mode, rate
351 modes = self.rates[mode][rate]
352 mode_50 = modes.get(50)
353 mode_60 = modes.get(60)
359 if (mode_50 != mode_60):
361 open("/proc/stb/video/videomode_50hz", "w").write(mode_50)
362 open("/proc/stb/video/videomode_60hz", "w").write(mode_60)
364 print "cannot open /proc/stb/vide/videomode_50hz or videomode_60hz"
366 # Too slow moving to Scart/multi in modeSelectionMoved
368 # open("/proc/stb/video/videomode_50hz", "w").write(mode_60)
370 # print "cannot open /proc/stb/vide/videomode_60Hz"
374 open("/proc/stb/video/videomode", "w").write(mode_50)
376 print "cannot open /proc/stb/vide/videomode"
378 self.changedAspect(None)
380 def changedAspect(self, configElement):
385 # 16:9, 16:10 use policy_43
386 # auto always "bestfit"
387 # config.av.policy_169:
388 # letterbox use letterbox
389 # panscan use panscan
391 # config.av.policy_43:
392 # pillarbox use panscan
393 # pansca use letterbox ("panscan" is just a bad term, it is inverse-panscan)
394 # nonlinear use nonlinear
397 port = config.av.videoport.value
398 if port not in config.av.videomode:
399 print "current port not available. couldn't set aspect"
402 mode = config.av.videomode[port].value
403 force_wide = self.isWidescreenMode(mode)
404 valstr = config.av.aspect.value
406 policy2 = "policy" # use main policy
408 if force_wide or valstr == "16_9" or valstr == "16_10":
409 if force_wide or valstr == "16_9":
411 elif valstr == "16_10":
414 policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value]
415 policy2 = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
416 elif valstr == "auto":
421 policy = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
423 if not config.av.wss.value:
424 wss = "auto(4:3_off)"
428 self.setAspect(aspect, policy, policy2, wss)
430 def setAspect(self, aspect, policy, policy2, wss):
431 print "set aspect, policy, policy2, wss", aspect, policy, policy2, wss
433 open("/proc/stb/video/aspect", "w").write(aspect)
434 open("/proc/stb/video/policy", "w").write(policy)
435 open("/proc/stb/denc/0/wss", "w").write(wss)
437 open("/proc/stb/video/policy2", "w").write(policy2)
441 def isPortUsed(self, port):
443 self.readPreferredModes()
444 return len(self.modes_preferred) != 0
448 def saveVideomode(self, port, mode, rate):
449 print "save Videomode", port, mode, rate
450 config.av.videoport.value = port
451 config.av.videoport.save()
452 if port in config.av.videomode:
453 config.av.videomode[port].value = mode
454 config.av.videomode[port].save()
455 if mode in config.av.videorate:
456 config.av.videorate[mode].value = rate
457 config.av.videorate[mode].save()
460 def setMode(self, port, mode, rate):
461 self.setVideomode(port, mode, rate)
463 def saveMode(self, port, mode, rate):
464 self.saveVideomode(port, mode, rate)
466 def updateAspect(self, configElement):
467 self.changedAspect(configElement)
469 video_hw = VideoHardware()
470 video_hw.setConfiguredMode()