e40914b3f42afff786d8492731339688b55cfb8d
[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
12 from Components.config import ConfigSelection
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                 self.ignore_preferred = False   # "edid override"
57
58                 self.readAvailableModes()
59                 self.readPreferredModes()
60
61                 # until we have the hotplug poll socket
62                 self.timer = eTimer()
63                 self.timer.timeout.get().append(self.readAvailableModes)
64                 self.timer.start(1000)
65
66         def readAvailableModes(self):
67                 try:
68                         modes = open("/proc/stb/video/videomode_choices").read()[:-1]
69                 except IOError:
70                         print "couldn't read available videomodes."
71                         self.modes_available = [ ]
72                         return
73                 self.modes_available = modes.split(' ')
74
75         def readPreferredModes(self):
76                 try:
77                         modes = open("/proc/stb/video/videomode_preferred").read()[:-1]
78                         self.modes_preferred = modes.split(' ')
79                 except IOError:
80                         print "reading preferred modes failed, using all modes"
81                         self.modes_preferred = self.modes_available
82
83                 if self.modes_preferred != self.last_modes_preferred:
84                         self.last_modes_preferred = self.modes_preferred
85                         self.on_hotplug("DVI") # must be DVI
86
87         # check if a high-level mode with a given rate is available.
88         def isModeAvailable(self, port, mode, rate):
89                 rate = self.rates[mode][rate]
90                 for mode in rate.values():
91                         # DVI modes must be in "modes_preferred"
92                         if port == "DVI":
93                                 if mode not in self.modes_preferred and not self.ignore_preferred:
94                                         return False
95                         if mode not in self.modes_available:
96                                 return False
97                 return True
98
99         def setMode(self, port, mode, rate):
100                 # we can ignore "port"
101                 self.current_mode = mode
102                 modes = self.rates[mode][rate]
103
104                 mode_50 = modes.get(50)
105                 mode_60 = modes.get(60)
106                 if mode_50 is None:
107                         mode_50 = mode_60
108                 if mode_60 is None:
109                         mode_60 = mode_50
110
111                 try:
112                         open("/proc/stb/video/videomode_60hz", "w").write(mode_50)
113                         open("/proc/stb/video/videomode_50hz", "w").write(mode_60)
114                 except IOError:
115                         try:
116                                 # fallback if no possibility to setup 50/60 hz mode
117                                 open("/proc/stb/video/videomode", "w").write(mode_50)
118                         except IOError:
119                                 print "setting videomode failed."
120
121         def isPortAvailable(self, port):
122                 # fixme
123                 return True
124
125         def getPortList(self):
126                 return [port for port in self.modes if self.isPortAvailable(port)]
127
128         # get a list with all modes, with all rates, for a given port.
129         def getModeList(self, port):
130                 res = [ ]
131                 for mode in self.modes[port]:
132                         # list all rates which are completely valid
133                         rates = [rate for rate in self.rates[mode] if self.isModeAvailable(port, mode, rate)]
134
135                         # if at least one rate is ok, add this mode
136                         if len(rates):
137                                 res.append( (mode, rates) )
138                 return res
139
140 video_hw = VideoHardware()
141
142 class VideoSetup(Screen, ConfigListScreen):
143         def __init__(self, session, hw):
144                 Screen.__init__(self, session)
145                 self.skinName = "Setup"
146                 self.hw = hw
147
148                 self.list = [ ]
149                 ConfigListScreen.__init__(self, self.list)
150
151                 self["actions"] = ActionMap(["OkCancelActions"],
152                         {
153                                 "ok": self.ok,
154                                 "cancel": self.cancel
155                         },-1)
156
157                 self["title"] = Label(_("Video-Setup"))
158
159                 self["oktext"] = Label(_("OK"))
160                 self["canceltext"] = Label(_("Cancel"))
161                 self["ok"] = Pixmap()
162                 self["cancel"] = Pixmap()
163
164                 # the following data is static for user selection, however not static for different attached hardware.
165
166                 # create list of output ports
167                 portlist = self.hw.getPortList()
168
169                 # create list of available modes
170                 self.config_port = ConfigSelection(choices = [(port, _(port)) for port in portlist])
171                 self.config_mode = { }
172                 self.config_rate = { }
173
174                 for port in portlist:
175                         modes = self.hw.getModeList(port)
176                         print "port:", port, "modes:", modes
177                         if len(modes):
178                                 self.config_mode[port] = ConfigSelection(choices = [mode for (mode, rates) in modes])
179                         for (mode, rates) in modes:
180                                 self.config_rate[mode] = ConfigSelection(choices = rates)
181                 self.createSetup()
182
183         def createSetup(self):
184                 self.list = [ ]
185                 self.list.append(getConfigListEntry(_("Output Type"), self.config_port))
186
187                 # if we have modes for this port:
188                 if self.config_port.value in self.config_mode:
189                         # add mode- and rate-selection:
190                         self.list.append(getConfigListEntry(_("Mode"), self.config_mode[self.config_port.value]))
191                         self.list.append(getConfigListEntry(_("Rate"), self.config_rate[self.config_mode[self.config_port.value].value]))
192
193                 self["config"].list = self.list
194                 self["config"].l.setList(self.list)
195
196         def keyLeft(self):
197                 ConfigListScreen.keyLeft(self)
198                 self.createSetup()
199
200         def keyRight(self):
201                 ConfigListScreen.keyRight(self)
202                 self.createSetup()
203
204         def cancel(self):
205                 self.close()
206
207         def confirm(self, do_revert):
208                 if do_revert:
209                         print "cannot revert yet :)"
210                 else:
211                         self.close()
212
213         def ok(self):
214                 port = self.config_port.value
215                 mode = self.config_mode[port].value
216                 rate = self.config_rate[mode].value
217                 self.hw.setMode(port, mode, rate)
218                 self.session.openWithCallback(self.confirm, MessageBox, "Revert to old settings?", MessageBox.TYPE_YESNO, timeout = 5)
219
220 #class VideomodeHotplug:
221 #       def __init__(self, hw):
222 #               self.hw = hw
223 #               self.hw.on_hotplug.append(self.hotplug)
224 #
225 #       def hotplug(self, what):
226 #               print "hotplug detected on port '%s'" % (what)
227 # ...
228 #
229 #hotplug = None
230 #
231 #def startHotplug(self):
232 #       global hotplug
233 #       hotplug = VideomodeHotplug()
234 #       hotplug.start()
235 #
236 #def stopHotplug(self):
237 #       global hotplug
238 #       hotplug.stop()
239 #
240 #
241 #def autostart(reason, session = None, **kwargs):
242 #       if session is not None:
243 #               global my_global_session
244 #               my_global_session = session
245 #               return
246 #
247 #       if reason == 0:
248 #               startHotplug()
249 #       elif reason == 1:
250 #               stopHotplug()
251
252 def videoSetupMain(session, **kwargs):
253         session.open(VideoSetup, video_hw)
254
255 def startSetup(menuid):
256         if menuid != "system": 
257                 return [ ]
258
259         return [(_("Video Setup"), videoSetupMain, "video_setup", None)]
260
261 def Plugins(**kwargs):
262         return [ 
263 #               PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
264                 PluginDescriptor(name=_("Video Setup"), description=_("Advanced Video Setup"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup) 
265         ]