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" },
26 "60Hz": { 60: "pal60" },
27 "multi": { 50: "pal", 60: "pal60" } }
29 rates["NTSC"] = { "60Hz": { 60: "ntsc" } }
31 rates["Multi"] = { "multi": { 50: "pal", 60: "ntsc" } }
33 rates["480p"] = { "60Hz": { 60: "480p" } }
35 rates["576p"] = { "50Hz": { 50: "576p" } }
37 rates["720p"] = { "50Hz": { 50: "720p50", 60: "720p50" },
38 "60Hz": { 60: "720p" },
39 "multi": { 50: "720p50" } }
41 rates["1080i"] = { "50Hz": { 50: "1080i50" },
42 "60Hz": { 60: "1080i" },
43 "multi": { 50: "1080i50", 60: "1080i" } }
46 "1024x768": { 60: "1024x768"}, # not possible on DM7025
47 "800x600" : { 60: "800x600"}, # also not possible
48 "720x480" : { 60: "720x480"},
49 "720x576" : { 60: "720x576"},
50 "1280x720": { 60: "1280x720"},
51 "1280x720 multi": { 50: "1280x720_50", 60: "1280x720"},
52 "1920x1080": { 60: "1920x1080"},
53 "1920x1080 multi": { 50: "1920x1080", 60: "1920x1080_50"},
54 "1280x1024" : { 60: "1280x1024"},
55 "1366x768" : { 60: "1366x768"},
56 "1366x768 multi" : { 50: "1366x768", 60: "1366x768_50"},
57 "1280x768": { 60: "1280x768"},
58 "640x480" : { 60: "640x480"}
61 modes["Scart"] = ["PAL", "NTSC", "Multi"]
62 modes["YPbPr"] = ["720p", "1080i", "576p", "480p"]
63 modes["DVI"] = ["720p", "1080i", "576p", "480p"]
64 modes["DVI-PC"] = ["PC"]
66 widescreen_modes = set(["720p", "1080i"])
69 self.last_modes_preferred = [ ]
70 self.on_hotplug = CList()
72 self.current_mode = None
73 self.current_port = None
75 self.readAvailableModes()
78 # self.on_hotplug.append(self.createConfig)
80 self.readPreferredModes()
82 # take over old AVSwitch component :)
83 from Components.AVSwitch import AVSwitch
84 # config.av.colorformat.notifiers = [ ]
85 config.av.aspectratio.notifiers = [ ]
86 config.av.tvsystem.notifiers = [ ]
87 config.av.wss.notifiers = [ ]
88 AVSwitch.setInput = self.AVSwitchSetInput
90 config.av.aspect.addNotifier(self.updateAspect)
91 config.av.wss.addNotifier(self.updateAspect)
92 config.av.policy_169.addNotifier(self.updateAspect)
93 config.av.policy_43.addNotifier(self.updateAspect)
95 # until we have the hotplug poll socket
96 # self.timer = eTimer()
97 # self.timer.callback.append(self.readPreferredModes)
98 # self.timer.start(1000)
100 config.av.colorformat.addNotifier(self.updateFastblank)
102 def AVSwitchSetInput(self, mode):
103 self.standby = mode == "SCART"
106 def readAvailableModes(self):
108 modes = open("/proc/stb/video/videomode_choices").read()[:-1]
110 print "couldn't read available videomodes."
111 self.modes_available = [ ]
113 self.modes_available = modes.split(' ')
115 def readPreferredModes(self):
117 modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
118 self.modes_preferred = modes.split(' ')
120 print "reading preferred modes failed, using all modes"
121 self.modes_preferred = self.modes_available
123 if self.modes_preferred != self.last_modes_preferred:
124 self.last_modes_preferred = self.modes_preferred
125 print "hotplug on dvi"
126 self.on_hotplug("DVI") # must be DVI
128 # check if a high-level mode with a given rate is available.
129 def isModeAvailable(self, port, mode, rate):
130 rate = self.rates[mode][rate]
131 for mode in rate.values():
132 # DVI modes must be in "modes_preferred"
134 # if mode not in self.modes_preferred and not config.av.edid_override.value:
135 # print "no, not preferred"
137 if mode not in self.modes_available:
141 def isWidescreenMode(self, port, mode):
142 return mode in self.widescreen_modes
144 def setMode(self, port, mode, rate, force = None):
145 print "setMode - port:", port, "mode:", mode, "rate:", rate
146 # we can ignore "port"
147 self.current_mode = mode
148 self.current_port = port
149 modes = self.rates[mode][rate]
151 mode_50 = modes.get(50)
152 mode_60 = modes.get(60)
153 if mode_50 is None or force == 60:
155 if mode_60 is None or force == 50:
159 open("/proc/stb/video/videomode_50hz", "w").write(mode_50)
160 open("/proc/stb/video/videomode_60hz", "w").write(mode_60)
163 # fallback if no possibility to setup 50/60 hz mode
164 open("/proc/stb/video/videomode", "w").write(mode_50)
166 print "setting videomode failed."
169 open("/etc/videomode", "w").write(mode_50) # use 50Hz mode (if available) for booting
171 print "writing initial videomode to /etc/videomode failed."
173 self.updateAspect(None)
175 def saveMode(self, port, mode, rate):
176 config.av.videoport.value = port
177 config.av.videoport.save()
178 config.av.videomode[port].value = mode
179 config.av.videomode[port].save()
180 config.av.videorate[mode].value = rate
181 config.av.videorate[mode].save()
183 def isPortAvailable(self, port):
187 def isPortUsed(self, port):
189 self.readPreferredModes()
190 return len(self.modes_preferred) != 0
194 def getPortList(self):
195 return [port for port in self.modes if self.isPortAvailable(port)]
197 # get a list with all modes, with all rates, for a given port.
198 def getModeList(self, port):
199 print "getModeList for port", port
201 for mode in self.modes[port]:
202 # list all rates which are completely valid
203 rates = [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
205 # if at least one rate is ok, add this mode
207 res.append( (mode, rates) )
210 def createConfig(self, *args):
211 # create list of output ports
212 portlist = self.getPortList()
214 # create list of available modes
215 config.av.videoport = ConfigSelection(choices = [(port, _(port)) for port in portlist])
216 config.av.videomode = ConfigSubDict()
217 config.av.videorate = ConfigSubDict()
219 for port in portlist:
220 modes = self.getModeList(port)
222 config.av.videomode[port] = ConfigSelection(choices = [mode for (mode, rates) in modes])
223 for (mode, rates) in modes:
224 config.av.videorate[mode] = ConfigSelection(choices = rates)
226 def setConfiguredMode(self):
227 port = config.av.videoport.value
228 if port not in config.av.videomode:
229 print "current port not available, not setting videomode"
232 mode = config.av.videomode[port].value
234 if mode not in config.av.videorate:
235 print "current mode not available, not setting videomode"
238 rate = config.av.videorate[mode].value
239 self.setMode(port, mode, rate)
241 def updateAspect(self, cfgelement):
242 # determine aspect = {any,4:3,16:9,16:10}
243 # determine policy = {bestfit,letterbox,panscan,nonlinear}
246 # config.av.videoport.value: current video output device
249 # 4_3: use policy_169
250 # 16_9,16_10: use policy_43
251 # auto always "bestfit"
252 # config.av.policy_169
253 # letterbox use letterbox
254 # panscan use panscan
256 # config.av.policy_43
257 # pillarbox use panscan
258 # panscan use letterbox ("panscan" is just a bad term, it's inverse-panscan)
259 # nonlinear use nonlinear
262 port = config.av.videoport.value
263 if port not in config.av.videomode:
264 print "current port not available, not setting videomode"
266 mode = config.av.videomode[port].value
268 force_widescreen = self.isWidescreenMode(port, mode)
270 is_widescreen = force_widescreen or config.av.aspect.value in ["16_9", "16_10"]
271 is_auto = config.av.aspect.value == "auto"
277 aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value]
278 policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value]
284 policy = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
286 if not config.av.wss.value:
287 wss = "auto(4:3_off)"
291 print "-> setting aspect, policy, wss", aspect, policy, wss
292 open("/proc/stb/video/aspect", "w").write(aspect)
293 open("/proc/stb/video/policy", "w").write(policy)
294 open("/proc/stb/denc/0/wss", "w").write(wss)
295 self.updateSlowblank()
296 self.updateFastblank()
298 def updateSlowblank(self):
300 from Components.SystemInfo import SystemInfo
301 if SystemInfo["ScartSwitch"]:
311 open("/proc/stb/avs/0/sb", "w").write(sb)
312 open("/proc/stb/avs/0/input", "w").write(input)
314 def updateStandby(self):
315 self.updateSlowblank()
316 self.updateFastblank()
318 def updateFastblank(self, *args):
320 from Components.SystemInfo import SystemInfo
321 if SystemInfo["ScartSwitch"]:
326 if self.current_port == "Scart" and config.av.colorformat.value == "rgb":
330 open("/proc/stb/avs/0/fb", "w").write(fb)
332 config.av.edid_override = ConfigYesNo(default = False)
333 video_hw = VideoHardware()
334 video_hw.setConfiguredMode()