5e61d67d9a1b424d36fd2cbf79aa24cf18b211d8
[enigma2.git] / lib / python / Plugins / SystemPlugins / Videomode / plugin.py
1 from Screens.Screen import Screen
2 from Plugins.Plugin import PluginDescriptor
3
4 from enigma import eTimer
5
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, ConfigNothing, ConfigSelection, ConfigSubDict
13
14 from Tools.CList import CList
15
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.
20 class VideoHardware:
21         rates = { } # high-level, use selectable modes.
22
23         modes = { }  # a list of (high-level) modes for a certain port.
24
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"} }
36         rates["PC"] = { 
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                 "640x480" : { 60: "640x480"} 
47         }
48
49         modes["Scart"] = ["PAL", "NTSC", "Multi"]
50         modes["YPrPb"] = ["720p", "1080i"]
51         modes["DVI"] = ["720p", "1080i", "PC"]
52
53         def __init__(self):
54                 self.last_modes_preferred =  [ ]
55                 self.on_hotplug = CList()
56
57                 self.on_hotplug.append(self.createConfig)
58                 self.ignore_preferred = False   # "edid override"
59
60                 self.readAvailableModes()
61                 self.readPreferredModes()
62
63                 # until we have the hotplug poll socket
64                 self.timer = eTimer()
65                 self.timer.timeout.get().append(self.readAvailableModes)
66                 self.timer.start(1000)
67
68         def readAvailableModes(self):
69                 try:
70                         modes = open("/proc/stb/video/videomode_choices").read()[:-1]
71                 except IOError:
72                         print "couldn't read available videomodes."
73                         self.modes_available = [ ]
74                         return
75                 self.modes_available = modes.split(' ')
76
77         def readPreferredModes(self):
78                 try:
79                         modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
80                         self.modes_preferred = modes.split(' ')
81                 except IOError:
82                         print "reading preferred modes failed, using all modes"
83                         self.modes_preferred = self.modes_available
84
85                 if self.modes_preferred != self.last_modes_preferred:
86                         self.last_modes_preferred = self.modes_preferred
87                         self.on_hotplug("DVI") # must be DVI
88
89         # check if a high-level mode with a given rate is available.
90         def isModeAvailable(self, port, mode, rate):
91                 rate = self.rates[mode][rate]
92                 for mode in rate.values():
93                         # DVI modes must be in "modes_preferred"
94                         if port == "DVI":
95                                 if mode not in self.modes_preferred and not self.ignore_preferred:
96                                         return False
97                         if mode not in self.modes_available:
98                                 return False
99                 return True
100
101         def setMode(self, port, mode, rate):
102                 # we can ignore "port"
103                 self.current_mode = mode
104                 modes = self.rates[mode][rate]
105
106                 mode_50 = modes.get(50)
107                 mode_60 = modes.get(60)
108                 if mode_50 is None:
109                         mode_50 = mode_60
110                 if mode_60 is None:
111                         mode_60 = mode_50
112
113                 try:
114                         open("/proc/stb/video/videomode_60hz", "w").write(mode_50)
115                         open("/proc/stb/video/videomode_50hz", "w").write(mode_60)
116                 except IOError:
117                         try:
118                                 # fallback if no possibility to setup 50/60 hz mode
119                                 open("/proc/stb/video/videomode", "w").write(mode_50)
120                         except IOError:
121                                 print "setting videomode failed."
122
123         def isPortAvailable(self, port):
124                 # fixme
125                 return True
126
127         def getPortList(self):
128                 return [port for port in self.modes if self.isPortAvailable(port)]
129
130         # get a list with all modes, with all rates, for a given port.
131         def getModeList(self, port):
132                 res = [ ]
133                 for mode in self.modes[port]:
134                         # list all rates which are completely valid
135                         rates = [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
136
137                         # if at least one rate is ok, add this mode
138                         if len(rates):
139                                 res.append( (mode, rates) )
140                 return res
141
142         def createConfig(self, *args):
143                 # create list of output ports
144                 portlist = self.getPortList()
145
146                 # create list of available modes
147                 config.av.videoport = ConfigSelection(choices = [(port, _(port)) for port in portlist])
148                 config.av.videomode = ConfigSubDict()
149                 config.av.videorate = ConfigSubDict()
150
151                 for port in portlist:
152                         modes = self.getModeList(port)
153                         if len(modes):
154                                 config.av.videomode[port] = ConfigSelection(choices = [mode for (mode, rates) in modes])
155                         for (mode, rates) in modes:
156                                 config.av.videorate[mode] = ConfigSelection(choices = rates)
157
158 video_hw = VideoHardware()
159
160 class VideoSetup(Screen, ConfigListScreen):
161         def __init__(self, session, hw):
162                 Screen.__init__(self, session)
163                 self.skinName = "Setup"
164                 self.setup_title = "Videomode Setup"
165                 self.hw = hw
166                 self.onChangedEntry = [ ]
167
168                 # handle hotplug by re-creating setup
169                 self.onShow.append(self.startHotplug)
170                 self.onHide.append(self.stopHotplug)
171
172                 self.list = [ ]
173                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changedEntry)
174
175                 self["actions"] = ActionMap(["SetupActions"], 
176                         {
177                                 "cancel": self.keyCancel,
178                                 "save": self.apply,
179                         }, -2)
180
181                 self["title"] = Label(_("Video-Setup"))
182
183                 self["oktext"] = Label(_("OK"))
184                 self["canceltext"] = Label(_("Cancel"))
185                 self["ok"] = Pixmap()
186                 self["cancel"] = Pixmap()
187
188                 self.createSetup()
189                 self.grabLastGoodMode()
190
191         def startHotplug(self):
192                 self.hw.on_hotplug.append(self.createSetup)
193
194         def stopHotplug(self):
195                 self.hw.on_hotplug.remove(self.createSetup)
196
197         def createSetup(self):
198                 self.list = [ ]
199                 self.list.append(getConfigListEntry(_("Output Type"), config.av.videoport))
200
201                 # if we have modes for this port:
202                 if config.av.videoport.value in config.av.videomode:
203                         # add mode- and rate-selection:
204                         self.list.append(getConfigListEntry(_("Mode"), config.av.videomode[config.av.videoport.value]))
205                         self.list.append(getConfigListEntry(_("Rate"), config.av.videorate[config.av.videomode[config.av.videoport.value].value]))
206
207                 self["config"].list = self.list
208                 self["config"].l.setList(self.list)
209
210         def keyLeft(self):
211                 ConfigListScreen.keyLeft(self)
212                 self.createSetup()
213
214         def keyRight(self):
215                 ConfigListScreen.keyRight(self)
216                 self.createSetup()
217
218         def confirm(self, confirmed):
219                 if not confirmed:
220                         self.hw.setMode(*self.last_good)
221                 else:
222                         self.keySave()
223
224         def grabLastGoodMode(self):
225                 port = config.av.videoport.value
226                 mode = config.av.videomode[port].value
227                 rate = config.av.videorate[mode].value
228                 self.last_good = (port, mode, rate)
229
230         def apply(self):
231                 port = config.av.videoport.value
232                 mode = config.av.videomode[port].value
233                 rate = config.av.videorate[mode].value
234                 if (port, mode, rate) != self.last_good or True:
235                         self.hw.setMode(port, mode, rate)
236                         self.session.openWithCallback(self.confirm, MessageBox, "Is this videomode ok?", MessageBox.TYPE_YESNO, timeout = 5, default = False)
237                 else:
238                         self.keySave()
239
240         # for summary:
241         def changedEntry(self):
242                 for x in self.onChangedEntry:
243                         x()
244
245         def getCurrentEntry(self):
246                 return self["config"].getCurrent()[0]
247
248         def getCurrentValue(self):
249                 return str(self["config"].getCurrent()[1].getText())
250
251         def createSummary(self):
252                 return SetupSummary
253
254 #class VideomodeHotplug:
255 #       def __init__(self, hw):
256 #               self.hw = hw
257 #               self.hw.on_hotplug.append(self.hotplug)
258 #
259 #       def hotplug(self, what):
260 #               print "hotplug detected on port '%s'" % (what)
261 # ...
262 #
263 #hotplug = None
264 #
265 #def startHotplug(self):
266 #       global hotplug
267 #       hotplug = VideomodeHotplug()
268 #       hotplug.start()
269 #
270 #def stopHotplug(self):
271 #       global hotplug
272 #       hotplug.stop()
273 #
274 #
275 #def autostart(reason, session = None, **kwargs):
276 #       if session is not None:
277 #               global my_global_session
278 #               my_global_session = session
279 #               return
280 #
281 #       if reason == 0:
282 #               startHotplug()
283 #       elif reason == 1:
284 #               stopHotplug()
285
286 def videoSetupMain(session, **kwargs):
287         session.open(VideoSetup, video_hw)
288
289 def startSetup(menuid):
290         if menuid != "system": 
291                 return [ ]
292
293         return [(_("Video Setup"), videoSetupMain, "video_setup", None)]
294
295 def Plugins(**kwargs):
296         return [ 
297 #               PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
298                 PluginDescriptor(name=_("Video Setup"), description=_("Advanced Video Setup"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup) 
299         ]