[videomode] fix model name duo->bm750
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / Videomode / VideoHardware.py
1 from Components.config import config, ConfigSubDict, ConfigSelection
2 from Tools.CList import CList
3 from Tools.HardwareInfo import HardwareInfo
4
5 # VideoHardware is the interface to /proc/stb/video.
6 class VideoHardware:
7         is_init = True
8
9         modes = { # a list of modes for available port
10                 "Scart" : ["PAL", "NTSC", "Multi"],
11                 "YPbPr" : ["720p", "1080i", "576p", "480p", "576i", "480i"],
12                 "DVI"   : ["720p", "1080i", "576p", "480p", "576i", "480i"],
13                 "DVI-PC": ["PC"]
14         }
15         rates = { # list of rates for available mode
16                 "PAL":   { "50Hz" : {50: "pal"},
17                                    "60Hz" : {60: "pal60"},
18                                    "multi": {50: "pal", 60: "pal60"}
19                 },
20                 "NTSC":  { "60Hz" : {60: "ntsc"} },
21                 "Multi": { "multi": {50: "pal", 60: "ntsc"} },
22                 "480i":  { "60Hz" : {60: "480i"} },
23                 "576i":  { "50Hz" : {50: "576i"} },
24                 "480p":  { "60Hz" : {60: "480p"} },
25                 "576p":  { "50Hz" : {50: "576p"} },
26                 "720p":  {
27                         "50Hz" : {50: "720p50"},
28                         "60Hz" : {60: "720p"},
29                         "multi": {50: "720p50", 60: "720p"}
30                 },
31                 "1080i": {
32                         "50Hz" : {50: "1080i50"},
33                         "60Hz" : {60: "1080i"},
34                         "multi": {50: "1080i50", 60: "1080i"}
35                 },
36                 "1080p": {
37                         "50Hz" : {50: "1080p50"},
38                         "60Hz" : {60: "1080p"},
39                         "multi": {50: "1080p50", 60: "1080p"}
40                 },
41                 "PC": {
42                         "1024x768": {60: "1024x768"},
43                         "800x600" : {60: "800x600"},
44                         "720x480" : {60: "720x480"},
45                         "720x576" : {60: "720x576"},
46                         "1280x720": {60: "1280x720"},
47                         "1280x720 multi": {50: "1280x720_50", 60: "1280x720"},
48                         "1920x1080": {60: "1920x1080"},
49                         "1920x1080 multi": {50: "1920x1080", 60: "1920x1080_50"},
50                         "1280x1024": {60: "1280x1024"},
51                         "1366x768": {60: "1366x768"},
52                         "1366x768 multi": {50: "1366x768", 60: "1366x768_50"},
53                         "1280x768": {60: "1280x768"},
54                         "640x480" : {60: "640x480"}
55                 }
56         }
57
58         widescreen_modes = set(["720p", "1080i", "1080p"])
59         hdmi_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2"])
60         hdmi_pc_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2"])
61
62         def getDeviceName(self):
63                 device_name = "unknown"
64                 try:
65                         file = open("/proc/stb/info/vumodel", "r")
66                         device_name = file.readline().strip()
67                         file.close()
68                 except IOError:
69                         from Tools.HardwareInfo import HardwareInfo
70                         device_name = HardwareInfo.get_device_name()
71
72                 return device_name
73
74         def isVumodel(self, hw_type):
75                 return hw_type in set(["bm750", "solo", "uno", "ultimo", "solo2", "duo2"])
76
77         # re-define AVSwitch.getOutputAspect
78         def getOutputAspect(self):
79                 ret = (16,9)
80                 port = config.av.videoport.value
81                 if port not in config.av.videomode:
82                         print "current port is not available. force 16:9"
83                 else:
84                         mode = config.av.videomode[port].value
85                         force_wide = self.isWidescreenMode(mode)
86                         valstr = config.av.aspect.value
87
88                         if force_wide:
89                                 pass
90                         elif valstr == "16_10":
91                                 ret = (16,10)
92                         elif valstr == "auto":
93                                 try:
94                                         aspect_str = open("/proc/stb/vmpeg/0/aspect", "r").read()
95                                         if aspect_str == "1": # 4:3
96                                                 ret = (4,3)
97                                 except IOError:
98                                         pass
99                         elif valstr == "4_3":
100                                 ret = (4,3)
101                 return ret
102
103         def __init__(self):
104                 self.last_modes_preferred = [ ]
105                 self.on_hotplug = CList()
106
107                 self.readAvailableModes()
108
109                 if self.modes.has_key("DVI-PC") and not self.getModeList("DVI-PC"):
110                         print "remove DVI-PC because it does not exist."
111                         del self.modes["DVI-PC"]
112
113                 self.createConfig()
114
115                 self.readPreferredModes()
116
117                 # re-define AVSwitch components
118                 from Components.AVSwitch import AVSwitch
119                 config.av.aspectratio.notifiers = [ ]
120                 config.av.tvsystem.notifiers = [ ]
121                 config.av.wss.notifiers = [ ]
122                 AVSwitch.getOutputAspect = self.getOutputAspect
123
124                 config.av.aspect.addNotifier(self.changedAspect)
125                 config.av.wss.addNotifier(self.changedAspect)
126                 config.av.policy_169.addNotifier(self.changedAspect)
127                 config.av.policy_43.addNotifier(self.changedAspect)
128
129                 # addNotifiers for port, mode, rate
130                 config.av.videoport.addNotifier(self.changedVideomode)
131                 for port in self.getPortList():
132                         config.av.videomode[port].addNotifier(self.changedVideomode)
133                         for mode in self.getModeList(port):
134                                 config.av.videorate[mode[0]].addNotifier(self.changedVideomode)
135
136                 self.is_init = False
137
138         def readAvailableModes(self):
139                 try:
140                         modes = open("/proc/stb/video/videomode_choices").read()[:-1]
141                         self.modes_available = modes.split(' ')
142                 except IOError:
143                         print "failed to read video_choices."
144                         self.modes_available = [ ]
145
146         def readPreferredModes(self):
147                 try:
148                         modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
149                         self.modes_preferred = modes.split(' ')
150                 except IOError:
151                         print "failed to read video_preferred."
152                         self.modes_preferred = self.modes_available
153
154                 if self.modes_preferred != self.last_modes_preferred:
155                         self.last_modes_preferred = self.modes_preferred
156                         print "hotplug on DVI"
157                         self.on_hotplug("DVI") # must be DVI
158
159         # check if HDMI is available
160         def isHDMIAvailable(self, hw_type):
161                 return hw_type in self.hdmi_hw_types
162
163         # check if HDMI-PC is available
164         def isHDMI_PCAvailable(self, hw_type):
165                 return hw_type in self.hdmi_pc_hw_types
166
167         # check if mode is always widescreen
168         def isWidescreenMode(self, mode):
169                 return mode in self.widescreen_modes
170
171         # check if rate is available for mode
172         def isModeAvailable(self, port, mode, rate):
173                 rate = self.rates[mode][rate]
174                 for mode in rate.values():
175                         if mode not in self.modes_available:
176                                 return False
177
178                 return True
179
180         # check isModeAvailable in this port
181         def isPortAvailable(self, port):
182                 for mode in self.getModeList(port):
183                         if len(self.getRateList(port, mode[0])):
184                                 return True
185
186                 return False
187
188         # get a list of all available port
189         def getPortList(self):
190                 return [port for port in self.modes if self.isPortAvailable(port)]
191
192         # get a list of all available mode for a given port
193         def getModeList(self, port):
194                 modelist = [ ]
195                 for mode in self.modes[port]:
196                         rates = self.getRateList(port, mode)
197
198                         if len(rates):
199                                 modelist.append( (mode, rates))
200
201                 return modelist
202
203         # get a list of all available rate for a given port, mode
204         def getRateList(self, port, mode):
205                 return [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
206
207         def createConfig(self):
208                 config.av.videomode = ConfigSubDict()
209                 config.av.videorate = ConfigSubDict()
210
211                 hw_type = self.getDeviceName()
212                 # vu+ support 1080p
213                 if self.isVumodel(hw_type):
214                         self.modes["DVI"].insert(self.modes["DVI"].index("1080i")+1, "1080p")
215
216                 portlist = [ ]
217                 port_choices = self.getPortList()
218
219                 for port in port_choices:
220                         desc = port
221                         if desc == 'DVI' and self.isHDMIAvailable(hw_type):
222                                 desc = 'HDMI'
223                         if desc == 'DVI-PC' and self.isHDMI_PCAvailable(hw_type):
224                                 desc = 'HDMI-PC'
225                         portlist.append( (port, desc))
226
227                         # create list of available modes
228                         modelist = [ ]
229                         mode_choices = self.getModeList(port)
230
231                         for mode in mode_choices:
232                                 modelist.append( (mode[0], mode[0]))
233
234                                 # create list of available rates
235                                 ratelist = [ ]
236                                 rate_choices = self.getRateList(port, mode[0])
237
238                                 for rate in rate_choices:
239                                         ratelist.append( (rate, rate))
240
241                                 config.av.videorate[mode[0]] = ConfigSelection(choices = ratelist)
242                         config.av.videomode[port] = ConfigSelection(choices = modelist)
243                 config.av.videoport = ConfigSelection(choices = portlist)
244
245         def changedVideomode(self, configElement):
246                 if self.is_init:
247                         return
248
249                 self.setConfiguredMode()
250
251         def setConfiguredMode(self):
252                 port = config.av.videoport.value
253                 mode = config.av.videomode[port].value
254                 rate = config.av.videorate[mode].value
255
256                 self.setVideomode(port, mode, rate)
257
258         def setVideomode(self, port, mode, rate):
259                 if port is None or port not in config.av.videomode:
260                         print "current port not available. couldn't set videomode"
261                         return
262
263                 if mode not in config.av.videorate:
264                         print "current mode not available. couldn't set videomode"
265                         return
266
267                 if mode is None:
268                         modelist = self.getModeList(port)
269                         mode = modelist[0][0]
270
271                         ratelist = self.getRateList(port, mode)
272                         rate = ratelist[0]
273
274                 if rate is None:
275                         ratelist = self.getRateList(port, mode)
276                         rate = ratelist[0]
277
278                 print "set Videomode", port, mode, rate
279
280                 modes = self.rates[mode][rate]
281                 mode_50 = modes.get(50)
282                 mode_60 = modes.get(60)
283                 if mode_50 is None:
284                         mode_50 = mode_60
285                 if mode_60 is None:
286                         mode_60 = mode_50
287
288                 if (mode_50 != mode_60):
289                         try:
290                                 open("/proc/stb/video/videomode_50hz", "w").write(mode_50)
291                                 open("/proc/stb/video/videomode_60hz", "w").write(mode_60)
292                         except IOError:
293                                 print "cannot open /proc/stb/vide/videomode_50hz or videomode_60hz"
294
295                         # Too slow moving to Scart/multi in modeSelectionMoved
296                         #try:
297                         #       open("/proc/stb/video/videomode_50hz", "w").write(mode_60)
298                         #except IOError:
299                         #       print "cannot open /proc/stb/vide/videomode_60Hz"
300
301                 else:
302                         try:
303                                 open("/proc/stb/video/videomode", "w").write(mode_50)
304                         except IOError:
305                                 print "cannot open /proc/stb/vide/videomode"
306
307                 self.changedAspect(None)
308
309         def changedAspect(self, configElement):
310                 if self.is_init:
311                         return
312                 # config.av.aspect:
313                 #       4:3                     use policy_169
314                 #       16:9, 16:10     use policy_43
315                 #       auto            always "bestfit"
316                 # config.av.policy_169:
317                 #       letterbox       use letterbox
318                 #       panscan         use panscan
319                 #       scale           use bestfit
320                 # config.av.policy_43:
321                 #       pillarbox       use panscan
322                 #       pansca          use letterbox ("panscan" is just a bad term, it is inverse-panscan)
323                 #       nonlinear       use nonlinear
324                 #       scale           use bestfit
325
326                 port = config.av.videoport.value
327                 if port not in config.av.videomode:
328                         print "current port not available. couldn't set aspect"
329                         return
330
331                 mode = config.av.videomode[port].value
332                 force_wide = self.isWidescreenMode(mode)
333                 valstr = config.av.aspect.value
334
335                 policy2 = "policy" # use main policy
336
337                 if force_wide or valstr == "16_9" or valstr == "16_10":
338                         if force_wide or valstr == "16_9":
339                                 aspect = "16:9"
340                         elif valstr == "16_10":
341                                 aspect = "16:10"
342
343                         policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value]
344                         policy2 = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
345                 elif valstr == "auto":
346                         aspect = "any"
347                         policy = "bestfit"
348                 else:
349                         aspect = "4:3"
350                         policy = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value]
351
352                 if not config.av.wss.value:
353                         wss = "auto(4:3_off)"
354                 else:
355                         wss = "auto"
356
357                 self.setAspect(aspect, policy, policy2, wss)
358
359         def setAspect(self, aspect, policy, policy2, wss):
360                 print "set aspect, policy, policy2, wss", aspect, policy, policy2, wss
361
362                 open("/proc/stb/video/aspect", "w").write(aspect)
363                 open("/proc/stb/video/policy", "w").write(policy)
364                 open("/proc/stb/denc/0/wss", "w").write(wss)
365                 try:
366                         open("/proc/stb/video/policy2", "w").write(policy2)
367                 except IOError:
368                         pass
369
370         def isPortUsed(self, port):
371                 if port == "DVI":
372                         self.readPreferredModes()
373                         return len(self.modes_preferred) != 0
374                 else:
375                         return True
376
377         def saveVideomode(self, port, mode, rate):
378                 print "save Videomode", port, mode, rate
379                 config.av.videoport.value = port
380                 config.av.videoport.save()
381                 if port in config.av.videomode:
382                         config.av.videomode[port].value = mode
383                         config.av.videomode[port].save()
384                 if mode in config.av.videorate:
385                         config.av.videorate[mode].value = rate
386                         config.av.videorate[mode].save()
387
388         # for dependency
389         def setMode(self, port, mode, rate):
390                 self.setVideomode(port, mode, rate)
391
392         def saveMode(self, port, mode, rate):
393                 self.saveVideomode(port, mode, rate)
394
395         def updateAspect(self, configElement):
396                 self.changedAspect(configElement)
397
398 video_hw = VideoHardware()
399 video_hw.setConfiguredMode()
400