1 from Screens.Screen import Screen
2 from Plugins.Plugin import PluginDescriptor
4 from enigma import eTimer
6 from Components.ActionMap import ActionMap
7 from Components.Label import Label
8 from Components.Pixmap import Pixmap
9 from Screens.MessageBox import MessageBox
10 from Screens.Setup import SetupSummary
11 from Components.ConfigList import ConfigListScreen
12 from Components.config import getConfigListEntry, config, ConfigSelection, ConfigSubDict, ConfigYesNo
14 from Tools.CList import CList
16 # The "VideoHardware" is the interface to /proc/stb/video.
17 # It generates hotplug events, and gives you the list of
18 # available and preferred modes, as well as handling the currently
19 # selected mode. No other strict checking is done.
21 rates = { } # high-level, use selectable modes.
23 modes = { } # a list of (high-level) modes for a certain port.
25 rates["PAL"] = { "50Hz": { 50: "pal", 60: "pal"},
26 "60Hz": { 50: "pal60", 60: "pal60"},
27 "multi": { 50: "pal", 60: "pal60"} }
28 rates["NTSC"] = { "60Hz": { 50: "ntsc", 60: "ntsc"} }
29 rates["Multi"] = { "multi": { 50: "pal", 60: "ntsc"} }
30 rates["720p"] = { "50Hz": { 50: "720p50", 60: "720p50"},
31 "60Hz": { 50: "720p", 60: "720p"},
32 "multi": { 50: "720p50", 60: "720p"} }
33 rates["1080i"] = { "50Hz": { 50: "1080i50", 60: "1080i50"},
34 "60Hz": { 50: "1080i", 60: "1080i"},
35 "multi": { 50: "1080i50", 60: "1080i"} }
37 "1024x768": { 60: "1024x768"}, # not possible on DM7025
38 "800x600" : { 60: "800x600"}, # also not possible
39 "720x480" : { 60: "720x480"},
40 "720x576" : { 60: "720x576"},
41 "1280x720": { 60: "1280x720"},
42 "1280x720 multi": { 50: "1280x720_50", 60: "1280x720"},
43 "1920x1080": { 60: "1920x1080"},
44 "1920x1080 multi": { 50: "1920x1080", 60: "1920x1080_50"},
45 "1280x1024" : { 60: "1280x1024"},
46 "1366x768" : { 60: "1366x768"},
47 "1366x768 multi" : { 50: "1366x768", 60: "1366x768_50"},
48 "1280x768": { 60: "1280x768"},
49 "640x480" : { 60: "640x480"}
52 modes["Scart"] = ["PAL", "NTSC", "Multi"]
53 modes["YPbPr"] = ["720p", "1080i"]
54 modes["DVI"] = ["720p", "1080i", "PC"]
55 modes["DVI-PC"] = ["PC"]
57 widescreen_modes = set(["720p", "1080i"])
60 self.last_modes_preferred = [ ]
61 self.on_hotplug = CList()
63 self.current_mode = None
64 self.current_port = None
66 self.readAvailableModes()
69 # self.on_hotplug.append(self.createConfig)
71 self.readPreferredModes()
73 # take over old AVSwitch component :)
74 from Components.AVSwitch import AVSwitch
75 # config.av.colorformat.notifiers = [ ]
76 config.av.aspectratio.notifiers = [ ]
77 config.av.tvsystem.notifiers = [ ]
78 config.av.wss.notifiers = [ ]
79 AVSwitch.setInput = self.AVSwitchSetInput
81 config.av.aspect.addNotifier(self.updateAspect)
82 config.av.wss.addNotifier(self.updateAspect)
83 config.av.policy_169.addNotifier(self.updateAspect)
84 config.av.policy_43.addNotifier(self.updateAspect)
86 # until we have the hotplug poll socket
87 # self.timer = eTimer()
88 # self.timer.callback.append(self.readPreferredModes)
89 # self.timer.start(1000)
91 config.av.colorformat.addNotifier(self.updateFastblank)
93 def AVSwitchSetInput(self, mode):
94 self.standby = mode == "SCART"
97 def readAvailableModes(self):
99 modes = open("/proc/stb/video/videomode_choices").read()[:-1]
101 print "couldn't read available videomodes."
102 self.modes_available = [ ]
104 self.modes_available = modes.split(' ')
106 def readPreferredModes(self):
108 modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
109 self.modes_preferred = modes.split(' ')
111 print "reading preferred modes failed, using all modes"
112 self.modes_preferred = self.modes_available
114 if self.modes_preferred != self.last_modes_preferred:
115 self.last_modes_preferred = self.modes_preferred
116 print "hotplug on dvi"
117 self.on_hotplug("DVI") # must be DVI
119 # check if a high-level mode with a given rate is available.
120 def isModeAvailable(self, port, mode, rate):
121 rate = self.rates[mode][rate]
122 for mode in rate.values():
123 # DVI modes must be in "modes_preferred"
125 # if mode not in self.modes_preferred and not config.av.edid_override.value:
126 # print "no, not preferred"
128 if mode not in self.modes_available:
132 def isWidescreenMode(self, port, mode):
133 return mode in self.widescreen_modes
135 def setMode(self, port, mode, rate, force = None):
136 print "setMode - port:", port, "mode:", mode, "rate:", rate
137 # we can ignore "port"
138 self.current_mode = mode
139 self.current_port = port
140 modes = self.rates[mode][rate]
142 mode_50 = modes.get(50)
143 mode_60 = modes.get(60)
144 if mode_50 is None or force == 60:
146 if mode_60 is None or force == 50:
149 dvimode = (mode_50.find('x') != -1 or mode_60.find('x') != -1) and '1' or '0'
151 open("/etc/dvimode", "w").write(dvimode) # use 50Hz mode (if available) for booting
153 print "writing initial dvimode to /etc/dvimode failed."
156 open("/proc/stb/hdmi/enable_hdmi_reset", "w").write(dvimode)
158 print "setting dvimode failed."
161 open("/proc/stb/video/videomode_50hz", "w").write(mode_50)
162 open("/proc/stb/video/videomode_60hz", "w").write(mode_60)
165 # fallback if no possibility to setup 50/60 hz mode
166 open("/proc/stb/video/videomode", "w").write(mode_50)
168 print "setting videomode failed."
171 open("/etc/videomode", "w").write(mode_50) # use 50Hz mode (if available) for booting
173 print "writing initial videomode to /etc/videomode failed."
175 self.updateAspect(None)
177 def saveMode(self, port, mode, rate):
178 config.av.videoport.value = port
179 config.av.videoport.save()
180 config.av.videomode[port].value = mode
181 config.av.videomode[port].save()
182 config.av.videorate[mode].value = rate
183 config.av.videorate[mode].save()
185 def isPortAvailable(self, port):
189 def isPortUsed(self, port):
191 self.readPreferredModes()
192 return len(self.modes_preferred) != 0
196 def getPortList(self):
197 return [port for port in self.modes if self.isPortAvailable(port)]
199 # get a list with all modes, with all rates, for a given port.
200 def getModeList(self, port):
201 print "getModeList for port", port
203 for mode in self.modes[port]:
204 # list all rates which are completely valid
205 rates = [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
207 # if at least one rate is ok, add this mode
209 res.append( (mode, rates) )
212 def createConfig(self, *args):
213 # create list of output ports
214 portlist = self.getPortList()
216 # create list of available modes
217 config.av.videoport = ConfigSelection(choices = [(port, _(port)) for port in portlist])
218 config.av.videomode = ConfigSubDict()
219 config.av.videorate = ConfigSubDict()
221 for port in portlist:
222 modes = self.getModeList(port)
224 config.av.videomode[port] = ConfigSelection(choices = [mode for (mode, rates) in modes])
225 for (mode, rates) in modes:
226 config.av.videorate[mode] = ConfigSelection(choices = rates)
228 def setConfiguredMode(self):
229 port = config.av.videoport.value
230 if port not in config.av.videomode:
231 print "current port not available, not setting videomode"
234 mode = config.av.videomode[port].value
236 if mode not in config.av.videorate:
237 print "current mode not available, not setting videomode"
240 rate = config.av.videorate[mode].value
241 self.setMode(port, mode, rate)
243 def updateAspect(self, cfgelement):
244 # determine aspect = {any,4:3,16:9,16:10}
245 # determine policy = {bestfit,letterbox,panscan,nonlinear}
248 # config.av.videoport.value: current video output device
251 # 4_3: use policy_169
252 # 16_9,16_10: use policy_43
253 # auto always "bestfit"
254 # config.av.policy_169
255 # letterbox use letterbox
256 # panscan use panscan
258 # config.av.policy_43
259 # pillarbox use panscan
260 # panscan use letterbox ("panscan" is just a bad term, it's inverse-panscan)
261 # nonlinear use nonlinear
264 port = config.av.videoport.value
265 if port not in config.av.videomode:
266 print "current port not available, not setting videomode"
268 mode = config.av.videomode[port].value
270 force_widescreen = self.isWidescreenMode(port, mode)
272 is_widescreen = force_widescreen or config.av.aspect.value in ["16_9", "16_10"]
273 is_auto = config.av.aspect.value == "auto"
279 aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value]
280 policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value]
286 policy = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
288 if not config.av.wss.value:
289 wss = "auto(4:3_off)"
293 print "-> setting aspect, policy, wss", aspect, policy, wss
294 open("/proc/stb/video/aspect", "w").write(aspect)
295 open("/proc/stb/video/policy", "w").write(policy)
296 open("/proc/stb/denc/0/wss", "w").write(wss)
297 self.updateSlowblank()
298 self.updateFastblank()
300 def updateSlowblank(self):
302 from Components.SystemInfo import SystemInfo
303 if SystemInfo["ScartSwitch"]:
313 open("/proc/stb/avs/0/sb", "w").write(sb)
314 open("/proc/stb/avs/0/input", "w").write(input)
316 def updateStandby(self):
317 self.updateSlowblank()
318 self.updateFastblank()
320 def updateFastblank(self, *args):
322 from Components.SystemInfo import SystemInfo
323 if SystemInfo["ScartSwitch"]:
328 if self.current_port == "Scart" and config.av.colorformat.value == "rgb":
332 open("/proc/stb/avs/0/fb", "w").write(fb)
334 config.av.edid_override = ConfigYesNo(default = False)
335 video_hw = VideoHardware()
336 video_hw.setConfiguredMode()