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